VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / net / ipv4 / raw.c
index a065088..e378ddc 100644 (file)
@@ -338,6 +338,10 @@ static int raw_send_hdrinc(struct sock *sk, void *from, int length,
 
                iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
        }
+       err = -EPERM;
+       if (!vx_check(0, VX_ADMIN) && !capable(CAP_NET_RAW)
+               && (!raw_addr_in_list(0, 0, iph->saddr, sk->sk_nx_info)))
+               goto error;
 
        err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
                      dst_output);
@@ -352,7 +356,7 @@ error_fault:
        err = -EFAULT;
        kfree_skb(skb);
 error:
-       IP_INC_STATS(IpOutDiscards);
+       IP_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
        return err; 
 }
 
@@ -462,6 +466,13 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                                    .proto = inet->hdrincl ? IPPROTO_RAW :
                                                             sk->sk_protocol,
                                  };
+               
+               if (sk->sk_nx_info) {
+                       err = ip_find_src(sk->sk_nx_info, &rt, &fl);
+
+                       if (err)
+                               goto done;
+               }
                err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
        }
        if (err)
@@ -513,7 +524,7 @@ static void raw_close(struct sock *sk, long timeout)
         */
        ip_ra_control(sk, 0, NULL);
 
-       inet_sock_release(sk);
+       sk_common_release(sk);
 }
 
 /* This gets rid of all the nasties in af_inet. -DaveM */
@@ -588,9 +599,11 @@ int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        }
        if (inet->cmsg_flags)
                ip_cmsg_recv(msg, skb);
+       if (flags & MSG_TRUNC)
+               copied = skb->len;
 done:
        skb_free_datagram(sk, skb);
-out:   return err ? : copied;
+out:   return err ? err : copied;
 }
 
 static int raw_init(struct sock *sk)
@@ -601,7 +614,7 @@ static int raw_init(struct sock *sk)
        return 0;
 }
 
-static int raw_seticmpfilter(struct sock *sk, char *optval, int optlen)
+static int raw_seticmpfilter(struct sock *sk, char __user *optval, int optlen)
 {
        if (optlen > sizeof(struct icmp_filter))
                optlen = sizeof(struct icmp_filter);
@@ -610,7 +623,7 @@ static int raw_seticmpfilter(struct sock *sk, char *optval, int optlen)
        return 0;
 }
 
-static int raw_geticmpfilter(struct sock *sk, char *optval, int *optlen)
+static int raw_geticmpfilter(struct sock *sk, char __user *optval, int __user *optlen)
 {
        int len, ret = -EFAULT;
 
@@ -630,7 +643,7 @@ out:        return ret;
 }
 
 static int raw_setsockopt(struct sock *sk, int level, int optname, 
-                         char *optval, int optlen)
+                         char __user *optval, int optlen)
 {
        if (level != SOL_RAW)
                return ip_setsockopt(sk, level, optname, optval, optlen);
@@ -645,7 +658,7 @@ static int raw_setsockopt(struct sock *sk, int level, int optname,
 }
 
 static int raw_getsockopt(struct sock *sk, int level, int optname, 
-                         char *optval, int *optlen)
+                         char __user *optval, int __user *optlen)
 {
        if (level != SOL_RAW)
                return ip_getsockopt(sk, level, optname, optval, optlen);
@@ -664,7 +677,7 @@ static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
        switch (cmd) {
                case SIOCOUTQ: {
                        int amount = atomic_read(&sk->sk_wmem_alloc);
-                       return put_user(amount, (int *)arg);
+                       return put_user(amount, (int __user *)arg);
                }
                case SIOCINQ: {
                        struct sk_buff *skb;
@@ -675,12 +688,12 @@ static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
                        if (skb != NULL)
                                amount = skb->len;
                        spin_unlock_irq(&sk->sk_receive_queue.lock);
-                       return put_user(amount, (int *)arg);
+                       return put_user(amount, (int __user *)arg);
                }
 
                default:
 #ifdef CONFIG_IP_MROUTE
-                       return ipmr_ioctl(sk, cmd, arg);
+                       return ipmr_ioctl(sk, cmd, (void __user *)arg);
 #else
                        return -ENOIOCTLCMD;
 #endif
@@ -690,7 +703,7 @@ static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
 struct proto raw_prot = {
        .name =         "RAW",
        .close =        raw_close,
-       .connect =      udp_connect,
+       .connect =      ip4_datagram_connect,
        .disconnect =   udp_disconnect,
        .ioctl =        raw_ioctl,
        .init =         raw_init,