Basada en el c贸digo de http://cboard.cprogramming.com/networking-device-communication/41635-ping-program.html:
#include "FiveLinux.ch"
function Main()
聽 聽MsgInfo( Ping( "192.168.0.22" ) )
聽 聽
return nil
#pragma BEGINDUMP 聽
#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];
static unsigned short in_cksum(unsigned short *, int);
static void parse_argvs(char**, char*, char* );
static void usage();
static char* getip();
static char* toip(char*);
HB_FUNC( PING )
{
聽 聽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( ( char * ) hb_parc( 1 ) ), 20 );
聽 聽strncpy( src_addr, toip( getip() ), 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)
聽 聽{
聽 聽 聽 聽hb_retl( FALSE );
聽 聽 聽 聽return;
聽 聽 聽 聽// 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)
聽 聽{
聽 聽 聽 聽hb_retl( FALSE );
聽 聽 聽 聽// perror("recv");
聽 聽}
聽 聽else
聽 聽{
聽 聽 聽 聽hb_retl( TRUE );
聽 聽 聽 聽// 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;
}
static 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++;
聽 聽 聽 聽}
聽 聽}
}
static void usage()
{
聽 聽fprintf(stderr, "\nUsage: pinger [destination] <-s [source]>\n");
聽 聽fprintf(stderr, "Destination must be provided\n");
聽 聽fprintf(stderr, "Source is optional\n\n");
}
static 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
聽*/
static 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)
聽*/
static 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);
}
#pragma ENDDUMP