]> sjero.net Git - dccp2tcp/blob - connections.c
IPv6 encapsulation bugfix
[dccp2tcp] / connections.c
1 /******************************************************************************
2 Utility to convert a DCCP flow to a TCP flow for DCCP analysis via
3                 tcptrace. Functions for differentiating different DCCP connections.
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 #include "dccp2tcp.h"
24
25 /*Lookup a connection. If it doesn't exist, add a new connection and return it.*/
26 int get_host(u_char *src_id, u_char* dest_id, int id_len, int src_port, int dest_port,
27                 struct hcon **fwd, struct hcon **rev){
28         struct connection *ptr;
29
30         /*Empty list*/
31         if(chead==NULL){
32                 if(add_connection(src_id, dest_id, id_len, src_port, dest_port)==NULL){
33                         return 1;
34                 }
35                 *fwd=&chead->A;
36                 *rev=&chead->B;
37                 return 0;
38         }
39
40         /*Loop list looking for connection*/
41         ptr=chead;
42         while(ptr!=NULL){
43                 if(memcmp(ptr->A.id,src_id,id_len)==0 && ptr->A.port==src_port &&
44                                 !(ptr->A.state==CLOSE && ptr->B.state==CLOSE)){
45                         *fwd=&ptr->A;
46                         *rev=&ptr->B;
47                         return 0;
48                 }
49                 if(memcmp(ptr->B.id,src_id,id_len)==0 && ptr->B.port==src_port &&
50                                 !(ptr->B.state==CLOSE && ptr->A.state==CLOSE)){
51                         *fwd=&ptr->B;
52                         *rev=&ptr->A;
53                         return 0;
54                 }
55                 ptr=ptr->next;
56         }
57
58         /*Add new connection*/
59         ptr=add_connection(src_id, dest_id, id_len, src_port, dest_port);
60         if(ptr==NULL){
61                 return 1;
62         }
63         *fwd=&ptr->A;
64         *rev=&ptr->B;
65         return 0;
66 }
67
68 /*Add a connection. Return it. On failure, return NULL*/
69 struct connection *add_connection(u_char *src_id, u_char* dest_id, int id_len, int src_port, int dest_port){
70         struct connection *ptr;
71         struct connection *prev;
72
73         /*Allocate memory*/
74         if(chead==NULL){
75                 ptr=chead=malloc(sizeof(struct connection));
76         }else{
77                 ptr=chead;
78                 prev=chead;
79                 while(ptr!=NULL){
80                         prev=ptr;
81                         ptr=ptr->next;
82                 }
83                 ptr=prev->next=malloc(sizeof(struct connection));
84         }
85
86         if(ptr==NULL){
87                 dbgprintf(0,"Error: Couldn't allocate Memory\n");
88                 exit(1);
89         }
90
91         /*Initialize*/
92         ptr->A.id=malloc(id_len);
93         ptr->B.id=malloc(id_len);
94         if(ptr->A.id==NULL||ptr->B.id==NULL){
95                 dbgprintf(0,"Error: Couldn't allocate Memory\n");
96                 exit(1);
97         }
98         memcpy(ptr->A.id,src_id,id_len);
99         ptr->A.port=src_port;
100         ptr->A.state=INIT;
101         ptr->A.type=UNKNOWN;
102         memcpy(ptr->B.id,dest_id,id_len);
103         ptr->B.port=dest_port;
104         ptr->B.state=INIT;
105         ptr->B.type=UNKNOWN;
106
107         return ptr;
108 }
109
110 /*Update the state on a host*/
111 int update_state(struct hcon* hst, enum con_state st){
112         if(!hst){
113                 return 1;
114         }
115         hst->state=st;
116         return 0;
117 }
118
119 /*Free all connections*/
120 void cleanup_connections(){
121         struct connection *ptr;
122         struct connection *prev;
123         prev=ptr=chead;
124
125         while(ptr!=NULL){
126                 prev=ptr;
127                 free(ptr->A.id);
128                 free(ptr->B.id);
129                 ptr=ptr->next;
130                 free(prev);
131         }
132 return;
133 }
134
135 /* Setup Half Connection Structure*/
136 u_int32_t initialize_hcon(struct hcon *hcn, __be32 initial)
137 {
138         /*set default values*/
139         hcn->cur=0;
140         hcn->size=TBL_SZ;
141         hcn->high_ack=0;
142
143         /*allocate table*/
144         hcn->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
145         if(hcn->table==NULL){
146                 dbgprintf(0,"Can't Allocate Memory!\n");
147                 exit(1);
148         }
149
150         /*add first sequence number*/
151         hcn->table[0].old=initial;
152         hcn->table[0].new=initial;
153         hcn->table[0].type=DCCP_PKT_REQUEST;
154         hcn->table[0].size=0;
155         update_state(hcn,OPEN);
156 return initial;
157 }
158
159 /*Convert Sequence Numbers*/
160 u_int32_t add_new_seq(struct hcon *hcn, __be32 num, int size, enum dccp_pkt_type type)
161 {
162         int prev;
163         if(hcn==NULL){
164                 dbgprintf(0,"ERROR NULL POINTER!\n");
165                 exit(1);
166         }
167
168         if(hcn->table==NULL){
169                 dbgprintf(1, "Warning: Connection uninitialized\n");
170                 return initialize_hcon(hcn, num);
171         }
172
173         /*account for missing packets*/
174         if(num - hcn->table[hcn->cur].old +1 >=100){
175                         dbgprintf(1,"Missing more than 100 packets!\n");
176         }
177         while(hcn->table[hcn->cur].old +1 < num && hcn->table[hcn->cur].old +1 > 0){
178                 prev=hcn->cur;
179                 if(num - hcn->table[hcn->cur].old +1 <100){
180                         dbgprintf(1,"Missing Packet: %X\n",hcn->table[prev].new+1);
181                 }
182                 hcn->cur=(hcn->cur+1)%(hcn->size);/*find next available table slot*/
183                 hcn->table[hcn->cur].old=hcn->table[prev].old+1;
184                 hcn->table[hcn->cur].new=hcn->table[prev].new + hcn->table[prev].size;
185                 hcn->table[hcn->cur].size=size;
186                 hcn->table[hcn->cur].type=type;
187         }
188
189         prev=hcn->cur;
190         hcn->cur=(hcn->cur+1)%(hcn->size);/*find next available table slot*/
191         hcn->table[hcn->cur].old=num;
192         hcn->table[hcn->cur].size=size;
193         hcn->table[hcn->cur].type=type;
194         if(hcn->table[prev].type==DCCP_PKT_REQUEST || hcn->table[prev].type==DCCP_PKT_RESPONSE){
195                 hcn->table[hcn->cur].new=hcn->table[prev].new + hcn->table[prev].size;
196                 hcn->table[hcn->cur].size=1;
197                 return hcn->table[prev].new + hcn->table[prev].size+1;
198         }
199         if(type==DCCP_PKT_DATA || type==DCCP_PKT_DATAACK || type==DCCP_PKT_ACK){
200                 hcn->table[hcn->cur].new=hcn->table[prev].new + hcn->table[prev].size;
201                 return hcn->table[hcn->cur].new+1;
202         }
203         if(type==DCCP_PKT_SYNC || type==DCCP_PKT_SYNCACK){
204                 hcn->table[hcn->cur].new=hcn->table[prev].new + hcn->table[prev].size;
205                 return hcn->table[hcn->cur].new;
206         }
207         hcn->table[hcn->cur].new=hcn->table[prev].new + hcn->table[prev].size;
208 return hcn->table[hcn->cur].new +1;
209 }
210
211 /*Convert Ack Numbers*/
212 u_int32_t convert_ack(struct hcon *hcn, __be32 num, struct hcon *o_hcn)
213 {
214         if(hcn==NULL){
215                 dbgprintf(0,"ERROR NULL POINTER!\n");
216                 exit(1);
217         }
218
219         if(hcn->table==NULL){
220                 dbgprintf(1, "Warning: Connection uninitialized\n");
221                 initialize_hcon(hcn, num);
222         }
223
224         /*loop through table looking for the DCCP ack number*/
225         for(int i=0; i < hcn->size; i++){
226                 if(hcn->table[i].old==num){
227                         return  hcn->table[i].new + hcn->table[i].size + 1; /*TCP acks the sequence number plus 1*/
228                 }
229         }
230
231         dbgprintf(1, "Error: Address Not Found! looking for: %X. Using highest ACK, %i, instead\n", num, o_hcn->high_ack);
232 return 0;
233 }
234
235 /* Get size of packet being acked*/
236 int acked_packet_size(struct hcon *hcn, __be32 num)
237 {
238         if(hcn==NULL){
239                 dbgprintf(0,"ERROR NULL POINTER!\n");
240                 exit(1);
241         }
242
243         if(hcn->table==NULL){
244                 dbgprintf(1, "Warning: Connection uninitialized\n");
245                 initialize_hcon(hcn, num);
246         }
247
248         /*loop through table looking for the DCCP ack number*/
249         for(int i=0; i < hcn->size; i++){
250                 if(hcn->table[i].old==num){
251                         return  hcn->table[i].size;
252                 }
253         }
254
255         dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
256 return 0;
257 }
258
259 /*Parse Ack Vector Options
260  * Returns the Number of packets since last recorded loss*/
261 unsigned int interp_ack_vect(u_char* hdr)
262 {
263         int hdrlen=((struct dccp_hdr*)hdr)->dccph_doff*4;
264         //struct dccp_hdr_ext* e=(struct dccp_hdr_ext*)hdr + sizeof(struct dccp_hdr);
265         int optlen;
266         int len;
267         int tmp;
268         int bp=0;
269         int additional=0;
270         u_char* opt;
271         u_char* cur;
272
273         /*setup pointer to DCCP options and determine how long the options are*/
274         optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
275         opt=hdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
276
277         if(optlen<=0){
278                 return 0;
279         }
280
281         /*parse options*/
282         while(optlen > 0){
283
284                 /*One byte options (no length)*/
285                 if(*opt< 32){
286                         optlen--;
287                         opt++;
288                         continue;
289                 }
290
291                 /*Check option length*/
292                 len=*(opt+1);
293                 if(len > optlen){
294                         dbgprintf(0, "Warning: Option would extend into packet data\n");
295                         return additional;
296                 }
297
298                 /*Ack Vector Option*/
299                 if(*opt==38 || *opt==39){
300                         tmp=len-2;
301                         cur=opt+2;
302                         /*loop through Vector*/
303                         while(tmp > 0){
304                                 /*ack vector works BACKWARDS through time*/
305
306                                 /*keep track of total packets recieved and if
307                                 a packet is lost, subtract all packets received
308                                 after that*/
309                                 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
310                                         bp+=(*cur & 0x3F)+1;
311                                         additional= -bp;
312                                 }
313
314                                 if((*cur & 0xC0)==0x00){ //received packet
315                                         bp+= (*cur & 0x3F)+1;
316                                 }
317
318                                 if(((*cur& 0xC0)!= 0xC0) && ((*cur& 0xC0)!= 0x00) && ((*cur& 0xC0)!= 0x40)){
319                                         dbgprintf(1, "Warning: Invalid Ack Vector!! (Linux will handle poorly!)\n");
320                                 }
321                                 tmp--;
322                                 cur++;
323                         }
324                 }
325
326                 optlen-=len;
327                 opt+=len;
328         }
329
330         dbgprintf(2,"Ack vector adding: %i\n", additional);
331 return additional;
332 }