]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - net/ipv6/tcp_ipv6.c
afs: Add metadata xattrs
[mirror_ubuntu-bionic-kernel.git] / net / ipv6 / tcp_ipv6.c
index 4f4310a36a0481e2bd068e39285011ff28377ea5..2521690d62d6e591af594c3629f71f004240ed68 100644 (file)
@@ -109,9 +109,9 @@ static u32 tcp_v6_init_seq(const struct sk_buff *skb)
                                tcp_hdr(skb)->source);
 }
 
-static u32 tcp_v6_init_ts_off(const struct sk_buff *skb)
+static u32 tcp_v6_init_ts_off(const struct net *net, const struct sk_buff *skb)
 {
-       return secure_tcpv6_ts_off(ipv6_hdr(skb)->daddr.s6_addr32,
+       return secure_tcpv6_ts_off(net, ipv6_hdr(skb)->daddr.s6_addr32,
                                   ipv6_hdr(skb)->saddr.s6_addr32);
 }
 
@@ -292,7 +292,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
                                                         sk->sk_v6_daddr.s6_addr32,
                                                         inet->inet_sport,
                                                         inet->inet_dport);
-               tp->tsoffset = secure_tcpv6_ts_off(np->saddr.s6_addr32,
+               tp->tsoffset = secure_tcpv6_ts_off(sock_net(sk),
+                                                  np->saddr.s6_addr32,
                                                   sk->sk_v6_daddr.s6_addr32);
        }
 
@@ -514,11 +515,12 @@ static struct tcp_md5sig_key *tcp_v6_md5_lookup(const struct sock *sk,
        return tcp_v6_md5_do_lookup(sk, &addr_sk->sk_v6_daddr);
 }
 
-static int tcp_v6_parse_md5_keys(struct sock *sk, char __user *optval,
-                                int optlen)
+static int tcp_v6_parse_md5_keys(struct sock *sk, int optname,
+                                char __user *optval, int optlen)
 {
        struct tcp_md5sig cmd;
        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr;
+       u8 prefixlen;
 
        if (optlen < sizeof(cmd))
                return -EINVAL;
@@ -529,12 +531,22 @@ static int tcp_v6_parse_md5_keys(struct sock *sk, char __user *optval,
        if (sin6->sin6_family != AF_INET6)
                return -EINVAL;
 
+       if (optname == TCP_MD5SIG_EXT &&
+           cmd.tcpm_flags & TCP_MD5SIG_FLAG_PREFIX) {
+               prefixlen = cmd.tcpm_prefixlen;
+               if (prefixlen > 128 || (ipv6_addr_v4mapped(&sin6->sin6_addr) &&
+                                       prefixlen > 32))
+                       return -EINVAL;
+       } else {
+               prefixlen = ipv6_addr_v4mapped(&sin6->sin6_addr) ? 32 : 128;
+       }
+
        if (!cmd.tcpm_keylen) {
                if (ipv6_addr_v4mapped(&sin6->sin6_addr))
                        return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3],
-                                             AF_INET);
+                                             AF_INET, prefixlen);
                return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr,
-                                     AF_INET6);
+                                     AF_INET6, prefixlen);
        }
 
        if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
@@ -542,10 +554,12 @@ static int tcp_v6_parse_md5_keys(struct sock *sk, char __user *optval,
 
        if (ipv6_addr_v4mapped(&sin6->sin6_addr))
                return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3],
-                                     AF_INET, cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
+                                     AF_INET, prefixlen, cmd.tcpm_key,
+                                     cmd.tcpm_keylen, GFP_KERNEL);
 
        return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr,
-                             AF_INET6, cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
+                             AF_INET6, prefixlen, cmd.tcpm_key,
+                             cmd.tcpm_keylen, GFP_KERNEL);
 }
 
 static int tcp_v6_md5_hash_headers(struct tcp_md5sig_pool *hp,
@@ -720,7 +734,7 @@ static void tcp_v6_init_req(struct request_sock *req,
             np->rxopt.bits.rxinfo ||
             np->rxopt.bits.rxoinfo || np->rxopt.bits.rxhlim ||
             np->rxopt.bits.rxohlim || np->repflow)) {
-               atomic_inc(&skb->users);
+               refcount_inc(&skb->users);
                ireq->pktopts = skb;
        }
 }
@@ -788,7 +802,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
 
        skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len);
 
-       t1 = (struct tcphdr *) skb_push(buff, tot_len);
+       t1 = skb_push(buff, tot_len);
        skb_reset_transport_header(buff);
 
        /* Swap the send and the receive. */
@@ -949,7 +963,7 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
 
        tcp_v6_send_ack(sk, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
                        tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
-                       tcp_time_stamp + tcptw->tw_ts_offset,
+                       tcp_time_stamp_raw() + tcptw->tw_ts_offset,
                        tcptw->tw_ts_recent, tw->tw_bound_dev_if, tcp_twsk_md5_key(tcptw),
                        tw->tw_tclass, cpu_to_be32(tw->tw_flowlabel));
 
@@ -971,7 +985,7 @@ static void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
                        tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt,
                        tcp_rsk(req)->rcv_nxt,
                        req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale,
-                       tcp_time_stamp + tcp_rsk(req)->ts_off,
+                       tcp_time_stamp_raw() + tcp_rsk(req)->ts_off,
                        req->ts_recent, sk->sk_bound_dev_if,
                        tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr),
                        0, 0);
@@ -1185,7 +1199,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
                 * across. Shucks.
                 */
                tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newsk->sk_v6_daddr,
-                              AF_INET6, key->key, key->keylen,
+                              AF_INET6, 128, key->key, key->keylen,
                               sk_gfp_mask(sk, GFP_ATOMIC));
        }
 #endif
@@ -1248,9 +1262,6 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
        if (skb->protocol == htons(ETH_P_IP))
                return tcp_v4_do_rcv(sk, skb);
 
-       if (tcp_filter(sk, skb))
-               goto discard;
-
        /*
         *      socket locking is here for SMP purposes as backlog rcv
         *      is currently called with bh processing disabled.
@@ -1453,6 +1464,8 @@ process:
                if (nsk == sk) {
                        reqsk_put(req);
                        tcp_v6_restore_cb(skb);
+               } else if (tcp_filter(sk, skb)) {
+                       goto discard_and_relse;
                } else if (tcp_child_process(sk, nsk, skb)) {
                        tcp_v6_send_reset(nsk, skb);
                        goto discard_and_relse;
@@ -1796,7 +1809,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
                   from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
                   icsk->icsk_probes_out,
                   sock_i_ino(sp),
-                  atomic_read(&sp->sk_refcnt), sp,
+                  refcount_read(&sp->sk_refcnt), sp,
                   jiffies_to_clock_t(icsk->icsk_rto),
                   jiffies_to_clock_t(icsk->icsk_ack.ato),
                   (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
@@ -1829,7 +1842,7 @@ static void get_timewait6_sock(struct seq_file *seq,
                   dest->s6_addr32[2], dest->s6_addr32[3], destp,
                   tw->tw_substate, 0, 0,
                   3, jiffies_delta_to_clock_t(delta), 0, 0, 0, 0,
-                  atomic_read(&tw->tw_refcnt), tw);
+                  refcount_read(&tw->tw_refcnt), tw);
 }
 
 static int tcp6_seq_show(struct seq_file *seq, void *v)
@@ -1909,6 +1922,7 @@ struct proto tcpv6_prot = {
        .unhash                 = inet_unhash,
        .get_port               = inet_csk_get_port,
        .enter_memory_pressure  = tcp_enter_memory_pressure,
+       .leave_memory_pressure  = tcp_leave_memory_pressure,
        .stream_memory_free     = tcp_stream_memory_free,
        .sockets_allocated      = &tcp_sockets_allocated,
        .memory_allocated       = &tcp_memory_allocated,