]> git.neil.brown.name Git - history.git/commitdiff
[IPV6]: Convert /proc/net/tcp6 to seq_file.
authorHideaki Yoshifuji <yoshfuji@linux-ipv6.org>
Sun, 25 May 2003 12:44:01 +0000 (05:44 -0700)
committerDavid S. Miller <davem@nuts.ninka.net>
Sun, 25 May 2003 12:44:01 +0000 (05:44 -0700)
net/ipv6/af_inet6.c
net/ipv6/tcp_ipv6.c

index 90dbbdecc6cfa26ff2c315bcabcdf1edbcf211c4..c77815599497b0c7c5af5450461d7fcfcea36d97 100644 (file)
@@ -77,7 +77,8 @@ MODULE_LICENSE("GPL");
 extern int raw6_proc_init(void);
 extern int raw6_proc_exit(void);
 
-extern int tcp6_get_info(char *, char **, off_t, int);
+extern int tcp6_proc_init(void);
+extern void tcp6_proc_exit(void);
 
 extern int udp6_proc_init(void);
 extern void udp6_proc_exit(void);
@@ -789,7 +790,7 @@ static int __init inet6_init(void)
        err = -ENOMEM;
        if (raw6_proc_init())
                goto proc_raw6_fail;
-       if (!proc_net_create("tcp6", 0, tcp6_get_info))
+       if (tcp6_proc_init())
                goto proc_tcp6_fail;
        if (udp6_proc_init())
                goto proc_udp6_fail;
@@ -824,7 +825,7 @@ proc_anycast6_fail:
 proc_misc6_fail:
        udp6_proc_exit();
 proc_udp6_fail:
-       proc_net_remove("tcp6");
+       tcp6_proc_exit();
 proc_tcp6_fail:
        raw6_proc_exit();
 proc_raw6_fail:
index d2920063972ca823832f0d02258a5c5d037caafb..ebcbc30701c5088e55ff2a9d2a361e60ec4deb42 100644 (file)
@@ -17,6 +17,7 @@
  *     YOSHIFUJI Hideaki @USAGI and:   Support IPV6_V6ONLY socket option, which
  *     Alexey Kuznetsov                allow both IPv4 and IPv6 sockets to bind
  *                                     a single port at the same time.
+ *     YOSHIFUJI Hideaki @USAGI:       convert /proc/net/tcp6 to seq_file.
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -55,6 +56,9 @@
 
 #include <asm/uaccess.h>
 
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
 static void    tcp_v6_send_reset(struct sk_buff *skb);
 static void    tcp_v6_or_send_ack(struct sk_buff *skb, struct open_request *req);
 static void    tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len, 
@@ -1934,7 +1938,8 @@ static int tcp_v6_destroy_sock(struct sock *sk)
 }
 
 /* Proc filesystem TCPv6 sock list dumping. */
-static void get_openreq6(struct sock *sk, struct open_request *req, char *tmpbuf, int i, int uid)
+static void get_openreq6(struct seq_file *seq, 
+                        struct sock *sk, struct open_request *req, int i, int uid)
 {
        struct in6_addr *dest, *src;
        int ttd = req->expires - jiffies;
@@ -1944,28 +1949,28 @@ static void get_openreq6(struct sock *sk, struct open_request *req, char *tmpbuf
 
        src = &req->af.v6_req.loc_addr;
        dest = &req->af.v6_req.rmt_addr;
-       sprintf(tmpbuf,
-               "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-               "%02X %08X:%08X %02X:%08X %08X %5d %8d %d %d %p",
-               i,
-               src->s6_addr32[0], src->s6_addr32[1],
-               src->s6_addr32[2], src->s6_addr32[3],
-               ntohs(inet_sk(sk)->sport),
-               dest->s6_addr32[0], dest->s6_addr32[1],
-               dest->s6_addr32[2], dest->s6_addr32[3],
-               ntohs(req->rmt_port),
-               TCP_SYN_RECV,
-               0,0, /* could print option size, but that is af dependent. */
-               1,   /* timers active (only the expire timer) */  
-               ttd, 
-               req->retrans,
-               uid,
-               0,  /* non standard timer */  
-               0, /* open_requests have no inode */
-               0, req);
+       seq_printf(seq,
+                  "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
+                  "%02X %08X:%08X %02X:%08X %08X %5d %8d %d %d %p\n",
+                  i,
+                  src->s6_addr32[0], src->s6_addr32[1],
+                  src->s6_addr32[2], src->s6_addr32[3],
+                  ntohs(inet_sk(sk)->sport),
+                  dest->s6_addr32[0], dest->s6_addr32[1],
+                  dest->s6_addr32[2], dest->s6_addr32[3],
+                  ntohs(req->rmt_port),
+                  TCP_SYN_RECV,
+                  0,0, /* could print option size, but that is af dependent. */
+                  1,   /* timers active (only the expire timer) */  
+                  ttd, 
+                  req->retrans,
+                  uid,
+                  0,  /* non standard timer */  
+                  0, /* open_requests have no inode */
+                  0, req);
 }
 
-static void get_tcp6_sock(struct sock *sp, char *tmpbuf, int i)
+static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
 {
        struct in6_addr *dest, *src;
        __u16 destp, srcp;
@@ -1993,28 +1998,29 @@ static void get_tcp6_sock(struct sock *sp, char *tmpbuf, int i)
                timer_expires = jiffies;
        }
 
-       sprintf(tmpbuf,
-               "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-               "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u %d",
-               i,
-               src->s6_addr32[0], src->s6_addr32[1],
-               src->s6_addr32[2], src->s6_addr32[3], srcp,
-               dest->s6_addr32[0], dest->s6_addr32[1],
-               dest->s6_addr32[2], dest->s6_addr32[3], destp,
-               sp->state, 
-               tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq,
-               timer_active, timer_expires-jiffies,
-               tp->retransmits,
-               sock_i_uid(sp),
-               tp->probes_out,
-               sock_i_ino(sp),
-               atomic_read(&sp->refcnt), sp,
-               tp->rto, tp->ack.ato, (tp->ack.quick<<1)|tp->ack.pingpong,
-               tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh
-               );
+       seq_printf(seq,
+                  "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
+                  "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u %d\n",
+                  i,
+                  src->s6_addr32[0], src->s6_addr32[1],
+                  src->s6_addr32[2], src->s6_addr32[3], srcp,
+                  dest->s6_addr32[0], dest->s6_addr32[1],
+                  dest->s6_addr32[2], dest->s6_addr32[3], destp,
+                  sp->state, 
+                  tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq,
+                  timer_active, timer_expires-jiffies,
+                  tp->retransmits,
+                  sock_i_uid(sp),
+                  tp->probes_out,
+                  sock_i_ino(sp),
+                  atomic_read(&sp->refcnt), sp,
+                  tp->rto, tp->ack.ato, (tp->ack.quick<<1)|tp->ack.pingpong,
+                  tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh
+                  );
 }
 
-static void get_timewait6_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i)
+static void get_timewait6_sock(struct seq_file *seq, 
+                              struct tcp_tw_bucket *tw, int i)
 {
        struct in6_addr *dest, *src;
        __u16 destp, srcp;
@@ -2028,144 +2034,67 @@ static void get_timewait6_sock(struct tcp_tw_bucket *tw, char *tmpbuf, int i)
        destp = ntohs(tw->dport);
        srcp  = ntohs(tw->sport);
 
-       sprintf(tmpbuf,
-               "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-               "%02X %08X:%08X %02X:%08X %08X %5d %8d %d %d %p",
-               i,
-               src->s6_addr32[0], src->s6_addr32[1],
-               src->s6_addr32[2], src->s6_addr32[3], srcp,
-               dest->s6_addr32[0], dest->s6_addr32[1],
-               dest->s6_addr32[2], dest->s6_addr32[3], destp,
-               tw->substate, 0, 0,
-               3, ttd, 0, 0, 0, 0,
-               atomic_read(&tw->refcnt), tw);
+       seq_printf(seq,
+                  "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
+                  "%02X %08X:%08X %02X:%08X %08X %5d %8d %d %d %p\n",
+                  i,
+                  src->s6_addr32[0], src->s6_addr32[1],
+                  src->s6_addr32[2], src->s6_addr32[3], srcp,
+                  dest->s6_addr32[0], dest->s6_addr32[1],
+                  dest->s6_addr32[2], dest->s6_addr32[3], destp,
+                  tw->substate, 0, 0,
+                  3, ttd, 0, 0, 0, 0,
+                  atomic_read(&tw->refcnt), tw);
 }
 
-#define LINE_LEN 190
-#define LINE_FMT "%-190s\n"
-
-int tcp6_get_info(char *buffer, char **start, off_t offset, int length)
+static int tcp6_seq_show(struct seq_file *seq, void *v)
 {
-       int len = 0, num = 0, i;
-       off_t begin, pos = 0;
-       char tmpbuf[LINE_LEN+2];
-
-       if (offset < LINE_LEN+1)
-               len += sprintf(buffer, LINE_FMT,
-                              "  sl  "                                         /* 6 */
-                              "local_address                         "         /* 38 */
-                              "remote_address                        "         /* 38 */
-                              "st tx_queue rx_queue tr tm->when retrnsmt"      /* 41 */
-                              "   uid  timeout inode");                        /* 21 */
-                                                                               /*----*/
-                                                                               /*144 */
-
-       pos = LINE_LEN+1;
-
-       /* First, walk listening socket table. */
-       tcp_listen_lock();
-       for(i = 0; i < TCP_LHTABLE_SIZE; i++) {
-               struct sock *sk = tcp_listening_hash[i];
-               struct tcp_listen_opt *lopt;
-               int k;
-
-               for (sk = tcp_listening_hash[i]; sk; sk = sk->next, num++) {
-                       struct open_request *req;
-                       int uid;
-                       struct tcp_opt *tp = tcp_sk(sk);
-
-                       if (sk->family != PF_INET6)
-                               continue;
-                       pos += LINE_LEN+1;
-                       if (pos >= offset) {
-                               get_tcp6_sock(sk, tmpbuf, num);
-                               len += sprintf(buffer+len, LINE_FMT, tmpbuf);
-                               if (pos >= offset + length) {
-                                       tcp_listen_unlock();
-                                       goto out_no_bh;
-                               }
-                       }
-
-                       uid = sock_i_uid(sk);
-                       read_lock_bh(&tp->syn_wait_lock);
-                       lopt = tp->listen_opt;
-                       if (lopt && lopt->qlen != 0) {
-                               for (k=0; k<TCP_SYNQ_HSIZE; k++) {
-                                       for (req = lopt->syn_table[k]; req; req = req->dl_next, num++) {
-                                               if (req->class->family != PF_INET6)
-                                                       continue;
-                                               pos += LINE_LEN+1;
-                                               if (pos <= offset)
-                                                       continue;
-                                               get_openreq6(sk, req, tmpbuf, num, uid);
-                                               len += sprintf(buffer+len, LINE_FMT, tmpbuf);
-                                               if (pos >= offset + length) { 
-                                                       read_unlock_bh(&tp->syn_wait_lock);
-                                                       tcp_listen_unlock();
-                                                       goto out_no_bh;
-                                               }
-                                       }
-                               }
-                       }
-                       read_unlock_bh(&tp->syn_wait_lock);
+       struct tcp_iter_state *st;
+
+       if (v == (void *)1) {
+               seq_printf(seq,
+                          "  sl  "
+                          "local_address                         "
+                          "remote_address                        "
+                          "st tx_queue rx_queue tr tm->when retrnsmt"
+                          "   uid  timeout inode\n");
+               goto out;
+       }
+       st = seq->private;
 
-                       /* Completed requests are in normal socket hash table */
-               }
+       switch (st->state) {
+       case TCP_SEQ_STATE_LISTENING:
+       case TCP_SEQ_STATE_ESTABLISHED:
+               get_tcp6_sock(seq, v, st->num);
+               break;
+       case TCP_SEQ_STATE_OPENREQ:
+               get_openreq6(seq, st->syn_wait_sk, v, st->num, st->uid);
+               break;
+       case TCP_SEQ_STATE_TIME_WAIT:
+               get_timewait6_sock(seq, v, st->num);
+               break;
        }
-       tcp_listen_unlock();
+out:
+       return 0;
+}
 
-       local_bh_disable();
+static struct file_operations tcp6_seq_fops;
+static struct tcp_seq_afinfo tcp6_seq_afinfo = {
+       .owner          = THIS_MODULE,
+       .name           = "tcp6",
+       .family         = AF_INET6,
+       .seq_show       = tcp6_seq_show,
+       .seq_fops       = &tcp6_seq_fops,
+};
 
-       /* Next, walk established hash chain. */
-       for (i = 0; i < tcp_ehash_size; i++) {
-               struct tcp_ehash_bucket *head = &tcp_ehash[i];
-               struct sock *sk;
-               struct tcp_tw_bucket *tw;
-
-               read_lock(&head->lock);
-               for(sk = head->chain; sk; sk = sk->next, num++) {
-                       if (sk->family != PF_INET6)
-                               continue;
-                       pos += LINE_LEN+1;
-                       if (pos <= offset)
-                               continue;
-                       get_tcp6_sock(sk, tmpbuf, num);
-                       len += sprintf(buffer+len, LINE_FMT, tmpbuf);
-                       if (pos >= offset + length) {
-                               read_unlock(&head->lock);
-                               goto out;
-                       }
-               }
-               for (tw = (struct tcp_tw_bucket *)tcp_ehash[i+tcp_ehash_size].chain;
-                    tw != NULL;
-                    tw = (struct tcp_tw_bucket *)tw->next, num++) {
-                       if (tw->family != PF_INET6)
-                               continue;
-                       pos += LINE_LEN+1;
-                       if (pos <= offset)
-                               continue;
-                       get_timewait6_sock(tw, tmpbuf, num);
-                       len += sprintf(buffer+len, LINE_FMT, tmpbuf);
-                       if (pos >= offset + length) {
-                               read_unlock(&head->lock);
-                               goto out;
-                       }
-               }
-               read_unlock(&head->lock);
-       }
+int __init tcp6_proc_init(void)
+{
+       return tcp_proc_register(&tcp6_seq_afinfo);
+}
 
-out:
-       local_bh_enable();
-out_no_bh:
-
-       begin = len - (pos - offset);
-       *start = buffer + begin;
-       len -= begin;
-       if (len > length)
-               len = length;
-       if (len < 0)
-               len = 0; 
-       return len;
+void tcp6_proc_exit(void)
+{
+       tcp_proc_unregister(&tcp6_seq_afinfo);
 }
 
 struct proto tcpv6_prot = {