Merge tag 'v3.10.76' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / ipv4 / tcp_ipv4.c
index 719652305a2950a3407804136bf7f42dc1d18e15..23f97a0cfc18b9f1d7b951b041e865e65b4590d6 100644 (file)
@@ -176,7 +176,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        if (IS_ERR(rt)) {
                err = PTR_ERR(rt);
                if (err == -ENETUNREACH)
-                       IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
+                       IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
                return err;
        }
 
@@ -233,7 +233,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        /* OK, now commit destination to socket.  */
        sk->sk_gso_type = SKB_GSO_TCPV4;
        sk_setup_caps(sk, &rt->dst);
-
+        printk(KERN_INFO "[socket_conn]IPV4 socket[%lu] sport:%u \n", SOCK_INODE(sk->sk_socket)->i_ino, ntohs(inet->inet_sport));
        if (!tp->write_seq && likely(!tp->repair))
                tp->write_seq = secure_tcp_sequence_number(inet->inet_saddr,
                                                           inet->inet_daddr,
@@ -268,7 +268,7 @@ EXPORT_SYMBOL(tcp_v4_connect);
  * It can be called through tcp_release_cb() if socket was owned by user
  * at the time tcp_v4_err() was called to handle ICMP message.
  */
-static void tcp_v4_mtu_reduced(struct sock *sk)
+void tcp_v4_mtu_reduced(struct sock *sk)
 {
        struct dst_entry *dst;
        struct inet_sock *inet = inet_sk(sk);
@@ -298,6 +298,7 @@ static void tcp_v4_mtu_reduced(struct sock *sk)
                tcp_simple_retransmit(sk);
        } /* else let the usual retransmit timer handle it */
 }
+EXPORT_SYMBOL(tcp_v4_mtu_reduced);
 
 static void do_redirect(struct sk_buff *skb, struct sock *sk)
 {
@@ -445,7 +446,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
 
                if (remaining) {
                        inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
-                                                 remaining, TCP_RTO_MAX);
+                                                 remaining, sysctl_tcp_rto_max);
                } else {
                        /* RTO revert clocked out retransmission.
                         * Will retransmit now */
@@ -706,7 +707,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
 
        net = dev_net(skb_dst(skb)->dev);
        arg.tos = ip_hdr(skb)->tos;
-       ip_send_unicast_reply(net, skb, ip_hdr(skb)->saddr,
+       ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
+                             skb, ip_hdr(skb)->saddr,
                              ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len);
 
        TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
@@ -789,7 +791,8 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
        if (oif)
                arg.bound_dev_if = oif;
        arg.tos = tos;
-       ip_send_unicast_reply(net, skb, ip_hdr(skb)->saddr,
+       ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
+                             skb, ip_hdr(skb)->saddr,
                              ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len);
 
        TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
@@ -1003,7 +1006,7 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
        struct tcp_sock *tp = tcp_sk(sk);
        struct tcp_md5sig_info *md5sig;
 
-       key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET);
+       key = tcp_md5_do_lookup(sk, addr, family);
        if (key) {
                /* Pre-existing entry - just update that one. */
                memcpy(key->key, newkey, newkeylen);
@@ -1048,7 +1051,7 @@ int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family)
        struct tcp_md5sig_key *key;
        struct tcp_md5sig_info *md5sig;
 
-       key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET);
+       key = tcp_md5_do_lookup(sk, addr, family);
        if (!key)
                return -ENOENT;
        hlist_del_rcu(&key->node);
@@ -1423,7 +1426,7 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk,
         * because it's been added to the accept queue directly.
         */
        inet_csk_reset_xmit_timer(child, ICSK_TIME_RETRANS,
-           TCP_TIMEOUT_INIT, TCP_RTO_MAX);
+           TCP_TIMEOUT_INIT, sysctl_tcp_rto_max);
 
        /* Add the child socket directly into the accept queue */
        inet_csk_reqsk_queue_add(sk, req, child);
@@ -1527,6 +1530,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
        ireq->rmt_addr = saddr;
        ireq->no_srccheck = inet_sk(sk)->transparent;
        ireq->opt = tcp_v4_save_options(skb);
+       ireq->ir_mark = inet_request_mark(sk, skb);
 
        if (security_inet_conn_request(sk, skb, req))
                goto drop_and_free;
@@ -1898,7 +1902,7 @@ void tcp_v4_early_demux(struct sk_buff *skb)
                skb->sk = sk;
                skb->destructor = sock_edemux;
                if (sk->sk_state != TCP_TIME_WAIT) {
-                       struct dst_entry *dst = sk->sk_rx_dst;
+                       struct dst_entry *dst = ACCESS_ONCE(sk->sk_rx_dst);
 
                        if (dst)
                                dst = dst_check(dst, 0);
@@ -1948,7 +1952,7 @@ bool tcp_prequeue(struct sock *sk, struct sk_buff *skb)
                if (!inet_csk_ack_scheduled(sk))
                        inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
                                                  (3 * tcp_rto_min(sk)) / 4,
-                                                 TCP_RTO_MAX);
+                                                 sysctl_tcp_rto_max);
        }
        return true;
 }
@@ -2142,6 +2146,7 @@ const struct inet_connection_sock_af_ops ipv4_specific = {
        .compat_setsockopt = compat_ip_setsockopt,
        .compat_getsockopt = compat_ip_getsockopt,
 #endif
+       .mtu_reduced       = tcp_v4_mtu_reduced,
 };
 EXPORT_SYMBOL(ipv4_specific);
 
@@ -2161,6 +2166,7 @@ static int tcp_v4_init_sock(struct sock *sk)
        struct inet_connection_sock *icsk = inet_csk(sk);
 
        tcp_init_sock(sk);
+        icsk->icsk_MMSRB = 0;
 
        icsk->icsk_af_ops = &ipv4_specific;
 
@@ -2216,6 +2222,115 @@ void tcp_v4_destroy_sock(struct sock *sk)
 }
 EXPORT_SYMBOL(tcp_v4_destroy_sock);
 
+void tcp_v4_handle_retrans_time_by_uid(struct uid_err uid_e)
+{
+    unsigned int bucket;
+    uid_t skuid = (uid_t)(uid_e.appuid);
+       struct inet_connection_sock *icsk = NULL;//inet_csk(sk);
+
+
+    for (bucket = 0; bucket < tcp_hashinfo.ehash_mask; bucket++) {
+        struct hlist_nulls_node *node;
+        struct sock *sk;
+        spinlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, bucket);
+    
+        spin_lock_bh(lock);
+        sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[bucket].chain) {
+    
+            if (sysctl_ip_dynaddr && sk->sk_state == TCP_SYN_SENT)
+                continue;
+            if (sock_flag(sk, SOCK_DEAD))
+                continue;
+    
+            if(sk->sk_socket){
+                if(SOCK_INODE(sk->sk_socket)->i_uid != skuid)
+                    continue;
+                else
+                    printk("[mmspb] tcp_v4_handle_retrans_time_by_uid socket uid(%d) match!",
+                        SOCK_INODE(sk->sk_socket)->i_uid);
+            } else{
+                continue;
+           }
+
+                sock_hold(sk);
+                spin_unlock_bh(lock);
+    
+                local_bh_disable();
+                bh_lock_sock(sk);
+
+                // update sk time out value
+               icsk = inet_csk(sk);
+               printk("[mmspb] tcp_v4_handle_retrans_time_by_uid update timer\n");
+                                       
+               sk_reset_timer(sk, &icsk->icsk_retransmit_timer, jiffies + 2);
+               icsk->icsk_rto = sysctl_tcp_rto_min * 30;       
+               icsk->icsk_MMSRB = 1;
+                               
+                bh_unlock_sock(sk);
+                local_bh_enable();
+               spin_lock_bh(lock);
+                sock_put(sk);
+
+            }
+            spin_unlock_bh(lock);
+        }
+
+}
+
+
+/*
+ * tcp_v4_nuke_addr_by_uid - destroy all sockets of spcial uid
+ */
+void tcp_v4_reset_connections_by_uid(struct uid_err uid_e)
+{
+    unsigned int bucket;
+    uid_t skuid = (uid_t)(uid_e.appuid);
+
+    for (bucket = 0; bucket < tcp_hashinfo.ehash_mask; bucket++) {
+        struct hlist_nulls_node *node;
+        struct sock *sk;
+        spinlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, bucket);
+    
+restart:
+        spin_lock_bh(lock);
+        sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[bucket].chain) {
+    
+            if (sysctl_ip_dynaddr && sk->sk_state == TCP_SYN_SENT)
+                continue;
+            if (sock_flag(sk, SOCK_DEAD))
+                continue;
+    
+            if(sk->sk_socket){
+                if(SOCK_INODE(sk->sk_socket)->i_uid != skuid)
+                    continue;
+                else
+                    printk(KERN_INFO "SIOCKILLSOCK socket uid(%d) match!",
+                        SOCK_INODE(sk->sk_socket)->i_uid);
+            } else{
+                continue;
+           }
+
+                sock_hold(sk);
+                spin_unlock_bh(lock);
+    
+                local_bh_disable();
+                bh_lock_sock(sk);
+                sk->sk_err = uid_e.errNum;
+                printk(KERN_INFO "SIOCKILLSOCK set sk err == %d!! \n", sk->sk_err);
+                sk->sk_error_report(sk);
+    
+                tcp_done(sk);
+                bh_unlock_sock(sk);
+                local_bh_enable();
+                sock_put(sk);
+
+                goto restart;
+            }
+            spin_unlock_bh(lock);
+        }
+}
+
+
 #ifdef CONFIG_PROC_FS
 /* Proc filesystem TCP sock list dumping. */
 
@@ -2867,7 +2982,6 @@ struct proto tcp_prot = {
        .sendpage               = tcp_sendpage,
        .backlog_rcv            = tcp_v4_do_rcv,
        .release_cb             = tcp_release_cb,
-       .mtu_reduced            = tcp_v4_mtu_reduced,
        .hash                   = inet_hash,
        .unhash                 = inet_unhash,
        .get_port               = inet_csk_get_port,
@@ -2897,14 +3011,39 @@ struct proto tcp_prot = {
 };
 EXPORT_SYMBOL(tcp_prot);
 
+static void __net_exit tcp_sk_exit(struct net *net)
+{
+       int cpu;
+
+       for_each_possible_cpu(cpu)
+               inet_ctl_sock_destroy(*per_cpu_ptr(net->ipv4.tcp_sk, cpu));
+       free_percpu(net->ipv4.tcp_sk);
+}
+
 static int __net_init tcp_sk_init(struct net *net)
 {
+       int res, cpu;
+
+       net->ipv4.tcp_sk = alloc_percpu(struct sock *);
+       if (!net->ipv4.tcp_sk)
+               return -ENOMEM;
+
+       for_each_possible_cpu(cpu) {
+               struct sock *sk;
+
+               res = inet_ctl_sock_create(&sk, PF_INET, SOCK_RAW,
+                                          IPPROTO_TCP, net);
+               if (res)
+                       goto fail;
+               *per_cpu_ptr(net->ipv4.tcp_sk, cpu) = sk;
+       }
        net->ipv4.sysctl_tcp_ecn = 2;
        return 0;
-}
 
-static void __net_exit tcp_sk_exit(struct net *net)
-{
+fail:
+       tcp_sk_exit(net);
+
+       return res;
 }
 
 static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list)