134 lines
3.8 KiB
C
134 lines
3.8 KiB
C
|
/*
|
||
|
* 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>
|
||
|
*
|
||
|
* Fixes:
|
||
|
* Alan Cox : UDP sockets show the rxqueue/txqueue
|
||
|
* using hint flag for the netinfo.
|
||
|
* Pauline Middelink : Pidentd support
|
||
|
* Alan Cox : Make /proc safer.
|
||
|
*
|
||
|
* To Do:
|
||
|
* Put the creating userid in the proc/net/... files. This will
|
||
|
* allow us to write an RFC931 daemon for Linux
|
||
|
*
|
||
|
* 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 <linux/param.h>
|
||
|
#include "inet.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"
|
||
|
|
||
|
/*
|
||
|
* 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, int format)
|
||
|
{
|
||
|
struct sock **s_array;
|
||
|
struct sock *sp;
|
||
|
char *pos=buffer;
|
||
|
int i;
|
||
|
int timer_active;
|
||
|
unsigned long dest, src;
|
||
|
unsigned short destp, srcp;
|
||
|
|
||
|
s_array = pro->sock_array;
|
||
|
pos+=sprintf(pos, "sl local_address rem_address st tx_queue rx_queue tr tm->when uid\n");
|
||
|
/*
|
||
|
* This was very pretty but didn't work when a socket is destroyed at the wrong moment
|
||
|
* (eg a syn recv socket getting a reset), or a memory timer destroy. Instead of playing
|
||
|
* with timers we just concede defeat and cli().
|
||
|
*/
|
||
|
for(i = 0; i < SOCK_ARRAY_SIZE; i++) {
|
||
|
cli();
|
||
|
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);
|
||
|
timer_active = del_timer(&sp->timer);
|
||
|
if (!timer_active)
|
||
|
sp->timer.expires = 0;
|
||
|
pos+=sprintf(pos, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d\n",
|
||
|
i, src, srcp, dest, destp, sp->state,
|
||
|
format==0?sp->send_seq-sp->rcv_ack_seq:sp->rmem_alloc,
|
||
|
format==0?sp->acked_seq-sp->copied_seq:sp->wmem_alloc,
|
||
|
timer_active, sp->timer.expires, (unsigned) sp->retransmits,
|
||
|
SOCK_INODE(sp->socket)->i_uid);
|
||
|
if (timer_active)
|
||
|
add_timer(&sp->timer);
|
||
|
/* 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;
|
||
|
}
|
||
|
sti(); /* We only turn interrupts back on for a moment, but because the interrupt queues anything built up
|
||
|
before this will clear before we jump back and cli, so its not as bad as it looks */
|
||
|
}
|
||
|
return(strlen(buffer));
|
||
|
}
|
||
|
|
||
|
|
||
|
int tcp_get_info(char *buffer)
|
||
|
{
|
||
|
return get__netinfo(&tcp_prot, buffer,0);
|
||
|
}
|
||
|
|
||
|
|
||
|
int udp_get_info(char *buffer)
|
||
|
{
|
||
|
return get__netinfo(&udp_prot, buffer,1);
|
||
|
}
|
||
|
|
||
|
|
||
|
int raw_get_info(char *buffer)
|
||
|
{
|
||
|
return get__netinfo(&raw_prot, buffer,1);
|
||
|
}
|