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