/****************************************************** Desolation of the Dragon MUD II (C) 1997-2003 Jesse DeFer http://www.dotd.com dotd@dotd.com ******************************************************/ #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include "mud.h" /* Netstat for SMAUG v1.01 * * Works only on Linux because it needs /proc/net/tcp * If you don't have a sin_addr var in your descriptor, * then this won't work with name resolving turned on * * To add sin_addr: * In mud.h, in your descriptor_data structure, add: * struct in_addr sin_addr; * in comm.c, in new_descriptor add: * memcpy(&dnew->sin_addr, &sock.sin_addr, sizeof(dnew->sin_addr)); * below the dnew->port = ntohs( sock.sin_addr ); line * also remove the #if DESCRIPTOR_HAS_SIN_ADDR lines below */ extern int port; #define MUDPORT port bool compare_ip(DESCRIPTOR_DATA *d, unsigned int ip) { struct in_addr inp; #if DESCRIPTOR_HAS_SIN_ADDR if (ip == d->sin_addr.s_addr) return TRUE; #endif if (inet_aton(d->host, &inp) && ip == inp.s_addr) return TRUE; return FALSE; } void do_netstat( CHAR_DATA *ch, char *argument ) { char buf[MAX_INPUT_LENGTH]; FILE *fp; DESCRIPTOR_DATA *d; struct in_addr inp; int x, st, txq, rxq, tr, retrans; unsigned int localip, remoteip; unsigned short int localport, remoteport; unsigned int when; if (argument && !str_cmp(argument, "help")) { send_to_char("Name - Players name\n\r" "Remote Address - IP and Host of player\n\r" "RecvQ - Kernel TCP Receive Buffer\n\r" "SendQ - Kernel TCP Send Buffer \n\r" "Timer - TCP Retransmit Timer\n\r" "Retrans - Number of retransmits\n\r\n\r", ch); send_to_char("NOTES: When a player is experiencing network lag, you will likely see\n\r" " an increase in the SendQ, and non-zero values in Timer and Retrans.\n\r" " When Timer is non-zero, it will be that many seconds before the\n\r" " player will receive any data from the MUD. If the value is very\n\r" " large (it may grow to over a minute) then the player is severly\n\r" " lagging and is unlikely to recover. Non-zero values in Timer however\n\r" " are not necessarily a bad thing as TCP is designed this way and can\n\r" " recover. You should probably never see RecvQ greater than zero.\n\r", ch); return; } if (!(fp = fopen("/proc/net/tcp", "r"))) { send_to_char("Unable to open /proc/net/tcp\n\r", ch); return; } fgets(buf, MAX_INPUT_LENGTH-1, fp); ch_printf(ch, "%-20s %-21s %-5s %-5s %-5s %s\n\r", "Name", "Remote Address", "RecvQ", "SendQ", "Timer", "Retrans"); while (fgets(buf, MAX_INPUT_LENGTH-1, fp)) { sscanf(buf, "%d: %x:%hx %x:%hx %x %x:%x %d:%x %x", &x, &localip, &localport, &remoteip, &remoteport, &st, &txq, &rxq, &tr, &when, &retrans); for (d = first_descriptor; d; d = d->next) { if (st != 1 || d->port != remoteport || MUDPORT != localport || !compare_ip(d, remoteip)) continue; inp.s_addr = remoteip; sprintf(buf, "%s:%d", inet_ntoa(inp), remoteport); ch_printf(ch, "%-20s %-21s %-5d %-5d %-5.1f %-2d\n\r", d->original ? d->original->name : d->character ? d->character->name : "(none)", buf, rxq, txq, when/100.0, retrans ); } } fclose(fp); }