utils/log2pcaphex.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    Utility to extract pcap files from samba (log level 10) log files
00004 
00005    Copyright (C) Jelmer Vernooij 2003
00006    Thanks to Tim Potter for the genial idea
00007 
00008    Portions (from capconvert.c) (C) Andrew Tridgell 1997
00009    Portions (from text2pcap.c) (C) Ashok Narayanan 2001
00010 
00011    Example use with -h parameter: 
00012         log2pcaphex < samba-log-file | text2pcap -T 139,139 - foo.pcap
00013 
00014    TODO: Have correct IP and TCP checksums.
00015 
00016    This program is free software; you can redistribute it and/or modify
00017    it under the terms of the GNU General Public License as published by
00018    the Free Software Foundation; either version 2 of the License, or
00019    (at your option) any later version.
00020 
00021    This program is distributed in the hope that it will be useful,
00022    but WITHOUT ANY WARRANTY; without even the implied warranty of
00023    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024    GNU General Public License for more details.
00025 
00026    You should have received a copy of the GNU General Public License
00027    along with this program; if not, write to the Free Software
00028    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00029 */
00030 
00031 #include "includes.h"
00032 
00033 /* We don't care about the paranoid malloc checker in this standalone
00034    program */
00035 #undef malloc
00036 
00037 #include <assert.h>
00038 
00039 int quiet = 0;
00040 int hexformat = 0;
00041 
00042 #define itoa(a) ((a) < 0xa?'0'+(a):'A' + (a-0xa))
00043 
00044 #include <stdlib.h>
00045 #include <unistd.h>
00046 #include <sys/time.h>
00047 #include <stdio.h>
00048 #include <fcntl.h>
00049 
00050 #define TCPDUMP_MAGIC 0xa1b2c3d4
00051 
00052 /* tcpdump file format */
00053 struct tcpdump_file_header {
00054         uint32 magic;
00055         uint16 major;
00056         uint16 minor;
00057         int32 zone;
00058         uint32 sigfigs;
00059         uint32 snaplen;
00060         uint32 linktype;
00061 };
00062 
00063 struct tcpdump_packet {
00064         struct timeval ts;
00065         uint32 caplen;
00066         uint32 len;
00067 };
00068 
00069 typedef struct {
00070     uint8  ver_hdrlen;
00071     uint8  dscp;
00072     uint16 packet_length;
00073     uint16 identification;
00074     uint8  flags;
00075     uint8  fragment;
00076     uint8  ttl;
00077     uint8  protocol;
00078     uint16 hdr_checksum;
00079     uint32 src_addr;
00080     uint32 dest_addr;
00081 } hdr_ip_t;
00082 
00083 static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 6, 0, 0x01010101, 0x02020202};
00084 
00085 typedef struct {
00086     uint16 source_port;
00087     uint16 dest_port;
00088     uint32 seq_num;
00089     uint32 ack_num;
00090     uint8  hdr_length;
00091     uint8  flags;
00092     uint16 window;
00093     uint16 checksum;
00094     uint16 urg;
00095 } hdr_tcp_t;
00096 
00097 static hdr_tcp_t HDR_TCP = {139, 139, 0, 0, 0x50, 0, 0, 0, 0};
00098 
00099 static void print_pcap_header(FILE *out)
00100 {
00101         struct tcpdump_file_header h;
00102         h.magic = TCPDUMP_MAGIC;
00103         h.major = 2;
00104         h.minor = 4;
00105         h.zone = 0;
00106         h.sigfigs = 0;
00107         h.snaplen = 102400; /* As long packets as possible */
00108         h.linktype = 101; /* Raw IP */
00109         fwrite(&h, sizeof(struct tcpdump_file_header), 1, out);
00110 }
00111 
00112 static void print_pcap_packet(FILE *out, unsigned char *data, long length, long caplen)
00113 {
00114         static int i = 0;
00115         struct tcpdump_packet p;
00116         i++;
00117         p.ts.tv_usec = 0;
00118         p.ts.tv_sec = 0;
00119         p.caplen = caplen;
00120         p.len = length;
00121         fwrite(&p, sizeof(struct tcpdump_packet), 1, out);
00122         fwrite(data, sizeof(unsigned char), caplen, out);
00123 }
00124 
00125 static void print_hex_packet(FILE *out, unsigned char *data, long length)
00126 {
00127         long i,cur = 0;
00128         while(cur < length) {
00129                 fprintf(out, "%06lX ", cur);
00130                 for(i = cur; i < length && i < cur + 16; i++) {
00131                         fprintf(out, "%02x ", data[i]);
00132                 }
00133         
00134                 cur = i;
00135                 fprintf(out, "\n");
00136         }
00137 }
00138 
00139 static void print_netbios_packet(FILE *out, unsigned char *data, long length, long actual_length)
00140 {       
00141         unsigned char *newdata; long offset = 0;
00142         long newlen;
00143         
00144         newlen = length+sizeof(HDR_IP)+sizeof(HDR_TCP);
00145         newdata = (unsigned char *)malloc(newlen);
00146 
00147         HDR_IP.packet_length = htons(newlen);
00148         HDR_TCP.window = htons(0x2000);
00149         HDR_TCP.source_port = HDR_TCP.dest_port = htons(139);
00150 
00151         memcpy(newdata+offset, &HDR_IP, sizeof(HDR_IP));offset+=sizeof(HDR_IP);
00152         memcpy(newdata+offset, &HDR_TCP, sizeof(HDR_TCP));offset+=sizeof(HDR_TCP);
00153         memcpy(newdata+offset,data,length);
00154         
00155         print_pcap_packet(out, newdata, newlen, actual_length+offset);
00156         free(newdata);
00157 }
00158 
00159 unsigned char *curpacket = NULL;
00160 long curpacket_len = 0;
00161 
00162 static void read_log_msg(FILE *in, unsigned char **_buffer, long *buffersize, long *data_offset, long *data_length)
00163 {
00164         unsigned char *buffer;
00165         int tmp; long i;
00166         assert(fscanf(in, " size=%ld\n", buffersize));
00167         *buffersize+=4; /* for netbios */
00168         buffer = (unsigned char *)malloc(*buffersize);
00169         memset(buffer, 0, *buffersize);
00170         /* NetBIOS */
00171         buffer[0] = 0x00;
00172         buffer[1] = 0x00;
00173         memcpy(buffer+2, &buffersize, 2);
00174         buffer[4] = 0xFF;
00175         buffer[5] = 'S';
00176         buffer[6] = 'M';
00177         buffer[7] = 'B';
00178         assert(fscanf(in, "  smb_com=0x%x\n", &tmp)); buffer[smb_com] = tmp;
00179         assert(fscanf(in, "  smb_rcls=%d\n", &tmp)); buffer[smb_rcls] = tmp;
00180         assert(fscanf(in, "  smb_reh=%d\n", &tmp)); buffer[smb_reh] = tmp;
00181         assert(fscanf(in, "  smb_err=%d\n", &tmp)); memcpy(buffer+smb_err, &tmp, 2);
00182         assert(fscanf(in, "  smb_flg=%d\n", &tmp)); buffer[smb_flg] = tmp;
00183         assert(fscanf(in, "  smb_flg2=%d\n", &tmp)); memcpy(buffer+smb_flg2, &tmp, 2);
00184         assert(fscanf(in, "  smb_tid=%d\n", &tmp)); memcpy(buffer+smb_tid, &tmp, 2);
00185         assert(fscanf(in, "  smb_pid=%d\n", &tmp)); memcpy(buffer+smb_pid, &tmp, 2);
00186         assert(fscanf(in, "  smb_uid=%d\n", &tmp)); memcpy(buffer+smb_uid, &tmp, 2);
00187         assert(fscanf(in, "  smb_mid=%d\n", &tmp)); memcpy(buffer+smb_mid, &tmp, 2);
00188         assert(fscanf(in, "  smt_wct=%d\n", &tmp)); buffer[smb_wct] = tmp;
00189         for(i = 0; i < buffer[smb_wct]; i++) {
00190                 assert(fscanf(in, "  smb_vwv[%*2d]=%*5d (0x%X)\n", &tmp));
00191                 memcpy(buffer+smb_vwv+i*2, &tmp, 2);
00192         }
00193 
00194         *data_offset = smb_vwv+buffer[smb_wct]*2;
00195         assert(fscanf(in, "  smb_bcc=%ld\n", data_length)); buffer[(*data_offset)] = *data_length;
00196         (*data_offset)+=2;
00197         *_buffer = buffer;
00198 }
00199 
00200 static long read_log_data(FILE *in, unsigned char *buffer, long data_length)
00201 {
00202         long i, addr; char real[2][16]; int ret;
00203         unsigned int tmp;
00204         for(i = 0; i < data_length; i++) {
00205                 if(i % 16 == 0){
00206                         if(i != 0) { /* Read data after each line */
00207                                 assert(fscanf(in, "%8s %8s", real[0], real[1]) == 2);
00208                         }
00209                         ret = fscanf(in, "  [%03lX]", &addr);
00210                         if(!ret) {
00211                                 if(!quiet)fprintf(stderr, "Only first %ld bytes are logged, packet trace will be incomplete\nTry a higher log level\n", i);
00212                                 return i-1;
00213                         }
00214                         assert(addr == i);
00215                 }
00216                 if(!fscanf(in, "%02X", &tmp)) {
00217                         if(!quiet)fprintf(stderr, "Only first %ld bytes are logged, packet trace will be incomplete\nTry a higher log level\n", i-1);
00218                         return i-1;
00219                 }
00220                 buffer[i] = tmp;
00221         }
00222         return data_length;
00223 }
00224 
00225 int main (int argc, char **argv)
00226 {
00227         const char *infile, *outfile;
00228         FILE *out, *in;
00229         int opt;
00230         poptContext pc;
00231         char buffer[4096];
00232         long data_offset, data_length;
00233         long data_bytes_read = 0;
00234         int in_packet = 0;
00235         struct poptOption long_options[] = {
00236                 POPT_AUTOHELP
00237                 { "quiet", 'q', POPT_ARG_NONE, &quiet, 0, "Be quiet, don't output warnings" },
00238                 { "hex", 'h', POPT_ARG_NONE, &hexformat, 0, "Output format readable by text2pcap" },
00239                 POPT_TABLEEND
00240         };
00241         
00242         pc = poptGetContext(NULL, argc, (const char **) argv, long_options,
00243                             POPT_CONTEXT_KEEP_FIRST);
00244         poptSetOtherOptionHelp(pc, "[<infile> [<outfile>]]");
00245         
00246         
00247         while((opt = poptGetNextOpt(pc)) != -1) {
00248                 switch (opt) {
00249                 }
00250         }
00251 
00252         poptGetArg(pc); /* Drop argv[0], the program name */
00253 
00254         infile = poptGetArg(pc);
00255 
00256         if(infile) {
00257                 in  = fopen(infile, "r");
00258                 if(!in) {
00259                         perror("fopen");
00260                         return 1;
00261                 }
00262         } else in = stdin;
00263         
00264         outfile = poptGetArg(pc);
00265 
00266         if(outfile) {
00267                 out = fopen(outfile, "w+");
00268                 if(!out) { 
00269                         perror("fopen"); 
00270                         fprintf(stderr, "Can't find %s, using stdout...\n", outfile);
00271                 }
00272         }
00273 
00274         if(!outfile) out = stdout;
00275 
00276         if(!hexformat)print_pcap_header(out);
00277 
00278         while(!feof(in)) {
00279                 fgets(buffer, sizeof(buffer), in);
00280                 if(buffer[0] == '[') { /* Header */
00281                         if(strstr(buffer, "show_msg")) {
00282                                 in_packet++;
00283                                 if(in_packet == 1)continue;
00284                                 read_log_msg(in, &curpacket, &curpacket_len, &data_offset, &data_length);
00285                         } else if(in_packet && strstr(buffer, "dump_data")) {
00286                                 data_bytes_read = read_log_data(in, curpacket+data_offset, data_length);
00287                         }  else { 
00288                                 if(in_packet){ 
00289                                         if(hexformat) print_hex_packet(out, curpacket, curpacket_len); 
00290                                         else print_netbios_packet(out, curpacket, curpacket_len, data_bytes_read+data_offset);
00291                                         free(curpacket); 
00292                                 }
00293                                 in_packet = 0;
00294                         }
00295                 } 
00296         }
00297 
00298         return 0;
00299 }

Sambaに対してSat Aug 29 21:23:28 2009に生成されました。  doxygen 1.4.7