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 /*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;
32 if(add_connection(src_id, dest_id, id_len, src_port, dest_port)==NULL){
40 /*Loop list looking for connection*/
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)){
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)){
58 /*Add new connection*/
59 ptr=add_connection(src_id, dest_id, id_len, src_port, dest_port);
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;
75 ptr=chead=malloc(sizeof(struct connection));
83 ptr=prev->next=malloc(sizeof(struct connection));
87 dbgprintf(0,"Error: Couldn't allocate Memory\n");
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");
98 memcpy(ptr->A.id,src_id,id_len);
102 memcpy(ptr->B.id,dest_id,id_len);
103 ptr->B.port=dest_port;
110 /*Update the state on a host*/
111 int update_state(struct hcon* hst, enum con_state st){
119 /*Free all connections*/
120 void cleanup_connections(){
121 struct connection *ptr;
122 struct connection *prev;
135 /* Setup Half Connection Structure*/
136 u_int32_t initialize_hcon(struct hcon *hcn, __be32 initial)
138 /*set default values*/
144 hcn->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
145 if(hcn->table==NULL){
146 dbgprintf(0,"Can't Allocate Memory!\n");
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);
159 /*Convert Sequence Numbers*/
160 u_int32_t add_new_seq(struct hcon *hcn, __be32 num, int size, enum dccp_pkt_type type)
164 dbgprintf(0,"ERROR NULL POINTER!\n");
168 if(hcn->table==NULL){
169 dbgprintf(1, "Warning: Connection uninitialized\n");
170 return initialize_hcon(hcn, num);
173 /*account for missing packets*/
174 if(num - hcn->table[hcn->cur].old +1 >=100){
175 dbgprintf(1,"Missing more than 100 packets!\n");
177 while(hcn->table[hcn->cur].old +1 < num && hcn->table[hcn->cur].old +1 > 0){
179 if(num - hcn->table[hcn->cur].old +1 <100){
180 dbgprintf(1,"Missing Packet: %X\n",hcn->table[prev].new+1);
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;
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;
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;
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;
207 hcn->table[hcn->cur].new=hcn->table[prev].new + hcn->table[prev].size;
208 return hcn->table[hcn->cur].new +1;
211 /*Convert Ack Numbers*/
212 u_int32_t convert_ack(struct hcon *hcn, __be32 num, struct hcon *o_hcn)
215 dbgprintf(0,"ERROR NULL POINTER!\n");
219 if(hcn->table==NULL){
220 dbgprintf(1, "Warning: Connection uninitialized\n");
221 initialize_hcon(hcn, num);
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*/
231 dbgprintf(1, "Error: Address Not Found! looking for: %X. Using highest ACK, %i, instead\n", num, o_hcn->high_ack);
235 /* Get size of packet being acked*/
236 int acked_packet_size(struct hcon *hcn, __be32 num)
239 dbgprintf(0,"ERROR NULL POINTER!\n");
243 if(hcn->table==NULL){
244 dbgprintf(1, "Warning: Connection uninitialized\n");
245 initialize_hcon(hcn, num);
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;
255 dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
259 /*Parse Ack Vector Options
260 * Returns the Number of packets since last recorded loss*/
261 unsigned int interp_ack_vect(u_char* hdr)
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);
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);
284 /*One byte options (no length)*/
291 /*Check option length*/
294 dbgprintf(0, "Warning: Option would extend into packet data\n");
298 /*Ack Vector Option*/
299 if(*opt==38 || *opt==39){
302 /*loop through Vector*/
304 /*ack vector works BACKWARDS through time*/
306 /*keep track of total packets recieved and if
307 a packet is lost, subtract all packets received
309 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
314 if((*cur & 0xC0)==0x00){ //received packet
315 bp+= (*cur & 0x3F)+1;
318 if(((*cur& 0xC0)!= 0xC0) && ((*cur& 0xC0)!= 0x00) && ((*cur& 0xC0)!= 0x40)){
319 dbgprintf(1, "Warning: Invalid Ack Vector!! (Linux will handle poorly!)\n");
330 dbgprintf(2,"Ack vector adding: %i\n", additional);