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;
}
Esempio n. 2
0
/**
 * Allocate new cache manager
 * @arg sk		Netlink socket or NULL to auto allocate
 * @arg protocol	Netlink protocol this manager is used for
 * @arg flags		Flags (\c NL_AUTO_PROVIDE)
 * @arg result		Result pointer
 *
 * Allocates a new cache manager for the specified netlink protocol.
 *
 * 1. If sk is not specified (\c NULL) a netlink socket matching the
 *    specified protocol will be automatically allocated.
 *
 * 2. The socket will be put in non-blocking mode and sequence checking
 *    will be disabled regardless of whether the socket was provided by
 *    the caller or automatically allocated.
 *
 * 3. The socket will be connected.
 *
 * If the flag \c NL_AUTO_PROVIDE is specified, any cache added to the
 * manager will automatically be made available to other users using
 * nl_cache_mngt_provide().
 *
 * @note If the socket is provided by the caller, it is NOT recommended
 *       to use the socket for anything else besides receiving netlink
 *       notifications.
 *
 * @return 0 on success or a negative error code.
 */
int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags,
			struct nl_cache_mngr **result)
{
	struct nl_cache_mngr *mngr;
	int err = -NLE_NOMEM;

	/* Catch abuse of flags */
	if (flags & NL_ALLOCATED_SOCK)
		BUG();

	mngr = calloc(1, sizeof(*mngr));
	if (!mngr)
		return -NLE_NOMEM;

	if (!sk) {
		if (!(sk = nl_socket_alloc()))
			goto errout;

		flags |= NL_ALLOCATED_SOCK;
	}

	mngr->cm_sock = sk;
	mngr->cm_nassocs = NASSOC_INIT;
	mngr->cm_protocol = protocol;
	mngr->cm_flags = flags;
	mngr->cm_assocs = calloc(mngr->cm_nassocs,
				 sizeof(struct nl_cache_assoc));
	if (!mngr->cm_assocs)
		goto errout;

	/* Required to receive async event notifications */
	nl_socket_disable_seq_check(mngr->cm_sock);

	if ((err = nl_connect(mngr->cm_sock, protocol)) < 0)
		goto errout;

	if ((err = nl_socket_set_nonblocking(mngr->cm_sock)) < 0)
		goto errout;

	/* Create and allocate socket for sync cache fills */
	mngr->cm_sync_sock = nl_socket_alloc();
	if (!mngr->cm_sync_sock) {
		err = -NLE_NOMEM;
		goto errout;
	}
	if ((err = nl_connect(mngr->cm_sync_sock, protocol)) < 0)
		goto errout_free_sync_sock;

	NL_DBG(1, "Allocated cache manager %p, protocol %d, %d caches\n",
	       mngr, protocol, mngr->cm_nassocs);

	*result = mngr;
	return 0;

errout_free_sync_sock:
	nl_socket_free(mngr->cm_sync_sock);
errout:
	nl_cache_mngr_free(mngr);
	return err;
}
Esempio n. 3
0
int
iface_mon_start(iface_mon_cb cb)
{
    int err;

    iface_mon_sock = nl_socket_alloc();
    if (!iface_mon_sock) {
        fprintf(stderr, "Failed to allocate netlink socket.\n");
        return -ENOMEM;
    }

    nl_socket_disable_seq_check(iface_mon_sock);

    nl_socket_modify_cb(iface_mon_sock, NL_CB_VALID, NL_CB_CUSTOM, iface_mon_handler, cb);

    if (nl_connect(iface_mon_sock, NETLINK_ROUTE)) {
        fprintf(stderr, "Failed to connect to generic netlink.\n");
        err = -ENOLINK;
        goto out_handle_destroy;
    }

    nl_socket_add_membership(iface_mon_sock, RTNLGRP_LINK);

    return 0;

out_handle_destroy:
    nl_socket_free(iface_mon_sock);
    return err;
}
Esempio n. 4
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;
}
Esempio n. 5
0
int main()
{
  struct nl_sock * sk;
  int cbarg;

  // nl_debug = 4;

  // setup netlink socket
  sk = nl_socket_alloc();
  nl_socket_disable_seq_check(sk);	// disable sequence number check
  genl_connect(sk);

  int id = genl_ctrl_resolve(sk, DEMO_FAMILY_NAME);

  struct nl_msg * msg;


  // create a messgae
  msg = nlmsg_alloc();
  genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, id, 0,	// hdrlen
                        0,	// flags
                        DEMO_CMD,	// numeric command identifier
                        DEMO_VERSION	// interface version
                       );

  nla_put_string(msg, DEMO_ATTR1_STRING, "hola");
  nla_put_u16(msg, DEMO_ATTR2_UINT16, 0xf1);

  // send it
  nl_send_auto(sk, msg);

  // handle reply
  struct nl_cb * cb = NULL;
  cb = nl_cb_alloc(NL_CB_CUSTOM);

  //nl_cb_set_all(cb, NL_CB_DEBUG, NULL, NULL);
  nl_cb_set_all(cb, NL_CB_CUSTOM, cb_handler, &cbarg);
  nl_cb_err(cb, NL_CB_DEBUG, NULL, NULL);

  int nrecv = nl_recvmsgs_report(sk, cb);

  printf("cbarg %d nrecv %d\n", cbarg, nrecv);

  // cleanup
  nlmsg_free(msg);
  nl_close(sk);
  nl_socket_free(sk);

  return 0;
}
Esempio n. 6
0
int setup_socket(struct nl_sock *sk, struct options *opt)
{
	int ret;
	nl_socket_disable_seq_check(sk);

	if((ret = nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, netlink_msg_handler, opt)) < 0)
		return ret;

	if((ret = nl_connect(sk, NETLINK_ROUTE)) < 0)
		return ret;

	if((ret = nl_socket_add_memberships(sk, RTNLGRP_TC_STATS, 0)) < 0)
		return ret;
	return 0;
}
Esempio n. 7
0
/**
 * Allocate new cache manager
 * @arg sk		Netlink socket.
 * @arg protocol	Netlink Protocol this manager is used for
 * @arg flags		Flags
 * @arg result		Result pointer
 *
 * @return 0 on success or a negative error code.
 */
int nl_cache_mngr_alloc(struct nl_sock *sk, int protocol, int flags,
			struct nl_cache_mngr **result)
{
	struct nl_cache_mngr *mngr;
	int err = -NLE_NOMEM;

	if (sk == NULL)
		BUG();

	mngr = calloc(1, sizeof(*mngr));
	if (!mngr)
		goto errout;

	mngr->cm_handle = sk;
	mngr->cm_nassocs = 32;
	mngr->cm_protocol = protocol;
	mngr->cm_flags = flags;
	mngr->cm_assocs = calloc(mngr->cm_nassocs,
				 sizeof(struct nl_cache_assoc));
	if (!mngr->cm_assocs)
		goto errout;

	nl_socket_modify_cb(mngr->cm_handle, NL_CB_VALID, NL_CB_CUSTOM,
			    event_input, mngr);

	/* Required to receive async event notifications */
	nl_socket_disable_seq_check(mngr->cm_handle);

	if ((err = nl_connect(mngr->cm_handle, protocol) < 0))
		goto errout;

	if ((err = nl_socket_set_nonblocking(mngr->cm_handle) < 0))
		goto errout;

	NL_DBG(1, "Allocated cache manager %p, protocol %d, %d caches\n",
	       mngr, protocol, mngr->cm_nassocs);

	*result = mngr;
	return 0;

errout:
	nl_cache_mngr_free(mngr);
	return err;
}
Esempio n. 8
0
int ompi_btl_usnic_rtnl_sk_alloc(struct usnic_rtnl_sk **p_sk)
{
	struct usnic_rtnl_sk *unlsk;
	struct nl_sock *sock;
	int err;

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

	sock = nl_socket_alloc();
	if (!sock) {
		usnic_err("Failed to allocate nl socket\n");
		err = -ENOMEM;
		goto err_free_unlsk;
	}

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

	nl_socket_disable_seq_check(sock);
	err = nl_set_recv_timeout(sock);
	if (err < 0)
		goto err_close_nlsk;

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

err_close_nlsk:
	nl_close(sock);
err_free_sk:
	nl_socket_free(sock);
err_free_unlsk:
	free(unlsk);
	return err;
}
Esempio n. 9
0
static ni_socket_t *
__ni_rtevent_sock_open(void)
{
	unsigned int recv_buff_len = __ni_rtevent_config_recv_buff_len();
	unsigned int mesg_buff_len = __ni_rtevent_config_mesg_buff_len();
	ni_rtevent_handle_t *handle;
	ni_socket_t *sock;
	int fd, ret;

	if (!(handle = __ni_rtevent_handle_new())) {
		ni_error("Unable to allocate rtnetlink event handle: %m");
		return NULL;
	}

	if (!(handle->nlsock = nl_socket_alloc())) {
		ni_error("Cannot allocate rtnetlink event socket: %m");
		__ni_rtevent_handle_free(handle);
		return NULL;
	}

	/*
	 * Modify the callback for processing valid messages...
	 * We may pass some kind of data (event filter?) too...
	 */
	nl_socket_modify_cb(handle->nlsock, NL_CB_VALID, NL_CB_CUSTOM,
				__ni_rtevent_process_cb, NULL);

	/* Required to receive async event notifications */
	nl_socket_disable_seq_check(handle->nlsock);

	if ((ret = nl_connect(handle->nlsock, NETLINK_ROUTE)) < 0) {
		ni_error("Cannot open rtnetlink: %s", nl_geterror(ret));
		__ni_rtevent_handle_free(handle);
		return NULL;
	}

	/* Enable non-blocking processing */
	nl_socket_set_nonblocking(handle->nlsock);

	fd = nl_socket_get_fd(handle->nlsock);
	if (!(sock = ni_socket_wrap(fd, SOCK_DGRAM))) {
		ni_error("Cannot wrap rtnetlink event socket: %m");
		__ni_rtevent_handle_free(handle);
		return NULL;
	}

	if (recv_buff_len) {
		if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE,
				(char *)&recv_buff_len, sizeof(recv_buff_len)) &&
		    setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
				(char *)&recv_buff_len, sizeof(recv_buff_len))) {
			ni_warn("Unable to set netlink event receive buffer to %u bytes: %m",
					recv_buff_len);
		} else {
			ni_info("Using netlink event receive buffer of %u bytes",
					recv_buff_len);
		}
	}
	if (mesg_buff_len) {
		if (nl_socket_set_msg_buf_size(handle->nlsock, mesg_buff_len)) {
			ni_warn("Unable to set netlink event message buffer to %u bytes",
					mesg_buff_len);
		} else {
			ni_info("Using netlink event message buffer of %u bytes",
					mesg_buff_len);
		}
	}

	sock->user_data	= handle;
	sock->receive	= __ni_rtevent_receive;
	sock->close	= __ni_rtevent_close;
	sock->handle_error  = __ni_rtevent_sock_error_handler;
	sock->release_user_data = __ni_rtevent_sock_release_data;
	return sock;
}
Esempio n. 10
0
static struct nl_addr *process_get_neigh_mac(
		struct get_neigh_handler *neigh_handler)
{
	int err;
	struct nl_addr *ll_addr = get_neigh_mac(neigh_handler);
	struct rtnl_neigh *neigh_filter;
	fd_set fdset;
	int sock_fd;
	int fd;
	int nfds;
	int timer_fd;
	int ret;
	struct skt addr_dst;
	char buff[sizeof(SEND_PAYLOAD)] = SEND_PAYLOAD;
	int retries = 0;

	if (NULL != ll_addr)
		return ll_addr;

	err = nl_socket_add_membership(neigh_handler->sock,
				       RTNLGRP_NEIGH);
	if (err < 0)
		return NULL;

	neigh_filter = create_filter_neigh_for_dst(neigh_handler->dst,
						   neigh_handler->oif);
	if (neigh_filter == NULL)
		return NULL;

	set_neigh_filter(neigh_handler, neigh_filter);

	nl_socket_disable_seq_check(neigh_handler->sock);
	nl_socket_modify_cb(neigh_handler->sock, NL_CB_VALID, NL_CB_CUSTOM,
			    &get_neigh_cb, neigh_handler);

	fd = nl_socket_get_fd(neigh_handler->sock);

	err = create_socket(neigh_handler, &addr_dst, &sock_fd);

	if (err)
		return NULL;

	err = try_send_to(sock_fd, buff, sizeof(buff), &addr_dst);
	if (err)
		goto close_socket;

	timer_fd = create_timer(neigh_handler);
	if (timer_fd < 0)
		goto close_socket;

	nfds = MAX(fd, timer_fd) + 1;

	while (1) {
		FD_ZERO(&fdset);
		FD_SET(fd, &fdset);
		FD_SET(timer_fd, &fdset);

		/* wait for an incoming message on the netlink socket */
		ret = select(nfds, &fdset, NULL, NULL, NULL);
		if (ret == -1) {
			goto select_err;
		} else if (ret) {
			if (FD_ISSET(fd, &fdset)) {
				nl_recvmsgs_default(neigh_handler->sock);
				if (neigh_handler->found_ll_addr)
					break;
			} else {
				nl_cache_refill(neigh_handler->sock,
						neigh_handler->neigh_cache);
				ll_addr = get_neigh_mac(neigh_handler);
				if (NULL != ll_addr) {
					break;
				} else if (FD_ISSET(timer_fd, &fdset) &&
					   retries < NUM_OF_RETRIES) {
					try_send_to(sock_fd, buff, sizeof(buff),
						    &addr_dst);
				}
			}

			if (FD_ISSET(timer_fd, &fdset)) {
				uint64_t read_val;
				ssize_t rc;

				rc =
				    read(timer_fd, &read_val, sizeof(read_val));
				assert(rc == sizeof(read_val));
				if (++retries >=  NUM_OF_TRIES) {
					if (!errno)
						errno = EDESTADDRREQ;
					break;
				}
			}
		}
	}
select_err:
	close(timer_fd);
close_socket:
	close(sock_fd);
	return ll_addr ? ll_addr : neigh_handler->found_ll_addr;
}
Esempio n. 11
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_sock *nf_sock;
	struct nl_sock *rt_sock;
        struct nl_cache *link_cache;
	struct nfnl_log *log;
	enum nfnl_log_copy_mode copy_mode;
	uint32_t copy_range;
	int err;
	int family;

	nf_sock = nl_cli_alloc_socket();
	nl_socket_disable_seq_check(nf_sock);
	nl_socket_modify_cb(nf_sock, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL);

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

	nl_cli_connect(nf_sock, NETLINK_NETFILTER);

	family = nl_str2af(argv[1]);
	if (family == AF_UNSPEC)
		nl_cli_fatal(NLE_INVAL, "Unknown family \"%s\": %s",
			     argv[1], nl_geterror(family));

	nfnl_log_pf_unbind(nf_sock, family);
	if ((err = nfnl_log_pf_bind(nf_sock, family)) < 0)
		nl_cli_fatal(err, "Unable to bind logger: %s",
			     nl_geterror(err));

	log = alloc_log();
	nfnl_log_set_group(log, atoi(argv[2]));

	copy_mode = NFNL_LOG_COPY_META;
	if (argc > 3) {
		copy_mode = nfnl_log_str2copy_mode(argv[3]);
		if (copy_mode < 0)
			nl_cli_fatal(copy_mode,
				     "Unable to parse copy mode \"%s\": %s",
				     argv[3], nl_geterror(copy_mode));
	}
	nfnl_log_set_copy_mode(log, copy_mode);

	copy_range = 0xFFFF;
	if (argc > 4)
		copy_mode = atoi(argv[4]);
	nfnl_log_set_copy_range(log, copy_range);

	if ((err = nfnl_log_create(nf_sock, log)) < 0)
		nl_cli_fatal(err, "Unable to bind instance: %s",
			     nl_geterror(err));

	{
		struct nl_dump_params dp = {
			.dp_type = NL_DUMP_STATS,
			.dp_fd = stdout,
			.dp_dump_msgtype = 1,
		};

		printf("log params: ");
		nl_object_dump((struct nl_object *) log, &dp);
	}

	rt_sock = nl_cli_alloc_socket();
	nl_cli_connect(rt_sock, NETLINK_ROUTE);
	link_cache = nl_cli_link_alloc_cache(rt_sock);

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

		FD_ZERO(&rfds);

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

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

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

		if (retval) {
			if (FD_ISSET(nffd, &rfds))
				nl_recvmsgs_default(nf_sock);
			if (FD_ISSET(rtfd, &rfds))
				nl_recvmsgs_default(rt_sock);
		}
	}

	return 0;
}
Esempio n. 12
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(nf_sock, 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_sock *rt_sock;
	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;

	nf_sock = nfnl_queue_socket_alloc();
	if (nf_sock == NULL)
		nl_cli_fatal(ENOBUFS, "Unable to allocate netlink socket");

	nl_socket_disable_seq_check(nf_sock);
	nl_socket_modify_cb(nf_sock, 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");
		printf("family: [ inet | inet6 | ... ] \n");
		printf("group: the --queue-num arg that you gave to iptables\n");
		printf("copy_mode: [ none | meta | packet ] \n");
		return 2;
	}

	nl_cli_connect(nf_sock, NETLINK_NETFILTER);

	if ((family = nl_str2af(argv[1])) == AF_UNSPEC)
		nl_cli_fatal(NLE_INVAL, "Unknown family \"%s\"", argv[1]);

	nfnl_queue_pf_unbind(nf_sock, family);
	if ((err = nfnl_queue_pf_bind(nf_sock, family)) < 0)
		nl_cli_fatal(err, "Unable to bind logger: %s",
			     nl_geterror(err));

	queue = alloc_queue();
	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)
			nl_cli_fatal(copy_mode,
				     "Unable to parse copy mode \"%s\": %s",
				     argv[3], nl_geterror(copy_mode));
	}
	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 ((err = nfnl_queue_create(nf_sock, queue)) < 0)
		nl_cli_fatal(err, "Unable to bind queue: %s", nl_geterror(err));

	rt_sock = nl_cli_alloc_socket();
	nl_cli_connect(rt_sock, NETLINK_ROUTE);
	link_cache = nl_cli_link_alloc_cache(rt_sock);

	nl_socket_set_buffer_size(nf_sock, 1024*127, 1024*127);

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

		FD_ZERO(&rfds);

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

		rtfd = nl_socket_get_fd(rt_sock);
		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(nf_sock);
			if (FD_ISSET(rtfd, &rfds))
				nl_recvmsgs_default(rt_sock);
		}
	}

	return 0;
}
Esempio n. 13
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_sock *sk;
    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;

    sk = nl_socket_alloc();
    nl_socket_set_buffer_size(sk, 15000000, 15000000);

    //nl_handle_set_peer_pid(hndl, 0);
    //nl_set_passcred(hndl, 1);
    nl_socket_disable_seq_check(sk);

    if ( (ret_val=nl_connect(sk, NETLINK_GENERIC)) )
        goto init_return;


    if ( (ret_val=prepare_request_message(sk, 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(sk, msg, 0) ) != 0 )
        goto init_return;
    if ( (ret_val = read_message(sk, &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;
    }
    printf("Initialization netlink family OK\n");
    state.sk = sk;

    return 0;

init_return:
    nlmsg_free(ans_msg);

    if ( state.sk == NULL ) {
        nl_close(sk);
        nl_socket_free(sk);
    }

    return -EINVAL;
}