blob: 5d1dc3d0028bd13b60cb310936acb0791058480e [file] [log] [blame]
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* This file implements the various access functions for the
* PROC file system. It is mainly used for debugging and
* statistics.
*
* Version: @(#)proc.c 1.0.5 05/27/93
*
* Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
* Fred Baumgarten, <dc6iq@insu1.etec.uni-karlsruhe.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <asm/system.h>
#include <linux/autoconf.h>
#include <linux/sched.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/un.h>
#include <linux/in.h>
#include <sys/param.h>
#include "inet.h"
#include "timer.h"
#include "dev.h"
#include "ip.h"
#include "protocol.h"
#include "tcp.h"
#include "udp.h"
#include "skbuff.h"
#include "sock.h"
#include "raw.h"
extern struct timer *timer_base;
/*
* Get__netinfo returns the length of that string.
*
* KNOWN BUGS
* As in get_unix_netinfo, the buffer might be too small. If this
* happens, get__netinfo returns only part of the available infos.
*/
static int
get__netinfo(struct proto *pro, char *buffer)
{
struct sock **s_array;
struct sock *sp;
char *pos=buffer;
int i;
unsigned long dest, src;
unsigned short destp, srcp;
struct timer *tp;
s_array = pro->sock_array;
pos+=sprintf(pos, "sl local_address rem_address st tx_queue rx_queue tr tm->when\n");
for(i = 0; i < SOCK_ARRAY_SIZE; i++) {
sp = s_array[i];
while(sp != NULL) {
dest = sp->daddr;
src = sp->saddr;
destp = sp->dummy_th.dest;
srcp = sp->dummy_th.source;
/* Since we are Little Endian we need to swap the bytes :-( */
destp = ntohs(destp);
srcp = ntohs(srcp);
pos+=sprintf(pos, "%2d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08X %02X",
i, src, srcp, dest, destp, sp->state,
sp->send_seq-sp->rcv_ack_seq, sp->acked_seq-sp->copied_seq,
sp->time_wait.running, sp->time_wait.when-jiffies, sp->retransmits);
cli();
tp = timer_base;
while (tp) {
if (tp == &(sp->time_wait)) {
pos+=sprintf(pos, " *");
}
tp = tp->next;
}
sti();
pos+=sprintf(pos, "\n");
/* Is place in buffer too rare? then abort. */
if (pos > buffer+PAGE_SIZE-80) {
printk("oops, too many %s sockets for netinfo.\n",
pro->name);
return(strlen(buffer));
}
/*
* All sockets with (port mod SOCK_ARRAY_SIZE) = i
* are kept in sock_array[i], so we must follow the
* 'next' link to get them all.
*/
sp = sp->next;
}
}
return(strlen(buffer));
}
int tcp_get_info(char *buffer)
{
return get__netinfo(&tcp_prot, buffer);
}
int udp_get_info(char *buffer)
{
return get__netinfo(&udp_prot, buffer);
}
int raw_get_info(char *buffer)
{
return get__netinfo(&raw_prot, buffer);
}