diff options
-rw-r--r-- | net/core/rtnetlink.c | 31 | ||||
-rw-r--r-- | net/ipv6/route.c | 52 |
2 files changed, 46 insertions, 37 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index dfc58269240a..eeff0b23e944 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -188,22 +188,27 @@ void rtnl_set_sk_err(u32 group, int error) | |||
188 | 188 | ||
189 | int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) | 189 | int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) |
190 | { | 190 | { |
191 | struct rtattr *mx = (struct rtattr*)skb->tail; | 191 | struct nlattr *mx; |
192 | int i; | 192 | int i, valid = 0; |
193 | |||
194 | mx = nla_nest_start(skb, RTA_METRICS); | ||
195 | if (mx == NULL) | ||
196 | return -ENOBUFS; | ||
193 | 197 | ||
194 | RTA_PUT(skb, RTA_METRICS, 0, NULL); | 198 | for (i = 0; i < RTAX_MAX; i++) { |
195 | for (i=0; i<RTAX_MAX; i++) { | 199 | if (metrics[i]) { |
196 | if (metrics[i]) | 200 | valid++; |
197 | RTA_PUT(skb, i+1, sizeof(u32), metrics+i); | 201 | NLA_PUT_U32(skb, i+1, metrics[i]); |
202 | } | ||
198 | } | 203 | } |
199 | mx->rta_len = skb->tail - (u8*)mx; | ||
200 | if (mx->rta_len == RTA_LENGTH(0)) | ||
201 | skb_trim(skb, (u8*)mx - skb->data); | ||
202 | return 0; | ||
203 | 204 | ||
204 | rtattr_failure: | 205 | if (!valid) |
205 | skb_trim(skb, (u8*)mx - skb->data); | 206 | goto nla_put_failure; |
206 | return -1; | 207 | |
208 | return nla_nest_end(skb, mx); | ||
209 | |||
210 | nla_put_failure: | ||
211 | return nla_nest_cancel(skb, mx); | ||
207 | } | 212 | } |
208 | 213 | ||
209 | 214 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 7bcffa6ddba3..f0a66de84331 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -1936,8 +1936,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | |||
1936 | int prefix, unsigned int flags) | 1936 | int prefix, unsigned int flags) |
1937 | { | 1937 | { |
1938 | struct rtmsg *rtm; | 1938 | struct rtmsg *rtm; |
1939 | struct nlmsghdr *nlh; | 1939 | struct nlmsghdr *nlh; |
1940 | unsigned char *b = skb->tail; | ||
1941 | struct rta_cacheinfo ci; | 1940 | struct rta_cacheinfo ci; |
1942 | u32 table; | 1941 | u32 table; |
1943 | 1942 | ||
@@ -1948,8 +1947,11 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | |||
1948 | } | 1947 | } |
1949 | } | 1948 | } |
1950 | 1949 | ||
1951 | nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*rtm), flags); | 1950 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags); |
1952 | rtm = NLMSG_DATA(nlh); | 1951 | if (nlh == NULL) |
1952 | return -ENOBUFS; | ||
1953 | |||
1954 | rtm = nlmsg_data(nlh); | ||
1953 | rtm->rtm_family = AF_INET6; | 1955 | rtm->rtm_family = AF_INET6; |
1954 | rtm->rtm_dst_len = rt->rt6i_dst.plen; | 1956 | rtm->rtm_dst_len = rt->rt6i_dst.plen; |
1955 | rtm->rtm_src_len = rt->rt6i_src.plen; | 1957 | rtm->rtm_src_len = rt->rt6i_src.plen; |
@@ -1959,7 +1961,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | |||
1959 | else | 1961 | else |
1960 | table = RT6_TABLE_UNSPEC; | 1962 | table = RT6_TABLE_UNSPEC; |
1961 | rtm->rtm_table = table; | 1963 | rtm->rtm_table = table; |
1962 | RTA_PUT_U32(skb, RTA_TABLE, table); | 1964 | NLA_PUT_U32(skb, RTA_TABLE, table); |
1963 | if (rt->rt6i_flags&RTF_REJECT) | 1965 | if (rt->rt6i_flags&RTF_REJECT) |
1964 | rtm->rtm_type = RTN_UNREACHABLE; | 1966 | rtm->rtm_type = RTN_UNREACHABLE; |
1965 | else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK)) | 1967 | else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK)) |
@@ -1980,31 +1982,35 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | |||
1980 | rtm->rtm_flags |= RTM_F_CLONED; | 1982 | rtm->rtm_flags |= RTM_F_CLONED; |
1981 | 1983 | ||
1982 | if (dst) { | 1984 | if (dst) { |
1983 | RTA_PUT(skb, RTA_DST, 16, dst); | 1985 | NLA_PUT(skb, RTA_DST, 16, dst); |
1984 | rtm->rtm_dst_len = 128; | 1986 | rtm->rtm_dst_len = 128; |
1985 | } else if (rtm->rtm_dst_len) | 1987 | } else if (rtm->rtm_dst_len) |
1986 | RTA_PUT(skb, RTA_DST, 16, &rt->rt6i_dst.addr); | 1988 | NLA_PUT(skb, RTA_DST, 16, &rt->rt6i_dst.addr); |
1987 | #ifdef CONFIG_IPV6_SUBTREES | 1989 | #ifdef CONFIG_IPV6_SUBTREES |
1988 | if (src) { | 1990 | if (src) { |
1989 | RTA_PUT(skb, RTA_SRC, 16, src); | 1991 | NLA_PUT(skb, RTA_SRC, 16, src); |
1990 | rtm->rtm_src_len = 128; | 1992 | rtm->rtm_src_len = 128; |
1991 | } else if (rtm->rtm_src_len) | 1993 | } else if (rtm->rtm_src_len) |
1992 | RTA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr); | 1994 | NLA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr); |
1993 | #endif | 1995 | #endif |
1994 | if (iif) | 1996 | if (iif) |
1995 | RTA_PUT(skb, RTA_IIF, 4, &iif); | 1997 | NLA_PUT_U32(skb, RTA_IIF, iif); |
1996 | else if (dst) { | 1998 | else if (dst) { |
1997 | struct in6_addr saddr_buf; | 1999 | struct in6_addr saddr_buf; |
1998 | if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0) | 2000 | if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0) |
1999 | RTA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); | 2001 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); |
2000 | } | 2002 | } |
2003 | |||
2001 | if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0) | 2004 | if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0) |
2002 | goto rtattr_failure; | 2005 | goto nla_put_failure; |
2006 | |||
2003 | if (rt->u.dst.neighbour) | 2007 | if (rt->u.dst.neighbour) |
2004 | RTA_PUT(skb, RTA_GATEWAY, 16, &rt->u.dst.neighbour->primary_key); | 2008 | NLA_PUT(skb, RTA_GATEWAY, 16, &rt->u.dst.neighbour->primary_key); |
2009 | |||
2005 | if (rt->u.dst.dev) | 2010 | if (rt->u.dst.dev) |
2006 | RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->rt6i_dev->ifindex); | 2011 | NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); |
2007 | RTA_PUT(skb, RTA_PRIORITY, 4, &rt->rt6i_metric); | 2012 | |
2013 | NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); | ||
2008 | ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse); | 2014 | ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse); |
2009 | if (rt->rt6i_expires) | 2015 | if (rt->rt6i_expires) |
2010 | ci.rta_expires = jiffies_to_clock_t(rt->rt6i_expires - jiffies); | 2016 | ci.rta_expires = jiffies_to_clock_t(rt->rt6i_expires - jiffies); |
@@ -2016,14 +2022,12 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | |||
2016 | ci.rta_id = 0; | 2022 | ci.rta_id = 0; |
2017 | ci.rta_ts = 0; | 2023 | ci.rta_ts = 0; |
2018 | ci.rta_tsage = 0; | 2024 | ci.rta_tsage = 0; |
2019 | RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci); | 2025 | NLA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci); |
2020 | nlh->nlmsg_len = skb->tail - b; | 2026 | |
2021 | return skb->len; | 2027 | return nlmsg_end(skb, nlh); |
2022 | 2028 | ||
2023 | nlmsg_failure: | 2029 | nla_put_failure: |
2024 | rtattr_failure: | 2030 | return nlmsg_cancel(skb, nlh); |
2025 | skb_trim(skb, b - skb->data); | ||
2026 | return -1; | ||
2027 | } | 2031 | } |
2028 | 2032 | ||
2029 | int rt6_dump_route(struct rt6_info *rt, void *p_arg) | 2033 | int rt6_dump_route(struct rt6_info *rt, void *p_arg) |
@@ -2031,8 +2035,8 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg) | |||
2031 | struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) p_arg; | 2035 | struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) p_arg; |
2032 | int prefix; | 2036 | int prefix; |
2033 | 2037 | ||
2034 | if (arg->cb->nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(struct rtmsg))) { | 2038 | if (nlmsg_len(arg->cb->nlh) >= sizeof(struct rtmsg)) { |
2035 | struct rtmsg *rtm = NLMSG_DATA(arg->cb->nlh); | 2039 | struct rtmsg *rtm = nlmsg_data(arg->cb->nlh); |
2036 | prefix = (rtm->rtm_flags & RTM_F_PREFIX) != 0; | 2040 | prefix = (rtm->rtm_flags & RTM_F_PREFIX) != 0; |
2037 | } else | 2041 | } else |
2038 | prefix = 0; | 2042 | prefix = 0; |