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