Пример #1
0
/**
 * nfnl_open - open a nfnetlink handler
 *
 * This function creates a nfnetlink handler, this is required to establish
 * a communication between the userspace and the nfnetlink system.
 *
 * On success, a valid address that points to a nfnl_handle structure
 * is returned. On error, NULL is returned and errno is set approapiately.
 */
struct nfnl_handle *nfnl_open(void)
{
	struct nfnl_handle *nfnlh;
	unsigned int addr_len;

	nfnlh = malloc(sizeof(*nfnlh));
	if (!nfnlh)
		return NULL;

	memset(nfnlh, 0, sizeof(*nfnlh));
	nfnlh->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
	if (nfnlh->fd == -1)
		goto err_free;

	nfnlh->local.nl_family = AF_NETLINK;
	nfnlh->peer.nl_family = AF_NETLINK;

	addr_len = sizeof(nfnlh->local);
	getsockname(nfnlh->fd, (struct sockaddr *)&nfnlh->local, &addr_len);
	if (addr_len != sizeof(nfnlh->local)) {
		errno = EINVAL;
		goto err_close;
	}
	if (nfnlh->local.nl_family != AF_NETLINK) {
		errno = EINVAL;
		goto err_close;
	}
	nfnlh->seq = time(NULL);
	nfnlh->rcv_buffer_size = NFNL_BUFFSIZE;

	/* don't set pid here, only first socket of process has real pid !!! 
	 * binding to pid '0' will default */

	/* let us do the initial bind */
	if (recalc_rebind_subscriptions(nfnlh) < 0)
		goto err_close;

	/* use getsockname to get the netlink pid that the kernel assigned us */
	addr_len = sizeof(nfnlh->local);
	getsockname(nfnlh->fd, (struct sockaddr *)&nfnlh->local, &addr_len);
	if (addr_len != sizeof(nfnlh->local)) {
		errno = EINVAL;
		goto err_close;
	}
	/* sequence tracking enabled by default */
	nfnlh->flags |= NFNL_F_SEQTRACK_ENABLED;

	return nfnlh;

err_close:
	close(nfnlh->fd);
err_free:
	free(nfnlh);
	return NULL;
}
Пример #2
0
/**
 * nfnl_subsys_open - open a netlink subsystem
 * @nfnlh: libnfnetlink handle
 * @subsys_id: which nfnetlink subsystem we are interested in
 * @cb_count: number of callbacks that are used maximum.
 * @subscriptions: netlink groups we want to be subscribed to
 *
 * This function creates a subsystem handler that contains the set of 
 * callbacks that handle certain types of messages coming from a netfilter
 * subsystem. Initially the callback set is empty, you can register callbacks
 * via nfnl_callback_register().
 *
 * On error, NULL is returned and errno is set appropiately. On success,
 * a valid address that points to a nfnl_subsys_handle structure is returned.
 */
struct nfnl_subsys_handle *
nfnl_subsys_open(struct nfnl_handle *nfnlh, uint8_t subsys_id,
		 uint8_t cb_count, uint32_t subscriptions)
{
	struct nfnl_subsys_handle *ssh;

	assert(nfnlh);

	if (subsys_id > NFNL_MAX_SUBSYS) { 
		errno = ENOENT;
		return NULL;
	}

	ssh = &nfnlh->subsys[subsys_id];
	if (ssh->cb) {
		errno = EBUSY;
		return NULL;
	}

	ssh->cb = calloc(cb_count, sizeof(*(ssh->cb)));
	if (!ssh->cb)
		return NULL;

	ssh->nfnlh = nfnlh;
	ssh->cb_count = cb_count;
	ssh->subscriptions = subscriptions;
	ssh->subsys_id = subsys_id;

	/* although now we have nfnl_join to subscribe to certain
	 * groups, just keep this to ensure compatibility */
	if (recalc_rebind_subscriptions(nfnlh) < 0) {
		free(ssh->cb);
		ssh->cb = NULL;
		return NULL;
	}
	
	return ssh;
}
Пример #3
0
/**
 * nfnl_open - open a nfnetlink handler
 *
 * This function creates a nfnetlink handler, this is required to establish
 * a communication between the userspace and the nfnetlink system.
 *
 * On success, a valid address that points to a nfnl_handle structure
 * is returned. On error, NULL is returned and errno is set approapiately.
 */
struct nfnl_handle *nfnl_open(void)
{
	struct nfnl_handle *nfnlh;
	unsigned int addr_len;
	int err;

	nfnlh = malloc(sizeof(*nfnlh));
	if (!nfnlh)
		return NULL;

	memset(nfnlh, 0, sizeof(*nfnlh));
	nfnlh->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
	if (nfnlh->fd == -1)
		goto err_free;

	nfnlh->local.nl_family = AF_NETLINK;
	nfnlh->peer.nl_family = AF_NETLINK;

	addr_len = sizeof(nfnlh->local);
	err = getsockname(nfnlh->fd, (struct sockaddr *)&nfnlh->local, 
			  &addr_len);
	if (addr_len != sizeof(nfnlh->local)) {
		errno = EINVAL;
		goto err_close;
	}
	if (nfnlh->local.nl_family != AF_NETLINK) {
		errno = EINVAL;
		goto err_close;
	}
	nfnlh->seq = time(NULL);

	/* don't set pid here, only first socket of process has real pid !!! 
	 * binding to pid '0' will default */

	/* let us do the initial bind */
	if (recalc_rebind_subscriptions(nfnlh) < 0)
		goto err_close;

	/* use getsockname to get the netlink pid that the kernel assigned us */
	addr_len = sizeof(nfnlh->local);
	err = getsockname(nfnlh->fd, (struct sockaddr *)&nfnlh->local, 
			  &addr_len);
	if (addr_len != sizeof(nfnlh->local)) {
		errno = EINVAL;
		goto err_close;
	}
#if defined(AEI_VDSL_CUSTOMER_NCS)

	printf("set NETLINK_RECV_NO_ENOBUFS\n");
	unsigned int enable=1;
	setsockopt(nfnlh->fd, SOL_NETLINK, NETLINK_NO_ENOBUFS,
			  &enable, sizeof(enable));
#endif

	return nfnlh;

err_close:
	close(nfnlh->fd);
err_free:
	free(nfnlh);
	return NULL;
}