1 /******************************************************************************
2 Author: Samuel Jero <sj323707@ohio.edu>
6 Description: Program to ping hosts using DCCP REQ packets to test for DCCP connectivity.
7 ******************************************************************************/
15 #include <sys/types.h>
17 #include <sys/socket.h>
18 #include <sys/select.h>
19 #include <netinet/ip.h>
20 #include <netinet/ip6.h>
21 #include <netinet/in.h>
22 #include <netinet/ip_icmp.h>
23 #include <netinet/icmp6.h>
24 #include <arpa/inet.h>
28 #include <linux/dccp.h>
29 #include "checksums.h"
32 #define MAX(x,y) (x>y ? x : y)
33 /*Structure for simpler IPv4/IPv6 Address handling*/
36 struct sockaddr_in *ipv4;
37 struct sockaddr_in6 *ipv6;
50 char* response_label[]= {
52 "Closed Port (Reset)",
53 "Open Port (Response)",
55 "Destination Unreachable",
58 "DCCP Not Supported (Parameter Problem)"
68 enum responses reply_type;
90 int debug=0; /*set to 1 to turn on debugging information*/
91 int count=-1; /*Default number of pings (-1 is infinity)*/
92 int dest_port=33434; /*Default port*/
93 int ttl=64; /*Default TTL*/
94 long interval=1000; /*Default delay between pings in ms*/
95 int ip_type=AF_UNSPEC; /*IPv4 or IPv6*/
96 ipaddr_ptr_t dest_addr; /*Destination Address*/
97 ipaddr_ptr_t src_addr; /*Source Address*/
98 struct request_queue queue;
99 struct stats ping_stats;
103 void getAddresses(char *src, char* dst);
105 void handleDCCPpacket(int rcv_socket, int send_socket);
106 void handleICMP4packet(int rcv_socket);
107 void handleICMP6packet(int rcv_socket);
108 void buildRequestPacket(unsigned char* buffer, int *len, int seq);
109 void updateRequestPacket(unsigned char* buffer, int *len, int seq);
110 int logPacket(int seq);
111 int logResponse(ipaddr_ptr_t *src, int seq, int type);
112 void dbgprintf(int level, const char *fmt, ...);
113 void sanitize_environment();
117 /*Parse commandline options*/
118 int main(int argc, char *argv[])
125 ping_stats.replies_received=0;
126 ping_stats.requests_sent=0;
127 ping_stats.rtt_avg=0;
128 ping_stats.rtt_max=0;
129 ping_stats.rtt_min=0;
132 sanitize_environment();
134 while ((c = getopt(argc, argv, "64c:p:i:dt:S:")) != -1) {
143 count = atoi(optarg);
145 dbgprintf(0, "Error: count must be positive");
150 dest_port = atoi(optarg);
153 interval = (long)(atof(optarg) * 1000.0);
155 fprintf(stderr, "Invalid interval\n");
164 if (ttl < 1 || ttl > 255) {
165 fprintf(stderr, "Invalid TTL\n");
185 getAddresses(src, dst);
186 if(src_addr.gen==NULL || dest_addr.gen==NULL){
187 dbgprintf(0,"Error: Can't determine source or destination address\n");
198 void getAddresses(char *src, char* dst){
199 struct addrinfo hint;
200 struct addrinfo *dtmp, *stmp;
201 struct ifaddrs *temp, *cur;
202 struct sockaddr_in6* iv6;
206 /*Lookup destination Address*/
207 memset(&hint,0,sizeof(struct addrinfo));
208 hint.ai_family=ip_type;
209 hint.ai_flags=AI_V4MAPPED | AI_ADDRCONFIG;
211 if((err=getaddrinfo(dst,NULL,&hint,&dtmp))!=0){
212 dbgprintf(0,"Error: Couldn't lookup destination %s (%s)\n", dst, gai_strerror(err));
216 dbgprintf(0,"Error: Unknown Host %s\n", dst);
219 addrlen=dtmp->ai_addrlen;
220 hint.ai_family=ip_type=dtmp->ai_family;
221 dest_addr.gen=malloc(dtmp->ai_addrlen);
222 if(dest_addr.gen==NULL){
223 dbgprintf(0,"Error: Can't allocate Memory\n");
226 memcpy(dest_addr.gen,dtmp->ai_addr,dtmp->ai_addrlen);
230 /*Get a meaningful source address*/
232 /*Use Commandline arg*/
233 if((err=getaddrinfo(src,NULL,&hint,&stmp))!=0){
234 dbgprintf(0,"Error: Source Address %s is invalid (%s)\n", src, gai_strerror(err));
238 dbgprintf(0,"Error: Unknown Host %s\n", dst);
241 addrlen=stmp->ai_addrlen;
242 src_addr.gen=malloc(stmp->ai_addrlen);
243 if(src_addr.gen==NULL){
244 dbgprintf(0,"Error: Can't allocate Memory\n");
247 memcpy(src_addr.gen,stmp->ai_addr,stmp->ai_addrlen);
251 /*Guess a good source address*/
255 if(cur->ifa_addr==NULL || cur->ifa_addr->sa_family!=ip_type){ /*Not matching ipv4/ipv6 of dest*/
259 if(cur->ifa_flags & IFF_LOOPBACK){ /*Don't use loopback addresses*/
263 if(cur->ifa_addr!=NULL && cur->ifa_addr->sa_family==AF_INET6){
264 iv6=(struct sockaddr_in6*)cur->ifa_addr;
266 if(iv6->sin6_scope_id!=0){ /*Not globally valid address, if ipv6*/
272 src_addr.gen=malloc(sizeof(struct sockaddr_storage));
273 if(src_addr.gen==NULL){
274 dbgprintf(0,"Error: Can't allocate Memory\n");
277 src_addr.gen->sa_family=ip_type;
278 memcpy(src_addr.gen,cur->ifa_addr,addrlen);
287 /*Preform the ping functionality*/
293 unsigned char sbuffer[slen];
295 struct timeval timeout;
296 struct timeval t,delay, add;
301 rs=socket(ip_type, SOCK_RAW ,IPPROTO_RAW);
303 dbgprintf(0, "Error opening raw socket\n");
306 ds=socket(ip_type, SOCK_RAW ,IPPROTO_DCCP);
308 dbgprintf(0, "Error opening raw DCCP socket\n");
311 is4=socket(ip_type,SOCK_RAW,IPPROTO_ICMP);
313 dbgprintf(0,"Error opening raw ICMPv4 socket\n");
316 is6=socket(ip_type,SOCK_RAW,IPPROTO_ICMPV6);
318 dbgprintf(0,"Error opening raw ICMPv6 socket\n");
323 /*Build DCCP packet*/
324 buildRequestPacket(sbuffer,&slen,seq);
325 if(ip_type==AF_INET){
326 addrlen=sizeof(struct sockaddr_in);
328 addrlen=sizeof(struct sockaddr_in6);
332 if(ip_type==AF_INET){
333 dbgprintf(0, "PINGING %s on DCCP port %i\n",
334 inet_ntop(ip_type, (void*)&dest_addr.ipv4->sin_addr, pbuf, 1000),dest_port);
336 dbgprintf(0, "PINGING %s on DCCP port %i\n",
337 inet_ntop(ip_type, (void*)&dest_addr.ipv6->sin6_addr, pbuf, 1000),dest_port);
342 if(sendto(rs, &sbuffer, slen, MSG_DONTWAIT,(struct sockaddr*)dest_addr.gen,addrlen)<0){
343 dbgprintf(0,"Error: sendto failed\n");
345 if (logPacket(seq)<0){
346 dbgprintf(0,"Error: Couldn't record request!\n");
348 if(ip_type==AF_INET){
349 dbgprintf(1, "Sending DCCP Request to %s\n",inet_ntop(ip_type, (void*)&dest_addr.ipv4->sin_addr, pbuf, 1000));
351 dbgprintf(1, "Sending DCCP Request to %s\n",inet_ntop(ip_type, (void*)&dest_addr.ipv6->sin6_addr, pbuf, 1000));
354 /*Use select to wait on packets or until interval has passed*/
355 add.tv_sec=interval/1000;
356 add.tv_usec=(interval%1000)*1000;
357 gettimeofday(&t,NULL);
358 timeradd(&t,&add,&delay);
359 while(timercmp(&t,&delay,<)){
360 /*Prepare for select*/
365 timersub(&delay,&t,&timeout);
368 if(select(MAX(ds+1,MAX(is4+1,is6+1)),&sel, NULL,NULL,&timeout)<0){
369 dbgprintf(0,"Select() error\n");
372 if(FD_ISSET(ds,&sel)){
373 /*Data on the DCCP socket*/
374 handleDCCPpacket(ds,rs);
377 if(FD_ISSET(is4,&sel) && ip_type==AF_INET){
378 /*Data on the ICMPv4 socket*/
379 handleICMP4packet(is4);
381 if(FD_ISSET(is6,&sel) && ip_type==AF_INET6){
382 /*Data on the ICMPv6 socket*/
383 handleICMP6packet(is6);
385 gettimeofday(&t,NULL);
397 updateRequestPacket(sbuffer,&slen, seq);
406 void handleDCCPpacket(int rcv_socket, int send_socket){
408 unsigned char rbuffer[rlen];
409 ipaddr_ptr_t rcv_addr;
410 socklen_t rcv_addr_len;
411 struct dccp_hdr *dhdr;
412 struct dccp_hdr_reset *dhdr_re;
413 struct dccp_hdr_response *dhdr_rp;
414 struct dccp_hdr_ack_bits *dhdr_sync;
418 /*Memory for socket address*/
419 rcv_addr_len=sizeof(struct sockaddr_storage);
420 rcv_addr.gen=malloc(rcv_addr_len);
421 if(rcv_addr.gen==NULL){
422 dbgprintf(0,"Error: Can't Allocate Memory!\n");
427 rcv_addr_len=sizeof(struct sockaddr_storage);
428 if((rlen=recvfrom(rcv_socket, &rbuffer, 1000,0,rcv_addr.gen,&rcv_addr_len))<0){
429 dbgprintf(0, "Error on receive from DCCP socket (%s)\n",strerror(errno));
432 if(rcv_addr.gen->sa_family!=ip_type){ //confirm IP type
433 dbgprintf(1, "DCCP packet on %s. Tossing.\n", (ip_type==AF_INET) ? "IPv4" : "IPv6");
438 if(rcv_addr.gen->sa_family==AF_INET){
440 if(memcmp(&rcv_addr.ipv4->sin_addr,&dest_addr.ipv4->sin_addr,
441 sizeof(dest_addr.ipv4->sin_addr))!=0){ //not from destination
442 dbgprintf(1,"DCCP packet from 3rd host\n");
446 if(rlen < sizeof(struct dccp_hdr)+sizeof(struct iphdr)){ //check packet size
448 dbgprintf(1, "Packet smaller than possible DCCP packet received on DCCP socket\n");
452 iph=(struct iphdr*)rbuffer;
453 ptr=rbuffer+iph->ihl*4;
456 if(memcmp(&rcv_addr.ipv6->sin6_addr, &dest_addr.ipv6->sin6_addr,
457 sizeof(dest_addr.ipv6->sin6_addr))!=0){ //not from destination
458 dbgprintf(1,"DCCP packet from 3rd host\n");
462 if(rlen < sizeof(struct dccp_hdr)){ //check packet size
464 dbgprintf(1, "Packet smaller than possible DCCP packet received on DCCP socket\n");
472 dhdr=(struct dccp_hdr*)ptr;
473 if(dhdr->dccph_sport!=htons(dest_port)){
474 dbgprintf(1,"DCCP packet with wrong Source Port (%i)\n", ntohs(dhdr->dccph_sport));
478 if(dhdr->dccph_dport!=htons(dest_port)){
479 dbgprintf(1,"DCCP packet with wrong Destination Port\n");
485 if(dhdr->dccph_type==DCCP_PKT_RESET){
486 if(rlen < (ptr-rbuffer)+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_reset)){
487 dbgprintf(1, "Error: Reset packet too small!");
490 dhdr_re=(struct dccp_hdr_reset*)(ptr+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext));
491 logResponse(&rcv_addr, ntohl(dhdr_re->dccph_reset_ack.dccph_ack_nr_low), RESET);
492 /*Nothing else to do*/
494 if(dhdr->dccph_type==DCCP_PKT_RESPONSE){
495 if(rlen < (ptr-rbuffer)+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_response)){
496 dbgprintf(1, "Error: Response packet too small!");
499 dhdr_rp=(struct dccp_hdr_response*)(ptr+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext));
500 logResponse(&rcv_addr,ntohl(dhdr_rp->dccph_resp_ack.dccph_ack_nr_low),RESPONSE);
501 /*TODO:Send Close back*/
503 if(dhdr->dccph_type==DCCP_PKT_SYNC || dhdr->dccph_type==DCCP_PKT_SYNCACK){
504 if(rlen < (ptr-rbuffer)+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_ack_bits)){
505 dbgprintf(1, "Error: Response packet too small!");
508 dhdr_sync=(struct dccp_hdr_ack_bits*)(ptr+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext));
509 logResponse(&rcv_addr,ntohl(dhdr_sync->dccph_ack_nr_low),SYNC);
516 void handleICMP4packet(int rcv_socket){
518 unsigned char rbuffer[rlen];
519 ipaddr_ptr_t rcv_addr;
520 socklen_t rcv_addr_len;
521 struct icmphdr *icmp4;
522 struct dccp_hdr *dhdr;
523 struct dccp_hdr_ext *dhdre;
524 struct iphdr* ip4hdr;
527 /*Memory for socket address*/
528 rcv_addr_len=sizeof(struct sockaddr_storage);
529 rcv_addr.gen=malloc(rcv_addr_len);
530 if(rcv_addr.gen==NULL){
531 dbgprintf(0,"Error: Can't Allocate Memory!\n");
536 if((rlen=recvfrom(rcv_socket, &rbuffer, 1000,0,rcv_addr.gen,&rcv_addr_len))<0){
537 dbgprintf(0, "Error on receive from ICMPv4 socket (%s)\n",strerror(errno));
540 if(rlen < sizeof(struct icmphdr)){ //check packet size
541 dbgprintf(1, "Packet smaller than possible ICMPv4 packet!\n");
546 icmp4=(struct icmphdr*)rbuffer;
547 if(icmp4->type!=ICMP_DEST_UNREACH && icmp4->type!=ICMP_TIME_EXCEEDED){ //check icmp types
548 dbgprintf(1, "Tossing ICMPv4 packet of type %i\n", icmp4->type);
553 /*Check packet size again*/
554 if(rlen<sizeof(struct icmphdr)+sizeof(struct iphdr)+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)){
555 dbgprintf(1, "Tossing ICMPv4 packet that's too small to contain DCCP header!\n");
560 /*Decode IPv4 header*/
561 ip4hdr=(struct iphdr*)(rbuffer+sizeof(struct icmphdr));
562 if(memcmp(&src_addr.ipv4->sin_addr,&ip4hdr->saddr,sizeof(src_addr.ipv4->sin_addr))!=0){
563 /*Source address doesn't match*/
567 if(memcmp(&dest_addr.ipv4->sin_addr,&ip4hdr->daddr,sizeof(dest_addr.ipv4->sin_addr))!=0){
568 /*Destination address doesn't match*/
572 if(ip4hdr->protocol!=IPPROTO_DCCP){
578 /*Decode DCCP header*/
579 dhdr=(struct dccp_hdr*)(rbuffer+sizeof(struct icmphdr)+ip4hdr->ihl*4);
580 if(dhdr->dccph_dport!=htons(dest_port)){
581 /*DCCP Destination Ports don't match*/
585 if(dhdr->dccph_sport!=htons(dest_port)){
586 /*DCCP Source Ports don't match*/
590 dhdre=(struct dccp_hdr_ext*)(rbuffer+sizeof(struct icmphdr)+ip4hdr->ihl*4+sizeof(struct dccp_hdr));
593 if(icmp4->type==ICMP_DEST_UNREACH){
594 type=DEST_UNREACHABLE;
596 if(icmp4->type==ICMP_TIME_EXCEEDED){
599 logResponse(&rcv_addr,ntohl(dhdre->dccph_seq_low),type);
604 void handleICMP6packet(int rcv_socket){
606 unsigned char rbuffer[rlen];
607 ipaddr_ptr_t rcv_addr;
608 socklen_t rcv_addr_len;
609 struct icmp6_hdr *icmp6;
610 struct ip6_hdr* ip6hdr;
611 struct dccp_hdr *dhdr;
612 struct dccp_hdr_ext *dhdre;
615 /*Memory for socket address*/
616 rcv_addr_len=sizeof(struct sockaddr_storage);
617 rcv_addr.gen=malloc(rcv_addr_len);
618 if(rcv_addr.gen==NULL){
619 dbgprintf(0,"Error: Can't Allocate Memory!\n");
624 if((rlen=recvfrom(rcv_socket, &rbuffer, 1000,0,rcv_addr.gen,&rcv_addr_len))<0){
625 dbgprintf(0, "Error on receive from ICMPv6 socket (%s)\n",strerror(errno));
628 if(rlen < sizeof(struct icmp6_hdr)){ //check packet size
629 dbgprintf(1, "Packet smaller than possible ICMPv6 packet!\n");
634 icmp6=(struct icmp6_hdr*)rbuffer;
635 if(icmp6->icmp6_type!=ICMP6_DST_UNREACH && icmp6->icmp6_type!=ICMP6_PACKET_TOO_BIG
636 && icmp6->icmp6_type!=ICMP6_TIME_EXCEEDED && icmp6->icmp6_type!=ICMP6_PARAM_PROB){ //check icmp types
637 dbgprintf(1, "Tossing ICMPv6 packet of type %i\n", icmp6->icmp6_type);
642 /*Check packet size again*/
643 if(rlen<sizeof(struct icmp6_hdr)+sizeof(struct ip6_hdr)+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)){
644 dbgprintf(1, "Tossing ICMPv6 packet that's too small to contain DCCP header!\n");
649 /*Decode IPv6 header*/
650 ip6hdr=(struct ip6_hdr*)(rbuffer+sizeof(struct icmp6_hdr));
651 if(memcmp(&src_addr.ipv6->sin6_addr,&ip6hdr->ip6_src,sizeof(src_addr.ipv6->sin6_addr))!=0){
652 /*Source address doesn't match*/
656 if(memcmp(&dest_addr.ipv6->sin6_addr,&ip6hdr->ip6_dst,sizeof(dest_addr.ipv6->sin6_addr))!=0){
657 /*Destination address doesn't match*/
661 if(ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_nxt!=IPPROTO_DCCP){
667 /*Decode DCCP header*/
668 dhdr=(struct dccp_hdr*)(rbuffer+sizeof(struct icmp6_hdr)+sizeof(struct ip6_hdr));
669 if(dhdr->dccph_dport!=htons(dest_port)){
670 /*DCCP Destination Ports don't match*/
674 if(dhdr->dccph_sport!=htons(dest_port)){
675 /*DCCP Source Ports don't match*/
679 dhdre=(struct dccp_hdr_ext*)(rbuffer+sizeof(struct icmp6_hdr)+sizeof(struct ip6_hdr)+sizeof(struct dccp_hdr));
684 if(icmp6->icmp6_type==ICMP6_DST_UNREACH){
685 type=DEST_UNREACHABLE;
687 if(icmp6->icmp6_type==ICMP6_PACKET_TOO_BIG){
690 if(icmp6->icmp6_type==ICMP6_TIME_EXCEEDED){
693 if(icmp6->icmp6_type==ICMP6_PARAM_PROB){
694 type=PARAMETER_PROBLEM;
696 logResponse(&rcv_addr,ntohl(dhdre->dccph_seq_low),type);
701 void buildRequestPacket(unsigned char* buffer, int *len, int seq){
702 struct dccp_hdr *dhdr;
703 struct dccp_hdr_ext *dhdre;
704 struct dccp_hdr_request *dhdrr;
705 struct iphdr* ip4hdr;
706 struct ip6_hdr* ip6hdr;
709 int dccp_hdr_len=sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_request);
711 if(*len < dccp_hdr_len+sizeof(struct ip6_hdr)){
712 dbgprintf(0, "Error: Insufficient buffer space\n");
716 memset(buffer, 0, *len);
720 if(ip_type==AF_INET){
721 ip_hdr_len=sizeof(struct iphdr);
722 ip4hdr=(struct iphdr*)buffer;
723 ip4hdr->check=htons(0);
724 memcpy(&ip4hdr->daddr, &dest_addr.ipv4->sin_addr, sizeof(dest_addr.ipv4->sin_addr));
725 ip4hdr->frag_off=htons(0);
726 ip4hdr->id=htons(1);//first
728 ip4hdr->protocol=IPPROTO_DCCP;
729 memcpy(&ip4hdr->saddr, &src_addr.ipv4->sin_addr, sizeof(src_addr.ipv4->sin_addr));
731 ip4hdr->tot_len=htons(ip_hdr_len+dccp_hdr_len);
735 ip_hdr_len=sizeof(struct ip6_hdr);
736 ip6hdr=(struct ip6_hdr*)buffer;
737 memcpy(&ip6hdr->ip6_dst, &dest_addr.ipv6->sin6_addr, sizeof(dest_addr.ipv6->sin6_addr));
738 memcpy(&ip6hdr->ip6_src, &src_addr.ipv6->sin6_addr, sizeof(src_addr.ipv6->sin6_addr));
739 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_flow=htonl(6<<28); //version, traffic class, flow label
740 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_hlim=ttl;
741 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_nxt=IPPROTO_DCCP;
742 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_plen=htons(dccp_hdr_len);
746 dhdr=(struct dccp_hdr*)(buffer+ip_hdr_len);
747 dhdre=(struct dccp_hdr_ext*)(buffer+ip_hdr_len+sizeof(struct dccp_hdr));
748 dhdrr=(struct dccp_hdr_request*)(buffer+ip_hdr_len+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext));
750 dhdr->dccph_checksum=0;
752 dhdr->dccph_doff=dccp_hdr_len/4;
753 dhdr->dccph_dport=htons(dest_port);
754 dhdr->dccph_reserved=0;
755 dhdr->dccph_sport=htons(dest_port);
757 dhdr->dccph_type=DCCP_PKT_REQUEST;
758 dhdr->dccph_seq2=htonl(0); //Reserved if using 48 bit sequence numbers
759 dhdr->dccph_seq=htonl(0); //High 16bits of sequence number. Always make 0 for simplicity.
760 dhdre->dccph_seq_low=htonl(seq);
761 dhdrr->dccph_req_service= htonl(0x50455246);
764 if(ip_type==AF_INET){
765 dhdr->dccph_checksum=ipv4_pseudohdr_chksum((buffer+ip_hdr_len), dccp_hdr_len,
766 (unsigned char*) &dest_addr.ipv4->sin_addr,
767 (unsigned char*)&src_addr.ipv4->sin_addr, IPPROTO_DCCP);
768 ip4hdr->check=ipv4_chksum(buffer,ip_hdr_len);
770 dhdr->dccph_checksum=ipv6_pseudohdr_chksum((buffer+ip_hdr_len), dccp_hdr_len,
771 (unsigned char*) &dest_addr.ipv6->sin6_addr,
772 (unsigned char*)&src_addr.ipv6->sin6_addr, IPPROTO_DCCP);
774 *len=ip_hdr_len+dccp_hdr_len;
778 void updateRequestPacket(unsigned char* buffer, int *len, int seq){
779 struct dccp_hdr *dhdr;
780 struct dccp_hdr_ext *dhdre;
781 struct iphdr* ip4hdr;
784 int dccp_hdr_len=sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_request);
788 if(ip_type==AF_INET){
789 ip_hdr_len=sizeof(struct iphdr);
790 ip4hdr=(struct iphdr*)buffer;
791 ip4hdr->check=htons(0);
792 ip4hdr->id=htons(seq);
794 ip_hdr_len=sizeof(struct ip6_hdr);
798 dhdr=(struct dccp_hdr*)(buffer+ip_hdr_len);
799 dhdre=(struct dccp_hdr_ext*)(buffer+ip_hdr_len+sizeof(struct dccp_hdr));
800 dhdr->dccph_checksum=0;
801 dhdre->dccph_seq_low=htonl(seq);
804 if(ip_type==AF_INET){
805 dhdr->dccph_checksum=ipv4_pseudohdr_chksum((buffer+ip_hdr_len), dccp_hdr_len,
806 (unsigned char*) &dest_addr.ipv4->sin_addr,
807 (unsigned char*)&src_addr.ipv4->sin_addr, IPPROTO_DCCP);
808 ip4hdr->check=ipv4_chksum(buffer,ip_hdr_len);
810 dhdr->dccph_checksum=ipv6_pseudohdr_chksum((buffer+ip_hdr_len), dccp_hdr_len,
811 (unsigned char*) &dest_addr.ipv6->sin6_addr,
812 (unsigned char*)&src_addr.ipv6->sin6_addr, IPPROTO_DCCP);
814 *len=ip_hdr_len+dccp_hdr_len;
818 int logPacket(int seq){
821 /*Add new request to queue*/
822 tmp=malloc(sizeof(struct request));
824 dbgprintf(0,"Error: Can't allocate Memory!\n");
832 tmp->reply_type=UNKNOWN;
833 gettimeofday(&tmp->sent,NULL);
835 if(queue.head==NULL){
836 queue.head=queue.tail=tmp;
839 queue.head->prev=tmp;
840 tmp->next=queue.head;
843 /*Update Statistics*/
844 if(ping_stats.requests_sent==0){
845 gettimeofday(&ping_stats.start,NULL);
847 ping_stats.requests_sent++;
851 int logResponse(ipaddr_ptr_t *src, int seq, int type){
856 if(queue.tail==NULL){
857 dbgprintf(1,"Response received but no requests sent!\n");
865 gettimeofday(&cur->reply,NULL);
866 if(type<DEST_UNREACHABLE && type!=UNKNOWN){
871 cur->reply_type=type;
878 dbgprintf(1,"Response received but no requests sent with sequence number %i!\n", seq);
882 diff=(cur->reply.tv_usec + 1000000*cur->reply.tv_sec) - (cur->sent.tv_usec + 1000000*cur->sent.tv_sec);
886 if(type<DEST_UNREACHABLE && type!=UNKNOWN){
887 if(ip_type==AF_INET){
888 dbgprintf(0, "Response from %s : seq=%i time=%.1fms status=%s\n",
889 inet_ntop(ip_type, (void*)&src->ipv4->sin_addr, pbuf, 1000),
890 seq, diff,response_label[type]);
892 dbgprintf(0, "Response from %s : seq=%i time=%.1fms status=%s\n",
893 inet_ntop(ip_type, (void*)&src->ipv6->sin6_addr, pbuf, 1000),
894 seq, diff,response_label[type]);
897 if(ip_type==AF_INET){
898 dbgprintf(0, "%s from %s : seq=%i\n",response_label[type],
899 inet_ntop(ip_type, (void*)&src->ipv4->sin_addr, pbuf, 1000),
902 dbgprintf(0, "%s from %s : seq=%i\n",response_label[type],
903 inet_ntop(ip_type, (void*)&src->ipv6->sin6_addr, pbuf, 1000),
908 /*Update statistics*/
909 if(type<DEST_UNREACHABLE && type!=UNKNOWN){
911 ping_stats.rtt_avg=((ping_stats.replies_received*ping_stats.rtt_avg)+(diff))/(ping_stats.replies_received+1);
912 ping_stats.replies_received++;
913 if(diff < ping_stats.rtt_min){
914 ping_stats.rtt_min=diff;
916 if(diff > ping_stats.rtt_max){
917 ping_stats.rtt_max=diff;
923 gettimeofday(&ping_stats.stop,NULL);
927 /*Usage information for program*/
930 dbgprintf(0, "dccpping: [-d] [-6|-4] [-c count] [-p port] [-i interval] [-t ttl] [-S srcaddress] remote_host\n");
934 /*Program will probably be run setuid, so be extra careful*/
935 void sanitize_environment()
937 #if defined(_SVID_SOURCE) || defined(_XOPEN_SOURCE)
940 extern char **environ;
946 void dbgprintf(int level, const char *fmt, ...)
951 vfprintf(stderr, fmt, args);