Skip to content

Commit

Permalink
[NETLINK]: Correctly set NLM_F_MULTI without checking the pid
Browse files Browse the repository at this point in the history
This patch rectifies some rtnetlink message builders that derive the
flags from the pid. It is now explicit like the other cases
which get it right. Also fixes half a dozen dumpers which did not
set NLM_F_MULTI at all.

Signed-off-by: Jamal Hadi Salim <[email protected]>
Signed-off-by: Thomas Graf <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Jamal Hadi Salim authored and davem330 committed Jun 19, 2005
1 parent 1797754 commit b6544c0
Show file tree
Hide file tree
Showing 14 changed files with 83 additions and 78 deletions.
14 changes: 7 additions & 7 deletions net/core/neighbour.c
Original file line number Diff line number Diff line change
Expand Up @@ -1859,18 +1859,17 @@ int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
}

static int neigh_fill_info(struct sk_buff *skb, struct neighbour *n,
u32 pid, u32 seq, int event)
u32 pid, u32 seq, int event, unsigned int flags)
{
unsigned long now = jiffies;
unsigned char *b = skb->tail;
struct nda_cacheinfo ci;
int locked = 0;
u32 probes;
struct nlmsghdr *nlh = NLMSG_PUT(skb, pid, seq, event,
sizeof(struct ndmsg));
struct nlmsghdr *nlh = NLMSG_NEW(skb, pid, seq, event,
sizeof(struct ndmsg), flags);
struct ndmsg *ndm = NLMSG_DATA(nlh);

nlh->nlmsg_flags = pid ? NLM_F_MULTI : 0;
ndm->ndm_family = n->ops->family;
ndm->ndm_flags = n->flags;
ndm->ndm_type = n->type;
Expand Down Expand Up @@ -1920,7 +1919,8 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
continue;
if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq,
RTM_NEWNEIGH) <= 0) {
RTM_NEWNEIGH,
NLM_F_MULTI) <= 0) {
read_unlock_bh(&tbl->lock);
rc = -1;
goto out;
Expand Down Expand Up @@ -2329,7 +2329,7 @@ void neigh_app_ns(struct neighbour *n)
if (!skb)
return;

if (neigh_fill_info(skb, n, 0, 0, RTM_GETNEIGH) < 0) {
if (neigh_fill_info(skb, n, 0, 0, RTM_GETNEIGH, 0) < 0) {
kfree_skb(skb);
return;
}
Expand All @@ -2348,7 +2348,7 @@ static void neigh_app_notify(struct neighbour *n)
if (!skb)
return;

if (neigh_fill_info(skb, n, 0, 0, RTM_NEWNEIGH) < 0) {
if (neigh_fill_info(skb, n, 0, 0, RTM_NEWNEIGH, 0) < 0) {
kfree_skb(skb);
return;
}
Expand Down
13 changes: 8 additions & 5 deletions net/core/rtnetlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,14 +178,14 @@ int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics)


static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
int type, u32 pid, u32 seq, u32 change)
int type, u32 pid, u32 seq, u32 change,
unsigned int flags)
{
struct ifinfomsg *r;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;

nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*r));
if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*r), flags);
r = NLMSG_DATA(nlh);
r->ifi_family = AF_UNSPEC;
r->ifi_type = dev->type;
Expand Down Expand Up @@ -275,7 +275,10 @@ static int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *c
for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
if (idx < s_idx)
continue;
if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, 0) <= 0)
if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK,
NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq, 0,
NLM_F_MULTI) <= 0)
break;
}
read_unlock(&dev_base_lock);
Expand Down Expand Up @@ -449,7 +452,7 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
if (!skb)
return;

if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, change) < 0) {
if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, change, 0) < 0) {
kfree_skb(skb);
return;
}
Expand Down
9 changes: 5 additions & 4 deletions net/decnet/dn_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -716,13 +716,13 @@ static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *a
}

static int dn_dev_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
u32 pid, u32 seq, int event)
u32 pid, u32 seq, int event, unsigned int flags)
{
struct ifaddrmsg *ifm;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;

nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
ifm = NLMSG_DATA(nlh);

ifm->ifa_family = AF_DECnet;
Expand Down Expand Up @@ -755,7 +755,7 @@ static void rtmsg_ifa(int event, struct dn_ifaddr *ifa)
netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, ENOBUFS);
return;
}
if (dn_dev_fill_ifaddr(skb, ifa, 0, 0, event) < 0) {
if (dn_dev_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) {
kfree_skb(skb);
netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, EINVAL);
return;
Expand Down Expand Up @@ -790,7 +790,8 @@ static int dn_dev_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
if (dn_dev_fill_ifaddr(skb, ifa,
NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq,
RTM_NEWADDR) <= 0)
RTM_NEWADDR,
NLM_F_MULTI) <= 0)
goto done;
}
}
Expand Down
11 changes: 6 additions & 5 deletions net/decnet/dn_route.c
Original file line number Diff line number Diff line change
Expand Up @@ -1465,17 +1465,17 @@ int dn_route_input(struct sk_buff *skb)
return dn_route_input_slow(skb);
}

static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, int nowait)
static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
int event, int nowait, unsigned int flags)
{
struct dn_route *rt = (struct dn_route *)skb->dst;
struct rtmsg *r;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
struct rta_cacheinfo ci;

nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r));
nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
r = NLMSG_DATA(nlh);
nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
r->rtm_family = AF_DECnet;
r->rtm_dst_len = 16;
r->rtm_src_len = 0;
Expand Down Expand Up @@ -1596,7 +1596,7 @@ int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg)

NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;

err = dn_rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0);
err = dn_rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0, 0);

if (err == 0)
goto out_free;
Expand Down Expand Up @@ -1644,7 +1644,8 @@ int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb)
continue;
skb->dst = dst_clone(&rt->u.dst);
if (dn_rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1) <= 0) {
cb->nlh->nlmsg_seq, RTM_NEWROUTE,
1, NLM_F_MULTI) <= 0) {
dst_release(xchg(&skb->dst, NULL));
rcu_read_unlock_bh();
goto done;
Expand Down
7 changes: 4 additions & 3 deletions net/decnet/dn_rules.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,14 +342,15 @@ static struct notifier_block dn_fib_rules_notifier = {
.notifier_call = dn_fib_rules_event,
};

static int dn_fib_fill_rule(struct sk_buff *skb, struct dn_fib_rule *r, struct netlink_callback *cb)
static int dn_fib_fill_rule(struct sk_buff *skb, struct dn_fib_rule *r,
struct netlink_callback *cb, unsigned int flags)
{
struct rtmsg *rtm;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;


nlh = NLMSG_PUT(skb, NETLINK_CREDS(cb->skb)->pid, cb->nlh->nlmsg_seq, RTM_NEWRULE, sizeof(*rtm));
nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWRULE, sizeof(*rtm), flags);
rtm = NLMSG_DATA(nlh);
rtm->rtm_family = AF_DECnet;
rtm->rtm_dst_len = r->r_dst_len;
Expand Down Expand Up @@ -394,7 +395,7 @@ int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
for(r = dn_fib_rules, idx = 0; r; r = r->r_next, idx++) {
if (idx < s_idx)
continue;
if (dn_fib_fill_rule(skb, r, cb) < 0)
if (dn_fib_fill_rule(skb, r, cb, NLM_F_MULTI) < 0)
break;
}
read_unlock(&dn_fib_rules_lock);
Expand Down
8 changes: 4 additions & 4 deletions net/decnet/dn_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,13 +270,13 @@ static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern

static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
u8 tb_id, u8 type, u8 scope, void *dst, int dst_len,
struct dn_fib_info *fi)
struct dn_fib_info *fi, unsigned int flags)
{
struct rtmsg *rtm;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;

nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*rtm));
nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags);
rtm = NLMSG_DATA(nlh);
rtm->rtm_family = AF_DECnet;
rtm->rtm_dst_len = dst_len;
Expand Down Expand Up @@ -345,7 +345,7 @@ static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, int tb_id,

if (dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id,
f->fn_type, f->fn_scope, &f->fn_key, z,
DN_FIB_INFO(f)) < 0) {
DN_FIB_INFO(f), 0) < 0) {
kfree_skb(skb);
return;
}
Expand Down Expand Up @@ -377,7 +377,7 @@ static __inline__ int dn_hash_dump_bucket(struct sk_buff *skb,
tb->n,
(f->fn_state & DN_S_ZOMBIE) ? 0 : f->fn_type,
f->fn_scope, &f->fn_key, dz->dz_order,
f->fn_info) < 0) {
f->fn_info, NLM_F_MULTI) < 0) {
cb->args[3] = i;
return -1;
}
Expand Down
9 changes: 4 additions & 5 deletions net/ipv4/devinet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1030,14 +1030,13 @@ static struct notifier_block ip_netdev_notifier = {
};

static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
u32 pid, u32 seq, int event)
u32 pid, u32 seq, int event, unsigned int flags)
{
struct ifaddrmsg *ifm;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;

nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
ifm = NLMSG_DATA(nlh);
ifm->ifa_family = AF_INET;
ifm->ifa_prefixlen = ifa->ifa_prefixlen;
Expand Down Expand Up @@ -1090,7 +1089,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
continue;
if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq,
RTM_NEWADDR) <= 0) {
RTM_NEWADDR, NLM_F_MULTI) <= 0) {
rcu_read_unlock();
goto done;
}
Expand All @@ -1113,7 +1112,7 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa)

if (!skb)
netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, ENOBUFS);
else if (inet_fill_ifaddr(skb, ifa, 0, 0, event) < 0) {
else if (inet_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) {
kfree_skb(skb);
netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, EINVAL);
} else {
Expand Down
3 changes: 2 additions & 1 deletion net/ipv4/fib_hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,8 @@ fn_hash_dump_bucket(struct sk_buff *skb, struct netlink_callback *cb,
&f->fn_key,
fz->fz_order,
fa->fa_tos,
fa->fa_info) < 0) {
fa->fa_info,
NLM_F_MULTI) < 0) {
cb->args[3] = i;
return -1;
}
Expand Down
3 changes: 2 additions & 1 deletion net/ipv4/fib_lookup.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ extern int fib_nh_match(struct rtmsg *r, struct nlmsghdr *,
struct kern_rta *rta, struct fib_info *fi);
extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
u8 tb_id, u8 type, u8 scope, void *dst,
int dst_len, u8 tos, struct fib_info *fi);
int dst_len, u8 tos, struct fib_info *fi,
unsigned int);
extern void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
int z, int tb_id,
struct nlmsghdr *n, struct netlink_skb_parms *req);
Expand Down
7 changes: 4 additions & 3 deletions net/ipv4/fib_rules.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,13 +367,14 @@ static struct notifier_block fib_rules_notifier = {

static __inline__ int inet_fill_rule(struct sk_buff *skb,
struct fib_rule *r,
struct netlink_callback *cb)
struct netlink_callback *cb,
unsigned int flags)
{
struct rtmsg *rtm;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;

nlh = NLMSG_PUT(skb, NETLINK_CREDS(cb->skb)->pid, cb->nlh->nlmsg_seq, RTM_NEWRULE, sizeof(*rtm));
nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWRULE, sizeof(*rtm), flags);
rtm = NLMSG_DATA(nlh);
rtm->rtm_family = AF_INET;
rtm->rtm_dst_len = r->r_dst_len;
Expand Down Expand Up @@ -422,7 +423,7 @@ int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
for (r=fib_rules, idx=0; r; r = r->r_next, idx++) {
if (idx < s_idx)
continue;
if (inet_fill_rule(skb, r, cb) < 0)
if (inet_fill_rule(skb, r, cb, NLM_F_MULTI) < 0)
break;
}
read_unlock(&fib_rules_lock);
Expand Down
6 changes: 3 additions & 3 deletions net/ipv4/fib_semantics.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
if (fib_dump_info(skb, pid, n->nlmsg_seq, event, tb_id,
fa->fa_type, fa->fa_scope, &key, z,
fa->fa_tos,
fa->fa_info) < 0) {
fa->fa_info, 0) < 0) {
kfree_skb(skb);
return;
}
Expand Down Expand Up @@ -932,13 +932,13 @@ u32 __fib_res_prefsrc(struct fib_result *res)
int
fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos,
struct fib_info *fi)
struct fib_info *fi, unsigned int flags)
{
struct rtmsg *rtm;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;

nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*rtm));
nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags);
rtm = NLMSG_DATA(nlh);
rtm->rtm_family = AF_INET;
rtm->rtm_dst_len = dst_len;
Expand Down
11 changes: 5 additions & 6 deletions net/ipv4/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -2581,7 +2581,7 @@ int ip_route_output_key(struct rtable **rp, struct flowi *flp)
}

static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
int nowait)
int nowait, unsigned int flags)
{
struct rtable *rt = (struct rtable*)skb->dst;
struct rtmsg *r;
Expand All @@ -2591,9 +2591,8 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
#ifdef CONFIG_IP_MROUTE
struct rtattr *eptr;
#endif
nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r));
nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
r = NLMSG_DATA(nlh);
nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
r->rtm_family = AF_INET;
r->rtm_dst_len = 32;
r->rtm_src_len = 0;
Expand Down Expand Up @@ -2744,7 +2743,7 @@ int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;

err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
RTM_NEWROUTE, 0);
RTM_NEWROUTE, 0, 0);
if (!err)
goto out_free;
if (err < 0) {
Expand Down Expand Up @@ -2781,8 +2780,8 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb)
continue;
skb->dst = dst_clone(&rt->u.dst);
if (rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq,
RTM_NEWROUTE, 1) <= 0) {
cb->nlh->nlmsg_seq, RTM_NEWROUTE,
1, NLM_F_MULTI) <= 0) {
dst_release(xchg(&skb->dst, NULL));
rcu_read_unlock_bh();
goto done;
Expand Down
Loading

0 comments on commit b6544c0

Please sign in to comment.