home *** CD-ROM | disk | FTP | other *** search
- /* ICMP-related user commands */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include "global.h"
- #include "mbuf.h"
- #include "cmdparse.h"
- #include "domain.h"
- #include "netuser.h"
- #include "internet.h"
- #include "timer.h"
- #include "ping.h"
- #include "misc.h"
- #include "Terminal.h"
- #include "udp.h"
- #include "icmp.h"
- #include "vterm.h"
-
- #define HOPMAXQUERY 5 /* Max# queries each TTL value */
-
- extern int16 lport; /* local port placeholder */
-
- static int pingem(int32, int16, int16);
- static int16 hash_ping(int32);
- static struct ping *add_ping(int32);
- static void del_ping(struct ping *);
-
- static void send_hop(void);
- static int docheck (int argc,char *argv[]);
- static int dottl (int argc,char *argv[]);
- static int dowait (int argc,char *argv[]);
- static int donum (int argc,char *argv[]);
-
- struct cmds Hopcmds[] = {
- "check", docheck, 2, "hop check <host>", NULLCHAR,
- "maxttl", dottl, 0, 0, NULLCHAR,
- "maxwait", dowait, 0, 0, NULLCHAR,
- "queries", donum, 0, 0, NULLCHAR,
- NULLCHAR,
- };
-
- /* ICMP message types */
- extern char *icmptypes[];
-
- /* ICMP unreachable messages */
- extern char *unreach[];
-
- int dohop(int argc, char *argv[])
- {
- return subcmd(Hopcmds, argc, argv);
- }
-
- int doicmpstat(void)
- {
- extern struct icmp_errors icmp_errors;
- extern struct icmp_stats icmp_stats;
- extern char *icmptypes[];
- register int i;
-
- cwprintf(NULL, "ICMP: chksum err %u no space %u icmp %u bdcsts %u\r\n",
- icmp_errors.checksum,icmp_errors.nospace,icmp_errors.noloop,
- icmp_errors.bdcsts);
- cwprintf(NULL, "type rcvd sent\r\n");
- for(i=0;i<ICMP_TYPES;i++)
- {
- if(icmp_stats.input[i] == 0 && icmp_stats.output[i] == 0)
- continue;
- cwprintf(NULL, "%-6u%-6u%-6u",i,icmp_stats.input[i],
- icmp_stats.output[i]);
- if(icmptypes[i] != NULLCHAR)
- cwprintf(NULL, " %s",icmptypes[i]);
- cwprintf(NULL, "\r\n");
- }
- return 0;
- }
-
- /* Hash table list heads */
- struct ping *ping[PMOD];
-
- /* Counter for generating seq numbers */
- static int16 iclk;
-
- /* Increment counter -- called by low level clock tick */
- void icmpclk(void)
- {
- iclk++;
- }
-
- static int32 cticks;
- static int16 hopttl;
- static int16 hopquery;
- static struct socket lsocket, fsocket; /* socket address */
- static int32 lastsource;
- static int32 hopmean;
- static struct timer hop_time_t;
- static Terminal *window;
-
- static int16 Hopmaxttl = 30; /* max attempts */
- static int16 Hopmaxwait = 5; /* secs timeout each attempt */
- static int16 Hopmaxquery = 3; /* #probes each attempt */
-
- /* Set/show # queries sent each TTL value */
- static int donum(int argc, char *argv[])
- {
- int n = atoi(argv[1]);
-
- if (argc < 2)
- {
- cwprintf(NULL, "%d checks for each host\n", Hopmaxquery);
- }
- else if (n < 1 || n > HOPMAXQUERY)
- {
- cwprintf(NULL, "Checks for each host must be > 0 and <= %d\n", HOPMAXQUERY);
- return (1);
- }
- else
- {
- Hopmaxquery = n;
- }
- return (0);
- }
-
- /* Set/show maximum TTL value for a traceroute query */
- static int dottl(int argc, char *argv[])
- {
- int n = atoi(argv[1]);
-
- if (argc < 2)
- {
- cwprintf(NULL, "Maximum ttl %d\n", Hopmaxttl);
- }
- else if (n < 2 || n > 255)
- {
- cwprintf(NULL, "Maximum ttl must be > 0 and <= 255\n");
- return (1);
- }
- else
- {
- Hopmaxttl = n;
- }
- return (0);
- }
-
- static void hop_timeout(void *vp)
- {
- if (hopquery == 1)
- {
- if (lastsource != 0)
- {
- cwprintf(window, " (mean %ld)", 10 * hopmean / Hopmaxquery);
- hopmean = 0;
- }
- cwprintf(window, "\n%3d %-40s", hopttl, inet_ntoa(0));
- }
- cticks = clock() - cticks;
- cwprintf(window, " *** ");
- hopmean += cticks;
- send_hop();
- }
-
- /* Set/show #secs until timeout for a traceroute query */
- static int dowait(int argc, char *argv[])
- {
- int n = atoi(argv[1]);
-
- if (argc < 2)
- {
- cwprintf(NULL, "Maximum wait for reply %d\n", Hopmaxwait);
- }
- else if (n < 1)
- {
- cwprintf(NULL, "Maximum wait for reply must be > 0\n");
- return (1);
- }
- else
- {
- Hopmaxwait = n;
- }
- return (0);
- }
-
- static void send_hop(void)
- {
- if (hopquery >= Hopmaxquery)
- {
- hopquery = 0;
- hopttl++;
- }
- if (hopttl < Hopmaxttl)
- {
- send_udp(&lsocket, &fsocket, 0, hopttl, 0, 0, 0, 0);
- cticks = clock();
- hopquery++;
- hop_time_t.func = hop_timeout; /* what to call on timeout */
- hop_time_t.arg = NULL;
- set_timer(&hop_time_t, Hopmaxwait * 1000L);
- start_timer(&hop_time_t);
- }
- }
-
- void hop_rec(struct icmp *icmphdr, struct udp *udphdr, int32 source, int16 type)
- {
- BOOL tracedone = FALSE;
- struct socket fsocket; /* socket address */
-
- if (udphdr->source != lsocket.port)
- return;
-
- stop_timer(&hop_time_t);
- if (lastsource != source)
- {
- if (lastsource != 0)
- {
- cwprintf(window, " (mean %ldms)", 10 * hopmean / Hopmaxquery);
- hopmean = 0;
- }
- cwprintf(window, "\n%3d %-40s", hopttl, inet_ntoa(source));
- }
- lastsource = source;
- cticks = clock() - cticks;
- cwprintf(window, " %4ldms", 10 * cticks);
- hopmean += cticks;
-
- if (icmphdr->type == DEST_UNREACH)
- {
- switch(icmphdr->code)
- {
- case PORT_UNREACH:
- ++tracedone;
- break;
- case NET_UNREACH:
- ++tracedone;
- cwprintf(window, " !N");
- break;
- case HOST_UNREACH:
- ++tracedone;
- cwprintf(window, " !H");
- break;
- case PROT_UNREACH:
- ++tracedone;
- cwprintf(window, " !P");
- break;
- case FRAG_NEEDED:
- ++tracedone;
- cwprintf(window, " !F");
- break;
- case ROUTE_FAIL:
- ++tracedone;
- cwprintf(window, " !S");
- break;
- case ADMIN_PROHIB:
- ++tracedone;
- cwprintf(window, " !A");
- break;
- default:
- cwprintf(window, " !?");
- break;
- }
- }
- if (!tracedone)
- send_hop();
-
- if (tracedone || hopttl >= Hopmaxttl)
- {
- cwprintf(window, "\n\ntraceroute done: ");
- if (hopttl >= Hopmaxttl)
- {
- cwprintf(window, "!! maximum TTL exceeded\n");
- }
- else if (source == fsocket.address && icmphdr->code == DEST_UNREACH)
- {
- cwprintf(window, "normal (%s %s)\n", icmptypes[type], unreach[icmphdr->code]);
- }
- else
- {
- cwprintf(window, "!! %s %s\n", icmptypes[type], unreach[icmphdr->code]);
- }
- window->Attr = ATTR_REVERSE;
- window->Flags.flags.dont_destroy = FALSE;
- Window_CloseDown(window);
- window = NULL;
- }
- }
-
- static int docheck(int argc, char *argv[])
- {
- char title[80];
-
- /* Set up the connection. */
- fsocket.address = resolve(argv[1]);
- if (fsocket.address != 0)
- {
- fsocket.port = (int16) (32768L+666);
- lsocket.address = ip_addr; /* our ip address */
- lsocket.port = lport++; /* next unused port */
-
- hopttl = 0;
- hopquery = Hopmaxquery;
- lastsource = 0;
- hopmean = 0;
-
- sprintf(title, "Hop check to %s", argv[1]);
- window = Window_Open(NULL, title, term_NO_INPUT);
- vterm_parse(window->vt, argc-2, &argv[2]);
- send_hop();
- }
- else
- {
- cwprintf(NULL, "Hop - Can't resolve %s\n", argv[1]);
- }
- return(0);
- }
-
- /* Send ICMP Echo Request packets */
- int doping(int argc, char **argv)
- {
- int32 dest;
- struct ping *pp1;
- register struct ping *pp;
- int16 hval;
- int i;
-
- if(argc < 2)
- {
- cwprintf(NULL, "Host Sent Rcvd %% Avg RTT Interval\r\n");
- for (i = 0; i < PMOD; i++)
- {
- for (pp = ping[i]; pp != NULLPING; pp = pp->next)
- {
- cwprintf(NULL, "%-40s",inet_ntoa(pp->remote));
- cwprintf(NULL, "%8lu%8lu", pp->count, pp->echoes);
- cwprintf(NULL, "%4lu%10lu%10lu\r\n",
- (long)pp->echoes * 100 / pp->count,
- pp->echoes != 0 ?
- (long)pp->ttotal * MSPTICK / pp->echoes : 0,
- ((long)pp->timer.start * MSPTICK + 500) / 1000);
- }
- }
- return 0;
- }
- if (strcmp(argv[1],"clear") == 0)
- {
- for(i = 0; i < PMOD; i++)
- {
- for (pp = ping[i]; pp != NULLPING; pp = pp1)
- {
- pp1 = pp->next;
- del_ping(pp);
- }
- }
- return 0;
- }
- if ((dest = resolve(argv[1])) == 0)
- {
- cwprintf(NULL, "Host %s unknown\r\n",argv[1]);
- return 1;
- }
- /* See if dest is already in table */
- hval = hash_ping(dest);
- for (pp = ping[hval]; pp != NULLPING; pp = pp->next)
- {
- if(pp->remote == dest)
- {
- break;
- }
- }
- if(argc > 2)
- {
- /* Inter-ping time is specified; set up timer structure */
- if(pp == NULLPING)
- pp = add_ping(dest);
- if (pp->window != NULL)
- cwtitle(pp->window, "Ping - %s", argv[1]);
- pp->timer.start = atoi(argv[2]) * (int32)(1000 / MSPTICK);
- pp->timer.func = ptimeout;
- pp->timer.arg = (char *)pp;
- pp->remote = dest;
- start_timer(&pp->timer);
- pp->count++;
- pingem(dest, iclk, REPEAT);
- }
- else
- pingem(dest, iclk, ONESHOT);
-
- return 0;
- }
-
- /* Called by ping timeout */
- void ptimeout(char *p)
- {
- register struct ping *pp;
-
- /* Send another ping */
- pp = (struct ping *)p;
- pp->count++;
- pingem(pp->remote,iclk,REPEAT);
- start_timer(&pp->timer);
- }
- /* Send ICMP Echo Request packet */
- static int pingem(int32 dest, int16 seq, int16 id)
- {
- struct mbuf *bp;
- struct icmp icmp;
- extern struct icmp_stats icmp_stats;
-
- icmp_stats.output[ECHO]++;
- icmp.type = ECHO;
- icmp.code = 0;
- icmp.args.echo.seq = seq;
- icmp.args.echo.id = id;
- if((bp = htonicmp(&icmp,NULLBUF)) == NULLBUF)
- return 0;
- return ip_send(ip_addr,dest,ICMP_PTCL,0,0,bp,len_mbuf(bp),0,0);
- }
-
- /* Called with incoming Echo Reply packet */
- void echo_proc(int32 source, int32 dest, struct icmp *icmp)
- {
- register struct ping *pp;
- int16 hval;
- int16 rtt;
-
- dest = dest;
-
- rtt = iclk - icmp->args.echo.seq;
- hval = hash_ping(source);
- for(pp = ping[hval]; pp != NULLPING; pp = pp->next)
- if(pp->remote == source)
- break;
- if (pp == NULLPING || icmp->args.echo.id != 1)
- {
- cwprintf(NULL, "%s: echo reply id %u seq %u, %lu ms\r\n",
- inet_ntoa(source),
- icmp->args.echo.id,icmp->args.echo.seq,
- (long)rtt * MSPTICK);
- }
- else if (pp->window != NULL)
- {
- cwprintf(pp->window, "echo reply id %u seq %u, %lu ms\r\n",
- icmp->args.echo.id,icmp->args.echo.seq,
- (long)rtt * MSPTICK);
- }
- else
- {
- /* Repeated poll, just keep stats */
- pp->ttotal += rtt;
- pp->echoes++;
- }
- }
-
- static int16 hash_ping(int32 dest)
- {
- int16 hval;
-
- hval = (hiword(dest) ^ loword(dest)) % PMOD;
- return hval;
- }
-
- /* Add entry to ping table */
- static struct ping * add_ping(int32 dest)
- {
- struct ping *pp;
- int16 hval;
-
- pp = (struct ping *)calloc(1,sizeof(struct ping));
- if(pp == NULLPING)
- return NULLPING;
-
- hval = hash_ping(dest);
- pp->prev = NULLPING;
- pp->next = ping[hval];
- if(pp->next != NULLPING)
- pp->next->prev = pp;
- ping[hval] = pp;
- pp->window = Window_Open(NULL, "Ping", term_NO_INPUT);
- return pp;
- }
- /* Delete entry from ping table */
- static void del_ping(struct ping *pp)
- {
- int16 hval;
-
- stop_timer(&pp->timer);
-
- if(pp->next != NULLPING)
- pp->next->prev = pp->prev;
- if(pp->prev != NULLPING)
- {
- pp->prev->next = pp->next;
- }
- else
- {
- hval = hash_ping(pp->remote);
- ping[hval] = pp->next;
- }
- if (pp->window)
- {
- pp->window->Attr = ATTR_REVERSE;
- pp->window->Flags.flags.dont_destroy = FALSE;
- Window_CloseDown(pp->window);
- }
- free((char *)pp);
- }
-