* Authors: Jamal Hadi Salim (2002-4)
*/
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <net/sock.h>
+#include <net/netlink.h>
#include <net/pkt_sched.h>
#include <linux/tc_act/tc_pedit.h>
#include <net/tc_act/tc_pedit.h>
.lock = &pedit_lock,
};
-static int tcf_pedit_init(struct rtattr *rta, struct rtattr *est,
+static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = {
+ [TCA_PEDIT_PARMS] = { .len = sizeof(struct tc_pedit) },
+};
+
+static int tcf_pedit_init(struct nlattr *nla, struct nlattr *est,
struct tc_action *a, int ovr, int bind)
{
- struct rtattr *tb[TCA_PEDIT_MAX];
+ struct nlattr *tb[TCA_PEDIT_MAX + 1];
struct tc_pedit *parm;
- int ret = 0;
+ int ret = 0, err;
struct tcf_pedit *p;
struct tcf_common *pc;
struct tc_pedit_key *keys = NULL;
int ksize;
- if (rta == NULL || rtattr_parse_nested(tb, TCA_PEDIT_MAX, rta) < 0)
+ if (nla == NULL)
return -EINVAL;
- if (tb[TCA_PEDIT_PARMS - 1] == NULL ||
- RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm))
+ err = nla_parse_nested(tb, TCA_PEDIT_MAX, nla, pedit_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[TCA_PEDIT_PARMS] == NULL)
return -EINVAL;
- parm = RTA_DATA(tb[TCA_PEDIT_PARMS-1]);
+ parm = nla_data(tb[TCA_PEDIT_PARMS]);
ksize = parm->nkeys * sizeof(struct tc_pedit_key);
- if (RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm) + ksize)
+ if (nla_len(tb[TCA_PEDIT_PARMS]) < sizeof(*parm) + ksize)
return -EINVAL;
pc = tcf_hash_check(parm->index, a, bind, &pedit_hash_info);
return -EINVAL;
pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind,
&pedit_idx_gen, &pedit_hash_info);
- if (unlikely(!pc))
- return -ENOMEM;
+ if (IS_ERR(pc))
+ return PTR_ERR(pc);
p = to_pedit(pc);
keys = kmalloc(ksize, GFP_KERNEL);
if (keys == NULL) {
}
}
- pptr = skb->nh.raw;
+ pptr = skb_network_header(skb);
spin_lock(&p->tcf_lock);
if (tkey->offmask) {
if (skb->len > tkey->at) {
char *j = pptr + tkey->at;
- offset += ((*j & tkey->offmask) >>
- tkey->shift);
+ offset += ((*j & tkey->offmask) >>
+ tkey->shift);
} else {
goto bad;
}
printk("offset must be on 32 bit boundaries\n");
goto bad;
}
- if (skb->len < 0 ||
- (offset > 0 && offset > skb->len)) {
+ if (offset > 0 && offset > skb->len) {
printk("offset %d cant exceed pkt length %d\n",
offset, skb->len);
goto bad;
*ptr = ((*ptr & tkey->mask) ^ tkey->val);
munged++;
}
-
+
if (munged)
skb->tc_verd = SET_TC_MUNGED(skb->tc_verd);
goto done;
bad:
p->tcf_qstats.overlimits++;
done:
- p->tcf_bstats.bytes += skb->len;
+ p->tcf_bstats.bytes += qdisc_pkt_len(skb);
p->tcf_bstats.packets++;
spin_unlock(&p->tcf_lock);
return p->tcf_action;
static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
int bind, int ref)
{
- unsigned char *b = skb->tail;
+ unsigned char *b = skb_tail_pointer(skb);
struct tcf_pedit *p = a->priv;
struct tc_pedit *opt;
struct tcf_t t;
- int s;
-
+ int s;
+
s = sizeof(*opt) + p->tcfp_nkeys * sizeof(struct tc_pedit_key);
/* netlink spinlocks held above us - must use ATOMIC */
opt->refcnt = p->tcf_refcnt - ref;
opt->bindcnt = p->tcf_bindcnt - bind;
- RTA_PUT(skb, TCA_PEDIT_PARMS, s, opt);
+ NLA_PUT(skb, TCA_PEDIT_PARMS, s, opt);
t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install);
t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse);
t.expires = jiffies_to_clock_t(p->tcf_tm.expires);
- RTA_PUT(skb, TCA_PEDIT_TM, sizeof(t), &t);
+ NLA_PUT(skb, TCA_PEDIT_TM, sizeof(t), &t);
kfree(opt);
return skb->len;
-rtattr_failure:
- skb_trim(skb, b - skb->data);
+nla_put_failure:
+ nlmsg_trim(skb, b);
kfree(opt);
return -1;
}