home *** CD-ROM | disk | FTP | other *** search
- /* ICMP-related user commands */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include "dbox.h"
- #include "werr.h"
- #include "global.h"
- #include "icmp.h"
- #include "mbuf.h"
- #include "netuser.h"
- #include "internet.h"
- #include "timer.h"
- #include "ping.h"
- #include "misc.h"
- #include "session.h"
- #include "domain.h"
-
- #define Ping_Host 1
- #define Ping_Interval 3
- #define Ping_Size 4
- #define Ping_OK 5
-
- static int ping_start(int32, char *, char *, char *, struct session *);
- static int ping_error(char *, char *, struct session *);
- static int pingem(struct ping *);
- static int16 hash_ping(int32);
- static struct ping *add_ping(int32);
- static void pingparse(struct session *, char *, int16);
- static void del_ping(struct ping *);
-
- /* Hash table list heads */
- struct ping *ping[PMOD];
-
- void start_ping(void)
- {
- struct session *session;
- char buffer[80];
- char Host[256];
- char Interval[5];
- char Size[5];
- dbox d;
-
- if ((d = dbox_new("Ping")) == NULL)
- return;
-
- dbox_setfield(d, Ping_Host, "");
- dbox_setfield(d, Ping_Interval, "1");
- dbox_setfield(d, Ping_Size, "64");
-
- dbox_show(d);
-
- if (dbox_fillin(d) == Ping_OK)
- {
- dbox_getfield(d, Ping_Host, Host, 50);
- dbox_getfield(d, Ping_Interval, Interval, 5);
- dbox_getfield(d, Ping_Size, Size, 5);
-
- /* Allocate a session descriptor */
- sprintf(buffer, "PING - %.60s", Host);
- if ((session = newsession(buffer)) == NULLSESSION)
- {
- werr(0, "Too many sessions");
- return;
- }
-
- session->name = strdup(Host);
- session->type = RESOLVING;
- session->parse = NULLVFP;
-
- sprintf(buffer, "Resolving %.60s ...\n", Host);
- Window_Write(session->window, buffer, strlen(buffer));
-
- resolve_a(Host, Interval, Size, session, ping_start, ping_error);
- }
-
- dbox_dispose(&d);
- }
-
- static int ping_error(char *host, char *message, struct session *s)
- {
- char buffer[80];
-
- sprintf(buffer, "Cannot PING %s - %s\n", host, message);
- Window_Write(s->window, buffer, strlen(buffer));
-
- detachsession(s);
-
- return 0;
- }
-
- /* Send ICMP Echo Request packets */
- static int ping_start(int32 address, char *host, char *arg1, char *arg2, struct session *s)
- {
- char buffer[80];
- register struct ping *pp;
- int16 hval;
- int interval;
- int size;
-
- if ((interval = atoi(arg1)) == 0)
- interval = 1;
-
- if ((size = atoi(arg2)) == 0)
- size = 64;
-
- if (size < 4) size = 4;
-
- /* See if address is already in table */
- hval = hash_ping(address);
- for (pp = ping[hval]; pp != NULLPING; pp = pp->next){
- if (pp->remote == address){
- break;
- }
- }
-
- s->type = PING;
- s->addr = address;
- s->parse = pingparse;
- s->echo = 0;
- s->raw = 1;
-
- /* Inter-ping time is specified; set up timer structure */
- if (pp == NULLPING) pp = add_ping(address);
- pp->timer.start = interval * (int32)(1000 / MSPTICK);
- pp->timer.func = ptimeout;
- pp->timer.arg = (char *)pp;
- pp->interval= interval;
- pp->size = size;
- pp->remote = address;
- pp->host = strdup(host);
- pp->id = clock() & 0xFFFF;
- pp->user = s;
- pp->mintime = 999999999;
- pp->maxtime = 0;
- start_timer(&pp->timer);
- pp->count++;
-
- pingem(pp);
-
- sprintf(buffer, "PING %s (%s): %d data bytes\n", host, inet_ntoa(address), size);
- Window_Write(s->window, buffer, strlen(buffer));
-
- s->cb.ping = pp;
-
- return 0;
- }
-
- static void pingparse(struct session *s, char *buf, int16 n)
- {
- char buffer[80];
- struct ping *pp;
- int percentage;
- int average;
-
- if (n != 1 || *buf != 0x03) return;
-
- pp = s->cb.ping;
-
- percentage = ((pp->count - pp->echoes) * 100) / pp->count;
-
- sprintf(buffer, "\n--- %s ping statistics ---\n", s->name);
- Window_Write(s->window, buffer, strlen(buffer));
-
- sprintf(buffer, "%d packets transmitted, %d packets received, %d%% packet loss\n", pp->count, pp->echoes, percentage);
- Window_Write(s->window, buffer, strlen(buffer));
-
- if (pp->echoes > 0)
- {
- average = pp->ttotal / pp->echoes;
- sprintf(buffer, "round-trip min/avg/max = %d/%d/%d ms\n", pp->mintime, average, pp->maxtime);
- Window_Write(s->window, buffer, strlen(buffer));
- }
-
- del_ping(pp);
- }
-
- /* Called by ping timeout */
- void ptimeout(char *p)
- {
- register struct ping *pp;
-
- /* Send another ping */
- pp = (struct ping *)p;
-
- pp->count++;
-
- pingem(pp);
-
- start_timer(&pp->timer);
- }
-
- /* Send ICMP Echo Request packet */
- static int pingem(struct ping *pp)
- {
- struct mbuf *bp, *tbp;
- struct icmp icmp;
- extern struct icmp_stats icmp_stats;
- register int i;
-
- bp = alloc_mbuf(pp->size);
- put32(bp->data, clock());
- for (i = 4; i < pp->size; i++) bp->data[i] = i;
- bp->cnt = pp->size;
- icmp_stats.output[ECHO]++;
- icmp.type = ECHO;
- icmp.code = 0;
- icmp.args.echo.seq = pp->count - 1;
- icmp.args.echo.id = pp->id;
- if ((tbp = htonicmp(&icmp,bp)) == NULLBUF) {
- free_p(bp);
- return 0;
- }
- return ip_send(ip_addr,pp->remote,ICMP_PTCL,0,0,tbp,len_mbuf(tbp),0,0);
- }
-
- /* Called with incoming Echo Reply packet */
- void echo_proc(int32 source, int32 dest, struct icmp *icmp, struct mbuf *bp)
- {
- char buffer[80];
- register struct ping *pp;
- struct session *s;
- int16 hval;
- int16 rtt;
-
- dest = dest;
-
- rtt = (clock() - get32(bp->data)) * MSPTICK;
-
- hval = hash_ping(source);
- for (pp = ping[hval]; pp != NULLPING; pp = pp->next) {
- if (pp->remote == source) {
- s = (struct session *)pp->user;
- sprintf(buffer, "%d bytes from %s: icmp_seq=%d time=%d ms\n", len_mbuf(bp), inet_ntoa(pp->remote), icmp->args.echo.seq, rtt);
- Window_Write(s->window, buffer, strlen(buffer));
- if (pp->mintime > rtt) pp->mintime = rtt;
- if (pp->maxtime < rtt) pp->maxtime = rtt;
- pp->ttotal += rtt;
- pp->echoes++;
- return;
- }
- }
- }
-
- 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;
-
- if ((pp = (struct ping *)calloc(1, sizeof(struct ping))) == 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;
- 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->user != NULL)
- detachsession(pp->user);
- free((char *)pp);
- }
-
-