suricata
source-pcap-file-helper.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2016 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Danny Browning <danny.browning@protectwise.com>
22  *
23  * File based pcap packet acquisition support
24  */
25 
27 #include "util-checksum.h"
28 #include "util-profiling.h"
29 #include "source-pcap-file.h"
30 
31 extern int max_pending_packets;
33 
34 static void PcapFileCallbackLoop(char *user, struct pcap_pkthdr *h, u_char *pkt);
35 
37 {
38  if (pfv != NULL) {
39  if (pfv->pcap_handle != NULL) {
40  pcap_close(pfv->pcap_handle);
41  pfv->pcap_handle = NULL;
42  }
43  if (pfv->filename != NULL) {
44  if (pfv->shared != NULL && pfv->shared->should_delete) {
45  SCLogDebug("Deleting pcap file %s", pfv->filename);
46  if (unlink(pfv->filename) != 0) {
48  "Failed to delete %s", pfv->filename);
49  }
50  }
51  SCFree(pfv->filename);
52  pfv->filename = NULL;
53  }
54  pfv->shared = NULL;
55  SCFree(pfv);
56  }
57 }
58 
59 void PcapFileCallbackLoop(char *user, struct pcap_pkthdr *h, u_char *pkt)
60 {
61  SCEnter();
62 
63  PcapFileFileVars *ptv = (PcapFileFileVars *)user;
65 
66  if (unlikely(p == NULL)) {
67  SCReturn;
68  }
70 
72  p->ts.tv_sec = h->ts.tv_sec;
73  p->ts.tv_usec = h->ts.tv_usec;
74  SCLogDebug("p->ts.tv_sec %"PRIuMAX"", (uintmax_t)p->ts.tv_sec);
75  p->datalink = ptv->datalink;
76  p->pcap_cnt = ++pcap_g.cnt;
77 
78  p->pcap_v.tenant_id = ptv->shared->tenant_id;
79  ptv->shared->pkts++;
80  ptv->shared->bytes += h->caplen;
81 
82  if (unlikely(PacketCopyData(p, pkt, h->caplen))) {
83  TmqhOutputPacketpool(ptv->shared->tv, p);
85  SCReturn;
86  }
87 
88  /* We only check for checksum disable */
91  } else if (pcap_g.checksum_mode == CHECKSUM_VALIDATION_AUTO) {
93  SC_ATOMIC_GET(pcap_g.invalid_checksums))) {
96  }
97  }
98 
100 
101  if (TmThreadsSlotProcessPkt(ptv->shared->tv, ptv->shared->slot, p) != TM_ECODE_OK) {
102  pcap_breakloop(ptv->pcap_handle);
104  }
105 
106  SCReturn;
107 }
108 
109 char pcap_filename[PATH_MAX] = "unknown";
110 
111 const char *PcapFileGetFilename(void)
112 {
113  return pcap_filename;
114 }
115 
116 /**
117  * \brief Main PCAP file reading Loop function
118  */
120 {
121  SCEnter();
122 
123  int packet_q_len = 64;
124  int r;
125  TmEcode loop_result = TM_ECODE_OK;
127 
128  while (loop_result == TM_ECODE_OK) {
131  }
132 
133  /* make sure we have at least one packet in the packet pool, to prevent
134  * us from alloc'ing packets at line rate */
135  PacketPoolWait();
136 
137  /* Right now we just support reading packets one at a time. */
138  r = pcap_dispatch(ptv->pcap_handle, packet_q_len,
139  (pcap_handler)PcapFileCallbackLoop, (u_char *)ptv);
140  if (unlikely(r == -1)) {
141  SCLogError(SC_ERR_PCAP_DISPATCH, "error code %" PRId32 " %s for %s",
142  r, pcap_geterr(ptv->pcap_handle), ptv->filename);
143  if (ptv->shared->cb_result == TM_ECODE_FAILED) {
145  }
146  loop_result = TM_ECODE_DONE;
147  } else if (unlikely(r == 0)) {
148  SCLogInfo("pcap file %s end of file reached (pcap err code %" PRId32 ")",
149  ptv->filename, r);
150  ptv->shared->files++;
151  loop_result = TM_ECODE_DONE;
152  } else if (ptv->shared->cb_result == TM_ECODE_FAILED) {
154  "Pcap callback PcapFileCallbackLoop failed for %s", ptv->filename);
155  loop_result = TM_ECODE_FAILED;
156  }
158  }
159 
160  SCReturnInt(loop_result);
161 }
162 
164 {
165  char errbuf[PCAP_ERRBUF_SIZE] = "";
166 
167  if(unlikely(pfv->filename == NULL)) {
168  SCLogError(SC_ERR_INVALID_ARGUMENT, "Filename was null");
170  }
171 
172  pfv->pcap_handle = pcap_open_offline(pfv->filename, errbuf);
173  if (pfv->pcap_handle == NULL) {
174  SCLogError(SC_ERR_FOPEN, "%s", errbuf);
176  }
177 
178  if (pfv->shared != NULL && pfv->shared->bpf_string != NULL) {
179  SCLogInfo("using bpf-filter \"%s\"", pfv->shared->bpf_string);
180 
181  if (pcap_compile(pfv->pcap_handle, &pfv->filter, pfv->shared->bpf_string, 1, 0) < 0) {
182  SCLogError(SC_ERR_BPF, "bpf compilation error %s for %s",
183  pcap_geterr(pfv->pcap_handle), pfv->filename);
185  }
186 
187  if (pcap_setfilter(pfv->pcap_handle, &pfv->filter) < 0) {
188  SCLogError(SC_ERR_BPF,"could not set bpf filter %s for %s",
189  pcap_geterr(pfv->pcap_handle), pfv->filename);
190  pcap_freecode(&pfv->filter);
192  }
193  pcap_freecode(&pfv->filter);
194  }
195 
196  pfv->datalink = pcap_datalink(pfv->pcap_handle);
197  SCLogDebug("datalink %" PRId32 "", pfv->datalink);
198 
199  DecoderFunc temp;
200  TmEcode validated = ValidateLinkType(pfv->datalink, &temp);
201  SCReturnInt(validated);
202 }
203 
204 TmEcode ValidateLinkType(int datalink, DecoderFunc *decoder)
205 {
206  switch (datalink) {
207  case LINKTYPE_LINUX_SLL:
208  *decoder = DecodeSll;
209  break;
210  case LINKTYPE_ETHERNET:
211  *decoder = DecodeEthernet;
212  break;
213  case LINKTYPE_PPP:
214  *decoder = DecodePPP;
215  break;
216  case LINKTYPE_IPV4:
217  case LINKTYPE_RAW:
218  case LINKTYPE_RAW2:
220  *decoder = DecodeRaw;
221  break;
222  case LINKTYPE_NULL:
223  *decoder = DecodeNull;
224  break;
225 
226  default:
227  SCLogError(
229  "datalink type %" PRId32 " not (yet) supported in module PcapFile.",
230  datalink
231  );
233  }
234 
236 }
237 /* eof */
TmEcode InitPcapFile(PcapFileFileVars *pfv)
ChecksumValidationMode checksum_mode
int DecodePPP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len, PacketQueue *pq)
Definition: decode-ppp.c:43
void CleanupPcapFileFileVars(PcapFileFileVars *pfv)
#define SCLogDebug(...)
Definition: util-debug.h:335
int(* DecoderFunc)(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len, PacketQueue *pq)
Definition: decode.h:956
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
#define LINKTYPE_LINUX_SLL
Definition: decode.h:1075
PcapFileSharedVars * shared
#define unlikely(expr)
Definition: util-optimize.h:35
#define LINKTYPE_IPV4
Definition: decode.h:1081
int DecodeSll(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len, PacketQueue *pq)
Definition: decode-sll.c:39
int DecodeNull(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len, PacketQueue *pq)
Definition: decode-null.c:48
struct bpf_program filter
volatile uint8_t suricata_ctl_flags
Definition: suricata.c:201
uint64_t pcap_cnt
Definition: decode.h:562
Packet * PacketGetFromQueueOrAlloc(void)
Get a packet. We try to get a packet from the packetpool first, but if that is empty we alloc a packe...
Definition: decode.c:177
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1136
int ChecksumAutoModeCheck(uint64_t thread_count, uint64_t iface_count, uint64_t iface_fail)
Check if the number of invalid checksums indicate checksum offloading in place.
Definition: util-checksum.c:70
#define LINKTYPE_PPP
Definition: decode.h:1076
#define LINKTYPE_NULL
Definition: decode.h:1073
#define SURICATA_STOP
Definition: suricata.h:95
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
int max_pending_packets
Definition: suricata.c:215
int datalink
Definition: decode.h:575
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
#define PACKET_PROFILING_TMM_END(p, id)
TmEcode PcapFileDispatch(PcapFileFileVars *ptv)
Main PCAP file reading Loop function.
#define SCEnter(...)
Definition: util-debug.h:337
#define PACKET_PROFILING_TMM_START(p, id)
#define PKT_IGNORE_CHECKSUM
Definition: decode.h:1103
#define SCReturnInt(x)
Definition: util-debug.h:341
#define LINKTYPE_RAW
Definition: decode.h:1077
#define LINKTYPE_GRE_OVER_IP
Definition: decode.h:1082
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
void PacketPoolWait(void)
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
uint32_t tenant_id
Definition: source-pcap.h:37
#define SCFree(a)
Definition: util-mem.h:322
#define LINKTYPE_RAW2
Definition: decode.h:1080
char pcap_filename[PATH_MAX]
TmEcode ValidateLinkType(int datalink, DecoderFunc *decoder)
const char * PcapFileGetFilename(void)
#define StatsSyncCountersIfSignalled(tv)
Definition: counters.h:137
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:192
int DecodeRaw(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len, PacketQueue *pq)
Definition: decode-raw.c:46
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint32_t len, PacketQueue *pq)
int PacketCopyData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
Definition: decode.c:259
#define LINKTYPE_ETHERNET
Definition: decode.h:1074
#define SCReturn
Definition: util-debug.h:339
struct timeval ts
Definition: decode.h:452
PcapFileGlobalVars pcap_g
uint32_t flags
Definition: decode.h:444
PcapPacketVars pcap_v
Definition: decode.h:481