Newsgroup: it.comp.os.linux.development
Titolo: Comincio ad odiare il Ping

Non riesco a capire perché in fase di compilazione non mi dia errori (dopo
avere trovato un computer con le librerie giuste), mentre a runtime mi dà il
seguente errore:
-socket: Operazione non permessa
-Segmentation fault (core dumped)
Il secondo dovrebbe essere relativo a puntatori, però mi sembra che siano in
regola, mentre per il primo non so da che parte farmi.
Vi ringrazio già da adesso per l'aiuto.
Mattia.
#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 char *inet_ntoa();
extern unsigned long inet_addr();
unsigned short checksum(unsigned short *addr, int len);
char *pr_type(unsigned char rtype, unsigned char rcode);
char *pr_addr(struct in_addr inaddr);
#define NOT_DOTTED_QUAD ((unsigned 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 */
unsigned 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 */
int main(int argc, char *argv[])
{
 int status;
 register char *opt;
 timelimit = curtime() + (attempts * timeout);
 status = ping(argv[1]);
 printf("%s\n", status);
 exit(status);
}
int ping(char *host) /* name of host to be pinged */
{
 struct hostent *hp;
 char hostname[MAXDNAME+1];
 struct in_addr inaddr[MAXADDRS];
 unsigned long addr;
 int naddrs;
 int status;
 register int i;
/*
 * Determine remote host address(es).
 */
        printf("ping0");
 if (host == NULL)
  return(EX_ERROR);
        printf("ping1");
 addr = inet_addr(host);
 printf("ping2");
 if (addr != NOT_DOTTED_QUAD)
 {
  printf("ping3");
  hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
  if (hp != NULL)
   host = strcpy(hostname, hp->h_name);
  inaddr[0].s_addr = addr;
  naddrs = 1;
  printf("ping4");
 }
 else
 {
  printf("ping5");
  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;
  printf("ping6");
 }
/*
 * 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;
 }
        printf("ping7");
 return(status);
}
int 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];
 unsigned 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((unsigned 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);
}
int 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(unsigned 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;
 unsigned 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(unsigned char rtype, unsigned 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]);
}
unsigned short checksum(unsigned short *addr, int len)
{
 register int nleft = len;
 register unsigned short *w = addr;
 register int sum = 0;
 unsigned 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)
 {
  *(unsigned char *)(&answer) = *(unsigned 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);
}

>>>>>>>>>

Cerca di imparare ad usare un debugger (gdb ad ex.) e soprattutto leggi molto
bene la documentazione (libc in questo caso ) ...
e ricorda che "l'odio è figlio dell'ignoranza..." ;-))
Ciao

 e ricorda che "l'odio è figlio dell'ignoranza..." ;-))
E tu ci odi così tanto da mandarci più di 500 righe citate inutilmente
dall'altro messaggio perché ignori la netiquette, immagino :-)
http://www.rfc1855.org/
Ciao,
Marco


Non potevi quotare un po' di linee in meno ?

  printf("%s\n", status);
Ciao ciao,
Andrea
-- 
"...Unix, MS-DOS, and Windows NT (also known as the Good, the Bad, and 
 the Ugly)."
(by Matt Welsh)

 bene la documentazione (libc in questo caso ) ...
Tu invece potrsti evitare di riquotare 400 righe solo per aggiungercene
3, sia pure di consiglio valido?
Comunque il primo debugger si chiama printf ...
Ciao
-- 
Simone Piccardi
Microsoft is NOT the answer. Microsoft is the Question.
The answer is: "NO!"