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