Blame view
net/netfilter/nfnetlink_log.c
26.9 KB
0597f2680 [NETFILTER]: Add ... |
1 2 3 4 5 |
/* * This is a module which is used for logging packets to userspace via * nfetlink. * * (C) 2005 by Harald Welte <laforge@netfilter.org> |
f229f6ce4 netfilter: add my... |
6 |
* (C) 2006-2012 Patrick McHardy <kaber@trash.net> |
0597f2680 [NETFILTER]: Add ... |
7 8 9 10 11 12 13 |
* * Based on the old ipv4-only ipt_ULOG.c: * (C) 2000-2004 by Harald Welte <laforge@netfilter.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. |
0597f2680 [NETFILTER]: Add ... |
14 15 16 |
*/ #include <linux/module.h> #include <linux/skbuff.h> |
e035edd16 netfilter: nfnetl... |
17 |
#include <linux/if_arp.h> |
0597f2680 [NETFILTER]: Add ... |
18 19 20 21 22 |
#include <linux/init.h> #include <linux/ip.h> #include <linux/ipv6.h> #include <linux/netdevice.h> #include <linux/netfilter.h> |
573ce260b net-next: replace... |
23 |
#include <net/netlink.h> |
0597f2680 [NETFILTER]: Add ... |
24 25 26 27 28 29 30 31 32 |
#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nfnetlink_log.h> #include <linux/spinlock.h> #include <linux/sysctl.h> #include <linux/proc_fs.h> #include <linux/security.h> #include <linux/list.h> #include <linux/jhash.h> #include <linux/random.h> |
5a0e3ad6a include cleanup: ... |
33 |
#include <linux/slab.h> |
0597f2680 [NETFILTER]: Add ... |
34 |
#include <net/sock.h> |
f01ffbd6e [NETFILTER]: nf_l... |
35 |
#include <net/netfilter/nf_log.h> |
9368a53c4 netfilter: nfnetl... |
36 |
#include <net/netns/generic.h> |
d9e150071 netfilter: nfnetl... |
37 |
#include <net/netfilter/nfnetlink_log.h> |
0597f2680 [NETFILTER]: Add ... |
38 |
|
60063497a atomic: use <linu... |
39 |
#include <linux/atomic.h> |
0597f2680 [NETFILTER]: Add ... |
40 |
|
fbcd923c3 [NETFILTER]: add ... |
41 42 43 |
#ifdef CONFIG_BRIDGE_NETFILTER #include "../bridge/br_private.h" #endif |
c2db29243 [NETFILTER]: ULOG... |
44 |
#define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE |
2c6764b74 netfilter: nfnetl... |
45 |
#define NFULNL_TIMEOUT_DEFAULT 100 /* every second */ |
0597f2680 [NETFILTER]: Add ... |
46 |
#define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */ |
6b6ec99a0 [NETFILTER]: nfne... |
47 |
#define NFULNL_COPY_RANGE_MAX 0xFFFF /* max packet size is limited by 16-bit struct nfattr nfa_len field */ |
0597f2680 [NETFILTER]: Add ... |
48 49 50 |
#define PRINTR(x, args...) do { if (net_ratelimit()) \ printk(x, ## args); } while (0); |
0597f2680 [NETFILTER]: Add ... |
51 52 53 54 55 56 57 |
struct nfulnl_instance { struct hlist_node hlist; /* global list of instances */ spinlock_t lock; atomic_t use; /* use count */ unsigned int qlen; /* number of nlmsgs in skb */ struct sk_buff *skb; /* pre-allocatd skb */ |
0597f2680 [NETFILTER]: Add ... |
58 |
struct timer_list timer; |
9368a53c4 netfilter: nfnetl... |
59 |
struct net *net; |
9eea9515c userns: nfnetlink... |
60 |
struct user_namespace *peer_user_ns; /* User namespace of the peer process */ |
15e473046 netlink: Rename p... |
61 |
int peer_portid; /* PORTID of the peer process */ |
0597f2680 [NETFILTER]: Add ... |
62 63 64 65 66 67 |
/* configurable parameters */ unsigned int flushtimeout; /* timeout until queue flush */ unsigned int nlbufsiz; /* netlink buffer allocation size */ unsigned int qthreshold; /* threshold of the queue */ u_int32_t copy_range; |
0af5f6c1e [NETFILTER] nfnet... |
68 |
u_int32_t seq; /* instance-local sequential counter */ |
0597f2680 [NETFILTER]: Add ... |
69 |
u_int16_t group_num; /* number of this queue */ |
0af5f6c1e [NETFILTER] nfnet... |
70 |
u_int16_t flags; |
601e68e10 [NETFILTER]: Fix ... |
71 |
u_int8_t copy_mode; |
bed1be208 netfilter: nfnetl... |
72 |
struct rcu_head rcu; |
0597f2680 [NETFILTER]: Add ... |
73 |
}; |
0597f2680 [NETFILTER]: Add ... |
74 |
#define INSTANCE_BUCKETS 16 |
0597f2680 [NETFILTER]: Add ... |
75 |
static unsigned int hash_init; |
9368a53c4 netfilter: nfnetl... |
76 77 78 79 80 81 82 83 84 85 86 87 |
static int nfnl_log_net_id __read_mostly; struct nfnl_log_net { spinlock_t instances_lock; struct hlist_head instance_table[INSTANCE_BUCKETS]; atomic_t global_seq; }; static struct nfnl_log_net *nfnl_log_pernet(struct net *net) { return net_generic(net, nfnl_log_net_id); } |
0597f2680 [NETFILTER]: Add ... |
88 89 90 91 92 93 |
static inline u_int8_t instance_hashfn(u_int16_t group_num) { return ((group_num & 0xff) % INSTANCE_BUCKETS); } static struct nfulnl_instance * |
9368a53c4 netfilter: nfnetl... |
94 |
__instance_lookup(struct nfnl_log_net *log, u_int16_t group_num) |
0597f2680 [NETFILTER]: Add ... |
95 96 |
{ struct hlist_head *head; |
0597f2680 [NETFILTER]: Add ... |
97 |
struct nfulnl_instance *inst; |
9368a53c4 netfilter: nfnetl... |
98 |
head = &log->instance_table[instance_hashfn(group_num)]; |
b67bfe0d4 hlist: drop the n... |
99 |
hlist_for_each_entry_rcu(inst, head, hlist) { |
0597f2680 [NETFILTER]: Add ... |
100 101 102 103 104 105 106 107 108 109 110 111 112 |
if (inst->group_num == group_num) return inst; } return NULL; } static inline void instance_get(struct nfulnl_instance *inst) { atomic_inc(&inst->use); } static struct nfulnl_instance * |
9368a53c4 netfilter: nfnetl... |
113 |
instance_lookup_get(struct nfnl_log_net *log, u_int16_t group_num) |
0597f2680 [NETFILTER]: Add ... |
114 115 |
{ struct nfulnl_instance *inst; |
bed1be208 netfilter: nfnetl... |
116 |
rcu_read_lock_bh(); |
9368a53c4 netfilter: nfnetl... |
117 |
inst = __instance_lookup(log, group_num); |
f5c5440d4 netfilter: nfnetl... |
118 119 |
if (inst && !atomic_inc_not_zero(&inst->use)) inst = NULL; |
bed1be208 netfilter: nfnetl... |
120 |
rcu_read_unlock_bh(); |
0597f2680 [NETFILTER]: Add ... |
121 122 123 |
return inst; } |
bed1be208 netfilter: nfnetl... |
124 125 |
static void nfulnl_instance_free_rcu(struct rcu_head *head) { |
9368a53c4 netfilter: nfnetl... |
126 127 128 129 130 |
struct nfulnl_instance *inst = container_of(head, struct nfulnl_instance, rcu); put_net(inst->net); kfree(inst); |
bed1be208 netfilter: nfnetl... |
131 132 |
module_put(THIS_MODULE); } |
0597f2680 [NETFILTER]: Add ... |
133 134 135 |
static void instance_put(struct nfulnl_instance *inst) { |
bed1be208 netfilter: nfnetl... |
136 137 |
if (inst && atomic_dec_and_test(&inst->use)) call_rcu_bh(&inst->rcu, nfulnl_instance_free_rcu); |
0597f2680 [NETFILTER]: Add ... |
138 139 140 141 142 |
} static void nfulnl_timer(unsigned long data); static struct nfulnl_instance * |
9368a53c4 netfilter: nfnetl... |
143 144 |
instance_create(struct net *net, u_int16_t group_num, int portid, struct user_namespace *user_ns) |
0597f2680 [NETFILTER]: Add ... |
145 146 |
{ struct nfulnl_instance *inst; |
9368a53c4 netfilter: nfnetl... |
147 |
struct nfnl_log_net *log = nfnl_log_pernet(net); |
baab2ce7d [NETFILTER]: nfne... |
148 |
int err; |
0597f2680 [NETFILTER]: Add ... |
149 |
|
9368a53c4 netfilter: nfnetl... |
150 151 |
spin_lock_bh(&log->instances_lock); if (__instance_lookup(log, group_num)) { |
baab2ce7d [NETFILTER]: nfne... |
152 |
err = -EEXIST; |
0597f2680 [NETFILTER]: Add ... |
153 154 |
goto out_unlock; } |
10dfdc69e [NETFILTER] nfnet... |
155 |
inst = kzalloc(sizeof(*inst), GFP_ATOMIC); |
baab2ce7d [NETFILTER]: nfne... |
156 157 |
if (!inst) { err = -ENOMEM; |
0597f2680 [NETFILTER]: Add ... |
158 |
goto out_unlock; |
baab2ce7d [NETFILTER]: nfne... |
159 |
} |
0597f2680 [NETFILTER]: Add ... |
160 |
|
aace57e05 [NETFILTER]: nfne... |
161 162 |
if (!try_module_get(THIS_MODULE)) { kfree(inst); |
baab2ce7d [NETFILTER]: nfne... |
163 |
err = -EAGAIN; |
aace57e05 [NETFILTER]: nfne... |
164 165 |
goto out_unlock; } |
0597f2680 [NETFILTER]: Add ... |
166 |
INIT_HLIST_NODE(&inst->hlist); |
181a46a56 [NETFILTER]: Use ... |
167 |
spin_lock_init(&inst->lock); |
0597f2680 [NETFILTER]: Add ... |
168 169 |
/* needs to be two, since we _put() after creation */ atomic_set(&inst->use, 2); |
e6f689db5 [NETFILTER]: Use ... |
170 |
setup_timer(&inst->timer, nfulnl_timer, (unsigned long)inst); |
0597f2680 [NETFILTER]: Add ... |
171 |
|
9368a53c4 netfilter: nfnetl... |
172 |
inst->net = get_net(net); |
9eea9515c userns: nfnetlink... |
173 |
inst->peer_user_ns = user_ns; |
15e473046 netlink: Rename p... |
174 |
inst->peer_portid = portid; |
0597f2680 [NETFILTER]: Add ... |
175 176 177 178 179 180 |
inst->group_num = group_num; inst->qthreshold = NFULNL_QTHRESH_DEFAULT; inst->flushtimeout = NFULNL_TIMEOUT_DEFAULT; inst->nlbufsiz = NFULNL_NLBUFSIZ_DEFAULT; inst->copy_mode = NFULNL_COPY_PACKET; |
6b6ec99a0 [NETFILTER]: nfne... |
181 |
inst->copy_range = NFULNL_COPY_RANGE_MAX; |
0597f2680 [NETFILTER]: Add ... |
182 |
|
f5c5440d4 netfilter: nfnetl... |
183 |
hlist_add_head_rcu(&inst->hlist, |
9368a53c4 netfilter: nfnetl... |
184 |
&log->instance_table[instance_hashfn(group_num)]); |
0597f2680 [NETFILTER]: Add ... |
185 |
|
9368a53c4 netfilter: nfnetl... |
186 |
spin_unlock_bh(&log->instances_lock); |
0597f2680 [NETFILTER]: Add ... |
187 188 |
return inst; |
0597f2680 [NETFILTER]: Add ... |
189 |
out_unlock: |
9368a53c4 netfilter: nfnetl... |
190 |
spin_unlock_bh(&log->instances_lock); |
baab2ce7d [NETFILTER]: nfne... |
191 |
return ERR_PTR(err); |
0597f2680 [NETFILTER]: Add ... |
192 |
} |
e35670614 [NETFILTER]: nfne... |
193 |
static void __nfulnl_flush(struct nfulnl_instance *inst); |
0597f2680 [NETFILTER]: Add ... |
194 |
|
f5c5440d4 netfilter: nfnetl... |
195 |
/* called with BH disabled */ |
0597f2680 [NETFILTER]: Add ... |
196 |
static void |
9afdb00c8 [NETFILTER]: nfne... |
197 |
__instance_destroy(struct nfulnl_instance *inst) |
0597f2680 [NETFILTER]: Add ... |
198 199 |
{ /* first pull it out of the global list */ |
f5c5440d4 netfilter: nfnetl... |
200 |
hlist_del_rcu(&inst->hlist); |
0597f2680 [NETFILTER]: Add ... |
201 |
|
0597f2680 [NETFILTER]: Add ... |
202 |
/* then flush all pending packets from skb */ |
f5c5440d4 netfilter: nfnetl... |
203 204 205 206 |
spin_lock(&inst->lock); /* lockless readers wont be able to use us */ inst->copy_mode = NFULNL_COPY_DISABLED; |
e35670614 [NETFILTER]: nfne... |
207 208 |
if (inst->skb) __nfulnl_flush(inst); |
f5c5440d4 netfilter: nfnetl... |
209 |
spin_unlock(&inst->lock); |
0597f2680 [NETFILTER]: Add ... |
210 211 212 |
/* and finally put the refcount */ instance_put(inst); |
0597f2680 [NETFILTER]: Add ... |
213 214 215 |
} static inline void |
9368a53c4 netfilter: nfnetl... |
216 217 |
instance_destroy(struct nfnl_log_net *log, struct nfulnl_instance *inst) |
0597f2680 [NETFILTER]: Add ... |
218 |
{ |
9368a53c4 netfilter: nfnetl... |
219 |
spin_lock_bh(&log->instances_lock); |
9afdb00c8 [NETFILTER]: nfne... |
220 |
__instance_destroy(inst); |
9368a53c4 netfilter: nfnetl... |
221 |
spin_unlock_bh(&log->instances_lock); |
0597f2680 [NETFILTER]: Add ... |
222 223 224 225 226 227 228 229 230 |
} static int nfulnl_set_mode(struct nfulnl_instance *inst, u_int8_t mode, unsigned int range) { int status = 0; spin_lock_bh(&inst->lock); |
601e68e10 [NETFILTER]: Fix ... |
231 |
|
0597f2680 [NETFILTER]: Add ... |
232 233 234 235 236 237 |
switch (mode) { case NFULNL_COPY_NONE: case NFULNL_COPY_META: inst->copy_mode = mode; inst->copy_range = 0; break; |
601e68e10 [NETFILTER]: Fix ... |
238 |
|
0597f2680 [NETFILTER]: Add ... |
239 240 |
case NFULNL_COPY_PACKET: inst->copy_mode = mode; |
6b6ec99a0 [NETFILTER]: nfne... |
241 242 |
inst->copy_range = min_t(unsigned int, range, NFULNL_COPY_RANGE_MAX); |
0597f2680 [NETFILTER]: Add ... |
243 |
break; |
601e68e10 [NETFILTER]: Fix ... |
244 |
|
0597f2680 [NETFILTER]: Add ... |
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
default: status = -EINVAL; break; } spin_unlock_bh(&inst->lock); return status; } static int nfulnl_set_nlbufsiz(struct nfulnl_instance *inst, u_int32_t nlbufsiz) { int status; spin_lock_bh(&inst->lock); if (nlbufsiz < NFULNL_NLBUFSIZ_DEFAULT) status = -ERANGE; else if (nlbufsiz > 131072) status = -ERANGE; else { inst->nlbufsiz = nlbufsiz; status = 0; } spin_unlock_bh(&inst->lock); return status; } static int nfulnl_set_timeout(struct nfulnl_instance *inst, u_int32_t timeout) { spin_lock_bh(&inst->lock); inst->flushtimeout = timeout; spin_unlock_bh(&inst->lock); return 0; } static int nfulnl_set_qthresh(struct nfulnl_instance *inst, u_int32_t qthresh) { spin_lock_bh(&inst->lock); inst->qthreshold = qthresh; spin_unlock_bh(&inst->lock); return 0; } |
0af5f6c1e [NETFILTER] nfnet... |
293 294 295 296 |
static int nfulnl_set_flags(struct nfulnl_instance *inst, u_int16_t flags) { spin_lock_bh(&inst->lock); |
ee433530d [NETFILTER]: nfne... |
297 |
inst->flags = flags; |
0af5f6c1e [NETFILTER] nfnet... |
298 299 300 301 |
spin_unlock_bh(&inst->lock); return 0; } |
c6a8f6483 [NETFILTER]: nfne... |
302 |
static struct sk_buff * |
3ab1f683b nfnetlink: add su... |
303 |
nfulnl_alloc_skb(u32 peer_portid, unsigned int inst_size, unsigned int pkt_size) |
0597f2680 [NETFILTER]: Add ... |
304 305 |
{ struct sk_buff *skb; |
ad2ad0f96 [NETFILTER]: Fix ... |
306 |
unsigned int n; |
0597f2680 [NETFILTER]: Add ... |
307 |
|
0597f2680 [NETFILTER]: Add ... |
308 309 |
/* alloc skb which should be big enough for a whole multipart * message. WARNING: has to be <= 128k due to slab restrictions */ |
ad2ad0f96 [NETFILTER]: Fix ... |
310 |
n = max(inst_size, pkt_size); |
3ab1f683b nfnetlink: add su... |
311 |
skb = nfnetlink_alloc_skb(&init_net, n, peer_portid, GFP_ATOMIC); |
0597f2680 [NETFILTER]: Add ... |
312 |
if (!skb) { |
ad2ad0f96 [NETFILTER]: Fix ... |
313 314 315 |
if (n > pkt_size) { /* try to allocate only as much as we need for current * packet */ |
0597f2680 [NETFILTER]: Add ... |
316 |
|
3ab1f683b nfnetlink: add su... |
317 318 |
skb = nfnetlink_alloc_skb(&init_net, pkt_size, peer_portid, GFP_ATOMIC); |
ad2ad0f96 [NETFILTER]: Fix ... |
319 |
if (!skb) |
0a9ee8134 netfilter: Remove... |
320 321 322 |
pr_err("nfnetlink_log: can't even alloc %u bytes ", pkt_size); |
ad2ad0f96 [NETFILTER]: Fix ... |
323 |
} |
0597f2680 [NETFILTER]: Add ... |
324 325 326 327 328 329 330 331 |
} return skb; } static int __nfulnl_send(struct nfulnl_instance *inst) { |
29c5d4afb [NETFILTER]: nfne... |
332 |
int status = -1; |
0597f2680 [NETFILTER]: Add ... |
333 |
|
d550d0958 netfilter: nfnetl... |
334 335 336 337 338 339 340 341 |
if (inst->qlen > 1) { struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0, NLMSG_DONE, sizeof(struct nfgenmsg), 0); if (!nlh) goto out; } |
9368a53c4 netfilter: nfnetl... |
342 |
status = nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid, |
cd8c20b65 netfilter: nfnetl... |
343 |
MSG_DONTWAIT); |
0597f2680 [NETFILTER]: Add ... |
344 345 346 |
inst->qlen = 0; inst->skb = NULL; |
d550d0958 netfilter: nfnetl... |
347 |
out: |
0597f2680 [NETFILTER]: Add ... |
348 349 |
return status; } |
e35670614 [NETFILTER]: nfne... |
350 351 352 353 354 355 356 357 358 |
static void __nfulnl_flush(struct nfulnl_instance *inst) { /* timer holds a reference */ if (del_timer(&inst->timer)) instance_put(inst); if (inst->skb) __nfulnl_send(inst); } |
c6a8f6483 [NETFILTER]: nfne... |
359 360 |
static void nfulnl_timer(unsigned long data) |
0597f2680 [NETFILTER]: Add ... |
361 |
{ |
601e68e10 [NETFILTER]: Fix ... |
362 |
struct nfulnl_instance *inst = (struct nfulnl_instance *)data; |
0597f2680 [NETFILTER]: Add ... |
363 |
|
0597f2680 [NETFILTER]: Add ... |
364 |
spin_lock_bh(&inst->lock); |
370e6a878 [NETFILTER]: nfne... |
365 366 |
if (inst->skb) __nfulnl_send(inst); |
0597f2680 [NETFILTER]: Add ... |
367 |
spin_unlock_bh(&inst->lock); |
05f7b7b36 [NETFILTER]: nfne... |
368 |
instance_put(inst); |
0597f2680 [NETFILTER]: Add ... |
369 |
} |
0af5f6c1e [NETFILTER] nfnet... |
370 371 |
/* This is an inline function, we don't really care about a long * list of arguments */ |
601e68e10 [NETFILTER]: Fix ... |
372 |
static inline int |
9368a53c4 netfilter: nfnetl... |
373 374 |
__build_packet_message(struct nfnl_log_net *log, struct nfulnl_instance *inst, |
601e68e10 [NETFILTER]: Fix ... |
375 |
const struct sk_buff *skb, |
0597f2680 [NETFILTER]: Add ... |
376 |
unsigned int data_len, |
76108cea0 netfilter: Use un... |
377 |
u_int8_t pf, |
0597f2680 [NETFILTER]: Add ... |
378 379 380 |
unsigned int hooknum, const struct net_device *indev, const struct net_device *outdev, |
d7a5c3244 [NETFILTER]: nfne... |
381 |
const char *prefix, unsigned int plen) |
0597f2680 [NETFILTER]: Add ... |
382 |
{ |
0597f2680 [NETFILTER]: Add ... |
383 384 385 |
struct nfulnl_msg_packet_hdr pmsg; struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; |
27a884dc3 [SK_BUFF]: Conver... |
386 |
sk_buff_data_t old_tail = inst->skb->tail; |
0626af313 netfilter: take c... |
387 |
struct sock *sk; |
0c36b48b3 netfilter: nfnetl... |
388 |
const unsigned char *hwhdrp; |
0597f2680 [NETFILTER]: Add ... |
389 |
|
d550d0958 netfilter: nfnetl... |
390 |
nlh = nlmsg_put(inst->skb, 0, 0, |
0597f2680 [NETFILTER]: Add ... |
391 |
NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET, |
d550d0958 netfilter: nfnetl... |
392 393 394 395 |
sizeof(struct nfgenmsg), 0); if (!nlh) return -1; nfmsg = nlmsg_data(nlh); |
0597f2680 [NETFILTER]: Add ... |
396 397 398 |
nfmsg->nfgen_family = pf; nfmsg->version = NFNETLINK_V0; nfmsg->res_id = htons(inst->group_num); |
febf0a431 [NETFILTER] bug: ... |
399 |
pmsg.hw_protocol = skb->protocol; |
0597f2680 [NETFILTER]: Add ... |
400 |
pmsg.hook = hooknum; |
1db20a529 nfnetlink_log: St... |
401 402 |
if (nla_put(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg)) goto nla_put_failure; |
0597f2680 [NETFILTER]: Add ... |
403 |
|
1db20a529 nfnetlink_log: St... |
404 405 406 |
if (prefix && nla_put(inst->skb, NFULA_PREFIX, plen, prefix)) goto nla_put_failure; |
0597f2680 [NETFILTER]: Add ... |
407 408 |
if (indev) { |
fbcd923c3 [NETFILTER]: add ... |
409 |
#ifndef CONFIG_BRIDGE_NETFILTER |
1db20a529 nfnetlink_log: St... |
410 411 412 |
if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV, htonl(indev->ifindex))) goto nla_put_failure; |
fbcd923c3 [NETFILTER]: add ... |
413 414 415 416 417 |
#else if (pf == PF_BRIDGE) { /* Case 1: outdev is physical input device, we need to * look for bridge group (when called from * netfilter_bridge) */ |
1db20a529 nfnetlink_log: St... |
418 419 |
if (nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV, htonl(indev->ifindex)) || |
fbcd923c3 [NETFILTER]: add ... |
420 |
/* this is the bridge group "brX" */ |
f350a0a87 bridge: use rx_ha... |
421 |
/* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */ |
1db20a529 nfnetlink_log: St... |
422 423 424 |
nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV, htonl(br_port_get_rcu(indev)->br->dev->ifindex))) goto nla_put_failure; |
fbcd923c3 [NETFILTER]: add ... |
425 426 427 |
} else { /* Case 2: indev is bridge group, we need to look for * physical device (when called from ipv4) */ |
1db20a529 nfnetlink_log: St... |
428 429 430 431 432 433 434 |
if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV, htonl(indev->ifindex))) goto nla_put_failure; if (skb->nf_bridge && skb->nf_bridge->physindev && nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV, htonl(skb->nf_bridge->physindev->ifindex))) goto nla_put_failure; |
fbcd923c3 [NETFILTER]: add ... |
435 436 |
} #endif |
0597f2680 [NETFILTER]: Add ... |
437 438 439 |
} if (outdev) { |
fbcd923c3 [NETFILTER]: add ... |
440 |
#ifndef CONFIG_BRIDGE_NETFILTER |
1db20a529 nfnetlink_log: St... |
441 442 443 |
if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV, htonl(outdev->ifindex))) goto nla_put_failure; |
fbcd923c3 [NETFILTER]: add ... |
444 445 446 447 448 |
#else if (pf == PF_BRIDGE) { /* Case 1: outdev is physical output device, we need to * look for bridge group (when called from * netfilter_bridge) */ |
1db20a529 nfnetlink_log: St... |
449 450 |
if (nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, htonl(outdev->ifindex)) || |
fbcd923c3 [NETFILTER]: add ... |
451 |
/* this is the bridge group "brX" */ |
f350a0a87 bridge: use rx_ha... |
452 |
/* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */ |
1db20a529 nfnetlink_log: St... |
453 454 455 |
nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV, htonl(br_port_get_rcu(outdev)->br->dev->ifindex))) goto nla_put_failure; |
fbcd923c3 [NETFILTER]: add ... |
456 457 458 |
} else { /* Case 2: indev is a bridge group, we need to look * for physical device (when called from ipv4) */ |
1db20a529 nfnetlink_log: St... |
459 460 461 462 463 464 465 |
if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV, htonl(outdev->ifindex))) goto nla_put_failure; if (skb->nf_bridge && skb->nf_bridge->physoutdev && nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, htonl(skb->nf_bridge->physoutdev->ifindex))) goto nla_put_failure; |
fbcd923c3 [NETFILTER]: add ... |
466 467 |
} #endif |
0597f2680 [NETFILTER]: Add ... |
468 |
} |
1db20a529 nfnetlink_log: St... |
469 470 471 |
if (skb->mark && nla_put_be32(inst->skb, NFULA_MARK, htonl(skb->mark))) goto nla_put_failure; |
0597f2680 [NETFILTER]: Add ... |
472 |
|
2c38de4c1 netfilter: fix lo... |
473 474 |
if (indev && skb->dev && skb->mac_header != skb->network_header) { |
0597f2680 [NETFILTER]: Add ... |
475 |
struct nfulnl_msg_packet_hw phw; |
b95cce357 [NET]: Wrap hard_... |
476 477 478 |
int len = dev_parse_header(skb, phw.hw_addr); if (len > 0) { phw.hw_addrlen = htons(len); |
1db20a529 nfnetlink_log: St... |
479 480 |
if (nla_put(inst->skb, NFULA_HWADDR, sizeof(phw), &phw)) goto nla_put_failure; |
b95cce357 [NET]: Wrap hard_... |
481 |
} |
0597f2680 [NETFILTER]: Add ... |
482 |
} |
72961ecf8 netfilter: nfnetl... |
483 |
if (indev && skb_mac_header_was_set(skb)) { |
2dba62c30 netfilter: nfnetl... |
484 |
if (nla_put_be16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) || |
1db20a529 nfnetlink_log: St... |
485 |
nla_put_be16(inst->skb, NFULA_HWLEN, |
0c36b48b3 netfilter: nfnetl... |
486 487 488 489 490 491 492 493 494 495 496 |
htons(skb->dev->hard_header_len))) goto nla_put_failure; hwhdrp = skb_mac_header(skb); if (skb->dev->type == ARPHRD_SIT) hwhdrp -= ETH_HLEN; if (hwhdrp >= skb->head && nla_put(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len, hwhdrp)) |
1db20a529 nfnetlink_log: St... |
497 |
goto nla_put_failure; |
72961ecf8 netfilter: nfnetl... |
498 |
} |
b7aa0bf70 [NET]: convert ne... |
499 |
if (skb->tstamp.tv64) { |
0597f2680 [NETFILTER]: Add ... |
500 |
struct nfulnl_msg_packet_timestamp ts; |
b7aa0bf70 [NET]: convert ne... |
501 502 503 |
struct timeval tv = ktime_to_timeval(skb->tstamp); ts.sec = cpu_to_be64(tv.tv_sec); ts.usec = cpu_to_be64(tv.tv_usec); |
0597f2680 [NETFILTER]: Add ... |
504 |
|
1db20a529 nfnetlink_log: St... |
505 506 |
if (nla_put(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts)) goto nla_put_failure; |
0597f2680 [NETFILTER]: Add ... |
507 508 509 |
} /* UID */ |
0626af313 netfilter: take c... |
510 511 512 513 514 |
sk = skb->sk; if (sk && sk->sk_state != TCP_TIME_WAIT) { read_lock_bh(&sk->sk_callback_lock); if (sk->sk_socket && sk->sk_socket->file) { struct file *file = sk->sk_socket->file; |
437589a74 Merge branch 'for... |
515 516 517 518 |
const struct cred *cred = file->f_cred; struct user_namespace *user_ns = inst->peer_user_ns; __be32 uid = htonl(from_kuid_munged(user_ns, cred->fsuid)); __be32 gid = htonl(from_kgid_munged(user_ns, cred->fsgid)); |
0626af313 netfilter: take c... |
519 |
read_unlock_bh(&sk->sk_callback_lock); |
1db20a529 nfnetlink_log: St... |
520 521 522 |
if (nla_put_be32(inst->skb, NFULA_UID, uid) || nla_put_be32(inst->skb, NFULA_GID, gid)) goto nla_put_failure; |
0597f2680 [NETFILTER]: Add ... |
523 |
} else |
0626af313 netfilter: take c... |
524 |
read_unlock_bh(&sk->sk_callback_lock); |
0597f2680 [NETFILTER]: Add ... |
525 |
} |
0af5f6c1e [NETFILTER] nfnet... |
526 |
/* local sequence number */ |
1db20a529 nfnetlink_log: St... |
527 528 529 |
if ((inst->flags & NFULNL_CFG_F_SEQ) && nla_put_be32(inst->skb, NFULA_SEQ, htonl(inst->seq++))) goto nla_put_failure; |
0dfedd287 [NETFILTER]: nfne... |
530 |
|
0af5f6c1e [NETFILTER] nfnet... |
531 |
/* global sequence number */ |
1db20a529 nfnetlink_log: St... |
532 533 |
if ((inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) && nla_put_be32(inst->skb, NFULA_SEQ_GLOBAL, |
9368a53c4 netfilter: nfnetl... |
534 |
htonl(atomic_inc_return(&log->global_seq)))) |
1db20a529 nfnetlink_log: St... |
535 |
goto nla_put_failure; |
0af5f6c1e [NETFILTER] nfnet... |
536 |
|
0597f2680 [NETFILTER]: Add ... |
537 |
if (data_len) { |
df6fb868d [NETFILTER]: nfne... |
538 539 |
struct nlattr *nla; int size = nla_attr_size(data_len); |
0597f2680 [NETFILTER]: Add ... |
540 |
|
df6fb868d [NETFILTER]: nfne... |
541 |
if (skb_tailroom(inst->skb) < nla_total_size(data_len)) { |
0597f2680 [NETFILTER]: Add ... |
542 543 |
printk(KERN_WARNING "nfnetlink_log: no tailroom! "); |
d550d0958 netfilter: nfnetl... |
544 |
return -1; |
0597f2680 [NETFILTER]: Add ... |
545 |
} |
df6fb868d [NETFILTER]: nfne... |
546 547 548 |
nla = (struct nlattr *)skb_put(inst->skb, nla_total_size(data_len)); nla->nla_type = NFULA_PAYLOAD; nla->nla_len = size; |
0597f2680 [NETFILTER]: Add ... |
549 |
|
df6fb868d [NETFILTER]: nfne... |
550 |
if (skb_copy_bits(skb, 0, nla_data(nla), data_len)) |
0597f2680 [NETFILTER]: Add ... |
551 552 |
BUG(); } |
601e68e10 [NETFILTER]: Fix ... |
553 |
|
0597f2680 [NETFILTER]: Add ... |
554 555 |
nlh->nlmsg_len = inst->skb->tail - old_tail; return 0; |
df6fb868d [NETFILTER]: nfne... |
556 |
nla_put_failure: |
0597f2680 [NETFILTER]: Add ... |
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 |
PRINTR(KERN_ERR "nfnetlink_log: error creating log nlmsg "); return -1; } #define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) static struct nf_loginfo default_loginfo = { .type = NF_LOG_TYPE_ULOG, .u = { .ulog = { .copy_len = 0xffff, .group = 0, .qthreshold = 1, }, }, }; /* log handler for internal netfilter logging api */ |
5f7340eff netfilter: xt_NFL... |
576 |
void |
8cdb46da0 netfilter: log: n... |
577 578 |
nfulnl_log_packet(struct net *net, u_int8_t pf, |
0597f2680 [NETFILTER]: Add ... |
579 580 581 582 583 584 585 586 587 588 589 |
unsigned int hooknum, const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const struct nf_loginfo *li_user, const char *prefix) { unsigned int size, data_len; struct nfulnl_instance *inst; const struct nf_loginfo *li; unsigned int qthreshold; |
d7a5c3244 [NETFILTER]: nfne... |
590 |
unsigned int plen; |
9368a53c4 netfilter: nfnetl... |
591 |
struct nfnl_log_net *log = nfnl_log_pernet(net); |
0597f2680 [NETFILTER]: Add ... |
592 |
|
601e68e10 [NETFILTER]: Fix ... |
593 |
if (li_user && li_user->type == NF_LOG_TYPE_ULOG) |
0597f2680 [NETFILTER]: Add ... |
594 595 596 |
li = li_user; else li = &default_loginfo; |
9368a53c4 netfilter: nfnetl... |
597 |
inst = instance_lookup_get(log, li->u.ulog.group); |
0597f2680 [NETFILTER]: Add ... |
598 |
if (!inst) |
0597f2680 [NETFILTER]: Add ... |
599 |
return; |
0597f2680 [NETFILTER]: Add ... |
600 |
|
d7a5c3244 [NETFILTER]: nfne... |
601 602 |
plen = 0; if (prefix) |
881dbfe8a [NETFILTER]: nfne... |
603 |
plen = strlen(prefix) + 1; |
d7a5c3244 [NETFILTER]: nfne... |
604 |
|
0597f2680 [NETFILTER]: Add ... |
605 606 607 |
/* FIXME: do we want to make the size calculation conditional based on * what is actually present? way more branches and checks, but more * memory efficient... */ |
573ce260b net-next: replace... |
608 |
size = nlmsg_total_size(sizeof(struct nfgenmsg)) |
df6fb868d [NETFILTER]: nfne... |
609 610 611 |
+ nla_total_size(sizeof(struct nfulnl_msg_packet_hdr)) + nla_total_size(sizeof(u_int32_t)) /* ifindex */ + nla_total_size(sizeof(u_int32_t)) /* ifindex */ |
fbcd923c3 [NETFILTER]: add ... |
612 |
#ifdef CONFIG_BRIDGE_NETFILTER |
df6fb868d [NETFILTER]: nfne... |
613 614 |
+ nla_total_size(sizeof(u_int32_t)) /* ifindex */ + nla_total_size(sizeof(u_int32_t)) /* ifindex */ |
fbcd923c3 [NETFILTER]: add ... |
615 |
#endif |
df6fb868d [NETFILTER]: nfne... |
616 617 |
+ nla_total_size(sizeof(u_int32_t)) /* mark */ + nla_total_size(sizeof(u_int32_t)) /* uid */ |
76aa1ce13 [NETFILTER]: nfne... |
618 |
+ nla_total_size(sizeof(u_int32_t)) /* gid */ |
df6fb868d [NETFILTER]: nfne... |
619 620 621 |
+ nla_total_size(plen) /* prefix */ + nla_total_size(sizeof(struct nfulnl_msg_packet_hw)) + nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp)); |
0597f2680 [NETFILTER]: Add ... |
622 |
|
eeff9beec netfilter: nfnetl... |
623 624 625 626 627 |
if (in && skb_mac_header_was_set(skb)) { size += nla_total_size(skb->dev->hard_header_len) + nla_total_size(sizeof(u_int16_t)) /* hwtype */ + nla_total_size(sizeof(u_int16_t)); /* hwlen */ } |
0597f2680 [NETFILTER]: Add ... |
628 |
spin_lock_bh(&inst->lock); |
0af5f6c1e [NETFILTER] nfnet... |
629 |
if (inst->flags & NFULNL_CFG_F_SEQ) |
df6fb868d [NETFILTER]: nfne... |
630 |
size += nla_total_size(sizeof(u_int32_t)); |
0af5f6c1e [NETFILTER] nfnet... |
631 |
if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) |
df6fb868d [NETFILTER]: nfne... |
632 |
size += nla_total_size(sizeof(u_int32_t)); |
0af5f6c1e [NETFILTER] nfnet... |
633 |
|
0597f2680 [NETFILTER]: Add ... |
634 635 |
qthreshold = inst->qthreshold; /* per-rule qthreshold overrides per-instance */ |
5ca431f9a netfilter: nfnetl... |
636 637 638 |
if (li->u.ulog.qthreshold) if (qthreshold > li->u.ulog.qthreshold) qthreshold = li->u.ulog.qthreshold; |
601e68e10 [NETFILTER]: Fix ... |
639 |
|
0597f2680 [NETFILTER]: Add ... |
640 641 642 643 644 |
switch (inst->copy_mode) { case NFULNL_COPY_META: case NFULNL_COPY_NONE: data_len = 0; break; |
601e68e10 [NETFILTER]: Fix ... |
645 |
|
0597f2680 [NETFILTER]: Add ... |
646 |
case NFULNL_COPY_PACKET: |
601e68e10 [NETFILTER]: Fix ... |
647 |
if (inst->copy_range == 0 |
0597f2680 [NETFILTER]: Add ... |
648 649 650 651 |
|| inst->copy_range > skb->len) data_len = skb->len; else data_len = inst->copy_range; |
601e68e10 [NETFILTER]: Fix ... |
652 |
|
df6fb868d [NETFILTER]: nfne... |
653 |
size += nla_total_size(data_len); |
0597f2680 [NETFILTER]: Add ... |
654 |
break; |
601e68e10 [NETFILTER]: Fix ... |
655 |
|
f5c5440d4 netfilter: nfnetl... |
656 |
case NFULNL_COPY_DISABLED: |
0597f2680 [NETFILTER]: Add ... |
657 |
default: |
55b5a91e1 [NETFILTER]: nfne... |
658 |
goto unlock_and_release; |
0597f2680 [NETFILTER]: Add ... |
659 |
} |
d63b043d9 [NETFILTER]: nfne... |
660 661 |
if (inst->skb && size > skb_tailroom(inst->skb) - sizeof(struct nfgenmsg)) { |
0597f2680 [NETFILTER]: Add ... |
662 663 |
/* either the queue len is too high or we don't have * enough room in the skb left. flush to userspace. */ |
e35670614 [NETFILTER]: nfne... |
664 |
__nfulnl_flush(inst); |
55b5a91e1 [NETFILTER]: nfne... |
665 |
} |
0597f2680 [NETFILTER]: Add ... |
666 |
|
55b5a91e1 [NETFILTER]: nfne... |
667 |
if (!inst->skb) { |
3ab1f683b nfnetlink: add su... |
668 669 |
inst->skb = nfulnl_alloc_skb(inst->peer_portid, inst->nlbufsiz, size); |
55b5a91e1 [NETFILTER]: nfne... |
670 |
if (!inst->skb) |
0597f2680 [NETFILTER]: Add ... |
671 |
goto alloc_failure; |
0597f2680 [NETFILTER]: Add ... |
672 |
} |
0597f2680 [NETFILTER]: Add ... |
673 |
inst->qlen++; |
9368a53c4 netfilter: nfnetl... |
674 |
__build_packet_message(log, inst, skb, data_len, pf, |
8248779b1 netfilter: nfnetl... |
675 |
hooknum, in, out, prefix, plen); |
0597f2680 [NETFILTER]: Add ... |
676 |
|
d63b043d9 [NETFILTER]: nfne... |
677 678 |
if (inst->qlen >= qthreshold) __nfulnl_flush(inst); |
0597f2680 [NETFILTER]: Add ... |
679 680 |
/* timer_pending always called within inst->lock, so there * is no chance of a race here */ |
d63b043d9 [NETFILTER]: nfne... |
681 |
else if (!timer_pending(&inst->timer)) { |
0597f2680 [NETFILTER]: Add ... |
682 683 684 685 |
instance_get(inst); inst->timer.expires = jiffies + (inst->flushtimeout*HZ/100); add_timer(&inst->timer); } |
0597f2680 [NETFILTER]: Add ... |
686 |
|
ed32abeaf [NETFILTER]: nfne... |
687 688 689 |
unlock_and_release: spin_unlock_bh(&inst->lock); instance_put(inst); |
0597f2680 [NETFILTER]: Add ... |
690 691 692 |
return; alloc_failure: |
0597f2680 [NETFILTER]: Add ... |
693 |
/* FIXME: statistics */ |
ed32abeaf [NETFILTER]: nfne... |
694 |
goto unlock_and_release; |
0597f2680 [NETFILTER]: Add ... |
695 |
} |
5f7340eff netfilter: xt_NFL... |
696 |
EXPORT_SYMBOL_GPL(nfulnl_log_packet); |
0597f2680 [NETFILTER]: Add ... |
697 698 699 700 701 702 |
static int nfulnl_rcv_nl_event(struct notifier_block *this, unsigned long event, void *ptr) { struct netlink_notify *n = ptr; |
9368a53c4 netfilter: nfnetl... |
703 |
struct nfnl_log_net *log = nfnl_log_pernet(n->net); |
0597f2680 [NETFILTER]: Add ... |
704 |
|
dee5817e8 netfilter: remove... |
705 |
if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) { |
0597f2680 [NETFILTER]: Add ... |
706 |
int i; |
15e473046 netlink: Rename p... |
707 |
/* destroy all instances for this portid */ |
9368a53c4 netfilter: nfnetl... |
708 |
spin_lock_bh(&log->instances_lock); |
0597f2680 [NETFILTER]: Add ... |
709 |
for (i = 0; i < INSTANCE_BUCKETS; i++) { |
b67bfe0d4 hlist: drop the n... |
710 |
struct hlist_node *t2; |
0597f2680 [NETFILTER]: Add ... |
711 |
struct nfulnl_instance *inst; |
9368a53c4 netfilter: nfnetl... |
712 |
struct hlist_head *head = &log->instance_table[i]; |
0597f2680 [NETFILTER]: Add ... |
713 |
|
b67bfe0d4 hlist: drop the n... |
714 |
hlist_for_each_entry_safe(inst, t2, head, hlist) { |
9368a53c4 netfilter: nfnetl... |
715 |
if (n->portid == inst->peer_portid) |
0597f2680 [NETFILTER]: Add ... |
716 717 718 |
__instance_destroy(inst); } } |
9368a53c4 netfilter: nfnetl... |
719 |
spin_unlock_bh(&log->instances_lock); |
0597f2680 [NETFILTER]: Add ... |
720 721 722 723 724 725 726 727 728 729 |
} return NOTIFY_DONE; } static struct notifier_block nfulnl_rtnl_notifier = { .notifier_call = nfulnl_rcv_nl_event, }; static int nfulnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb, |
399383246 netfilter: nfnetl... |
730 731 |
const struct nlmsghdr *nlh, const struct nlattr * const nfqa[]) |
0597f2680 [NETFILTER]: Add ... |
732 733 734 |
{ return -ENOTSUPP; } |
ca735b3aa netfilter: use a ... |
735 |
static struct nf_logger nfulnl_logger __read_mostly = { |
0597f2680 [NETFILTER]: Add ... |
736 737 738 739 |
.name = "nfnetlink_log", .logfn = &nfulnl_log_packet, .me = THIS_MODULE, }; |
fd8281ada [NETFILTER]: nfne... |
740 741 742 743 744 745 746 |
static const struct nla_policy nfula_cfg_policy[NFULA_CFG_MAX+1] = { [NFULA_CFG_CMD] = { .len = sizeof(struct nfulnl_msg_config_cmd) }, [NFULA_CFG_MODE] = { .len = sizeof(struct nfulnl_msg_config_mode) }, [NFULA_CFG_TIMEOUT] = { .type = NLA_U32 }, [NFULA_CFG_QTHRESH] = { .type = NLA_U32 }, [NFULA_CFG_NLBUFSIZ] = { .type = NLA_U32 }, [NFULA_CFG_FLAGS] = { .type = NLA_U16 }, |
0597f2680 [NETFILTER]: Add ... |
747 748 749 750 |
}; static int nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, |
399383246 netfilter: nfnetl... |
751 752 |
const struct nlmsghdr *nlh, const struct nlattr * const nfula[]) |
0597f2680 [NETFILTER]: Add ... |
753 |
{ |
d550d0958 netfilter: nfnetl... |
754 |
struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
0597f2680 [NETFILTER]: Add ... |
755 756 |
u_int16_t group_num = ntohs(nfmsg->res_id); struct nfulnl_instance *inst; |
b7047a1c8 [NETFILTER]: nfne... |
757 |
struct nfulnl_msg_config_cmd *cmd = NULL; |
30e0c6a6b netfilter: nf_log... |
758 |
struct net *net = sock_net(ctnl); |
9368a53c4 netfilter: nfnetl... |
759 |
struct nfnl_log_net *log = nfnl_log_pernet(net); |
0597f2680 [NETFILTER]: Add ... |
760 |
int ret = 0; |
b7047a1c8 [NETFILTER]: nfne... |
761 762 763 764 765 766 767 |
if (nfula[NFULA_CFG_CMD]) { u_int8_t pf = nfmsg->nfgen_family; cmd = nla_data(nfula[NFULA_CFG_CMD]); /* Commands without queue context */ switch (cmd->command) { case NFULNL_CFG_CMD_PF_BIND: |
30e0c6a6b netfilter: nf_log... |
768 |
return nf_log_bind_pf(net, pf, &nfulnl_logger); |
b7047a1c8 [NETFILTER]: nfne... |
769 |
case NFULNL_CFG_CMD_PF_UNBIND: |
30e0c6a6b netfilter: nf_log... |
770 |
nf_log_unbind_pf(net, pf); |
b7047a1c8 [NETFILTER]: nfne... |
771 772 773 |
return 0; } } |
9368a53c4 netfilter: nfnetl... |
774 |
inst = instance_lookup_get(log, group_num); |
15e473046 netlink: Rename p... |
775 |
if (inst && inst->peer_portid != NETLINK_CB(skb).portid) { |
c0506365a [NETFILTER]: nfne... |
776 777 778 |
ret = -EPERM; goto out_put; } |
b7047a1c8 [NETFILTER]: nfne... |
779 |
if (cmd != NULL) { |
0597f2680 [NETFILTER]: Add ... |
780 781 782 783 784 785 |
switch (cmd->command) { case NFULNL_CFG_CMD_BIND: if (inst) { ret = -EBUSY; goto out_put; } |
9368a53c4 netfilter: nfnetl... |
786 |
inst = instance_create(net, group_num, |
15e473046 netlink: Rename p... |
787 |
NETLINK_CB(skb).portid, |
e32123e59 netlink: rename s... |
788 |
sk_user_ns(NETLINK_CB(skb).sk)); |
baab2ce7d [NETFILTER]: nfne... |
789 790 |
if (IS_ERR(inst)) { ret = PTR_ERR(inst); |
f414c16c0 [NETFILTER]: nfne... |
791 |
goto out; |
0597f2680 [NETFILTER]: Add ... |
792 793 794 795 796 |
} break; case NFULNL_CFG_CMD_UNBIND: if (!inst) { ret = -ENODEV; |
f414c16c0 [NETFILTER]: nfne... |
797 |
goto out; |
0597f2680 [NETFILTER]: Add ... |
798 |
} |
9368a53c4 netfilter: nfnetl... |
799 |
instance_destroy(log, inst); |
a49c65037 netfilter: nfnetl... |
800 |
goto out_put; |
0597f2680 [NETFILTER]: Add ... |
801 |
default: |
cd21f0ac4 [NETFILTER]: nfne... |
802 |
ret = -ENOTSUPP; |
0597f2680 [NETFILTER]: Add ... |
803 804 |
break; } |
0597f2680 [NETFILTER]: Add ... |
805 |
} |
df6fb868d [NETFILTER]: nfne... |
806 |
if (nfula[NFULA_CFG_MODE]) { |
0597f2680 [NETFILTER]: Add ... |
807 |
struct nfulnl_msg_config_mode *params; |
df6fb868d [NETFILTER]: nfne... |
808 |
params = nla_data(nfula[NFULA_CFG_MODE]); |
0597f2680 [NETFILTER]: Add ... |
809 |
|
c0506365a [NETFILTER]: nfne... |
810 811 812 813 |
if (!inst) { ret = -ENODEV; goto out; } |
0597f2680 [NETFILTER]: Add ... |
814 |
nfulnl_set_mode(inst, params->copy_mode, |
d1208b999 [NETFILTER] bug: ... |
815 |
ntohl(params->copy_range)); |
0597f2680 [NETFILTER]: Add ... |
816 |
} |
df6fb868d [NETFILTER]: nfne... |
817 |
if (nfula[NFULA_CFG_TIMEOUT]) { |
0dfedd287 [NETFILTER]: nfne... |
818 |
__be32 timeout = nla_get_be32(nfula[NFULA_CFG_TIMEOUT]); |
0597f2680 [NETFILTER]: Add ... |
819 |
|
c0506365a [NETFILTER]: nfne... |
820 821 822 823 |
if (!inst) { ret = -ENODEV; goto out; } |
0597f2680 [NETFILTER]: Add ... |
824 825 |
nfulnl_set_timeout(inst, ntohl(timeout)); } |
df6fb868d [NETFILTER]: nfne... |
826 |
if (nfula[NFULA_CFG_NLBUFSIZ]) { |
0dfedd287 [NETFILTER]: nfne... |
827 |
__be32 nlbufsiz = nla_get_be32(nfula[NFULA_CFG_NLBUFSIZ]); |
0597f2680 [NETFILTER]: Add ... |
828 |
|
c0506365a [NETFILTER]: nfne... |
829 830 831 832 |
if (!inst) { ret = -ENODEV; goto out; } |
0597f2680 [NETFILTER]: Add ... |
833 834 |
nfulnl_set_nlbufsiz(inst, ntohl(nlbufsiz)); } |
df6fb868d [NETFILTER]: nfne... |
835 |
if (nfula[NFULA_CFG_QTHRESH]) { |
0dfedd287 [NETFILTER]: nfne... |
836 |
__be32 qthresh = nla_get_be32(nfula[NFULA_CFG_QTHRESH]); |
0597f2680 [NETFILTER]: Add ... |
837 |
|
c0506365a [NETFILTER]: nfne... |
838 839 840 841 |
if (!inst) { ret = -ENODEV; goto out; } |
0597f2680 [NETFILTER]: Add ... |
842 843 |
nfulnl_set_qthresh(inst, ntohl(qthresh)); } |
df6fb868d [NETFILTER]: nfne... |
844 |
if (nfula[NFULA_CFG_FLAGS]) { |
0dfedd287 [NETFILTER]: nfne... |
845 |
__be16 flags = nla_get_be16(nfula[NFULA_CFG_FLAGS]); |
c0506365a [NETFILTER]: nfne... |
846 847 848 849 850 |
if (!inst) { ret = -ENODEV; goto out; } |
ee433530d [NETFILTER]: nfne... |
851 |
nfulnl_set_flags(inst, ntohs(flags)); |
0af5f6c1e [NETFILTER] nfnet... |
852 |
} |
0597f2680 [NETFILTER]: Add ... |
853 854 |
out_put: instance_put(inst); |
dd16704eb [NETFILTER]: nfne... |
855 |
out: |
0597f2680 [NETFILTER]: Add ... |
856 857 |
return ret; } |
7c8d4cb41 [NETFILTER]: nfne... |
858 |
static const struct nfnl_callback nfulnl_cb[NFULNL_MSG_MAX] = { |
0597f2680 [NETFILTER]: Add ... |
859 |
[NFULNL_MSG_PACKET] = { .call = nfulnl_recv_unsupp, |
37d2e7a20 [NETFILTER] nfnet... |
860 |
.attr_count = NFULA_MAX, }, |
0597f2680 [NETFILTER]: Add ... |
861 |
[NFULNL_MSG_CONFIG] = { .call = nfulnl_recv_config, |
fd8281ada [NETFILTER]: nfne... |
862 863 |
.attr_count = NFULA_CFG_MAX, .policy = nfula_cfg_policy }, |
0597f2680 [NETFILTER]: Add ... |
864 |
}; |
7c8d4cb41 [NETFILTER]: nfne... |
865 |
static const struct nfnetlink_subsystem nfulnl_subsys = { |
0597f2680 [NETFILTER]: Add ... |
866 867 868 |
.name = "log", .subsys_id = NFNL_SUBSYS_ULOG, .cb_count = NFULNL_MSG_MAX, |
0597f2680 [NETFILTER]: Add ... |
869 870 871 872 873 |
.cb = nfulnl_cb, }; #ifdef CONFIG_PROC_FS struct iter_state { |
9368a53c4 netfilter: nfnetl... |
874 |
struct seq_net_private p; |
0597f2680 [NETFILTER]: Add ... |
875 876 |
unsigned int bucket; }; |
9368a53c4 netfilter: nfnetl... |
877 |
static struct hlist_node *get_first(struct net *net, struct iter_state *st) |
0597f2680 [NETFILTER]: Add ... |
878 |
{ |
9368a53c4 netfilter: nfnetl... |
879 |
struct nfnl_log_net *log; |
0597f2680 [NETFILTER]: Add ... |
880 881 |
if (!st) return NULL; |
9368a53c4 netfilter: nfnetl... |
882 |
log = nfnl_log_pernet(net); |
0597f2680 [NETFILTER]: Add ... |
883 |
for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) { |
9368a53c4 netfilter: nfnetl... |
884 885 886 887 |
struct hlist_head *head = &log->instance_table[st->bucket]; if (!hlist_empty(head)) return rcu_dereference_bh(hlist_first_rcu(head)); |
0597f2680 [NETFILTER]: Add ... |
888 889 890 |
} return NULL; } |
9368a53c4 netfilter: nfnetl... |
891 892 |
static struct hlist_node *get_next(struct net *net, struct iter_state *st, struct hlist_node *h) |
0597f2680 [NETFILTER]: Add ... |
893 |
{ |
0e60ebe04 netfilter: add __... |
894 |
h = rcu_dereference_bh(hlist_next_rcu(h)); |
0597f2680 [NETFILTER]: Add ... |
895 |
while (!h) { |
9368a53c4 netfilter: nfnetl... |
896 897 |
struct nfnl_log_net *log; struct hlist_head *head; |
0597f2680 [NETFILTER]: Add ... |
898 899 |
if (++st->bucket >= INSTANCE_BUCKETS) return NULL; |
9368a53c4 netfilter: nfnetl... |
900 901 902 |
log = nfnl_log_pernet(net); head = &log->instance_table[st->bucket]; h = rcu_dereference_bh(hlist_first_rcu(head)); |
0597f2680 [NETFILTER]: Add ... |
903 904 905 |
} return h; } |
9368a53c4 netfilter: nfnetl... |
906 907 |
static struct hlist_node *get_idx(struct net *net, struct iter_state *st, loff_t pos) |
0597f2680 [NETFILTER]: Add ... |
908 909 |
{ struct hlist_node *head; |
9368a53c4 netfilter: nfnetl... |
910 |
head = get_first(net, st); |
0597f2680 [NETFILTER]: Add ... |
911 912 |
if (head) |
9368a53c4 netfilter: nfnetl... |
913 |
while (pos && (head = get_next(net, st, head))) |
0597f2680 [NETFILTER]: Add ... |
914 915 916 |
pos--; return pos ? NULL : head; } |
9368a53c4 netfilter: nfnetl... |
917 |
static void *seq_start(struct seq_file *s, loff_t *pos) |
bed1be208 netfilter: nfnetl... |
918 |
__acquires(rcu_bh) |
0597f2680 [NETFILTER]: Add ... |
919 |
{ |
bed1be208 netfilter: nfnetl... |
920 |
rcu_read_lock_bh(); |
9368a53c4 netfilter: nfnetl... |
921 |
return get_idx(seq_file_net(s), s->private, *pos); |
0597f2680 [NETFILTER]: Add ... |
922 923 924 925 926 |
} static void *seq_next(struct seq_file *s, void *v, loff_t *pos) { (*pos)++; |
9368a53c4 netfilter: nfnetl... |
927 |
return get_next(seq_file_net(s), s->private, v); |
0597f2680 [NETFILTER]: Add ... |
928 929 930 |
} static void seq_stop(struct seq_file *s, void *v) |
bed1be208 netfilter: nfnetl... |
931 |
__releases(rcu_bh) |
0597f2680 [NETFILTER]: Add ... |
932 |
{ |
bed1be208 netfilter: nfnetl... |
933 |
rcu_read_unlock_bh(); |
0597f2680 [NETFILTER]: Add ... |
934 935 936 937 938 |
} static int seq_show(struct seq_file *s, void *v) { const struct nfulnl_instance *inst = v; |
601e68e10 [NETFILTER]: Fix ... |
939 940 |
return seq_printf(s, "%5d %6d %5d %1d %5d %6d %2d ", |
0597f2680 [NETFILTER]: Add ... |
941 |
inst->group_num, |
15e473046 netlink: Rename p... |
942 |
inst->peer_portid, inst->qlen, |
0597f2680 [NETFILTER]: Add ... |
943 944 945 |
inst->copy_mode, inst->copy_range, inst->flushtimeout, atomic_read(&inst->use)); } |
56b3d975b [NET]: Make all i... |
946 |
static const struct seq_operations nful_seq_ops = { |
0597f2680 [NETFILTER]: Add ... |
947 948 949 950 951 952 953 954 |
.start = seq_start, .next = seq_next, .stop = seq_stop, .show = seq_show, }; static int nful_open(struct inode *inode, struct file *file) { |
9368a53c4 netfilter: nfnetl... |
955 956 |
return seq_open_net(inode, file, &nful_seq_ops, sizeof(struct iter_state)); |
0597f2680 [NETFILTER]: Add ... |
957 |
} |
da7071d7e [PATCH] mark stru... |
958 |
static const struct file_operations nful_file_ops = { |
0597f2680 [NETFILTER]: Add ... |
959 960 961 962 |
.owner = THIS_MODULE, .open = nful_open, .read = seq_read, .llseek = seq_lseek, |
9368a53c4 netfilter: nfnetl... |
963 |
.release = seq_release_net, |
0597f2680 [NETFILTER]: Add ... |
964 965 966 |
}; #endif /* PROC_FS */ |
9368a53c4 netfilter: nfnetl... |
967 |
static int __net_init nfnl_log_net_init(struct net *net) |
0597f2680 [NETFILTER]: Add ... |
968 |
{ |
9368a53c4 netfilter: nfnetl... |
969 970 |
unsigned int i; struct nfnl_log_net *log = nfnl_log_pernet(net); |
601e68e10 [NETFILTER]: Fix ... |
971 |
|
0597f2680 [NETFILTER]: Add ... |
972 |
for (i = 0; i < INSTANCE_BUCKETS; i++) |
9368a53c4 netfilter: nfnetl... |
973 974 975 976 977 978 979 980 981 982 983 984 985 |
INIT_HLIST_HEAD(&log->instance_table[i]); spin_lock_init(&log->instances_lock); #ifdef CONFIG_PROC_FS if (!proc_create("nfnetlink_log", 0440, net->nf.proc_netfilter, &nful_file_ops)) return -ENOMEM; #endif return 0; } static void __net_exit nfnl_log_net_exit(struct net *net) { |
e778f56e2 netfilter: nf_{lo... |
986 |
#ifdef CONFIG_PROC_FS |
9368a53c4 netfilter: nfnetl... |
987 |
remove_proc_entry("nfnetlink_log", net->nf.proc_netfilter); |
e778f56e2 netfilter: nf_{lo... |
988 |
#endif |
9368a53c4 netfilter: nfnetl... |
989 990 991 992 993 994 995 996 997 998 999 1000 |
} static struct pernet_operations nfnl_log_net_ops = { .init = nfnl_log_net_init, .exit = nfnl_log_net_exit, .id = &nfnl_log_net_id, .size = sizeof(struct nfnl_log_net), }; static int __init nfnetlink_log_init(void) { int status = -ENOMEM; |
601e68e10 [NETFILTER]: Fix ... |
1001 |
|
0597f2680 [NETFILTER]: Add ... |
1002 1003 1004 1005 1006 1007 1008 1009 |
/* it's not really all that important to have a random value, so * we can do this from the init function, even if there hasn't * been that much entropy yet */ get_random_bytes(&hash_init, sizeof(hash_init)); netlink_register_notifier(&nfulnl_rtnl_notifier); status = nfnetlink_subsys_register(&nfulnl_subsys); if (status < 0) { |
9368a53c4 netfilter: nfnetl... |
1010 1011 |
pr_err("log: failed to create netlink socket "); |
0597f2680 [NETFILTER]: Add ... |
1012 1013 |
goto cleanup_netlink_notifier; } |
ca735b3aa netfilter: use a ... |
1014 1015 |
status = nf_log_register(NFPROTO_UNSPEC, &nfulnl_logger); if (status < 0) { |
9368a53c4 netfilter: nfnetl... |
1016 1017 |
pr_err("log: failed to register logger "); |
ca735b3aa netfilter: use a ... |
1018 1019 |
goto cleanup_subsys; } |
9368a53c4 netfilter: nfnetl... |
1020 1021 1022 1023 |
status = register_pernet_subsys(&nfnl_log_net_ops); if (status < 0) { pr_err("log: failed to register pernet ops "); |
ca735b3aa netfilter: use a ... |
1024 |
goto cleanup_logger; |
6fc09f10f netfilter: nfnetl... |
1025 |
} |
0597f2680 [NETFILTER]: Add ... |
1026 |
return status; |
ca735b3aa netfilter: use a ... |
1027 1028 |
cleanup_logger: nf_log_unregister(&nfulnl_logger); |
0597f2680 [NETFILTER]: Add ... |
1029 |
cleanup_subsys: |
0597f2680 [NETFILTER]: Add ... |
1030 1031 1032 1033 1034 |
nfnetlink_subsys_unregister(&nfulnl_subsys); cleanup_netlink_notifier: netlink_unregister_notifier(&nfulnl_rtnl_notifier); return status; } |
65b4b4e81 [NETFILTER]: Rena... |
1035 |
static void __exit nfnetlink_log_fini(void) |
0597f2680 [NETFILTER]: Add ... |
1036 |
{ |
9368a53c4 netfilter: nfnetl... |
1037 |
unregister_pernet_subsys(&nfnl_log_net_ops); |
e92ad99c7 [NETFILTER]: nf_l... |
1038 |
nf_log_unregister(&nfulnl_logger); |
32292a7ff [NETFILTER]: Fix ... |
1039 1040 |
nfnetlink_subsys_unregister(&nfulnl_subsys); netlink_unregister_notifier(&nfulnl_rtnl_notifier); |
0597f2680 [NETFILTER]: Add ... |
1041 1042 1043 1044 1045 |
} MODULE_DESCRIPTION("netfilter userspace logging"); MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); MODULE_LICENSE("GPL"); |
f682faefb [NETFILTER]: fix ... |
1046 |
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ULOG); |
0597f2680 [NETFILTER]: Add ... |
1047 |
|
65b4b4e81 [NETFILTER]: Rena... |
1048 1049 |
module_init(nfnetlink_log_init); module_exit(nfnetlink_log_fini); |