📄 tcpdump.c
字号:
#include <config.h>#include <stdlib.h>#include <sys/mman.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <firestorm.h>#include <plugin.h>#include <packet.h>#include <cleanup.h>#include <args.h>#include <alert.h>#include <signature.h>#include <decode.h>#include <capture.h>#include <args.h>PLUGIN_STD_DEFS();#ifndef lib_pcap_h#define pcap_file_header tcpd_file_headerstruct 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;};#define pcap_pkthdr tcpd_pkthdrstruct tcpd_pkthdr { struct timeval ts; unsigned int caplen; unsigned int len;};#endif /* lib_pcap_h */proc_args_parse args_parse;proc_decode_subproto decode_subproto;proc_serial_number serial_number;struct { char *name; unsigned int magic; int size; int swap;}magics[]={ {"standard", 0xa1b2c3d4, 16, 0}, {"redhat", 0xa1b2cd34, 24, 0}, {"byte-swapped standard", 0xd4c3b2a1, 16, 1}, {"byte-swapped redhat", 0x34cdb2a1, 24, 1}, {NULL, 0, 0}};/* This is our own private data */struct tcpd_priv { struct packet pkt; void *end; void *cur; int swap; unsigned int phsiz; struct proto *protocol; void *map; unsigned int map_size; int fd; size_t snaplen; unsigned int (*r32)(unsigned int);};int cb_file(struct arg *, void *);struct arg tcpd_args[]={ {"file",ARGTYPE_STRING,cb_file}, {NULL,ARGTYPE_NOP,NULL}};unsigned int read32(unsigned int x){return x;}unsigned int read32_swap(unsigned int x){return bswap32(x);}int cb_file(struct arg *a, void *priv){ struct stat st; struct tcpd_priv *p=priv; struct pcap_file_header *fh; int i; if ( !p ) return 0; if ( p->fd > -1 ) { mesg(M_ERR,"tcpdump: Can't capture from more than one file"); return 0; } /* Interface for us is just the filename */ if ( (p->fd=open(a->val.v_str, O_RDONLY)) < 0 ) { mesg(M_ERR,"tcpdump: %s: open(): %s", a->val.v_str, get_err()); return 0; } /* get the size of the file so we can map it in */ if ( fstat(p->fd, &st) ) { mesg(M_ERR,"tcpdump: %s: fstat(): %s", a->val.v_str, get_err()); close(p->fd); return 0; } /* Check the file is actually even big enough */ if ( st.st_size < sizeof(struct pcap_file_header) ) { mesg(M_ERR,"tcpdump: %s: Not a valid libpcap file", a->val.v_str); close(p->fd); return 0; } /* Memory map that sucker */ p->map_size=st.st_size; if ( (p->map=mmap(NULL, p->map_size, PROT_READ, MAP_SHARED, p->fd, 0))==MAP_FAILED) { mesg(M_ERR,"tcpdump: %s: mmap(): %s", a->val.v_str, get_err()); close(p->fd); return 0; } p->end=p->map+st.st_size; fh=(struct pcap_file_header *)p->map; /* Check what format the file is */ for(p->phsiz=i=0; magics[i].name; i++) { if ( fh->magic==magics[i].magic ) { if ( magics[i].swap ) { p->r32=read32_swap; }else{ p->r32=read32; } p->phsiz=magics[i].size; p->snaplen=p->r32(fh->snaplen); mesg(M_INFO,"tcpdump: %s: %s: snaplen=%u", a->val.v_str, magics[i].name, p->snaplen); break; } } if ( !p->phsiz ) { mesg(M_ERR,"tcpdump: %s: Bad voodoo magic (0x%x)", a->val.v_str, fh->magic); munmap(p->map, p->map_size); close(p->fd); return 0; } /* Make sure we can decode this link type, not much point * carrying on if we can't decode anything ;) */ if ( !(p->protocol=decode_subproto("__pcap_dlt", p->r32(fh->linktype))) ) { mesg(M_ERR,"tcpdump: %s: Unknown link type (0x%x)", a->val.v_str, p->r32(fh->linktype)); munmap(p->map, p->map_size); close(p->fd); return 0; } return 1;}/* Initialise a capture process, we open the file and then * return our opaque private data structure to firestorm */void *tcpd_init(char *args){ struct tcpd_priv *p=NULL; if ( !args ) return NULL; if ( !(p=malloc(sizeof(*p))) ) return NULL; p->fd = -1; switch ( args_parse(tcpd_args, args, p) ) { case -1: mesg(M_ERR,"tcpdump: parse error: %s", args); case 0: /* fall through */ free(p); p=NULL; return NULL; default: break; } /* Initialise final few fields from header */ p->cur=p->map; p->cur+=sizeof(struct pcap_file_header); return p;}/* Stop the capture and cleanup our process */void tcpd_end(void *priv){ struct tcpd_priv *p=priv; if ( !p ) return; if ( p->map ) munmap(p->map, p->map_size); if ( p->fd>=0 ) close(p->fd); free(p);}void tcpd_go(void *priv, struct capture *c){ struct pcap_pkthdr *h; struct tcpd_priv *p=priv; if ( !p ) return; p->pkt.capture=c; p->pkt.flags=FP_PROMISC; while(c->state == CAP_STATE_CAPTURE) { /* Make sure a packet header is present */ if ( p->cur+p->phsiz > p->end ) { c->state=CAP_STATE_STOP; return; } /* Advance the p->cur to be the start of the * actual packet data */ h=(struct pcap_pkthdr *)p->cur; p->cur+=p->phsiz; /* Check the packet is present */ if ( (p->cur+p->r32(h->caplen)) > (p->end) ) { c->state=CAP_STATE_STOP; return; } /* Fill in the struct packet stuff */ p->pkt.time.tv_sec=p->r32(h->ts.tv_sec); p->pkt.time.tv_usec=p->r32(h->ts.tv_usec); p->pkt.len=p->r32(h->len); p->pkt.caplen=p->r32(h->caplen); p->pkt.base=p->cur; p->pkt.end=p->cur+p->pkt.caplen; /* advance the file pointer */ p->cur+=p->pkt.caplen; /* Dispatch to the firestorm decode engine */ p->pkt.layer[0].proto=p->protocol; p->pkt.layer[0].h.raw=p->pkt.base; p->pkt.layer[0].flags=0; p->pkt.layer[0].session=NULL; p->pkt.llen=0; serial_number(&p->pkt.serial); p->protocol->decode(&p->pkt); }}struct capdev tcpdump_cap={ .name="tcpdump", .init=tcpd_init, .end=tcpd_end, .go=tcpd_go,};int PLUGIN_CAPDEV (struct capture_api *c){ object_check(c); serial_number=c->serial_number; decode_subproto=c->decode_subproto; args_parse=c->args_parse; if ( !c->capdev_add(&tcpdump_cap) ) return PLUGIN_ERR_FAIL; return PLUGIN_ERR_OK;}int PLUGIN_INIT (struct plugin_in *in, struct plugin_out *out){ /* validate input */ plugin_check(in, out); /* tell firestorm who we are */ PLUGIN_ID("capture.tcpdump", "Reads packets in from tcpdump files"); PLUGIN_VERSION(2, 0); PLUGIN_AUTHOR("Gianni Tedesco", "gianni@scaramanga.co.uk"); PLUGIN_LICENSE("GPL"); return PLUGIN_ERR_OK;}int PLUGIN_UNLOAD (int code) { return PLUGIN_ERR_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -