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