LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-22-2005, 09:58 AM   #1
mgp
LQ Newbie
 
Registered: Sep 2004
Posts: 6

Rep: Reputation: 0
ICMP Programming


All,

I have been working with some ICMP code, and have noticed a few wierd things I cant figure out.
When I start the prog. It hesitates at the sent bytes message.
As soon as I start a standard ping from an other shell window I get replies on both ICMP requests.
Why is this side affect happening and how could I repair this issue.

Thanks in advance,

MGP

********************* DEMO CODE******************************************
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h> `
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <linux/ip.h>
#include <linux/icmp.h>
#include <string.h>
#include <unistd.h>


char dst_addr[20];
char src_addr[20];

unsigned short in_cksum(unsigned short *, int);
void parse_argvs(char**, char*, char* );
void usage();
char* getip();
char* toip(char*);

int main(int argc, char* argv[])
{
struct iphdr* ip;
struct iphdr* ip_reply;
struct icmphdr* icmp;
struct sockaddr_in connection;
char* packet;
char* buffer;
int sockfd;
int optval;
int addrlen;
int siz;


if (getuid() != 0)
{
fprintf(stderr, "%s: root privelidges needed\n", *(argv + 0));
exit(EXIT_FAILURE);
}

parse_argvs(argv, dst_addr, src_addr);
strncpy(dst_addr, toip(dst_addr), 20);
strncpy(src_addr, toip(src_addr), 20);
printf("Source address: %s\n", src_addr);
printf("Destination address: %s\n", dst_addr);

/*
* allocate all necessary memory
*/
packet = malloc(sizeof(struct iphdr) + sizeof(struct icmphdr));
buffer = malloc(sizeof(struct iphdr) + sizeof(struct icmphdr));
/****************************************************************/

ip = (struct iphdr*) packet;
icmp = (struct icmphdr*) (packet + sizeof(struct iphdr));

/*
* here the ip packet is set up
*/
ip->ihl = 5;
ip->version = 4;
ip->tos = 0;
ip->tot_len = sizeof(struct iphdr) + sizeof(struct icmphdr);
ip->id = htons(0);
ip->frag_off = 0;
ip->ttl = 64;
ip->protocol = IPPROTO_ICMP;
ip->saddr = inet_addr(src_addr);
ip->daddr = inet_addr(dst_addr);
ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr));

if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1)
{
perror("socket");
exit(EXIT_FAILURE);
}

/*
* IP_HDRINCL must be set on the socket so that
* the kernel does not attempt to automatically add
* a default ip header to the packet
*/

setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(int));

/*
* here the icmp packet is created
* also the ip checksum is generated
*/
icmp->type = ICMP_ECHO;
icmp->code = 0;
icmp->un.echo.id = random();
icmp->un.echo.sequence = 0;
icmp-> checksum = in_cksum((unsigned short *)icmp, sizeof(struct icmphdr));


connection.sin_family = AF_INET;
connection.sin_addr.s_addr = inet_addr(dst_addr);

/*
* now the packet is sent
*/

sendto(sockfd, packet, ip->tot_len, 0, (struct sockaddr *)&connection, sizeof(struct sockaddr));
printf("Sent %d byte packet to %s\n", ip->tot_len, dst_addr);

/*
* now we listen for responses
*/
addrlen = sizeof(connection);
if (( siz = recvfrom(sockfd, buffer, sizeof(struct iphdr) + sizeof(struct icmphdr), 0, (struct sockaddr *)&connection, &addrlen)) == -1)
{
perror("recv");
}
else
{
printf("Received %d byte reply from %s:\n", siz , dst_addr);
ip_reply = (struct iphdr*) buffer;
printf("ID: %d\n", ntohs(ip_reply->id));
printf("TTL: %d\n", ip_reply->ttl);
}

free(packet);
free(buffer);
close(sockfd);
return 0;
}
void parse_argvs(char** argv, char* dst, char* src)
{
int i;
if(!(*(argv + 1)))
{
/* there are no options on the command line */
usage();
exit(EXIT_FAILURE);
}
if (*(argv + 1) && (!(*(argv + 2))))
{
/*
* only one argument provided
* assume it is the destination server
* source address is local host
*/
strncpy(dst, *(argv + 1), 15);
strncpy(src, getip(), 15);
return;
}
else if ((*(argv + 1) && (*(argv + 2))))
{
/*
* both the destination and source address are defined
* for now only implemented is a source address and
* destination address
*/
strncpy(dst, *(argv + 1), 15);
i = 2;
while(*(argv + i + 1))
{
if (strncmp(*(argv + i), "-s", 2) == 0)
{
strncpy(src, *(argv + i + 1), 15);
break;
}
i++;
}
}

}

void usage()
{
fprintf(stderr, "\nUsage: pinger [destination] <-s [source]>\n");
fprintf(stderr, "Destination must be provided\n");
fprintf(stderr, "Source is optional\n\n");
}

char* getip()
{
char buffer[256];
struct hostent* h;

gethostname(buffer, 256);
h = gethostbyname(buffer);

return inet_ntoa(*(struct in_addr *)h->h_addr);

}

/*
* return the ip address if host provided by DNS name
*/
char* toip(char* address)
{
struct hostent* h;
h = gethostbyname(address);
return inet_ntoa(*(struct in_addr *)h->h_addr);
}

/*
* in_cksum --
* Checksum routine for Internet Protocol
* family headers (C Version)
*/
unsigned short in_cksum(unsigned short *addr, int len)
{
register int sum = 0;
u_short answer = 0;
register u_short *w = addr;
register int nleft = len;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1)
{
sum += *w++;
nleft -= 2;
}
/* mop up an odd byte, if necessary */
if (nleft == 1)
{
*(u_char *) (&answer) = *(u_char *) w;
sum += answer;
}
/* add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return (answer);
}
 
Old 11-23-2005, 07:04 PM   #2
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
I would suspect you are using blocking sockets(are you? im more familiar with winsock, gasp i say that on this site). if you are then the socket will listen until it receives a response blocking the thread.
 
Old 11-24-2005, 05:06 AM   #3
primo
Member
 
Registered: Jun 2005
Posts: 542

Rep: Reputation: 34
ip->tot_len needs htons( ) of the whole thing, then do ntohs( ) when you use it with sendto( ) below.

Check return values to let you know if there are problems.

It's better to bzero( ) the sockaddr_in variables before using them. They tend to contain more values.
 
Old 07-21-2009, 03:11 AM   #4
virtualCoder
Member
 
Registered: Sep 2007
Distribution: Ubuntu
Posts: 33

Rep: Reputation: 15
Sorry for polling such an old thread, I had a question about sending ICMP packets without using raw packets. The ping and traceroute utilities (using ICMP) can be used without having sudo access, but sending and retrieving raw packets requires sudo access (actually traceroute even has to modify the IP header as well for ttl).

So what I am guessing is that there must be another way of sending ICMP packets without sudo access. Can someone please point me in the right direction?

Thank you.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
About ICMP Ephracis Linux - Networking 1 11-22-2004 08:01 AM
ICMP traffic archives/writing ICMP traffic in a file maia_1 Programming 0 07-20-2004 03:43 AM
What is ICMP? codedv Linux - Networking 2 01-04-2004 10:12 AM
icmp settings chapzilla Linux - Networking 2 08-07-2003 10:44 AM
Icmp mikeyt_3333 Linux - Security 1 08-09-2001 05:40 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:21 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration