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);
175  if (!RunModeUnixSocketIsActive()) {
177  } else {
180  }
181  }
182 
183  if (pfv->shared != NULL && pfv->shared->bpf_string != NULL) {
184  SCLogInfo("using bpf-filter \"%s\"", pfv->shared->bpf_string);
185 
186  if (pcap_compile(pfv->pcap_handle, &pfv->filter, pfv->shared->bpf_string, 1, 0) < 0) {
187  SCLogError(SC_ERR_BPF, "bpf compilation error %s for %s",
188  pcap_geterr(pfv->pcap_handle), pfv->filename);
190  }
191 
192  if (pcap_setfilter(pfv->pcap_handle, &pfv->filter) < 0) {
193  SCLogError(SC_ERR_BPF,"could not set bpf filter %s for %s",
194  pcap_geterr(pfv->pcap_handle), pfv->filename);
196  }
197  }
198 
199  pfv->datalink = pcap_datalink(pfv->pcap_handle);
200  SCLogDebug("datalink %" PRId32 "", pfv->datalink);
201 
202  Decoder temp;
203  TmEcode validated = ValidateLinkType(pfv->datalink, &temp);
204  SCReturnInt(validated);
205 }
206 
207 TmEcode ValidateLinkType(int datalink, Decoder *decoder)
208 {
209  switch (datalink) {
210  case LINKTYPE_LINUX_SLL:
211  *decoder = DecodeSll;
212  break;
213  case LINKTYPE_ETHERNET:
214  *decoder = DecodeEthernet;
215  break;
216  case LINKTYPE_PPP:
217  *decoder = DecodePPP;
218  break;
219  case LINKTYPE_IPV4:
220  case LINKTYPE_RAW:
221  case LINKTYPE_RAW2:
223  *decoder = DecodeRaw;
224  break;
225  case LINKTYPE_NULL:
226  *decoder = DecodeNull;
227  break;
228 
229  default:
230  SCLogError(
232  "datalink type %" PRId32 " not (yet) supported in module PcapFile.",
233  datalink
234  );
236  }
237 
239 }
240 /* eof */
TmEcode InitPcapFile(PcapFileFileVars *pfv)
ChecksumValidationMode checksum_mode
void CleanupPcapFileFileVars(PcapFileFileVars *pfv)
#define SCLogDebug(...)
Definition: util-debug.h:335
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
#define LINKTYPE_LINUX_SLL
Definition: decode.h:1082
int DecodePPP(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
Definition: decode-ppp.c:43
PcapFileSharedVars * shared
#define unlikely(expr)
Definition: util-optimize.h:35
int DecodeRaw(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
Definition: decode-raw.c:46
#define LINKTYPE_IPV4
Definition: decode.h:1088
struct bpf_program filter
volatile uint8_t suricata_ctl_flags
Definition: suricata.c:201
uint64_t pcap_cnt
Definition: decode.h:566
int DecodeNull(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
Definition: decode-null.c:48
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:176
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1143
int(* Decoder)(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint32_t, PacketQueue *)
#define LINKTYPE_PPP
Definition: decode.h:1083
#define LINKTYPE_NULL
Definition: decode.h:1080
#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:579
int RunModeUnixSocketIsActive(void)
int DecodeEthernet(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
#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:1110
#define SCReturnInt(x)
Definition: util-debug.h:341
#define LINKTYPE_RAW
Definition: decode.h:1084
#define LINKTYPE_GRE_OVER_IP
Definition: decode.h:1089
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
int DecodeSll(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, uint32_t len, PacketQueue *pq)
Definition: decode-sll.c:39
void PacketPoolWait(void)
int ChecksumAutoModeCheck(uint32_t thread_count, unsigned int iface_count, unsigned int iface_fail)
Check if the number of invalid checksums indicate checksum offloading in place.
Definition: util-checksum.c:70
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
uint32_t tenant_id
Definition: source-pcap.h:42
#define SCFree(a)
Definition: util-mem.h:236
#define LINKTYPE_RAW2
Definition: decode.h:1087
char pcap_filename[PATH_MAX]
const char * PcapFileGetFilename(void)
#define StatsSyncCountersIfSignalled(tv)
Definition: counters.h:136
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:193
#define LINKTYPE_ETHERNET
Definition: decode.h:1081
#define SCReturn
Definition: util-debug.h:339
struct timeval ts
Definition: decode.h:450
TmEcode UnixSocketPcapFile(TmEcode tm, struct timespec *last_processed)
PcapFileGlobalVars pcap_g
uint32_t flags
Definition: decode.h:442
TmEcode ValidateLinkType(int datalink, Decoder *decoder)
PcapPacketVars pcap_v
Definition: decode.h:483
int PacketCopyData(Packet *p, uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
Definition: decode.c:258