The HyperNews Linux KHG Discussion Pages

Question: Problem with ICMP echo-request/reply

Forum: The Linux Kernel Hackers' Guide
Re: Question Problem in doing RAW SOCKET Programming (anjali sharma)
Keywords: Client server program using Raw sockets.
Date: Thu, 09 Jul 1998 12:17:09 GMT
From: Raghavendra Bhat <raghu@swec.xko.dec.com>


I have the following program to simulate "ping". I am sending an ICMP echo 
request to a specified host and expect the host to respond with ICMP echo
response. I understand from TCP/IP books that the kernel of the target host 
will send the "echo response" as soon as it receives the "echo request". But 
"recvfrom()" in my program waits forever since it doesn't receive any 
"echo response". While "myping" is waiting in recvfrom(), if I do a
"ping" to the target host from my host, "myping" comes out successfully
with correct packet size also. This means that IF my current host receives
the "echo response", it is properly delivering the packet to my program. That
is,
there should not be any problem with my recvfrom(). But I am not able to make 
out why my targethost's kernel is not responding to my "echo request". Could
it be because my "echo request" is not reaching the target machine or the 
target machine is not able to identify the received packet as "echo request"?
Can anybody tell me the reason for this? What could be the possible reasons
and
what is the solution?

Thanks in advance,
Raghu

___________________________________________________________________________

/* myping.c */
/* 
 * This program simulates the "ping" program. But it doesn't bother about
 * checksum, unique sequence id, etc.
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netdb.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>

/* My own ICMP structure */
struct myicmp
{
    unsigned char icmp_type;
    unsigned char icmp_code;
    unsigned short icmp_cksum;
    unsigned short icmp_id1;
    unsigned short icmp_seq1;
};

/* argv[1] can be either hostname or IP address */
main(int argc, char *argv[])
{
  struct sockaddr_in address;
  u_char sendpack[32];
  struct myicmp *icp;
  int Nbytes, sock , status, buf_len;
  struct sockaddr_in    Current_Sockaddr;
  char buffer[100];
  struct hostent *host;

  if (argc != 2)
  {
        printf("usage : %s <hostname|IP address>\n", argv[0]);
        exit(1);
  }

  if ((host=gethostbyname((const char*)argv[1])) == NULL)
  {
        if ((address.sin_addr.s_addr = inet_addr(argv[1])) == -1)
        {
          printf("%s: unknown host\n", argv[1]);
          exit(1);
        }
  }
  else
  {
        bcopy(host->h_addr_list[0], &(address.sin_addr.s_addr),
host->h_length);
  }

  memset(sendpack, 0x0, sizeof(sendpack));
  memset(buffer, 0x0, sizeof(buffer));

  icp=(struct myicmp*)sendpack;

  icp->icmp_type=ICMP_ECHO;
  icp->icmp_code=0;
  icp->icmp_seq1=1; /* any abritrary sequence number */
  icp->icmp_id1=123; /* any arbitrary id */

  address.sin_family = AF_INET;

  /* 1 is for ICMP protocol : from /etc/protocols */
  sock = socket(AF_INET,SOCK_RAW, 1);

  buf_len = sizeof(buffer);
  Nbytes= sendto(sock,  (const void *)sendpack, sizeof(sendpack), 0,
        (struct sockaddr *)&address,sizeof(address));

  printf ("Data is sent to %s\n", inet_ntoa(address.sin_addr));
  printf ("No of bytes sent = %d\n", Nbytes);

  buf_len = sizeof(Current_Sockaddr );

  Nbytes= recvfrom(sock, buffer,  buf_len, 0,
              (struct sockaddr *)&Current_Sockaddr, &buf_len  );

  printf ("Data received from %s\n", inet_ntoa(Current_Sockaddr.sin_addr));

  /* get the sequence-id : First 20 bytes are for IP header :
     21t byte is the sequence-id */
  icp=(struct myicmp*)&buffer[20];
  printf("Received sequence id is %d\n", icp->icmp_seq1);

  printf ("No of bytes recd = %d\n", Nbytes);
}
________________________________________________________________________