Note that there are some explanatory texts on larger screens.

plurals
  1. POset time out in setsockopt ()
    text
    copied!<p>I use this code to send data (IPPROTO_ICMP), using socket to send and receive data </p> <pre><code>#include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;sys/types.h&gt; #include &lt;sys/socket.h&gt; #include &lt;netinet/in.h&gt; #include &lt;arpa/inet.h&gt; #include &lt;netdb.h&gt; #include &lt;linux/ip.h&gt; #include &lt;linux/icmp.h&gt; #include &lt;string.h&gt; #include &lt;unistd.h&gt; 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 icmphdr* icmp_reply; struct sockaddr_in connection; char* packet; char* buffer; int sockfd; int optval; int addrlen; int siz; int i; //int toto=0; //struct timeval timeout; //timeout.tv_sec = 10; //timeout.tv_usec = 0; if (getuid() != 0) { fprintf(stderr, "%s: root privelidges needed\n", *(argv + 0)); exit(EXIT_FAILURE); } //icmp_type = 11; 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-&gt;ihl = 5; ip-&gt;version = 4; ip-&gt;tos = 0; ip-&gt;tot_len = sizeof(struct iphdr) + sizeof(struct icmphdr); ip-&gt;id = htons(0); ip-&gt;frag_off = 0; ip-&gt;ttl = 1; ip-&gt;protocol = IPPROTO_ICMP; ip-&gt;saddr = inet_addr(src_addr); ip-&gt;daddr = inet_addr(dst_addr); ip-&gt;check = in_cksum((unsigned short *)ip, sizeof(struct iphdr)); if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1) { perror("socket"); exit(EXIT_FAILURE); } printf("=====&gt; sockfd= %d \n",sockfd); /* * 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, &amp;optval, sizeof(int)); /* if (setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&amp;timeout, sizeof(timeout)) &lt; 0) error("setsockopt failed\n"); if (setsockopt (sockfd, SOL_SOCKET , SO_SNDTIMEO, (char *)&amp;timeout, sizeof(timeout)) &lt; 0) error("setsockopt failed\n");*/ /* * here the icmp packet is created * also the ip checksum is generated */ icmp-&gt;type = ICMP_ECHO; icmp-&gt;code = 0; icmp-&gt;un.echo.id = random(); icmp-&gt;un.echo.sequence = 0; icmp-&gt; 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 */ //ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, // const struct sockaddr *dest_addr, socklen_t addrlen); //toto=11; for(ip-&gt;ttl =1;ip-&gt;ttl &lt;25 /*&amp;&amp; (icmp_type==11)*/;ip-&gt;ttl++) { sendto(sockfd, packet, ip-&gt;tot_len, 0, (struct sockaddr *)&amp;connection, sizeof(struct sockaddr)); printf("Sent %d byte packet to %s , &gt;&gt;&gt;&gt;&gt; TTL=%d\n", ip-&gt;tot_len, dst_addr,ip-&gt;ttl); for (i = 0; i &lt; ip-&gt;tot_len; i++) { printf("%02X%s", (uint8_t)packet[i], (i + 1)%16 ? " " : "\n"); } printf("\n"); printf("ICMP msgtype=%d, code=%d \n", icmp-&gt;type, icmp-&gt;code); /* * now we listen for responses */ addrlen = sizeof(connection); printf("recvfrom 00\n"); if (( siz = recvfrom(sockfd, buffer, sizeof(struct iphdr) + sizeof(struct icmphdr), 0, (struct sockaddr *)&amp;connection, &amp;addrlen)) == -1) { perror("recv"); } else { printf("recvfrom 11\n"); //printf("Received %d byte reply from %s:\n", siz , dst_addr); printf("node num :[ %d] IP= %s:\n", ip-&gt;ttl, dst_addr); ip_reply = (struct iphdr*) buffer; icmp_reply = (struct icmphdr*)(buffer+sizeof(struct iphdr)); for (i = 0; i &lt; siz; i++) { printf("%02X%s", (uint8_t)buffer[i], (i + 1)%16 ? " " : "\n"); } printf("\n icmp_reply-&gt;type %d \n",icmp_reply-&gt;type); printf("RCV ip-&gt;daddr = %s \n",inet_ntoa(*((struct in_addr *)&amp;ip_reply-&gt;saddr))); printf("\n"); printf("ID: %d\n", ntohs(ip_reply-&gt;id)); printf("TTL: %d\n", ip_reply-&gt;ttl); } printf("recvfrom 12\n"); } 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) &amp;&amp; (!(*(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) &amp;&amp; (*(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] &lt;-s [source]&gt;\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-&gt;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-&gt;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 &gt; 1) { sum += *w++; nleft -= 2; } /* mop up an odd byte, if necessary */ if (nleft == 1) { *(u_char *) (&amp;answer) = *(u_char *) w; sum += answer; } /* add back carry outs from top 16 bits to low 16 bits */ sum = (sum &gt;&gt; 16) + (sum &amp; 0xffff); /* add hi 16 to low 16 */ sum += (sum &gt;&gt; 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return (answer); } </code></pre> <p>the issue is when I add "toto" variable the program is blocking</p> <p>===> result of running code when is blocked </p> <pre><code>root@root:/home/aa/test# ./ping www.yahoo.com Source address: 192.168.1.227 Destination address: 98.139.183.24 =====&gt; sockfd= 3 Sent 28 byte packet to 98.139.183.24 , &gt;&gt;&gt;&gt;&gt; TTL=1 45 00 1C 00 00 00 00 00 01 01 C1 CE C0 A8 01 E3 62 8B B7 18 08 00 90 BA 67 45 00 00 ICMP msgtype=8, code=0 recvfrom 00 </code></pre> <p>it's weird but when I compile with optimisation flag the problem doesn't occur </p> <p>==> gcc -O -o ping ping.c instead of using gcc -O -o ping ping.c</p> <p>this is the first problem !!</p> <p>the second problem occurred when I use timeout in setsockopt function. !!</p> <p>in the code I replace this function </p> <pre><code>setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &amp;optval, sizeof(int)); </code></pre> <p>by : </p> <pre><code>if (setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&amp;timeout, sizeof(timeout)) &lt; 0) error("setsockopt failed\n"); if (setsockopt (sockfd, SOL_SOCKET , SO_SNDTIMEO, (char *)&amp;timeout, sizeof(timeout)) &lt; 0) error("setsockopt failed\n"); </code></pre> <p>==> the result of running code with error "recv: Resource temporarily unavailable"</p> <pre><code>Source address: 192.168.1.227 Destination address: 98.139.183.24 =====&gt; sockfd= 3 Sent 28 byte packet to 98.139.183.24 , &gt;&gt;&gt;&gt;&gt; TTL=1 45 00 1C 00 00 00 00 00 01 01 C1 CE C0 A8 01 E3 62 8B B7 18 08 00 90 BA 67 45 00 00 ICMP msgtype=8, code=0 recvfrom 00 recv: Resource temporarily unavailable recvfrom 12 Sent 28 byte packet to 98.139.183.24 , &gt;&gt;&gt;&gt;&gt; TTL=2 45 00 1C 00 00 00 00 00 02 01 C1 CE C0 A8 01 E3 62 8B B7 18 08 00 90 BA 67 45 00 00 ICMP msgtype=8, code=0 recvfrom 00 recv: Resource temporarily unavailable recvfrom 12 Sent 28 byte packet to 98.139.183.24 , &gt;&gt;&gt;&gt;&gt; TTL=3 45 00 1C 00 00 00 00 00 03 01 C1 CE C0 A8 01 E3 62 8B B7 18 08 00 90 BA 67 45 00 00 ICMP msgtype=8, code=0 recvfrom 00 </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload