OSDN Git Service

net: inet: Support UID-based routing in IP protocols.
[android-x86/kernel.git] / net / ipv6 / datagram.c
index 9dd3882..c5d76d2 100644 (file)
@@ -54,6 +54,7 @@ static void ip6_datagram_flow_key_init(struct flowi6 *fl6, struct sock *sk)
        fl6->fl6_dport = inet->inet_dport;
        fl6->fl6_sport = inet->inet_sport;
        fl6->flowlabel = np->flow_label;
+       fl6->flowi6_uid = sk->sk_uid;
 
        if (!fl6->flowi6_oif)
                fl6->flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
@@ -450,9 +451,10 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
                copied = len;
        }
        err = skb_copy_datagram_msg(skb, 0, msg, copied);
-       if (err)
-               goto out_free_skb;
-
+       if (unlikely(err)) {
+               kfree_skb(skb);
+               return err;
+       }
        sock_recv_timestamp(msg, sk, skb);
 
        serr = SKB_EXT_ERR(skb);
@@ -509,8 +511,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
        msg->msg_flags |= MSG_ERRQUEUE;
        err = copied;
 
-out_free_skb:
-       kfree_skb(skb);
+       consume_skb(skb);
 out:
        return err;
 }
@@ -715,6 +716,11 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg,
                        put_cmsg(msg, SOL_IPV6, IPV6_ORIGDSTADDR, sizeof(sin6), &sin6);
                }
        }
+       if (np->rxopt.bits.recvfragsize && opt->frag_max_size) {
+               int val = opt->frag_max_size;
+
+               put_cmsg(msg, SOL_IPV6, IPV6_RECVFRAGSIZE, sizeof(val), &val);
+       }
 }
 
 void ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg,
@@ -727,13 +733,13 @@ EXPORT_SYMBOL_GPL(ip6_datagram_recv_ctl);
 
 int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
                          struct msghdr *msg, struct flowi6 *fl6,
-                         struct ipv6_txoptions *opt,
-                         int *hlimit, int *tclass, int *dontfrag)
+                         struct ipcm6_cookie *ipc6, struct sockcm_cookie *sockc)
 {
        struct in6_pktinfo *src_info;
        struct cmsghdr *cmsg;
        struct ipv6_rt_hdr *rthdr;
        struct ipv6_opt_hdr *hdr;
+       struct ipv6_txoptions *opt = ipc6->opt;
        int len;
        int err = 0;
 
@@ -745,6 +751,13 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
                        goto exit_f;
                }
 
+               if (cmsg->cmsg_level == SOL_SOCKET) {
+                       err = __sock_cmsg_send(sk, msg, cmsg, sockc);
+                       if (err)
+                               return err;
+                       continue;
+               }
+
                if (cmsg->cmsg_level != SOL_IPV6)
                        continue;
 
@@ -946,8 +959,8 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
                                goto exit_f;
                        }
 
-                       *hlimit = *(int *)CMSG_DATA(cmsg);
-                       if (*hlimit < -1 || *hlimit > 0xff) {
+                       ipc6->hlimit = *(int *)CMSG_DATA(cmsg);
+                       if (ipc6->hlimit < -1 || ipc6->hlimit > 0xff) {
                                err = -EINVAL;
                                goto exit_f;
                        }
@@ -967,7 +980,7 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
                                goto exit_f;
 
                        err = 0;
-                       *tclass = tc;
+                       ipc6->tclass = tc;
 
                        break;
                    }
@@ -985,7 +998,7 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
                                goto exit_f;
 
                        err = 0;
-                       *dontfrag = df;
+                       ipc6->dontfrag = df;
 
                        break;
                    }