]> sjero.net Git - dccpping/blob - dccpping.c
Add #define option to enable multiplexing DCCP ping streams based on PID via the...
[dccpping] / dccpping.c
1 /******************************************************************************
2 Author: Samuel Jero <sj323707@ohio.edu>
3
4 Date: 10/2012
5
6 Description: Program to ping hosts using DCCP REQ packets to test for DCCP connectivity.
7 ******************************************************************************/
8 #include <stdarg.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <strings.h>
13 #include <unistd.h>
14 #include <errno.h>
15 #include <signal.h>
16 #include <sys/types.h>
17 #include <sys/time.h>
18 #include <sys/socket.h>
19 #include <sys/select.h>
20 #include <netinet/ip.h>
21 #include <netinet/ip6.h>
22 #include <netinet/in.h>
23 #include <netinet/ip_icmp.h>
24 #include <netinet/icmp6.h>
25 #include <arpa/inet.h>
26 #include <netdb.h>
27 #include <net/if.h>
28 #include <ifaddrs.h>
29 #include <linux/dccp.h>
30 #include "checksums.h"
31
32
33 /*Use the DCCP source port to multiplex DCCP Ping streams by PID*/
34 #define SRC_PORT_AS_PID_MULTIPLEX 1
35
36
37 #define MAX(x,y) (x>y ? x : y)
38 extern int errno;
39
40
41 /*Structure for simpler IPv4/IPv6 Address handling*/
42 typedef union ipaddr{
43         struct sockaddr *gen;
44         struct sockaddr_in *ipv4;
45         struct sockaddr_in6 *ipv6;
46 } ipaddr_ptr_t;
47
48 /*Possible Responses to a Request*/
49 enum responses{
50         UNKNOWN=0,
51         RESET,
52         RESPONSE,
53         SYNC,
54         DEST_UNREACHABLE,
55         TTL_EXPIRATION,
56         TOO_BIG,
57         PARAMETER_PROBLEM,
58         DCCP_ERROR
59 };
60
61 /*Output strings corresponding to enum responses*/
62 static const char* response_label[]= {
63 "Unknown",
64 "Closed Port (Reset)",
65 "Open Port (Response)",
66 "Open Port (Sync)",
67 "Destination Unreachable",
68 "TTL Expiration",
69 "Packet Too Big",
70 "DCCP Not Supported (Parameter Problem)",
71 "Protocol Error (DCCP Reset)"
72 };
73
74 /*Structure to keep track of information about a request*/
75 struct request{
76         int                             request_seq;
77         int                             packet_seq;
78         int                             num_replies;
79         int                             num_errors;
80         struct timeval  sent;
81         struct timeval  reply;
82         enum responses  reply_type;
83         struct request  *next;
84         struct request  *prev;
85 };
86
87 /*Request Queue head structure*/
88 struct request_queue{
89         struct request *head;
90         struct request *tail;
91 };
92
93 /*Statistics about the requests and replies sent*/
94 struct stats{
95         int                             requests_sent;
96         int                             replies_received;
97         int                             errors;
98         double                  rtt_min;
99         double                  rtt_avg;
100         double                  rtt_max;
101         struct timeval  start;
102         struct timeval  stop;
103 };
104
105 struct params{
106         int count;                              /*Number of pings (-1 is infinity)*/
107         int dest_port;                  /*Destination port*/
108         int src_port;                   /*Source port---used to encode pid*/
109         int ttl;                                /*TTL*/
110         long interval;                  /*Delay between pings in ms*/
111         int ip_type;                    /*IPv4 or IPv6*/
112         ipaddr_ptr_t dest_addr; /*Destination Address*/
113         ipaddr_ptr_t src_addr;  /*Source Address*/
114 };
115
116
117 int                                     debug=0;                /*set to 1 to turn on debugging information*/
118 struct request_queue    queue;                  /*Queue of requests to track RTT/duplicate information*/
119 struct stats                    ping_stats;             /*Ping Statistics*/
120 struct params                   parms;                  /*Parameters for ping*/
121
122
123 void getAddresses(char *src, char* dst);
124 void doping();
125 void handleDCCPpacket(int rcv_socket, int send_socket);
126 void handleICMP4packet(int rcv_socket);
127 void handleICMP6packet(int rcv_socket);
128 void buildRequestPacket(unsigned char* buffer, int *len, int seq);
129 void updateRequestPacket(unsigned char* buffer, int *len, int seq);
130 void sendClose(int seq, u_int16_t ack_h, u_int32_t ack_l, int socket);
131 void sendReset(int seq, u_int16_t ack_h, u_int32_t ack_l, int socket);
132 int logPacket(int req_seq, int packet_seq);
133 int logResponse(ipaddr_ptr_t *src, int seq, int type);
134 void clearQueue();
135 void sigHandler();
136 void usage();
137 void sanitize_environment();
138 void dbgprintf(int level, const char *fmt, ...);
139
140
141 /*Parse commandline options*/
142 int main(int argc, char *argv[])
143 {
144         char c;
145         char *src=NULL;
146         char *dst=NULL;
147
148         /*Set Defaults*/
149         queue.head=NULL;
150         queue.tail=NULL;
151         ping_stats.replies_received=0;
152         ping_stats.requests_sent=0;
153         ping_stats.rtt_avg=0;
154         ping_stats.rtt_max=0;
155         ping_stats.rtt_min=0;
156         ping_stats.errors=0;
157         parms.count=-1;
158         parms.dest_port=33434;
159         parms.ttl=64;
160         parms. interval=1000;
161         parms.ip_type=AF_UNSPEC;
162         parms.dest_addr.gen=NULL;
163         parms.src_addr.gen=NULL;
164
165         sanitize_environment();
166
167         while ((c = getopt(argc, argv, "64c:p:i:dt:S:")) != -1) {
168                 switch (c) {
169                         case '6':
170                                 parms.ip_type=AF_INET6;
171                                 break;
172                         case '4':
173                                 parms.ip_type=AF_INET;
174                                 break;
175                         case 'c':
176                                 parms.count = atoi(optarg);
177                                 if(parms.count<=0){
178                                         dbgprintf(0, "Error: count must be positive");
179                                         exit(1);
180                                 }
181                                 break;
182                         case 'p':
183                                 parms.dest_port = atoi(optarg);
184                                 break;
185                         case 'i':
186                                 parms.interval = (long)(atof(optarg) * 1000.0);
187                                 if (parms.interval <= 0) {
188                                         dbgprintf(0, "Error: Invalid interval\n");
189                                         exit(1);
190                                 }
191                                 break;
192                         case 'd':
193                                 debug++;
194                                 break;
195                         case 't':
196                                 parms.ttl = atoi(optarg);
197                                 if (parms.ttl < 1 || parms.ttl > 255) {
198                                         dbgprintf(0,"Error: Invalid TTL\n");
199                                 }
200                                 break;
201                         case 'S':
202                                 src=optarg;
203                                 break;
204                         default:
205                                 usage();
206                                 break;
207                 }
208         }
209
210         argc -= optind;
211         argv += optind;
212
213         if (argc != 1) {
214                 usage();
215         }
216         dst=argv[0];
217
218 #if SRC_PORT_AS_PID_MULTIPLEX
219         /*Encode PID in source port*/
220         parms.src_port=(getpid()+1024)%65535;
221 #else
222         parms.src_port=parms.dest_port;
223 #endif
224
225         getAddresses(src, dst);
226         if(parms.src_addr.gen==NULL || parms.dest_addr.gen==NULL){
227                 dbgprintf(0,"Error: Can't determine source or destination address\n");
228                 exit(1);
229         }
230
231         signal(SIGINT, sigHandler);
232         doping();
233
234         free(parms.src_addr.gen);
235         free(parms.dest_addr.gen);
236         clearQueue();
237         return 0;
238 }
239
240 void getAddresses(char *src, char* dst){
241         struct addrinfo hint;
242         struct addrinfo *dtmp, *stmp;
243         struct ifaddrs *temp, *cur;
244         struct sockaddr_in6* iv6;
245         int addrlen;
246         int err;
247
248         /*Lookup destination Address*/
249         memset(&hint,0,sizeof(struct addrinfo));
250         hint.ai_family=parms.ip_type;
251         hint.ai_flags=AI_V4MAPPED | AI_ADDRCONFIG;
252
253         if((err=getaddrinfo(dst,NULL,&hint,&dtmp))!=0){
254                 dbgprintf(0,"Error: Couldn't lookup destination %s (%s)\n", dst, gai_strerror(err));
255                 exit(1);
256         }
257         if(dtmp==NULL){
258                 dbgprintf(0,"Error: Unknown Host %s\n", dst);
259                 exit(1);
260         }else{
261                 addrlen=dtmp->ai_addrlen;
262                 hint.ai_family=parms.ip_type=dtmp->ai_family;
263                 parms.dest_addr.gen=malloc(dtmp->ai_addrlen);
264                 if(parms.dest_addr.gen==NULL){
265                         dbgprintf(0,"Error: Can't allocate Memory\n");
266                         exit(1);
267                 }
268                 memcpy(parms.dest_addr.gen,dtmp->ai_addr,dtmp->ai_addrlen);
269         }
270         freeaddrinfo(dtmp);
271
272         /*Get a meaningful source address*/
273         if(src!=NULL){
274                 /*Use Commandline arg*/
275                 if((err=getaddrinfo(src,NULL,&hint,&stmp))!=0){
276                         dbgprintf(0,"Error: Source Address %s is invalid (%s)\n", src, gai_strerror(err));
277                         exit(1);
278                 }
279                 if(stmp==NULL){
280                         dbgprintf(0,"Error: Unknown Host %s\n", dst);
281                         exit(1);
282                 }else{
283                         addrlen=stmp->ai_addrlen;
284                         parms.src_addr.gen=malloc(stmp->ai_addrlen);
285                         if(parms.src_addr.gen==NULL){
286                                 dbgprintf(0,"Error: Can't allocate Memory\n");
287                                 exit(1);
288                         }
289                         memcpy(parms.src_addr.gen,stmp->ai_addr,stmp->ai_addrlen);
290                 }
291                 freeaddrinfo(stmp);
292         }else{
293                 /*Guess a good source address*/
294                 getifaddrs(&temp);
295                 cur=temp;
296                 while(cur!=NULL){
297                         if(cur->ifa_addr==NULL || cur->ifa_addr->sa_family!=parms.ip_type){
298                                 /*Not matching ipv4/ipv6 of dest*/
299                                 cur=cur->ifa_next;
300                                 continue;
301                         }
302                         if(cur->ifa_flags & IFF_LOOPBACK){ /*Don't use loopback addresses*/
303                                 cur=cur->ifa_next;
304                                 continue;
305                         }
306                         if(cur->ifa_addr!=NULL && cur->ifa_addr->sa_family==AF_INET6){
307                                 iv6=(struct sockaddr_in6*)cur->ifa_addr;
308
309                                 if(iv6->sin6_scope_id!=0){ /*Not globally valid address, if ipv6*/
310                                         cur=cur->ifa_next;
311                                         continue;
312                                 }
313                         }
314
315                         parms.src_addr.gen=malloc(sizeof(struct sockaddr_storage));
316                         if(parms.src_addr.gen==NULL){
317                                 dbgprintf(0,"Error: Can't allocate Memory\n");
318                                 exit(1);
319                         }
320                         parms.src_addr.gen->sa_family=parms.ip_type;
321                         memcpy(parms.src_addr.gen,cur->ifa_addr,addrlen);
322                         //break;
323                         cur=cur->ifa_next;
324                 }
325                 freeifaddrs(temp);
326         }
327         return;
328 }
329
330 /*Preform the ping functionality*/
331 void doping(){
332         int rs, is4,is6,ds;
333         int done=0;
334         int addrlen;
335         int slen=1500;
336         unsigned char sbuffer[slen];
337         fd_set sel;
338         struct timeval timeout;
339         struct timeval t,delay, add;
340         char pbuf[1000];
341         int request_seq=1;
342         int packet_seq;
343
344         /*Open Sockets*/
345         rs=socket(parms.ip_type, SOCK_RAW ,IPPROTO_RAW);
346         if(rs<0){
347                 dbgprintf(0, "Error opening raw socket\n");
348                 exit(1);
349         }
350         ds=socket(parms.ip_type, SOCK_RAW ,IPPROTO_DCCP);
351         if(ds<0){
352                 dbgprintf(0, "Error opening raw DCCP socket\n");
353                 exit(1);
354         }
355         is4=socket(parms.ip_type,SOCK_RAW,IPPROTO_ICMP);
356         if(is4<0){
357                 dbgprintf(0,"Error opening raw ICMPv4 socket\n");
358                 exit(1);
359         }
360         is6=socket(parms.ip_type,SOCK_RAW,IPPROTO_ICMPV6);
361         if(is6<0){
362                 dbgprintf(0,"Error opening raw ICMPv6 socket\n");
363                 exit(1);
364         }
365
366
367         /*Build DCCP packet*/
368         packet_seq=rand();
369         buildRequestPacket(sbuffer,&slen,packet_seq);
370         if(parms.ip_type==AF_INET){
371                 addrlen=sizeof(struct sockaddr_in);
372         }else{
373                 addrlen=sizeof(struct sockaddr_in6);
374         }
375
376         /*Start Message*/
377         if(parms.ip_type==AF_INET){
378                 printf("PINGING %s on DCCP port %i\n",
379                                 inet_ntop(parms.ip_type, (void*)&parms.dest_addr.ipv4->sin_addr, pbuf, 1000),
380                                 parms.dest_port);
381         }else{
382                 printf("PINGING %s on DCCP port %i\n",
383                                 inet_ntop(parms.ip_type, (void*)&parms.dest_addr.ipv6->sin6_addr, pbuf, 1000),
384                                 parms.dest_port);
385         }
386
387         while(!done){
388                 /*Send Ping*/
389                 if(sendto(rs, &sbuffer, slen, MSG_DONTWAIT,(struct sockaddr*)parms.dest_addr.gen,addrlen)<0){
390                         if(errno!=EINTR){
391                                 dbgprintf(0,"Error: sendto failed\n");
392                         }
393                 }
394                 if(parms.count==0){done=1; break;}
395
396                 if (logPacket(request_seq,packet_seq)<0){
397                         dbgprintf(0,"Error: Couldn't record request!\n");
398                 }
399                 if(parms.ip_type==AF_INET){
400                         dbgprintf(1, "Sending DCCP Request to %s\n",
401                                         inet_ntop(parms.ip_type, (void*)&parms.dest_addr.ipv4->sin_addr, pbuf, 1000));
402                 }else{
403                         dbgprintf(1, "Sending DCCP Request to %s\n",
404                                         inet_ntop(parms.ip_type, (void*)&parms.dest_addr.ipv6->sin6_addr, pbuf, 1000));
405                 }
406
407                 /*Use select to wait on packets or until interval has passed*/
408                 add.tv_sec=parms.interval/1000;
409                 add.tv_usec=(parms.interval%1000)*1000;
410                 gettimeofday(&t,NULL);
411                 timeradd(&t,&add,&delay);
412                 while(timercmp(&t,&delay,<)){
413                         /*Prepare for select*/
414                         FD_ZERO(&sel);
415                         FD_SET(ds,&sel);
416                         FD_SET(is4,&sel);
417                         FD_SET(is6,&sel);
418                         timersub(&delay,&t,&timeout);
419
420                         /*Do select call*/
421                         if(select(MAX(ds+1,MAX(is4+1,is6+1)),&sel, NULL,NULL,&timeout)<0){
422                                 if(errno!=EINTR){
423                                         dbgprintf(0,"Select() error (%s)\n",strerror(errno));
424                                 }
425                         }
426                         if(parms.count==0){done=1;break;}
427
428                         if(FD_ISSET(ds,&sel)){
429                                 /*Data on the DCCP socket*/
430                                 handleDCCPpacket(ds,rs);
431
432                         }
433                         if(FD_ISSET(is4,&sel) && parms.ip_type==AF_INET){
434                                 /*Data on the ICMPv4 socket*/
435                                 handleICMP4packet(is4);
436                         }
437                         if(FD_ISSET(is6,&sel) && parms.ip_type==AF_INET6){
438                                 /*Data on the ICMPv6 socket*/
439                                 handleICMP6packet(is6);
440                         }
441                         gettimeofday(&t,NULL);
442                 }
443
444                 /*Update count*/
445                 if(parms.count>-1){
446                         parms.count--;
447                 }
448                 request_seq++;
449                 packet_seq=rand();
450                 updateRequestPacket(sbuffer,&slen, packet_seq);
451         }
452
453         close(rs);
454         close(is4);
455         close(is6);
456         close(ds);
457 }
458
459 void handleDCCPpacket(int rcv_socket, int send_socket){
460         int rlen=1500;
461         unsigned char rbuffer[rlen];
462         ipaddr_ptr_t rcv_addr;
463         socklen_t rcv_addr_len;
464         struct dccp_hdr *dhdr;
465         struct dccp_hdr_reset *dhdr_re;
466         struct dccp_hdr_ext *dhdre;
467         struct dccp_hdr_response *dhdr_rp;
468         struct dccp_hdr_ack_bits *dhdr_sync;
469         unsigned char* ptr;
470         struct iphdr* iph;
471
472         /*Memory for socket address*/
473         rcv_addr_len=sizeof(struct sockaddr_storage);
474         rcv_addr.gen=malloc(rcv_addr_len);
475         if(rcv_addr.gen==NULL){
476                 dbgprintf(0,"Error: Can't Allocate Memory!\n");
477                 exit(1);
478         }
479
480         /*Receive Packet*/
481         rcv_addr_len=sizeof(struct sockaddr_storage);
482         if((rlen=recvfrom(rcv_socket, &rbuffer, 1000,0,rcv_addr.gen,&rcv_addr_len))<0){
483                 if(errno!=EINTR){
484                         dbgprintf(0, "Error on receive from DCCP socket (%s)\n",strerror(errno));
485                 }
486         }
487         if(rlen<0){
488                 return;
489         }
490
491         if(rcv_addr.gen->sa_family!=parms.ip_type){ //confirm IP type
492                 dbgprintf(1, "DCCP packet on %s. Tossing.\n", (parms.ip_type==AF_INET) ? "IPv4" : "IPv6");
493                 free(rcv_addr.gen);
494                 return;
495         }
496
497         if(rcv_addr.gen->sa_family==AF_INET){
498                 /*IPv4*/
499                 if(memcmp(&rcv_addr.ipv4->sin_addr,&parms.dest_addr.ipv4->sin_addr,
500                                 sizeof(parms.dest_addr.ipv4->sin_addr))!=0){ //not from destination
501                         dbgprintf(1,"DCCP packet from 3rd host\n");
502                         free(rcv_addr.gen);
503                         return;
504                 }
505                 if(rlen < sizeof(struct dccp_hdr)+sizeof(struct iphdr)){ //check packet size
506
507                         dbgprintf(1, "Packet smaller than possible DCCP packet received on DCCP socket\n");
508                         free(rcv_addr.gen);
509                         return;
510                 }
511                 iph=(struct iphdr*)rbuffer;
512                 ptr=rbuffer+iph->ihl*4;
513         }else{
514                 /*IPv6*/
515                 if(memcmp(&rcv_addr.ipv6->sin6_addr, &parms.dest_addr.ipv6->sin6_addr,
516                                 sizeof(parms.dest_addr.ipv6->sin6_addr))!=0){ //not from destination
517                         dbgprintf(1,"DCCP packet from 3rd host\n");
518                         free(rcv_addr.gen);
519                         return;
520                 }
521                 if(rlen < sizeof(struct dccp_hdr)){ //check packet size
522
523                         dbgprintf(1, "Packet smaller than possible DCCP packet received on DCCP socket\n");
524                         free(rcv_addr.gen);
525                         return;
526                 }
527                 ptr=rbuffer;
528         }
529
530         /*DCCP checks*/
531         dhdr=(struct dccp_hdr*)ptr;
532         if(dhdr->dccph_sport!=htons(parms.dest_port)){
533                 dbgprintf(1,"DCCP packet with wrong Source Port (%i)\n", ntohs(dhdr->dccph_sport));
534                 free(rcv_addr.gen);
535                 return;
536         }
537         if(dhdr->dccph_dport!=htons(parms.src_port)){
538                 dbgprintf(1,"DCCP packet with wrong Destination Port\n");
539                 free(rcv_addr.gen);
540                 return;
541         }
542
543         /*Pick Response*/
544         if(dhdr->dccph_type==DCCP_PKT_RESET){
545                 if(rlen < (ptr-rbuffer)+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_reset)){
546                         dbgprintf(1, "Tossing DCCP Reset packet that's small!\n");
547                         return;
548                 }
549                 dhdr_re=(struct dccp_hdr_reset*)(ptr+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext));
550
551                 /*Log*/
552                 if(dhdr_re->dccph_reset_code==DCCP_RESET_CODE_NO_CONNECTION){
553                         logResponse(&rcv_addr, ntohl(dhdr_re->dccph_reset_ack.dccph_ack_nr_low), RESET);
554                 }else{
555                         logResponse(&rcv_addr, ntohl(dhdr_re->dccph_reset_ack.dccph_ack_nr_low), DCCP_ERROR);
556                 }
557                 /*Nothing else to do*/
558         }
559         if(dhdr->dccph_type==DCCP_PKT_RESPONSE){
560                 if(rlen < (ptr-rbuffer)+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_response)){
561                         dbgprintf(1, "Tossing DCCP Response packet that's too small!\n");
562                         return;
563                 }
564
565                 /*Log*/
566                 dhdre=(struct dccp_hdr_ext*)(ptr+sizeof(struct dccp_hdr));
567                 dhdr_rp=(struct dccp_hdr_response*)(ptr+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext));
568                 logResponse(&rcv_addr,ntohl(dhdr_rp->dccph_resp_ack.dccph_ack_nr_low),RESPONSE);
569
570                 /*Send Close*/
571                 sendClose(ntohl(dhdr_rp->dccph_resp_ack.dccph_ack_nr_low),
572                                 dhdr->dccph_seq, dhdre->dccph_seq_low,send_socket);
573         }
574         if(dhdr->dccph_type==DCCP_PKT_SYNC || dhdr->dccph_type==DCCP_PKT_SYNCACK){
575                 if(rlen < (ptr-rbuffer)+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_ack_bits)){
576                         dbgprintf(1, "Tossing DCCP Sync/SyncAck packet that's too small!\n");
577                         return;
578                 }
579
580                 /*Log*/
581                 dhdre=(struct dccp_hdr_ext*)(ptr+sizeof(struct dccp_hdr));
582                 dhdr_sync=(struct dccp_hdr_ack_bits*)(ptr+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext));
583                 logResponse(&rcv_addr,ntohl(dhdr_sync->dccph_ack_nr_low),SYNC);
584
585                 /*Send Reset*/
586                 sendReset(ntohl(dhdr_sync->dccph_ack_nr_low),
587                                                 dhdr->dccph_seq, dhdre->dccph_seq_low,send_socket);
588         }
589
590         free(rcv_addr.gen);
591 }
592
593 void handleICMP4packet(int rcv_socket){
594         int rlen=1500;
595         unsigned char rbuffer[rlen];
596         ipaddr_ptr_t rcv_addr;
597         socklen_t rcv_addr_len;
598         struct icmphdr *icmp4;
599         struct dccp_hdr *dhdr;
600         struct dccp_hdr_ext *dhdre;
601         struct iphdr* ip4hdr;
602         int type;
603
604         /*Memory for socket address*/
605         rcv_addr_len=sizeof(struct sockaddr_storage);
606         rcv_addr.gen=malloc(rcv_addr_len);
607         if(rcv_addr.gen==NULL){
608                 dbgprintf(0,"Error: Can't Allocate Memory!\n");
609                 exit(1);
610         }
611
612         /*Receive Packet*/
613         if((rlen=recvfrom(rcv_socket, &rbuffer, 1000,0,rcv_addr.gen,&rcv_addr_len))<0){
614                 if(errno!=EINTR){
615                         dbgprintf(0, "Error on receive from ICMPv4 socket (%s)\n",strerror(errno));
616                 }
617         }
618         if(rlen<0){
619                 return;
620         }
621
622         if(rlen < sizeof(struct icmphdr)){ //check packet size
623                 dbgprintf(1, "Packet smaller than possible ICMPv4 packet!\n");
624                 free(rcv_addr.gen);
625                 return;
626         }
627
628         icmp4=(struct icmphdr*)rbuffer;
629         if(icmp4->type!=ICMP_DEST_UNREACH && icmp4->type!=ICMP_TIME_EXCEEDED){ //check icmp types
630                 dbgprintf(1, "Tossing ICMPv4 packet of type %i\n", icmp4->type);
631                 free(rcv_addr.gen);
632                 return;
633         }
634
635         /*Check packet size again*/
636         if(rlen<sizeof(struct icmphdr)+sizeof(struct iphdr)+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)){
637                 dbgprintf(1, "Tossing ICMPv4 packet that's too small to contain DCCP header!\n");
638                 free(rcv_addr.gen);
639                 return;
640         }
641
642         /*Decode IPv4 header*/
643         ip4hdr=(struct iphdr*)(rbuffer+sizeof(struct icmphdr));
644         if(memcmp(&parms.src_addr.ipv4->sin_addr,&ip4hdr->saddr,sizeof(parms.src_addr.ipv4->sin_addr))!=0){
645                 /*Source address doesn't match*/
646                 dbgprintf(1,"Tossing ICMPv4 packet because the embedded IPv4 source address isn't us\n");
647                 free(rcv_addr.gen);
648                 return;
649         }
650         if(memcmp(&parms.dest_addr.ipv4->sin_addr,&ip4hdr->daddr,sizeof(parms.dest_addr.ipv4->sin_addr))!=0){
651                 /*Destination address doesn't match*/
652                 dbgprintf(1,"Tossing ICMPv4 packet because the embedded IPv4 destination address isn't our target\n");
653                 free(rcv_addr.gen);
654                 return;
655         }
656         if(ip4hdr->protocol!=IPPROTO_DCCP){
657                 /*Not DCCP!*/
658                 dbgprintf(1,"Tossing ICMPv4 packet because the embedded packet isn't DCCP\n");
659                 free(rcv_addr.gen);
660                 return;
661         }
662
663         /*Decode DCCP header*/
664         dhdr=(struct dccp_hdr*)(rbuffer+sizeof(struct icmphdr)+ip4hdr->ihl*4);
665         if(dhdr->dccph_dport!=htons(parms.dest_port)){
666                 /*DCCP Destination Ports don't match*/
667                 dbgprintf(1,"Tossing ICMPv4 packet because the embedded packet doesn't have our DCCP destination port\n");
668                 free(rcv_addr.gen);
669                 return;
670         }
671         if(dhdr->dccph_sport!=htons(parms.src_port)){
672                 /*DCCP Source Ports don't match*/
673                 dbgprintf(1,"Tossing ICMPv4 packet because the embedded packet doesn't have our DCCP source port\n");
674                 free(rcv_addr.gen);
675                 return;
676         }
677         dhdre=(struct dccp_hdr_ext*)(rbuffer+sizeof(struct icmphdr)+ip4hdr->ihl*4+sizeof(struct dccp_hdr));
678
679         /*Log*/
680         if(icmp4->type==ICMP_DEST_UNREACH){
681                 type=DEST_UNREACHABLE;
682         }
683         if(icmp4->type==ICMP_TIME_EXCEEDED){
684                 type=TTL_EXPIRATION;
685         }
686         logResponse(&rcv_addr,ntohl(dhdre->dccph_seq_low),type);
687         free(rcv_addr.gen);
688         return;
689 }
690
691 void handleICMP6packet(int rcv_socket){
692         int rlen=1500;
693         unsigned char rbuffer[rlen];
694         ipaddr_ptr_t rcv_addr;
695         socklen_t rcv_addr_len;
696         struct icmp6_hdr *icmp6;
697         struct ip6_hdr* ip6hdr;
698         struct dccp_hdr *dhdr;
699         struct dccp_hdr_ext *dhdre;
700         int type;
701
702         /*Memory for socket address*/
703         rcv_addr_len=sizeof(struct sockaddr_storage);
704         rcv_addr.gen=malloc(rcv_addr_len);
705         if(rcv_addr.gen==NULL){
706                 dbgprintf(0,"Error: Can't Allocate Memory!\n");
707                 exit(1);
708         }
709
710         /*Receive Packet*/
711         if((rlen=recvfrom(rcv_socket, &rbuffer, 1000,0,rcv_addr.gen,&rcv_addr_len))<0){
712                 dbgprintf(0, "Error on receive from ICMPv6 socket (%s)\n",strerror(errno));
713         }
714
715         if(rlen < sizeof(struct icmp6_hdr)){ //check packet size
716                 dbgprintf(1, "Packet smaller than possible ICMPv6 packet!\n");
717                 free(rcv_addr.gen);
718                 return;
719         }
720
721         icmp6=(struct icmp6_hdr*)rbuffer;
722         if(icmp6->icmp6_type!=ICMP6_DST_UNREACH && icmp6->icmp6_type!=ICMP6_PACKET_TOO_BIG
723                         && icmp6->icmp6_type!=ICMP6_TIME_EXCEEDED && icmp6->icmp6_type!=ICMP6_PARAM_PROB){ //check icmp types
724                 dbgprintf(1, "Tossing ICMPv6 packet of type %i\n", icmp6->icmp6_type);
725                 free(rcv_addr.gen);
726                 return;
727         }
728
729         /*Check packet size again*/
730         if(rlen<sizeof(struct icmp6_hdr)+sizeof(struct ip6_hdr)+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)){
731                 dbgprintf(1, "Tossing ICMPv6 packet that's too small to contain DCCP header!\n");
732                 free(rcv_addr.gen);
733                 return;
734         }
735
736         /*Decode IPv6 header*/
737         ip6hdr=(struct ip6_hdr*)(rbuffer+sizeof(struct icmp6_hdr));
738         if(memcmp(&parms.src_addr.ipv6->sin6_addr,&ip6hdr->ip6_src,sizeof(parms.src_addr.ipv6->sin6_addr))!=0){
739                 dbgprintf(1,"Tossing ICMPv6 packet because the embedded IPv6 source address isn't us\n");
740                 /*Source address doesn't match*/
741                 free(rcv_addr.gen);
742                 return;
743         }
744         if(memcmp(&parms.dest_addr.ipv6->sin6_addr,&ip6hdr->ip6_dst,sizeof(parms.dest_addr.ipv6->sin6_addr))!=0){
745                 /*Destination address doesn't match*/
746                 dbgprintf(1,"Tossing ICMPv6 packet because the embedded IPv6 destination address isn't our target\n");
747                 free(rcv_addr.gen);
748                 return;
749         }
750         if(ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_nxt!=IPPROTO_DCCP){
751                 /*Not DCCP!*/
752                 dbgprintf(1,"Tossing ICMPv6 packet because the embedded packet isn't DCCP\n");
753                 free(rcv_addr.gen);
754                 return;
755         }
756
757         /*Decode DCCP header*/
758         dhdr=(struct dccp_hdr*)(rbuffer+sizeof(struct icmp6_hdr)+sizeof(struct ip6_hdr));
759         if(dhdr->dccph_dport!=htons(parms.dest_port)){
760                 /*DCCP Destination Ports don't match*/
761                 dbgprintf(1,"Tossing ICMPv6 packet because the embedded packet doesn't have our DCCP destination port\n");
762                 free(rcv_addr.gen);
763                 return;
764         }
765         if(dhdr->dccph_sport!=htons(parms.src_port)){
766                 /*DCCP Source Ports don't match*/
767                 dbgprintf(1,"Tossing ICMPv6 packet because the embedded packet doesn't have our DCCP source port\n");
768                 free(rcv_addr.gen);
769                 return;
770         }
771         dhdre=(struct dccp_hdr_ext*)(rbuffer+sizeof(struct icmp6_hdr)+sizeof(struct ip6_hdr)+sizeof(struct dccp_hdr));
772
773         /*Log*/
774         if(icmp6->icmp6_type==ICMP6_DST_UNREACH){
775                 type=DEST_UNREACHABLE;
776         }
777         if(icmp6->icmp6_type==ICMP6_PACKET_TOO_BIG){
778                 type=TOO_BIG;
779         }
780         if(icmp6->icmp6_type==ICMP6_TIME_EXCEEDED){
781                 type=TTL_EXPIRATION;
782         }
783         if(icmp6->icmp6_type==ICMP6_PARAM_PROB){
784                 type=PARAMETER_PROBLEM;
785         }
786         logResponse(&rcv_addr,ntohl(dhdre->dccph_seq_low),type);
787         free(rcv_addr.gen);
788         return;
789 }
790
791 void buildRequestPacket(unsigned char* buffer, int *len, int seq){
792         struct dccp_hdr *dhdr;
793         struct dccp_hdr_ext *dhdre;
794         struct dccp_hdr_request *dhdrr;
795         struct iphdr* ip4hdr;
796         struct ip6_hdr* ip6hdr;
797
798         int ip_hdr_len;
799         int dccp_hdr_len=sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_request);
800
801         if(*len < dccp_hdr_len+sizeof(struct ip6_hdr)){
802                 dbgprintf(0, "Error: Insufficient buffer space\n");
803                 exit(1);
804         }
805
806         memset(buffer, 0, *len);
807
808         /*IP header*/
809         ip4hdr=NULL;
810         if(parms.ip_type==AF_INET){
811                 ip_hdr_len=sizeof(struct iphdr);
812                 ip4hdr=(struct iphdr*)buffer;
813                 ip4hdr->check=htons(0);
814                 memcpy(&ip4hdr->daddr, &parms.dest_addr.ipv4->sin_addr, sizeof(parms.dest_addr.ipv4->sin_addr));
815                 ip4hdr->frag_off=htons(0);
816                 ip4hdr->id=htons(1);//first
817                 ip4hdr->ihl=5;
818                 ip4hdr->protocol=IPPROTO_DCCP;
819                 memcpy(&ip4hdr->saddr, &parms.src_addr.ipv4->sin_addr, sizeof(parms.src_addr.ipv4->sin_addr));
820                 ip4hdr->tos=0;
821                 ip4hdr->tot_len=htons(ip_hdr_len+dccp_hdr_len);
822                 ip4hdr->ttl=parms.ttl;
823                 ip4hdr->version=4;
824         }else{
825                 ip_hdr_len=sizeof(struct ip6_hdr);
826                 ip6hdr=(struct ip6_hdr*)buffer;
827                 memcpy(&ip6hdr->ip6_dst, &parms.dest_addr.ipv6->sin6_addr, sizeof(parms.dest_addr.ipv6->sin6_addr));
828                 memcpy(&ip6hdr->ip6_src, &parms.src_addr.ipv6->sin6_addr, sizeof(parms.src_addr.ipv6->sin6_addr));
829                 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_flow=htonl(6<<28); //version, traffic class, flow label
830                 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_hlim=parms.ttl;
831                 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_nxt=IPPROTO_DCCP;
832                 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_plen=htons(dccp_hdr_len);
833         }
834
835         /*DCCP header*/
836         dhdr=(struct dccp_hdr*)(buffer+ip_hdr_len);
837         dhdre=(struct dccp_hdr_ext*)(buffer+ip_hdr_len+sizeof(struct dccp_hdr));
838         dhdrr=(struct dccp_hdr_request*)(buffer+ip_hdr_len+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext));
839         dhdr->dccph_ccval=0;
840         dhdr->dccph_checksum=0;
841         dhdr->dccph_cscov=0;
842         dhdr->dccph_doff=dccp_hdr_len/4;
843         dhdr->dccph_dport=htons(parms.dest_port);
844         dhdr->dccph_reserved=0;
845         dhdr->dccph_sport=htons(parms.src_port);
846         dhdr->dccph_x=1;
847         dhdr->dccph_type=DCCP_PKT_REQUEST;
848         dhdr->dccph_seq2=htonl(0); //Reserved if using 48 bit sequence numbers
849         dhdr->dccph_seq=htonl(0);  //High 16bits of sequence number. Always make 0 for simplicity.
850         dhdre->dccph_seq_low=htonl(seq);
851         dhdrr->dccph_req_service= htonl(0x50455246);
852
853         /*Checksums*/
854         if(parms.ip_type==AF_INET){
855                 dhdr->dccph_checksum=ipv4_pseudohdr_chksum((buffer+ip_hdr_len), dccp_hdr_len,
856                                 (unsigned char*) &parms.dest_addr.ipv4->sin_addr,
857                                 (unsigned char*)&parms.src_addr.ipv4->sin_addr, IPPROTO_DCCP);
858                 ip4hdr->check=ipv4_chksum(buffer,ip_hdr_len);
859         }else{
860                 dhdr->dccph_checksum=ipv6_pseudohdr_chksum((buffer+ip_hdr_len), dccp_hdr_len,
861                                 (unsigned char*) &parms.dest_addr.ipv6->sin6_addr,
862                                 (unsigned char*)&parms.src_addr.ipv6->sin6_addr, IPPROTO_DCCP);
863         }
864         *len=ip_hdr_len+dccp_hdr_len;
865         return;
866 }
867
868 void updateRequestPacket(unsigned char* buffer, int *len, int seq){
869         struct dccp_hdr *dhdr;
870         struct dccp_hdr_ext *dhdre;
871         struct iphdr* ip4hdr;
872
873         int ip_hdr_len;
874         int dccp_hdr_len=sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_request);
875
876         /*IP header*/
877         ip4hdr=NULL;
878         if(parms.ip_type==AF_INET){
879                 ip_hdr_len=sizeof(struct iphdr);
880                 ip4hdr=(struct iphdr*)buffer;
881                 ip4hdr->check=htons(0);
882                 ip4hdr->id=htons(seq);
883         }else{
884                 ip_hdr_len=sizeof(struct ip6_hdr);
885         }
886
887         /*DCCP header*/
888         dhdr=(struct dccp_hdr*)(buffer+ip_hdr_len);
889         dhdre=(struct dccp_hdr_ext*)(buffer+ip_hdr_len+sizeof(struct dccp_hdr));
890         dhdr->dccph_checksum=0;
891         dhdre->dccph_seq_low=htonl(seq);
892
893         /*Checksums*/
894         if(parms.ip_type==AF_INET){
895                 dhdr->dccph_checksum=ipv4_pseudohdr_chksum((buffer+ip_hdr_len), dccp_hdr_len,
896                                 (unsigned char*) &parms.dest_addr.ipv4->sin_addr,
897                                 (unsigned char*)&parms.src_addr.ipv4->sin_addr, IPPROTO_DCCP);
898                 ip4hdr->check=ipv4_chksum(buffer,ip_hdr_len);
899         }else{
900                 dhdr->dccph_checksum=ipv6_pseudohdr_chksum((buffer+ip_hdr_len), dccp_hdr_len,
901                                 (unsigned char*) &parms.dest_addr.ipv6->sin6_addr,
902                                 (unsigned char*)&parms.src_addr.ipv6->sin6_addr, IPPROTO_DCCP);
903         }
904         *len=ip_hdr_len+dccp_hdr_len;
905         return;
906 }
907
908 void sendClose(int seq, u_int16_t ack_h, u_int32_t ack_l, int socket){
909         unsigned char buffer[1500];
910         struct dccp_hdr *dhdr;
911         struct dccp_hdr_ext *dhdre;
912         struct dccp_hdr_ack_bits *dhd_ack;
913         struct iphdr* ip4hdr;
914         struct ip6_hdr* ip6hdr;
915         int len;
916         int addrlen;
917
918         int ip_hdr_len;
919         int dccp_hdr_len=sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_ack_bits);
920
921         memset(buffer, 0, 1500);
922
923         /*IP header*/
924         ip4hdr=NULL;
925         if(parms.ip_type==AF_INET){
926                 ip_hdr_len=sizeof(struct iphdr);
927                 ip4hdr=(struct iphdr*)buffer;
928                 ip4hdr->check=htons(0);
929                 memcpy(&ip4hdr->daddr, &parms.dest_addr.ipv4->sin_addr, sizeof(parms.dest_addr.ipv4->sin_addr));
930                 ip4hdr->frag_off=htons(0);
931                 ip4hdr->id=htons(1);//first
932                 ip4hdr->ihl=5;
933                 ip4hdr->protocol=IPPROTO_DCCP;
934                 memcpy(&ip4hdr->saddr, &parms.src_addr.ipv4->sin_addr, sizeof(parms.src_addr.ipv4->sin_addr));
935                 ip4hdr->tos=0;
936                 ip4hdr->tot_len=htons(ip_hdr_len+dccp_hdr_len);
937                 ip4hdr->ttl=parms.ttl;
938                 ip4hdr->version=4;
939         }else{
940                 ip_hdr_len=sizeof(struct ip6_hdr);
941                 ip6hdr=(struct ip6_hdr*)buffer;
942                 memcpy(&ip6hdr->ip6_dst, &parms.dest_addr.ipv6->sin6_addr, sizeof(parms.dest_addr.ipv6->sin6_addr));
943                 memcpy(&ip6hdr->ip6_src, &parms.src_addr.ipv6->sin6_addr, sizeof(parms.src_addr.ipv6->sin6_addr));
944                 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_flow=htonl(6<<28); //version, traffic class, flow label
945                 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_hlim=parms.ttl;
946                 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_nxt=IPPROTO_DCCP;
947                 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_plen=htons(dccp_hdr_len);
948         }
949
950         /*DCCP header*/
951         dhdr=(struct dccp_hdr*)(buffer+ip_hdr_len);
952         dhdre=(struct dccp_hdr_ext*)(buffer+ip_hdr_len+sizeof(struct dccp_hdr));
953         dhd_ack=(struct dccp_hdr_ack_bits*)(buffer+ip_hdr_len+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext));
954         dhdr->dccph_ccval=0;
955         dhdr->dccph_checksum=0;
956         dhdr->dccph_cscov=0;
957         dhdr->dccph_doff=dccp_hdr_len/4;
958         dhdr->dccph_dport=htons(parms.dest_port);
959         dhdr->dccph_reserved=0;
960         dhdr->dccph_sport=htons(parms.src_port);
961         dhdr->dccph_x=1;
962         dhdr->dccph_type=DCCP_PKT_CLOSE;
963         dhdr->dccph_seq2=htonl(0); //Reserved if using 48 bit sequence numbers
964         dhdr->dccph_seq=htonl(0);  //High 16bits of sequence number. Always make 0 for simplicity.
965         dhdre->dccph_seq_low=htonl(seq+1);
966         dhd_ack->dccph_ack_nr_high=ack_h;
967         dhd_ack->dccph_ack_nr_low=ack_l;
968
969         /*Checksums*/
970         if(parms.ip_type==AF_INET){
971                 dhdr->dccph_checksum=ipv4_pseudohdr_chksum((buffer+ip_hdr_len), dccp_hdr_len,
972                                 (unsigned char*) &parms.dest_addr.ipv4->sin_addr,
973                                 (unsigned char*)&parms.src_addr.ipv4->sin_addr, IPPROTO_DCCP);
974                 ip4hdr->check=ipv4_chksum(buffer,ip_hdr_len);
975         }else{
976                 dhdr->dccph_checksum=ipv6_pseudohdr_chksum((buffer+ip_hdr_len), dccp_hdr_len,
977                                 (unsigned char*) &parms.dest_addr.ipv6->sin6_addr,
978                                 (unsigned char*)&parms.src_addr.ipv6->sin6_addr, IPPROTO_DCCP);
979         }
980         len=ip_hdr_len+dccp_hdr_len;
981
982         /*Send*/
983         if(parms.ip_type==AF_INET){
984                 addrlen=sizeof(struct sockaddr_in);
985         }else{
986                 addrlen=sizeof(struct sockaddr_in6);
987         }
988         if(sendto(socket, &buffer, len, MSG_DONTWAIT,(struct sockaddr*)parms.dest_addr.gen,addrlen)<0){
989                 if(errno!=EINTR){
990                         dbgprintf(0,"Error: sendto failed\n");
991                 }
992         }
993         return;
994 }
995
996 void sendReset(int seq, u_int16_t ack_h, u_int32_t ack_l, int socket){
997         unsigned char buffer[1500];
998         struct dccp_hdr *dhdr;
999         struct dccp_hdr_ext *dhdre;
1000         struct dccp_hdr_reset *dh_re;
1001         struct iphdr* ip4hdr;
1002         struct ip6_hdr* ip6hdr;
1003         int len;
1004         int addrlen;
1005
1006         int ip_hdr_len;
1007         int dccp_hdr_len=sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_reset);
1008
1009         memset(buffer, 0, 1500);
1010
1011         /*IP header*/
1012         ip4hdr=NULL;
1013         if(parms.ip_type==AF_INET){
1014                 ip_hdr_len=sizeof(struct iphdr);
1015                 ip4hdr=(struct iphdr*)buffer;
1016                 ip4hdr->check=htons(0);
1017                 memcpy(&ip4hdr->daddr, &parms.dest_addr.ipv4->sin_addr, sizeof(parms.dest_addr.ipv4->sin_addr));
1018                 ip4hdr->frag_off=htons(0);
1019                 ip4hdr->id=htons(1);//first
1020                 ip4hdr->ihl=5;
1021                 ip4hdr->protocol=IPPROTO_DCCP;
1022                 memcpy(&ip4hdr->saddr, &parms.src_addr.ipv4->sin_addr, sizeof(parms.src_addr.ipv4->sin_addr));
1023                 ip4hdr->tos=0;
1024                 ip4hdr->tot_len=htons(ip_hdr_len+dccp_hdr_len);
1025                 ip4hdr->ttl=parms.ttl;
1026                 ip4hdr->version=4;
1027         }else{
1028                 ip_hdr_len=sizeof(struct ip6_hdr);
1029                 ip6hdr=(struct ip6_hdr*)buffer;
1030                 memcpy(&ip6hdr->ip6_dst, &parms.dest_addr.ipv6->sin6_addr, sizeof(parms.dest_addr.ipv6->sin6_addr));
1031                 memcpy(&ip6hdr->ip6_src, &parms.src_addr.ipv6->sin6_addr, sizeof(parms.src_addr.ipv6->sin6_addr));
1032                 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_flow=htonl(6<<28); //version, traffic class, flow label
1033                 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_hlim=parms.ttl;
1034                 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_nxt=IPPROTO_DCCP;
1035                 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_plen=htons(dccp_hdr_len);
1036         }
1037
1038         /*DCCP header*/
1039         dhdr=(struct dccp_hdr*)(buffer+ip_hdr_len);
1040         dhdre=(struct dccp_hdr_ext*)(buffer+ip_hdr_len+sizeof(struct dccp_hdr));
1041         dh_re=(struct dccp_hdr_reset*)(buffer+ip_hdr_len+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext));
1042         dhdr->dccph_ccval=0;
1043         dhdr->dccph_checksum=0;
1044         dhdr->dccph_cscov=0;
1045         dhdr->dccph_doff=dccp_hdr_len/4;
1046         dhdr->dccph_dport=htons(parms.dest_port);
1047         dhdr->dccph_reserved=0;
1048         dhdr->dccph_sport=htons(parms.src_port);
1049         dhdr->dccph_x=1;
1050         dhdr->dccph_type=DCCP_PKT_RESET;
1051         dhdr->dccph_seq2=htonl(0); //Reserved if using 48 bit sequence numbers
1052         dhdr->dccph_seq=htonl(0);  //High 16bits of sequence number. Always make 0 for simplicity.
1053         dhdre->dccph_seq_low=htonl(seq+1);
1054         dh_re->dccph_reset_ack.dccph_ack_nr_high=ack_h;
1055         dh_re->dccph_reset_ack.dccph_ack_nr_low=ack_l;
1056         dh_re->dccph_reset_code=DCCP_RESET_CODE_CLOSED;
1057         dh_re->dccph_reset_data[0]=0;
1058         dh_re->dccph_reset_data[1]=0;
1059         dh_re->dccph_reset_data[2]=0;
1060
1061         /*Checksums*/
1062         if(parms.ip_type==AF_INET){
1063                 dhdr->dccph_checksum=ipv4_pseudohdr_chksum((buffer+ip_hdr_len), dccp_hdr_len,
1064                                 (unsigned char*) &parms.dest_addr.ipv4->sin_addr,
1065                                 (unsigned char*)&parms.src_addr.ipv4->sin_addr, IPPROTO_DCCP);
1066                 ip4hdr->check=ipv4_chksum(buffer,ip_hdr_len);
1067         }else{
1068                 dhdr->dccph_checksum=ipv6_pseudohdr_chksum((buffer+ip_hdr_len), dccp_hdr_len,
1069                                 (unsigned char*) &parms.dest_addr.ipv6->sin6_addr,
1070                                 (unsigned char*)&parms.src_addr.ipv6->sin6_addr, IPPROTO_DCCP);
1071         }
1072         len=ip_hdr_len+dccp_hdr_len;
1073
1074         /*Send*/
1075         if(parms.ip_type==AF_INET){
1076                 addrlen=sizeof(struct sockaddr_in);
1077         }else{
1078                 addrlen=sizeof(struct sockaddr_in6);
1079         }
1080         if(sendto(socket, &buffer, len, MSG_DONTWAIT,(struct sockaddr*)parms.dest_addr.gen,addrlen)<0){
1081                 if(errno!=EINTR){
1082                         dbgprintf(0,"Error: sendto failed\n");
1083                 }
1084         }
1085         return;
1086 }
1087
1088 int logPacket(int req_seq, int packet_seq){
1089         struct request *tmp;
1090
1091         /*Add new request to queue*/
1092         tmp=malloc(sizeof(struct request));
1093         if(tmp==NULL){
1094                 dbgprintf(0,"Error: Can't allocate Memory!\n");
1095                 exit(1);
1096         }
1097         tmp->next=NULL;
1098         tmp->prev=NULL;
1099         tmp->num_replies=0;
1100         tmp->num_errors=0;
1101         tmp->packet_seq=packet_seq;
1102         tmp->request_seq=req_seq;
1103         tmp->reply_type=UNKNOWN;
1104         gettimeofday(&tmp->sent,NULL);
1105
1106         if(queue.head==NULL){
1107                 queue.head=queue.tail=tmp;
1108         }else{
1109                 queue.head->prev=tmp;
1110                 tmp->next=queue.head;
1111                 queue.head=tmp;
1112         }
1113
1114         /*Update Statistics*/
1115         if(ping_stats.requests_sent==0){
1116                 gettimeofday(&ping_stats.start,NULL);
1117         }
1118         ping_stats.requests_sent++;
1119         return 0;
1120 }
1121
1122 int logResponse(ipaddr_ptr_t *src, int seq, int type){
1123         struct request *cur;
1124         double diff;
1125         char pbuf[1000];
1126
1127         if(queue.tail==NULL){
1128                 dbgprintf(1,"Response received but no requests sent!\n");
1129                 return -1;
1130         }
1131
1132         /*Locate request*/
1133         cur=queue.tail;
1134         while(cur!=NULL){
1135                 if(cur->packet_seq==seq){
1136                         gettimeofday(&cur->reply,NULL);
1137                         if(cur->num_replies>0){
1138                                 printf("Duplicate packet detected! (%i)\n",cur->request_seq);
1139                         }
1140                         if(type<DEST_UNREACHABLE && type!=UNKNOWN){
1141                                 cur->num_replies++;
1142                         }else{
1143                                 cur->num_errors++;
1144                         }
1145                         cur->reply_type=type;
1146                         break;
1147                 }
1148                 cur=cur->prev;
1149         }
1150
1151         if(cur==NULL){
1152                 dbgprintf(1,"Response received but no requests sent with sequence number %i!\n", seq);
1153                 return -1;
1154         }
1155
1156         diff=(cur->reply.tv_usec + 1000000*cur->reply.tv_sec) - (cur->sent.tv_usec + 1000000*cur->sent.tv_sec);
1157         diff=diff/1000.0;
1158
1159         /*Print Message*/
1160         if(type<DEST_UNREACHABLE && type!=UNKNOWN){
1161                 if(parms.ip_type==AF_INET){
1162                         printf( "Response from %s : seq=%i  time=%.1fms  status=%s\n",
1163                                         inet_ntop(parms.ip_type, (void*)&src->ipv4->sin_addr, pbuf, 1000),
1164                                         cur->request_seq, diff,response_label[type]);
1165                 }else{
1166                         printf("Response from %s : seq=%i  time=%.1fms  status=%s\n",
1167                                         inet_ntop(parms.ip_type, (void*)&src->ipv6->sin6_addr, pbuf, 1000),
1168                                         cur->request_seq, diff,response_label[type]);
1169                 }
1170         }else{
1171                 if(parms.ip_type==AF_INET){
1172                         printf("%s from %s : seq=%i\n",response_label[type],
1173                                         inet_ntop(parms.ip_type, (void*)&src->ipv4->sin_addr, pbuf, 1000),
1174                                         cur->request_seq);
1175                 }else{
1176                         printf("%s from %s : seq=%i\n",response_label[type],
1177                                         inet_ntop(parms.ip_type, (void*)&src->ipv6->sin6_addr, pbuf, 1000),
1178                                         cur->request_seq);
1179                 }
1180         }
1181
1182         /*Update statistics*/
1183         if(type<DEST_UNREACHABLE && type!=UNKNOWN){
1184                 /*Good Response*/
1185                 if(cur->num_replies==1){
1186                         ping_stats.rtt_avg=((ping_stats.replies_received*ping_stats.rtt_avg)+(diff))/(ping_stats.replies_received+1);
1187                         ping_stats.replies_received++;
1188                 }else{
1189                         ping_stats.errors++;
1190                 }
1191                 if(diff < ping_stats.rtt_min || ping_stats.rtt_min==0){
1192                         ping_stats.rtt_min=diff;
1193                 }
1194                 if(diff > ping_stats.rtt_max){
1195                         ping_stats.rtt_max=diff;
1196                 }
1197         }else{
1198                 /*Error*/
1199                 ping_stats.errors++;
1200         }
1201         gettimeofday(&ping_stats.stop,NULL);
1202         return 0;
1203 }
1204
1205 void clearQueue(){
1206         struct request *cur;
1207         struct request *tmp;
1208
1209         cur=queue.head;
1210         while(cur!=NULL){
1211                 tmp=cur;
1212                 cur=cur->next;
1213                 free(tmp);
1214         }
1215         queue.head=NULL;
1216         queue.tail=NULL;
1217         return;
1218 }
1219
1220 void sigHandler(){
1221         char pbuf[1000];
1222         int diff;
1223         double ploss;
1224
1225         /*Print Stats*/
1226         if(parms.ip_type==AF_INET){
1227                 printf("-----------%s PING STATISTICS-----------\n",
1228                                 inet_ntop(parms.ip_type, (void*)&parms.dest_addr.ipv4->sin_addr, pbuf, 1000));
1229         }else if(parms.ip_type==AF_INET6){
1230                 printf("-----------%s PING STATISTICS-----------\n",
1231                                 inet_ntop(parms.ip_type, (void*)&parms.dest_addr.ipv6->sin6_addr, pbuf, 1000));
1232         }
1233         diff=(ping_stats.stop.tv_usec + 1000000*ping_stats.stop.tv_sec) -
1234                         (ping_stats.start.tv_usec + 1000000*ping_stats.start.tv_sec);
1235         diff=diff/1000.0;
1236         ploss=(1.0*(ping_stats.requests_sent-ping_stats.replies_received)/ping_stats.requests_sent*1.0)*100;
1237         printf("%i packets transmitted, %i received, %i errors, %.2f%% loss, time %ims\n",
1238                         ping_stats.requests_sent,ping_stats.replies_received,ping_stats.errors,
1239                         ploss,diff);
1240         printf("rtt min/avg/max = %.1f/%.1f/%.1f ms\n",
1241                         ping_stats.rtt_min,ping_stats.rtt_avg,ping_stats.rtt_max);
1242
1243
1244         /*Exit Quickly*/
1245         parms.count=0;
1246 }
1247
1248 /*Usage information for program*/
1249 void usage()
1250 {
1251         dbgprintf(0, "dccpping: [-d] [-6|-4] [-c count] [-p port] [-i interval] [-t ttl] [-S srcaddress] remote_host\n");
1252         exit(0);
1253 }
1254
1255 /*Program will probably be run setuid, so be extra careful*/
1256 void sanitize_environment()
1257 {
1258 #if defined(_SVID_SOURCE) || defined(_XOPEN_SOURCE)
1259         clearenv();
1260 #else
1261         extern char **environ;
1262         environ = NULL;
1263 #endif
1264 }
1265
1266 /*Debug Printf*/
1267 void dbgprintf(int level, const char *fmt, ...)
1268 {
1269     va_list args;
1270     if(debug>=level){
1271         va_start(args, fmt);
1272         vfprintf(stderr, fmt, args);
1273         va_end(args);
1274     }
1275 }