case NFQNL_COPY_PACKET:
queue->copy_mode = mode;
- /* we're using struct nfattr which has 16bit nfa_len */
+ /* we're using struct nlattr which has 16bit nla_len */
if (range > 0xffff)
queue->copy_range = 0xffff;
else
QDEBUG("entered\n");
- /* all macros expand to constant values at compile time */
- size = NLMSG_SPACE(sizeof(struct nfgenmsg)) +
- + NFA_SPACE(sizeof(struct nfqnl_msg_packet_hdr))
- + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
- + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
+ size = NLMSG_ALIGN(sizeof(struct nfgenmsg))
+ + nla_total_size(sizeof(struct nfqnl_msg_packet_hdr))
+ + nla_total_size(sizeof(u_int32_t)) /* ifindex */
+ + nla_total_size(sizeof(u_int32_t)) /* ifindex */
#ifdef CONFIG_BRIDGE_NETFILTER
- + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
- + NFA_SPACE(sizeof(u_int32_t)) /* ifindex */
+ + nla_total_size(sizeof(u_int32_t)) /* ifindex */
+ + nla_total_size(sizeof(u_int32_t)) /* ifindex */
#endif
- + NFA_SPACE(sizeof(u_int32_t)) /* mark */
- + NFA_SPACE(sizeof(struct nfqnl_msg_packet_hw))
- + NFA_SPACE(sizeof(struct nfqnl_msg_packet_timestamp));
+ + nla_total_size(sizeof(u_int32_t)) /* mark */
+ + nla_total_size(sizeof(struct nfqnl_msg_packet_hw))
+ + nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp));
outdev = entinf->outdev;
else
data_len = queue->copy_range;
- size += NFA_SPACE(data_len);
+ size += nla_total_size(data_len);
break;
default:
pmsg.hw_protocol = entskb->protocol;
pmsg.hook = entinf->hook;
- NFA_PUT(skb, NFQA_PACKET_HDR, sizeof(pmsg), &pmsg);
+ NLA_PUT(skb, NFQA_PACKET_HDR, sizeof(pmsg), &pmsg);
indev = entinf->indev;
if (indev) {
tmp_uint = htonl(indev->ifindex);
#ifndef CONFIG_BRIDGE_NETFILTER
- NFA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint), &tmp_uint);
+ NLA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint), &tmp_uint);
#else
if (entinf->pf == PF_BRIDGE) {
/* Case 1: indev is physical input device, we need to
* look for bridge group (when called from
* netfilter_bridge) */
- NFA_PUT(skb, NFQA_IFINDEX_PHYSINDEV, sizeof(tmp_uint),
+ NLA_PUT(skb, NFQA_IFINDEX_PHYSINDEV, sizeof(tmp_uint),
&tmp_uint);
/* this is the bridge group "brX" */
tmp_uint = htonl(indev->br_port->br->dev->ifindex);
- NFA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint),
+ NLA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint),
&tmp_uint);
} else {
/* Case 2: indev is bridge group, we need to look for
* physical device (when called from ipv4) */
- NFA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint),
+ NLA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint),
&tmp_uint);
if (entskb->nf_bridge
&& entskb->nf_bridge->physindev) {
tmp_uint = htonl(entskb->nf_bridge->physindev->ifindex);
- NFA_PUT(skb, NFQA_IFINDEX_PHYSINDEV,
+ NLA_PUT(skb, NFQA_IFINDEX_PHYSINDEV,
sizeof(tmp_uint), &tmp_uint);
}
}
if (outdev) {
tmp_uint = htonl(outdev->ifindex);
#ifndef CONFIG_BRIDGE_NETFILTER
- NFA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint), &tmp_uint);
+ NLA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint), &tmp_uint);
#else
if (entinf->pf == PF_BRIDGE) {
/* Case 1: outdev is physical output device, we need to
* look for bridge group (when called from
* netfilter_bridge) */
- NFA_PUT(skb, NFQA_IFINDEX_PHYSOUTDEV, sizeof(tmp_uint),
+ NLA_PUT(skb, NFQA_IFINDEX_PHYSOUTDEV, sizeof(tmp_uint),
&tmp_uint);
/* this is the bridge group "brX" */
tmp_uint = htonl(outdev->br_port->br->dev->ifindex);
- NFA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint),
+ NLA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint),
&tmp_uint);
} else {
/* Case 2: outdev is bridge group, we need to look for
* physical output device (when called from ipv4) */
- NFA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint),
+ NLA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint),
&tmp_uint);
if (entskb->nf_bridge
&& entskb->nf_bridge->physoutdev) {
tmp_uint = htonl(entskb->nf_bridge->physoutdev->ifindex);
- NFA_PUT(skb, NFQA_IFINDEX_PHYSOUTDEV,
+ NLA_PUT(skb, NFQA_IFINDEX_PHYSOUTDEV,
sizeof(tmp_uint), &tmp_uint);
}
}
if (entskb->mark) {
tmp_uint = htonl(entskb->mark);
- NFA_PUT(skb, NFQA_MARK, sizeof(u_int32_t), &tmp_uint);
+ NLA_PUT(skb, NFQA_MARK, sizeof(u_int32_t), &tmp_uint);
}
- if (indev && entskb->dev
- && entskb->dev->hard_header_parse) {
+ if (indev && entskb->dev) {
struct nfqnl_msg_packet_hw phw;
-
- int len = entskb->dev->hard_header_parse(entskb,
- phw.hw_addr);
- phw.hw_addrlen = htons(len);
- NFA_PUT(skb, NFQA_HWADDR, sizeof(phw), &phw);
+ int len = dev_parse_header(entskb, phw.hw_addr);
+ if (len) {
+ phw.hw_addrlen = htons(len);
+ NLA_PUT(skb, NFQA_HWADDR, sizeof(phw), &phw);
+ }
}
if (entskb->tstamp.tv64) {
ts.sec = cpu_to_be64(tv.tv_sec);
ts.usec = cpu_to_be64(tv.tv_usec);
- NFA_PUT(skb, NFQA_TIMESTAMP, sizeof(ts), &ts);
+ NLA_PUT(skb, NFQA_TIMESTAMP, sizeof(ts), &ts);
}
if (data_len) {
- struct nfattr *nfa;
- int size = NFA_LENGTH(data_len);
+ struct nlattr *nla;
+ int size = nla_attr_size(data_len);
- if (skb_tailroom(skb) < (int)NFA_SPACE(data_len)) {
+ if (skb_tailroom(skb) < nla_total_size(data_len)) {
printk(KERN_WARNING "nf_queue: no tailroom!\n");
goto nlmsg_failure;
}
- nfa = (struct nfattr *)skb_put(skb, NFA_ALIGN(size));
- nfa->nfa_type = NFQA_PAYLOAD;
- nfa->nfa_len = size;
+ nla = (struct nlattr *)skb_put(skb, nla_total_size(data_len));
+ nla->nla_type = NFQA_PAYLOAD;
+ nla->nla_len = size;
- if (skb_copy_bits(entskb, 0, NFA_DATA(nfa), data_len))
+ if (skb_copy_bits(entskb, 0, nla_data(nla), data_len))
BUG();
}
return skb;
nlmsg_failure:
-nfattr_failure:
+nla_put_failure:
if (skb)
kfree_skb(skb);
*errp = -EINVAL;
nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e)
{
int diff;
+ int err;
diff = data_len - e->skb->len;
if (diff < 0) {
if (data_len > 0xFFFF)
return -EINVAL;
if (diff > skb_tailroom(e->skb)) {
- struct sk_buff *newskb;
-
- newskb = skb_copy_expand(e->skb,
- skb_headroom(e->skb),
- diff,
- GFP_ATOMIC);
- if (newskb == NULL) {
+ err = pskb_expand_head(e->skb, 0,
+ diff - skb_tailroom(e->skb),
+ GFP_ATOMIC);
+ if (err) {
printk(KERN_WARNING "nf_queue: OOM "
"in mangle, dropping packet\n");
- return -ENOMEM;
+ return err;
}
- if (e->skb->sk)
- skb_set_owner_w(newskb, e->skb->sk);
- kfree_skb(e->skb);
- e->skb = newskb;
}
skb_put(e->skb, diff);
}
- if (!skb_make_writable(&e->skb, data_len))
+ if (!skb_make_writable(e->skb, data_len))
return -ENOMEM;
skb_copy_to_linear_data(e->skb, data, data_len);
e->skb->ip_summed = CHECKSUM_NONE;
{
struct net_device *dev = ptr;
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
/* Drop any packets associated with the downed device */
if (event == NETDEV_DOWN)
nfqnl_dev_drop(dev->ifindex);
struct hlist_head *head = &instance_table[i];
hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
- if (n->pid == inst->peer_pid)
+ if ((n->net == &init_net) &&
+ (n->pid == inst->peer_pid))
__instance_destroy(inst);
}
}
.notifier_call = nfqnl_rcv_nl_event,
};
-static const int nfqa_verdict_min[NFQA_MAX] = {
- [NFQA_VERDICT_HDR-1] = sizeof(struct nfqnl_msg_verdict_hdr),
- [NFQA_MARK-1] = sizeof(u_int32_t),
- [NFQA_PAYLOAD-1] = 0,
+static const struct nla_policy nfqa_verdict_policy[NFQA_MAX+1] = {
+ [NFQA_VERDICT_HDR] = { .len = sizeof(struct nfqnl_msg_verdict_hdr) },
+ [NFQA_MARK] = { .type = NLA_U32 },
+ [NFQA_PAYLOAD] = { .type = NLA_UNSPEC },
};
static int
nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
- struct nlmsghdr *nlh, struct nfattr *nfqa[])
+ struct nlmsghdr *nlh, struct nlattr *nfqa[])
{
struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
u_int16_t queue_num = ntohs(nfmsg->res_id);
struct nfqnl_queue_entry *entry;
int err;
- if (nfattr_bad_size(nfqa, NFQA_MAX, nfqa_verdict_min)) {
- QDEBUG("bad attribute size\n");
- return -EINVAL;
- }
-
queue = instance_lookup_get(queue_num);
if (!queue)
return -ENODEV;
goto err_out_put;
}
- if (!nfqa[NFQA_VERDICT_HDR-1]) {
+ if (!nfqa[NFQA_VERDICT_HDR]) {
err = -EINVAL;
goto err_out_put;
}
- vhdr = NFA_DATA(nfqa[NFQA_VERDICT_HDR-1]);
+ vhdr = nla_data(nfqa[NFQA_VERDICT_HDR]);
verdict = ntohl(vhdr->verdict);
if ((verdict & NF_VERDICT_MASK) > NF_MAX_VERDICT) {
goto err_out_put;
}
- if (nfqa[NFQA_PAYLOAD-1]) {
- if (nfqnl_mangle(NFA_DATA(nfqa[NFQA_PAYLOAD-1]),
- NFA_PAYLOAD(nfqa[NFQA_PAYLOAD-1]), entry) < 0)
+ if (nfqa[NFQA_PAYLOAD]) {
+ if (nfqnl_mangle(nla_data(nfqa[NFQA_PAYLOAD]),
+ nla_len(nfqa[NFQA_PAYLOAD]), entry) < 0)
verdict = NF_DROP;
}
- if (nfqa[NFQA_MARK-1])
+ if (nfqa[NFQA_MARK])
entry->skb->mark = ntohl(*(__be32 *)
- NFA_DATA(nfqa[NFQA_MARK-1]));
+ nla_data(nfqa[NFQA_MARK]));
issue_verdict(entry, verdict);
instance_put(queue);
static int
nfqnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb,
- struct nlmsghdr *nlh, struct nfattr *nfqa[])
+ struct nlmsghdr *nlh, struct nlattr *nfqa[])
{
return -ENOTSUPP;
}
-static const int nfqa_cfg_min[NFQA_CFG_MAX] = {
- [NFQA_CFG_CMD-1] = sizeof(struct nfqnl_msg_config_cmd),
- [NFQA_CFG_PARAMS-1] = sizeof(struct nfqnl_msg_config_params),
+static const struct nla_policy nfqa_cfg_policy[NFQA_CFG_MAX+1] = {
+ [NFQA_CFG_CMD] = { .len = sizeof(struct nfqnl_msg_config_cmd) },
+ [NFQA_CFG_PARAMS] = { .len = sizeof(struct nfqnl_msg_config_params) },
};
static struct nf_queue_handler nfqh = {
static int
nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
- struct nlmsghdr *nlh, struct nfattr *nfqa[])
+ struct nlmsghdr *nlh, struct nlattr *nfqa[])
{
struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
u_int16_t queue_num = ntohs(nfmsg->res_id);
QDEBUG("entering for msg %u\n", NFNL_MSG_TYPE(nlh->nlmsg_type));
- if (nfattr_bad_size(nfqa, NFQA_CFG_MAX, nfqa_cfg_min)) {
- QDEBUG("bad attribute size\n");
- return -EINVAL;
- }
-
queue = instance_lookup_get(queue_num);
- if (nfqa[NFQA_CFG_CMD-1]) {
+ if (nfqa[NFQA_CFG_CMD]) {
struct nfqnl_msg_config_cmd *cmd;
- cmd = NFA_DATA(nfqa[NFQA_CFG_CMD-1]);
+ cmd = nla_data(nfqa[NFQA_CFG_CMD]);
QDEBUG("found CFG_CMD\n");
switch (cmd->command) {
}
}
- if (nfqa[NFQA_CFG_PARAMS-1]) {
+ if (nfqa[NFQA_CFG_PARAMS]) {
struct nfqnl_msg_config_params *params;
if (!queue) {
ret = -ENOENT;
goto out_put;
}
- params = NFA_DATA(nfqa[NFQA_CFG_PARAMS-1]);
+ params = nla_data(nfqa[NFQA_CFG_PARAMS]);
nfqnl_set_mode(queue, params->copy_mode,
ntohl(params->copy_range));
}
- if (nfqa[NFQA_CFG_QUEUE_MAXLEN-1]) {
+ if (nfqa[NFQA_CFG_QUEUE_MAXLEN]) {
__be32 *queue_maxlen;
- queue_maxlen = NFA_DATA(nfqa[NFQA_CFG_QUEUE_MAXLEN-1]);
+ queue_maxlen = nla_data(nfqa[NFQA_CFG_QUEUE_MAXLEN]);
spin_lock_bh(&queue->lock);
queue->queue_maxlen = ntohl(*queue_maxlen);
spin_unlock_bh(&queue->lock);
return ret;
}
-static struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = {
+static const struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = {
[NFQNL_MSG_PACKET] = { .call = nfqnl_recv_unsupp,
.attr_count = NFQA_MAX, },
[NFQNL_MSG_VERDICT] = { .call = nfqnl_recv_verdict,
- .attr_count = NFQA_MAX, },
+ .attr_count = NFQA_MAX,
+ .policy = nfqa_verdict_policy },
[NFQNL_MSG_CONFIG] = { .call = nfqnl_recv_config,
- .attr_count = NFQA_CFG_MAX, },
+ .attr_count = NFQA_CFG_MAX,
+ .policy = nfqa_cfg_policy },
};
-static struct nfnetlink_subsystem nfqnl_subsys = {
+static const struct nfnetlink_subsystem nfqnl_subsys = {
.name = "nf_queue",
.subsys_id = NFNL_SUBSYS_QUEUE,
.cb_count = NFQNL_MSG_MAX,
static int nfqnl_open(struct inode *inode, struct file *file)
{
- struct seq_file *seq;
- struct iter_state *is;
- int ret;
-
- is = kzalloc(sizeof(*is), GFP_KERNEL);
- if (!is)
- return -ENOMEM;
- ret = seq_open(file, &nfqnl_seq_ops);
- if (ret < 0)
- goto out_free;
- seq = file->private_data;
- seq->private = is;
- return ret;
-out_free:
- kfree(is);
- return ret;
+ return seq_open_private(file, &nfqnl_seq_ops,
+ sizeof(struct iter_state));
}
static const struct file_operations nfqnl_file_ops = {