[NET]: Introduce inet_connection_sock
[firefly-linux-kernel-4.4.55.git] / net / ipv4 / tcp_diag.c
index 8faa8948f75c2d67db9643dc07b24af7abc609a5..5f4c74f45e82e147b8688cf64a2e68fa0a309b7b 100644 (file)
@@ -42,26 +42,19 @@ struct tcpdiag_entry
 
 static struct sock *tcpnl;
 
-
 #define TCPDIAG_PUT(skb, attrtype, attrlen) \
-({ int rtalen = RTA_LENGTH(attrlen);        \
-   struct rtattr *rta;                      \
-   if (skb_tailroom(skb) < RTA_ALIGN(rtalen)) goto nlmsg_failure; \
-   rta = (void*)__skb_put(skb, RTA_ALIGN(rtalen)); \
-   rta->rta_type = attrtype;                \
-   rta->rta_len = rtalen;                   \
-   RTA_DATA(rta); })
+       RTA_DATA(__RTA_PUT(skb, attrtype, attrlen))
 
 static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
                        int ext, u32 pid, u32 seq, u16 nlmsg_flags)
 {
-       struct inet_sock *inet = inet_sk(sk);
+       const struct inet_sock *inet = inet_sk(sk);
        struct tcp_sock *tp = tcp_sk(sk);
+       const struct inet_connection_sock *icsk = inet_csk(sk);
        struct tcpdiagmsg *r;
        struct nlmsghdr  *nlh;
        struct tcp_info  *info = NULL;
        struct tcpdiag_meminfo  *minfo = NULL;
-       struct tcpvegas_info *vinfo = NULL;
        unsigned char    *b = skb->tail;
 
        nlh = NLMSG_PUT(skb, pid, seq, TCPDIAG_GETSOCK, sizeof(*r));
@@ -73,9 +66,11 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
                if (ext & (1<<(TCPDIAG_INFO-1)))
                        info = TCPDIAG_PUT(skb, TCPDIAG_INFO, sizeof(*info));
                
-               if ((tcp_is_westwood(tp) || tcp_is_vegas(tp))
-                   && (ext & (1<<(TCPDIAG_VEGASINFO-1))))
-                       vinfo = TCPDIAG_PUT(skb, TCPDIAG_VEGASINFO, sizeof(*vinfo));
+               if (ext & (1<<(TCPDIAG_CONG-1))) {
+                       size_t len = strlen(tp->ca_ops->name);
+                       strcpy(TCPDIAG_PUT(skb, TCPDIAG_CONG, len+1),
+                              tp->ca_ops->name);
+               }
        }
        r->tcpdiag_family = sk->sk_family;
        r->tcpdiag_state = sk->sk_state;
@@ -87,7 +82,7 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
        r->id.tcpdiag_cookie[1] = (u32)(((unsigned long)sk >> 31) >> 1);
 
        if (r->tcpdiag_state == TCP_TIME_WAIT) {
-               struct tcp_tw_bucket *tw = (struct tcp_tw_bucket*)sk;
+               const struct inet_timewait_sock *tw = inet_twsk(sk);
                long tmo = tw->tw_ttd - jiffies;
                if (tmo < 0)
                        tmo = 0;
@@ -105,10 +100,12 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
                r->tcpdiag_inode = 0;
 #ifdef CONFIG_IP_TCPDIAG_IPV6
                if (r->tcpdiag_family == AF_INET6) {
+                       const struct tcp6_timewait_sock *tcp6tw = tcp6_twsk(sk);
+
                        ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src,
-                                      &tw->tw_v6_rcv_saddr);
+                                      &tcp6tw->tw_v6_rcv_saddr);
                        ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_dst,
-                                      &tw->tw_v6_daddr);
+                                      &tcp6tw->tw_v6_daddr);
                }
 #endif
                nlh->nlmsg_len = skb->tail - b;
@@ -133,14 +130,14 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
 
 #define EXPIRES_IN_MS(tmo)  ((tmo-jiffies)*1000+HZ-1)/HZ
 
-       if (tp->pending == TCP_TIME_RETRANS) {
+       if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
                r->tcpdiag_timer = 1;
-               r->tcpdiag_retrans = tp->retransmits;
-               r->tcpdiag_expires = EXPIRES_IN_MS(tp->timeout);
-       } else if (tp->pending == TCP_TIME_PROBE0) {
+               r->tcpdiag_retrans = icsk->icsk_retransmits;
+               r->tcpdiag_expires = EXPIRES_IN_MS(icsk->icsk_timeout);
+       } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
                r->tcpdiag_timer = 4;
                r->tcpdiag_retrans = tp->probes_out;
-               r->tcpdiag_expires = EXPIRES_IN_MS(tp->timeout);
+               r->tcpdiag_expires = EXPIRES_IN_MS(icsk->icsk_timeout);
        } else if (timer_pending(&sk->sk_timer)) {
                r->tcpdiag_timer = 2;
                r->tcpdiag_retrans = tp->probes_out;
@@ -166,30 +163,18 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
        if (info) 
                tcp_get_info(sk, info);
 
-       if (vinfo) {
-               if (tcp_is_vegas(tp)) {
-                       vinfo->tcpv_enabled = tp->vegas.doing_vegas_now;
-                       vinfo->tcpv_rttcnt = tp->vegas.cntRTT;
-                       vinfo->tcpv_rtt = jiffies_to_usecs(tp->vegas.baseRTT);
-                       vinfo->tcpv_minrtt = jiffies_to_usecs(tp->vegas.minRTT);
-               } else {
-                       vinfo->tcpv_enabled = 0;
-                       vinfo->tcpv_rttcnt = 0;
-                       vinfo->tcpv_rtt = jiffies_to_usecs(tp->westwood.rtt);
-                       vinfo->tcpv_minrtt = jiffies_to_usecs(tp->westwood.rtt_min);
-               }
-       }
+       if (sk->sk_state < TCP_TIME_WAIT && tp->ca_ops->get_info)
+               tp->ca_ops->get_info(tp, ext, skb);
 
        nlh->nlmsg_len = skb->tail - b;
        return skb->len;
 
+rtattr_failure:
 nlmsg_failure:
        skb_trim(skb, b - skb->data);
        return -1;
 }
 
-extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport,
-                                 int dif);
 #ifdef CONFIG_IP_TCPDIAG_IPV6
 extern struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport,
                                  struct in6_addr *daddr, u16 dport,
@@ -211,9 +196,9 @@ static int tcpdiag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh)
        struct sk_buff *rep;
 
        if (req->tcpdiag_family == AF_INET) {
-               sk = tcp_v4_lookup(req->id.tcpdiag_dst[0], req->id.tcpdiag_dport,
-                                  req->id.tcpdiag_src[0], req->id.tcpdiag_sport,
-                                  req->id.tcpdiag_if);
+               sk = inet_lookup(&tcp_hashinfo, req->id.tcpdiag_dst[0],
+                                req->id.tcpdiag_dport, req->id.tcpdiag_src[0],
+                                req->id.tcpdiag_sport, req->id.tcpdiag_if);
        }
 #ifdef CONFIG_IP_TCPDIAG_IPV6
        else if (req->tcpdiag_family == AF_INET6) {
@@ -255,7 +240,7 @@ static int tcpdiag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh)
 out:
        if (sk) {
                if (sk->sk_state == TCP_TIME_WAIT)
-                       tcp_tw_put((struct tcp_tw_bucket*)sk);
+                       inet_twsk_put((struct inet_timewait_sock *)sk);
                else
                        sock_put(sk);
        }
@@ -455,9 +440,10 @@ static int tcpdiag_dump_sock(struct sk_buff *skb, struct sock *sk,
 }
 
 static int tcpdiag_fill_req(struct sk_buff *skb, struct sock *sk,
-                           struct open_request *req,
+                           struct request_sock *req,
                            u32 pid, u32 seq)
 {
+       const struct inet_request_sock *ireq = inet_rsk(req);
        struct inet_sock *inet = inet_sk(sk);
        unsigned char *b = skb->tail;
        struct tcpdiagmsg *r;
@@ -482,9 +468,9 @@ static int tcpdiag_fill_req(struct sk_buff *skb, struct sock *sk,
                tmo = 0;
 
        r->id.tcpdiag_sport = inet->sport;
-       r->id.tcpdiag_dport = req->rmt_port;
-       r->id.tcpdiag_src[0] = req->af.v4_req.loc_addr;
-       r->id.tcpdiag_dst[0] = req->af.v4_req.rmt_addr;
+       r->id.tcpdiag_dport = ireq->rmt_port;
+       r->id.tcpdiag_src[0] = ireq->loc_addr;
+       r->id.tcpdiag_dst[0] = ireq->rmt_addr;
        r->tcpdiag_expires = jiffies_to_msecs(tmo),
        r->tcpdiag_rqueue = 0;
        r->tcpdiag_wqueue = 0;
@@ -493,9 +479,9 @@ static int tcpdiag_fill_req(struct sk_buff *skb, struct sock *sk,
 #ifdef CONFIG_IP_TCPDIAG_IPV6
        if (r->tcpdiag_family == AF_INET6) {
                ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src,
-                              &req->af.v6_req.loc_addr);
+                              &tcp6_rsk(req)->loc_addr);
                ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_dst,
-                              &req->af.v6_req.rmt_addr);
+                              &tcp6_rsk(req)->rmt_addr);
        }
 #endif
        nlh->nlmsg_len = skb->tail - b;
@@ -512,8 +498,8 @@ static int tcpdiag_dump_reqs(struct sk_buff *skb, struct sock *sk,
 {
        struct tcpdiag_entry entry;
        struct tcpdiagreq *r = NLMSG_DATA(cb->nlh);
-       struct tcp_sock *tp = tcp_sk(sk);
-       struct tcp_listen_opt *lopt;
+       struct inet_connection_sock *icsk = inet_csk(sk);
+       struct listen_sock *lopt;
        struct rtattr *bc = NULL;
        struct inet_sock *inet = inet_sk(sk);
        int j, s_j;
@@ -528,9 +514,9 @@ static int tcpdiag_dump_reqs(struct sk_buff *skb, struct sock *sk,
 
        entry.family = sk->sk_family;
 
-       read_lock_bh(&tp->syn_wait_lock);
+       read_lock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
 
-       lopt = tp->listen_opt;
+       lopt = icsk->icsk_accept_queue.listen_opt;
        if (!lopt || !lopt->qlen)
                goto out;
 
@@ -541,13 +527,15 @@ static int tcpdiag_dump_reqs(struct sk_buff *skb, struct sock *sk,
        }
 
        for (j = s_j; j < TCP_SYNQ_HSIZE; j++) {
-               struct open_request *req, *head = lopt->syn_table[j];
+               struct request_sock *req, *head = lopt->syn_table[j];
 
                reqnum = 0;
                for (req = head; req; reqnum++, req = req->dl_next) {
+                       struct inet_request_sock *ireq = inet_rsk(req);
+
                        if (reqnum < s_reqnum)
                                continue;
-                       if (r->id.tcpdiag_dport != req->rmt_port &&
+                       if (r->id.tcpdiag_dport != ireq->rmt_port &&
                            r->id.tcpdiag_dport)
                                continue;
 
@@ -555,16 +543,16 @@ static int tcpdiag_dump_reqs(struct sk_buff *skb, struct sock *sk,
                                entry.saddr =
 #ifdef CONFIG_IP_TCPDIAG_IPV6
                                        (entry.family == AF_INET6) ?
-                                       req->af.v6_req.loc_addr.s6_addr32 :
+                                       tcp6_rsk(req)->loc_addr.s6_addr32 :
 #endif
-                                       &req->af.v4_req.loc_addr;
+                                       &ireq->loc_addr;
                                entry.daddr = 
 #ifdef CONFIG_IP_TCPDIAG_IPV6
                                        (entry.family == AF_INET6) ?
-                                       req->af.v6_req.rmt_addr.s6_addr32 :
+                                       tcp6_rsk(req)->rmt_addr.s6_addr32 :
 #endif
-                                       &req->af.v4_req.rmt_addr;
-                               entry.dport = ntohs(req->rmt_port);
+                                       &ireq->rmt_addr;
+                               entry.dport = ntohs(ireq->rmt_port);
 
                                if (!tcpdiag_bc_run(RTA_DATA(bc),
                                                    RTA_PAYLOAD(bc), &entry))
@@ -585,7 +573,7 @@ static int tcpdiag_dump_reqs(struct sk_buff *skb, struct sock *sk,
        }
 
 out:
-       read_unlock_bh(&tp->syn_wait_lock);
+       read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
 
        return err;
 }
@@ -602,13 +590,13 @@ static int tcpdiag_dump(struct sk_buff *skb, struct netlink_callback *cb)
        if (cb->args[0] == 0) {
                if (!(r->tcpdiag_states&(TCPF_LISTEN|TCPF_SYN_RECV)))
                        goto skip_listen_ht;
-               tcp_listen_lock();
-               for (i = s_i; i < TCP_LHTABLE_SIZE; i++) {
+               inet_listen_lock(&tcp_hashinfo);
+               for (i = s_i; i < INET_LHTABLE_SIZE; i++) {
                        struct sock *sk;
                        struct hlist_node *node;
 
                        num = 0;
-                       sk_for_each(sk, node, &tcp_listening_hash[i]) {
+                       sk_for_each(sk, node, &tcp_hashinfo.listening_hash[i]) {
                                struct inet_sock *inet = inet_sk(sk);
 
                                if (num < s_num) {
@@ -626,7 +614,7 @@ static int tcpdiag_dump(struct sk_buff *skb, struct netlink_callback *cb)
                                        goto syn_recv;
 
                                if (tcpdiag_dump_sock(skb, sk, cb) < 0) {
-                                       tcp_listen_unlock();
+                                       inet_listen_unlock(&tcp_hashinfo);
                                        goto done;
                                }
 
@@ -635,7 +623,7 @@ syn_recv:
                                        goto next_listen;
 
                                if (tcpdiag_dump_reqs(skb, sk, cb) < 0) {
-                                       tcp_listen_unlock();
+                                       inet_listen_unlock(&tcp_hashinfo);
                                        goto done;
                                }
 
@@ -649,7 +637,7 @@ next_listen:
                        cb->args[3] = 0;
                        cb->args[4] = 0;
                }
-               tcp_listen_unlock();
+               inet_listen_unlock(&tcp_hashinfo);
 skip_listen_ht:
                cb->args[0] = 1;
                s_i = num = s_num = 0;
@@ -658,8 +646,8 @@ skip_listen_ht:
        if (!(r->tcpdiag_states&~(TCPF_LISTEN|TCPF_SYN_RECV)))
                return skb->len;
 
-       for (i = s_i; i < tcp_ehash_size; i++) {
-               struct tcp_ehash_bucket *head = &tcp_ehash[i];
+       for (i = s_i; i < tcp_hashinfo.ehash_size; i++) {
+               struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[i];
                struct sock *sk;
                struct hlist_node *node;
 
@@ -691,7 +679,7 @@ next_normal:
 
                if (r->tcpdiag_states&TCPF_TIME_WAIT) {
                        sk_for_each(sk, node,
-                                   &tcp_ehash[i + tcp_ehash_size].chain) {
+                                   &tcp_hashinfo.ehash[i + tcp_hashinfo.ehash_size].chain) {
                                struct inet_sock *inet = inet_sk(sk);
 
                                if (num < s_num)
@@ -787,7 +775,8 @@ static void tcpdiag_rcv(struct sock *sk, int len)
 
 static int __init tcpdiag_init(void)
 {
-       tcpnl = netlink_kernel_create(NETLINK_TCPDIAG, tcpdiag_rcv);
+       tcpnl = netlink_kernel_create(NETLINK_TCPDIAG, tcpdiag_rcv,
+                                     THIS_MODULE);
        if (tcpnl == NULL)
                return -ENOMEM;
        return 0;