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