1 /******************************************************************************
2 Utility to convert a DCCP flow to a TCP flow for DCCP analysis via
3 tcptrace. Functions for differentiating different DCCP connections.
5 Copyright (C) 2013 Samuel Jero <sj323707@ohio.edu>
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.
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.
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/>.
20 Author: Samuel Jero <sj323707@ohio.edu>
22 ******************************************************************************/
25 int isClosed(struct hcon *A, struct hcon *B, int pkt_type);
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 int pkt_type, struct hcon **fwd, struct hcon **rev){
30 struct connection *ptr;
34 if(add_connection(src_id, dest_id, id_len, src_port, dest_port)==NULL){
42 /*Loop list looking for connection*/
45 if(memcmp(ptr->A.id,src_id,id_len)==0 && ptr->A.port==src_port &&
46 !isClosed(&ptr->A, &ptr->B, pkt_type)){
51 if(memcmp(ptr->B.id,src_id,id_len)==0 && ptr->B.port==src_port &&
52 !isClosed(&ptr->A, &ptr->B, pkt_type)){
60 /*Add new connection*/
61 ptr=add_connection(src_id, dest_id, id_len, src_port, dest_port);
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, int 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*/
82 if(A->state==DEAD || B->state==DEAD){
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;
96 ptr=chead=malloc(sizeof(struct connection));
104 ptr=prev->next=malloc(sizeof(struct connection));
108 dbgprintf(0,"Error: Couldn't allocate Memory\n");
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");
119 memcpy(ptr->A.id,src_id,id_len);
120 ptr->A.port=src_port;
123 memcpy(ptr->B.id,dest_id,id_len);
124 ptr->B.port=dest_port;
131 /*Update the state on a host*/
132 int update_state(struct hcon* hst, enum con_state st){
140 /*Free all connections*/
141 void cleanup_connections(){
142 struct connection *ptr;
143 struct connection *prev;
156 /* Setup Half Connection Structure*/
157 u_int32_t initialize_hcon(struct hcon *hcn, __be32 initial)
159 /*set default values*/
165 hcn->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
166 if(hcn->table==NULL){
167 dbgprintf(0,"Can't Allocate Memory!\n");
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);
180 /*Convert Sequence Numbers*/
181 u_int32_t add_new_seq(struct hcon *hcn, __be32 num, int size, enum dccp_pkt_type type)
185 dbgprintf(0,"ERROR NULL POINTER!\n");
189 if(hcn->table==NULL){
190 dbgprintf(1, "Warning: Connection uninitialized\n");
191 return initialize_hcon(hcn, num);
194 /*account for missing packets*/
195 if(num - hcn->table[hcn->cur].old +1 >=100){
196 dbgprintf(1,"Missing more than 100 packets!\n");
198 while(hcn->table[hcn->cur].old +1 < num && hcn->table[hcn->cur].old +1 > 0){
200 if(num - hcn->table[hcn->cur].old +1 <100){
201 dbgprintf(1,"Missing Packet %i\n",hcn->table[prev].new+1);
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;
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;
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;
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;
228 hcn->table[hcn->cur].new=hcn->table[prev].new + hcn->table[prev].size;
229 return hcn->table[hcn->cur].new +1;
232 /*Convert Ack Numbers*/
233 u_int32_t convert_ack(struct hcon *hcn, __be32 num, struct hcon *o_hcn)
236 dbgprintf(0,"ERROR NULL POINTER!\n");
240 if(hcn->table==NULL){
241 dbgprintf(1, "Warning: Connection uninitialized\n");
242 initialize_hcon(hcn, num);
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*/
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;
257 /* Get size of packet being acked*/
258 int acked_packet_size(struct hcon *hcn, __be32 num)
261 dbgprintf(0,"ERROR NULL POINTER!\n");
265 if(hcn->table==NULL){
266 dbgprintf(1, "Warning: Connection uninitialized\n");
267 initialize_hcon(hcn, num);
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;
277 dbgprintf(1, "Error: Sequence Number Not Found! looking for %i\n", num);
281 /*Parse Ack Vector Options
282 * Returns the Number of packets since last recorded loss*/
283 unsigned int interp_ack_vect(u_char* hdr)
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);
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);
306 /*One byte options (no length)*/
313 /*Check option length*/
316 dbgprintf(0, "Warning: Option would extend into packet data\n");
320 /*Ack Vector Option*/
321 if(*opt==38 || *opt==39){
324 /*loop through Vector*/
326 /*ack vector works BACKWARDS through time*/
328 /*keep track of total packets recieved and if
329 a packet is lost, subtract all packets received
331 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
336 if((*cur & 0xC0)==0x00){ //received packet
337 bp+= (*cur & 0x3F)+1;
340 if(((*cur& 0xC0)!= 0xC0) && ((*cur& 0xC0)!= 0x00) && ((*cur& 0xC0)!= 0x40)){
341 dbgprintf(1, "Warning: Invalid Ack Vector!! (Linux will handle poorly!)\n");
352 dbgprintf(2,"Ack vector adding: %i\n", additional);