diff options
Diffstat (limited to 'net/netfilter/nfnetlink_log.c')
-rw-r--r-- | net/netfilter/nfnetlink_log.c | 108 |
1 files changed, 32 insertions, 76 deletions
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 5cb30ebba0f..e32e30e7a17 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -10,11 +10,6 @@ * 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. - * - * 2006-01-26 Harald Welte <laforge@netfilter.org> - * - Add optional local and global sequence number to detect lost - * events from userspace - * */ #include <linux/module.h> #include <linux/skbuff.h> @@ -163,10 +158,7 @@ instance_create(u_int16_t group_num, int pid) /* needs to be two, since we _put() after creation */ atomic_set(&inst->use, 2); - init_timer(&inst->timer); - inst->timer.function = nfulnl_timer; - inst->timer.data = (unsigned long)inst; - /* don't start timer yet. (re)start it with every packet */ + setup_timer(&inst->timer, nfulnl_timer, (unsigned long)inst); inst->peer_pid = pid; inst->group_num = group_num; @@ -200,20 +192,14 @@ out_unlock: static int __nfulnl_send(struct nfulnl_instance *inst); static void -_instance_destroy2(struct nfulnl_instance *inst, int lock) +__instance_destroy(struct nfulnl_instance *inst) { /* first pull it out of the global list */ - if (lock) - write_lock_bh(&instances_lock); - UDEBUG("removing instance %p (queuenum=%u) from hash\n", inst, inst->group_num); hlist_del(&inst->hlist); - if (lock) - write_unlock_bh(&instances_lock); - /* then flush all pending packets from skb */ spin_lock_bh(&inst->lock); @@ -235,15 +221,11 @@ _instance_destroy2(struct nfulnl_instance *inst, int lock) } static inline void -__instance_destroy(struct nfulnl_instance *inst) -{ - _instance_destroy2(inst, 0); -} - -static inline void instance_destroy(struct nfulnl_instance *inst) { - _instance_destroy2(inst, 1); + write_lock_bh(&instances_lock); + __instance_destroy(inst); + write_unlock_bh(&instances_lock); } static int @@ -365,9 +347,6 @@ __nfulnl_send(struct nfulnl_instance *inst) { int status; - if (!inst->skb) - return 0; - if (inst->qlen > 1) inst->lastnlh->nlmsg_type = NLMSG_DONE; @@ -391,7 +370,8 @@ static void nfulnl_timer(unsigned long data) UDEBUG("timer function called, flushing buffer\n"); spin_lock_bh(&inst->lock); - __nfulnl_send(inst); + if (inst->skb) + __nfulnl_send(inst); spin_unlock_bh(&inst->lock); instance_put(inst); } @@ -409,15 +389,14 @@ __build_packet_message(struct nfulnl_instance *inst, const struct nf_loginfo *li, const char *prefix, unsigned int plen) { - unsigned char *old_tail; struct nfulnl_msg_packet_hdr pmsg; struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; __be32 tmp_uint; + sk_buff_data_t old_tail = inst->skb->tail; UDEBUG("entered\n"); - old_tail = inst->skb->tail; nlh = NLMSG_PUT(inst->skb, 0, 0, NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET, sizeof(struct nfgenmsg)); @@ -509,11 +488,11 @@ __build_packet_message(struct nfulnl_instance *inst, NFA_PUT(inst->skb, NFULA_HWADDR, sizeof(phw), &phw); } - if (skb->tstamp.off_sec) { + if (skb->tstamp.tv64) { struct nfulnl_msg_packet_timestamp ts; - - ts.sec = cpu_to_be64(skb->tstamp.off_sec); - ts.usec = cpu_to_be64(skb->tstamp.off_usec); + struct timeval tv = ktime_to_timeval(skb->tstamp); + ts.sec = cpu_to_be64(tv.tv_sec); + ts.usec = cpu_to_be64(tv.tv_usec); NFA_PUT(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts); } @@ -596,7 +575,6 @@ nfulnl_log_packet(unsigned int pf, struct nfulnl_instance *inst; const struct nf_loginfo *li; unsigned int qthreshold; - unsigned int nlbufsiz; unsigned int plen; if (li_user && li_user->type == NF_LOG_TYPE_ULOG) @@ -606,12 +584,7 @@ nfulnl_log_packet(unsigned int pf, inst = instance_lookup_get(li->u.ulog.group); if (!inst) - inst = instance_lookup_get(0); - if (!inst) { - PRINTR("nfnetlink_log: trying to log packet, " - "but no instance for group %u\n", li->u.ulog.group); return; - } plen = 0; if (prefix) @@ -667,24 +640,11 @@ nfulnl_log_packet(unsigned int pf, break; default: - spin_unlock_bh(&inst->lock); - instance_put(inst); - return; + goto unlock_and_release; } - if (size > inst->nlbufsiz) - nlbufsiz = size; - else - nlbufsiz = inst->nlbufsiz; - - if (!inst->skb) { - if (!(inst->skb = nfulnl_alloc_skb(nlbufsiz, size))) { - UDEBUG("error in nfulnl_alloc_skb(%u, %u)\n", - inst->nlbufsiz, size); - goto alloc_failure; - } - } else if (inst->qlen >= qthreshold || - size > skb_tailroom(inst->skb)) { + if (inst->qlen >= qthreshold || + (inst->skb && size > skb_tailroom(inst->skb))) { /* either the queue len is too high or we don't have * enough room in the skb left. flush to userspace. */ UDEBUG("flushing old skb\n"); @@ -693,12 +653,12 @@ nfulnl_log_packet(unsigned int pf, if (del_timer(&inst->timer)) instance_put(inst); __nfulnl_send(inst); + } - if (!(inst->skb = nfulnl_alloc_skb(nlbufsiz, size))) { - UDEBUG("error in nfulnl_alloc_skb(%u, %u)\n", - inst->nlbufsiz, size); + if (!inst->skb) { + inst->skb = nfulnl_alloc_skb(inst->nlbufsiz, size); + if (!inst->skb) goto alloc_failure; - } } UDEBUG("qlen %d, qthreshold %d\n", inst->qlen, qthreshold); @@ -760,7 +720,7 @@ static struct notifier_block nfulnl_rtnl_notifier = { static int nfulnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb, - struct nlmsghdr *nlh, struct nfattr *nfqa[], int *errp) + struct nlmsghdr *nlh, struct nfattr *nfqa[]) { return -ENOTSUPP; } @@ -798,7 +758,7 @@ static const int nfula_cfg_min[NFULA_CFG_MAX] = { static int nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - struct nlmsghdr *nlh, struct nfattr *nfula[], int *errp) + struct nlmsghdr *nlh, struct nfattr *nfula[]) { struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); u_int16_t group_num = ntohs(nfmsg->res_id); @@ -830,13 +790,13 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, NETLINK_CB(skb).pid); if (!inst) { ret = -EINVAL; - goto out_put; + goto out; } break; case NFULNL_CFG_CMD_UNBIND: if (!inst) { ret = -ENODEV; - goto out_put; + goto out; } if (inst->peer_pid != NETLINK_CB(skb).pid) { @@ -845,7 +805,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, } instance_destroy(inst); - break; + goto out; case NFULNL_CFG_CMD_PF_BIND: UDEBUG("registering log handler for pf=%u\n", pf); ret = nf_log_register(pf, &nfulnl_logger); @@ -869,7 +829,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, "group=%u pid=%u =>ENOENT\n", group_num, NETLINK_CB(skb).pid); ret = -ENOENT; - goto out_put; + goto out; } if (inst->peer_pid != NETLINK_CB(skb).pid) { @@ -939,10 +899,8 @@ struct iter_state { unsigned int bucket; }; -static struct hlist_node *get_first(struct seq_file *seq) +static struct hlist_node *get_first(struct iter_state *st) { - struct iter_state *st = seq->private; - if (!st) return NULL; @@ -953,10 +911,8 @@ static struct hlist_node *get_first(struct seq_file *seq) return NULL; } -static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h) +static struct hlist_node *get_next(struct iter_state *st, struct hlist_node *h) { - struct iter_state *st = seq->private; - h = h->next; while (!h) { if (++st->bucket >= INSTANCE_BUCKETS) @@ -967,13 +923,13 @@ static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h) return h; } -static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos) +static struct hlist_node *get_idx(struct iter_state *st, loff_t pos) { struct hlist_node *head; - head = get_first(seq); + head = get_first(st); if (head) - while (pos && (head = get_next(seq, head))) + while (pos && (head = get_next(st, head))) pos--; return pos ? NULL : head; } @@ -981,13 +937,13 @@ static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos) static void *seq_start(struct seq_file *seq, loff_t *pos) { read_lock_bh(&instances_lock); - return get_idx(seq, *pos); + return get_idx(seq->private, *pos); } static void *seq_next(struct seq_file *s, void *v, loff_t *pos) { (*pos)++; - return get_next(s, v); + return get_next(s->private, v); } static void seq_stop(struct seq_file *s, void *v) |