]> sjero.net Git - dccp2tcp/blob - dccp2tcp.c
Add GNU GPL headers to all files
[dccp2tcp] / dccp2tcp.c
1 /******************************************************************************
2 Utility to convert a DCCP flow to a TCP flow for DCCP analysis via
3                 tcptrace.
4
5 Copyright (C) 2012  Samuel Jero <sj323707@ohio.edu>
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20 Author: Samuel Jero <sj323707@ohio.edu>
21 Date: 11/2012
22
23 Notes:
24         1)CCID2 ONLY
25         2)DCCP MUST use 48 bit sequence numbers
26         3)Checksums are not computed (they are zeroed)
27         4)DCCP DATA packets are not implemented (Linux doesn't use them)
28         5)DCCP Ack packets show up as TCP packets containing one byte
29 ******************************************************************************/
30 #include "dccp2tcp.h"
31
32
33 int debug=0;    /*set to 1 to turn on debugging information*/
34 int yellow=0;   /*tcptrace yellow line as currently acked packet*/
35 int green=0;    /*tcptrace green line as currently acked packet*/
36 int sack=0;             /*add TCP SACKS*/
37
38 pcap_t*                 in;                     /*libpcap input file discriptor*/
39 pcap_dumper_t   *out;           /*libpcap output file discriptor*/
40 struct connection *chead;       /*connection list*/
41
42
43
44 void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes);
45 int convert_packet(struct packet *new, const struct const_packet* old);
46 unsigned int interp_ack_vect(u_char* hdr);
47 u_int32_t initialize_seq(struct host *seq, __be32 initial);
48 u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type);
49 u_int32_t convert_ack(struct host *seq, __be32 num);
50 int acked_packet_size(struct host *seq, __be32 num);
51 void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack);
52
53
54 /*Parse commandline options and open files*/
55 int main(int argc, char *argv[])
56 {
57         char ebuf[200];
58         char *erbuffer=ebuf;
59         char *dfile=NULL;
60         char *tfile=NULL;
61
62         /*parse commandline options*/
63         if(argc<3 || argc > 9){
64                 dbgprintf(0, "Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
65                 exit(1);
66         }
67
68         /*loop through commandline options*/
69         for(int i=1; i < argc; i++){
70                 if(argv[i][0]!='-' || (argv[i][0]=='-' && strlen(argv[i])==1)){
71                         if(dfile==NULL  || argv[i][0]=='-'){
72                                 /*assign first non-dash (or only dash) argument to the dccp file*/
73                                 dfile=argv[i];
74                         }else{
75                                 if(tfile==NULL){
76                                         tfile=argv[i]; /*assign second non-dash argument to the dccp file*/
77                                 }else{
78                                         dbgprintf(0,"Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
79                                         exit(1);
80                                 }
81                         }
82                 }else{
83                         if(argv[i][1]=='d' && strlen(argv[i])==2){ /*debug option*/
84                                 debug++;
85                         }
86                         if(argv[i][1]=='y' && strlen(argv[i])==2){ /*yellow option*/
87                                 yellow=1;
88                         }
89                         if(argv[i][1]=='g' && strlen(argv[i])==2){ /*green option*/
90                                 green=1;
91                         }
92                         if(argv[i][1]=='s' && strlen(argv[i])==2){ /*sack option*/
93                                 sack++;
94                         }
95                 }
96         }
97         
98         if(dfile==NULL || tfile==NULL){
99                 dbgprintf(0,"Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
100                 exit(1);
101         }
102
103         /*all options validated*/
104
105         if(debug){
106                 dbgprintf(1,"Debug On\n");
107                 if(green){
108                         dbgprintf(1,"Tcptrace green line at highest acknowledgment\n");
109                 }else{
110                         dbgprintf(1,"Tcptrace green line at highest acknowledged acknowledgment\n");
111                 }
112                 if(yellow){
113                         dbgprintf(1,"Tcptrace yellow line at highest acknowledgment\n");
114                 }else{
115                         dbgprintf(1,"Tcptrace yellow line window value (a made up number)\n");
116                 }
117                 if(sack){
118                         dbgprintf(1,"Adding TCP SACKS\n");
119                 }
120                 dbgprintf(1,"Input file: %s\n", dfile);
121                 dbgprintf(1,"Output file: %s\n", tfile);
122         }
123
124         /*attempt to open input file*/
125         in=pcap_open_offline(dfile, erbuffer);
126         if(in==NULL){
127                 dbgprintf(0,"Error opening input file\n");
128                 exit(1);
129         }
130
131         /*attempt to open output file*/
132         out=pcap_dump_open(in,tfile);
133         if(out==NULL){
134                 dbgprintf(0,"Error opening output file\n");
135                 exit(1);
136         }
137
138         /*process packets*/
139         chead=NULL;
140         u_char *user=(u_char*)out;
141         pcap_loop(in, -1, handle_packet, user); 
142         
143         /*close files*/
144         pcap_close(in);
145         pcap_dump_close(out);
146
147         /*Delete all connections*/
148         cleanup_connections();
149 return 0;
150 }
151
152
153 /*call back function for pcap_loop--do basic packet handling*/
154 void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
155 {
156         u_char                          *ndata;
157         struct pcap_pkthdr      nh;
158         int                                     link_type;
159         struct packet           new;
160         struct const_packet     old;
161
162         /*Determine the link type for this packet*/
163         link_type=pcap_datalink(in);
164
165         /*create new libpcap header*/
166         memcpy(&nh, h, sizeof(struct pcap_pkthdr));
167
168         /*Setup packet structs*/
169         old.h=h;
170         old.length=h->caplen;
171         old.data=bytes;
172         old.dest_id=NULL;
173         old.src_id=NULL;
174         new.h=&nh;
175         new.length=MAX_PACKET;
176         new.dest_id=NULL;
177         new.src_id=NULL;
178
179         /*create buffer for new packet*/
180         new.data=ndata=malloc(MAX_PACKET);
181         if(ndata==NULL){
182                 dbgprintf(0,"Error: Couldn't allocate Memory\n");
183                 exit(1);
184         }
185
186         /*make sure the packet is all zero*/
187         memset(new.data, 0, MAX_PACKET);
188         
189         /*do all the fancy conversions*/
190         if(!do_encap(link_type, &new, &old)){
191                 free(ndata);
192                 return;
193         }
194
195         /*save packet*/
196         pcap_dump(user,&nh, ndata);
197
198         free(ndata);
199 return;
200 }
201
202
203 /*do all the dccp to tcp conversions*/
204 int convert_packet(struct packet *new, const struct const_packet* old)
205 {       
206         struct tcphdr                           *tcph;
207         struct dccp_hdr                         *dccph;
208         struct dccp_hdr_ext             *dccphex;
209         struct dccp_hdr_ack_bits        *dccphack;
210         struct host                                     *h1=NULL;
211         struct host                                     *h2=NULL;
212         int                                             datalength;
213         int                                                     len=0;
214         const u_char*                           pd;
215         u_char*                                         npd;
216         u_char*                                         tcpopt;
217
218         /*Safety checks*/
219         if(!new || !old || !new->data || !old->data || !new->h || !old->h){
220                 dbgprintf(0,"Error:  Convert Packet Function given bad data!\n");
221                 exit(1);
222                 return 0;
223         }
224         if(old->length < (sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)) || new->length < sizeof(struct dccp_hdr)){
225                 dbgprintf(0, "Error: DCCP Packet Too short!\n");
226                 return 0;
227         }
228
229         /*cast header pointers*/
230         tcph=(struct tcphdr*)new->data;
231         dccph=(struct dccp_hdr*)old->data;
232         dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
233         dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
234
235         dbgprintf(2,"Sequence Number: %llu\n", (unsigned long long)
236                         (((unsigned long)ntohs(dccph->dccph_seq)<<32) + ntohl(dccphex->dccph_seq_low)));
237
238         /*Get Hosts*/
239         if(get_host(new->src_id, new->dest_id, new->id_len,
240                         dccph->dccph_sport, dccph->dccph_dport, &h1, &h2)){
241                 dbgprintf(0,"Error: Can't Get Hosts!\n");
242                 return 0;
243         }
244         if(h1==NULL || h2==NULL){
245                 dbgprintf(0, "Error: Can't Get Hosts!\n");
246                 return 0;
247         }
248
249         /*Ensure packet is at least as large as DCCP header*/
250         if(old->length < dccph->dccph_doff*4){
251                 dbgprintf(0, "Error: DCCP Header truncated\n");
252                 return 0;
253         }
254         if(dccph->dccph_type!=DCCP_PKT_DATA &&
255                         old->length < (sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) +
256                         sizeof(struct dccp_hdr_ack_bits))){
257                 dbgprintf(0, "Error: DCCP Packet Too short!\n");
258         }
259
260         /*determine data length*/
261         datalength=old->length - dccph->dccph_doff*4;
262         pd=old->data + dccph->dccph_doff*4;
263
264         /*set TCP standard features*/
265         tcph->source=dccph->dccph_sport;
266         tcph->dest=dccph->dccph_dport;
267         tcph->doff=5;
268         tcph->check=htonl(0);
269         tcph->urg_ptr=0;
270
271         /*Adjust TCP advertised window size*/
272         if(!yellow){
273                 tcph->window=htons(30000);
274         }
275
276         /*make changes by packet type*/
277         if(dccph->dccph_type==DCCP_PKT_REQUEST){//DCCP REQUEST -->TCP SYN
278                 dbgprintf(2,"Packet Type: Request\n");
279                 if(h1->state==INIT){
280                         if(yellow){
281                                 tcph->window=htons(0);
282                         }
283                         tcph->ack_seq=htonl(0);
284                         tcph->seq=htonl(initialize_seq(h1, ntohl(dccphex->dccph_seq_low)));
285                         tcph->syn=1;
286                         tcph->ack=0;
287                         tcph->fin=0;
288                         tcph->rst=0;
289
290                         /* add Sack-permitted option, if relevant*/
291                         if(sack){
292                                 tcpopt=(u_char*)(new->data + tcph->doff*4);
293                                 *tcpopt=4;
294                                 tcpopt++;
295                                 *tcpopt=2;
296                                 tcph->doff++;
297                         }
298
299                         /*calculate length*/
300                         len=tcph->doff*4;
301                 }
302         }
303
304         if(dccph->dccph_type==DCCP_PKT_RESPONSE){//DCCP RESPONSE-->TCP SYN,ACK
305                 dbgprintf(2,"Packet Type: Response\n");
306                 if(h2->state==OPEN && h1->state==INIT){
307                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
308                         if(yellow){
309                                 tcph->window=htons(0);
310                         }
311                         tcph->seq=htonl(initialize_seq(h1, ntohl(dccphex->dccph_seq_low)));
312                         tcph->syn=1;
313                         tcph->ack=1;
314                         tcph->fin=0;
315                         tcph->rst=0;
316
317                         /* add Sack-permitted option, if relevant*/
318                         if(sack){
319                                 tcpopt=(u_char*)(new->data + tcph->doff*4);
320                                 *tcpopt=4;
321                                 *(tcpopt+1)=2;
322                                 tcph->doff++;
323                         }
324
325                         /*calculate length*/
326                         len=tcph->doff*4;
327                 }
328         }
329
330         if(dccph->dccph_type==DCCP_PKT_DATA){//DCCP DATA----Never seen in packet capture
331                 dbgprintf(0,"DCCP Data packet not yet implemented\n");
332                 exit(1);
333         }
334
335         if(dccph->dccph_type==DCCP_PKT_DATAACK){//DCCP DATAACK-->TCP ACK with data
336                 dbgprintf(2,"Packet Type: DataAck\n");
337                 if(green){
338                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
339                 }else{
340                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
341                 }
342                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
343                 if(yellow){
344                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
345                 }
346                 if(sack){
347                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
348                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
349                         }
350                 }
351
352                 tcph->syn=0;
353                 tcph->ack=1;
354                 tcph->fin=0;
355                 tcph->rst=0;
356
357                 /*copy data*/
358                 npd=new->data + tcph->doff*4;
359                 memcpy(npd, pd, datalength);
360
361                 /*calculate length*/
362                 len= tcph->doff*4 + datalength;
363         }
364
365         if(dccph->dccph_type==DCCP_PKT_ACK){ //DCCP ACK -->TCP ACK with no data
366                 dbgprintf(2,"Packet Type: Ack\n");
367                 if(green){
368                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
369                 }else{
370                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
371                 }
372                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
373                 if(yellow){
374                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*1400);
375                         if(-interp_ack_vect((u_char*)dccph)*1400 > 65535){
376                                 printf("Note: TCP Window Overflow @ %d.%d\n", (int)old->h->ts.tv_sec, (int)old->h->ts.tv_usec);
377                         }
378                 }
379                 if(sack){
380                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
381                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
382                         }
383                 }
384
385                 tcph->syn=0;
386                 tcph->ack=1;
387                 tcph->fin=0;
388                 tcph->rst=0;
389
390                 /*calculate length*/
391                 len=tcph->doff*4 + 1;
392         }
393
394         if(dccph->dccph_type==DCCP_PKT_CLOSEREQ){//DCCP CLOSEREQ----Never seen in packet capture
395                 dbgprintf(0,"DCCP CloseReq not yet implemented\n");
396                 exit(1);
397         }
398
399         if(dccph->dccph_type==DCCP_PKT_CLOSE){//DCCP CLOSE-->TCP FIN,ACK
400                 dbgprintf(2,"Packet Type: Close\n");
401                 update_state(h1,CLOSE);
402                 if(green){
403                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
404                 }else{
405                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
406                 }
407                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
408                 if(yellow){
409                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
410                 }
411                 if(sack){
412                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
413                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
414                         }
415                 }
416
417                 tcph->syn=0;
418                 tcph->ack=1;
419                 tcph->fin=1;
420                 tcph->rst=0;
421
422                 /*calculate length*/
423                 len=tcph->doff*4;
424         }
425
426         if(dccph->dccph_type==DCCP_PKT_RESET){//DCCP RESET-->TCP FIN,ACK (only seen at end of connection as CLOSE ACK)
427                 if(h2->state==CLOSE){
428                         update_state(h1,CLOSE);
429                 }
430                 dbgprintf(2,"Packet Type: Reset\n");
431                 if(green){
432                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
433                 }else{
434                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
435                 }
436                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
437                 if(yellow){
438                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
439                 }
440                 if(sack){
441                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
442                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
443                         }
444                 }
445
446                 tcph->syn=0;
447                 tcph->ack=1;
448                 tcph->fin=1;
449                 tcph->rst=0;
450
451                 /*calculate length*/
452                 len=tcph->doff*4;
453         }
454
455         if(dccph->dccph_type==DCCP_PKT_SYNC){//DCCP SYNC
456                 dbgprintf(2,"Packet Type: Sync\n");
457                 if(green){
458                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
459                 }else{
460                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
461                 }
462                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
463                 if(yellow){
464                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
465                 }else{
466                         tcph->window=htons(0);
467                 }
468                 if(sack){
469                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
470                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
471                         }
472                 }
473
474                 tcph->syn=0;
475                 tcph->ack=1;
476                 tcph->fin=0;
477                 tcph->rst=0;
478
479                 /*calculate length*/
480                 len=tcph->doff*4;
481         }
482
483         if(dccph->dccph_type==DCCP_PKT_SYNCACK){//DCCP SYNACK
484                 dbgprintf(2,"Packet Type: SyncAck\n");
485                 if(green){
486                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
487                 }else{
488                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
489                 }
490                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
491                 if(yellow){
492                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
493                 }else{
494                         tcph->window=htons(0);
495                 }
496                 if(sack){
497                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
498                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low));
499                         }
500                 }
501
502                 tcph->syn=0;
503                 tcph->ack=1;
504                 tcph->fin=0;
505                 tcph->rst=0;
506
507                 /*calculate length*/
508                 len=tcph->doff*4;
509         }
510
511         if(dccph->dccph_type==DCCP_PKT_INVALID){//DCCP INVALID----Never seen in packet capture
512                 dbgprintf(0,"Invalid DCCP Packet!!\n");
513                 return 0;
514         }
515
516         new->length=len;
517 return 1;
518 }
519
520
521 /*Parse Ack Vector Options
522  * Returns the Number of packets since last recorded loss*/
523 unsigned int interp_ack_vect(u_char* hdr)
524 {
525         int hdrlen=((struct dccp_hdr*)hdr)->dccph_doff*4;
526         //struct dccp_hdr_ext* e=(struct dccp_hdr_ext*)hdr + sizeof(struct dccp_hdr);
527         int optlen;
528         int len;
529         int tmp;
530         int bp=0;
531         int additional=0;
532         u_char* opt;
533         u_char* cur;
534
535         /*setup pointer to DCCP options and determine how long the options are*/
536         optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
537         opt=hdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
538
539         /*parse options*/
540         while(optlen > 0){
541
542                 /*One byte options (no length)*/
543                 if(*opt< 32){
544                         optlen--;
545                         opt++;
546                         continue;
547                 }
548
549                 /*Check option length*/
550                 len=*(opt+1);
551                 if(len > optlen){
552                         dbgprintf(0, "Warning: Option would extend into packet data\n");
553                         return additional;
554                 }
555
556                 /*Ack Vector Option*/
557                 if(*opt==38 || *opt==39){
558                         tmp=len-2;
559                         cur=opt+2;
560                         /*loop through Vector*/
561                         while(tmp > 0){
562                                 /*ack vector works BACKWARDS through time*/
563
564                                 /*keep track of total packets recieved and if
565                                 a packet is lost, subtract all packets received
566                                 after that*/
567                                 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
568                                         bp+=(*cur & 0x3F)+1;
569                                         additional= -bp;
570                                 }
571                                         
572                                 if((*cur & 0xC0)==0x00){ //received packet
573                                         bp+= (*cur & 0x3F)+1;
574                                 }
575
576                                 if(((*cur& 0xC0)!= 0xC0) && ((*cur& 0xC0)!= 0x00) && ((*cur& 0xC0)!= 0x40)){
577                                         dbgprintf(1, "Warning: Invalid Ack Vector!! (Linux will handle poorly!)\n");
578                                 }
579                                 tmp--;
580                                 cur++;
581                         }
582                 }
583                 
584                 optlen-=len;
585                 opt+=len;
586         }
587
588         dbgprintf(2,"Ack vector adding: %i\n", additional);
589 return additional;
590 }
591
592
593 /* Setup Sequence Number Structure*/
594 u_int32_t initialize_seq(struct host *seq, __be32 initial)
595 {
596         /*set default values*/
597         seq->cur=0;
598         seq->size=TBL_SZ;
599         
600         /*allocate table*/
601         seq->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
602         if(seq->table==NULL){
603                 dbgprintf(0,"Can't Allocate Memory!\n");
604                 exit(1);
605         }
606
607         /*add first sequence number*/
608         seq->table[0].old=initial;
609         seq->table[0].new=initial;
610         seq->table[0].type=DCCP_PKT_REQUEST;
611         seq->table[0].size=0;
612         update_state(seq,OPEN);
613 return initial;
614 }
615
616
617 /*Convert Sequence Numbers*/
618 u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type)
619 {
620         int prev;
621         if(seq==NULL){
622                 dbgprintf(0,"ERROR NULL POINTER!\n");
623                 exit(1);
624         }
625         
626         if(seq->table==NULL){
627                 dbgprintf(1, "Warning: Connection uninitialized\n");
628                 return initialize_seq(seq, num);
629         }
630
631         /*account for missing packets*/
632         if(num - seq->table[seq->cur].old +1 >=100){
633                         dbgprintf(1,"Missing more than 100 packets!\n");
634         }
635         while(seq->table[seq->cur].old +1 < num && seq->table[seq->cur].old +1 > 0){
636                 prev=seq->cur;
637                 if(num - seq->table[seq->cur].old +1 <100){
638                         dbgprintf(1,"Missing Packet: %X\n",seq->table[prev].new+1);
639                 }
640                 seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
641                 seq->table[seq->cur].old=seq->table[prev].old+1;
642                 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
643                 seq->table[seq->cur].size=size;
644                 seq->table[seq->cur].type=type;
645         }
646
647         prev=seq->cur;
648         seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
649         seq->table[seq->cur].old=num;
650         seq->table[seq->cur].size=size;
651         seq->table[seq->cur].type=type;
652         if(seq->table[prev].type==DCCP_PKT_REQUEST || seq->table[prev].type==DCCP_PKT_RESPONSE){
653                 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
654                 seq->table[seq->cur].size=1;
655                 return seq->table[prev].new + seq->table[prev].size+1;
656         }
657         if(type==DCCP_PKT_DATA || type==DCCP_PKT_DATAACK || type==DCCP_PKT_ACK){
658                 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
659                 return seq->table[seq->cur].new+1;
660         }
661         if(type==DCCP_PKT_SYNC || type==DCCP_PKT_SYNCACK){
662                 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
663                 return seq->table[seq->cur].new;
664         }
665         seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
666 return seq->table[seq->cur].new +1;
667 }
668
669
670 /*Convert Ack Numbers*/
671 u_int32_t convert_ack(struct host *seq, __be32 num)
672 {
673         if(seq==NULL){
674                 dbgprintf(0,"ERROR NULL POINTER!\n");
675                 exit(1);
676         }
677
678         if(seq->table==NULL){
679                 dbgprintf(1, "Warning: Connection uninitialized\n");
680                 initialize_seq(seq, num);
681         }
682
683         /*loop through table looking for the DCCP ack number*/
684         for(int i=0; i < seq->size; i++){
685                 if(seq->table[i].old==num){
686                         return  seq->table[i].new + seq->table[i].size + 1; /*TCP acks the sequence number plus 1*/
687                 }
688         }
689         
690         dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
691 return 0;
692 }
693
694
695 /* Get size of packet being acked*/
696 int acked_packet_size(struct host *seq, __be32 num)
697 {
698         if(seq==NULL){
699                 dbgprintf(0,"ERROR NULL POINTER!\n");
700                 exit(1);
701         }
702
703         if(seq->table==NULL){
704                 dbgprintf(1, "Warning: Connection uninitialized\n");
705                 initialize_seq(seq, num);
706         }
707
708         /*loop through table looking for the DCCP ack number*/
709         for(int i=0; i < seq->size; i++){
710                 if(seq->table[i].old==num){
711                         return  seq->table[i].size;
712                 }
713         }
714         
715         dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
716 return 0;
717 }
718
719
720 /*Ack Vector to SACK Option*/
721 void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack)
722 {
723         int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
724         int optlen;
725         int len;
726         int tmp;
727         __be32 bp;
728         u_char* temp;
729         u_char* opt;
730         u_char* cur;
731         u_char* tlen;
732         u_int32_t bL=0;
733         u_int32_t bR;
734         u_int32_t* pL;
735         u_int32_t* pR;
736         int num_blocks;
737         int cont;
738         int isopt;
739         
740         /*setup pointer to DCCP options and determine how long the options are*/
741         optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
742         opt=dccphdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
743
744         /*setup tcp pointers*/
745         num_blocks=4;
746         *tcpopts=5;
747         tlen=tcpopts+1;
748         temp=tlen;
749         temp++;
750         pL=(u_int32_t*)temp;
751         pR=pL+1;
752
753         /*setup tcp control variables*/
754         bp=dccpack;
755         cont=0;
756         *tlen=2;
757         isopt=0;
758
759         /*parse options*/
760         while(optlen > 0){
761
762                 /*One byte options (no length)*/
763                 if(*opt< 32){
764                         optlen--;
765                         opt++;
766                         continue;
767                 }
768
769                 len=*(opt+1);
770                 if(len > optlen){
771                         dbgprintf(0, "Warning: Option would extend into packet data\n");
772                         break;
773                 }
774
775                 /*Ack Vector Option*/
776                 if(*opt==38 || *opt==39){
777                         tmp=len-2;
778                         cur=opt+2;
779                         /*loop through Vector*/
780                         while(tmp > 0){
781                                 /*ack vector works BACKWARDS through time*/
782
783                                 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
784                                         if(cont){ /*end a SACK run, if one is started*/
785                                                 bR=convert_ack(seq, bp);
786                                                 cont=0;
787                                                 num_blocks--;
788                                                 *pR=htonl(bR);
789                                                 *pL=htonl(bL);
790                                                 tcph->doff+=2;
791                                                 *tlen+=8;
792                                                 pL=pR+1;
793                                                 pR=pL+1;                        
794                                         }
795                                         bp= bp - (*cur & 0x3F)- 1;
796                                 }
797                                         
798                                 if((*cur & 0xC0)==0x00){ //received packet
799                                         if(!cont){ /*if no SACK run and we can start another one, do so*/
800                                                 if(num_blocks>0){
801                                                         bL=convert_ack(seq, bp);
802                                                         isopt=1;
803                                                         cont=1;
804
805                                                 }
806                                         }
807                                         bp =  bp -(*cur & 0x3F)- 1;
808                                 }
809                                 tmp--;
810                                 cur++;
811                         }
812                 }
813                 
814                 optlen-=len;
815                 opt+=len;
816         }
817
818         /*if we are in the middle of a SACK run, close it*/
819         if(cont){
820                 bR=convert_ack(seq, bp);
821                 *pR=htonl(bR);
822                 *pL=htonl(bL);
823                 tcph->doff+=2;
824                 *tlen+=8;
825                 cont=0;
826         }
827
828         /*adjust length if the option is actually added*/
829         if(isopt){
830                 tcph->doff+=1;
831         }
832 return;
833 }
834
835 /*Debug Printf*/
836 void dbgprintf(int level, const char *fmt, ...)
837 {
838     va_list args;
839     if(debug>=level){
840         va_start(args, fmt);
841         vfprintf(stderr, fmt, args);
842         va_end(args);
843     }
844 }