* of bogies that move around on the scope while the ping sensor can be
* used to display hosts on your network.
*
- * The ping code is only compiled in if you define HAVE_PING, because,
- * unfortunately, creating an ICMP socket is a privileged operation, the
- * program needs to be installed SUID root if you want to use the ping
- * mode. If you check the code you will see that this privilige is given up
- * immediately after the socket is created.
+ * The ping code is only compiled in if you define HAVE_ICMP or HAVE_ICMPHDR,
+ * because, unfortunately, different systems have different ways of creating
+ * these sorts of packets.
+ *
+ * Also: creating an ICMP socket is a privileged operation, so the program
+ * needs to be installed SUID root if you want to use the ping mode. If you
+ * check the code you will see that this privilige is given up immediately
+ * after the socket is created.
*
* It should be easy to extend this code to support other sorts of sensors.
* Some ideas:
* - plot the process table, by process size, cpu usage, or total time;
* - plot the logged on users by idle time or cpu usage.
*
- * Copyright (C) 1998 by Stephen Martin (smartin@canada.com).
+ * Copyright (C) 1998 by Stephen Martin (smartin@vanderfleet-martin.net).
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
- * $Revision: 1.6 $
+ * $Revision: 1.14 $
*
* Version 1.0 April 27, 1998.
* - Initial version
* - Now need to define HAVE_PING to compile in the ping stuff.
*/
+/* These are computed by configure now:
+ #define HAVE_ICMP
+ #define HAVE_ICMPHDR
+ */
+
+
/* Include Files */
-#ifdef HAVE_PING
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#include <netinet/udp.h>
-#include <arpa/inet.h>
-#include <signal.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <signal.h>
-#include <limits.h>
-#endif /* HAVE_PING */
-#include <math.h>
-#include <stdio.h>
#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
#include "screenhack.h"
#include "colors.h"
#include "hsv.h"
-#include <X11/extensions/XShm.h>
+
+#if defined(HAVE_ICMP) || defined(HAVE_ICMPHDR)
+# include <unistd.h>
+# include <limits.h>
+# include <signal.h>
+# include <fcntl.h>
+# include <sys/types.h>
+# include <sys/time.h>
+# include <sys/ipc.h>
+# include <sys/shm.h>
+# include <sys/socket.h>
+# include <netinet/in_systm.h>
+# include <netinet/in.h>
+# include <netinet/ip.h>
+# include <netinet/ip_icmp.h>
+# include <netinet/udp.h>
+# include <arpa/inet.h>
+# include <netdb.h>
+#endif /* HAVE_ICMP || HAVE_ICMPHDR */
+
/* Defines */
-#ifndef MIN
-#define MIN(a,b) ((a)<(b)?(a - 50):(b - 10))
-#endif /* MIN */
+#undef MY_MIN
+#define MY_MIN(a,b) ((a)<(b)?(a - 50):(b - 10))
+
+#ifndef LINE_MAX
+# define LINE_MAX 2048
+#endif
+
+/* Frigging icmp */
+
+#if defined(HAVE_ICMP)
+# define HAVE_PING
+# define ICMP icmp
+# define ICMP_TYPE(p) (p)->icmp_type
+# define ICMP_CODE(p) (p)->icmp_code
+# define ICMP_CHECKSUM(p) (p)->icmp_cksum
+# define ICMP_ID(p) (p)->icmp_id
+# define ICMP_SEQ(p) (p)->icmp_seq
+#elif defined(HAVE_ICMPHDR)
+# define HAVE_PING
+# define ICMP icmphdr
+# define ICMP_TYPE(p) (p)->type
+# define ICMP_CODE(p) (p)->code
+# define ICMP_CHECKSUM(p) (p)->checksum
+# define ICMP_ID(p) (p)->un.echo.id
+# define ICMP_SEQ(p) (p)->un.echo.sequence
+#else
+# undef HAVE_PING
+#endif
/* Forward References */
centrex, centrey, radius; /* Parts of the scope circle */
Bogie *visable; /* List of visable objects */
int current; /* Current position of sweep */
-
+ int sweepnum; /* The current id of the sweep */
int delay; /* how long between each frame of the anim */
} sonar_info;
static int timer_expired;
-
#endif /* HAVE_PING */
/*
char *name; /* The name of the target */
int nexttick; /* The next tick that this will be seen */
int nextdist; /* The distance on that tick */
- int movedlasttick; /* Flag to indicate we just moved this one */
+ int movedonsweep; /* The number of the sweep this last moved */
} sim_target;
/*
/* Allocate a bogie and initialize it */
if ((new = (Bogie *) calloc(1, sizeof(Bogie))) == NULL) {
- fprintf(stderr, "Out of Memory\n");
+ fprintf(stderr, "%s: Out of Memory\n", progname);
return NULL;
}
new->name = name;
struct hostent *hent = gethostbyname(target->name);
if (hent == NULL) {
- fprintf(stderr, "Could not resolve host %s\n", target->name);
+ fprintf(stderr, "%s: could not resolve host %s\n",
+ progname, target->name);
return 0;
}
memcpy(&iaddr->sin_addr, hent->h_addr_list[0],
/* Create the target */
if ((target = calloc(1, sizeof(ping_target))) == NULL) {
- fprintf(stderr, "Out of Memory\n");
+ fprintf(stderr, "%s: Out of Memory\n", progname);
goto target_init_error;
}
if ((target->name = strdup(name)) == NULL) {
- fprintf(stderr, "Out of Memory\n");
+ fprintf(stderr, "%s: Out of Memory\n", progname);
goto target_init_error;
}
/* Make sure we in fact have a file to process */
if ((fname == NULL) || (fname[0] == '\0')) {
- fprintf(stderr, "Invalid ping host file name\n");
+ fprintf(stderr, "%s: invalid ping host file name\n", progname);
return NULL;
}
if ((fp = fopen(fname, "r")) == NULL) {
char msg[1024];
- sprintf(msg, "Unable to open host file %s", fname);
+ sprintf(msg, "%s: unable to open host file %s", progname, fname);
perror(msg);
return NULL;
}
else
continue;
+ /* Check to see if the addr looks like an addr. If not, assume
+ the addr is a name and there is no addr. This way, we can
+ handle files whose lines have "xx.xx.xx.xx hostname" as their
+ first two tokens, and also files that have a hostname as their
+ first token (like .ssh/known_hosts and .rhosts.)
+ */
+ {
+ int i; char c;
+ if (4 != sscanf(addr, "%d.%d.%d.%d%c", &i, &i, &i, &i, &c))
+ {
+ name = addr;
+ addr = NULL;
+ }
+ }
+ /*printf ("\"%s\" \"%s\"\n", name, addr);*/
+
/* Create a new target using first the name then the address */
new = NULL;
if (name != NULL)
new = newHost(name);
- if (new == NULL)
+ if (new == NULL && addr != NULL)
new = newHost(addr);
/* Add it to the list if we got one */
/* Get our hostname */
if (gethostname(hostname, BUFSIZ)) {
- fprintf(stderr, "Unable to get local hostname\n");
+ fprintf(stderr, "%s: unable to get local hostname\n", progname);
return NULL;
}
/* Get our IP address and convert it to a string */
if ((hent = gethostbyname(hostname)) == NULL) {
- fprintf(stderr, "Unable to lookup our IP address\n");
+ fprintf(stderr, "%s: unable to lookup our IP address\n", progname);
return NULL;
}
strcpy(address, inet_ntoa(*((struct in_addr *)hent->h_addr_list[0])));
/* Get a pointer to the last "." in the string */
if ((p = strrchr(address, '.')) == NULL) {
- fprintf(stderr, "Can't parse IP address %s\n", address);
+ fprintf(stderr, "%s: can't parse IP address %s\n", progname, address);
return NULL;
}
p++;
/* Construct targets for all addresses in this subnet */
+ /* #### jwz: actually, this is wrong, since it assumes a
+ netmask of 255.255.255.0. But I'm not sure how to find
+ the local netmask.
+ */
for (i = 254; i > 0; i--) {
sprintf(p, "%d", i);
new = newHost(address);
/* Create the ping info structure */
if ((pi = (ping_info *) calloc(1, sizeof(ping_info))) == NULL) {
- fprintf(stderr, "Out of memory\n");
+ fprintf(stderr, "%s: Out of memory\n", progname);
goto ping_init_error;
}
/* Create the ICMP socket and turn off SUID */
if ((pi->icmpsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
- perror("Can't create ICMP socket");
+ char msg[1024];
+ sprintf(msg, "%s: can't create ICMP socket", progname);
+ perror(msg);
fprintf(stderr,
"%s: this program must be setuid to root for `ping mode' to work.\n",
progname);
/* Unknown source */
- fprintf(stderr, "Illegal pingSource: %s\n", src);
- goto ping_init_error;
+ fprintf(stderr,
+ "%s: pingSource must be `file', `list', or `subnet', not: %s\n",
+ progname, src);
+ exit (1);
}
/* Make sure there is something to ping */
if (pi->targets == NULL) {
- fprintf(stderr, "Nothing to ping");
+ fprintf(stderr, "%s: nothing to ping", progname);
goto ping_init_error;
}
/* Local Variables */
u_char *packet;
- struct icmp *icmph;
+ struct ICMP *icmph;
int result;
/*
* name or do an address lookup when it comes back.
*/
- int pcktsiz = sizeof(struct icmp) + sizeof(struct timeval) +
+ int pcktsiz = sizeof(struct ICMP) + sizeof(struct timeval) +
strlen(pt->name) + 1;
/* Create the ICMP packet */
if ((packet = (u_char *) malloc(pcktsiz)) == (void *) 0)
return; /* Out of memory */
- icmph = (struct icmp *) packet;
- icmph->icmp_type = ICMP_ECHO;
- icmph->icmp_code = 0;
- icmph->icmp_cksum = 0;
- icmph->icmp_id = pi->pid;
- icmph->icmp_seq = pi->seq++;
- gettimeofday((struct timeval *) &packet[sizeof(struct icmp)],
+ icmph = (struct ICMP *) packet;
+ ICMP_TYPE(icmph) = ICMP_ECHO;
+ ICMP_CODE(icmph) = 0;
+ ICMP_CHECKSUM(icmph) = 0;
+ ICMP_ID(icmph) = pi->pid;
+ ICMP_SEQ(icmph) = pi->seq++;
+ gettimeofday((struct timeval *) &packet[sizeof(struct ICMP)],
(struct timezone *) 0);
- strcpy((char *) &packet[sizeof(struct icmp) + sizeof(struct timeval)],
+ strcpy((char *) &packet[sizeof(struct ICMP) + sizeof(struct timeval)],
pt->name);
- icmph->icmp_cksum = checksum((u_short *)packet, pcktsiz);
+ ICMP_CHECKSUM(icmph) = checksum((u_short *)packet, pcktsiz);
/* Send it */
&pt->address, sizeof(pt->address))) != pcktsiz) {
#if 0
char errbuf[BUFSIZ];
- sprintf(errbuf, "Error sending ping to %s", pt->name);
+ sprintf(errbuf, "%s: error sending ping to %s", progname, pt->name);
perror(errbuf);
#endif
}
if (nleft == 1) {
*(u_char *)(&answer) = *(u_char *)w ;
+ *(1 + (u_char *)(&answer)) = 0;
sum += answer;
}
struct timeval *then;
struct ip *ip;
int iphdrlen;
- struct icmp *icmph;
+ struct ICMP *icmph;
Bogie *bl = NULL;
Bogie *new;
char *name;
sa.sa_flags = 0;
sa.sa_handler = sigcatcher;
if (sigaction(SIGALRM, &sa, 0) == -1) {
- perror("Unable to trap sigalarm");
+ char msg[1024];
+ sprintf(msg, "%s: unable to trap SIGALRM", progname);
+ perror(msg);
exit(1);
}
gettimeofday(&now, (struct timezone *) 0);
ip = (struct ip *) packet;
+
iphdrlen = ip->ip_hl << 2;
- icmph = (struct icmp *) &packet[iphdrlen];
+ /* On DEC OSF1 4.0, the preceeding line needs to be
+ iphdrlen = (ip->ip_vhl & 0x0F) << 2;
+ but I don't know how to do this portably. -- jwz.
+ */
+
+ icmph = (struct ICMP *) &packet[iphdrlen];
/* Was the packet a reply?? */
- if (icmph->icmp_type != ICMP_ECHOREPLY) {
+ if (ICMP_TYPE(icmph) != ICMP_ECHOREPLY) {
/* Ignore anything but ICMP Replies */
continue; /* Nope */
}
/* Was it for us? */
- if (icmph->icmp_id != pi->pid) {
+ if (ICMP_ID(icmph) != pi->pid) {
/* Ignore packets not set from us */
continue; /* Nope */
}
if ((name =
strdup((char *) &packet[iphdrlen +
- + sizeof(struct icmp)
+ + sizeof(struct ICMP)
+ sizeof(struct timeval)])) == NULL) {
- fprintf(stderr, "Out of memory\n");
+ fprintf(stderr, "%s: Out of memory\n", progname);
return bl;
}
/* Compute the round trip time */
then = (struct timeval *) &packet[iphdrlen +
- sizeof(struct icmp)];
+ sizeof(struct ICMP)];
new->distance = delta(then, &now) / 100;
if (new->distance == 0)
new->distance = 2; /* HACK */
ping(sonar_info *si, void *vpi)
{
+ /*
+ * This tries to distribute the targets evely around the field of the
+ * sonar.
+ */
+
ping_info *pi = (ping_info *) vpi;
static ping_target *ptr = NULL;
sim_info *si;
int i;
- /* Seed the random number generator */
-
- srand((int) time(NULL));
-
/* Create the simulation info structure */
if ((si = (sim_info *) calloc(1, sizeof(sim_info))) == NULL) {
- fprintf(stderr, "Out of memory\n");
+ fprintf(stderr, "%s: Out of memory\n", progname);
return NULL;
}
if ((si->teamA = (sim_target *)calloc(si->numA, sizeof(sim_target)))
== NULL) {
free(si);
- fprintf(stderr, "Out of Memory\n");
+ fprintf(stderr, "%s: Out of Memory\n", progname);
return NULL;
}
si->teamAID = get_string_resource("teamAName", "TeamAName");
if ((si->teamA[i].name = (char *) malloc(strlen(si->teamAID) + 4))
== NULL) {
free(si);
- fprintf(stderr, "Out of Memory\n");
+ fprintf(stderr, "%s: Out of Memory\n", progname);
return NULL;
}
sprintf(si->teamA[i].name, "%s%03d", si->teamAID, i+1);
- si->teamA[i].nexttick = (int) (90.0 * rand() / RAND_MAX);
- si->teamA[i].nextdist = (int) (100.0 * rand() / RAND_MAX);
+ si->teamA[i].nexttick = (int) (90.0 * random() / RAND_MAX);
+ si->teamA[i].nextdist = (int) (100.0 * random() / RAND_MAX);
+ si->teamA[i].movedonsweep = -1;
}
/* Team B */
if ((si->teamB = (sim_target *)calloc(si->numB, sizeof(sim_target)))
== NULL) {
free(si);
- fprintf(stderr, "Out of Memory\n");
+ fprintf(stderr, "%s: Out of Memory\n", progname);
return NULL;
}
si->teamBID = get_string_resource("teamBName", "TeamBName");
if ((si->teamB[i].name = (char *) malloc(strlen(si->teamBID) + 4))
== NULL) {
free(si);
- fprintf(stderr, "Out of Memory\n");
+ fprintf(stderr, "%s: Out of Memory\n", progname);
return NULL;
}
sprintf(si->teamB[i].name, "%s%03d", si->teamBID, i+1);
- si->teamB[i].nexttick = (int) (90.0 * rand() / RAND_MAX);
- si->teamB[i].nextdist = (int) (100.0 * rand() / RAND_MAX);
+ si->teamB[i].nexttick = (int) (90.0 * random() / RAND_MAX);
+ si->teamB[i].nextdist = (int) (100.0 * random() / RAND_MAX);
+ si->teamB[i].movedonsweep = -1;
}
/* Done */
/* Create the Sonar information structure */
if ((si = (sonar_info *) calloc(1, sizeof(sonar_info))) == NULL) {
- fprintf(stderr, "Out of memory\n");
+ fprintf(stderr, "%s: Out of memory\n", progname);
return NULL;
}
si->height = xwa.height;
si->centrex = si->width / 2;
si->centrey = si->height / 2;
- si->maxx = si->centrex + MIN(si->centrex, si->centrey) - 10;
- si->minx = si->centrex - MIN(si->centrex, si->centrey) + 10;
- si->maxy = si->centrey + MIN(si->centrex, si->centrey) - 10;
- si->miny = si->centrey - MIN(si->centrex, si->centrey) + 10;
+ si->maxx = si->centrex + MY_MIN(si->centrex, si->centrey) - 10;
+ si->minx = si->centrex - MY_MIN(si->centrex, si->centrey) + 10;
+ si->maxy = si->centrey + MY_MIN(si->centrex, si->centrey) - 10;
+ si->miny = si->centrey - MY_MIN(si->centrex, si->centrey) + 10;
si->radius = si->maxx - si->centrex;
si->current = 0;
+ si->sweepnum = 0;
/* Get the font */
if (((si->font = XLoadQueryFont(dpy, get_string_resource ("font", "Font")))
== NULL) &&
((si->font = XLoadQueryFont(dpy, "fixed")) == NULL)) {
- fprintf(stderr, "Can't load an appropriate font\n");
+ fprintf(stderr, "%s: can't load an appropriate font\n", progname);
return NULL;
}
int xdist, xtick;
- t->movedlasttick = 1;
- xtick = (int) (3.0 * rand() / RAND_MAX) - 1;
- xdist = (int) (11.0 * rand() / RAND_MAX) - 5;
+ xtick = (int) (3.0 * random() / RAND_MAX) - 1;
+ xdist = (int) (11.0 * random() / RAND_MAX) - 5;
if (((t->nexttick + xtick) < 90) && ((t->nexttick + xtick) >= 0))
t->nexttick += xtick;
else
for (i = 0; i < info->numA; i++) {
t = &info->teamA[i];
- if (!t->movedlasttick && (t->nexttick == (si->current * -1))) {
+ if ((t->movedonsweep != si->sweepnum) &&
+ (t->nexttick == (si->current * -1))) {
new = newBogie(strdup(t->name), t->nextdist, si->current, TTL);
if (list != NULL)
new->next = list;
list = new;
updateLocation(t);
- } else
- t->movedlasttick = 0;
+ t->movedonsweep = si->sweepnum;
+ }
}
/* Team B */
for (i = 0; i < info->numB; i++) {
t = &info->teamB[i];
- if (!t->movedlasttick && (t->nexttick == (si->current * -1))) {
+ if ((t->movedonsweep != si->sweepnum) &&
+ (t->nexttick == (si->current * -1))) {
new = newBogie(strdup(t->name), t->nextdist, si->current, TTL);
if (list != NULL)
new->next = list;
list = new;
- t->movedlasttick = 1;
updateLocation(t);
- } else
- t->movedlasttick = 0;
+ t->movedonsweep = si->sweepnum;
+ }
}
/* Done */
/* Compute the coordinates of the object */
- distance = (log((double) distance) / 10.0) * si->radius;
+ if (distance != 0)
+ distance = (log((double) distance) / 10.0) * si->radius;
x = ox + ((double) distance * cos(4.0 * ((double) degrees)/57.29578));
y = oy - ((double) distance * sin(4.0 * ((double) degrees)/57.29578));
if ((sensor_info = (void *) init_sim()) == NULL)
exit(1);
} else {
- fprintf(stderr, "Unsupported Sonar mode: %s\n", mode);
+ fprintf(stderr, "%s: unsupported Sonar mode: %s\n", progname, mode);
fprintf(stderr,
"\tCurrently supported modes are `ping' and `simulation'\n");
exit(1);
/* Set up and sleep for the next one */
si->current = (si->current - 1) % 90;
+ if (si->current == 0)
+ si->sweepnum++;
XSync (dpy, False);
gettimeofday(&finish, (struct timezone *) 0);
sleeptime = si->delay - delta(&start, &finish);
screenhack_handle_events (dpy);
if (sleeptime > 0L)
usleep(sleeptime);
+
}
}