• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source3/utils/
1/*
2   Unix SMB/CIFS implementation.
3   Utility to extract pcap files from samba (log level 10) log files
4
5   Copyright (C) Jelmer Vernooij 2003
6   Thanks to Tim Potter for the genial idea
7
8   Portions (from capconvert.c) (C) Andrew Tridgell 1997
9   Portions (from text2pcap.c) (C) Ashok Narayanan 2001
10
11   Example:
12	Output NBSS(SMB) packets in hex and convert to pcap adding
13	Eth/IP/TCP headers
14
15	log2pcap -h < samba.log | text2pcap -T 139,139 - samba.pcap
16
17	Output directly to pcap format without Eth headers or TCP
18	sequence numbers
19
20	log2pcap samba.log samba.pcap
21
22    TODO:
23	- Hex to text2pcap outputs are not properly parsed in Wireshark
24	  the NBSS or SMB level.  This is a bug.
25	- Writing directly to pcap format doesn't include sequence numbers
26	  in the TCP packets
27	- Check if a packet is a response or request and set IP to/from
28	  addresses accordingly.  Currently all packets come from the same
29	  dummy IP and go to the same dummy IP
30	- Add a message when done parsing about the number of pacekts
31	  processed
32	- Parse NBSS packet header data from log file
33	- Have correct IP and TCP checksums.
34
35   Warning:
36	Samba log level 10 outputs a max of 512 bytes from the packet data
37	section.  Packets larger than this will be truncated.
38
39   This program is free software; you can redistribute it and/or modify
40   it under the terms of the GNU General Public License as published by
41   the Free Software Foundation; either version 3 of the License, or
42   (at your option) any later version.
43
44   This program is distributed in the hope that it will be useful,
45   but WITHOUT ANY WARRANTY; without even the implied warranty of
46   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
47   GNU General Public License for more details.
48
49   You should have received a copy of the GNU General Public License
50   along with this program.  If not, see <http://www.gnu.org/licenses/>.
51*/
52
53#include "includes.h"
54
55/* We don't care about the paranoid malloc checker in this standalone
56   program */
57#undef malloc
58
59#include <assert.h>
60
61int quiet = 0;
62int hexformat = 0;
63
64#define itoa(a) ((a) < 0xa?'0'+(a):'A' + (a-0xa))
65
66#include <stdlib.h>
67#include <unistd.h>
68#include <sys/time.h>
69#include <stdio.h>
70#include <fcntl.h>
71
72#define TCPDUMP_MAGIC 0xa1b2c3d4
73
74/* tcpdump file format */
75struct tcpdump_file_header {
76	uint32 magic;
77	uint16 major;
78	uint16 minor;
79	int32 zone;
80	uint32 sigfigs;
81	uint32 snaplen;
82	uint32 linktype;
83};
84
85struct tcpdump_packet {
86	struct timeval ts;
87	uint32 caplen;
88	uint32 len;
89};
90
91typedef struct {
92    uint8  ver_hdrlen;
93    uint8  dscp;
94    uint16 packet_length;
95    uint16 identification;
96    uint8  flags;
97    uint8  fragment;
98    uint8  ttl;
99    uint8  protocol;
100    uint16 hdr_checksum;
101    uint32 src_addr;
102    uint32 dest_addr;
103} hdr_ip_t;
104
105static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 6, 0, 0x01010101, 0x02020202};
106
107typedef struct {
108    uint16 source_port;
109    uint16 dest_port;
110    uint32 seq_num;
111    uint32 ack_num;
112    uint8  hdr_length;
113    uint8  flags;
114    uint16 window;
115    uint16 checksum;
116    uint16 urg;
117} hdr_tcp_t;
118
119static hdr_tcp_t HDR_TCP = {139, 139, 0, 0, 0x50, 0, 0, 0, 0};
120
121static void print_pcap_header(FILE *out)
122{
123	struct tcpdump_file_header h;
124	h.magic = TCPDUMP_MAGIC;
125	h.major = 2;
126	h.minor = 4;
127	h.zone = 0;
128	h.sigfigs = 0;
129	h.snaplen = 102400; /* As long packets as possible */
130	h.linktype = 101; /* Raw IP */
131	fwrite(&h, sizeof(struct tcpdump_file_header), 1, out);
132}
133
134static void print_pcap_packet(FILE *out, unsigned char *data, long length,
135			      long caplen)
136{
137	static int i = 0;
138	struct tcpdump_packet p;
139	i++;
140	p.ts.tv_usec = 0;
141	p.ts.tv_sec = 0;
142	p.caplen = caplen;
143	p.len = length;
144	fwrite(&p, sizeof(struct tcpdump_packet), 1, out);
145	fwrite(data, sizeof(unsigned char), caplen, out);
146}
147
148static void print_hex_packet(FILE *out, unsigned char *data, long length)
149{
150	long i,cur = 0;
151	while(cur < length) {
152		fprintf(out, "%06lX ", cur);
153		for(i = cur; i < length && i < cur + 16; i++) {
154			fprintf(out, "%02x ", data[i]);
155		}
156
157		cur = i;
158		fprintf(out, "\n");
159	}
160}
161
162static void print_netbios_packet(FILE *out, unsigned char *data, long length,
163				 long actual_length)
164{
165	unsigned char *newdata; long offset = 0;
166	long newlen;
167
168	newlen = length+sizeof(HDR_IP)+sizeof(HDR_TCP);
169	newdata = (unsigned char *)malloc(newlen);
170
171	HDR_IP.packet_length = htons(newlen);
172	HDR_TCP.window = htons(0x2000);
173	HDR_TCP.source_port = HDR_TCP.dest_port = htons(139);
174
175	memcpy(newdata+offset, &HDR_IP, sizeof(HDR_IP));offset+=sizeof(HDR_IP);
176	memcpy(newdata+offset, &HDR_TCP, sizeof(HDR_TCP));offset+=sizeof(HDR_TCP);
177	memcpy(newdata+offset,data,length);
178
179	print_pcap_packet(out, newdata, newlen, actual_length+offset);
180	free(newdata);
181}
182
183unsigned char *curpacket = NULL;
184unsigned short curpacket_len = 0;
185long line_num = 0;
186
187/* Read the log message produced by lib/util.c:show_msg() containing the:
188 *  SMB_HEADER
189 *  SMB_PARAMETERS
190 *  SMB_DATA.ByteCount
191 *
192 * Example:
193 * [2007/04/08 20:41:39, 5] lib/util.c:show_msg(516)
194 *   size=144
195 *   smb_com=0x73
196 *   smb_rcls=0
197 *   smb_reh=0
198 *   smb_err=0
199 *   smb_flg=136
200 *   smb_flg2=49153
201 *   smb_tid=1
202 *   smb_pid=65279
203 *   smb_uid=0
204 *   smb_mid=64
205 *   smt_wct=3
206 *   smb_vwv[ 0]=  117 (0x75)
207 *   smb_vwv[ 1]=  128 (0x80)
208 *   smb_vwv[ 2]=    1 (0x1)
209 *   smb_bcc=87
210 */
211static void read_log_msg(FILE *in, unsigned char **_buffer,
212			 unsigned short *buffersize, long *data_offset,
213			 long *data_length)
214{
215	unsigned char *buffer;
216	int tmp; long i;
217	assert(fscanf(in, " size=%hu\n", buffersize)); line_num++;
218	buffer = (unsigned char *)malloc(*buffersize+4); /* +4 for NBSS Header */
219	memset(buffer, 0, *buffersize+4);
220	/* NetBIOS Session Service */
221	buffer[0] = 0x00;
222	buffer[1] = 0x00;
223	memcpy(buffer+2, &buffersize, 2); /* TODO: need to copy as little-endian regardless of platform */
224	/* SMB Packet */
225	buffer[4] = 0xFF;
226	buffer[5] = 'S';
227	buffer[6] = 'M';
228	buffer[7] = 'B';
229	assert(fscanf(in, "  smb_com=0x%x\n", &tmp)); buffer[smb_com] = tmp; line_num++;
230	assert(fscanf(in, "  smb_rcls=%d\n", &tmp)); buffer[smb_rcls] = tmp; line_num++;
231	assert(fscanf(in, "  smb_reh=%d\n", &tmp)); buffer[smb_reh] = tmp; line_num++;
232	assert(fscanf(in, "  smb_err=%d\n", &tmp)); memcpy(buffer+smb_err, &tmp, 2); line_num++;
233	assert(fscanf(in, "  smb_flg=%d\n", &tmp)); buffer[smb_flg] = tmp; line_num++;
234	assert(fscanf(in, "  smb_flg2=%d\n", &tmp)); memcpy(buffer+smb_flg2, &tmp, 2); line_num++;
235	assert(fscanf(in, "  smb_tid=%d\n", &tmp)); memcpy(buffer+smb_tid, &tmp, 2); line_num++;
236	assert(fscanf(in, "  smb_pid=%d\n", &tmp)); memcpy(buffer+smb_pid, &tmp, 2); line_num++;
237	assert(fscanf(in, "  smb_uid=%d\n", &tmp)); memcpy(buffer+smb_uid, &tmp, 2); line_num++;
238	assert(fscanf(in, "  smb_mid=%d\n", &tmp)); memcpy(buffer+smb_mid, &tmp, 2); line_num++;
239	assert(fscanf(in, "  smt_wct=%d\n", &tmp)); buffer[smb_wct] = tmp; line_num++;
240	for(i = 0; i < buffer[smb_wct]; i++) {
241		assert(fscanf(in, "  smb_vwv[%*3d]=%*5d (0x%X)\n", &tmp)); line_num++;
242		memcpy(buffer+smb_vwv+i*2, &tmp, 2);
243	}
244
245	*data_offset = smb_vwv+buffer[smb_wct]*2;
246	assert(fscanf(in, "  smb_bcc=%ld\n", data_length)); buffer[(*data_offset)] = *data_length; line_num++;
247	(*data_offset)+=2;
248	*_buffer = buffer;
249}
250
251/* Read the log message produced by lib/util.c:dump_data() containing:
252 *  SMB_DATA.Bytes
253 *
254 * Example:
255 * [2007/04/08 20:41:39, 10] lib/util.c:dump_data(2243)
256 *   [000] 00 55 00 6E 00 69 00 78  00 00 00 53 00 61 00 6D  .U.n.i.x ...S.a.m
257 *   [010] 00 62 00 61 00 20 00 33  00 2E 00 30 00 2E 00 32  .b.a. .3 ...0...2
258 *   [020] 00 34 00 2D 00 49 00 73  00 69 00 6C 00 6F 00 6E  .4.-.I.s .i.l.o.n
259 *   [030] 00 20 00 4F 00 6E 00 65  00 46 00 53 00 20 00 76  . .O.n.e .F.S. .v
260 *   [040] 00 34 00 2E 00 30 00 00  00 49 00 53 00 49 00 4C  .4...0.. .I.S.I.L
261 *   [050] 00 4F 00 4E 00 00 00                              .O.N...
262 */
263static long read_log_data(FILE *in, unsigned char *buffer, long data_length)
264{
265	long i, addr; char real[2][16]; int ret;
266	unsigned int tmp;
267	for(i = 0; i < data_length; i++) {
268		if(i % 16 == 0){
269			if(i != 0) {
270				/* Read and discard the ascii data after each line. */
271				assert(fscanf(in, "  %8c %8c\n", real[0], real[1]) == 2);
272			}
273			ret = fscanf(in, "  [%03lX]", &addr); line_num++;
274			if(!ret) {
275				if(!quiet)
276					fprintf(stderr, "%ld: Only first %ld bytes are logged, "
277					    "packet trace will be incomplete\n", line_num, i-1);
278				return i-1;
279			}
280			assert(addr == i);
281		}
282		if(!fscanf(in, "%02X", &tmp)) {
283			if(!quiet)
284				fprintf(stderr, "%ld: Log message formated incorrectly. "
285				    "Only first %ld bytes are logged, packet trace will "
286				    "be incomplete\n", line_num, i-1);
287			while ((tmp = getc(in)) != '\n');
288			return i-1;
289		}
290		buffer[i] = tmp;
291	}
292
293	/* Consume the newline so we don't increment num_lines twice */
294	while ((tmp = getc(in)) != '\n');
295	return data_length;
296}
297
298int main (int argc, char **argv)
299{
300	const char *infile, *outfile;
301	FILE *out, *in;
302	int opt;
303	poptContext pc;
304	char buffer[4096];
305	long data_offset, data_length;
306	long data_bytes_read = 0;
307	int in_packet = 0;
308	struct poptOption long_options[] = {
309		POPT_AUTOHELP
310		{ "quiet", 'q', POPT_ARG_NONE, &quiet, 0, "Be quiet, don't output warnings" },
311		{ "hex", 'h', POPT_ARG_NONE, &hexformat, 0, "Output format readable by text2pcap" },
312		POPT_TABLEEND
313	};
314
315	pc = poptGetContext(NULL, argc, (const char **) argv, long_options,
316			    POPT_CONTEXT_KEEP_FIRST);
317	poptSetOtherOptionHelp(pc, "[<infile> [<outfile>]]");
318
319
320	while((opt = poptGetNextOpt(pc)) != -1) {
321		switch (opt) {
322		}
323	}
324
325	poptGetArg(pc); /* Drop argv[0], the program name */
326
327	infile = poptGetArg(pc);
328
329	if(infile) {
330		in  = fopen(infile, "r");
331		if(!in) {
332			perror("fopen");
333			return 1;
334		}
335	} else in = stdin;
336
337	outfile = poptGetArg(pc);
338
339	if(outfile) {
340		out = fopen(outfile, "w+");
341		if(!out) {
342			perror("fopen");
343			fprintf(stderr, "Can't find %s, using stdout...\n", outfile);
344			return 1;
345		}
346	}
347
348	if(!outfile) out = stdout;
349
350	if(!hexformat)print_pcap_header(out);
351
352	while(!feof(in)) {
353		fgets(buffer, sizeof(buffer), in); line_num++;
354		if(buffer[0] == '[') { /* Header */
355			if(strstr(buffer, "show_msg")) {
356				in_packet++;
357				if(in_packet == 1)continue;
358				read_log_msg(in, &curpacket, &curpacket_len, &data_offset, &data_length);
359			} else if(in_packet && strstr(buffer, "dump_data")) {
360				data_bytes_read = read_log_data(in, curpacket+data_offset, data_length);
361			}  else {
362				if(in_packet){
363					if(hexformat) print_hex_packet(out, curpacket, curpacket_len);
364					else print_netbios_packet(out, curpacket, curpacket_len, data_bytes_read+data_offset);
365					free(curpacket);
366				}
367				in_packet = 0;
368			}
369		}
370	}
371
372	if (in != stdin) {
373		fclose(in);
374	}
375
376	if (out != stdout) {
377		fclose(out);
378	}
379
380	return 0;
381}
382