1/*
2 * netfilter module for userspace bridged Ethernet frames logging daemons
3 *
4 *	Authors:
5 *	Bart De Schuymer <bdschuym@pandora.be>
6 *	Harald Welte <laforge@netfilter.org>
7 *
8 *  November, 2004
9 *
10 * Based on ipt_ULOG.c, which is
11 * (C) 2000-2002 by Harald Welte <laforge@netfilter.org>
12 *
13 * This module accepts two parameters:
14 *
15 * nlbufsiz:
16 *   The parameter specifies how big the buffer for each netlink multicast
17 * group is. e.g. If you say nlbufsiz=8192, up to eight kb of packets will
18 * get accumulated in the kernel until they are sent to userspace. It is
19 * NOT possible to allocate more than 128kB, and it is strongly discouraged,
20 * because atomically allocating 128kB inside the network rx softirq is not
21 * reliable. Please also keep in mind that this buffer size is allocated for
22 * each nlgroup you are using, so the total kernel memory usage increases
23 * by that factor.
24 *
25 * flushtimeout:
26 *   Specify, after how many hundredths of a second the queue should be
27 *   flushed even if it is not full yet.
28 *
29 */
30
31#include <linux/module.h>
32#include <linux/spinlock.h>
33#include <linux/socket.h>
34#include <linux/skbuff.h>
35#include <linux/kernel.h>
36#include <linux/timer.h>
37#include <linux/netlink.h>
38#include <linux/netdevice.h>
39#include <linux/module.h>
40#include <linux/netfilter_bridge/ebtables.h>
41#include <linux/netfilter_bridge/ebt_ulog.h>
42#include <net/sock.h>
43#include "../br_private.h"
44
45#define PRINTR(format, args...) do { if (net_ratelimit()) \
46				printk(format , ## args); } while (0)
47
48static unsigned int nlbufsiz = NLMSG_GOODSIZE;
49module_param(nlbufsiz, uint, 0600);
50MODULE_PARM_DESC(nlbufsiz, "netlink buffer size (number of bytes) "
51			   "(defaults to 4096)");
52
53static unsigned int flushtimeout = 10;
54module_param(flushtimeout, uint, 0600);
55MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths ofa second) "
56			       "(defaults to 10)");
57
58typedef struct {
59	unsigned int qlen;		/* number of nlmsgs' in the skb */
60	struct nlmsghdr *lastnlh;	/* netlink header of last msg in skb */
61	struct sk_buff *skb;		/* the pre-allocated skb */
62	struct timer_list timer;	/* the timer function */
63	spinlock_t lock;		/* the per-queue lock */
64} ebt_ulog_buff_t;
65
66static ebt_ulog_buff_t ulog_buffers[EBT_ULOG_MAXNLGROUPS];
67static struct sock *ebtulognl;
68
69/* send one ulog_buff_t to userspace */
70static void ulog_send(unsigned int nlgroup)
71{
72	ebt_ulog_buff_t *ub = &ulog_buffers[nlgroup];
73
74	if (timer_pending(&ub->timer))
75		del_timer(&ub->timer);
76
77	if (!ub->skb)
78		return;
79
80	/* last nlmsg needs NLMSG_DONE */
81	if (ub->qlen > 1)
82		ub->lastnlh->nlmsg_type = NLMSG_DONE;
83
84	NETLINK_CB(ub->skb).dst_group = nlgroup + 1;
85	netlink_broadcast(ebtulognl, ub->skb, 0, nlgroup + 1, GFP_ATOMIC);
86
87	ub->qlen = 0;
88	ub->skb = NULL;
89}
90
91/* timer function to flush queue in flushtimeout time */
92static void ulog_timer(unsigned long data)
93{
94	spin_lock_bh(&ulog_buffers[data].lock);
95	if (ulog_buffers[data].skb)
96		ulog_send(data);
97	spin_unlock_bh(&ulog_buffers[data].lock);
98}
99
100static struct sk_buff *ulog_alloc_skb(unsigned int size)
101{
102	struct sk_buff *skb;
103	unsigned int n;
104
105	n = max(size, nlbufsiz);
106	skb = alloc_skb(n, GFP_ATOMIC);
107	if (!skb) {
108		PRINTR(KERN_ERR "ebt_ulog: can't alloc whole buffer "
109		       "of size %ub!\n", n);
110		if (n > size) {
111			/* try to allocate only as much as we need for
112			 * current packet */
113			skb = alloc_skb(size, GFP_ATOMIC);
114			if (!skb)
115				PRINTR(KERN_ERR "ebt_ulog: can't even allocate "
116				       "buffer of size %ub\n", size);
117		}
118	}
119
120	return skb;
121}
122
123static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
124   const struct net_device *in, const struct net_device *out,
125   const struct ebt_ulog_info *uloginfo, const char *prefix)
126{
127	ebt_ulog_packet_msg_t *pm;
128	size_t size, copy_len;
129	struct nlmsghdr *nlh;
130	unsigned int group = uloginfo->nlgroup;
131	ebt_ulog_buff_t *ub = &ulog_buffers[group];
132	spinlock_t *lock = &ub->lock;
133	ktime_t kt;
134
135	if ((uloginfo->cprange == 0) ||
136	    (uloginfo->cprange > skb->len + ETH_HLEN))
137		copy_len = skb->len + ETH_HLEN;
138	else
139		copy_len = uloginfo->cprange;
140
141	size = NLMSG_SPACE(sizeof(*pm) + copy_len);
142	if (size > nlbufsiz) {
143		PRINTR("ebt_ulog: Size %Zd needed, but nlbufsiz=%d\n",
144		       size, nlbufsiz);
145		return;
146	}
147
148	spin_lock_bh(lock);
149
150	if (!ub->skb) {
151		if (!(ub->skb = ulog_alloc_skb(size)))
152			goto alloc_failure;
153	} else if (size > skb_tailroom(ub->skb)) {
154		ulog_send(group);
155
156		if (!(ub->skb = ulog_alloc_skb(size)))
157			goto alloc_failure;
158	}
159
160	nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, 0,
161			size - NLMSG_ALIGN(sizeof(*nlh)));
162	ub->qlen++;
163
164	pm = NLMSG_DATA(nlh);
165
166	/* Fill in the ulog data */
167	pm->version = EBT_ULOG_VERSION;
168	kt = ktime_get_real();
169	pm->stamp = ktime_to_timeval(kt);
170	if (ub->qlen == 1)
171		ub->skb->tstamp = kt;
172	pm->data_len = copy_len;
173	pm->mark = skb->mark;
174	pm->hook = hooknr;
175	if (uloginfo->prefix != NULL)
176		strcpy(pm->prefix, uloginfo->prefix);
177	else
178		*(pm->prefix) = '\0';
179
180	if (in) {
181		strcpy(pm->physindev, in->name);
182		/* If in isn't a bridge, then physindev==indev */
183		if (in->br_port)
184			strcpy(pm->indev, in->br_port->br->dev->name);
185		else
186			strcpy(pm->indev, in->name);
187	} else
188		pm->indev[0] = pm->physindev[0] = '\0';
189
190	if (out) {
191		/* If out exists, then out is a bridge port */
192		strcpy(pm->physoutdev, out->name);
193		strcpy(pm->outdev, out->br_port->br->dev->name);
194	} else
195		pm->outdev[0] = pm->physoutdev[0] = '\0';
196
197	if (skb_copy_bits(skb, -ETH_HLEN, pm->data, copy_len) < 0)
198		BUG();
199
200	if (ub->qlen > 1)
201		ub->lastnlh->nlmsg_flags |= NLM_F_MULTI;
202
203	ub->lastnlh = nlh;
204
205	if (ub->qlen >= uloginfo->qthreshold)
206		ulog_send(group);
207	else if (!timer_pending(&ub->timer)) {
208		ub->timer.expires = jiffies + flushtimeout * HZ / 100;
209		add_timer(&ub->timer);
210	}
211
212unlock:
213	spin_unlock_bh(lock);
214
215	return;
216
217nlmsg_failure:
218	printk(KERN_CRIT "ebt_ulog: error during NLMSG_PUT. This should "
219	       "not happen, please report to author.\n");
220	goto unlock;
221alloc_failure:
222	goto unlock;
223}
224
225/* this function is registered with the netfilter core */
226static void ebt_log_packet(unsigned int pf, unsigned int hooknum,
227   const struct sk_buff *skb, const struct net_device *in,
228   const struct net_device *out, const struct nf_loginfo *li,
229   const char *prefix)
230{
231	struct ebt_ulog_info loginfo;
232
233	if (!li || li->type != NF_LOG_TYPE_ULOG) {
234		loginfo.nlgroup = EBT_ULOG_DEFAULT_NLGROUP;
235		loginfo.cprange = 0;
236		loginfo.qthreshold = EBT_ULOG_DEFAULT_QTHRESHOLD;
237		loginfo.prefix[0] = '\0';
238	} else {
239		loginfo.nlgroup = li->u.ulog.group;
240		loginfo.cprange = li->u.ulog.copy_len;
241		loginfo.qthreshold = li->u.ulog.qthreshold;
242		strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix));
243	}
244
245	ebt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
246}
247
248static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr,
249   const struct net_device *in, const struct net_device *out,
250   const void *data, unsigned int datalen)
251{
252	struct ebt_ulog_info *uloginfo = (struct ebt_ulog_info *)data;
253
254	ebt_ulog_packet(hooknr, skb, in, out, uloginfo, NULL);
255}
256
257
258static int ebt_ulog_check(const char *tablename, unsigned int hookmask,
259   const struct ebt_entry *e, void *data, unsigned int datalen)
260{
261	struct ebt_ulog_info *uloginfo = (struct ebt_ulog_info *)data;
262
263	if (datalen != EBT_ALIGN(sizeof(struct ebt_ulog_info)) ||
264	    uloginfo->nlgroup > 31)
265		return -EINVAL;
266
267	uloginfo->prefix[EBT_ULOG_PREFIX_LEN - 1] = '\0';
268
269	if (uloginfo->qthreshold > EBT_ULOG_MAX_QLEN)
270		uloginfo->qthreshold = EBT_ULOG_MAX_QLEN;
271
272	return 0;
273}
274
275static struct ebt_watcher ulog = {
276	.name		= EBT_ULOG_WATCHER,
277	.watcher	= ebt_ulog,
278	.check		= ebt_ulog_check,
279	.me		= THIS_MODULE,
280};
281
282static struct nf_logger ebt_ulog_logger = {
283	.name		= EBT_ULOG_WATCHER,
284	.logfn		= &ebt_log_packet,
285	.me		= THIS_MODULE,
286};
287
288static int __init ebt_ulog_init(void)
289{
290	int i, ret = 0;
291
292	if (nlbufsiz >= 128*1024) {
293		printk(KERN_NOTICE "ebt_ulog: Netlink buffer has to be <= 128kB,"
294		       " please try a smaller nlbufsiz parameter.\n");
295		return -EINVAL;
296	}
297
298	/* initialize ulog_buffers */
299	for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) {
300		setup_timer(&ulog_buffers[i].timer, ulog_timer, i);
301		spin_lock_init(&ulog_buffers[i].lock);
302	}
303
304	ebtulognl = netlink_kernel_create(NETLINK_NFLOG, EBT_ULOG_MAXNLGROUPS,
305					  NULL, NULL, THIS_MODULE);
306	if (!ebtulognl)
307		ret = -ENOMEM;
308	else if ((ret = ebt_register_watcher(&ulog)))
309		sock_release(ebtulognl->sk_socket);
310
311	if (nf_log_register(PF_BRIDGE, &ebt_ulog_logger) < 0) {
312		printk(KERN_WARNING "ebt_ulog: not logging via ulog "
313		       "since somebody else already registered for PF_BRIDGE\n");
314		/* we cannot make module load fail here, since otherwise
315		 * ebtables userspace would abort */
316	}
317
318	return ret;
319}
320
321static void __exit ebt_ulog_fini(void)
322{
323	ebt_ulog_buff_t *ub;
324	int i;
325
326	nf_log_unregister(&ebt_ulog_logger);
327	ebt_unregister_watcher(&ulog);
328	for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) {
329		ub = &ulog_buffers[i];
330		if (timer_pending(&ub->timer))
331			del_timer(&ub->timer);
332		spin_lock_bh(&ub->lock);
333		if (ub->skb) {
334			kfree_skb(ub->skb);
335			ub->skb = NULL;
336		}
337		spin_unlock_bh(&ub->lock);
338	}
339	sock_release(ebtulognl->sk_socket);
340}
341
342module_init(ebt_ulog_init);
343module_exit(ebt_ulog_fini);
344MODULE_LICENSE("GPL");
345MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
346MODULE_DESCRIPTION("ebtables userspace logging module for bridged Ethernet"
347		   " frames");
348