📄 dump.c
字号:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <string.h>#include <ctype.h>#include <firestorm.h>#include <packet.h>#include <args.h>#include <cleanup.h>#include <alert.h>#include <signature.h>#include <decode.h>#include <target.h>#include <plugin.h>#include <capture.h>#include <config.h>#ifdef HAVE_SYS_UIO_H#include <sys/uio.h>#endifPLUGIN_STD_DEFS();#define MAGIC_LBL 0xa1b2c3d4/* Imported functions */proc_args_parse args_parse;proc_decode_proto decode_proto;/* pcap protocol */struct proto *pcap_dlt=NULL;/* If we don't have libpcap */#ifndef lib_pcap_h#define pcap_file_header tcpd_file_header#define pcap_pkthdr tcpd_pkthdr#define PCAP_VERSION_MAJOR 2#define PCAP_VERSION_MINOR 4struct tcpd_file_header{ unsigned int magic; unsigned short version_major; unsigned short version_minor; int thiszone; unsigned int sigfigs; unsigned int snaplen; unsigned int linktype;};struct tcpd_pkthdr { struct timeval ts; unsigned int caplen; unsigned int len;};#endifstruct dump_priv { struct proto *proto; unsigned int hdr; int fd; char *fn; unsigned int id;};/* Arguments */int cb_proto(struct arg *, void *);int cb_file(struct arg *, void *);struct arg dump_args[]={ {"proto", ARGTYPE_STRING, cb_proto}, {"file", ARGTYPE_STRING, cb_file}, {NULL,ARGTYPE_NOP,NULL}};/* Target information */int dump_a(struct generator *, struct packet *, struct alert*, void *);int dump_v(char *, void **);void dump_h(void *);void dump_c(void *);struct target alert_t[]={ target_init("dump", dump_a, dump_v, dump_h, dump_c), target_null()};struct proto_child *find_proto(struct packet *pkt){ struct proto_child *c; unsigned int i; /* Find the first layer in the packet which * contains a protocol usable by libpcap */ for(i=0; i<pkt->llen; i++) { for(c=pcap_dlt->children; c; c=c->next) { if ( pkt->layer[i].proto==c->proto ) { return c; } } } return NULL;}int cb_proto(struct arg *a, void *priv){ struct proto_child *c; struct dump_priv *p=priv; if ( !p || !a->val.v_str ) return 0; if ( p->proto ) { mesg(M_ERR,"dump: You already specified a protocol!"); return 0; } /* Lookup a valid pcap protocol by name */ for(c=pcap_dlt->children; c; c=c->next) { if ( !strcmp(a->val.v_str, c->proto->name) ) { p->proto=c->proto; p->id=c->id; return 1; } } mesg(M_ERR,"dump: couldn't find libpcap protocol for '%s'", a->val.v_str); return 0;}int dump_openfile(struct dump_priv *p){ if ( (p->fd=open(p->fn, O_RDWR|O_CREAT, 00640))<0 ) { mesg(M_ERR,"dump: %s: open(): %s", p->fn, get_err()); return 0; } return 1;}int cb_file(struct arg *a, void *priv){ struct dump_priv *p=priv; if ( !p ) return 0; if ( p->fd>=0 ) { mesg(M_ERR,"dump: You already specified a file!"); return 0; } if ( (p->fn=strdup(a->val.v_str))==NULL ) { mesg(M_ERR,"ascii: strdup: %s", get_err()); return 0; } return 1;}/* Actually write the file header to the file */int dump_fheader(struct dump_priv *priv){ struct dump_priv *p=priv; struct pcap_file_header fh; fh.magic=MAGIC_LBL; fh.version_major=PCAP_VERSION_MAJOR; fh.version_minor=PCAP_VERSION_MINOR; fh.thiszone=0; fh.sigfigs=0; fh.snaplen=65535; fh.linktype=p->id; if (write(p->fd, &fh, sizeof(fh)) < sizeof(fh)) { mesg(M_CRIT,"dump: write(): %s", get_err()); return 2; } return 1;}/* FIXME: This could be structured much better */int dump_a(struct generator *gen, struct packet *pkt, struct alert *a, void *priv){ struct dump_priv *p=priv; struct proto_child *c; struct pcap_pkthdr ph; unsigned int ofs; unsigned int layer; struct iovec iov[2]; if ( !pkt ) return 0; if ( p->proto && p->hdr==1 ) goto fast_path; /* The file is most likely corrupt by this point */ if ( p->hdr==2 ) { mesg(M_CRIT,"dump: warning: alert not recorded, " "previous I/O errors."); return 0; } /* Try find a protocol in order to write the * pcap header */ if ( !p->proto ) { if ( (c=find_proto(pkt)) ) { p->proto=c->proto; p->id=c->id; mesg(M_INFO,"dump: dumping in '%s' format (%u)", p->proto->name, p->id); }else{ mesg(M_CRIT,"dump: warning: alert not recorded, " "no suitable protocol."); return 1; } } /* If we haven't already written our header * then do so */ if ( !p->hdr ) { if ( (p->hdr=dump_fheader(p))==2 ) return 0; }fast_path: /* Find where to start dumping from */ for(layer=0; layer<pkt->llen; layer++) { if ( pkt->layer[layer].proto == p->proto ) { goto dump_packet; } } mesg(M_CRIT,"dump: warning: alert not recorded, " "no suitable protocol."); return 1;dump_packet: /* Figure out how far in to the packet * our first byte of data is */ ofs=(unsigned int)(pkt->layer[layer].h.raw-pkt->base); /* Fill in the packet header */ ph.caplen=pkt->caplen-ofs; ph.len=pkt->len-ofs; ph.ts.tv_sec=pkt->time.tv_sec; ph.ts.tv_usec=pkt->time.tv_usec; /* Fill in the vectors */ iov[0].iov_base=&ph; iov[0].iov_len=sizeof(ph); iov[1].iov_base=pkt->base+ofs; iov[1].iov_len=ph.caplen; /* We can write two vectors at once, w00t! */ if ( writev(p->fd, iov, 2) < (iov[0].iov_len+iov[1].iov_len) ) { mesg(M_CRIT,"dump: writev(): %s", get_err()); p->hdr=2; return 0; } return 1;}/* Check file header and decide what to do */int dump_cheader(struct dump_priv *priv){ struct dump_priv *p=priv; struct pcap_file_header fh; struct proto_child *c=NULL; int read_result; read_result=read(p->fd, &fh, sizeof(fh)); if ( read_result == -1) { mesg(M_ERR,"dump: read(): %s", get_err()); goto err; } /* This case has to be before the next, * else empty files become invalid */ if ( read_result == 0 ) return 1; /* Check the header */ if ( ( read_result < sizeof(fh) ) || ( fh.magic != MAGIC_LBL) ) { mesg(M_ERR,"dump: bad voodoo magic!"); goto err; } /* Magic was valid, check proto id */ for(c=pcap_dlt->children; c; c=c->next) { if ( fh.linktype==c->id ) { p->proto=c->proto; p->id=c->id; p->hdr=1; mesg(M_INFO,"dump: Logging in '%s' format", p->proto->name); if ( lseek(p->fd, 0, SEEK_END)<0 ) { mesg(M_ERR,"dump: lseek(): %s", get_err()); goto err; } return 1; } } mesg(M_ERR,"dump: existing file has unknown " "protocol (%u) - wimping out", fh.linktype);err: close(p->fd); free(p); return 0;}int dump_v(char *args, void **ptr){ struct dump_priv *p=NULL; if ( !args ) return 0; if ( !(p=calloc(1, sizeof(*p))) ) { return 0; } p->fd=-1; switch ( args_parse(dump_args, args, p) ) { case -1: mesg(M_ERR,"dump: parse error: %s", args); case 0: /* fall through */ if ( p->fd>=0 ) close(p->fd); free(p); return 0; default: break; } if (!dump_openfile(p)) { free(p); return 0; } *ptr=p; return dump_cheader(p);}void dump_h(void *priv){ struct dump_priv *p=priv; if ( !p ) return; if ( fsync(p->fd) ) mesg(M_CRIT,"dump: fsync(): %s", get_err()); if ( close(p->fd) ) mesg(M_CRIT,"dump: close(): %s", get_err()); if ( !dump_openfile(p) ) { mesg(M_CRIT,"dump: error reopening logfile"); return; } p->hdr=0;}void dump_c(void *priv){ struct dump_priv *p=priv; if ( !p ) return; /* We wan't to warn the user if the whole file * didn't get written right for whatever reason */ if ( fsync(p->fd) ) mesg(M_CRIT,"dump: fsync(): %s", get_err()); if ( close(p->fd) ) mesg(M_CRIT,"dump: close(): %s -- " "stop using NFS you muppet", get_err()); free(p);}int PLUGIN_TARGET (struct target_api *t){ object_check(t); args_parse=t->args_parse; if ( !(pcap_dlt=decode_proto("__pcap_dlt")) ) return PLUGIN_ERR_FAIL; if ( !t->target_add(alert_t) ) return PLUGIN_ERR_FAIL; return PLUGIN_ERR_OK;} int PLUGIN_INIT (struct plugin_in *in, struct plugin_out *out){ plugin_check(in, out); PLUGIN_ID("target.dump", "Log to a tcpdump file"); PLUGIN_VERSION(1,0); PLUGIN_AUTHOR("Gianni Tedesco", "gianni@scaramanga.co.uk"); PLUGIN_LICENSE("GPL"); if ( !(decode_proto=in->import("decode.proto")) ) { return PLUGIN_ERR_OBJECT; } return PLUGIN_ERR_OK;}int PLUGIN_UNLOAD (int code) { return PLUGIN_ERR_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -