Sorry to be coming into this late. I find I cannot reproduce the problem
using the version of gatping I have here (the prototype I wrote almost a
year ago, which I believe is the same as the version Scott sort-of released).

I ran gatping on an Oxygen system made using the image oxygen-090601.ima,
the latest image I could locate (getting it from URL

   http://leaf.sourceforge.net/pub/oxygen/development/ ).

I made a disk from the image and customized it ONLY by modifying
/etc/network.conf so eth0 would get an address via DHCP. I then copied to
the host the gatping executable I have here, compiled on a Debian Potato
system against whatever libc it uses by default (apparently libc-2.1.3.so).
When I ran it with my network range specified (that is, as "gatping
192.168.1."), it executed properly and returned an accurate list of the
hosts on the LAN.

Jeff Newmiller did spot what looks like an error in the source. This line --

        ping_data_size = MIN_PING_DATA ;

should be added near the top of main(), just before this line --

        ping_pkt_size =  ping_data_size + SIZE_ICMP_HDR         ;

OTOH, that shouldn't be causing a problem with free(); if it was causing a
segfault -- I think it doesn't only because malloc() actually allocates more
memory than you ask for, sometimes -- that should show up when trying to
write to the out-of-bounds location, not when trying to free() the memory
... that is, a few lines earlier than what the debug report shows.

So despite Jeff's help, I don't think we know yet the actual cause of this
problem. Perhaps one of you who are seeing the problem could be specific
about the Oxygen image involved, what actual command you are running, and
whatever else you can think of that might help to pin down the problem.
         
In the meantime, I'm attaching the source and executable for gatping with
the correction I mention above incorporated. 

At 01:00 PM 10/31/01 -0800, Scott C. Best wrote:
>Jeff:
>
>       Akshally...no. :) Gatping wasn't released so much
>as it was wrapped into the echowall distribution for the
>purpose of brute-force updating the ARP cache. It doesn't
>have much utility beyond that...which is NOT to say that
>I wouldn't welcome any improvements that yield a version
>compatable with Oxygen. :)
>
>-Scott
>
>
>On Wed, 31 Oct 2001, Jeff Newmiller wrote:
>
>> On Wed, 31 Oct 2001, David Douthitt wrote:
>>
>> [...]
>>
>> > Breakpoint 1, send_ping (s=5, h=0x804ac58) at gatping.c:161
>> > 161             buffer = ( char * ) malloc ( ( size_t ) ping_pkt_size )
>> > ;
>> > (gdb) n
>> > 162             memset ( buffer, 0, ping_pkt_size * sizeof ( char ) )
>> > ;
>> > (gdb) p buffer
>> > $1 = 0x804a398 "P\235\020@P\235\020@\020"
>> > (gdb) n
>> > 166             icp->icmp_type = ICMP_ECHO      ;
>>
>> This trace doesn't seem to show the whole story.  From the Scott's code:
>>
>> 157             buffer = ( char * ) malloc ( ( size_t ) ping_pkt_size ) ;
>> 158             memset ( buffer, 0, ping_pkt_size * sizeof ( char ) )   ;
>> 159             icp = ( struct icmp * ) buffer  ;
>>
>> To my way of thinking, this code shows poor programming practice.  It
>> should look something like:
>>
>> 157   icp = ( struct icmp * )
>>             calloc ( 1
>>                    , ( size_t ) ( sizeof( struct icmp )
>>                                   + sizeof( PING_DATA ) ) );
>>
>> The ping_pkt_size value is initialized in main, using an uninitialized
>> value for ping_data_size.  The buffer size of 8 is too small, and the icp
>> (well, pdp) initialization code is overwriting memory beyond the buffer.
>>
>> Yecch.  This was released?


gatping

/* gatping.c                                                    */
/* Ray Olszewski <[EMAIL PROTECTED]>                              */
/* prototype for the EchoSounder app                            */
/* copyright (c) 2000 by Ray Olszewski and Echogent Systems     */
/* License: <OSF-compatible license to be added>                */
/* begun November 30, 2000                                      */
/* current as of October 31, 2001                               */

/* NOTE: portions of this program cribbed from the source for
        fping, a program developed by Stanford University       */

/* round up the usual suepects */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>

#include <netinet/in_systm.h>
#include <netinet/in.h>
/* these next two may be a problem - fping source complains about them */
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>

#include <sys/time.h>

/* data added after ICMP header  - can this be even shorter??? */
typedef struct ping_data
        {
        int             ping_count      ;  /* will be 1 in this setting */
        struct timeval  ping_ts         ;  /* time sent */
        } 
        PING_DATA       ;

#define MIN_PING_DATA sizeof(PING_DATA)
#define SIZE_IP_HDR 20
#define SIZE_ICMP_HDR   ICMP_MINLEN     /* from icmp.h */
/* may not need this either */
#define DEFAULT_PING_DATA_SIZE ( MIN_PING_DATA + 44)

typedef struct  host_entry
        {
        struct host_entry        *next          ; /* linked list        */
        int                     count           ; /* for debug          */
        struct sockaddr_in      saddr           ; /* IP address         */
        }
        HOST_ENTRY      ;

typedef struct  valid_host
        {
        struct valid_host       *next           ; /* linked list        */
        int                     count           ; /* for debug          */
        char                    ip_add[18]      ; /* dotted-quad form   */
        char                    mac_add[20]     ; /* colon form         */
        }
        VALID_HOST      ;

/* globals */

HOST_ENTRY      *rrlist=NULL    ; /* list of hosts to be pinged */
HOST_ENTRY      **table=NULL    ; /* array of pointers to items in the list */
HOST_ENTRY      *cursor         ; /* will track current position in list */

VALID_HOST      *goodlist=NULL  ; /* will hold list of valid host numbers */
VALID_HOST      *cursor2        ; /* will track current position in list  */

u_int           ping_pkt_size   ;
u_int           ping_data_size  ;
int             ident           ; /* pid */
struct timezone tz              ;

/* an array for the IP addresses we will ping */
/* default network can be overridden on command line */
char            network[13] = "192.168.123."    ;
int             lowhost = 1                     ;
int             highhost = 254                  ;


struct timeval  current_time    ;

char    * pingfile=NULL         ; /* the list of addresses to ping */
char    * outfile=NULL          ; /* the name of the file that holds the final table */

int             mysock          ; /* will identify the raw socket */
int             ping_file       ; /* list of IP addresses to ping */
int             arp_table       ; /* the arp pseudo file        */

/* function prototypes */
int send_ping ( )       ;
int make_target_list () ;
int in_cksum ( u_short *p, int n )      ;
int search_arp ()               ;


/*  main program */
int main ( int argc, char **argv )
        {

        
        int             i, j, k         ; /* misc counters */
        struct protoent *proto          ;
        char            *buf            ;

        ident = getpid() & 0xFFFF       ;
        proto = getprotobyname ( "icmp" )       ;
        mysock = socket(AF_INET, SOCK_RAW, proto->p_proto )     ;
        ping_data_size = MIN_PING_DATA          ;
        ping_pkt_size =  ping_data_size + SIZE_ICMP_HDR         ;
        
        /* see if a network other than the default is specified */
        if ( argc == 2 )
                {
                strcpy ( network, argv[1] )     ;
                }       ;

        /* add code later to eval command-line options */

        /* assemble the list of targets */
        /* printf ( "Setting up target linked-list ... \n")        ; */
        make_target_list ()     ;

        /* walk through the list and ping each address once */
        cursor = rrlist         ;
        k = 0           ;
        while ( cursor != NULL  )       
                {
                send_ping ( mysock, cursor )    ;
                k++             ;
                cursor = cursor->next           ;
                }       ; /* while */
        
        /* give the kernel time to do things */
        /* system ( " sleep 1 " )       ; */

        /* now collect information from the arp table */

        search_arp ()   ;
        /* clean up and exit */

        }       ; /* main */


/* functions specified */

/* send_ping -- sends a single ping packet to a supplied address */
/* pretty much right from fping */
int send_ping ( int s  ,  HOST_ENTRY *h )
        {
        char            *buffer         ;
        struct icmp     *icp            ;
        PING_DATA       *pdp            ;
        int             n               ;

        buffer = ( char * ) malloc ( ( size_t ) ping_pkt_size ) ;
        memset ( buffer, 0, ping_pkt_size * sizeof ( char ) )   ;
        icp = ( struct icmp * ) buffer  ;

        /* gettimeofday ( &h->last_send_time, &tz )     ; */
        icp->icmp_type = ICMP_ECHO      ;
        icp->icmp_code = 0              ;
        icp->icmp_cksum = 0             ;
        icp->icmp_seq = 1               ;
        icp->icmp_id = ident            ;

        pdp = ( PING_DATA * ) ( buffer + SIZE_ICMP_HDR )        ;
        gettimeofday (&pdp->ping_ts, &tz )      ;
        pdp->ping_count = 1             ;
        icp->icmp_cksum = ( in_cksum ( ( u_short * ) icp, ping_pkt_size ) ) ;

        
        /* this is the line that does the actual work, BTW */
        n = sendto ( mysock , buffer, ping_pkt_size, 0, 
                        ( struct sockaddr * ) &h->saddr,
                        sizeof ( struct sockaddr_in ) ) ;
        if ( n < 0 || n != ping_pkt_size )
                printf ( "Problem with ping - returned %d\n",n )        ;       
        /* release the memory before exiting */
        free ( buffer ) ;       

        }       ; /* send_ping */


/* make_target_list -- creates a list of addresses to ping */
int make_target_list ( )
        {

        char            addrbuf[24]     ;
        int             buflen          ;
        int             i, j, k, m              ;
        HOST_ENTRY      *p              ;
        char            * testbuf       ;
        char            hoststring[6]           ;

        /* open the file of addreses - must be fixed length aaa.bbb.ccc.ddd */
        /* ping_file = open ("/tmp/pingfile",O_RDONLY,0644 )    ; */
        k = 0                   ;
        
        for ( i = lowhost ; i <= highhost ; i++ )
                {
                sprintf (hoststring,"%d", i )   ;
                strcpy ( addrbuf, network )     ;
                strcat ( addrbuf, hoststring )  ;

        /* read in an IP address in dotted-quad form */
        /* while ( ( buflen = ( read ( ping_file, addrbuf, 16 ) ) ) > 0 ) */
        /*      { */
                k++             ;
                /* printf ( "Read in as: %s", addrbuf ) ;*/
                /* allocate space for a new host entry  */
                p = ( HOST_ENTRY * ) malloc ( sizeof ( HOST_ENTRY ) )   ;
                memset ( ( char * ) p, 0, sizeof ( HOST_ENTRY ) )       ;
                 
                /* convert the address to internal form */
                m =  inet_aton ( addrbuf, &p->saddr.sin_addr )  ;
                testbuf = inet_ntoa ( p->saddr.sin_addr )       ;
                /* printf ( " Host number %d: %s\n",k,testbuf ) ; */
                p->saddr.sin_family = AF_INET   ; 
                p->count = k            ;
                /* add it to the linked list */
                p->next = NULL          ; /* signals last entry in list */
                if ( !rrlist )
                        { 
                        rrlist = p      ;
                        cursor = rrlist ;
                         }
                else 
                        { 
                        cursor->next = p        ;
                        cursor = p              ;
                        }       ;
                }       ; /* exit if that was the last line of data */

        }       ; /* make_target_list */


/* search_arp -- processes the arp table to find valid entries */
/* puts them in a linked list and writes the results to a file */
int search_arp ( )      
        {

        char            arpbuf[100]     ;
        int             buflen          ;
        int             i, j, k, m              ;
        VALID_HOST      *p              ;
        char            * testbuf       ;

        /* open the arp pseudo-file for reading */
        arp_table = open ("/proc/net/arp",O_RDONLY,0644 )    ;
        /* and read and ignore the header line */
        read ( arp_table, arpbuf, 79 )  ; 
        arpbuf[87] = '\0'       ;

         while ( ( buflen = ( read ( arp_table, arpbuf, 86 ) ) ) > 0 ) 
                {
                /* read a line */
                /* DEBUG */
                /* printf ( "%s\n",arpbuf )     ; */
                /* see if it has valid data */
                if ( strstr ( arpbuf, "0x2" ) != NULL  )
                        {
                        /* add the MAC and IP addresses to the list */
                        p = ( VALID_HOST * ) malloc ( sizeof ( VALID_HOST ) ) ;
                        memset ( ( char * ) p, 0, sizeof ( VALID_HOST ) )  ;
                        strncpy ( p->ip_add, &arpbuf[0],15 )    ;
                        strncpy ( p->mac_add, &arpbuf[41],18 )  ;
                        p->next = NULL  ;
                        if ( !goodlist )
                                {
                                goodlist = p      ;
                                cursor2 = goodlist ;
                                }
                        else
                                {
                                p->next = NULL  ;
                                cursor2->next = p       ;
                                cursor2 = p             ;
                                }       ;
                        /* and print the results to STDOUT */
                        printf ( "%s %s\n",p->ip_add,p->mac_add )       ;
                        }       ;
                }
        /* close the pseudo-file */
        /* print the results to STDOUT */
        
        }       ;

/* in_cksum -- computes checksum for ICMP packet */
/* taken directly from fping except for formatting      */

int in_cksum(u_short *p, int n)
        {
        register u_short answer;
        register long sum = 0;
        u_short odd_byte = 0;

        while( n > 1 )  { sum += *p++; n -= 2; }

        /* mop up an odd byte, if necessary */
        if( n == 1 ) 
                {
        *(u_char *)(&odd_byte) = *(u_char *)p;
        sum += odd_byte;
                }       ;
        }       ;



/* EOP */


--
------------------------------------"Never tell me the odds!"---
Ray Olszewski                                        -- Han Solo
Palo Alto, CA                                    [EMAIL PROTECTED]        
----------------------------------------------------------------

Reply via email to