1 /*
2 ** Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 ** Copyright (C) 2002-2013 Sourcefire, Inc.
4 ** Author(s): Ron Dempster <rdempste@cisco.com>
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License Version 2 as
8 ** published by the Free Software Foundation. You may not use, modify or
9 ** distribute this program under any other version of the GNU General
10 ** Public License.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software
19 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #include <assert.h>
27 #include <stdint.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <pcap.h>
31 #include <sfbpf.h>
32
33 #include "snort.h"
34 #include "dump.h"
35 #include "util.h"
36
37 uint16_t packet_dump_address_space_id;
38 volatile pcap_dumper_t* packet_dump_file = NULL;
39 pcap_t* packet_dump_pcap = NULL;
40 volatile int packet_dump_stop;
41 struct sfbpf_program packet_dump_fcode;
42
PacketDumpClose(void)43 void PacketDumpClose(void)
44 {
45 if (packet_dump_file)
46 {
47 pcap_dump_close((pcap_dumper_t*)packet_dump_file);
48 packet_dump_file = NULL;
49 pcap_close(packet_dump_pcap);
50 packet_dump_pcap = NULL;
51 sfbpf_freecode(&packet_dump_fcode);
52 LogMessage("Stopped packet dump\n");
53 }
54 packet_dump_stop = 0;
55 }
56
PacketDumpStop(void)57 static int PacketDumpStop(void)
58 {
59 if (packet_dump_file)
60 {
61 int i;
62
63 packet_dump_stop = 1;
64 for (i = 5; 0 < i; i--)
65 {
66 if (!packet_dump_stop)
67 break;
68 sleep(1);
69 }
70 return packet_dump_stop;
71 }
72 return 0;
73 }
74
PacketDumpCommand(uint16_t type,const uint8_t * data,uint32_t length,void ** new_config,char * statusBuf,int statusBuf_len)75 int PacketDumpCommand(uint16_t type, const uint8_t *data, uint32_t length, void **new_config,
76 char *statusBuf, int statusBuf_len)
77 {
78 if (!length)
79 PacketDumpStop();
80 else
81 {
82 const char* p;
83 const char* end;
84 const char* fname;
85 char fileName[PATH_MAX];
86 char *filter;
87
88 if (PacketDumpStop())
89 {
90 WarningMessage("Failed to stop the previous packet dump\n");
91 return 1;
92 }
93
94 if (sizeof(packet_dump_address_space_id) > length)
95 {
96 WarningMessage("Invalid packet dump message length\n");
97 return 1;
98 }
99 packet_dump_address_space_id = *(const uint16_t*)data;
100 data += sizeof(packet_dump_address_space_id);
101 length -= sizeof(packet_dump_address_space_id);
102
103 fname = (const char*)data;
104 end = fname + length;
105 for (p = fname; p < end && *p && (isalnum(*p) || *p == '/' || *p == '.' || *p == '-' || *p == '_'); p++);
106 if (p >= end || *p)
107 {
108 WarningMessage("Invalid packet dump file name\n");
109 return 1;
110 }
111
112 p++;
113 if (p >= end || *(end - 1))
114 {
115 WarningMessage("Invalid packet dump BPF\n");
116 return 1;
117 }
118 filter = strdup(p);
119 if (!filter)
120 {
121 WarningMessage("Couldn't allocate memory for the packet dump filter string\n");
122 return 1;
123 }
124 memset(&packet_dump_fcode, 0, sizeof(packet_dump_fcode));
125 if (sfbpf_compile(65535, DLT_EN10MB, &packet_dump_fcode, filter, 1, 0) < 0)
126 {
127 free(filter);
128 WarningMessage("Packet dump BPF state machine compilation failed\n");
129 return 1;
130 }
131 free(filter);
132 if (!sfbpf_validate(packet_dump_fcode.bf_insns, packet_dump_fcode.bf_len))
133 {
134 WarningMessage("Packet dump BPF state machine validation failed\n");
135 return 1;
136 }
137
138 if (!(packet_dump_pcap = pcap_open_dead(DLT_EN10MB, 65535)))
139 {
140 WarningMessage("Packet dump failed to open a pcap instance\n");
141 return 1;
142 }
143 snprintf(fileName, sizeof(fileName), "%s.%u", fname, (unsigned)(snort_conf->event_log_id >> 16));
144 if (!(packet_dump_file = pcap_dump_open(packet_dump_pcap, fileName)))
145 {
146 pcap_close(packet_dump_pcap);
147 packet_dump_pcap = NULL;
148 WarningMessage("Packet dump failed to open the pcap file\n");
149 return 1;
150 }
151
152 LogMessage("Opened %s for packet dump of address space ID %u with filter (%s)\n",
153 fileName, (unsigned)packet_dump_address_space_id, p);
154 }
155 return 0;
156 }
157
158
159