aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Dichtel <nicolas.dichtel@6wind.com>2012-12-03 20:13:39 -0500
committerDavid S. Miller <davem@davemloft.net>2012-12-04 13:08:11 -0500
commit1eb99af52c4bc705f4042f37f255975acfc738f2 (patch)
tree7ccdd3e0185a44644cb68d9e3e1f6c46cab71943
parent9a68ac72a44ecb6d4dc4a7cadf45e1a2cd183885 (diff)
ipmr/ip6mr: allow to get unresolved cache via netlink
/proc/net/ip[6]_mr_cache allows to get all mfc entries, even if they are put in the unresolved list (mfc[6]_unres_queue). But only the table RT_TABLE_DEFAULT is displayed. This patch adds the parsing of the unresolved list when the dump is made via rtnetlink, hence each table can be checked. In IPv6, we set rtm_type in ip6mr_fill_mroute(), because in case of unresolved mfc __ip6mr_fill_mroute() will not set it. In IPv4, it is already done. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/ipmr.c21
-rw-r--r--net/ipv6/ip6mr.c22
2 files changed, 41 insertions, 2 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 91782a7634c2..084dac3bc151 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -2154,6 +2154,7 @@ static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
2154{ 2154{
2155 struct nlmsghdr *nlh; 2155 struct nlmsghdr *nlh;
2156 struct rtmsg *rtm; 2156 struct rtmsg *rtm;
2157 int err;
2157 2158
2158 nlh = nlmsg_put(skb, portid, seq, RTM_NEWROUTE, sizeof(*rtm), NLM_F_MULTI); 2159 nlh = nlmsg_put(skb, portid, seq, RTM_NEWROUTE, sizeof(*rtm), NLM_F_MULTI);
2159 if (nlh == NULL) 2160 if (nlh == NULL)
@@ -2178,7 +2179,9 @@ static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
2178 if (nla_put_be32(skb, RTA_SRC, c->mfc_origin) || 2179 if (nla_put_be32(skb, RTA_SRC, c->mfc_origin) ||
2179 nla_put_be32(skb, RTA_DST, c->mfc_mcastgrp)) 2180 nla_put_be32(skb, RTA_DST, c->mfc_mcastgrp))
2180 goto nla_put_failure; 2181 goto nla_put_failure;
2181 if (__ipmr_fill_mroute(mrt, skb, c, rtm) < 0) 2182 err = __ipmr_fill_mroute(mrt, skb, c, rtm);
2183 /* do not break the dump if cache is unresolved */
2184 if (err < 0 && err != -ENOENT)
2182 goto nla_put_failure; 2185 goto nla_put_failure;
2183 2186
2184 return nlmsg_end(skb, nlh); 2187 return nlmsg_end(skb, nlh);
@@ -2221,6 +2224,22 @@ next_entry:
2221 } 2224 }
2222 e = s_e = 0; 2225 e = s_e = 0;
2223 } 2226 }
2227 spin_lock_bh(&mfc_unres_lock);
2228 list_for_each_entry(mfc, &mrt->mfc_unres_queue, list) {
2229 if (e < s_e)
2230 goto next_entry2;
2231 if (ipmr_fill_mroute(mrt, skb,
2232 NETLINK_CB(cb->skb).portid,
2233 cb->nlh->nlmsg_seq,
2234 mfc) < 0) {
2235 spin_unlock_bh(&mfc_unres_lock);
2236 goto done;
2237 }
2238next_entry2:
2239 e++;
2240 }
2241 spin_unlock_bh(&mfc_unres_lock);
2242 e = s_e = 0;
2224 s_h = 0; 2243 s_h = 0;
2225next_table: 2244next_table:
2226 t++; 2245 t++;
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index d51b91122866..93a769891b72 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -2235,6 +2235,7 @@ static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
2235{ 2235{
2236 struct nlmsghdr *nlh; 2236 struct nlmsghdr *nlh;
2237 struct rtmsg *rtm; 2237 struct rtmsg *rtm;
2238 int err;
2238 2239
2239 nlh = nlmsg_put(skb, portid, seq, RTM_NEWROUTE, sizeof(*rtm), NLM_F_MULTI); 2240 nlh = nlmsg_put(skb, portid, seq, RTM_NEWROUTE, sizeof(*rtm), NLM_F_MULTI);
2240 if (nlh == NULL) 2241 if (nlh == NULL)
@@ -2248,6 +2249,7 @@ static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
2248 rtm->rtm_table = mrt->id; 2249 rtm->rtm_table = mrt->id;
2249 if (nla_put_u32(skb, RTA_TABLE, mrt->id)) 2250 if (nla_put_u32(skb, RTA_TABLE, mrt->id))
2250 goto nla_put_failure; 2251 goto nla_put_failure;
2252 rtm->rtm_type = RTN_MULTICAST;
2251 rtm->rtm_scope = RT_SCOPE_UNIVERSE; 2253 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
2252 if (c->mfc_flags & MFC_STATIC) 2254 if (c->mfc_flags & MFC_STATIC)
2253 rtm->rtm_protocol = RTPROT_STATIC; 2255 rtm->rtm_protocol = RTPROT_STATIC;
@@ -2258,7 +2260,9 @@ static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
2258 if (nla_put(skb, RTA_SRC, 16, &c->mf6c_origin) || 2260 if (nla_put(skb, RTA_SRC, 16, &c->mf6c_origin) ||
2259 nla_put(skb, RTA_DST, 16, &c->mf6c_mcastgrp)) 2261 nla_put(skb, RTA_DST, 16, &c->mf6c_mcastgrp))
2260 goto nla_put_failure; 2262 goto nla_put_failure;
2261 if (__ip6mr_fill_mroute(mrt, skb, c, rtm) < 0) 2263 err = __ip6mr_fill_mroute(mrt, skb, c, rtm);
2264 /* do not break the dump if cache is unresolved */
2265 if (err < 0 && err != -ENOENT)
2262 goto nla_put_failure; 2266 goto nla_put_failure;
2263 2267
2264 return nlmsg_end(skb, nlh); 2268 return nlmsg_end(skb, nlh);
@@ -2301,6 +2305,22 @@ next_entry:
2301 } 2305 }
2302 e = s_e = 0; 2306 e = s_e = 0;
2303 } 2307 }
2308 spin_lock_bh(&mfc_unres_lock);
2309 list_for_each_entry(mfc, &mrt->mfc6_unres_queue, list) {
2310 if (e < s_e)
2311 goto next_entry2;
2312 if (ip6mr_fill_mroute(mrt, skb,
2313 NETLINK_CB(cb->skb).portid,
2314 cb->nlh->nlmsg_seq,
2315 mfc) < 0) {
2316 spin_unlock_bh(&mfc_unres_lock);
2317 goto done;
2318 }
2319next_entry2:
2320 e++;
2321 }
2322 spin_unlock_bh(&mfc_unres_lock);
2323 e = s_e = 0;
2304 s_h = 0; 2324 s_h = 0;
2305next_table: 2325next_table:
2306 t++; 2326 t++;