dotd-2.3.7/area/
dotd-2.3.7/clans/
dotd-2.3.7/classes/
dotd-2.3.7/councils/
dotd-2.3.7/deity/
dotd-2.3.7/dict/
dotd-2.3.7/doc/mudprogs/
dotd-2.3.7/player/a/
dotd-2.3.7/player/g/
/******************************************************
            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);
}