]> sjero.net Git - dccp2tcp/blob - ccid2.c
Checksum computation!
[dccp2tcp] / ccid2.c
1 /******************************************************************************
2 Utility to convert a DCCP flow to a TCP flow for DCCP analysis via
3                 tcptrace.
4
5 Copyright (C) 2013  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: 02/2013
22
23 Notes:
24         1)CCID2 ONLY
25         2)DCCP MUST use 48 bit sequence numbers
26         3)DCCP DATA packets are not implemented (Linux doesn't use them)
27         4)DCCP Ack packets show up as TCP packets containing one byte
28 ******************************************************************************/
29 #include "dccp2tcp.h"
30
31 unsigned int interp_ack_vect(u_char* hdr);
32 u_int32_t initialize_seq(struct host *seq, __be32 initial);
33 u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type);
34 u_int32_t convert_ack(struct host *seq, __be32 num);
35 int acked_packet_size(struct host *seq, __be32 num);
36 void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack);
37
38 /*do all the dccp to tcp conversions*/
39 int ccid2_convert_packet(struct packet *new, const struct const_packet* old)
40 {
41         struct tcphdr                           *tcph;
42         struct dccp_hdr                         *dccph;
43         struct dccp_hdr_ext             *dccphex;
44         struct dccp_hdr_ack_bits        *dccphack;
45         struct host                                     *h1=NULL;
46         struct host                                     *h2=NULL;
47         int                                             datalength;
48         int                                                     len=0;
49         const u_char*                           pd;
50         u_char*                                         npd;
51         u_char*                                         tcpopt;
52
53         /*cast header pointers*/
54         tcph=(struct tcphdr*)new->data;
55         dccph=(struct dccp_hdr*)old->data;
56         dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
57         dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
58
59         /*Get Hosts*/
60         if(get_host(new->src_id, new->dest_id, new->id_len,
61                         dccph->dccph_sport, dccph->dccph_dport, &h1, &h2)){
62                 dbgprintf(0,"Error: Can't Get Hosts!\n");
63                 return 0;
64         }
65         if(h1==NULL || h2==NULL){
66                 dbgprintf(0, "Error: Can't Get Hosts!\n");
67                 return 0;
68         }
69
70         /*Ensure packet is at least as large as DCCP header*/
71         if(dccph->dccph_type!=DCCP_PKT_DATA &&
72                         old->length < (sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) +
73                         sizeof(struct dccp_hdr_ack_bits))){
74                 dbgprintf(0, "Error: DCCP Packet Too short!\n");
75         }
76
77         /*determine data length*/
78         datalength=old->length - dccph->dccph_doff*4;
79         pd=old->data + dccph->dccph_doff*4;
80
81         /*set TCP standard features*/
82         tcph->source=dccph->dccph_sport;
83         tcph->dest=dccph->dccph_dport;
84         tcph->doff=5;
85         tcph->check=htonl(0);
86         tcph->urg_ptr=0;
87
88         /*Adjust TCP advertised window size*/
89         if(!yellow){
90                 tcph->window=htons(30000);
91         }
92
93         /*make changes by packet type*/
94         if(dccph->dccph_type==DCCP_PKT_REQUEST){//DCCP REQUEST -->TCP SYN
95                 dbgprintf(2,"Packet Type: Request\n");
96                 if(h1->state==INIT){
97                         if(yellow){
98                                 tcph->window=htons(0);
99                         }
100                         tcph->ack_seq=htonl(0);
101                         tcph->seq=htonl(initialize_seq(h1, ntohl(dccphex->dccph_seq_low)));
102                         tcph->syn=1;
103                         tcph->ack=0;
104                         tcph->fin=0;
105                         tcph->rst=0;
106
107                         /* add Sack-permitted option, if relevant*/
108                         if(sack){
109                                 tcpopt=(u_char*)(new->data + tcph->doff*4);
110                                 *tcpopt=4;
111                                 tcpopt++;
112                                 *tcpopt=2;
113                                 tcph->doff++;
114                         }
115
116                         /*calculate length*/
117                         len=tcph->doff*4;
118                 }
119         }
120
121         if(dccph->dccph_type==DCCP_PKT_RESPONSE){//DCCP RESPONSE-->TCP SYN,ACK
122                 dbgprintf(2,"Packet Type: Response\n");
123                 if(h2->state==OPEN && h1->state==INIT){
124                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
125                         if(yellow){
126                                 tcph->window=htons(0);
127                         }
128                         tcph->seq=htonl(initialize_seq(h1, ntohl(dccphex->dccph_seq_low)));
129                         tcph->syn=1;
130                         tcph->ack=1;
131                         tcph->fin=0;
132                         tcph->rst=0;
133
134                         /* add Sack-permitted option, if relevant*/
135                         if(sack){
136                                 tcpopt=(u_char*)(new->data + tcph->doff*4);
137                                 *tcpopt=4;
138                                 *(tcpopt+1)=2;
139                                 tcph->doff++;
140                         }
141
142                         /*calculate length*/
143                         len=tcph->doff*4;
144                 }
145         }
146
147         if(dccph->dccph_type==DCCP_PKT_DATA){//DCCP DATA----Never seen in packet capture
148                 dbgprintf(0,"DCCP Data packet not yet implemented\n");
149                 exit(1);
150         }
151
152         if(dccph->dccph_type==DCCP_PKT_DATAACK){//DCCP DATAACK-->TCP ACK with data
153                 dbgprintf(2,"Packet Type: DataAck\n");
154                 if(green){
155                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
156                 }else{
157                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
158                 }
159                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
160                 if(yellow){
161                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
162                 }
163                 if(sack){
164                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
165                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
166                         }
167                 }
168
169                 tcph->syn=0;
170                 tcph->ack=1;
171                 tcph->fin=0;
172                 tcph->rst=0;
173
174                 /*copy data*/
175                 npd=new->data + tcph->doff*4;
176                 memcpy(npd, pd, datalength);
177
178                 /*calculate length*/
179                 len= tcph->doff*4 + datalength;
180         }
181
182         if(dccph->dccph_type==DCCP_PKT_ACK){ //DCCP ACK -->TCP ACK with no data
183                 dbgprintf(2,"Packet Type: Ack\n");
184                 if(green){
185                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
186                 }else{
187                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
188                 }
189                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
190                 if(yellow){
191                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*1400);
192                         if(-interp_ack_vect((u_char*)dccph)*1400 > 65535){
193                                 printf("Note: TCP Window Overflow @ %d.%d\n", (int)old->h->ts.tv_sec, (int)old->h->ts.tv_usec);
194                         }
195                 }
196                 if(sack){
197                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
198                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
199                         }
200                 }
201
202                 tcph->syn=0;
203                 tcph->ack=1;
204                 tcph->fin=0;
205                 tcph->rst=0;
206
207                 /*calculate length*/
208                 len=tcph->doff*4 + 1;
209         }
210
211         if(dccph->dccph_type==DCCP_PKT_CLOSEREQ){//DCCP CLOSEREQ----Never seen in packet capture
212                 dbgprintf(0,"DCCP CloseReq not yet implemented\n");
213                 exit(1);
214         }
215
216         if(dccph->dccph_type==DCCP_PKT_CLOSE){//DCCP CLOSE-->TCP FIN,ACK
217                 dbgprintf(2,"Packet Type: Close\n");
218                 update_state(h1,CLOSE);
219                 if(green){
220                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
221                 }else{
222                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
223                 }
224                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
225                 if(yellow){
226                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
227                 }
228                 if(sack){
229                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
230                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
231                         }
232                 }
233
234                 tcph->syn=0;
235                 tcph->ack=1;
236                 tcph->fin=1;
237                 tcph->rst=0;
238
239                 /*calculate length*/
240                 len=tcph->doff*4;
241         }
242
243         if(dccph->dccph_type==DCCP_PKT_RESET){//DCCP RESET-->TCP FIN,ACK (only seen at end of connection as CLOSE ACK)
244                 if(h2->state==CLOSE){
245                         update_state(h1,CLOSE);
246                 }
247                 dbgprintf(2,"Packet Type: Reset\n");
248                 if(green){
249                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
250                 }else{
251                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
252                 }
253                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
254                 if(yellow){
255                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
256                 }
257                 if(sack){
258                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
259                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
260                         }
261                 }
262
263                 tcph->syn=0;
264                 tcph->ack=1;
265                 tcph->fin=1;
266                 tcph->rst=0;
267
268                 /*calculate length*/
269                 len=tcph->doff*4;
270         }
271
272         if(dccph->dccph_type==DCCP_PKT_SYNC){//DCCP SYNC
273                 dbgprintf(2,"Packet Type: Sync\n");
274                 if(green){
275                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
276                 }else{
277                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
278                 }
279                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
280                 if(yellow){
281                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
282                 }else{
283                         tcph->window=htons(0);
284                 }
285                 if(sack){
286                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
287                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
288                         }
289                 }
290
291                 tcph->syn=0;
292                 tcph->ack=1;
293                 tcph->fin=0;
294                 tcph->rst=0;
295
296                 /*calculate length*/
297                 len=tcph->doff*4;
298         }
299
300         if(dccph->dccph_type==DCCP_PKT_SYNCACK){//DCCP SYNACK
301                 dbgprintf(2,"Packet Type: SyncAck\n");
302                 if(green){
303                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
304                 }else{
305                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
306                 }
307                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
308                 if(yellow){
309                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
310                 }else{
311                         tcph->window=htons(0);
312                 }
313                 if(sack){
314                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
315                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low));
316                         }
317                 }
318
319                 tcph->syn=0;
320                 tcph->ack=1;
321                 tcph->fin=0;
322                 tcph->rst=0;
323
324                 /*calculate length*/
325                 len=tcph->doff*4;
326         }
327
328         if(dccph->dccph_type==DCCP_PKT_INVALID){//DCCP INVALID----Never seen in packet capture
329                 dbgprintf(0,"Invalid DCCP Packet!!\n");
330                 return 0;
331         }
332
333         new->length=len;
334 return 1;
335 }
336
337
338 /*Parse Ack Vector Options
339  * Returns the Number of packets since last recorded loss*/
340 unsigned int interp_ack_vect(u_char* hdr)
341 {
342         int hdrlen=((struct dccp_hdr*)hdr)->dccph_doff*4;
343         //struct dccp_hdr_ext* e=(struct dccp_hdr_ext*)hdr + sizeof(struct dccp_hdr);
344         int optlen;
345         int len;
346         int tmp;
347         int bp=0;
348         int additional=0;
349         u_char* opt;
350         u_char* cur;
351
352         /*setup pointer to DCCP options and determine how long the options are*/
353         optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
354         opt=hdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
355
356         /*parse options*/
357         while(optlen > 0){
358
359                 /*One byte options (no length)*/
360                 if(*opt< 32){
361                         optlen--;
362                         opt++;
363                         continue;
364                 }
365
366                 /*Check option length*/
367                 len=*(opt+1);
368                 if(len > optlen){
369                         dbgprintf(0, "Warning: Option would extend into packet data\n");
370                         return additional;
371                 }
372
373                 /*Ack Vector Option*/
374                 if(*opt==38 || *opt==39){
375                         tmp=len-2;
376                         cur=opt+2;
377                         /*loop through Vector*/
378                         while(tmp > 0){
379                                 /*ack vector works BACKWARDS through time*/
380
381                                 /*keep track of total packets recieved and if
382                                 a packet is lost, subtract all packets received
383                                 after that*/
384                                 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
385                                         bp+=(*cur & 0x3F)+1;
386                                         additional= -bp;
387                                 }
388
389                                 if((*cur & 0xC0)==0x00){ //received packet
390                                         bp+= (*cur & 0x3F)+1;
391                                 }
392
393                                 if(((*cur& 0xC0)!= 0xC0) && ((*cur& 0xC0)!= 0x00) && ((*cur& 0xC0)!= 0x40)){
394                                         dbgprintf(1, "Warning: Invalid Ack Vector!! (Linux will handle poorly!)\n");
395                                 }
396                                 tmp--;
397                                 cur++;
398                         }
399                 }
400
401                 optlen-=len;
402                 opt+=len;
403         }
404
405         dbgprintf(2,"Ack vector adding: %i\n", additional);
406 return additional;
407 }
408
409
410 /* Setup Sequence Number Structure*/
411 u_int32_t initialize_seq(struct host *seq, __be32 initial)
412 {
413         /*set default values*/
414         seq->cur=0;
415         seq->size=TBL_SZ;
416
417         /*allocate table*/
418         seq->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
419         if(seq->table==NULL){
420                 dbgprintf(0,"Can't Allocate Memory!\n");
421                 exit(1);
422         }
423
424         /*add first sequence number*/
425         seq->table[0].old=initial;
426         seq->table[0].new=initial;
427         seq->table[0].type=DCCP_PKT_REQUEST;
428         seq->table[0].size=0;
429         update_state(seq,OPEN);
430 return initial;
431 }
432
433
434 /*Convert Sequence Numbers*/
435 u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type)
436 {
437         int prev;
438         if(seq==NULL){
439                 dbgprintf(0,"ERROR NULL POINTER!\n");
440                 exit(1);
441         }
442
443         if(seq->table==NULL){
444                 dbgprintf(1, "Warning: Connection uninitialized\n");
445                 return initialize_seq(seq, num);
446         }
447
448         /*account for missing packets*/
449         if(num - seq->table[seq->cur].old +1 >=100){
450                         dbgprintf(1,"Missing more than 100 packets!\n");
451         }
452         while(seq->table[seq->cur].old +1 < num && seq->table[seq->cur].old +1 > 0){
453                 prev=seq->cur;
454                 if(num - seq->table[seq->cur].old +1 <100){
455                         dbgprintf(1,"Missing Packet: %X\n",seq->table[prev].new+1);
456                 }
457                 seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
458                 seq->table[seq->cur].old=seq->table[prev].old+1;
459                 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
460                 seq->table[seq->cur].size=size;
461                 seq->table[seq->cur].type=type;
462         }
463
464         prev=seq->cur;
465         seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
466         seq->table[seq->cur].old=num;
467         seq->table[seq->cur].size=size;
468         seq->table[seq->cur].type=type;
469         if(seq->table[prev].type==DCCP_PKT_REQUEST || seq->table[prev].type==DCCP_PKT_RESPONSE){
470                 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
471                 seq->table[seq->cur].size=1;
472                 return seq->table[prev].new + seq->table[prev].size+1;
473         }
474         if(type==DCCP_PKT_DATA || type==DCCP_PKT_DATAACK || type==DCCP_PKT_ACK){
475                 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
476                 return seq->table[seq->cur].new+1;
477         }
478         if(type==DCCP_PKT_SYNC || type==DCCP_PKT_SYNCACK){
479                 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
480                 return seq->table[seq->cur].new;
481         }
482         seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
483 return seq->table[seq->cur].new +1;
484 }
485
486
487 /*Convert Ack Numbers*/
488 u_int32_t convert_ack(struct host *seq, __be32 num)
489 {
490         if(seq==NULL){
491                 dbgprintf(0,"ERROR NULL POINTER!\n");
492                 exit(1);
493         }
494
495         if(seq->table==NULL){
496                 dbgprintf(1, "Warning: Connection uninitialized\n");
497                 initialize_seq(seq, num);
498         }
499
500         /*loop through table looking for the DCCP ack number*/
501         for(int i=0; i < seq->size; i++){
502                 if(seq->table[i].old==num){
503                         return  seq->table[i].new + seq->table[i].size + 1; /*TCP acks the sequence number plus 1*/
504                 }
505         }
506
507         dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
508 return 0;
509 }
510
511
512 /* Get size of packet being acked*/
513 int acked_packet_size(struct host *seq, __be32 num)
514 {
515         if(seq==NULL){
516                 dbgprintf(0,"ERROR NULL POINTER!\n");
517                 exit(1);
518         }
519
520         if(seq->table==NULL){
521                 dbgprintf(1, "Warning: Connection uninitialized\n");
522                 initialize_seq(seq, num);
523         }
524
525         /*loop through table looking for the DCCP ack number*/
526         for(int i=0; i < seq->size; i++){
527                 if(seq->table[i].old==num){
528                         return  seq->table[i].size;
529                 }
530         }
531
532         dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
533 return 0;
534 }
535
536
537 /*Ack Vector to SACK Option*/
538 void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack)
539 {
540         int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
541         int optlen;
542         int len;
543         int tmp;
544         __be32 bp;
545         u_char* temp;
546         u_char* opt;
547         u_char* cur;
548         u_char* tlen;
549         u_int32_t bL=0;
550         u_int32_t bR;
551         u_int32_t* pL;
552         u_int32_t* pR;
553         int num_blocks;
554         int cont;
555         int isopt;
556
557         /*setup pointer to DCCP options and determine how long the options are*/
558         optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
559         opt=dccphdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
560
561         /*setup tcp pointers*/
562         num_blocks=4;
563         *tcpopts=5;
564         tlen=tcpopts+1;
565         temp=tlen;
566         temp++;
567         pL=(u_int32_t*)temp;
568         pR=pL+1;
569
570         /*setup tcp control variables*/
571         bp=dccpack;
572         cont=0;
573         *tlen=2;
574         isopt=0;
575
576         /*parse options*/
577         while(optlen > 0){
578
579                 /*One byte options (no length)*/
580                 if(*opt< 32){
581                         optlen--;
582                         opt++;
583                         continue;
584                 }
585
586                 len=*(opt+1);
587                 if(len > optlen){
588                         dbgprintf(0, "Warning: Option would extend into packet data\n");
589                         break;
590                 }
591
592                 /*Ack Vector Option*/
593                 if(*opt==38 || *opt==39){
594                         tmp=len-2;
595                         cur=opt+2;
596                         /*loop through Vector*/
597                         while(tmp > 0){
598                                 /*ack vector works BACKWARDS through time*/
599
600                                 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
601                                         if(cont){ /*end a SACK run, if one is started*/
602                                                 bR=convert_ack(seq, bp);
603                                                 cont=0;
604                                                 num_blocks--;
605                                                 *pR=htonl(bR);
606                                                 *pL=htonl(bL);
607                                                 tcph->doff+=2;
608                                                 *tlen+=8;
609                                                 pL=pR+1;
610                                                 pR=pL+1;
611                                         }
612                                         bp= bp - (*cur & 0x3F)- 1;
613                                 }
614
615                                 if((*cur & 0xC0)==0x00){ //received packet
616                                         if(!cont){ /*if no SACK run and we can start another one, do so*/
617                                                 if(num_blocks>0){
618                                                         bL=convert_ack(seq, bp);
619                                                         isopt=1;
620                                                         cont=1;
621
622                                                 }
623                                         }
624                                         bp =  bp -(*cur & 0x3F)- 1;
625                                 }
626                                 tmp--;
627                                 cur++;
628                         }
629                 }
630
631                 optlen-=len;
632                 opt+=len;
633         }
634
635         /*if we are in the middle of a SACK run, close it*/
636         if(cont){
637                 bR=convert_ack(seq, bp);
638                 *pR=htonl(bR);
639                 *pL=htonl(bL);
640                 tcph->doff+=2;
641                 *tlen+=8;
642                 cont=0;
643         }
644
645         /*adjust length if the option is actually added*/
646         if(isopt){
647                 tcph->doff+=1;
648         }
649 return;
650 }