diff options
author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2008-04-02 20:22:53 -0400 |
---|---|---|
committer | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2008-04-05 09:33:38 -0400 |
commit | 7bc570c8b4f75ddb3fd5dbeb38127cdc4acbcc9c (patch) | |
tree | b688b728c3ea08479f75986d1e9f590fca1f8715 /net/ipv6/route.c | |
parent | 80a9492a33dd7d852465625022d56ff76d62174d (diff) |
[IPV6] MROUTE: Support multicast forwarding.
Based on ancient patch by Mickael Hoerdt
<hoerdt@clarinet.u-strasbg.fr>, which is available at
<http://www-r2.u-strasbg.fr/~hoerdt/dev/linux_ipv6_mforwarding/patch-linux-ipv6-mforwarding-0.1a>.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index cd82b6db35ff..3c314d5f46c6 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/route.h> | 36 | #include <linux/route.h> |
37 | #include <linux/netdevice.h> | 37 | #include <linux/netdevice.h> |
38 | #include <linux/in6.h> | 38 | #include <linux/in6.h> |
39 | #include <linux/mroute6.h> | ||
39 | #include <linux/init.h> | 40 | #include <linux/init.h> |
40 | #include <linux/if_arp.h> | 41 | #include <linux/if_arp.h> |
41 | #include <linux/proc_fs.h> | 42 | #include <linux/proc_fs.h> |
@@ -2106,7 +2107,7 @@ static inline size_t rt6_nlmsg_size(void) | |||
2106 | static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | 2107 | static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, |
2107 | struct in6_addr *dst, struct in6_addr *src, | 2108 | struct in6_addr *dst, struct in6_addr *src, |
2108 | int iif, int type, u32 pid, u32 seq, | 2109 | int iif, int type, u32 pid, u32 seq, |
2109 | int prefix, unsigned int flags) | 2110 | int prefix, int nowait, unsigned int flags) |
2110 | { | 2111 | { |
2111 | struct rtmsg *rtm; | 2112 | struct rtmsg *rtm; |
2112 | struct nlmsghdr *nlh; | 2113 | struct nlmsghdr *nlh; |
@@ -2166,9 +2167,24 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | |||
2166 | } else if (rtm->rtm_src_len) | 2167 | } else if (rtm->rtm_src_len) |
2167 | NLA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr); | 2168 | NLA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr); |
2168 | #endif | 2169 | #endif |
2169 | if (iif) | 2170 | if (iif) { |
2170 | NLA_PUT_U32(skb, RTA_IIF, iif); | 2171 | #ifdef CONFIG_IPV6_MROUTE |
2171 | else if (dst) { | 2172 | if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) { |
2173 | int err = ip6mr_get_route(skb, rtm, nowait); | ||
2174 | if (err <= 0) { | ||
2175 | if (!nowait) { | ||
2176 | if (err == 0) | ||
2177 | return 0; | ||
2178 | goto nla_put_failure; | ||
2179 | } else { | ||
2180 | if (err == -EMSGSIZE) | ||
2181 | goto nla_put_failure; | ||
2182 | } | ||
2183 | } | ||
2184 | } else | ||
2185 | #endif | ||
2186 | NLA_PUT_U32(skb, RTA_IIF, iif); | ||
2187 | } else if (dst) { | ||
2172 | struct in6_addr saddr_buf; | 2188 | struct in6_addr saddr_buf; |
2173 | if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev, | 2189 | if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev, |
2174 | dst, 0, &saddr_buf) == 0) | 2190 | dst, 0, &saddr_buf) == 0) |
@@ -2211,7 +2227,7 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg) | |||
2211 | 2227 | ||
2212 | return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE, | 2228 | return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE, |
2213 | NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq, | 2229 | NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq, |
2214 | prefix, NLM_F_MULTI); | 2230 | prefix, 0, NLM_F_MULTI); |
2215 | } | 2231 | } |
2216 | 2232 | ||
2217 | static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) | 2233 | static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) |
@@ -2277,7 +2293,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2277 | 2293 | ||
2278 | err = rt6_fill_node(skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, | 2294 | err = rt6_fill_node(skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, |
2279 | RTM_NEWROUTE, NETLINK_CB(in_skb).pid, | 2295 | RTM_NEWROUTE, NETLINK_CB(in_skb).pid, |
2280 | nlh->nlmsg_seq, 0, 0); | 2296 | nlh->nlmsg_seq, 0, 0, 0); |
2281 | if (err < 0) { | 2297 | if (err < 0) { |
2282 | kfree_skb(skb); | 2298 | kfree_skb(skb); |
2283 | goto errout; | 2299 | goto errout; |
@@ -2303,7 +2319,7 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | |||
2303 | goto errout; | 2319 | goto errout; |
2304 | 2320 | ||
2305 | err = rt6_fill_node(skb, rt, NULL, NULL, 0, | 2321 | err = rt6_fill_node(skb, rt, NULL, NULL, 0, |
2306 | event, info->pid, seq, 0, 0); | 2322 | event, info->pid, seq, 0, 0, 0); |
2307 | if (err < 0) { | 2323 | if (err < 0) { |
2308 | /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */ | 2324 | /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */ |
2309 | WARN_ON(err == -EMSGSIZE); | 2325 | WARN_ON(err == -EMSGSIZE); |