--- zzzz-none-000/linux-2.6.28.10/net/ipv6/ndisc.c 2009-05-02 18:54:43.000000000 +0000 +++ fusiv-7390-686/linux-2.6.28.10/net/ipv6/ndisc.c 2012-02-14 14:37:49.000000000 +0000 @@ -1074,6 +1074,20 @@ rtnl_set_sk_err(net, RTNLGRP_ND_USEROPT, err); } +#ifdef CONFIG_IPV6_CPE_RFC_6204 +static inline int accept_ra(struct inet6_dev *in6_dev) +{ + /* + * If forwarding is enabled, RA are not accepted unless the special + * hybrid mode (accept_ra=2) is enabled. + */ + if (in6_dev->cnf.forwarding && in6_dev->cnf.accept_ra < 2) + return 0; + + return in6_dev->cnf.accept_ra; +} +#endif + static void ndisc_router_discovery(struct sk_buff *skb) { struct ra_msg *ra_msg = (struct ra_msg *)skb_transport_header(skb); @@ -1119,18 +1133,24 @@ skb->dev->name); return; } - if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) { + if (!ndisc_parse_options(opt, optlen, &ndopts)) { in6_dev_put(in6_dev); + ND_PRINTK2(KERN_WARNING + "ICMP6 RA: invalid ND options\n"); return; } - if (!ndisc_parse_options(opt, optlen, &ndopts)) { +#ifdef CONFIG_IPV6_CPE_RFC_6204 + if (!accept_ra(in6_dev)) + goto skip_linkparms; +#else + if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_ra) { in6_dev_put(in6_dev); - ND_PRINTK2(KERN_WARNING - "ICMP6 RA: invalid ND options\n"); return; } +#endif + #ifdef CONFIG_IPV6_NDISC_NODETYPE /* skip link-specific parameters from interior routers */ if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT) @@ -1280,6 +1300,11 @@ NEIGH_UPDATE_F_ISROUTER); } +#ifdef CONFIG_IPV6_CPE_RFC_6204 + if (!accept_ra(in6_dev)) + goto out; +#endif + #ifdef CONFIG_IPV6_ROUTE_INFO if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) { struct nd_opt_hdr *p;