unsigned int qlen; /* number of nlmsgs in skb */
struct sk_buff *skb; /* pre-allocatd skb */
- struct nlmsghdr *lastnlh; /* netlink header of last msg in skb */
struct timer_list timer;
int peer_pid; /* PID of the peer process */
/* 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;
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);
instance_put(inst);
}
-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
static int
__nfulnl_send(struct nfulnl_instance *inst)
{
- int status;
-
- if (!inst->skb)
- return 0;
+ int status = -1;
if (inst->qlen > 1)
- inst->lastnlh->nlmsg_type = NLMSG_DONE;
+ NLMSG_PUT(inst->skb, 0, 0,
+ NLMSG_DONE,
+ sizeof(struct nfgenmsg));
status = nfnetlink_unicast(inst->skb, inst->peer_pid, MSG_DONTWAIT);
if (status < 0) {
inst->qlen = 0;
inst->skb = NULL;
- inst->lastnlh = NULL;
+nlmsg_failure:
return status;
}
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);
}
NFA_PUT(inst->skb, NFULA_MARK, sizeof(tmp_uint), &tmp_uint);
}
- if (indev && skb->dev && skb->dev->hard_header_parse) {
+ if (indev && skb->dev) {
struct nfulnl_msg_packet_hw phw;
- int len = skb->dev->hard_header_parse((struct sk_buff *)skb,
- phw.hw_addr);
- phw.hw_addrlen = htons(len);
- NFA_PUT(inst->skb, NFULA_HWADDR, sizeof(phw), &phw);
+ int len = dev_parse_header(skb, phw.hw_addr);
+ if (len > 0) {
+ phw.hw_addrlen = htons(len);
+ NFA_PUT(inst->skb, NFULA_HWADDR, sizeof(phw), &phw);
+ }
}
if (skb->tstamp.tv64) {
}
nlh->nlmsg_len = inst->skb->tail - old_tail;
- inst->lastnlh = nlh;
return 0;
nlmsg_failure:
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)
}
if (inst->qlen >= qthreshold ||
- (inst->skb && size > skb_tailroom(inst->skb))) {
+ (inst->skb && size >
+ skb_tailroom(inst->skb) - sizeof(struct nfgenmsg))) {
/* 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");
hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
UDEBUG("node = %p\n", inst);
- if (n->pid == inst->peer_pid)
+ if ((n->net == &init_net) &&
+ (n->pid == inst->peer_pid))
__instance_destroy(inst);
}
}
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;
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)
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;
}
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)
inst->flushtimeout, atomic_read(&inst->use));
}
-static struct seq_operations nful_seq_ops = {
+static const struct seq_operations nful_seq_ops = {
.start = seq_start,
.next = seq_next,
.stop = seq_stop,