aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/route.c
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2008-04-02 20:22:53 -0400
committerYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2008-04-05 09:33:38 -0400
commit7bc570c8b4f75ddb3fd5dbeb38127cdc4acbcc9c (patch)
treeb688b728c3ea08479f75986d1e9f590fca1f8715 /net/ipv6/route.c
parent80a9492a33dd7d852465625022d56ff76d62174d (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.c30
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)
2106static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, 2107static 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
2217static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) 2233static 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);