bRAWcap 1.1.0
b-plus Technologies - Ethernet Performance Transmitter Receiver
Loading...
Searching...
No Matches
11_filter_bpf_f.c

This example shows how bRAWcap can be used to filter (discard) specific packets by using a BPF (Berkley Packet Filter).

1/**
2 * @file 11_filter_bpf_f.c
3 *
4 * @brief bRAWcap Example - Demonstrates how to filter received packets by using a BPF filter string.
5 *
6 * It shows how to:
7 * - Open a handle to the first available adapter
8 * - Create and apply a BPF filter
9 * - Read the receive statistics
10 *
11 * This example makes use of C only.
12 *
13 * @version 1.0
14 *
15 * @date 2025-10-08
16 *
17 * HISTORY:
18 * - 2025-10-08: Initial version
19 *
20 * @copyright
21 * <b> © 2021 - b-plus technologies GmbH. All rights reserved!</b>
22 *
23 * All rights exclusively reserved for b-plus GmbH, unless expressly otherwise agreed.
24 *
25 * Redistribution in source or any other form, with or without modification, is not permitted.
26 *
27 * You may use this code under the according license terms of b-plus.
28 * Please contact b-plus at services@b-plus.com to get the appropriate terms and conditions.
29 */
30// Include bRAWcap
31#include "libbrawcap.h"
32
33// C STD
34#include <stdlib.h> // for strtol
35#include <stdio.h> // for printf
36#include <time.h> // for printing time info
37
38// Check command line parameters if a custom execution time is specified
39// To configure a custom execution time use "-t numberOfSeconds"
40// To configure a BPF filter string use "-f filterString"
41#if 1
42void ParseArgs(int argc, char** argv, int* exec_time, const char** filter_string)
43{
44 int i = 1;
45 while(i < argc)
46 {
47 if(strcmp(argv[i], "-t") == 0 && (i + 1) < argc)
48 {
49 char* pEnd = 0;
50 *exec_time = strtol(argv[i + 1], &pEnd, 0);
51 i += 2;
52 }
53 else if (strcmp(argv[i], "-f") == 0 && (i + 1) < argc)
54 {
55 *filter_string = argv[i + 1];
56 i += 2;
57 }
58 else
59 {
60 i++;
61 }
62 }
63}
64#endif
65
66int main(int argc, char** argv)
67{
68 // Set console title
69 SetConsoleTitleA("bRAWcap Example - BPF Filtering");
70
71 // Some generic helper locals...
72 int retVal = 0;
73 unsigned char demoModeLogged = 0;
74 unsigned long long packetCounter = 0;
75 int exec_time = 300; // 5 minutes
76 int runtime_sec = clock() / CLOCKS_PER_SEC;
77 const char* filter_string = "udp port 1900"; // Default BPF filter for SSDP packets
78
79 // Parse command line argument, to check for user specified execution time
80 ParseArgs(argc, argv, &exec_time, &filter_string);
81
82 // Here we will store the status of any bRAWcap function
84
85 // Here we store the number of available bRAWcap adapters
86 brawcap_adapter_count_t numberAdapters = 0;
87 // This will contain our bRAWcap handle to the adapter we want to receive from
88 brawcap_handle_t* pHandle = 0;
89 // Our local filter to configure which packets should be dropped
90 brawcap_filter_t* pFilter = 0;
91 // Our local packet for storing received data
92 brawcap_packet_t* pPacket = 0;
93
94 do
95 {
96 // First check if we have any bRAWcap adapters available.
97 // --> This function can only fail if we did something wrong.
98 // But we are sure that we did everything right...
99 // therefore we do not check it´s status.
100 brawcap_adapter_list_count(&numberAdapters);
101
102 // No adapters... nothing do receive from... lets exit ...
103 if (!numberAdapters)
104 {
105 printf("[WARNING] No bRAWcap adapter available... Will stop now.");
106 break;
107 }
108
109 // Get the name of the first adapter.
110 // To not overload the example with complex stuff,
111 // we always go for the first available adapter.
112 brawcap_adapter_name_t name = { '\0' };
114 {
115 printf("[ERROR] Unexpected status while retrieving adapter name: %d", brawcap_last_status());
116 retVal = -1;
117 break;
118 }
119
120 // Create a filter object where to store our filter settings
122 {
123 printf("[ERROR] Unexpected status while creating the filter: %d", brawcap_last_status());
124 retVal = -1;
125 break;
126 }
127
128 // Set the BPF filter
129 printf("[INFO] Using BPF filter: \"%s\"\n", filter_string);
130 if (!BRAWCAP_SUCCESS(brawcap_filter_bpf_set(pFilter, filter_string)))
131 {
132 printf("[ERROR] Unexpected status while setting BPF filter: %d", brawcap_last_status());
134 {
135 const char* compile_error = 0;
136 // Get the BPF compile error message, to check what is wrong with the filter string.
137 brawcap_filter_bpf_compile_error_get(pFilter, compile_error);
138 if (compile_error)
139 {
140 printf("[ERROR] BPF compile error: %s\n", compile_error);
141 }
142 }
143 retVal = -1;
144 break;
145 }
146
147 // Because we want to discard matched packets - do not forward to network stack -
148 // we set the filter indication to false
149 brawcap_filter_indicate_set(pFilter, 0);
150
151 // Set the filter to active
153
154 // Open a handle to the adapter by using the retrieved name.
155 if (!BRAWCAP_SUCCESS(brawcap_open(name, &pHandle)))
156 {
157 printf("[ERROR] Unexpected status while opening handle: %d", brawcap_last_status());
158 retVal = -1;
159 break;
160 }
161
162 // Now lets apply the filter to our opened handle
163 if(!BRAWCAP_SUCCESS(brawcap_rx_filter_set(pHandle, pFilter)))
164 {
165 printf("[ERROR] Unexpected status while applying the filter: %d", brawcap_last_status());
166 retVal = -1;
167 break;
168 }
169
170 // Because we do not want to process the packets somehow and just filter them.
171 // we can also reduce the drivers receive queue size for this handle to zero.
172 // With this setting the driver doesn´t even try to buffer those packets.
174 {
175 printf("[ERROR] Unexpected status while reducing driver queue size: %d", brawcap_last_status());
176 retVal = -1;
177 break;
178 }
179
180 // Create a packet object
181 // For simplicity and to make sure that we get all packets,
182 // we set the payload size to the max supported value.
184 {
185 printf("[ERROR] Unexpected status while creating packet: %d", brawcap_last_status());
186 retVal = -1;
187 break;
188 }
189
190 // Some local variables to buffer the packet data, later on.
191 brawcap_packet_size_t captureLength = 0;
192 brawcap_packet_size_t lengthOnWire = 0;
193 brawcap_timestamp_t* pTimestamp = 0;
194 UINT64 timestamp_sec = 0;
195 UINT32 timestamp_ns = 0;
196 const unsigned char* pPayload = 0;
197
198 // Our receive loop, we stay in here until we should stop receiving.
199 while (runtime_sec < exec_time)
200 {
201 // Now lets see if we have received a packet...
202 status = brawcap_rx_packet(pHandle, pPacket);
203
204 // Seems like we had success and got some packet data to look at. :-)
205 if (BRAWCAP_SUCCESS(status))
206 {
207 // Check if we made it out of the demo limitation... :-D
208 // ... notify the user and go ahead with receiving.
209 if (demoModeLogged)
210 {
211 printf("[NOTICE] DEMO MODE: Limitation period elapsed, receiving is available again.\n");
212 demoModeLogged = 0;
213 }
214
215 // --> The bRAWcap functions below can only fail if we did something wrong.
216 // But we are sure that we did everything right...
217 // therefore we do not check their status.
218 brawcap_packet_length_on_wire_get(pPacket, &lengthOnWire);
219 brawcap_packet_payload_get_v2(pPacket, &pPayload, &captureLength);
220 brawcap_packet_timestamp_get(pPacket, &pTimestamp);
221 brawcap_timestamp_value_ns_get(pTimestamp, &timestamp_sec, &timestamp_ns);
222
223 // Show the user what we received
224 printf("%llu. Packet:\n", ++packetCounter);
225 printf(" - Capture Length: %04u Bytes\n", captureLength);
226 printf(" - Length On Wire: %04u Bytes\n", lengthOnWire);
227 printf(" - Timestamp: %llu %09u ns\n", timestamp_sec, timestamp_ns);
228 printf(" - Payload: ");
229 // Do some nice formatting stuff, to improve readability...
230 UINT32 byteCounter = 1;
231 for (const unsigned char* pByte = pPayload; byteCounter <= captureLength; ++byteCounter)
232 {
233 printf("%02X ", (unsigned char)*pByte++);
234 if (!(byteCounter % 16)) printf("\n ");
235 else if (!(byteCounter % 8)) printf(" ");
236 }
237 printf("\n\n");
238 }
239 // Hm... we got a very silent connection...
240 // ... lets try again...
241 else if (status == BRAWCAP_STATUS_INFO_NO_DATA)
242 continue;
243 // Sad but we do not have a bRAWcap license for this feature... yet. :-(
244 // Notify our user about this sad information and
245 // wait some time to check if we are allowed to receive again...
246 else if (status == BRAWCAP_STATUS_WARNING_DEMO_MODE)
247 {
248 if (!demoModeLogged)
249 {
250 demoModeLogged = 1;
251 printf("[WARNING] DEMO MODE: Receiving not available.\n");
252 }
253 Sleep(1000);
254 }
255 // Ok... Something strange happened here... :-O
256 // Better stop now if we do not know how to handle it.
257 else
258 {
259 printf("[ERROR] Unexpected status while receiving packet: %d", brawcap_last_status());
260 retVal = -1;
261 break;
262 }
263 runtime_sec = (clock() / CLOCKS_PER_SEC - runtime_sec);
264 }
265 }while(0);
266
267 // We do not want to produce any memory leaks...
268 // ... so always cleanup what we have created
269 // --> The functions here can only fail if we did something wrong.
270 // But we are sure that we did everything right...
271 // therefore we do not check their status.
272 if (pHandle)
273 brawcap_close(pHandle);
274 if(pFilter)
275 brawcap_filter_free(pFilter);
276
277 return retVal;
278}
bRAWcap main header.
struct _brawcap_handle brawcap_handle_t
A bRAWcap handle.
Definition: brawcap_types_um.h:184
brawcap_status_t brawcap_close(brawcap_handle_t *pHandle)
Closes the specified bRAWcap handle.
brawcap_status_t brawcap_open(const brawcap_adapter_name_t name, brawcap_handle_t **const pHandle)
Opens a new bRAWcap handle on the adapter, specified by it´s name.
brawcap_status_t brawcap_last_status()
Reads the last status appeared in bRAWcap, for the calling thread.
brawcap_status_t
bRAWcap status/return codes.
Definition: brawcap_types_shared.h:140
#define BRAWCAP_SUCCESS(status)
Checks if the returned status indicates a success with no additional info.
Definition: brawcap_types_shared.h:112
@ BRAWCAP_STATUS_SUCCESS
Definition: brawcap_types_shared.h:142
@ BRAWCAP_STATUS_INFO_NO_DATA
Indicates that a function returns without any data.
Definition: brawcap_types_shared.h:329
@ BRAWCAP_STATUS_ERROR_BPF_COMPILE_FAILED
Indicates that the BPF filter compilation failed.
Definition: brawcap_types_shared.h:241
@ BRAWCAP_STATUS_WARNING_DEMO_MODE
The operation was not executed due to demo mode limitations.
Definition: brawcap_types_shared.h:252
struct _brawcap_timestamp brawcap_timestamp_t
bRAWcap timestamp object.
Definition: brawcap_types_shared.h:608
brawcap_status_t brawcap_timestamp_value_ns_get(brawcap_timestamp_t *const pTimestamp, UINT64 *const pSeconds, UINT32 *const pNanoseconds)
Reads out the timestamp value in seconds and nanoseconds.
UINT16 brawcap_packet_size_t
Type for handling the number of payload bytes per packet.
Definition: brawcap_types_shared.h:666
brawcap_status_t brawcap_packet_create(brawcap_packet_t **const pPacket, const brawcap_packet_size_t maxSize)
Creates a new packet.
struct _brawcap_packet brawcap_packet_t
bRAWcap packet object.
Definition: brawcap_types_shared.h:675
brawcap_status_t brawcap_packet_payload_get_v2(brawcap_packet_t *const pPacket, const unsigned char **const pPayload, brawcap_packet_size_t *const pLength)
Reads out the payload of the specified packet.
#define BRAWCAP_PACKET_SIZE_MAX
The maximum supported (byte) size for a single packet payload.
Definition: brawcap_types_shared.h:645
brawcap_status_t brawcap_packet_length_on_wire_get(brawcap_packet_t *const pPacket, brawcap_packet_size_t *const pLengthOnWire)
Reads out the length on wire of the specified packet. This value is especially useful for received pa...
brawcap_status_t brawcap_packet_timestamp_get(brawcap_packet_t *const pPacket, brawcap_timestamp_t **const pTimestamp)
Reads out the timestamp object for the specified packet.
brawcap_status_t brawcap_adapter_list_at(const brawcap_adapter_count_t index, brawcap_adapter_name_t name)
Reads out the adapter name of the adapter at the adapter list index.
brawcap_status_t brawcap_adapter_list_count(brawcap_adapter_count_t *const pCount)
Reads out the current number of supported adapters in the adapter list.
char brawcap_adapter_name_t[BRAWCAP_ADAPTER_NAME_LENGTH]
Fixed size array containing a adapter name.
Definition: brawcap_types_um.h:301
UINT8 brawcap_adapter_count_t
Type used for counting the available/supported adapters on a machine.
Definition: brawcap_types_um.h:286
brawcap_status_t brawcap_rx_packet(brawcap_handle_t *const pHandle, brawcap_packet_t *const pPacket)
Receives a single packet from the specified handle.
brawcap_status_t brawcap_rx_driver_queue_size_set(brawcap_handle_t *const pHandle, const brawcap_queue_size_t size)
Sets the driver queue size (in number of packets) for the specified handle.
brawcap_status_t brawcap_rx_filter_set(brawcap_handle_t *const pHandle, const brawcap_filter_t *const pFilter)
Sets the specified filter to the specified handle.
brawcap_status_t brawcap_filter_create(brawcap_filter_t **const pFilter, const brawcap_filter_type_t type)
Creates a new filter.
struct _brawcap_filter brawcap_filter_t
bRAWcap filter object.
Definition: brawcap_types_shared.h:959
brawcap_status_t brawcap_filter_free(brawcap_filter_t *pFilter)
Frees the specified filter. When this function is called the given filter becomes invalid and it´s me...
brawcap_status_t brawcap_filter_bpf_set(brawcap_filter_t *const pFilter, const char *const filterString)
Sets the BPF filter string for the specified filter.
brawcap_status_t brawcap_filter_indicate_set(brawcap_filter_t *const pFilter, const BOOLEAN indicate)
Specifies if packets which matched the specified filter should be indicated to the network stack.
brawcap_status_t brawcap_filter_activate(brawcap_filter_t *const pFilter)
Sets the specified filter to active.
brawcap_status_t brawcap_filter_bpf_compile_error_get(brawcap_filter_t *const pFilter, const char *pError)
Retrieves the BPF compile error message from the specified filter.
@ BRAWCAP_FILTER_TYPE_BPF
A Berkley Packet Filter.
Definition: brawcap_types_shared.h:946