Unix Programming - Problem with detecting the reception of a datagram

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > April 2006 > Problem with detecting the reception of a datagram





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author Problem with detecting the reception of a datagram
xoinki

2006-04-27, 7:55 am



hi all,

the program below sends a datagram to a specified host at regular
intervals, it can even broadcast datagrams, the problem here is i am
unable to detect the reception of a message,
that is... if a system with an IP address say 192.168.15.3 is not up or
not responding, then our program is unable to recieve the datagrams,
then bytes recieved would be zero.. but the listen module is not at all
executing if there is no datagram sent from a remote host..

Is this problem related to fork() system call used in main?
so that listen is executed only when a datagram has arrived?

pleeze do help thznks in advance....

here is the program..

#include<curses.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip_icmp.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include<signal.h>

#define PACKETSIZE 64

struct hostent *hname;
struct sockaddr_in addr;

void ping(void);


struct icmphdr1
{
u_int8_t type; /* message type */
u_int8_t code; /* type sub-code */
u_int16_t checksum;
/*union
{
struct
{
u_int16_t id;
u_int16_t sequence;
} echo; /* echo datagram
u_int32_t gateway; /* gateway address
struct
{
u_int16_t __unused;
u_int16_t mtu;
} frag; /* path mtu discovery
} un;*/
};
struct icmphdr1 *icmp;
struct packet
{
struct icmphdr1 hdr;
char msg[PACKETSIZE-sizeof(struct icmphdr1)];
};

int pid=3D-1;
struct protoent *proto=3DNULL;

/*sending a packet every 10 seconds*/

void send1()
{
ping();
alarm(2);

}

/*--------------------------------------------------------------------*/
/*--- checksum - standard 1s complement checksum
---*/
/*--------------------------------------------------------------------*/
unsigned short checksum(void *b, int len)
{ unsigned short *buf =3D b;
unsigned int sum=3D0;
unsigned short result;

for ( sum =3D 0; len > 1; len -=3D 2 )
sum +=3D *buf++;
if ( len =3D=3D 1 )
sum +=3D *(unsigned char*)buf;
sum =3D (sum >> 16) + (sum & 0xFFFF);
sum +=3D (sum >> 16);
result =3D ~sum;
return result;
}

/*--------------------------------------------------------------------*/
/*--- display - present echo info
---*/
/*--------------------------------------------------------------------*/
void display(void *buf, int bytes)
{ int i;
struct iphdr *ip=3D buf;
struct icmphdr1 *icmp =3D buf+ip->ihl*4;

printf("----------------\n");
if(icmp->type=3D=3D0)
printf("muhahaha helow\n");

/* for ( i =3D 0; i < bytes; i++ )
{
if ( !(i & 15) ) printf("\nX: ", i);
printf("X ", ((unsigned char*)buf)[i]);
}*/
printf("\n");
printf("IPv%d: hdr-size=3D%d pkt-size=3D%d protocol=3D%d TTL=3D%d src=3D%s=
",
ip->version, ip->ihl*4, ntohs(ip->tot_len), ip->protocol,
ip->ttl, inet_ntoa(ip->saddr));
printf("dst=3D%s\n", inet_ntoa(ip->daddr));
//if ( icmp->un.echo.id =3D=3D pid )
{
printf("ICMP: type[%d/%d] checksum[%d]\n",
icmp->type, icmp->code, ntohs(icmp->checksum));
}
}

/*--------------------------------------------------------------------*/
/*--- listener - separate process to listen for and collect
messages--*/
/*--------------------------------------------------------------------*/
void listener(void)
{ int sd;
struct sockaddr_in addr;
unsigned char buf[1024];

sd =3D socket(PF_INET, SOCK_RAW, proto->p_proto);
//printf("hi there\n");
if ( sd < 0 )
{
perror("socket");
exit(0);
}
for (;;)
{ int bytes, len=3Dsizeof(addr);

bzero(buf, sizeof(buf));
bytes =3D recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr*)&addr,
&len);
if ( bytes > 0 )
{
// struct iphdr *ip=3D buf;
/*if(icmp->type=3D=3D0)
printf("muhahaha helow\n");

else
printf("naaaa\n");*/

display(buf, bytes);
//printf("yess\n");
}
else
perror("recvfrom");
}
exit(0);
}

/*--------------------------------------------------------------------*/
/*--- ping - Create message and send it.
---*/
/*--------------------------------------------------------------------*/
void ping()
{ const int val=3D255;
int i, sd, cnt=3D1;
struct packet pckt;
struct sockaddr_in r_addr;

// proto =3D getprotobyname("OSPFIGP");

bzero(&addr, sizeof(addr));
addr.sin_family =3D hname->h_addrtype;
addr.sin_port =3D 0;
addr.sin_addr.s_addr =3D *(long*)hname->h_addr;

sd =3D socket(PF_INET, SOCK_RAW, proto->p_proto);

if ( sd < 0 )
{
perror("socket");
return;
}
if ( setsockopt(sd, SOL_IP, IP_TTL, &val, sizeof(val)) !=3D 0)
perror("Set TTL option");
if ( fcntl(sd, F_SETFL, O_NONBLOCK) !=3D 0 )
perror("Request nonblocking I/O");
//for (;;)
{ int len=3Dsizeof(r_addr);

printf("Msg #%d\n", cnt);
if ( recvfrom(sd, &pckt, sizeof(pckt), 0, (struct sockaddr*)&r_addr,
&len) > 0 )
printf("***Got message!***\n");
bzero(&pckt, sizeof(pckt));
pckt.hdr.type =3D 0;
//pckt.hdr.un.echo.id =3D pid;
for ( i =3D 0; i < sizeof(pckt.msg)-1; i++ )
pckt.msg[i] =3D i+'0';
pckt.msg[i] =3D 0;
//pckt.hdr.un.echo.sequence =3D cnt++;
pckt.hdr.checksum =3D checksum(&pckt, sizeof(pckt));

printf("hi helo\n");
if ( sendto(sd, &pckt, sizeof(pckt), 0, (struct sockaddr*)&addr,
sizeof(addr)) <=3D 0 )
perror("sendto");
printf("ji\n");
//sleep(1);
}
}

/*--------------------------------------------------------------------*/
/*--- main - look up host and start ping processes.
---*/
/*--------------------------------------------------------------------*/
int main(int count, char *strings[])
{
/*struct hostent *hname;
struct sockaddr_in addr;*/

if ( count !=3D 2 )
{
printf("usage: %s <addr>\n", strings[0]);
exit(0);
}
if ( count > 1 )
{
pid =3D getpid();
signal(SIGALRM,send1);
pid =3D getpid();
proto =3D getprotobyname("OSPFIGP");
hname =3D gethostbyname(strings[1]);
/*bzero(&addr, sizeof(addr));
addr.sin_family =3D hname->h_addrtype;
addr.sin_port =3D 0;
addr.sin_addr.s_addr =3D *(long*)hname->h_addr;
signal(SIGALRM,send1); */
if ( fork() =3D=3D 0 )
listener();
else
send1();
while(1)
{
pause();
}

}
else
printf("usage: myping <hostname>\n");
return 0;
}
=20

XOINKI

Nils O. Selåsdal

2006-04-27, 7:55 am

On Tue, 18 Apr 2006 03:55:42 -0700, xoinki wrote:

>
>
> hi all,
>
> the program below sends a datagram to a specified host at regular
> intervals, it can even broadcast datagrams, the problem here is i am
> unable to detect the reception of a message,
> that is... if a system with an IP address say 192.168.15.3 is not up or
> not responding, then our program is unable to recieve the datagrams,
> then bytes recieved would be zero.. but the listen module is not at all
> executing if there is no datagram sent from a remote host..


You are saying , if the other end doesn't send any datagrams,
you don't receive them ?
I fail to see the problem.

(also see my reply to a previous post you had about some
strange things in your program design)

manu

2006-04-27, 7:55 am

sir,
After the datagrams are sent to the system which is non responsive..
the source system must know that the system is not UP and automatically
update the information in the routing table.. for that i am checking
the recieved bytes is zero in the listen module. Now the problem with
this listen module is it is not at all executed when the system is not
UP and it only executes if the destination system is UP and sending
back ack's..

so there is no way for the source system to take futher action when a
neighbour is down since listen is not executed..

my question is.....
is fork() call the culprit here ?
what is the reason for this ?

thnking u for the response..
and waitin for u r reply..
Xoinki

Nils O. Selåsdal

2006-04-27, 7:55 am

manu wrote:
> sir,
> After the datagrams are sent to the system which is non responsive..
> the source system must know that the system is not UP and automatically
> update the information in the routing table.. for that i am checking
> the recieved bytes is zero in the listen module. Now the problem with
> this listen module is it is not at all executed when the system is not
> UP and it only executes if the destination system is UP and sending
> back ack's..

Naturally.

> so there is no way for the source system to take futher action when a
> neighbour is down since listen is not executed..
> my question is.....
> is fork() call the culprit here ?

No.
> what is the reason for this ?

Which 'listen' are you talkling about ?

Your listener function calls recvfrom in a loop.
If it never receivs anything(which it won't e.g. if the host
is down) it is blocked in the recvfrom call forever.

So make a sufficently big enough timeout(by the means of
e.g. using select/poll or alarm), to interrupt the call,
and take action accordingly if you don't receive anything within
that timeout.

Barry Margolin

2006-04-27, 7:55 am

In article <1145382456.930841.213430@g10g2000cwb.googlegroups.com>,
"manu" <manoharyes@gmail.com> wrote:

> sir,
> After the datagrams are sent to the system which is non responsive..
> the source system must know that the system is not UP and automatically


How would it know this? If you send a letter and don't get a reply,
does that mean the person you sent it to is dead?

IP and UDP do not require the receiver to acknowledge or reply when it
receives something, so there's no way to know automatically if it has
been received. You need to implement this in your application protocol,
or use TCP.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com