9p: Make sure we are able to clunk the cached fid on umount
[safe/jmp/linux-2.6] / net / ipv6 / datagram.c
index 0f0f94a..e6f9cdf 100644 (file)
@@ -5,8 +5,6 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>
  *
- *     $Id: datagram.c,v 1.24 2002/02/01 22:01:04 davem Exp $
- *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
  *      as published by the Free Software Foundation; either version
@@ -100,17 +98,15 @@ ipv4_connected:
                if (err)
                        goto out;
 
-               ipv6_addr_set(&np->daddr, 0, 0, htonl(0x0000ffff), inet->daddr);
+               ipv6_addr_set_v4mapped(inet->inet_daddr, &np->daddr);
 
-               if (ipv6_addr_any(&np->saddr)) {
-                       ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000ffff),
-                                     inet->saddr);
-               }
+               if (ipv6_addr_any(&np->saddr))
+                       ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr);
+
+               if (ipv6_addr_any(&np->rcv_saddr))
+                       ipv6_addr_set_v4mapped(inet->inet_rcv_saddr,
+                                              &np->rcv_saddr);
 
-               if (ipv6_addr_any(&np->rcv_saddr)) {
-                       ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000ffff),
-                                     inet->rcv_saddr);
-               }
                goto out;
        }
 
@@ -138,7 +134,7 @@ ipv4_connected:
        ipv6_addr_copy(&np->daddr, daddr);
        np->flow_label = fl.fl6_flowlabel;
 
-       inet->dport = usin->sin6_port;
+       inet->inet_dport = usin->sin6_port;
 
        /*
         *      Check for a route to destination an obtain the
@@ -149,8 +145,9 @@ ipv4_connected:
        ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
        ipv6_addr_copy(&fl.fl6_src, &np->saddr);
        fl.oif = sk->sk_bound_dev_if;
-       fl.fl_ip_dport = inet->dport;
-       fl.fl_ip_sport = inet->sport;
+       fl.mark = sk->sk_mark;
+       fl.fl_ip_dport = inet->inet_dport;
+       fl.fl_ip_sport = inet->inet_sport;
 
        if (!fl.oif && (addr_type&IPV6_ADDR_MULTICAST))
                fl.oif = np->mcast_oif;
@@ -177,7 +174,8 @@ ipv4_connected:
        if (final_p)
                ipv6_addr_copy(&fl.fl6_dst, final_p);
 
-       if ((err = __xfrm_lookup(&dst, &fl, sk, XFRM_LOOKUP_WAIT)) < 0) {
+       err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT);
+       if (err < 0) {
                if (err == -EREMOTE)
                        err = ip6_dst_blackhole(sk, &dst, &fl);
                if (err < 0)
@@ -191,7 +189,7 @@ ipv4_connected:
 
        if (ipv6_addr_any(&np->rcv_saddr)) {
                ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src);
-               inet->rcv_saddr = LOOPBACK4_IPV6;
+               inet->inet_rcv_saddr = LOOPBACK4_IPV6;
        }
 
        ip6_dst_store(sk, dst,
@@ -330,9 +328,8 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
                        if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)
                                sin->sin6_scope_id = IP6CB(skb)->iif;
                } else {
-                       ipv6_addr_set(&sin->sin6_addr, 0, 0,
-                                     htonl(0xffff),
-                                     *(__be32 *)(nh + serr->addr_offset));
+                       ipv6_addr_set_v4mapped(*(__be32 *)(nh + serr->addr_offset),
+                                              &sin->sin6_addr);
                }
        }
 
@@ -352,8 +349,8 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
                } else {
                        struct inet_sock *inet = inet_sk(sk);
 
-                       ipv6_addr_set(&sin->sin6_addr, 0, 0,
-                                     htonl(0xffff), ip_hdr(skb)->saddr);
+                       ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr,
+                                              &sin->sin6_addr);
                        if (inet->cmsg_flags)
                                ip_cmsg_recv(msg, skb);
                }
@@ -540,12 +537,17 @@ int datagram_send_ctl(struct net *net,
 
                        addr_type = __ipv6_addr_type(&src_info->ipi6_addr);
 
+                       rcu_read_lock();
                        if (fl->oif) {
-                               dev = dev_get_by_index(net, fl->oif);
-                               if (!dev)
+                               dev = dev_get_by_index_rcu(net, fl->oif);
+                               if (!dev) {
+                                       rcu_read_unlock();
                                        return -ENODEV;
-                       } else if (addr_type & IPV6_ADDR_LINKLOCAL)
+                               }
+                       } else if (addr_type & IPV6_ADDR_LINKLOCAL) {
+                               rcu_read_unlock();
                                return -EINVAL;
+                       }
 
                        if (addr_type != IPV6_ADDR_ANY) {
                                int strict = __ipv6_addr_src_scope(addr_type) <= IPV6_ADDR_SCOPE_LINKLOCAL;
@@ -556,8 +558,7 @@ int datagram_send_ctl(struct net *net,
                                        ipv6_addr_copy(&fl->fl6_src, &src_info->ipi6_addr);
                        }
 
-                       if (dev)
-                               dev_put(dev);
+                       rcu_read_unlock();
 
                        if (err)
                                goto exit_f;
@@ -663,6 +664,11 @@ int datagram_send_ctl(struct net *net,
                        switch (rthdr->type) {
 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
                        case IPV6_SRCRT_TYPE_2:
+                               if (rthdr->hdrlen != 2 ||
+                                   rthdr->segments_left != 1) {
+                                       err = -EINVAL;
+                                       goto exit_f;
+                               }
                                break;
 #endif
                        default:
@@ -734,7 +740,7 @@ int datagram_send_ctl(struct net *net,
                        LIMIT_NETDEBUG(KERN_DEBUG "invalid cmsg type: %d\n",
                                       cmsg->cmsg_type);
                        err = -EINVAL;
-                       break;
+                       goto exit_f;
                }
        }