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