Newsgroup: it.comp.os.linux.development
Titolo: Ping, socket ed errori che non capisco



Vi prego di aiutarmi, anche se può sembrare un pò lungo.

Per motivi universitari sto studiando il codice sorgente del ping.
Per iniziare ho trovato una versione semplificata (rping.c). Dopo averla
modificata, per adeguarla alle mie esigenze, in fase di compilazione (gcc
prova.c -o prova) mi restituisce i seguenti errori:

prova.c:395: conflicting types for 'pr_type'


prova.c:395: An argument type that has a default promotion can't
match an empty parameter name list declaration.


prova.c:27: previous declaration of  'pr_type'


Il codice è il seguente:

#include <stdio.h>

#include <errno.h>

#include <sys/time.h>

#include <sys/param.h>

#include <sys/socket.h>

#include <netinet/in_systm.h>

#include <netinet/in.h>

#include <netinet/ip.h>

#include <netinet/ip_icmp.h>

#include <netdb.h>

extern int errno;

extern void exit();

extern char *rindex();

extern char *strcpy();

extern char *strncpy();

extern char *inet_ntoa();

extern u_long inet_addr();

extern time_t time();

u_short checksum();

char *pr_type();

char *pr_addr();

#define NOT_DOTTED_QUAD ((u_long)-1)

#define curtime() time((time_t *)NULL)

#define TRUE 1

#define FALSE 0

#define MAXADDRS 35

#define MAXDNAME 256

#define MAXPKT 4096  /* max packet size */

#define PKTSIZE 64  /* icmp packet total size */

#define HDRLEN ICMP_MINLEN /* icmp header length */

#define DATALEN PKTSIZE-HDRLEN /* icmp packet data length */

u_char packet[MAXPKT];  /* packet buffer */

int attempts = 3;  /* number of retries */

int timeout = 2;  /* timeout in secs */

long timelimit;   /* safety limit */

#define EX_ALIVE 0  /* host is alive */

#define EX_DEAD  1  /* host is dead */

#define EX_USAGE 2  /* illegal parameter */

#define EX_ERROR 3  /* system error */

main(int argc, char *argv[])

{

 int status;

 register char *opt;

 timelimit = curtime() + (attempts * timeout);

 status = ping(argv[1]);

 printf("%s\n", status);

 exit(status);

}

 

ping(char *host) /* name of host to be pinged */

{

 struct hostent *hp;

 char hostname[MAXDNAME+1];

 struct in_addr inaddr[MAXADDRS];

 u_long addr;

 int naddrs;

 int status;

 register int i;

/*

 * Determine remote host address(es).

 */

 if (host == NULL)

  return(EX_ERROR);

 addr = inet_addr(host);

 if (addr != NOT_DOTTED_QUAD)

 {

  hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);

  if (hp != NULL)

   host = strcpy(hostname, hp->h_name);

  inaddr[0].s_addr = addr;

  naddrs = 1;

 }

 else

 {

  hp = gethostbyname(host);

  if (hp == NULL)

  {

   perror("Unknown host (ping): ");

   return(EX_ERROR);

  }

  host = strcpy(hostname, hp->h_name);

  for (i = 0; i < MAXADDRS && hp->h_addr_list[i]; i++)

   inaddr[i] = *(struct in_addr *)hp->h_addr_list[i];

  naddrs = i;

 }

/*

 * Send probe packet to each address of the remote host.

 */

 for (i = 0; i < naddrs; i++)

 {

  if (naddrs > 1)

   printf("Trying %s ...\n", inet_ntoa(inaddr[i]));

  status = ping_host(host, inaddr[i]);

  if (status == EX_ERROR)

   break;

  if (status == EX_ALIVE)

   break;

 }

 return(status);

}

 

ping_host(char *host, struct in_addr inaddr) /* name of host to be pinged,
network address of host */

{

 struct protoent *proto;

 struct sockaddr toaddr, fromaddr;

 struct sockaddr_in *to   = (struct sockaddr_in *)&toaddr;

 struct sockaddr_in *from = (struct sockaddr_in *)&fromaddr;

 int addrlen;

 int sock;

 int status;

 struct icmp *icmp = (struct icmp *)packet;

 struct timeval *timep = (struct timeval *)&packet[HDRLEN];

 u_char *datap = &packet[HDRLEN+sizeof(struct timeval)];

 int ident = getpid() & 0xFFFF; /* ident of icmp output packet
*/

 int sequence = 0;  /* sequence of icmp output packet */

 int cc = PKTSIZE;  /* size of icmp output packet */

 int nc;    /* total size of input packet */

/*

 * Set network address.

 */

 to->sin_family = AF_INET;

 to->sin_addr.s_addr = inaddr.s_addr;

 to->sin_port = 0;

/*

 * Allocate socket.

 */

 proto = getprotobyname("icmp");

 if (proto == NULL)

 {

  perror("Unknown protocol: icmp");

  return(EX_ERROR);

 }

 sock = socket(AF_INET, SOCK_RAW, proto->p_proto);

 if (sock < 0)

 {

  perror("socket");

  return(EX_ERROR);

 }

 printf("[%s] ", host), (void) fflush(stdout);

/*

 * Prepare output packet.

 * Store current time in data field after packet header.

 */

resend:

 timep = (struct timeval *)&packet[HDRLEN];

 (void) gettimeofday(timep, (struct timezone *)NULL);

 datap = &packet[HDRLEN+sizeof(struct timeval)];

 for (nc = sizeof(struct timeval); nc < DATALEN; nc++)

  *datap++ = nc;

 icmp = (struct icmp *)packet;

 icmp->icmp_type  = ICMP_ECHO;

 icmp->icmp_code  = 0;

 icmp->icmp_cksum = 0;

 icmp->icmp_id    = ident;

 icmp->icmp_seq   = sequence;

 icmp->icmp_cksum = checksum((u_short *)icmp, cc);

/*

 * Send probe packet to remote destination.

 */

 nc = sendto(sock, (char *)packet, cc, 0, &toaddr, sizeof(toaddr));

 if (nc < 0)

 {

  perror("sendto");

  (void) close(sock);

  return(EX_ERROR);

 }

/*

 * Wait until input packet arrives. Retry after timeout.

 */

reread:

 status = wait_sock(sock, timeout);

 if (status < 0)

 {

  perror("select");

  (void) close(sock);

  return(EX_ERROR);

 }

 else if (status == 0)

 {

  if (++sequence < attempts)

   goto resend;

  errno = ETIMEDOUT;

  perror("recvfrom");

  status = EX_DEAD;

  goto done;

 }

/*

 * Fetch available input packet.

 * Note. On Apollo, recvfrom() will not be interrupted by an alarm().

 */

 addrlen = sizeof(fromaddr);

 nc = recvfrom(sock, (char *)packet, sizeof(packet), 0, &fromaddr,
&addrlen);

 if (nc <= 0)

 {

  if (nc == 0)

   errno = ECONNRESET;

  if (errno == EINTR)

  {

   if (++sequence < attempts)

    goto resend;

   errno = ETIMEDOUT;

  }

  perror("recvfrom");

  (void) close(sock);

  return(EX_ERROR);

 }

/*

 * Analyze input packet. Reread if this is not what we want.

 */

 status = check_packet(packet, nc, cc, ident, sequence, from);

 if (status != EX_ALIVE)

 {

  if (curtime() <= timelimit)

   goto reread;

 }

done:

 printf("%s is %s\n", host, (status == EX_ALIVE ? "alive" : "dead"));

 (void) close(sock);

 return(status);

}

 

wait_sock(int sock, int secs)

{

 fd_set fds;

 struct timeval wait;

 int nreply;

 wait.tv_sec = secs;

 wait.tv_usec = 0;

 /* FD_ZERO(&fds); */

 bzero((char *)&fds, sizeof(fds));

 FD_SET(sock, &fds);

 nreply = select(FD_SETSIZE, &fds, (fd_set *)0, (fd_set *)0,
&wait);

 return(nreply);

}

 

int check_packet(u_char *buf, int nc, int cc, int ident, int sequence,
struct sockaddr_in *from)

/* address of input packet, total size of input packet, size of icmp
output packet,

   ident in icmp output packet, sequence in icmp output packet,
address we got input packet from */

{

 struct ip *ip;

 struct icmp *icmp;

 int iphdrlen;   /* ip header length of input packet
*/

 struct timeval *sendtime; /* time as stored in icmp packet */

 struct timeval recvtime; /* time input packet is received */

 int triptime;   /* round trip time in millisecs */

 char *host;   /* name of host we got packet from */

 (void) gettimeofday(&recvtime, (struct timezone *)NULL);

 /* from->sin_addr.s_addr = ntohl(from->sin_addr.s_addr); */

 host = inet_ntoa(from->sin_addr);

/*

 * The input packet contains the ip header in front of the icmp
packet.

 * Make sure the packet contains the icmp header after the ip
header.

 */

 ip = (struct ip *)buf;

 iphdrlen = ip->ip_hl << 2;

 if (nc < iphdrlen + ICMP_MINLEN)

 {

  printf("%d bytes from %s (packet too short)\n", nc, host);

  return(EX_DEAD);

 }

 nc -= iphdrlen;

 icmp = (struct icmp *)(buf + iphdrlen);

 printf("%d bytes from %s ", nc, host);

/*

 * Check if this is really an echo reply packet.

 */

 if (icmp->icmp_type != ICMP_ECHOREPLY)

 {

  printf("(not echo reply: %s)\n", pr_type(icmp->icmp_type, icmp->icmp_code));

  return(EX_DEAD);

 }

/*

 * Check the ident of the icmp packet.

 */

 if (icmp->icmp_id != ident)

 {

  printf("(not from us: ident %d should be %d)\n", icmp->icmp_id,
ident);

  return(EX_DEAD);

 }

/*

 * Check the sequence of the icmp packet.

 */

 if (icmp->icmp_seq != sequence)

 {

  printf("(out of sequence: seq %d should be %d)\n", icmp->icmp_seq,
sequence);

  return(EX_DEAD);

 }

/*

 * Check the size of the icmp packet.

 */

 if (nc != cc)

 {

  printf("(packet size error: size %d should be %d)\n", nc, cc);

  return(EX_DEAD);

 }

/*

 * This seems to be our reply packet. Compute round trip time.

 */

 sendtime = (struct timeval *)&icmp->icmp_data[0];

 if ((recvtime.tv_usec -= sendtime->tv_usec) < 0)

 {

  recvtime.tv_sec--;

  recvtime.tv_usec += 1000000;

 }

 recvtime.tv_sec -= sendtime->tv_sec;

 triptime = (recvtime.tv_sec*1000) + (recvtime.tv_usec/1000);

 printf("seq=%d ttl=%d time=%d ms\n", sequence, ip->ip_ttl, triptime);

 return(EX_ALIVE);

}

 

char *pr_addr(struct in_addr inaddr)

{

 static char buf[BUFSIZ];

 struct hostent *hp;

 u_long addr;

 addr = inaddr.s_addr;

 hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);

 if (hp != NULL)

  (void) sprintf(buf, "%s (%s)", hp->h_name, inet_ntoa(inaddr));

 else

  (void) sprintf(buf, "%s", inet_ntoa(inaddr));

 return(buf);

}

 

char *pr_type(u_char rtype, u_char rcode)

{

 static char *ctab[] =

 {

 /*  0 */ "network is unreachable",

 /*  1 */ "host is unreachable",

 /*  2 */ "dest unreachable, protocol",

 /*  3 */ "dest unreachable, port",

 /*  4 */ "dest unreachable, needfrag",

 /*  5 */ "dest unreachable, srcfail"

 };

 static char *ttab[] =

 {

 /*  0 */ "echo reply",

 /*  1 */ "ICMP 1",

 /*  2 */ "ICMP 2",

 /*  3 */ "destination unreachable",

 /*  4 */ "source quench",

 /*  5 */ "redirect",

 /*  6 */ "ICMP 6",

 /*  7 */ "ICMP 7",

 /*  8 */ "echo request",

 /*  9 */ "ICMP 9",

 /* 10 */ "ICMP 10",

 /* 11 */ "time exceeded",

 /* 12 */ "parameter problem",

 /* 13 */ "timestamp request",

 /* 14 */ "timestamp reply",

 /* 15 */ "info request",

 /* 16 */ "info reply",

 /* 17 */ "mask request",

 /* 18 */ "mask reply"

 };

 if (rtype > 18)

  return("unknown packet type");

 if (rtype == ICMP_UNREACH)

  if (rcode <= 5)

   return(ctab[rcode]);

 return(ttab[rtype]);

}

 

u_short checksum(u_short *addr, int len)

{

 register int nleft = len;

 register u_short *w = addr;

 register int sum = 0;

 u_short answer = 0;

/*

 * 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);

}

 

/*VARARGS1

error(char *fmt, a, b)

{

 /*(void) fprintf(stderr, "%s: ", program);

 (void) fprintf(stderr, fmt, a, b);

 (void) fprintf(stderr, "\n");

}*/

 


 
Ad okkio direi che il motivo e' che prima dichiari la funzione senza
argomenti e poi la definisci con argomenti...
kalb

menegon wrote:

Ad okkio direi che il motivo e' che prima dichiari
la funzione senza

argomenti e poi la definisci con argomenti...

kalb

Grazie per la risposta.

Se nella dichiarazione iniziale metto gli argomentimi restituisce questi
errori:

/var/tmp/ccFGdpsL.o: In function `ping':


/var/tmp/ccFGdpsL.o(.text+0xb8): undefined reference to `inet_addr'


/var/tmp/ccFGdpsL.o(.text+0xe4): undefined reference to `gethostbyaddr'


/var/tmp/ccFGdpsL.o(.text+0x134): undefined reference to `gethostbyname'


/var/tmp/ccFGdpsL.o(.text+0x250): undefined reference to `inet_ntoa'


/var/tmp/ccFGdpsL.o: In function `ping_host':


/var/tmp/ccFGdpsL.o(.text+0x374): undefined reference to `getprotobyname'


/var/tmp/ccFGdpsL.o(.text+0x3bc): undefined reference to `socket'


/var/tmp/ccFGdpsL.o(.text+0x500): undefined reference to `sendto'


/var/tmp/ccFGdpsL.o(.text+0x638): undefined reference to `recvfrom'


/var/tmp/ccFGdpsL.o: In function `check_packet':


/var/tmp/ccFGdpsL.o(.text+0x8a0): undefined reference to `inet_ntoa'


/var/tmp/ccFGdpsL.o: In function `pr_addr':


/var/tmp/ccFGdpsL.o(.text+0xb6c): undefined reference to `gethostbyaddr'


/var/tmp/ccFGdpsL.o(.text+0xb9c): undefined reference to `inet_ntoa'


/var/tmp/ccFGdpsL.o(.text+0xbdc): undefined reference to `inet_ntoa'


collect2: ld returned 1 exit status


Sono veramente in crisi.

Mattia.


 Mattia.
Sempre ad okkio, questi sono errori del linker, sembra che non riesca a
trovare le librerie necessarie. Ad ogni buon conto io ho copiato pari
pari il sorgente dal tuo msg in un file "ping.c" ed ho provato a
compilarlo, ottenendo gli errori del primo messaggio, poi ho dichiarato
la funzione con i parametri e me l'ha compilata senza fare una piega.
Controlla se le librerie ci sono e se il path e' giusto.
Ciao.
kalb

 collect2: ld returned 1 exit status
prova -lnsl per il linking della libreria resolv...
-- 
Francesco P. Lovergine