]> sjero.net Git - dccp2tcp/blob - dccp2tcp.c
Checksum computation!
[dccp2tcp] / dccp2tcp.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)DCCP DATA packets are not implemented (Linux doesn't use them)
27         4)DCCP Ack packets show up as TCP packets containing one byte
28 ******************************************************************************/
29 #include "dccp2tcp.h"
30
31
32 #define DCCP2TCP_VERSION 1.6
33 #define COPYRIGHT_YEAR 2013
34
35
36 int debug=0;    /*set to 1 to turn on debugging information*/
37 int yellow=0;   /*tcptrace yellow line as currently acked packet*/
38 int green=0;    /*tcptrace green line as currently acked packet*/
39 int sack=0;             /*add TCP SACKS*/
40
41
42 pcap_t*                 in;                     /*libpcap input file discriptor*/
43 pcap_dumper_t   *out;           /*libpcap output file discriptor*/
44 struct connection *chead;       /*connection list*/
45
46
47 void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes);
48 void version();
49 void usage();
50
51
52 /*Parse commandline options and open files*/
53 int main(int argc, char *argv[])
54 {
55         char ebuf[200];
56         char *erbuffer=ebuf;
57         char *dfile=NULL;
58         char *tfile=NULL;
59
60         /*parse commandline options*/
61         if(argc > 9){
62                 usage();
63         }
64
65         /*loop through commandline options*/
66         for(int i=1; i < argc; i++){
67                 if(argv[i][0]!='-' || (argv[i][0]=='-' && strlen(argv[i])==1)){
68                         if(dfile==NULL  || argv[i][0]=='-'){
69                                 /*assign first non-dash (or only dash) argument to the dccp file*/
70                                 dfile=argv[i];
71                         }else{
72                                 if(tfile==NULL){
73                                         tfile=argv[i]; /*assign second non-dash argument to the dccp file*/
74                                 }else{
75                                         usage();
76                                 }
77                         }
78                 }else{
79                         if(argv[i][1]=='d' && strlen(argv[i])==2){ /* -d */
80                                 debug++;
81                         }
82                         if(argv[i][1]=='y' && strlen(argv[i])==2){ /* -y */
83                                 yellow=1;
84                         }
85                         if(argv[i][1]=='g' && strlen(argv[i])==2){ /* -g */
86                                 green=1;
87                         }
88                         if(argv[i][1]=='s' && strlen(argv[i])==2){ /* -s */
89                                 sack++;
90                         }
91                         if(argv[i][1]=='h' && strlen(argv[i])==2){ /* -h */
92                                 usage();
93                         }
94                         if(argv[i][1]=='V' && strlen(argv[i])==2){ /* -V */
95                                 version();
96                         }
97                 }
98         }
99         
100         if(dfile==NULL || tfile==NULL){
101                 usage();
102         }
103
104         /*all options validated*/
105
106         if(debug){
107                 dbgprintf(1,"Debug On\n");
108                 if(green){
109                         dbgprintf(1,"Tcptrace green line at highest acknowledgment\n");
110                 }else{
111                         dbgprintf(1,"Tcptrace green line at highest acknowledged acknowledgment\n");
112                 }
113                 if(yellow){
114                         dbgprintf(1,"Tcptrace yellow line at highest acknowledgment\n");
115                 }else{
116                         dbgprintf(1,"Tcptrace yellow line window value (a made up number)\n");
117                 }
118                 if(sack){
119                         dbgprintf(1,"Adding TCP SACKS\n");
120                 }
121                 dbgprintf(1,"Input file: %s\n", dfile);
122                 dbgprintf(1,"Output file: %s\n", tfile);
123         }
124
125         /*attempt to open input file*/
126         in=pcap_open_offline(dfile, erbuffer);
127         if(in==NULL){
128                 dbgprintf(0,"Error opening input file\n");
129                 exit(1);
130         }
131
132         /*attempt to open output file*/
133         out=pcap_dump_open(in,tfile);
134         if(out==NULL){
135                 dbgprintf(0,"Error opening output file\n");
136                 exit(1);
137         }
138
139         /*process packets*/
140         chead=NULL;
141         u_char *user=(u_char*)out;
142         pcap_loop(in, -1, handle_packet, user); 
143         
144         /*close files*/
145         pcap_close(in);
146         pcap_dump_close(out);
147
148         /*Delete all connections*/
149         cleanup_connections();
150 return 0;
151 }
152
153
154 /*call back function for pcap_loop--do basic packet handling*/
155 void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
156 {
157         u_char                          *ndata;
158         struct pcap_pkthdr      nh;
159         int                                     link_type;
160         struct packet           new;
161         struct const_packet     old;
162
163         /*Determine the link type for this packet*/
164         link_type=pcap_datalink(in);
165
166         /*create new libpcap header*/
167         memcpy(&nh, h, sizeof(struct pcap_pkthdr));
168
169         /*Setup packet structs*/
170         old.h=h;
171         old.length=h->caplen;
172         old.data=bytes;
173         old.dest_id=NULL;
174         old.src_id=NULL;
175         new.h=&nh;
176         new.length=MAX_PACKET;
177         new.dest_id=NULL;
178         new.src_id=NULL;
179
180         /*create buffer for new packet*/
181         new.data=ndata=malloc(MAX_PACKET);
182         if(ndata==NULL){
183                 dbgprintf(0,"Error: Couldn't allocate Memory\n");
184                 exit(1);
185         }
186
187         /*make sure the packet is all zero*/
188         memset(new.data, 0, MAX_PACKET);
189         
190         /*do all the fancy conversions*/
191         if(!do_encap(link_type, &new, &old)){
192                 free(ndata);
193                 return;
194         }
195
196         /*save packet*/
197         pcap_dump(user,&nh, ndata);
198
199         free(ndata);
200 return;
201 }
202
203 /*do all the dccp to tcp conversions*/
204 int convert_packet(struct packet *new, const struct const_packet* old)
205 {
206         struct tcphdr                           *tcph;
207         struct dccp_hdr                         *dccph;
208         struct dccp_hdr_ext             *dccphex;
209         struct host                                     *h1=NULL;
210         struct host                                     *h2=NULL;
211
212         /*Safety checks*/
213         if(!new || !old || !new->data || !old->data || !new->h || !old->h){
214                 dbgprintf(0,"Error:  Convert Packet Function given bad data!\n");
215                 exit(1);
216                 return 0;
217         }
218         if(old->length < (sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)) || new->length < sizeof(struct dccp_hdr)){
219                 dbgprintf(0, "Error: DCCP Packet Too short!\n");
220                 return 0;
221         }
222
223         /*cast header pointers*/
224         tcph=(struct tcphdr*)new->data;
225         dccph=(struct dccp_hdr*)old->data;
226         dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
227
228         dbgprintf(2,"Sequence Number: %llu\n", (unsigned long long)
229                         (((unsigned long)ntohs(dccph->dccph_seq)<<32) + ntohl(dccphex->dccph_seq_low)));
230
231         /*Ensure packet is at least as large as DCCP header*/
232         if(old->length < dccph->dccph_doff*4){
233                 dbgprintf(0, "Error: DCCP Header truncated\n");
234                 return 0;
235         }
236
237         /*Get Hosts*/
238         if(get_host(new->src_id, new->dest_id, new->id_len,
239                         dccph->dccph_sport, dccph->dccph_dport, &h1, &h2)){
240                 dbgprintf(0,"Error: Can't Get Hosts!\n");
241                 return 0;
242         }
243         if(h1==NULL || h2==NULL){
244                 dbgprintf(0, "Error: Can't Get Hosts!\n");
245                 return 0;
246         }
247
248         /*TODO: Add CCID detection*/
249         if(h1->type==CCID2 && h2->type==CCID2){
250                 if(ccid2_convert_packet(new,old)==0){
251                         return 0;
252                 }
253         }
254         if(h1->type==CCID3 && h2->type==CCID3){
255                 //ccid3_convert_packet(new,old);
256         }
257         if(ccid2_convert_packet(new,old)==0){
258                 return 0;
259         }
260
261         /*Compute TCP checksums*/
262         if(new->id_len==IP4_ADDR_LEN){
263                         tcph->check=0;
264                         tcph->check=ipv4_pseudohdr_chksum(new->data,
265                                         new->length, new->dest_id, new->src_id, 6);
266         }else if(new->id_len==IP6_ADDR_LEN){
267                         tcph->check=0;
268                         tcph->check=ipv6_pseudohdr_chksum(new->data,
269                                         new->length, new->dest_id, new->src_id, 6);
270         }else{
271                 tcph->check=0;
272                 dbgprintf(2,"Unknown ID Length, can't do checksums");
273         }
274
275         return 1;
276 }
277
278 void version(){
279         dbgprintf(0, "dccp2tcp version %.1f\nCopyright (C) %i Samuel Jero <sj323707@ohio.edu>\n", DCCP2TCP_VERSION,COPYRIGHT_YEAR);
280         dbgprintf(0, "This program comes with ABSOLUTELY NO WARRANTY.\n");
281         dbgprintf(0, "This is free software, and you are welcome to\nredistribute it under certain conditions.\n");
282         exit(0);
283 }
284
285 /*Usage information for program*/
286 void usage()
287 {
288         dbgprintf(0,"Usage: dccp2tcp dccp_file tcp_file [-d] [-h] [-V] [-y] [-g] [-s]\n");
289         dbgprintf(0, "          -d   Debug. May be repeated for aditional verbosity.\n");
290         dbgprintf(0, "          -V   Version information\n");
291         dbgprintf(0, "          -h   Help\n");
292         dbgprintf(0, "          -y   Yellow line is highest ACK\n");
293         dbgprintf(0, "          -g   Green line is highest ACK\n");
294         dbgprintf(0, "          -s   convert ACK Vectors to SACKS\n");
295         exit(0);
296 }
297
298 /*Debug Printf*/
299 void dbgprintf(int level, const char *fmt, ...)
300 {
301     va_list args;
302     if(debug>=level){
303         va_start(args, fmt);
304         vfprintf(stderr, fmt, args);
305         va_end(args);
306     }
307 }