[MLSXFRM]: Add flow labeling
[deliverable/linux.git] / net / ipv4 / udp.c
index 2422a5f7195d002b457f0ced6e43c3dcd5998bff..a4d005eccc7f6668fb5f67abad9d9930fb63f999 100644 (file)
 #include <linux/module.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
+#include <linux/igmp.h>
 #include <linux/in.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <linux/mm.h>
-#include <linux/config.h>
 #include <linux/inet.h>
 #include <linux/ipv6.h>
 #include <linux/netdevice.h>
@@ -603,6 +603,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                                    .uli_u = { .ports =
                                               { .sport = inet->sport,
                                                 .dport = dport } } };
+               security_sk_classify_flow(sk, &fl);
                err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
                if (err)
                        goto out;
@@ -846,20 +847,7 @@ out:
 csum_copy_err:
        UDP_INC_STATS_BH(UDP_MIB_INERRORS);
 
-       /* Clear queue. */
-       if (flags&MSG_PEEK) {
-               int clear = 0;
-               spin_lock_bh(&sk->sk_receive_queue.lock);
-               if (skb == skb_peek(&sk->sk_receive_queue)) {
-                       __skb_unlink(skb, &sk->sk_receive_queue);
-                       clear = 1;
-               }
-               spin_unlock_bh(&sk->sk_receive_queue.lock);
-               if (clear)
-                       kfree_skb(skb);
-       }
-
-       skb_free_datagram(sk, skb);
+       skb_kill_datagram(sk, skb, flags);
 
        if (noblock)
                return -EAGAIN; 
@@ -1001,6 +989,7 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
                kfree_skb(skb);
                return -1;
        }
+       nf_reset(skb);
 
        if (up->encap_type) {
                /*
@@ -1094,7 +1083,7 @@ static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh,
  * Otherwise, csum completion requires chacksumming packet body,
  * including udp header and folding it to skb->csum.
  */
-static int udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
+static void udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
                             unsigned short ulen, u32 saddr, u32 daddr)
 {
        if (uh->check == 0) {
@@ -1108,7 +1097,6 @@ static int udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
        /* Probably, we should checksum udp header (it should be in cache
         * in any case) and data in tiny packets (< rx copybreak).
         */
-       return 0;
 }
 
 /*
@@ -1141,8 +1129,7 @@ int udp_rcv(struct sk_buff *skb)
        if (pskb_trim_rcsum(skb, ulen))
                goto short_packet;
 
-       if (udp_checksum_init(skb, uh, ulen, saddr, daddr) < 0)
-               goto csum_error;
+       udp_checksum_init(skb, uh, ulen, saddr, daddr);
 
        if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
                return udp_v4_mcast_deliver(skb, uh, saddr, daddr);
@@ -1163,6 +1150,7 @@ int udp_rcv(struct sk_buff *skb)
 
        if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
                goto drop;
+       nf_reset(skb);
 
        /* No socket. Drop packet silently, if checksum is wrong */
        if (udp_checksum_complete(skb))
@@ -1219,16 +1207,13 @@ static int udp_destroy_sock(struct sock *sk)
 /*
  *     Socket option code for UDP
  */
-static int udp_setsockopt(struct sock *sk, int level, int optname, 
+static int do_udp_setsockopt(struct sock *sk, int level, int optname,
                          char __user *optval, int optlen)
 {
        struct udp_sock *up = udp_sk(sk);
        int val;
        int err = 0;
 
-       if (level != SOL_UDP)
-               return ip_setsockopt(sk, level, optname, optval, optlen);
-
        if(optlen<sizeof(int))
                return -EINVAL;
 
@@ -1268,15 +1253,30 @@ static int udp_setsockopt(struct sock *sk, int level, int optname,
        return err;
 }
 
-static int udp_getsockopt(struct sock *sk, int level, int optname, 
+static int udp_setsockopt(struct sock *sk, int level, int optname,
+                         char __user *optval, int optlen)
+{
+       if (level != SOL_UDP)
+               return ip_setsockopt(sk, level, optname, optval, optlen);
+       return do_udp_setsockopt(sk, level, optname, optval, optlen);
+}
+
+#ifdef CONFIG_COMPAT
+static int compat_udp_setsockopt(struct sock *sk, int level, int optname,
+                                char __user *optval, int optlen)
+{
+       if (level != SOL_UDP)
+               return compat_ip_setsockopt(sk, level, optname, optval, optlen);
+       return do_udp_setsockopt(sk, level, optname, optval, optlen);
+}
+#endif
+
+static int do_udp_getsockopt(struct sock *sk, int level, int optname,
                          char __user *optval, int __user *optlen)
 {
        struct udp_sock *up = udp_sk(sk);
        int val, len;
 
-       if (level != SOL_UDP)
-               return ip_getsockopt(sk, level, optname, optval, optlen);
-
        if(get_user(len,optlen))
                return -EFAULT;
 
@@ -1305,6 +1305,23 @@ static int udp_getsockopt(struct sock *sk, int level, int optname,
        return 0;
 }
 
+static int udp_getsockopt(struct sock *sk, int level, int optname,
+                         char __user *optval, int __user *optlen)
+{
+       if (level != SOL_UDP)
+               return ip_getsockopt(sk, level, optname, optval, optlen);
+       return do_udp_getsockopt(sk, level, optname, optval, optlen);
+}
+
+#ifdef CONFIG_COMPAT
+static int compat_udp_getsockopt(struct sock *sk, int level, int optname,
+                                char __user *optval, int __user *optlen)
+{
+       if (level != SOL_UDP)
+               return compat_ip_getsockopt(sk, level, optname, optval, optlen);
+       return do_udp_getsockopt(sk, level, optname, optval, optlen);
+}
+#endif
 /**
  *     udp_poll - wait for a UDP event.
  *     @file - file struct
@@ -1353,23 +1370,27 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
 }
 
 struct proto udp_prot = {
-       .name =         "UDP",
-       .owner =        THIS_MODULE,
-       .close =        udp_close,
-       .connect =      ip4_datagram_connect,
-       .disconnect =   udp_disconnect,
-       .ioctl =        udp_ioctl,
-       .destroy =      udp_destroy_sock,
-       .setsockopt =   udp_setsockopt,
-       .getsockopt =   udp_getsockopt,
-       .sendmsg =      udp_sendmsg,
-       .recvmsg =      udp_recvmsg,
-       .sendpage =     udp_sendpage,
-       .backlog_rcv =  udp_queue_rcv_skb,
-       .hash =         udp_v4_hash,
-       .unhash =       udp_v4_unhash,
-       .get_port =     udp_v4_get_port,
-       .obj_size =     sizeof(struct udp_sock),
+       .name              = "UDP",
+       .owner             = THIS_MODULE,
+       .close             = udp_close,
+       .connect           = ip4_datagram_connect,
+       .disconnect        = udp_disconnect,
+       .ioctl             = udp_ioctl,
+       .destroy           = udp_destroy_sock,
+       .setsockopt        = udp_setsockopt,
+       .getsockopt        = udp_getsockopt,
+       .sendmsg           = udp_sendmsg,
+       .recvmsg           = udp_recvmsg,
+       .sendpage          = udp_sendpage,
+       .backlog_rcv       = udp_queue_rcv_skb,
+       .hash              = udp_v4_hash,
+       .unhash            = udp_v4_unhash,
+       .get_port          = udp_v4_get_port,
+       .obj_size          = sizeof(struct udp_sock),
+#ifdef CONFIG_COMPAT
+       .compat_setsockopt = compat_udp_setsockopt,
+       .compat_getsockopt = compat_udp_getsockopt,
+#endif
 };
 
 /* ------------------------------------------------------------------------ */
@@ -1448,11 +1469,10 @@ static int udp_seq_open(struct inode *inode, struct file *file)
        struct udp_seq_afinfo *afinfo = PDE(inode)->data;
        struct seq_file *seq;
        int rc = -ENOMEM;
-       struct udp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+       struct udp_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
 
        if (!s)
                goto out;
-       memset(s, 0, sizeof(*s));
        s->family               = afinfo->family;
        s->seq_ops.start        = udp_seq_start;
        s->seq_ops.next         = udp_seq_next;
This page took 0.038637 seconds and 5 git commands to generate.