Home | History | Annotate | Download | only in src
      1 /* libnfnetlink.c: generic library for communication with netfilter
      2  *
      3  * (C) 2002-2006 by Harald Welte <laforge (at) gnumonks.org>
      4  * (C) 2006-2011 by Pablo Neira Ayuso <pablo (at) netfilter.org>
      5  *
      6  * Based on some original ideas from Jay Schulist <jschlst (at) samba.org>
      7  *
      8  * Development of this code funded by Astaro AG (http://www.astaro.com)
      9  *
     10  * This program is free software; you can redistribute it and/or modify it
     11  * under the terms of the GNU General Public License version 2 as published
     12  * by the Free Software Foundation.
     13  *
     14  * 2005-09-14 Pablo Neira Ayuso <pablo (at) netfilter.org>:
     15  * 	Define structure nfnlhdr
     16  * 	Added __be64_to_cpu function
     17  *	Use NFA_TYPE macro to get the attribute type
     18  *
     19  * 2006-01-14 Harald Welte <laforge (at) netfilter.org>:
     20  * 	introduce nfnl_subsys_handle
     21  *
     22  * 2006-01-15 Pablo Neira Ayuso <pablo (at) netfilter.org>:
     23  * 	set missing subsys_id in nfnl_subsys_open
     24  * 	set missing nfnlh->local.nl_pid in nfnl_open
     25  *
     26  * 2006-01-26 Harald Welte <laforge (at) netfilter.org>:
     27  * 	remove bogus nfnlh->local.nl_pid from nfnl_open ;)
     28  * 	add 16bit attribute functions
     29  *
     30  * 2006-07-03 Pablo Neira Ayuso <pablo (at) netfilter.org>:
     31  * 	add iterator API
     32  * 	add replacements for nfnl_listen and nfnl_talk
     33  * 	fix error handling
     34  * 	add assertions
     35  * 	add documentation
     36  * 	minor cleanups
     37  */
     38 
     39 #include <stdlib.h>
     40 #include <stdio.h>
     41 #include <unistd.h>
     42 #include <errno.h>
     43 #include <string.h>
     44 #include <time.h>
     45 #include <netinet/in.h>
     46 #include <assert.h>
     47 #include <linux/types.h>
     48 #include <sys/socket.h>
     49 #include <sys/uio.h>
     50 
     51 #include <linux/netlink.h>
     52 
     53 #include <libnfnetlink/libnfnetlink.h>
     54 
     55 #ifndef NETLINK_ADD_MEMBERSHIP
     56 #define NETLINK_ADD_MEMBERSHIP 1
     57 #endif
     58 
     59 #ifndef SOL_NETLINK
     60 #define SOL_NETLINK 270
     61 #endif
     62 
     63 
     64 #define nfnl_error(format, args...) \
     65 	fprintf(stderr, "%s: " format "\n", __FUNCTION__, ## args)
     66 
     67 #ifdef _NFNL_DEBUG
     68 #define nfnl_debug_dump_packet nfnl_dump_packet
     69 #else
     70 #define nfnl_debug_dump_packet(a, b, ...)
     71 #endif
     72 
     73 struct nfnl_subsys_handle {
     74 	struct nfnl_handle 	*nfnlh;
     75 	u_int32_t		subscriptions;
     76 	u_int8_t		subsys_id;
     77 	u_int8_t		cb_count;
     78 	struct nfnl_callback 	*cb;	/* array of callbacks */
     79 };
     80 
     81 #define		NFNL_MAX_SUBSYS			16 /* enough for now */
     82 
     83 #define NFNL_F_SEQTRACK_ENABLED		(1 << 0)
     84 
     85 struct nfnl_handle {
     86 	int			fd;
     87 	struct sockaddr_nl	local;
     88 	struct sockaddr_nl	peer;
     89 	u_int32_t		subscriptions;
     90 	u_int32_t		seq;
     91 	u_int32_t		dump;
     92 	u_int32_t		rcv_buffer_size;	/* for nfnl_catch */
     93 	u_int32_t		flags;
     94 	struct nlmsghdr 	*last_nlhdr;
     95 	struct nfnl_subsys_handle subsys[NFNL_MAX_SUBSYS+1];
     96 };
     97 
     98 void nfnl_dump_packet(struct nlmsghdr *nlh, int received_len, char *desc)
     99 {
    100 	void *nlmsg_data = NLMSG_DATA(nlh);
    101 	struct nfattr *nfa = NFM_NFA(NLMSG_DATA(nlh));
    102 	int len = NFM_PAYLOAD(nlh);
    103 
    104 	printf("%s called from %s\n", __FUNCTION__, desc);
    105 	printf("  nlmsghdr = %p, received_len = %u\n", nlh, received_len);
    106 	printf("  NLMSG_DATA(nlh) = %p (+%td bytes)\n", nlmsg_data,
    107 	       (nlmsg_data - (void *)nlh));
    108 	printf("  NFM_NFA(NLMSG_DATA(nlh)) = %p (+%td bytes)\n",
    109 		nfa, ((void *)nfa - (void *)nlh));
    110 	printf("  NFM_PAYLOAD(nlh) = %u\n", len);
    111 	printf("  nlmsg_type = %u, nlmsg_len = %u, nlmsg_seq = %u "
    112 		"nlmsg_flags = 0x%x\n", nlh->nlmsg_type, nlh->nlmsg_len,
    113 		nlh->nlmsg_seq, nlh->nlmsg_flags);
    114 
    115 	while (NFA_OK(nfa, len)) {
    116 		printf("    nfa@%p: nfa_type=%u, nfa_len=%u\n",
    117 			nfa, NFA_TYPE(nfa), nfa->nfa_len);
    118 		nfa = NFA_NEXT(nfa,len);
    119 	}
    120 }
    121 
    122 /**
    123  * nfnl_fd - returns the descriptor that identifies the socket
    124  * @nfnlh: nfnetlink handler
    125  *
    126  * Use this function if you need to interact with the socket. Common
    127  * scenarios are the use of poll()/select() to achieve multiplexation.
    128  */
    129 int nfnl_fd(struct nfnl_handle *h)
    130 {
    131 	assert(h);
    132 	return h->fd;
    133 }
    134 
    135 /**
    136  * nfnl_portid - returns the Netlink port ID of this socket
    137  * @h: nfnetlink handler
    138  */
    139 unsigned int nfnl_portid(const struct nfnl_handle *h)
    140 {
    141 	assert(h);
    142 	return h->local.nl_pid;
    143 }
    144 
    145 static int recalc_rebind_subscriptions(struct nfnl_handle *nfnlh)
    146 {
    147 	int i, err;
    148 	u_int32_t new_subscriptions = nfnlh->subscriptions;
    149 
    150 	for (i = 0; i < NFNL_MAX_SUBSYS; i++)
    151 		new_subscriptions |= nfnlh->subsys[i].subscriptions;
    152 
    153 	nfnlh->local.nl_groups = new_subscriptions;
    154 	err = bind(nfnlh->fd, (struct sockaddr *)&nfnlh->local,
    155 		   sizeof(nfnlh->local));
    156 	if (err == -1)
    157 		return -1;
    158 
    159 	nfnlh->subscriptions = new_subscriptions;
    160 
    161 	return 0;
    162 }
    163 
    164 static void recalc_subscriptions(struct nfnl_handle *nfnlh)
    165 {
    166 	int i;
    167 	u_int32_t new_subscriptions = nfnlh->subscriptions;
    168 
    169 	for (i = 0; i < NFNL_MAX_SUBSYS; i++)
    170 		new_subscriptions |= nfnlh->subsys[i].subscriptions;
    171 
    172 	nfnlh->local.nl_groups = new_subscriptions;
    173 	nfnlh->subscriptions = new_subscriptions;
    174 }
    175 
    176 /**
    177  * nfnl_open - open a nfnetlink handler
    178  *
    179  * This function creates a nfnetlink handler, this is required to establish
    180  * a communication between the userspace and the nfnetlink system.
    181  *
    182  * On success, a valid address that points to a nfnl_handle structure
    183  * is returned. On error, NULL is returned and errno is set approapiately.
    184  */
    185 struct nfnl_handle *nfnl_open(void)
    186 {
    187 	struct nfnl_handle *nfnlh;
    188 	int fd;
    189 
    190 	fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
    191 	if (fd == -1)
    192 		return NULL;
    193 	nfnlh = nfnl_open2(fd, true);
    194 	if (nfnlh == NULL)
    195 		close(fd);
    196 	return nfnlh;
    197 }
    198 
    199 /**
    200  * nfnl_open2 - open a nfnetlink handler
    201  * @fd: passing file descriptor
    202  * @bind:  indicate the passing fd needs to be binded or not
    203  *
    204  * This function creates a nfnetlink handler, this is required to establish
    205  * a communication between the userspace and the nfnetlink system.
    206  *
    207  * On success, a valid address that points to a nfnl_handle structure
    208  * is returned. On error, NULL is returned and errno is set approapiately.
    209  */
    210 struct nfnl_handle *nfnl_open2(int fd, bool bind)
    211 {
    212 	struct nfnl_handle *nfnlh;
    213 	unsigned int addr_len;
    214 
    215 	if (fd < 0)
    216 		goto err;
    217 
    218 	nfnlh = malloc(sizeof(*nfnlh));
    219 	if (!nfnlh)
    220 		return NULL;
    221 
    222 	memset(nfnlh, 0, sizeof(*nfnlh));
    223 	nfnlh->fd = fd;
    224 
    225 	nfnlh->local.nl_family = AF_NETLINK;
    226 	nfnlh->peer.nl_family = AF_NETLINK;
    227 
    228 	addr_len = sizeof(nfnlh->local);
    229 	getsockname(nfnlh->fd, (struct sockaddr *)&nfnlh->local, &addr_len);
    230 	if (addr_len != sizeof(nfnlh->local)) {
    231 		errno = EINVAL;
    232 		goto err_free;
    233 	}
    234 	if (nfnlh->local.nl_family != AF_NETLINK) {
    235 		errno = EINVAL;
    236 		goto err_free;
    237 	}
    238 	nfnlh->seq = time(NULL);
    239 	nfnlh->rcv_buffer_size = NFNL_BUFFSIZE;
    240 
    241 	/* don't set pid here, only first socket of process has real pid !!!
    242 	 * binding to pid '0' will default */
    243 
    244 	/* let us do the initial bind */
    245 	if (bind) {
    246 		if (recalc_rebind_subscriptions(nfnlh) < 0)
    247 			goto err_free;
    248 	} else {
    249 		recalc_subscriptions(nfnlh);
    250 	}
    251 
    252 	/* use getsockname to get the netlink pid that the kernel assigned us */
    253 	addr_len = sizeof(nfnlh->local);
    254 	getsockname(nfnlh->fd, (struct sockaddr *)&nfnlh->local, &addr_len);
    255 	if (addr_len != sizeof(nfnlh->local)) {
    256 		errno = EINVAL;
    257 		goto err_free;
    258 	}
    259 	/* sequence tracking enabled by default */
    260 	nfnlh->flags |= NFNL_F_SEQTRACK_ENABLED;
    261 
    262 	return nfnlh;
    263 
    264 err_free:
    265 	free(nfnlh);
    266 err:
    267 	return NULL;
    268 }
    269 
    270 /**
    271  * nfnl_set_sequence_tracking - set netlink sequence tracking
    272  * @h: nfnetlink handler
    273  */
    274 void nfnl_set_sequence_tracking(struct nfnl_handle *h)
    275 {
    276 	h->flags |= NFNL_F_SEQTRACK_ENABLED;
    277 }
    278 
    279 /**
    280  * nfnl_unset_sequence_tracking - set netlink sequence tracking
    281  * @h: nfnetlink handler
    282  */
    283 void nfnl_unset_sequence_tracking(struct nfnl_handle *h)
    284 {
    285 	h->flags &= ~NFNL_F_SEQTRACK_ENABLED;
    286 }
    287 
    288 /**
    289  * nfnl_set_rcv_buffer_size - set the size of the receive buffer
    290  * @h: libnfnetlink handler
    291  * @size: buffer size
    292  *
    293  * This function sets the size of the receive buffer size, i.e. the size
    294  * of the buffer used by nfnl_recv. Default value is 4096 bytes.
    295  */
    296 void nfnl_set_rcv_buffer_size(struct nfnl_handle *h, unsigned int size)
    297 {
    298 	h->rcv_buffer_size = size;
    299 }
    300 
    301 /**
    302  * nfnl_subsys_open - open a netlink subsystem
    303  * @nfnlh: libnfnetlink handle
    304  * @subsys_id: which nfnetlink subsystem we are interested in
    305  * @cb_count: number of callbacks that are used maximum.
    306  * @subscriptions: netlink groups we want to be subscribed to
    307  *
    308  * This function creates a subsystem handler that contains the set of
    309  * callbacks that handle certain types of messages coming from a netfilter
    310  * subsystem. Initially the callback set is empty, you can register callbacks
    311  * via nfnl_callback_register().
    312  *
    313  * On error, NULL is returned and errno is set appropiately. On success,
    314  * a valid address that points to a nfnl_subsys_handle structure is returned.
    315  */
    316 struct nfnl_subsys_handle *
    317 nfnl_subsys_open(struct nfnl_handle *nfnlh, u_int8_t subsys_id,
    318 		 u_int8_t cb_count, u_int32_t subscriptions)
    319 {
    320 	return nfnl_subsys_open2 (nfnlh, subsys_id, cb_count, subscriptions, true);
    321 }
    322 
    323 /**
    324  * nfnl_subsys_open2 - open a netlink subsystem
    325  * @nfnlh: libnfnetlink handle
    326  * @subsys_id: which nfnetlink subsystem we are interested in
    327  * @cb_count: number of callbacks that are used maximum.
    328  * @subscriptions: netlink groups we want to be subscribed to
    329  * @bind: indicate the passing fd needs to be binded or not
    330  *
    331  * This function creates a subsystem handler that contains the set of
    332  * callbacks that handle certain types of messages coming from a netfilter
    333  * subsystem. Initially the callback set is empty, you can register callbacks
    334  * via nfnl_callback_register().
    335  *
    336  * On error, NULL is returned and errno is set appropiately. On success,
    337  * a valid address that points to a nfnl_subsys_handle structure is returned.
    338  */
    339 struct nfnl_subsys_handle *
    340 nfnl_subsys_open2(struct nfnl_handle *nfnlh, u_int8_t subsys_id,
    341 		 u_int8_t cb_count, u_int32_t subscriptions, bool bind)
    342 {
    343 	struct nfnl_subsys_handle *ssh;
    344 	int err = 0;
    345 
    346 	assert(nfnlh);
    347 
    348 	if (subsys_id > NFNL_MAX_SUBSYS) {
    349 		errno = ENOENT;
    350 		return NULL;
    351 	}
    352 
    353 	ssh = &nfnlh->subsys[subsys_id];
    354 	if (ssh->cb) {
    355 		errno = EBUSY;
    356 		return NULL;
    357 	}
    358 
    359 	ssh->cb = calloc(cb_count, sizeof(*(ssh->cb)));
    360 	if (!ssh->cb)
    361 		return NULL;
    362 
    363 	ssh->nfnlh = nfnlh;
    364 	ssh->cb_count = cb_count;
    365 	ssh->subscriptions = subscriptions;
    366 	ssh->subsys_id = subsys_id;
    367 
    368 	/* although now we have nfnl_join to subscribe to certain
    369 	 * groups, just keep this to ensure compatibility */
    370 	if (bind)
    371 		err = recalc_rebind_subscriptions(nfnlh);
    372 	else
    373 		recalc_subscriptions(nfnlh);
    374 	if (err < 0) {
    375 		free(ssh->cb);
    376 		ssh->cb = NULL;
    377 		return NULL;
    378 	}
    379 	return ssh;
    380 }
    381 
    382 /**
    383  * nfnl_subsys_close - close a nfnetlink subsys handler
    384  * @ssh: nfnetlink subsystem handler
    385  *
    386  * Release all the callbacks registered in a subsystem handler.
    387  */
    388 void nfnl_subsys_close(struct nfnl_subsys_handle *ssh)
    389 {
    390 	assert(ssh);
    391 
    392 	ssh->subscriptions = 0;
    393 	ssh->cb_count = 0;
    394 	if (ssh->cb) {
    395 		free(ssh->cb);
    396 		ssh->cb = NULL;
    397 	}
    398 }
    399 
    400 /**
    401  * nfnl_close - close a nfnetlink handler
    402  * @nfnlh: nfnetlink handler
    403  *
    404  * This function closes the nfnetlink handler. On success, 0 is returned.
    405  * On error, -1 is returned and errno is set appropiately.
    406  */
    407 int nfnl_close(struct nfnl_handle *nfnlh)
    408 {
    409 	int ret;
    410 
    411 	assert(nfnlh);
    412 	ret = close(nfnlh->fd);
    413 	if (ret < 0)
    414 		return ret;
    415 	return nfnl_close2(nfnlh);
    416 }
    417 
    418 /**
    419  * nfnl_close2 - close a nfnetlink handler but keep fd
    420  * @nfnlh: nfnetlink handler
    421  *
    422  * This function closes the nfnetlink handler. On success, 0 is returned.
    423  * On error, -1 is returned and errno is set appropiately.
    424  */
    425 int nfnl_close2(struct nfnl_handle *nfnlh)
    426 {
    427 	int i;
    428 
    429 	assert(nfnlh);
    430 
    431 	for (i = 0; i < NFNL_MAX_SUBSYS; i++)
    432 		nfnl_subsys_close(&nfnlh->subsys[i]);
    433 
    434 	free(nfnlh);
    435 
    436 	return 0;
    437 }
    438 
    439 /**
    440  * nfnl_join - join a nfnetlink multicast group
    441  * @nfnlh: nfnetlink handler
    442  * @group: group we want to join
    443  *
    444  * This function is used to join a certain multicast group. It must be
    445  * called once the nfnetlink handler has been created. If any doubt,
    446  * just use it if you have to listen to nfnetlink events.
    447  *
    448  * On success, 0 is returned. On error, -1 is returned and errno is set
    449  * approapiately.
    450  */
    451 int nfnl_join(const struct nfnl_handle *nfnlh, unsigned int group)
    452 {
    453 	assert(nfnlh);
    454 	return setsockopt(nfnlh->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
    455 			  &group, sizeof(group));
    456 }
    457 
    458 /**
    459  * nfnl_send - send a nfnetlink message through netlink socket
    460  * @nfnlh: nfnetlink handler
    461  * @n: netlink message
    462  *
    463  * On success, the number of bytes is returned. On error, -1 is returned
    464  * and errno is set appropiately.
    465  */
    466 int nfnl_send(struct nfnl_handle *nfnlh, struct nlmsghdr *n)
    467 {
    468 	assert(nfnlh);
    469 	assert(n);
    470 
    471 	nfnl_debug_dump_packet(n, n->nlmsg_len+sizeof(*n), "nfnl_send");
    472 
    473 	return sendto(nfnlh->fd, n, n->nlmsg_len, 0,
    474 		      (struct sockaddr *)&nfnlh->peer, sizeof(nfnlh->peer));
    475 }
    476 
    477 int nfnl_sendmsg(const struct nfnl_handle *nfnlh, const struct msghdr *msg,
    478 		 unsigned int flags)
    479 {
    480 	assert(nfnlh);
    481 	assert(msg);
    482 
    483 	return sendmsg(nfnlh->fd, msg, flags);
    484 }
    485 
    486 int nfnl_sendiov(const struct nfnl_handle *nfnlh, const struct iovec *iov,
    487 		 unsigned int num, unsigned int flags)
    488 {
    489 	struct msghdr msg;
    490 
    491 	assert(nfnlh);
    492 
    493 	msg.msg_name = (struct sockaddr *) &nfnlh->peer;
    494 	msg.msg_namelen = sizeof(nfnlh->peer);
    495 	msg.msg_iov = (struct iovec *) iov;
    496 	msg.msg_iovlen = num;
    497 	msg.msg_control = NULL;
    498 	msg.msg_controllen = 0;
    499 	msg.msg_flags = 0;
    500 
    501 	return nfnl_sendmsg(nfnlh, &msg, flags);
    502 }
    503 
    504 /**
    505  * nfnl_fill_hdr - fill in netlink and nfnetlink header
    506  * @nfnlh: nfnetlink handle
    507  * @nlh: netlink message to be filled in
    508  * @len: length of _payload_ bytes (not including nfgenmsg)
    509  * @family: AF_INET / ...
    510  * @res_id: resource id
    511  * @msg_type: nfnetlink message type (without subsystem)
    512  * @msg_flags: netlink message flags
    513  *
    514  * This function sets up appropiately the nfnetlink header. See that the
    515  * pointer to the netlink message passed must point to a memory region of
    516  * at least the size of struct nlmsghdr + struct nfgenmsg.
    517  */
    518 void nfnl_fill_hdr(struct nfnl_subsys_handle *ssh,
    519 		    struct nlmsghdr *nlh, unsigned int len,
    520 		    u_int8_t family,
    521 		    u_int16_t res_id,
    522 		    u_int16_t msg_type,
    523 		    u_int16_t msg_flags)
    524 {
    525 	assert(ssh);
    526 	assert(nlh);
    527 
    528 	struct nfgenmsg *nfg = (void *)nlh + sizeof(*nlh);
    529 
    530 	nlh->nlmsg_len = NLMSG_LENGTH(len+sizeof(*nfg));
    531 	nlh->nlmsg_type = (ssh->subsys_id<<8)|msg_type;
    532 	nlh->nlmsg_flags = msg_flags;
    533 	nlh->nlmsg_pid = 0;
    534 
    535 	if (ssh->nfnlh->flags & NFNL_F_SEQTRACK_ENABLED) {
    536 		nlh->nlmsg_seq = ++ssh->nfnlh->seq;
    537 		/* kernel uses sequence number zero for events */
    538 		if (!ssh->nfnlh->seq)
    539 			nlh->nlmsg_seq = ssh->nfnlh->seq = time(NULL);
    540 	} else {
    541 		/* unset sequence number, ignore it */
    542 		nlh->nlmsg_seq = 0;
    543 	}
    544 
    545 	nfg->nfgen_family = family;
    546 	nfg->version = NFNETLINK_V0;
    547 	nfg->res_id = htons(res_id);
    548 }
    549 
    550 struct nfattr *
    551 nfnl_parse_hdr(const struct nfnl_handle *nfnlh,
    552 		const struct nlmsghdr *nlh,
    553 		struct nfgenmsg **genmsg)
    554 {
    555 	if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg)))
    556 		return NULL;
    557 
    558 	if (nlh->nlmsg_len == NLMSG_LENGTH(sizeof(struct nfgenmsg))) {
    559 		if (genmsg)
    560 			*genmsg = (void *)nlh + sizeof(*nlh);
    561 		return NULL;
    562 	}
    563 
    564 	if (genmsg)
    565 		*genmsg = (void *)nlh + sizeof(*nlh);
    566 
    567 	return (void *)nlh + NLMSG_LENGTH(sizeof(struct nfgenmsg));
    568 }
    569 
    570 /**
    571  * nfnl_recv - receive data from a nfnetlink subsystem
    572  * @h: nfnetlink handler
    573  * @buf: buffer where the data will be stored
    574  * @len: size of the buffer
    575  *
    576  * This function doesn't perform any sanity checking. So do no expect
    577  * that the data is well-formed. Such checkings are done by the parsing
    578  * functions.
    579  *
    580  * On success, 0 is returned. On error, -1 is returned and errno is set
    581  * appropiately.
    582  *
    583  * Note that ENOBUFS is returned in case that nfnetlink is exhausted. In
    584  * that case is possible that the information requested is incomplete.
    585  */
    586 ssize_t
    587 nfnl_recv(const struct nfnl_handle *h, unsigned char *buf, size_t len)
    588 {
    589 	socklen_t addrlen;
    590 	int status;
    591 	struct sockaddr_nl peer;
    592 
    593 	assert(h);
    594 	assert(buf);
    595 	assert(len > 0);
    596 
    597 	if (len < sizeof(struct nlmsgerr)
    598 	    || len < sizeof(struct nlmsghdr)) {
    599 	    	errno = EBADMSG;
    600 		return -1;
    601 	}
    602 
    603 	addrlen = sizeof(h->peer);
    604 	status = recvfrom(h->fd, buf, len, 0, (struct sockaddr *)&peer,
    605 			&addrlen);
    606 	if (status <= 0)
    607 		return status;
    608 
    609 	if (addrlen != sizeof(peer)) {
    610 		errno = EINVAL;
    611 		return -1;
    612 	}
    613 
    614 	if (peer.nl_pid != 0) {
    615 		errno = ENOMSG;
    616 		return -1;
    617 	}
    618 
    619 	return status;
    620 }
    621 /**
    622  * nfnl_listen: listen for one or more netlink messages
    623  * @nfnhl: libnfnetlink handle
    624  * @handler: callback function to be called for every netlink message
    625  *          - the callback handler should normally return 0
    626  *          - but may return a negative error code which will cause
    627  *            nfnl_listen to return immediately with the same error code
    628  *          - or return a postivie error code which will cause
    629  *            nfnl_listen to return after it has finished processing all
    630  *            the netlink messages in the current packet
    631  *          Thus a positive error code will terminate nfnl_listen "soon"
    632  *          without any loss of data, a negative error code will terminate
    633  *          nfnl_listen "very soon" and throw away data already read from
    634  *          the netlink socket.
    635  * @jarg: opaque argument passed on to callback
    636  *
    637  * This function is used to receive and process messages coming from an open
    638  * nfnetlink handler like events or information request via nfnl_send().
    639  *
    640  * On error, -1 is returned, unfortunately errno is not always set
    641  * appropiately. For that reason, the use of this function is DEPRECATED.
    642  * Please, use nfnl_receive_process() instead.
    643  */
    644 int nfnl_listen(struct nfnl_handle *nfnlh,
    645 		int (*handler)(struct sockaddr_nl *, struct nlmsghdr *n,
    646 			       void *), void *jarg)
    647 {
    648 	struct sockaddr_nl nladdr;
    649 	char buf[NFNL_BUFFSIZE] __attribute__ ((aligned));
    650 	struct iovec iov;
    651 	int remain;
    652 	struct nlmsghdr *h;
    653 	struct nlmsgerr *msgerr;
    654 	int quit=0;
    655 
    656 	struct msghdr msg = {
    657 		.msg_name    = &nladdr,
    658 		.msg_namelen = sizeof(nladdr),
    659 		.msg_iov     = &iov,
    660 		.msg_iovlen  = 1,
    661 	};
    662 
    663 	memset(&nladdr, 0, sizeof(nladdr));
    664 	nladdr.nl_family = AF_NETLINK;
    665 	iov.iov_base = buf;
    666 	iov.iov_len = sizeof(buf);
    667 
    668 	while (! quit) {
    669 		remain = recvmsg(nfnlh->fd, &msg, 0);
    670 		if (remain < 0) {
    671 			if (errno == EINTR)
    672 				continue;
    673 			/* Bad file descriptor */
    674 			else if (errno == EBADF)
    675 				break;
    676 			else if (errno == EAGAIN)
    677 				break;
    678 			nfnl_error("recvmsg overrun: %s", strerror(errno));
    679 			continue;
    680 		}
    681 		if (remain == 0) {
    682 			nfnl_error("EOF on netlink");
    683 			return -1;
    684 		}
    685 		if (msg.msg_namelen != sizeof(nladdr)) {
    686 			nfnl_error("Bad sender address len (%d)",
    687 				   msg.msg_namelen);
    688 			return -1;
    689 		}
    690 
    691 		for (h = (struct nlmsghdr *)buf; remain >= sizeof(*h);) {
    692 			int err;
    693 			int len = h->nlmsg_len;
    694 			int l = len - sizeof(*h);
    695 
    696 			if (l < 0 || len > remain) {
    697 				if (msg.msg_flags & MSG_TRUNC) {
    698 					nfnl_error("MSG_TRUNC");
    699 					return -1;
    700 				}
    701 				nfnl_error("Malformed msg (len=%d)", len);
    702 				return -1;
    703 			}
    704 
    705 			/* end of messages reached, let's return */
    706 			if (h->nlmsg_type == NLMSG_DONE)
    707 				return 0;
    708 
    709 			/* Break the loop if success is explicitely
    710 			 * reported via NLM_F_ACK flag set */
    711 			if (h->nlmsg_type == NLMSG_ERROR) {
    712 				msgerr = NLMSG_DATA(h);
    713 				return msgerr->error;
    714 			}
    715 
    716 			err = handler(&nladdr, h, jarg);
    717 			if (err < 0)
    718 				return err;
    719 			quit |= err;
    720 
    721 			/* FIXME: why not _NEXT macros, etc.? */
    722 			//h = NLMSG_NEXT(h, remain);
    723 			remain -= NLMSG_ALIGN(len);
    724 			h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
    725 		}
    726 		if (msg.msg_flags & MSG_TRUNC) {
    727 			nfnl_error("MSG_TRUNC");
    728 			continue;
    729 		}
    730 		if (remain) {
    731 			nfnl_error("remnant size %d", remain);
    732 			return -1;
    733 		}
    734 	}
    735 
    736 	return quit;
    737 }
    738 
    739 /**
    740  * nfnl_talk - send a request and then receive and process messages returned
    741  * @nfnlh: nfnetelink handler
    742  * @n: netlink message that contains the request
    743  * @peer: peer PID
    744  * @groups: netlink groups
    745  * @junk: callback called if out-of-sequence messages were received
    746  * @jarg: data for the junk callback
    747  *
    748  * This function is used to request an action that does not returns any
    749  * information. On error, a negative value is returned, errno could be
    750  * set appropiately. For that reason, the use of this function is DEPRECATED.
    751  * Please, use nfnl_query() instead.
    752  */
    753 int nfnl_talk(struct nfnl_handle *nfnlh, struct nlmsghdr *n, pid_t peer,
    754 	      unsigned groups, struct nlmsghdr *answer,
    755 	      int (*junk)(struct sockaddr_nl *, struct nlmsghdr *n, void *),
    756 	      void *jarg)
    757 {
    758 	char buf[NFNL_BUFFSIZE] __attribute__ ((aligned));
    759 	struct sockaddr_nl nladdr;
    760 	struct nlmsghdr *h;
    761 	unsigned int seq;
    762 	int status;
    763 	struct iovec iov = {
    764 		n, n->nlmsg_len
    765 	};
    766 	struct msghdr msg = {
    767 		.msg_name    = &nladdr,
    768 		.msg_namelen = sizeof(nladdr),
    769 		.msg_iov     = &iov,
    770 		.msg_iovlen  = 1,
    771 	};
    772 
    773 	memset(&nladdr, 0, sizeof(nladdr));
    774 	nladdr.nl_family = AF_NETLINK;
    775 	nladdr.nl_pid = peer;
    776 	nladdr.nl_groups = groups;
    777 
    778 	n->nlmsg_seq = seq = ++nfnlh->seq;
    779 	/* FIXME: why ? */
    780 	if (!answer)
    781 		n->nlmsg_flags |= NLM_F_ACK;
    782 
    783 	status = sendmsg(nfnlh->fd, &msg, 0);
    784 	if (status < 0) {
    785 		nfnl_error("sendmsg(netlink) %s", strerror(errno));
    786 		return -1;
    787 	}
    788 	iov.iov_base = buf;
    789 	iov.iov_len = sizeof(buf);
    790 
    791 	while (1) {
    792 		status = recvmsg(nfnlh->fd, &msg, 0);
    793 		if (status < 0) {
    794 			if (errno == EINTR)
    795 				continue;
    796 			nfnl_error("recvmsg over-run");
    797 			continue;
    798 		}
    799 		if (status == 0) {
    800 			nfnl_error("EOF on netlink");
    801 			return -1;
    802 		}
    803 		if (msg.msg_namelen != sizeof(nladdr)) {
    804 			nfnl_error("Bad sender address len %d",
    805 				   msg.msg_namelen);
    806 			return -1;
    807 		}
    808 
    809 		for (h = (struct nlmsghdr *)buf; status >= sizeof(*h); ) {
    810 			int len = h->nlmsg_len;
    811 			int l = len - sizeof(*h);
    812 			int err;
    813 
    814 			if (l < 0 || len > status) {
    815 				if (msg.msg_flags & MSG_TRUNC) {
    816 					nfnl_error("Truncated message\n");
    817 					return -1;
    818 				}
    819 				nfnl_error("Malformed message: len=%d\n", len);
    820 				return -1; /* FIXME: libnetlink exits here */
    821 			}
    822 
    823 			if (h->nlmsg_pid != nfnlh->local.nl_pid ||
    824 			    h->nlmsg_seq != seq) {
    825 				if (junk) {
    826 					err = junk(&nladdr, h, jarg);
    827 					if (err < 0)
    828 						return err;
    829 				}
    830 				goto cont;
    831 			}
    832 
    833 			if (h->nlmsg_type == NLMSG_ERROR) {
    834 				struct nlmsgerr *err = NLMSG_DATA(h);
    835 				if (l < sizeof(struct nlmsgerr))
    836 					nfnl_error("ERROR truncated\n");
    837 				else {
    838 					errno = -err->error;
    839 					if (errno == 0) {
    840 						if (answer)
    841 							memcpy(answer, h, h->nlmsg_len);
    842 						return 0;
    843 					}
    844 					perror("NFNETLINK answers");
    845 				}
    846 				return err->error;
    847 			}
    848 			if (answer) {
    849 				memcpy(answer, h, h->nlmsg_len);
    850 				return 0;
    851 			}
    852 
    853 			nfnl_error("Unexpected reply!\n");
    854 cont:
    855 			status -= NLMSG_ALIGN(len);
    856 			h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
    857 		}
    858 		if (msg.msg_flags & MSG_TRUNC) {
    859 			nfnl_error("Messages truncated\n");
    860 			continue;
    861 		}
    862 		if (status)
    863 			nfnl_error("Remnant of size %d\n", status);
    864 	}
    865 }
    866 
    867 /**
    868  * nfnl_addattr_l - Add variable length attribute to nlmsghdr
    869  * @n: netlink message header to which attribute is to be added
    870  * @maxlen: maximum length of netlink message header
    871  * @type: type of new attribute
    872  * @data: content of new attribute
    873  * @len: attribute length
    874  */
    875 int nfnl_addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
    876 		   int alen)
    877 {
    878 	int len = NFA_LENGTH(alen);
    879 	struct nfattr *nfa;
    880 
    881 	assert(n);
    882 	assert(maxlen > 0);
    883 	assert(type >= 0);
    884 
    885 	if ((NLMSG_ALIGN(n->nlmsg_len) + len) > maxlen) {
    886 		errno = ENOSPC;
    887 		return -1;
    888 	}
    889 
    890 	nfa = NLMSG_TAIL(n);
    891 	nfa->nfa_type = type;
    892 	nfa->nfa_len = len;
    893 	memcpy(NFA_DATA(nfa), data, alen);
    894 	n->nlmsg_len = (NLMSG_ALIGN(n->nlmsg_len) + NFA_ALIGN(len));
    895 	return 0;
    896 }
    897 
    898 /**
    899  * nfnl_nfa_addattr_l - Add variable length attribute to struct nfattr
    900  *
    901  * @nfa: struct nfattr
    902  * @maxlen: maximal length of nfattr buffer
    903  * @type: type for new attribute
    904  * @data: content of new attribute
    905  * @alen: length of new attribute
    906  *
    907  */
    908 int nfnl_nfa_addattr_l(struct nfattr *nfa, int maxlen, int type,
    909 		       const void *data, int alen)
    910 {
    911 	struct nfattr *subnfa;
    912 	int len = NFA_LENGTH(alen);
    913 
    914 	assert(nfa);
    915 	assert(maxlen > 0);
    916 	assert(type >= 0);
    917 
    918 	if (NFA_ALIGN(nfa->nfa_len) + len > maxlen) {
    919 		errno = ENOSPC;
    920 		return -1;
    921 	}
    922 
    923 	subnfa = (struct nfattr *)(((char *)nfa) + NFA_ALIGN(nfa->nfa_len));
    924 	subnfa->nfa_type = type;
    925 	subnfa->nfa_len = len;
    926 	memcpy(NFA_DATA(subnfa), data, alen);
    927 	nfa->nfa_len = NFA_ALIGN(nfa->nfa_len) + len;
    928 
    929 	return 0;
    930 }
    931 
    932 /**
    933  * nfnl_addattr8 - Add u_int8_t attribute to nlmsghdr
    934  *
    935  * @n: netlink message header to which attribute is to be added
    936  * @maxlen: maximum length of netlink message header
    937  * @type: type of new attribute
    938  * @data: content of new attribute
    939  */
    940 int nfnl_addattr8(struct nlmsghdr *n, int maxlen, int type, u_int8_t data)
    941 {
    942 	assert(n);
    943 	assert(maxlen > 0);
    944 	assert(type >= 0);
    945 
    946 	return nfnl_addattr_l(n, maxlen, type, &data, sizeof(data));
    947 }
    948 
    949 /**
    950  * nfnl_nfa_addattr16 - Add u_int16_t attribute to struct nfattr
    951  *
    952  * @nfa: struct nfattr
    953  * @maxlen: maximal length of nfattr buffer
    954  * @type: type for new attribute
    955  * @data: content of new attribute
    956  *
    957  */
    958 int nfnl_nfa_addattr16(struct nfattr *nfa, int maxlen, int type,
    959 		       u_int16_t data)
    960 {
    961 	assert(nfa);
    962 	assert(maxlen > 0);
    963 	assert(type >= 0);
    964 
    965 	return nfnl_nfa_addattr_l(nfa, maxlen, type, &data, sizeof(data));
    966 }
    967 
    968 /**
    969  * nfnl_addattr16 - Add u_int16_t attribute to nlmsghdr
    970  *
    971  * @n: netlink message header to which attribute is to be added
    972  * @maxlen: maximum length of netlink message header
    973  * @type: type of new attribute
    974  * @data: content of new attribute
    975  *
    976  */
    977 int nfnl_addattr16(struct nlmsghdr *n, int maxlen, int type,
    978 		   u_int16_t data)
    979 {
    980 	assert(n);
    981 	assert(maxlen > 0);
    982 	assert(type >= 0);
    983 
    984 	return nfnl_addattr_l(n, maxlen, type, &data, sizeof(data));
    985 }
    986 
    987 /**
    988  * nfnl_nfa_addattr32 - Add u_int32_t attribute to struct nfattr
    989  *
    990  * @nfa: struct nfattr
    991  * @maxlen: maximal length of nfattr buffer
    992  * @type: type for new attribute
    993  * @data: content of new attribute
    994  *
    995  */
    996 int nfnl_nfa_addattr32(struct nfattr *nfa, int maxlen, int type,
    997 		       u_int32_t data)
    998 {
    999 	assert(nfa);
   1000 	assert(maxlen > 0);
   1001 	assert(type >= 0);
   1002 
   1003 	return nfnl_nfa_addattr_l(nfa, maxlen, type, &data, sizeof(data));
   1004 }
   1005 
   1006 /**
   1007  * nfnl_addattr32 - Add u_int32_t attribute to nlmsghdr
   1008  *
   1009  * @n: netlink message header to which attribute is to be added
   1010  * @maxlen: maximum length of netlink message header
   1011  * @type: type of new attribute
   1012  * @data: content of new attribute
   1013  *
   1014  */
   1015 int nfnl_addattr32(struct nlmsghdr *n, int maxlen, int type,
   1016 		   u_int32_t data)
   1017 {
   1018 	assert(n);
   1019 	assert(maxlen > 0);
   1020 	assert(type >= 0);
   1021 
   1022 	return nfnl_addattr_l(n, maxlen, type, &data, sizeof(data));
   1023 }
   1024 
   1025 /**
   1026  * nfnl_parse_attr - Parse a list of nfattrs into a pointer array
   1027  *
   1028  * @tb: pointer array, will be filled in (output)
   1029  * @max: size of pointer array
   1030  * @nfa: pointer to list of nfattrs
   1031  * @len: length of 'nfa'
   1032  *
   1033  * The returned value is equal to the number of remaining bytes of the netlink
   1034  * message that cannot be parsed.
   1035  */
   1036 int nfnl_parse_attr(struct nfattr *tb[], int max, struct nfattr *nfa, int len)
   1037 {
   1038 	assert(tb);
   1039 	assert(max > 0);
   1040 	assert(nfa);
   1041 
   1042 	memset(tb, 0, sizeof(struct nfattr *) * max);
   1043 
   1044 	while (NFA_OK(nfa, len)) {
   1045 		if (NFA_TYPE(nfa) <= max)
   1046 			tb[NFA_TYPE(nfa)-1] = nfa;
   1047                 nfa = NFA_NEXT(nfa,len);
   1048 	}
   1049 
   1050 	return len;
   1051 }
   1052 
   1053 /**
   1054  * nfnl_build_nfa_iovec - Build two iovec's from tag, length and value
   1055  *
   1056  * @iov: pointer to array of two 'struct iovec' (caller-allocated)
   1057  * @nfa: pointer to 'struct nfattr' (caller-allocated)
   1058  * @type: type (tag) of attribute
   1059  * @len: length of value
   1060  * @val: pointer to buffer containing 'value'
   1061  *
   1062  */
   1063 void nfnl_build_nfa_iovec(struct iovec *iov, struct nfattr *nfa,
   1064 			  u_int16_t type, u_int32_t len, unsigned char *val)
   1065 {
   1066 	assert(iov);
   1067 	assert(nfa);
   1068 
   1069         /* Set the attribut values */
   1070         nfa->nfa_len = sizeof(struct nfattr) + len;
   1071         nfa->nfa_type = type;
   1072 
   1073 	iov[0].iov_base = nfa;
   1074 	iov[0].iov_len = sizeof(*nfa);
   1075 	iov[1].iov_base = val;
   1076 	iov[1].iov_len = NFA_ALIGN(len);
   1077 }
   1078 
   1079 #ifndef SO_RCVBUFFORCE
   1080 #define SO_RCVBUFFORCE	(33)
   1081 #endif
   1082 
   1083 /**
   1084  * nfnl_rcvbufsiz - set the socket buffer size
   1085  * @h: nfnetlink handler
   1086  * @size: size of the buffer we want to set
   1087  *
   1088  * This function sets the new size of the socket buffer. Use this setting
   1089  * to increase the socket buffer size if your system is reporting ENOBUFS
   1090  * errors.
   1091  *
   1092  * This function returns the new size of the socket buffer.
   1093  */
   1094 unsigned int nfnl_rcvbufsiz(const struct nfnl_handle *h, unsigned int size)
   1095 {
   1096 	int status;
   1097 	socklen_t socklen = sizeof(size);
   1098 	unsigned int read_size = 0;
   1099 
   1100 	assert(h);
   1101 
   1102 	/* first we try the FORCE option, which is introduced in kernel
   1103 	 * 2.6.14 to give "root" the ability to override the system wide
   1104 	 * maximum */
   1105 	status = setsockopt(h->fd, SOL_SOCKET, SO_RCVBUFFORCE, &size, socklen);
   1106 	if (status < 0) {
   1107 		/* if this didn't work, we try at least to get the system
   1108 		 * wide maximum (or whatever the user requested) */
   1109 		setsockopt(h->fd, SOL_SOCKET, SO_RCVBUF, &size, socklen);
   1110 	}
   1111 	getsockopt(h->fd, SOL_SOCKET, SO_RCVBUF, &read_size, &socklen);
   1112 
   1113 	return read_size;
   1114 }
   1115 
   1116 /**
   1117  * nfnl_get_msg_first - get the first message of a multipart netlink message
   1118  * @h: nfnetlink handle
   1119  * @buf: data received that we want to process
   1120  * @len: size of the data received
   1121  *
   1122  * This function returns a pointer to the first netlink message contained
   1123  * in the chunk of data received from certain nfnetlink subsystem.
   1124  *
   1125  * On success, a valid address that points to the netlink message is returned.
   1126  * On error, NULL is returned.
   1127  */
   1128 struct nlmsghdr *nfnl_get_msg_first(struct nfnl_handle *h,
   1129 				    const unsigned char *buf,
   1130 				    size_t len)
   1131 {
   1132 	struct nlmsghdr *nlh;
   1133 
   1134 	assert(h);
   1135 	assert(buf);
   1136 	assert(len > 0);
   1137 
   1138 	/* first message in buffer */
   1139 	nlh = (struct nlmsghdr *)buf;
   1140 	if (!NLMSG_OK(nlh, len))
   1141 		return NULL;
   1142 	h->last_nlhdr = nlh;
   1143 
   1144 	return nlh;
   1145 }
   1146 
   1147 struct nlmsghdr *nfnl_get_msg_next(struct nfnl_handle *h,
   1148 				   const unsigned char *buf,
   1149 				   size_t len)
   1150 {
   1151 	struct nlmsghdr *nlh;
   1152 	size_t remain_len;
   1153 
   1154 	assert(h);
   1155 	assert(buf);
   1156 	assert(len > 0);
   1157 
   1158 	/* if last header in handle not inside this buffer,
   1159 	 * drop reference to last header */
   1160 	if (!h->last_nlhdr ||
   1161 	    (unsigned char *)h->last_nlhdr >= (buf + len)  ||
   1162 	    (unsigned char *)h->last_nlhdr < buf) {
   1163 		h->last_nlhdr = NULL;
   1164 		return NULL;
   1165 	}
   1166 
   1167 	/* n-th part of multipart message */
   1168 	if (h->last_nlhdr->nlmsg_type == NLMSG_DONE ||
   1169 	    h->last_nlhdr->nlmsg_flags & NLM_F_MULTI) {
   1170 		/* if last part in multipart message or no
   1171 		 * multipart message at all, return */
   1172 		h->last_nlhdr = NULL;
   1173 		return NULL;
   1174 	}
   1175 
   1176 	remain_len = (len - ((unsigned char *)h->last_nlhdr - buf));
   1177 	nlh = NLMSG_NEXT(h->last_nlhdr, remain_len);
   1178 
   1179 	if (!NLMSG_OK(nlh, remain_len)) {
   1180 		h->last_nlhdr = NULL;
   1181 		return NULL;
   1182 	}
   1183 
   1184 	h->last_nlhdr = nlh;
   1185 
   1186 	return nlh;
   1187 }
   1188 
   1189 /**
   1190  * nfnl_callback_register - register a callback for a certain message type
   1191  * @ssh: nfnetlink subsys handler
   1192  * @type: subsys call
   1193  * @cb: nfnetlink callback to be registered
   1194  *
   1195  * On success, 0 is returned. On error, -1 is returned and errno is set
   1196  * appropiately.
   1197  */
   1198 int nfnl_callback_register(struct nfnl_subsys_handle *ssh,
   1199 			   u_int8_t type, struct nfnl_callback *cb)
   1200 {
   1201 	assert(ssh);
   1202 	assert(cb);
   1203 
   1204 	if (type >= ssh->cb_count) {
   1205 		errno = EINVAL;
   1206 		return -1;
   1207 	}
   1208 
   1209 	memcpy(&ssh->cb[type], cb, sizeof(*cb));
   1210 
   1211 	return 0;
   1212 }
   1213 
   1214 /**
   1215  * nfnl_callback_unregister - unregister a certain callback
   1216  * @ssh: nfnetlink subsys handler
   1217  * @type: subsys call
   1218  *
   1219  * On sucess, 0 is returned. On error, -1 is returned and errno is
   1220  * set appropiately.
   1221  */
   1222 int nfnl_callback_unregister(struct nfnl_subsys_handle *ssh, u_int8_t type)
   1223 {
   1224 	assert(ssh);
   1225 
   1226 	if (type >= ssh->cb_count) {
   1227 		errno = EINVAL;
   1228 		return -1;
   1229 	}
   1230 
   1231 	ssh->cb[type].call = NULL;
   1232 
   1233 	return 0;
   1234 }
   1235 
   1236 int nfnl_check_attributes(const struct nfnl_handle *h,
   1237 			 const struct nlmsghdr *nlh,
   1238 			 struct nfattr *nfa[])
   1239 {
   1240 	assert(h);
   1241 	assert(nlh);
   1242 	assert(nfa);
   1243 
   1244 	int min_len;
   1245 	u_int8_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
   1246 	u_int8_t subsys_id = NFNL_SUBSYS_ID(nlh->nlmsg_type);
   1247 	const struct nfnl_subsys_handle *ssh;
   1248 	struct nfnl_callback *cb;
   1249 
   1250 	if (subsys_id > NFNL_MAX_SUBSYS)
   1251 		return -EINVAL;
   1252 
   1253 	ssh = &h->subsys[subsys_id];
   1254  	cb = &ssh->cb[type];
   1255 
   1256 #if 1
   1257 	/* checks need to be enabled as soon as this is called from
   1258 	 * somebody else than __nfnl_handle_msg */
   1259 	if (type >= ssh->cb_count)
   1260 		return -EINVAL;
   1261 
   1262 	min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
   1263 	if (nlh->nlmsg_len < min_len)
   1264 		return -EINVAL;
   1265 #endif
   1266 	memset(nfa, 0, sizeof(struct nfattr *) * cb->attr_count);
   1267 
   1268 	if (nlh->nlmsg_len > min_len) {
   1269 		struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh));
   1270 		int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
   1271 
   1272 		while (NFA_OK(attr, attrlen)) {
   1273 			unsigned int flavor = NFA_TYPE(attr);
   1274 			if (flavor) {
   1275 				if (flavor > cb->attr_count) {
   1276 					/* we have received an attribute from
   1277 					 * the kernel which we don't understand
   1278 					 * yet. We have to silently ignore this
   1279 					 * for the sake of future compatibility */
   1280 					attr = NFA_NEXT(attr, attrlen);
   1281 					continue;
   1282 				}
   1283 				nfa[flavor - 1] = attr;
   1284 			}
   1285 			attr = NFA_NEXT(attr, attrlen);
   1286 		}
   1287 	}
   1288 
   1289 	return 0;
   1290 }
   1291 
   1292 static int __nfnl_handle_msg(struct nfnl_handle *h, struct nlmsghdr *nlh,
   1293 			     int len)
   1294 {
   1295 	struct nfnl_subsys_handle *ssh;
   1296 	u_int8_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
   1297 	u_int8_t subsys_id = NFNL_SUBSYS_ID(nlh->nlmsg_type);
   1298 	int err = 0;
   1299 
   1300 	if (subsys_id > NFNL_MAX_SUBSYS)
   1301 		return -1;
   1302 
   1303 	ssh = &h->subsys[subsys_id];
   1304 
   1305 	if (nlh->nlmsg_len < NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct nfgenmsg))))
   1306 		return -1;
   1307 
   1308 	if (type >= ssh->cb_count)
   1309 		return -1;
   1310 
   1311 	if (ssh->cb[type].attr_count) {
   1312 		struct nfattr *nfa[ssh->cb[type].attr_count];
   1313 
   1314 		err = nfnl_check_attributes(h, nlh, nfa);
   1315 		if (err < 0)
   1316 			return err;
   1317 		if (ssh->cb[type].call)
   1318 			return ssh->cb[type].call(nlh, nfa, ssh->cb[type].data);
   1319 	}
   1320 	return 0;
   1321 }
   1322 
   1323 int nfnl_handle_packet(struct nfnl_handle *h, char *buf, int len)
   1324 {
   1325 
   1326 	while (len >= NLMSG_SPACE(0)) {
   1327 		u_int32_t rlen;
   1328 		struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
   1329 
   1330 		if (nlh->nlmsg_len < sizeof(struct nlmsghdr)
   1331 		    || len < nlh->nlmsg_len)
   1332 			return -1;
   1333 
   1334 		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
   1335 		if (rlen > len)
   1336 			rlen = len;
   1337 
   1338 		if (__nfnl_handle_msg(h, nlh, rlen) < 0)
   1339 			return -1;
   1340 
   1341 		len -= rlen;
   1342 		buf += rlen;
   1343 	}
   1344 	return 0;
   1345 }
   1346 
   1347 static int nfnl_is_error(struct nfnl_handle *h, struct nlmsghdr *nlh)
   1348 {
   1349 	/* This message is an ACK or a DONE */
   1350 	if (nlh->nlmsg_type == NLMSG_ERROR ||
   1351 	    (nlh->nlmsg_type == NLMSG_DONE &&
   1352 	     nlh->nlmsg_flags & NLM_F_MULTI)) {
   1353 		if (nlh->nlmsg_len < NLMSG_ALIGN(sizeof(struct nlmsgerr))) {
   1354 			errno = EBADMSG;
   1355 			return 1;
   1356 		}
   1357 		errno = -(*((int *)NLMSG_DATA(nlh)));
   1358 		return 1;
   1359 	}
   1360 	return 0;
   1361 }
   1362 
   1363 /* On error, -1 is returned and errno is set appropiately. On success,
   1364  * 0 is returned if there is no more data to process, >0 if there is
   1365  * more data to process */
   1366 static int nfnl_step(struct nfnl_handle *h, struct nlmsghdr *nlh)
   1367 {
   1368 	struct nfnl_subsys_handle *ssh;
   1369 	u_int8_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
   1370 	u_int8_t subsys_id = NFNL_SUBSYS_ID(nlh->nlmsg_type);
   1371 
   1372 	/* Is this an error message? */
   1373 	if (nfnl_is_error(h, nlh)) {
   1374 		/* This is an ACK */
   1375 		if (errno == 0)
   1376 			return 0;
   1377 		/* This an error message */
   1378 		return -1;
   1379 	}
   1380 
   1381 	/* nfnetlink sanity checks: check for nfgenmsg size */
   1382 	if (nlh->nlmsg_len < NLMSG_SPACE(sizeof(struct nfgenmsg))) {
   1383 		errno = ENOSPC;
   1384 		return -1;
   1385 	}
   1386 
   1387 	if (subsys_id > NFNL_MAX_SUBSYS) {
   1388 		errno = ENOENT;
   1389 		return -1;
   1390 	}
   1391 
   1392 	ssh = &h->subsys[subsys_id];
   1393 	if (!ssh) {
   1394 		errno = ENOENT;
   1395 		return -1;
   1396 	}
   1397 
   1398 	if (type >= ssh->cb_count) {
   1399 		errno = ENOENT;
   1400 		return -1;
   1401 	}
   1402 
   1403 	if (ssh->cb[type].attr_count) {
   1404 		int err;
   1405 		struct nfattr *tb[ssh->cb[type].attr_count];
   1406 		struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh));
   1407 		int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
   1408 		int len = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
   1409 
   1410 		err = nfnl_parse_attr(tb, ssh->cb[type].attr_count, attr, len);
   1411 		if (err == -1)
   1412 			return -1;
   1413 
   1414 		if (ssh->cb[type].call) {
   1415 			/*
   1416 			 * On error, the callback returns NFNL_CB_FAILURE and
   1417 			 * errno must be explicitely set. On success,
   1418 			 * NFNL_CB_STOP is returned and we're done, otherwise
   1419 			 * NFNL_CB_CONTINUE means that we want to continue
   1420 			 * data processing.
   1421 			 */
   1422 			return ssh->cb[type].call(nlh,
   1423 						  tb,
   1424 						  ssh->cb[type].data);
   1425 		}
   1426 	}
   1427 	/* no callback set, continue data processing */
   1428 	return 1;
   1429 }
   1430 
   1431 /**
   1432  * nfnl_process - process data coming from a nfnetlink system
   1433  * @h: nfnetlink handler
   1434  * @buf: buffer that contains the netlink message
   1435  * @len: size of the data contained in the buffer (not the buffer size)
   1436  *
   1437  * This function processes all the nfnetlink messages contained inside a
   1438  * buffer. It performs the appropiate sanity checks and passes the message
   1439  * to a certain handler that is registered via register_callback().
   1440  *
   1441  * On success, NFNL_CB_STOP is returned if the data processing has finished.
   1442  * If a value NFNL_CB_CONTINUE is returned, then there is more data to
   1443  * process. On error, NFNL_CB_CONTINUE is returned and errno is set to the
   1444  * appropiate value.
   1445  *
   1446  * In case that the callback returns NFNL_CB_FAILURE, errno may be set by
   1447  * the library client. If your callback decides not to process data anymore
   1448  * for any reason, then it must return NFNL_CB_STOP. Otherwise, if the
   1449  * callback continues the processing NFNL_CB_CONTINUE is returned.
   1450  */
   1451 int nfnl_process(struct nfnl_handle *h, const unsigned char *buf, size_t len)
   1452 {
   1453 	int ret = 0;
   1454 	struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
   1455 
   1456 	assert(h);
   1457 	assert(buf);
   1458 	assert(len > 0);
   1459 
   1460 	/* check for out of sequence message */
   1461 	if (nlh->nlmsg_seq && nlh->nlmsg_seq != h->seq) {
   1462 		errno = EILSEQ;
   1463 		return -1;
   1464 	}
   1465 	while (len >= NLMSG_SPACE(0) && NLMSG_OK(nlh, len)) {
   1466 
   1467 		ret = nfnl_step(h, nlh);
   1468 		if (ret <= NFNL_CB_STOP)
   1469 			break;
   1470 
   1471 		nlh = NLMSG_NEXT(nlh, len);
   1472 	}
   1473 	return ret;
   1474 }
   1475 
   1476 /*
   1477  * New parsing functions based on iterators
   1478  */
   1479 
   1480 struct nfnl_iterator {
   1481 	struct nlmsghdr *nlh;
   1482 	unsigned int	len;
   1483 };
   1484 
   1485 /**
   1486  * nfnl_iterator_create: create an nfnetlink iterator
   1487  * @h: nfnetlink handler
   1488  * @buf: buffer that contains data received from a nfnetlink system
   1489  * @len: size of the data contained in the buffer (not the buffer size)
   1490  *
   1491  * This function creates an iterator that can be used to parse nfnetlink
   1492  * message one by one. The iterator gives more control to the programmer
   1493  * in the messages processing.
   1494  *
   1495  * On success, a valid address is returned. On error, NULL is returned
   1496  * and errno is set to the appropiate value.
   1497  */
   1498 struct nfnl_iterator *
   1499 nfnl_iterator_create(const struct nfnl_handle *h,
   1500 		     const char *buf,
   1501 		     size_t len)
   1502 {
   1503 	struct nlmsghdr *nlh;
   1504 	struct nfnl_iterator *it;
   1505 
   1506 	assert(h);
   1507 	assert(buf);
   1508 	assert(len > 0);
   1509 
   1510 	it = malloc(sizeof(struct nfnl_iterator));
   1511 	if (!it) {
   1512 		errno = ENOMEM;
   1513 		return NULL;
   1514 	}
   1515 
   1516 	/* first message in buffer */
   1517 	nlh = (struct nlmsghdr *)buf;
   1518 	if (len < NLMSG_SPACE(0) || !NLMSG_OK(nlh, len)) {
   1519 		free(it);
   1520 		errno = EBADMSG;
   1521 		return NULL;
   1522 	}
   1523 	it->nlh = nlh;
   1524 	it->len = len;
   1525 
   1526 	return it;
   1527 }
   1528 
   1529 /**
   1530  * nfnl_iterator_destroy - destroy a nfnetlink iterator
   1531  * @it: nfnetlink iterator
   1532  *
   1533  * This function destroys a certain iterator. Nothing is returned.
   1534  */
   1535 void nfnl_iterator_destroy(struct nfnl_iterator *it)
   1536 {
   1537 	assert(it);
   1538 	free(it);
   1539 }
   1540 
   1541 /**
   1542  * nfnl_iterator_process - process a nfnetlink message
   1543  * @h: nfnetlink handler
   1544  * @it: nfnetlink iterator that contains the current message to be proccesed
   1545  *
   1546  * This function process just the current message selected by the iterator.
   1547  * On success, a value greater or equal to zero is returned. On error,
   1548  * -1 is returned and errno is appropiately set.
   1549  */
   1550 int nfnl_iterator_process(struct nfnl_handle *h, struct nfnl_iterator *it)
   1551 {
   1552 	assert(h);
   1553 	assert(it->nlh);
   1554 
   1555         /* check for out of sequence message */
   1556 	if (it->nlh->nlmsg_seq && it->nlh->nlmsg_seq != h->seq) {
   1557 		errno = EILSEQ;
   1558 		return -1;
   1559 	}
   1560 	if (it->len < NLMSG_SPACE(0) || !NLMSG_OK(it->nlh, it->len)) {
   1561 		errno = EBADMSG;
   1562 		return -1;
   1563 	}
   1564 	return nfnl_step(h, it->nlh);
   1565 }
   1566 
   1567 /**
   1568  * nfnl_iterator_next - get the next message hold by the iterator
   1569  * @h: nfnetlink handler
   1570  * @it: nfnetlink iterator that contains the current message processed
   1571  *
   1572  * This function update the current message to be processed pointer.
   1573  * It returns NFNL_CB_CONTINUE if there is still more messages to be
   1574  * processed, otherwise NFNL_CB_STOP is returned.
   1575  */
   1576 int nfnl_iterator_next(const struct nfnl_handle *h, struct nfnl_iterator *it)
   1577 {
   1578 	assert(h);
   1579 	assert(it);
   1580 
   1581 	it->nlh = NLMSG_NEXT(it->nlh, it->len);
   1582 	if (!it->nlh)
   1583 		return 0;
   1584 	return 1;
   1585 }
   1586 
   1587 /**
   1588  * nfnl_catch - get responses from the nfnetlink system and process them
   1589  * @h: nfnetlink handler
   1590 *
   1591  * This function handles the data received from the nfnetlink system.
   1592  * For example, events generated by one of the subsystems. The message
   1593  * is passed to the callback registered via callback_register(). Note that
   1594  * this a replacement of nfnl_listen and its use is recommended.
   1595  *
   1596  * On success, 0 is returned. On error, a -1 is returned. If you do not
   1597  * want to listen to events anymore, then your callback must return
   1598  * NFNL_CB_STOP.
   1599  *
   1600  * Note that ENOBUFS is returned in case that nfnetlink is exhausted. In
   1601  * that case is possible that the information requested is incomplete.
   1602  */
   1603 int nfnl_catch(struct nfnl_handle *h)
   1604 {
   1605 	int ret;
   1606 
   1607 	assert(h);
   1608 
   1609 	while (1) {
   1610 		unsigned char buf[h->rcv_buffer_size]
   1611 			__attribute__ ((aligned));
   1612 
   1613 		ret = nfnl_recv(h, buf, sizeof(buf));
   1614 		if (ret == -1) {
   1615 			/* interrupted syscall must retry */
   1616 			if (errno == EINTR)
   1617 				continue;
   1618 			break;
   1619 		}
   1620 
   1621 		ret = nfnl_process(h, buf, ret);
   1622 		if (ret <= NFNL_CB_STOP)
   1623 			break;
   1624 	}
   1625 
   1626 	return ret;
   1627 }
   1628 
   1629 /**
   1630  * nfnl_query - request/response communication challenge
   1631  * @h: nfnetlink handler
   1632  * @nlh: nfnetlink message to be sent
   1633  *
   1634  * This function sends a nfnetlink message to a certain subsystem and
   1635  * receives the response messages associated, such messages are passed to
   1636  * the callback registered via register_callback(). Note that this function
   1637  * is a replacement for nfnl_talk, its use is recommended.
   1638  *
   1639  * On success, 0 is returned. On error, a negative is returned. If your
   1640  * does not want to listen to events anymore, then your callback must
   1641  * return NFNL_CB_STOP.
   1642  *
   1643  * Note that ENOBUFS is returned in case that nfnetlink is exhausted. In
   1644  * that case is possible that the information requested is incomplete.
   1645  */
   1646 int nfnl_query(struct nfnl_handle *h, struct nlmsghdr *nlh)
   1647 {
   1648 	assert(h);
   1649 	assert(nlh);
   1650 
   1651 	if (nfnl_send(h, nlh) == -1)
   1652 		return -1;
   1653 
   1654 	return nfnl_catch(h);
   1655 }
   1656