]> sjero.net Git - dccpping/blob - dccpping.c
Use select to wait for new packets and delay between pings. Separate out processing...
[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 <sys/types.h>
16 #include <sys/time.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>
25 #include <netdb.h>
26 #include <net/if.h>
27 #include <ifaddrs.h>
28 #include <linux/dccp.h>
29 #include "checksums.h"
30
31
32 #define MAX(x,y) (x>y ? x : y)
33 typedef union ipaddr{
34         struct sockaddr *gen;
35         struct sockaddr_in *ipv4;
36         struct sockaddr_in6 *ipv6;
37 } ipaddr_ptr_t;
38
39
40 int debug=0;                    /*set to 1 to turn on debugging information*/
41 int count=-1;                   /*Default number of pings (-1 is infinity)*/
42 int dest_port=33434;    /*Default port*/
43 int ttl=64;                             /*Default TTL*/
44 long interval=1000;             /*Default delay between pings in ms*/
45 int ip_type=AF_UNSPEC;  /*IPv4 or IPv6*/
46 ipaddr_ptr_t dest_addr;
47 ipaddr_ptr_t src_addr;
48 extern int errno;
49
50
51 void getAddresses(char *src, char* dst);
52 void doping();
53 void handleDCCPpacket(int rcv_socket, int send_socket);
54 void handleICMPpacket(int rcv_socket);
55 void buildRequestPacket(unsigned char* buffer, int *len);
56 void updateRequestPacket(unsigned char* buffer, int *len);
57 void dbgprintf(int level, const char *fmt, ...);
58 void sanitize_environment();
59 void usage();
60
61
62 /*Parse commandline options*/
63 int main(int argc, char *argv[])
64 {
65         char c;
66         char *src=NULL;
67         char *dst=NULL;
68
69
70         sanitize_environment();
71
72         while ((c = getopt(argc, argv, "64c:p:i:dt:S:")) != -1) {
73                 switch (c) {
74                         case '6':
75                                 ip_type=AF_INET6;
76                                 break;
77                         case '4':
78                                 ip_type=AF_INET;
79                                 break;
80                         case 'c':
81                                 count = atoi(optarg);
82                                 if(count<=0){
83                                         dbgprintf(0, "Error: count must be positive");
84                                         exit(1);
85                                 }
86                                 break;
87                         case 'p':
88                                 dest_port = atoi(optarg);
89                                 break;
90                         case 'i':
91                                 interval = (long)(atof(optarg) * 1000.0);
92                                 if (interval <= 0) {
93                                         fprintf(stderr, "Invalid interval\n");
94                                         exit(1);
95                                 }
96                                 break;
97                         case 'd':
98                                 debug++;
99                                 break;
100                         case 't':
101                                 ttl = atoi(optarg);
102                                 if (ttl < 1 || ttl > 255) {
103                                         fprintf(stderr, "Invalid TTL\n");
104                                 }
105                                 break;
106                         case 'S':
107                                 src=optarg;
108                                 break;
109                         default:
110                                 usage();
111                                 break;
112                 }
113         }
114
115         argc -= optind;
116         argv += optind;
117
118         if (argc != 1) {
119                 usage();
120         }
121         dst=argv[0];
122
123         getAddresses(src, dst);
124         if(src_addr.gen==NULL || dest_addr.gen==NULL){
125                 dbgprintf(0,"Error: Can't determine source or destination address\n");
126                 exit(1);
127         }
128
129         doping();
130
131         free(src_addr.gen);
132         free(dest_addr.gen);
133         return 0;
134 }
135
136 void getAddresses(char *src, char* dst){
137         struct addrinfo hint;
138         struct addrinfo *dtmp, *stmp;
139         struct ifaddrs *temp, *cur;
140         struct sockaddr_in6* iv6;
141         int addrlen;
142         int err;
143
144         /*Lookup destination Address*/
145         memset(&hint,0,sizeof(struct addrinfo));
146         hint.ai_family=ip_type;
147         hint.ai_flags=AI_V4MAPPED | AI_ADDRCONFIG;
148
149         if((err=getaddrinfo(dst,NULL,&hint,&dtmp))!=0){
150                 dbgprintf(0,"Error: Couldn't lookup destination %s (%s)\n", dst, gai_strerror(err));
151                 exit(1);
152         }
153         if(dtmp==NULL){
154                 dbgprintf(0,"Error: Unknown Host %s\n", dst);
155                 exit(1);
156         }else{
157                 addrlen=dtmp->ai_addrlen;
158                 hint.ai_family=ip_type=dtmp->ai_family;
159                 dest_addr.gen=malloc(dtmp->ai_addrlen);
160                 if(dest_addr.gen==NULL){
161                         dbgprintf(0,"Error: Can't allocate Memory\n");
162                         exit(1);
163                 }
164                 memcpy(dest_addr.gen,dtmp->ai_addr,dtmp->ai_addrlen);
165         }
166         freeaddrinfo(dtmp);
167
168         /*Get a meaningful source address*/
169         if(src!=NULL){
170                 /*Use Commandline arg*/
171                 if((err=getaddrinfo(src,NULL,&hint,&stmp))!=0){
172                         dbgprintf(0,"Error: Source Address %s is invalid (%s)\n", src, gai_strerror(err));
173                         exit(1);
174                 }
175                 if(stmp==NULL){
176                         dbgprintf(0,"Error: Unknown Host %s\n", dst);
177                         exit(1);
178                 }else{
179                         addrlen=stmp->ai_addrlen;
180                         src_addr.gen=malloc(stmp->ai_addrlen);
181                         if(src_addr.gen==NULL){
182                                 dbgprintf(0,"Error: Can't allocate Memory\n");
183                                 exit(1);
184                         }
185                         memcpy(src_addr.gen,stmp->ai_addr,stmp->ai_addrlen);
186                 }
187                 freeaddrinfo(stmp);
188         }else{
189                 /*Guess a good source address*/
190                 getifaddrs(&temp);
191                 cur=temp;
192                 while(cur!=NULL){
193                         if(cur->ifa_addr==NULL || cur->ifa_addr->sa_family!=ip_type){ /*Not matching ipv4/ipv6 of dest*/
194                                 cur=cur->ifa_next;
195                                 continue;
196                         }
197                         if(cur->ifa_flags & IFF_LOOPBACK){ /*Don't use loopback addresses*/
198                                 cur=cur->ifa_next;
199                                 continue;
200                         }
201                         if(cur->ifa_addr!=NULL && cur->ifa_addr->sa_family==AF_INET6){
202                                 iv6=(struct sockaddr_in6*)cur->ifa_addr;
203
204                                 if(iv6->sin6_scope_id!=0){ /*Not globally valid address, if ipv6*/
205                                         cur=cur->ifa_next;
206                                         continue;
207                                 }
208                         }
209
210                         src_addr.gen=malloc(sizeof(struct sockaddr_storage));
211                         if(src_addr.gen==NULL){
212                                 dbgprintf(0,"Error: Can't allocate Memory\n");
213                                 exit(1);
214                         }
215                         src_addr.gen->sa_family=ip_type;
216                         memcpy(src_addr.gen,cur->ifa_addr,addrlen);
217                         //break;
218                         cur=cur->ifa_next;
219                 }
220                 freeifaddrs(temp);
221         }
222         return;
223 }
224
225 /*Preform the ping functionality*/
226 void doping(){
227         int rs, is,ds;
228         int done=0;
229         int addrlen;
230         int slen=1500;
231         unsigned char sbuffer[slen];
232         fd_set sel;
233         struct timeval timeout;
234         struct timeval t,delay, add;
235         char pbuf[1000];
236
237         /*Open Sockets*/
238         rs=socket(ip_type, SOCK_RAW ,IPPROTO_RAW);
239         if(rs<0){
240                 dbgprintf(0, "Error opening raw socket\n");
241                 exit(1);
242         }
243         ds=socket(ip_type, SOCK_RAW ,IPPROTO_DCCP);
244         if(ds<0){
245                 dbgprintf(0, "Error opening raw DCCP socket\n");
246                 exit(1);
247         }
248         is=socket(ip_type,SOCK_RAW,IPPROTO_ICMP);
249         if(is<0){
250                 dbgprintf(0,"Error opening raw ICMP socket\n");
251                 exit(1);
252         }
253
254
255         /*Build DCCP packet*/
256         buildRequestPacket(sbuffer,&slen);
257         if(ip_type==AF_INET){
258                 addrlen=sizeof(struct sockaddr_in);
259         }else{
260                 addrlen=sizeof(struct sockaddr_in6);
261         }
262
263         while(!done){
264                 /*Send Ping*/
265                 if(sendto(rs, &sbuffer, slen, MSG_DONTWAIT,(struct sockaddr*)dest_addr.gen,addrlen)<0){
266                         dbgprintf(0,"Error: sendto failed\n");
267                 }
268                 if(ip_type==AF_INET){
269                         dbgprintf(0, "Sending DCCP Request to %s\n",inet_ntop(ip_type, (void*)&dest_addr.ipv4->sin_addr, pbuf, 1000));
270                 }else{
271                         dbgprintf(0, "Sending DCCP Request to %s\n",inet_ntop(ip_type, (void*)&dest_addr.ipv6->sin6_addr, pbuf, 1000));
272                 }
273
274                 /*Use select to wait on packets or until interval has passed*/
275                 add.tv_sec=interval/1000;
276                 add.tv_usec=(interval%1000)*1000;
277                 gettimeofday(&t,NULL);
278                 timeradd(&t,&add,&delay);
279                 FD_ZERO(&sel);
280                 FD_SET(ds,&sel);
281                 FD_SET(is,&sel);
282                 while(timercmp(&t,&delay,<)){
283                         timersub(&delay,&t,&timeout);
284                         if(select(MAX(ds+1,is+1),&sel, NULL,NULL,&timeout)<0){
285                                 dbgprintf(0,"Select() error\n");
286                         }
287
288                         if(FD_ISSET(ds,&sel)){
289                                 /*Data on the DCCP socket*/
290                                 handleDCCPpacket(ds,rs);
291
292                         }
293                         if(FD_ISSET(is,&sel)){
294                                 /*Data on the ICMP socket*/
295                                 handleICMPpacket(is);
296                         }
297                         gettimeofday(&t,NULL);
298                 }
299
300                 /*Update count*/
301                 if(count>-1){
302                         count--;
303                 }
304                 if(count==0){
305                         done=1;
306                         break;
307                 }
308
309                 updateRequestPacket(sbuffer,&slen);
310         }
311
312         close(rs);
313         close(is);
314         close(ds);
315 }
316
317 void handleDCCPpacket(int rcv_socket, int send_socket){
318         int rlen=1500;
319         unsigned char rbuffer[rlen];
320         char pbuf[1000];
321         ipaddr_ptr_t rcv_addr;
322         socklen_t rcv_addr_len;
323         struct dccp_hdr *dhdr;
324
325         /*Memory for socket address*/
326         rcv_addr_len=sizeof(struct sockaddr_storage);
327         rcv_addr.gen=malloc(rcv_addr_len);
328         if(rcv_addr.gen==NULL){
329                 dbgprintf(0,"Error: Can't Allocate Memory!\n");
330                 exit(1);
331         }
332
333         /*Receive Packet*/
334         rcv_addr_len=sizeof(struct sockaddr_storage);
335         if((rlen=recvfrom(rcv_socket, &rbuffer, 1000,0,rcv_addr.gen,&rcv_addr_len))<0){
336                         dbgprintf(0, "Error on receive from DCCP socket (%s)\n",strerror(errno));
337         }
338
339         if(rcv_addr.gen->sa_family!=ip_type){ //confirm IP type
340                 dbgprintf(1, "DCCP packet on %s. Tossing.\n", (ip_type==AF_INET) ? "IPv4" : "IPv6");
341                 free(rcv_addr.gen);
342                 return;
343         }
344
345         if(rlen < sizeof(struct dccp_hdr)){ //check packet size
346                 dbgprintf(1, "Packet smaller than possible DCCP packet received on DCCP socket\n");
347                 free(rcv_addr.gen);
348                 return;
349         }
350
351         /*Check IP source*/
352         if(rcv_addr.gen->sa_family==AF_INET){
353                 /*IPv4*/
354                 if(memcmp(&rcv_addr.ipv4->sin_addr,&dest_addr.ipv4->sin_addr,
355                                 sizeof(dest_addr.ipv4->sin_addr))!=0){ //not from destination
356                         dbgprintf(1,"DCCP packet from 3rd host\n");
357                         free(rcv_addr.gen);
358                         return;
359                 }
360         }else{
361                 /*IPv6*/
362                 if(memcmp(&rcv_addr.ipv6->sin6_addr, &dest_addr.ipv6->sin6_addr,
363                                 sizeof(dest_addr.ipv6->sin6_addr))!=0){ //not from destination
364                         dbgprintf(1,"DCCP packet from 3rd host\n");
365                         free(rcv_addr.gen);
366                         return;
367                 }
368         }
369
370         /*DCCP checks*/
371         dhdr=(struct dccp_hdr*)rbuffer;
372         if(dhdr->dccph_sport!=htons(dest_port)){
373                 dbgprintf(1,"DCCP packet with wrong Source Port\n");
374                 free(rcv_addr.gen);
375                 return;
376         }
377         if(dhdr->dccph_dport!=htons(dest_port)){
378                 dbgprintf(1,"DCCP packet with wrong Destination Port\n");
379                 free(rcv_addr.gen);
380                 return;
381         }
382
383         /*Print Message*/
384         if(dhdr->dccph_type==DCCP_PKT_RESET){
385                 /*Print Message*/
386                 if(ip_type==AF_INET){
387                         dbgprintf(0, "Got DCCP RESET from %s\n",inet_ntop(ip_type, (void*)&rcv_addr.ipv4->sin_addr, pbuf, 1000));
388                 }else{
389                         dbgprintf(0, "Got DCCP RESET from %s\n",inet_ntop(ip_type, (void*)&rcv_addr.ipv6->sin6_addr, pbuf, 1000));
390                 }
391                 /*Nothing else to do*/
392         }
393         if(dhdr->dccph_type==DCCP_PKT_RESPONSE){
394                 /*Print Message*/
395                 if(ip_type==AF_INET){
396                         dbgprintf(0, "Got DCCP RESPONSE from %s\n",inet_ntop(ip_type, (void*)&rcv_addr.ipv4->sin_addr, pbuf, 1000));
397                 }else{
398                         dbgprintf(0, "Got DCCP RESPONSE from %s\n",inet_ntop(ip_type, (void*)&rcv_addr.ipv6->sin6_addr, pbuf, 1000));
399                 }
400                 /*Send Close back*/
401         }
402         if(dhdr->dccph_type==DCCP_PKT_SYNC || dhdr->dccph_type==DCCP_PKT_SYNCACK){
403                 /*Print Message*/
404                 if(ip_type==AF_INET){
405                         dbgprintf(0, "Got DCCP SYNC from %s\n",inet_ntop(ip_type, (void*)&rcv_addr.ipv4->sin_addr, pbuf, 1000));
406                 }else{
407                         dbgprintf(0, "Got DCCP SYNC from %s\n",inet_ntop(ip_type, (void*)&rcv_addr.ipv6->sin6_addr, pbuf, 1000));
408                 }
409                 /*Send Reset*/
410         }
411
412         free(rcv_addr.gen);
413 }
414
415 void handleICMPpacket(int rcv_socket){
416         int rlen=1500;
417         unsigned char rbuffer[rlen];
418         char pbuf[1000];
419         ipaddr_ptr_t rcv_addr;
420         socklen_t rcv_addr_len;
421         struct icmphdr *icmp4;
422         struct icmp6_hdr *icmp6;
423
424         /*Memory for socket address*/
425         rcv_addr_len=sizeof(struct sockaddr_storage);
426         rcv_addr.gen=malloc(rcv_addr_len);
427         if(rcv_addr.gen==NULL){
428                 dbgprintf(0,"Error: Can't Allocate Memory!\n");
429                 exit(1);
430         }
431
432         /*Receive Packet*/
433         if((rlen=recvfrom(rcv_socket, &rbuffer, 1000,0,rcv_addr.gen,&rcv_addr_len))<0){
434                 dbgprintf(0, "Error on receive from ICMP socket (%s)\n",strerror(errno));
435         }
436
437         if(rcv_addr.gen->sa_family!=ip_type){ //confirm IP type
438                 dbgprintf(1, "ICMP packet on %s. Tossing.\n", (ip_type==AF_INET) ? "IPv4" : "IPv6");
439                 free(rcv_addr.gen);
440                 return;
441         }
442
443         if(rcv_addr.gen->sa_family==AF_INET){
444                 /*IPv4*/
445                 if(rlen < sizeof(struct icmphdr)){ //check packet size
446                         dbgprintf(1, "Packet smaller than possible ICMP packet!\n");
447                         free(rcv_addr.gen);
448                         return;
449                 }
450
451                 icmp4=(struct icmphdr*)rbuffer;
452                 if(icmp4->type!=3 && icmp4->type!=11){ //check icmp types
453                         dbgprintf(1, "Tossing ICMP packet of type %i\n", icmp4->type);
454                         free(rcv_addr.gen);
455                         return;
456                 }
457
458                 /*Print Message*/
459                 dbgprintf(0, "Got ICMPv4 type %i from %s\n", icmp4->type,
460                                 inet_ntop(ip_type, (void*)&rcv_addr.ipv4->sin_addr, pbuf, 1000));
461
462         }else{
463                 /*IPv6*/
464                 if(rlen < sizeof(struct icmp6_hdr)){ //check packet size
465                         dbgprintf(1, "Packet smaller than possible ICMP packet!\n");
466                         free(rcv_addr.gen);
467                         return;
468                 }
469
470                 icmp6=(struct icmp6_hdr*)rbuffer;
471                 if(icmp6->icmp6_type!=1 && icmp6->icmp6_type!=2 && icmp6->icmp6_type!=3
472                                 && icmp6->icmp6_type!=4){ //check icmp types
473                         dbgprintf(1, "Tossing ICMP packet of type %i\n", icmp6->icmp6_type);
474                         free(rcv_addr.gen);
475                         return;
476                 }
477
478                 /*Print Message*/
479                 dbgprintf(0, "Got ICMPv6 type %i from %s\n", icmp6->icmp6_type,
480                                 inet_ntop(ip_type, (void*)&rcv_addr.ipv6->sin6_addr, pbuf, 1000));
481         }
482
483         free(rcv_addr.gen);
484 }
485
486 void buildRequestPacket(unsigned char* buffer, int *len){
487         struct dccp_hdr *dhdr;
488         struct dccp_hdr_ext *dhdre;
489         struct dccp_hdr_request *dhdrr;
490         struct iphdr* ip4hdr;
491         struct ip6_hdr* ip6hdr;
492
493         int ip_hdr_len;
494         int dccp_hdr_len=sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_request);
495         int seq=8;
496
497         if(*len < dccp_hdr_len+sizeof(struct ip6_hdr)){
498                 dbgprintf(0, "Error: Insufficient buffer space\n");
499                 exit(1);
500         }
501
502         memset(buffer, 0, *len);
503
504         /*IP header*/
505         ip4hdr=NULL;
506         if(ip_type==AF_INET){
507                 ip_hdr_len=sizeof(struct iphdr);
508                 ip4hdr=(struct iphdr*)buffer;
509                 ip4hdr->check=htons(0);
510                 memcpy(&ip4hdr->daddr, &dest_addr.ipv4->sin_addr, sizeof(dest_addr.ipv4->sin_addr));
511                 ip4hdr->frag_off=htons(0);
512                 ip4hdr->id=htons(1);//first
513                 ip4hdr->ihl=5;
514                 ip4hdr->protocol=IPPROTO_DCCP;
515                 memcpy(&ip4hdr->saddr, &src_addr.ipv4->sin_addr, sizeof(src_addr.ipv4->sin_addr));
516                 ip4hdr->tos=0;
517                 ip4hdr->tot_len=htons(ip_hdr_len+dccp_hdr_len);
518                 ip4hdr->ttl=ttl;
519                 ip4hdr->version=4;
520         }else{
521                 ip_hdr_len=sizeof(struct ip6_hdr);
522                 ip6hdr=(struct ip6_hdr*)buffer;
523                 memcpy(&ip6hdr->ip6_dst, &dest_addr.ipv6->sin6_addr, sizeof(dest_addr.ipv6->sin6_addr));
524                 memcpy(&ip6hdr->ip6_src, &src_addr.ipv6->sin6_addr, sizeof(src_addr.ipv6->sin6_addr));
525                 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_flow=htonl(6<<28); //version, traffic class, flow label
526                 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_hlim=ttl;
527                 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_nxt=IPPROTO_DCCP;
528                 ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_plen=htons(dccp_hdr_len);
529         }
530
531         /*DCCP header*/
532         dhdr=(struct dccp_hdr*)(buffer+ip_hdr_len);
533         dhdre=(struct dccp_hdr_ext*)(buffer+ip_hdr_len+sizeof(struct dccp_hdr));
534         dhdrr=(struct dccp_hdr_request*)(buffer+ip_hdr_len+sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext));
535         dhdr->dccph_ccval=0;
536         dhdr->dccph_checksum=0;
537         dhdr->dccph_cscov=0;
538         dhdr->dccph_doff=dccp_hdr_len/4;
539         dhdr->dccph_dport=htons(dest_port);
540         dhdr->dccph_reserved=0;
541         dhdr->dccph_sport=htons(dest_port);
542         dhdr->dccph_x=1;
543         dhdr->dccph_type=DCCP_PKT_REQUEST;
544         dhdr->dccph_seq2=htonl(0); //Reserved if using 48 bit sequence numbers
545         dhdr->dccph_seq=htonl(0);  //High 16bits of sequence number. Always make 0 for simplicity.
546         dhdre->dccph_seq_low=htonl(seq);
547         dhdrr->dccph_req_service= htonl(0x50455246);
548
549         /*Checksums*/
550         if(ip_type==AF_INET){
551                 dhdr->dccph_checksum=ipv4_pseudohdr_chksum((buffer+ip_hdr_len), dccp_hdr_len,
552                                 (unsigned char*) &dest_addr.ipv4->sin_addr,
553                                 (unsigned char*)&src_addr.ipv4->sin_addr, IPPROTO_DCCP);
554                 ip4hdr->check=ipv4_chksum(buffer,ip_hdr_len);
555         }else{
556                 dhdr->dccph_checksum=ipv6_pseudohdr_chksum((buffer+ip_hdr_len), dccp_hdr_len,
557                                 (unsigned char*) &dest_addr.ipv6->sin6_addr,
558                                 (unsigned char*)&src_addr.ipv6->sin6_addr, IPPROTO_DCCP);
559         }
560         *len=ip_hdr_len+dccp_hdr_len;
561         return;
562 }
563
564 void updateRequestPacket(unsigned char* buffer, int *len){
565         struct dccp_hdr *dhdr;
566         struct dccp_hdr_ext *dhdre;
567         struct iphdr* ip4hdr;
568
569         int ip_hdr_len;
570         int dccp_hdr_len=sizeof(struct dccp_hdr)+sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_request);
571         int tmp;
572
573         /*IP header*/
574         ip4hdr=NULL;
575         if(ip_type==AF_INET){
576                 ip_hdr_len=sizeof(struct iphdr);
577                 ip4hdr=(struct iphdr*)buffer;
578                 ip4hdr->check=htons(0);
579                 tmp=ntohs(ip4hdr->id);
580                 ip4hdr->id=htons(tmp+1);
581         }else{
582                 ip_hdr_len=sizeof(struct ip6_hdr);
583         }
584
585         /*DCCP header*/
586         dhdr=(struct dccp_hdr*)(buffer+ip_hdr_len);
587         dhdre=(struct dccp_hdr_ext*)(buffer+ip_hdr_len+sizeof(struct dccp_hdr));
588         dhdr->dccph_checksum=0;
589         tmp=ntohl(dhdre->dccph_seq_low);
590         dhdre->dccph_seq_low=htonl(tmp+1);
591
592         /*Checksums*/
593         if(ip_type==AF_INET){
594                 dhdr->dccph_checksum=ipv4_pseudohdr_chksum((buffer+ip_hdr_len), dccp_hdr_len,
595                                 (unsigned char*) &dest_addr.ipv4->sin_addr,
596                                 (unsigned char*)&src_addr.ipv4->sin_addr, IPPROTO_DCCP);
597                 ip4hdr->check=ipv4_chksum(buffer,ip_hdr_len);
598         }else{
599                 dhdr->dccph_checksum=ipv6_pseudohdr_chksum((buffer+ip_hdr_len), dccp_hdr_len,
600                                 (unsigned char*) &dest_addr.ipv6->sin6_addr,
601                                 (unsigned char*)&src_addr.ipv6->sin6_addr, IPPROTO_DCCP);
602         }
603         *len=ip_hdr_len+dccp_hdr_len;
604         return;
605 }
606
607 /*Usage information for program*/
608 void usage()
609 {
610         dbgprintf(0, "dccpping: [-d] [-6|-4] [-c count] [-p port] [-i interval] [-t ttl] [-S srcaddress] remote_host\n");
611         exit(0);
612 }
613
614 /*Program will probably be run setuid, so be extra careful*/
615 void sanitize_environment()
616 {
617 #if defined(_SVID_SOURCE) || defined(_XOPEN_SOURCE)
618         clearenv();
619 #else
620         extern char **environ;
621         environ = NULL;
622 #endif
623 }
624
625 /*Debug Printf*/
626 void dbgprintf(int level, const char *fmt, ...)
627 {
628     va_list args;
629     if(debug>=level){
630         va_start(args, fmt);
631         vfprintf(stderr, fmt, args);
632         va_end(args);
633     }
634 }