]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - net/ipv4/netfilter/ipt_ULOG.c
[NETFILTER]: Remove changelogs and CVS IDs
[linux-2.6.git] / net / ipv4 / netfilter / ipt_ULOG.c
1 /*
2  * netfilter module for userspace packet logging daemons
3  *
4  * (C) 2000-2004 by Harald Welte <laforge@netfilter.org>
5  * (C) 1999-2001 Paul `Rusty' Russell
6  * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  * This module accepts two parameters:
13  *
14  * nlbufsiz:
15  *   The parameter specifies how big the buffer for each netlink multicast
16  * group is. e.g. If you say nlbufsiz=8192, up to eight kb of packets will
17  * get accumulated in the kernel until they are sent to userspace. It is
18  * NOT possible to allocate more than 128kB, and it is strongly discouraged,
19  * because atomically allocating 128kB inside the network rx softirq is not
20  * reliable. Please also keep in mind that this buffer size is allocated for
21  * each nlgroup you are using, so the total kernel memory usage increases
22  * by that factor.
23  *
24  * Actually you should use nlbufsiz a bit smaller than PAGE_SIZE, since
25  * nlbufsiz is used with alloc_skb, which adds another
26  * sizeof(struct skb_shared_info).  Use NLMSG_GOODSIZE instead.
27  *
28  * flushtimeout:
29  *   Specify, after how many hundredths of a second the queue should be
30  *   flushed even if it is not full yet.
31  */
32
33 #include <linux/module.h>
34 #include <linux/spinlock.h>
35 #include <linux/socket.h>
36 #include <linux/skbuff.h>
37 #include <linux/kernel.h>
38 #include <linux/timer.h>
39 #include <linux/netlink.h>
40 #include <linux/netdevice.h>
41 #include <linux/mm.h>
42 #include <linux/moduleparam.h>
43 #include <linux/netfilter.h>
44 #include <linux/netfilter/x_tables.h>
45 #include <linux/netfilter_ipv4/ipt_ULOG.h>
46 #include <net/sock.h>
47 #include <linux/bitops.h>
48 #include <asm/unaligned.h>
49
50 MODULE_LICENSE("GPL");
51 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
52 MODULE_DESCRIPTION("iptables userspace logging module");
53 MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NFLOG);
54
55 #define ULOG_NL_EVENT           111             /* Harald's favorite number */
56 #define ULOG_MAXNLGROUPS        32              /* numer of nlgroups */
57
58 #if 0
59 #define DEBUGP(format, args...) printk("%s:%s:" format, \
60                                        __FILE__, __FUNCTION__ , ## args)
61 #else
62 #define DEBUGP(format, args...)
63 #endif
64
65 #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0)
66
67 static unsigned int nlbufsiz = NLMSG_GOODSIZE;
68 module_param(nlbufsiz, uint, 0400);
69 MODULE_PARM_DESC(nlbufsiz, "netlink buffer size");
70
71 static unsigned int flushtimeout = 10;
72 module_param(flushtimeout, uint, 0600);
73 MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths of a second)");
74
75 static int nflog = 1;
76 module_param(nflog, bool, 0400);
77 MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
78
79 /* global data structures */
80
81 typedef struct {
82         unsigned int qlen;              /* number of nlmsgs' in the skb */
83         struct nlmsghdr *lastnlh;       /* netlink header of last msg in skb */
84         struct sk_buff *skb;            /* the pre-allocated skb */
85         struct timer_list timer;        /* the timer function */
86 } ulog_buff_t;
87
88 static ulog_buff_t ulog_buffers[ULOG_MAXNLGROUPS];      /* array of buffers */
89
90 static struct sock *nflognl;            /* our socket */
91 static DEFINE_SPINLOCK(ulog_lock);      /* spinlock */
92
93 /* send one ulog_buff_t to userspace */
94 static void ulog_send(unsigned int nlgroupnum)
95 {
96         ulog_buff_t *ub = &ulog_buffers[nlgroupnum];
97
98         if (timer_pending(&ub->timer)) {
99                 DEBUGP("ipt_ULOG: ulog_send: timer was pending, deleting\n");
100                 del_timer(&ub->timer);
101         }
102
103         if (!ub->skb) {
104                 DEBUGP("ipt_ULOG: ulog_send: nothing to send\n");
105                 return;
106         }
107
108         /* last nlmsg needs NLMSG_DONE */
109         if (ub->qlen > 1)
110                 ub->lastnlh->nlmsg_type = NLMSG_DONE;
111
112         NETLINK_CB(ub->skb).dst_group = nlgroupnum + 1;
113         DEBUGP("ipt_ULOG: throwing %d packets to netlink group %u\n",
114                 ub->qlen, nlgroupnum + 1);
115         netlink_broadcast(nflognl, ub->skb, 0, nlgroupnum + 1, GFP_ATOMIC);
116
117         ub->qlen = 0;
118         ub->skb = NULL;
119         ub->lastnlh = NULL;
120 }
121
122
123 /* timer function to flush queue in flushtimeout time */
124 static void ulog_timer(unsigned long data)
125 {
126         DEBUGP("ipt_ULOG: timer function called, calling ulog_send\n");
127
128         /* lock to protect against somebody modifying our structure
129          * from ipt_ulog_target at the same time */
130         spin_lock_bh(&ulog_lock);
131         ulog_send(data);
132         spin_unlock_bh(&ulog_lock);
133 }
134
135 static struct sk_buff *ulog_alloc_skb(unsigned int size)
136 {
137         struct sk_buff *skb;
138         unsigned int n;
139
140         /* alloc skb which should be big enough for a whole
141          * multipart message. WARNING: has to be <= 131000
142          * due to slab allocator restrictions */
143
144         n = max(size, nlbufsiz);
145         skb = alloc_skb(n, GFP_ATOMIC);
146         if (!skb) {
147                 PRINTR("ipt_ULOG: can't alloc whole buffer %ub!\n", n);
148
149                 if (n > size) {
150                         /* try to allocate only as much as we need for
151                          * current packet */
152
153                         skb = alloc_skb(size, GFP_ATOMIC);
154                         if (!skb)
155                                 PRINTR("ipt_ULOG: can't even allocate %ub\n",
156                                        size);
157                 }
158         }
159
160         return skb;
161 }
162
163 static void ipt_ulog_packet(unsigned int hooknum,
164                             const struct sk_buff *skb,
165                             const struct net_device *in,
166                             const struct net_device *out,
167                             const struct ipt_ulog_info *loginfo,
168                             const char *prefix)
169 {
170         ulog_buff_t *ub;
171         ulog_packet_msg_t *pm;
172         size_t size, copy_len;
173         struct nlmsghdr *nlh;
174         struct timeval tv;
175
176         /* ffs == find first bit set, necessary because userspace
177          * is already shifting groupnumber, but we need unshifted.
178          * ffs() returns [1..32], we need [0..31] */
179         unsigned int groupnum = ffs(loginfo->nl_group) - 1;
180
181         /* calculate the size of the skb needed */
182         if ((loginfo->copy_range == 0) ||
183             (loginfo->copy_range > skb->len)) {
184                 copy_len = skb->len;
185         } else {
186                 copy_len = loginfo->copy_range;
187         }
188
189         size = NLMSG_SPACE(sizeof(*pm) + copy_len);
190
191         ub = &ulog_buffers[groupnum];
192
193         spin_lock_bh(&ulog_lock);
194
195         if (!ub->skb) {
196                 if (!(ub->skb = ulog_alloc_skb(size)))
197                         goto alloc_failure;
198         } else if (ub->qlen >= loginfo->qthreshold ||
199                    size > skb_tailroom(ub->skb)) {
200                 /* either the queue len is too high or we don't have
201                  * enough room in nlskb left. send it to userspace. */
202
203                 ulog_send(groupnum);
204
205                 if (!(ub->skb = ulog_alloc_skb(size)))
206                         goto alloc_failure;
207         }
208
209         DEBUGP("ipt_ULOG: qlen %d, qthreshold %d\n", ub->qlen,
210                 loginfo->qthreshold);
211
212         /* NLMSG_PUT contains a hidden goto nlmsg_failure !!! */
213         nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, ULOG_NL_EVENT,
214                         sizeof(*pm)+copy_len);
215         ub->qlen++;
216
217         pm = NLMSG_DATA(nlh);
218
219         /* We might not have a timestamp, get one */
220         if (skb->tstamp.tv64 == 0)
221                 __net_timestamp((struct sk_buff *)skb);
222
223         /* copy hook, prefix, timestamp, payload, etc. */
224         pm->data_len = copy_len;
225         tv = ktime_to_timeval(skb->tstamp);
226         put_unaligned(tv.tv_sec, &pm->timestamp_sec);
227         put_unaligned(tv.tv_usec, &pm->timestamp_usec);
228         put_unaligned(skb->mark, &pm->mark);
229         pm->hook = hooknum;
230         if (prefix != NULL)
231                 strncpy(pm->prefix, prefix, sizeof(pm->prefix));
232         else if (loginfo->prefix[0] != '\0')
233                 strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix));
234         else
235                 *(pm->prefix) = '\0';
236
237         if (in && in->hard_header_len > 0
238             && skb->mac_header != skb->network_header
239             && in->hard_header_len <= ULOG_MAC_LEN) {
240                 memcpy(pm->mac, skb_mac_header(skb), in->hard_header_len);
241                 pm->mac_len = in->hard_header_len;
242         } else
243                 pm->mac_len = 0;
244
245         if (in)
246                 strncpy(pm->indev_name, in->name, sizeof(pm->indev_name));
247         else
248                 pm->indev_name[0] = '\0';
249
250         if (out)
251                 strncpy(pm->outdev_name, out->name, sizeof(pm->outdev_name));
252         else
253                 pm->outdev_name[0] = '\0';
254
255         /* copy_len <= skb->len, so can't fail. */
256         if (skb_copy_bits(skb, 0, pm->payload, copy_len) < 0)
257                 BUG();
258
259         /* check if we are building multi-part messages */
260         if (ub->qlen > 1) {
261                 ub->lastnlh->nlmsg_flags |= NLM_F_MULTI;
262         }
263
264         ub->lastnlh = nlh;
265
266         /* if timer isn't already running, start it */
267         if (!timer_pending(&ub->timer)) {
268                 ub->timer.expires = jiffies + flushtimeout * HZ / 100;
269                 add_timer(&ub->timer);
270         }
271
272         /* if threshold is reached, send message to userspace */
273         if (ub->qlen >= loginfo->qthreshold) {
274                 if (loginfo->qthreshold > 1)
275                         nlh->nlmsg_type = NLMSG_DONE;
276                 ulog_send(groupnum);
277         }
278
279         spin_unlock_bh(&ulog_lock);
280
281         return;
282
283 nlmsg_failure:
284         PRINTR("ipt_ULOG: error during NLMSG_PUT\n");
285
286 alloc_failure:
287         PRINTR("ipt_ULOG: Error building netlink message\n");
288
289         spin_unlock_bh(&ulog_lock);
290 }
291
292 static unsigned int ipt_ulog_target(struct sk_buff **pskb,
293                                     const struct net_device *in,
294                                     const struct net_device *out,
295                                     unsigned int hooknum,
296                                     const struct xt_target *target,
297                                     const void *targinfo)
298 {
299         struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
300
301         ipt_ulog_packet(hooknum, *pskb, in, out, loginfo, NULL);
302
303         return XT_CONTINUE;
304 }
305
306 static void ipt_logfn(unsigned int pf,
307                       unsigned int hooknum,
308                       const struct sk_buff *skb,
309                       const struct net_device *in,
310                       const struct net_device *out,
311                       const struct nf_loginfo *li,
312                       const char *prefix)
313 {
314         struct ipt_ulog_info loginfo;
315
316         if (!li || li->type != NF_LOG_TYPE_ULOG) {
317                 loginfo.nl_group = ULOG_DEFAULT_NLGROUP;
318                 loginfo.copy_range = 0;
319                 loginfo.qthreshold = ULOG_DEFAULT_QTHRESHOLD;
320                 loginfo.prefix[0] = '\0';
321         } else {
322                 loginfo.nl_group = li->u.ulog.group;
323                 loginfo.copy_range = li->u.ulog.copy_len;
324                 loginfo.qthreshold = li->u.ulog.qthreshold;
325                 strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix));
326         }
327
328         ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
329 }
330
331 static int ipt_ulog_checkentry(const char *tablename,
332                                const void *e,
333                                const struct xt_target *target,
334                                void *targinfo,
335                                unsigned int hookmask)
336 {
337         struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
338
339         if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') {
340                 DEBUGP("ipt_ULOG: prefix term %i\n",
341                        loginfo->prefix[sizeof(loginfo->prefix) - 1]);
342                 return 0;
343         }
344         if (loginfo->qthreshold > ULOG_MAX_QLEN) {
345                 DEBUGP("ipt_ULOG: queue threshold %i > MAX_QLEN\n",
346                         loginfo->qthreshold);
347                 return 0;
348         }
349         return 1;
350 }
351
352 static struct xt_target ipt_ulog_reg = {
353         .name           = "ULOG",
354         .family         = AF_INET,
355         .target         = ipt_ulog_target,
356         .targetsize     = sizeof(struct ipt_ulog_info),
357         .checkentry     = ipt_ulog_checkentry,
358         .me             = THIS_MODULE,
359 };
360
361 static struct nf_logger ipt_ulog_logger = {
362         .name           = "ipt_ULOG",
363         .logfn          = ipt_logfn,
364         .me             = THIS_MODULE,
365 };
366
367 static int __init ipt_ulog_init(void)
368 {
369         int ret, i;
370
371         DEBUGP("ipt_ULOG: init module\n");
372
373         if (nlbufsiz > 128*1024) {
374                 printk("Netlink buffer has to be <= 128kB\n");
375                 return -EINVAL;
376         }
377
378         /* initialize ulog_buffers */
379         for (i = 0; i < ULOG_MAXNLGROUPS; i++) {
380                 init_timer(&ulog_buffers[i].timer);
381                 ulog_buffers[i].timer.function = ulog_timer;
382                 ulog_buffers[i].timer.data = i;
383         }
384
385         nflognl = netlink_kernel_create(NETLINK_NFLOG, ULOG_MAXNLGROUPS, NULL,
386                                         THIS_MODULE);
387         if (!nflognl)
388                 return -ENOMEM;
389
390         ret = xt_register_target(&ipt_ulog_reg);
391         if (ret < 0) {
392                 sock_release(nflognl->sk_socket);
393                 return ret;
394         }
395         if (nflog)
396                 nf_log_register(PF_INET, &ipt_ulog_logger);
397
398         return 0;
399 }
400
401 static void __exit ipt_ulog_fini(void)
402 {
403         ulog_buff_t *ub;
404         int i;
405
406         DEBUGP("ipt_ULOG: cleanup_module\n");
407
408         if (nflog)
409                 nf_log_unregister(&ipt_ulog_logger);
410         xt_unregister_target(&ipt_ulog_reg);
411         sock_release(nflognl->sk_socket);
412
413         /* remove pending timers and free allocated skb's */
414         for (i = 0; i < ULOG_MAXNLGROUPS; i++) {
415                 ub = &ulog_buffers[i];
416                 if (timer_pending(&ub->timer)) {
417                         DEBUGP("timer was pending, deleting\n");
418                         del_timer(&ub->timer);
419                 }
420
421                 if (ub->skb) {
422                         kfree_skb(ub->skb);
423                         ub->skb = NULL;
424                 }
425         }
426 }
427
428 module_init(ipt_ulog_init);
429 module_exit(ipt_ulog_fini);