1 /*
2 * Copyright (C) 2007 WIDE Project. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the project nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28 /*
29 $Id: binread.c,v 1.14 2007/12/05 05:31:41 nishida Exp $
30 */
31 #include "tcpillust.h"
32 #include <sys/socket.h>
33 #include <pcap.h>
34 #include <net/if_arp.h>
35 #if defined (linux) || defined(__APPLE__)
36 #define __FAVOR_BSD
37 #else
38 #if defined(__FreeBSD__)
39 #include <osreldate.h>
40 #if __FreeBSD_version < 800064
41 #include <net/slip.h>
42 #endif
43 #endif
44 #endif
45 #include <netinet/in.h>
46 #include <netinet/in_systm.h>
47 #include <net/if.h>
48 #include <netinet/if_ether.h>
49 #include <netinet/ip.h>
50 #include <netinet/ip6.h>
51 #include <netinet/tcp.h>
52
53 #define PPP_HDRLEN 4
54 #define NULL_HDRLEN 4
55 #define ATM_HDRLEN 8
56 #ifndef SLIP_HDRLEN
57 #define SLIP_HDRLEN 16
58 #endif
59
60 static void dumper __P((u_char *, const struct pcap_pkthdr *, const u_char *));
61 static void dumpip __P((u_char *, const struct timeval *, int));
62 static void dumpip6 __P((u_char *, const struct timeval *, int));
63 static int pcap_dlt;
64 static int pcap_snap;
65 static long seq1;
66 static long seq2;
67 static long base;
68 static long mbase;
69 static u_char *pktbuffer;
70 static struct tcppkt *tpacket;
71
72 struct tcppkt *
read_binfile(filename)73 read_binfile(filename)
74 char *filename;
75 {
76 char errbuf[PCAP_ERRBUF_SIZE];
77 pcap_t *pc;
78 int count = -1;
79
80 if (!(pc = pcap_open_offline(filename, errbuf))){
81 perror("pcap_open");
82 exit(-1);
83 }
84 pcap_dlt = pcap_datalink(pc);
85 pcap_snap = pcap_snapshot(pc);
86
87 if (!pktcount) {
88 if ((pktbuffer = (u_char *)malloc(pcap_snap +4)) == NULL){
89 perror("malloc");
90 exit(-1);
91 }
92 }
93
94 if (pcap_loop(pc, count, dumper, (u_char *)NULL) < 0) {
95 perror("pcap_loop");
96 exit(-2);
97 }
98 pcap_close(pc);
99 capendtime = tpacket[pktcount -1].captime - tpacket[0].captime;
100
101 return tpacket;
102 }
103
104 static void
dumper(u_char * user,const struct pcap_pkthdr * inh,const u_char * inp)105 dumper(u_char *user, const struct pcap_pkthdr *inh, const u_char *inp)
106 {
107 u_char *p;
108 int caplen = inh->caplen;
109
110 if (caplen > pcap_snap) {
111 fprintf(stderr, "packet too large %s:%d\n", __FILE__, __LINE__);
112 exit(-1);
113 }
114
115 memcpy(pktbuffer, inp, caplen);
116 p = pktbuffer;
117
118 switch (pcap_dlt) {
119 case DLT_EN10MB:
120 if (caplen < (sizeof (struct ether_header)))
121 return;
122 p += sizeof(struct ether_header);
123 dumpip(p, &inh->ts, caplen);
124 break;
125
126 case DLT_SLIP:
127 if (caplen < SLIP_HDRLEN)
128 return;
129 p += SLIP_HDRLEN;
130 dumpip(p, &inh->ts, caplen);
131 break;
132
133 case DLT_PPP:
134 if (caplen < PPP_HDRLEN)
135 return;
136 p += PPP_HDRLEN;
137 dumpip(p, &inh->ts, caplen);
138 break;
139
140 case DLT_NULL:
141 if (caplen < NULL_HDRLEN)
142 return;
143 p += NULL_HDRLEN;
144 dumpip(p, &inh->ts, caplen);
145 break;
146
147 case DLT_ATM_RFC1483:
148 if (caplen < ATM_HDRLEN)
149 return;
150 p += ATM_HDRLEN;
151 dumpip(p, &inh->ts, caplen);
152 break;
153
154 default:
155 fprintf(stderr, "Unknown DLT %x\n", pcap_dlt);
156 exit(-1);
157 break;
158 }
159 }
160
161 static void
dumpip(u_char * p,const struct timeval * tvp,int caplen)162 dumpip(u_char *p, const struct timeval *tvp, int caplen)
163 {
164 struct ip *ip;
165 struct tcphdr *tcp;
166 int len;
167 long datalen;
168 static u_long addr1, addr2;
169 static u_short port1, port2;
170
171 ip = (struct ip *)p;
172 if (ip->ip_v == 6){
173 /* this is IPv6 */
174 dumpip6(p, tvp, caplen);
175 return;
176 }
177 if (ip->ip_p != IPPROTO_TCP){
178 printf("not tcp\n");
179 return;
180 }
181
182 /* skip ip header */
183 p+= ip->ip_hl * 4;
184 tcp = (struct tcphdr *)p;
185 len = (tcp->th_off) *4 - sizeof(struct tcphdr);
186
187 if (pktcount) {
188 if ((ntohl(ip->ip_src.s_addr) != addr1 ||
189 ntohl(ip->ip_dst.s_addr) != addr2) &&
190 (ntohl(ip->ip_src.s_addr) != addr2 ||
191 ntohl(ip->ip_dst.s_addr) != addr1)){
192 printf("Warning: address unmatch\n");
193 return;
194 }
195
196 if ((ntohs(tcp->th_sport) != port1 ||
197 ntohs(tcp->th_dport) != port2) &&
198 (ntohs(tcp->th_sport) != port2 ||
199 ntohs(tcp->th_dport) != port1)){
200 printf("Warning: port unmatch\n");
201 return;
202 }
203 }
204
205 if (!pktcount){
206 isv6 = 0; /* this is ipv4 connection */
207 tpacket = (struct tcppkt *)malloc(sizeof(struct tcppkt));
208 if (tpacket == NULL){
209 perror("malloc");
210 exit(-1);
211 }
212 pktcount += 1;
213 } else {
214 pktcount += 1;
215 tpacket = (struct tcppkt *)realloc(tpacket,
216 sizeof(struct tcppkt) * pktcount);
217 if (tpacket == NULL){
218 perror("realloc");
219 exit(-1);
220 }
221 }
222
223 if (pktcount == 1){
224 addr1 = ntohl(ip->ip_src.s_addr);
225 addr2 = ntohl(ip->ip_dst.s_addr);
226 port1 = ntohs(tcp->th_sport);
227 port2 = ntohs(tcp->th_dport);
228 seq1 = ntohl(tcp->th_seq);
229 seq2 = ntohl(tcp->th_ack);
230 base = tvp->tv_sec;
231 mbase = tvp->tv_usec;
232 } else {
233 if (!seq2) {
234 if (addr1 == ntohl(ip->ip_src.s_addr)) seq2 = ntohl(tcp->th_ack);
235 else seq2 = ntohl(tcp->th_seq);
236 }
237 }
238
239 datalen = ntohs(ip->ip_len) - ip->ip_hl * 4 - tcp->th_off *4;
240
241 memset(&tpacket[pktcount -1], 0, sizeof(struct tcppkt));
242 tpacket[pktcount -1].captime =
243 (tvp->tv_sec - base) + (float)(tvp->tv_usec - mbase)/1000000.0;
244 tpacket[pktcount -1].src6_addr[3] = ntohl(ip->ip_src.s_addr);
245 tpacket[pktcount -1].dst6_addr[3] = ntohl(ip->ip_dst.s_addr);
246 tpacket[pktcount -1].id = ntohs(ip->ip_id);
247
248 if (addr1 == ntohl(ip->ip_src.s_addr)) {
249 tpacket[pktcount -1].seq = ntohl(tcp->th_seq) - seq1;
250 if (ntohl(tcp->th_ack))
251 tpacket[pktcount -1].ack = ntohl(tcp->th_ack) - seq2;
252 } else {
253 tpacket[pktcount -1].seq = ntohl(tcp->th_seq) - seq2;
254 if (ntohl(tcp->th_ack))
255 tpacket[pktcount -1].ack = ntohl(tcp->th_ack) - seq1;
256 }
257
258 tpacket[pktcount -1].src_port = ntohs(tcp->th_sport);
259 tpacket[pktcount -1].dst_port = ntohs(tcp->th_dport);
260 tpacket[pktcount -1].win = ntohs(tcp->th_win);
261 tpacket[pktcount -1].flags = tcp->th_flags;
262 tpacket[pktcount -1].datalen = datalen;
263
264 if (!snaplen) snaplen = caplen;
265
266 if ((tpacket[pktcount -1].data = malloc(snaplen)) == NULL){
267 fprintf(stderr, "cannot malloc for packet data. \
268 Please choose small snaplen value\n");
269 exit(-1);
270 }
271 memcpy(tpacket[pktcount -1].data, ip, snaplen);
272
273 #if 0
274 /* process tcp option, currently not implemented */
275 p += sizeof(struct tcphdr);
276 while(len > 0){
277 if (*p == 0 || *p == 1){
278 len --;
279 p ++;
280 continue;
281 }
282 if (*p == TCPOPT_TIMESTAMP){
283 len -= 10;
284 p+= 10;
285 continue;
286 }
287 p ++;
288 optlen = *p -1;
289 p += optlen;
290 len -= optlen;
291 }
292 #endif
293 }
294
295 static void
dumpip6(u_char * p,const struct timeval * tvp,int caplen)296 dumpip6(u_char *p, const struct timeval *tvp, int caplen)
297 {
298 struct ip6_hdr *ip6;
299 struct tcphdr *tcp;
300 static u_long addr1[4], addr2[4];
301 static u_short port1, port2;
302 long datalen;
303 u_char proto;
304 int len;
305
306 ip6 = (struct ip6_hdr *)p;
307 /* skip ip header */
308 p += sizeof(struct ip6_hdr);
309 if (ip6->ip6_nxt != IPPROTO_TCP){
310 /* skip external header */
311 while(1){
312 proto = ((struct ip6_hbh *)p)->ip6h_nxt;
313 len = ((struct ip6_hbh *)p)->ip6h_len;
314 if (proto == IPPROTO_HOPOPTS || proto == IPPROTO_ROUTING
315 || proto == IPPROTO_DSTOPTS){
316 p += len;
317 }
318 break;
319 }
320 if (proto != IPPROTO_TCP){
321 printf("Not tcp\n");
322 return;
323 }
324 p += len;
325 }
326 tcp = (struct tcphdr *)p;
327 len = (tcp->th_off) *4 - sizeof(struct tcphdr);
328
329 if (pktcount){
330 if ((memcmp(ip6->ip6_src.s6_addr, addr1, 16) ||
331 memcmp(ip6->ip6_dst.s6_addr, addr2, 16)) &&
332 (memcmp(ip6->ip6_src.s6_addr, addr2, 16) ||
333 memcmp(ip6->ip6_dst.s6_addr, addr1, 16))){
334 printf("Warning: address unmatch\n");
335 return;
336 }
337 if ((ntohs(tcp->th_sport) != port1 ||
338 ntohs(tcp->th_dport) != port2) &&
339 (ntohs(tcp->th_sport) != port2 ||
340 ntohs(tcp->th_dport) != port1)){
341 printf("Warning: port unmatch\n");
342 return;
343 }
344 }
345
346 if (!pktcount){
347 tpacket = (struct tcppkt *)malloc(sizeof(struct tcppkt));
348 if (tpacket == NULL){
349 perror("malloc");
350 exit(-1);
351 }
352 pktcount += 1;
353 isv6 = 1; /* this is ipv6 connection */
354 } else {
355 pktcount += 1;
356 tpacket = (struct tcppkt *)realloc(tpacket,
357 sizeof(struct tcppkt) * pktcount);
358 if (tpacket == NULL){
359 perror("realloc");
360 exit(-1);
361 }
362 }
363
364 if (pktcount == 1){
365 memcpy(&addr1, ip6->ip6_src.s6_addr, 16);
366 memcpy(&addr2, ip6->ip6_dst.s6_addr, 16);
367 port1 = ntohs(tcp->th_sport);
368 port2 = ntohs(tcp->th_dport);
369 seq1 = ntohl(tcp->th_seq);
370 seq2 = ntohl(tcp->th_ack);
371 base = tvp->tv_sec;
372 mbase = tvp->tv_usec;
373 } else {
374 if (!seq2) {
375 if (!memcmp(ip6->ip6_src.s6_addr, addr1, 16))
376 seq2 = ntohl(tcp->th_ack);
377 else
378 seq2 = ntohl(tcp->th_seq);
379 }
380 }
381
382 datalen = ntohs(ip6->ip6_plen) - tcp->th_off *4;
383
384 memset(&tpacket[pktcount -1], 0, sizeof(struct tcppkt));
385 tpacket[pktcount -1].captime =
386 (tvp->tv_sec - base) + (float)(tvp->tv_usec - mbase)/1000000.0;
387 memcpy(tpacket[pktcount -1].src6_addr, ip6->ip6_src.s6_addr, 16);
388 memcpy(tpacket[pktcount -1].dst6_addr, ip6->ip6_dst.s6_addr, 16);
389 tpacket[pktcount -1].flow = ip6->ip6_flow;
390
391 if (!memcmp(addr1, ip6->ip6_src.s6_addr, 16)) {
392 tpacket[pktcount -1].seq = ntohl(tcp->th_seq) - seq1;
393 if (ntohl(tcp->th_ack))
394 tpacket[pktcount -1].ack = ntohl(tcp->th_ack) - seq2;
395 } else {
396 tpacket[pktcount -1].seq = ntohl(tcp->th_seq) - seq2;
397 if (ntohl(tcp->th_ack))
398 tpacket[pktcount -1].ack = ntohl(tcp->th_ack) - seq1;
399 }
400
401 tpacket[pktcount -1].src_port = ntohs(tcp->th_sport);
402 tpacket[pktcount -1].dst_port = ntohs(tcp->th_dport);
403 tpacket[pktcount -1].win = ntohs(tcp->th_win);
404 tpacket[pktcount -1].flags = tcp->th_flags;
405 tpacket[pktcount -1].datalen = datalen;
406
407 if (!snaplen) snaplen = caplen;
408
409 if ((tpacket[pktcount -1].data = malloc(snaplen)) == NULL){
410 fprintf(stderr, "cannot malloc for packet data. \
411 Please choose small snaplen value\n");
412 exit(-1);
413 }
414 memcpy(tpacket[pktcount -1].data, ip6, snaplen);
415
416 if (!snaplen) snaplen = caplen;
417
418 if ((tpacket[pktcount -1].data = malloc(snaplen)) == NULL){
419 fprintf(stderr, "cannot malloc for packet data. \
420 Please choose small snaplen value\n");
421 exit(-1);
422 }
423 memcpy(tpacket[pktcount -1].data, ip6, snaplen);
424 }
425
426 char *
create_msg(int id,int fast)427 create_msg(int id, int fast)
428 {
429 static char buf[65535];
430 u_char *p = (u_char *)ilt[id].data;
431 struct ip *ip = (struct ip *)p;
432 struct ip6_hdr *ip6;
433 struct tcphdr *tcp;
434 int i, datalen, off, hlen = 0;
435 u_char proto;
436 void tcp_print();
437
438 if (!isv6) {
439 datalen = ntohs(ip->ip_len) - ip->ip_hl * 4;
440 p+= ip->ip_hl * 4;
441 tcp = (struct tcphdr *)p;
442 off = sizeof(struct ip);
443 } else {
444 ip6 = (struct ip6_hdr *)p;
445 /* skip ip header */
446 p += sizeof(struct ip6_hdr);
447 if (ip6->ip6_nxt != IPPROTO_TCP){
448 /* skip external header */
449 while(1){
450 proto = ((struct ip6_hbh *)p)->ip6h_nxt;
451 hlen = ((struct ip6_hbh *)p)->ip6h_len;
452 if (proto == IPPROTO_HOPOPTS
453 || proto == IPPROTO_ROUTING || proto == IPPROTO_DSTOPTS){
454 p += hlen;
455 }
456 break;
457 }
458 p += hlen;
459 }
460 tcp = (struct tcphdr *)p;
461 datalen = ntohs(ip6->ip6_plen);
462 off = sizeof(struct ip6_hdr) + hlen;
463 }
464 bzero(buf, sizeof(buf));
465
466 if (datalen + off < snaplen)
467 tcp_print(p, datalen, ip, 0, buf);
468 else
469 tcp_print(p, datalen, ip, 1, buf);
470
471 if (fast) return buf;
472
473 /* hex dump */
474 sprintf(buf + strlen(buf), "\n");
475 off = 0;
476 p = (u_char *)ilt[id].data;
477 hlen = ip->ip_hl * 4 + tcp->th_off * 4;
478 while(hlen) {
479 sprintf(buf + strlen(buf), "\n 0x%04x: ", off);
480 if (hlen >= 16) {
481 for (i = 0; i < 16; i ++) {
482 if (i % 2)
483 sprintf(buf + strlen(buf), "%02x ", *(p +i));
484 else
485 sprintf(buf + strlen(buf), "%02x", *(p +i));
486 }
487 } else {
488 for (i = 0; i < hlen; i ++) {
489 if (i % 2)
490 sprintf(buf + strlen(buf), "%02x ", *(p +i));
491 else
492 sprintf(buf + strlen(buf), "%02x", *(p +i));
493 }
494 break;
495 }
496 hlen -= 16;
497 p += 16;
498 off += 16;
499 }
500
501 return buf;
502 }
503