]> err.no Git - linux-2.6/blobdiff - net/ipv6/ndisc.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[linux-2.6] / net / ipv6 / ndisc.c
index 06d80c6dc5ceb3078fc316fb1b1ed73e99464169..282fdb31f8ed92455a2aba625d45301433d92364 100644 (file)
@@ -442,8 +442,9 @@ static void pndisc_destructor(struct pneigh_entry *n)
  */
 static void __ndisc_send(struct net_device *dev,
                         struct neighbour *neigh,
-                        struct in6_addr *daddr, struct in6_addr *saddr,
-                        struct icmp6hdr *icmp6h, struct in6_addr *target,
+                        const struct in6_addr *daddr,
+                        const struct in6_addr *saddr,
+                        struct icmp6hdr *icmp6h, const struct in6_addr *target,
                         int llinfo)
 {
        struct flowi fl;
@@ -478,7 +479,7 @@ static void __ndisc_send(struct net_device *dev,
 
        skb = sock_alloc_send_skb(sk,
                                  (MAX_HEADER + sizeof(struct ipv6hdr) +
-                                  len + LL_RESERVED_SPACE(dev)),
+                                  len + LL_ALLOCATED_SPACE(dev)),
                                  1, &err);
        if (!skb) {
                ND_PRINTK0(KERN_ERR
@@ -529,12 +530,13 @@ static void __ndisc_send(struct net_device *dev,
 }
 
 static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
-                  struct in6_addr *daddr, struct in6_addr *solicited_addr,
-                  int router, int solicited, int override, int inc_opt)
+                         const struct in6_addr *daddr,
+                         const struct in6_addr *solicited_addr,
+                         int router, int solicited, int override, int inc_opt)
 {
        struct in6_addr tmpaddr;
        struct inet6_ifaddr *ifp;
-       struct in6_addr *src_addr;
+       const struct in6_addr *src_addr;
        struct icmp6hdr icmp6h = {
                .icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT,
        };
@@ -564,8 +566,8 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
 }
 
 void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
-                  struct in6_addr *solicit,
-                  struct in6_addr *daddr, struct in6_addr *saddr)
+                  const struct in6_addr *solicit,
+                  const struct in6_addr *daddr, const struct in6_addr *saddr)
 {
        struct in6_addr addr_buf;
        struct icmp6hdr icmp6h = {
@@ -584,8 +586,8 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
                     !ipv6_addr_any(saddr) ? ND_OPT_SOURCE_LL_ADDR : 0);
 }
 
-void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
-                  struct in6_addr *daddr)
+void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr,
+                  const struct in6_addr *daddr)
 {
        struct icmp6hdr icmp6h = {
                .icmp6_type = NDISC_ROUTER_SOLICITATION,
@@ -816,10 +818,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
                is_router = !!idev->cnf.forwarding;
 
        if (dad) {
-               struct in6_addr maddr;
-
-               ipv6_addr_all_nodes(&maddr);
-               ndisc_send_na(dev, NULL, &maddr, &msg->target,
+               ndisc_send_na(dev, NULL, &in6addr_linklocal_allnodes, &msg->target,
                              is_router, 0, (ifp != NULL), 1);
                goto out;
        }
@@ -1093,6 +1092,14 @@ static void ndisc_router_discovery(struct sk_buff *skb)
                return;
        }
 
+#ifdef CONFIG_IPV6_NDISC_NODETYPE
+       if (skb->ndisc_nodetype == NDISC_NODETYPE_HOST) {
+               ND_PRINTK2(KERN_WARNING
+                          "ICMPv6 RA: from host or unauthorized router\n");
+               return;
+       }
+#endif
+
        /*
         *      set the RA_RECV flag in the interface
         */
@@ -1116,6 +1123,12 @@ static void ndisc_router_discovery(struct sk_buff *skb)
                return;
        }
 
+#ifdef CONFIG_IPV6_NDISC_NODETYPE
+       /* skip link-specific parameters from interior routers */
+       if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT)
+               goto skip_linkparms;
+#endif
+
        if (in6_dev->if_flags & IF_RS_SENT) {
                /*
                 *      flag that an RA was received after an RS was sent
@@ -1230,6 +1243,10 @@ skip_defrtr:
                }
        }
 
+#ifdef CONFIG_IPV6_NDISC_NODETYPE
+skip_linkparms:
+#endif
+
        /*
         *      Process options.
         */
@@ -1261,7 +1278,13 @@ skip_defrtr:
                for (p = ndopts.nd_opts_ri;
                     p;
                     p = ndisc_next_option(p, ndopts.nd_opts_ri_end)) {
-                       if (((struct route_info *)p)->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)
+                       struct route_info *ri = (struct route_info *)p;
+#ifdef CONFIG_IPV6_NDISC_NODETYPE
+                       if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT &&
+                           ri->prefix_len == 0)
+                               continue;
+#endif
+                       if (ri->prefix_len > in6_dev->cnf.accept_ra_rt_info_max_plen)
                                continue;
                        rt6_route_rcv(skb->dev, (u8*)p, (p->nd_opt_len) << 3,
                                      &ipv6_hdr(skb)->saddr);
@@ -1269,6 +1292,12 @@ skip_defrtr:
        }
 #endif
 
+#ifdef CONFIG_IPV6_NDISC_NODETYPE
+       /* skip link-specific ndopts from interior routers */
+       if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT)
+               goto out;
+#endif
+
        if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) {
                struct nd_opt_hdr *p;
                for (p = ndopts.nd_opts_pi;
@@ -1332,6 +1361,16 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
        int optlen;
        u8 *lladdr = NULL;
 
+#ifdef CONFIG_IPV6_NDISC_NODETYPE
+       switch (skb->ndisc_nodetype) {
+       case NDISC_NODETYPE_HOST:
+       case NDISC_NODETYPE_NODEFAULT:
+               ND_PRINTK2(KERN_WARNING
+                          "ICMPv6 Redirect: from host or unauthorized router\n");
+               return;
+       }
+#endif
+
        if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) {
                ND_PRINTK2(KERN_WARNING
                           "ICMPv6 Redirect: source address is not link-local.\n");
@@ -1407,7 +1446,7 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
 }
 
 void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
-                        struct in6_addr *target)
+                        const struct in6_addr *target)
 {
        struct net_device *dev = skb->dev;
        struct net *net = dev_net(dev);
@@ -1482,7 +1521,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
 
        buff = sock_alloc_send_skb(sk,
                                   (MAX_HEADER + sizeof(struct ipv6hdr) +
-                                   len + LL_RESERVED_SPACE(dev)),
+                                   len + LL_ALLOCATED_SPACE(dev)),
                                   1, &err);
        if (buff == NULL) {
                ND_PRINTK0(KERN_ERR
@@ -1688,10 +1727,10 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * f
        return ret;
 }
 
-static int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name,
-                                       int nlen, void __user *oldval,
-                                       size_t __user *oldlenp,
-                                       void __user *newval, size_t newlen)
+int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name,
+                                int nlen, void __user *oldval,
+                                size_t __user *oldlenp,
+                                void __user *newval, size_t newlen)
 {
        struct net_device *dev = ctl->extra1;
        struct inet6_dev *idev;