4
4
* program into the xt_bpf match.
5
5
*
6
6
* TEST:
7
- * ./run_cookie_uid_helper_example.sh
8
- * Then generate some traffic in variate ways. ping 0 -c 10 would work
9
- * but the cookie and uid in this case could both be 0. A sample output
10
- * with some traffic generated by web browser is shown below:
7
+ * ./run_cookie_uid_helper_example.sh -option
8
+ * option:
9
+ * -t: do traffic monitoring test, the program will continuously
10
+ * print out network traffic happens after program started A sample
11
+ * output is shown below:
11
12
*
12
13
* cookie: 877, uid: 0x3e8, Pakcet Count: 20, Bytes Count: 11058
13
14
* cookie: 132, uid: 0x0, Pakcet Count: 2, Bytes Count: 286
18
19
* cookie: 0, uid: 0x0, Pakcet Count: 6, Bytes Count: 712
19
20
* cookie: 880, uid: 0xfffe, Pakcet Count: 1, Bytes Count: 70
20
21
*
22
+ * -s: do getsockopt SO_COOKIE test, the program will set up a pair of
23
+ * UDP sockets and send packets between them. And read out the traffic data
24
+ * directly from the ebpf map based on the socket cookie.
25
+ *
21
26
* Clean up: if using shell script, the script file will delete the iptables
22
27
* rule and unmount the bpf program when exit. Else the iptables rule need
23
28
* to be deleted by hand, see run_cookie_uid_helper_example.sh for detail.
34
39
#include <limits.h>
35
40
#include <linux/bpf.h>
36
41
#include <linux/if_ether.h>
42
+ #include <net/if.h>
43
+ #include <signal.h>
37
44
#include <stdbool.h>
38
45
#include <stdint.h>
39
46
#include <stdio.h>
46
53
#include <bpf/bpf.h>
47
54
#include "libbpf.h"
48
55
56
+ #define PORT 8888
57
+
49
58
struct stats {
50
59
uint32_t uid ;
51
60
uint64_t packets ;
@@ -54,6 +63,8 @@ struct stats {
54
63
55
64
static int map_fd , prog_fd ;
56
65
66
+ static bool test_finish ;
67
+
57
68
static void maps_create (void )
58
69
{
59
70
map_fd = bpf_create_map (BPF_MAP_TYPE_HASH , sizeof (uint32_t ),
@@ -164,7 +175,7 @@ static void prog_attach_iptables(char *file)
164
175
printf ("file path too long: %s\n" , file );
165
176
exit (1 );
166
177
}
167
- sprintf (rules , "iptables -A INPUT -m bpf --object-pinned %s -j ACCEPT" ,
178
+ sprintf (rules , "iptables -A OUTPUT -m bpf --object-pinned %s -j ACCEPT" ,
168
179
file );
169
180
ret = system (rules );
170
181
if (ret < 0 ) {
@@ -177,7 +188,8 @@ static void print_table(void)
177
188
{
178
189
struct stats curEntry ;
179
190
uint32_t curN = UINT32_MAX ;
180
- uint32_t nextN , res ;
191
+ uint32_t nextN ;
192
+ int res ;
181
193
182
194
while (bpf_map_get_next_key (map_fd , & curN , & nextN ) > -1 ) {
183
195
curN = nextN ;
@@ -193,25 +205,117 @@ static void print_table(void)
193
205
}
194
206
}
195
207
196
- int main ( int argc , char * argv [] )
208
+ static void udp_client ( void )
197
209
{
198
- if (argc > 2 ) {
199
- printf ("Too many argument provided\n" );
200
- return 1 ;
201
- } else if (argc < 2 ) {
202
- printf ("Usage: %s bpfObjName\n" , argv [0 ]);
203
- return 1 ;
210
+ struct sockaddr_in si_other = {0 };
211
+ struct sockaddr_in si_me = {0 };
212
+ struct stats dataEntry ;
213
+ int s_rcv , s_send , i , recv_len ;
214
+ char message = 'a' ;
215
+ char buf ;
216
+ uint64_t cookie ;
217
+ int res ;
218
+ socklen_t cookie_len = sizeof (cookie );
219
+ socklen_t slen = sizeof (si_other );
220
+
221
+ s_rcv = socket (PF_INET , SOCK_DGRAM , 0 );
222
+ if (s_rcv < 0 )
223
+ error (1 , errno , "rcv socket creat failed!\n" );
224
+ si_other .sin_family = AF_INET ;
225
+ si_other .sin_port = htons (PORT );
226
+ if (inet_aton ("127.0.0.1" , & si_other .sin_addr ) == 0 )
227
+ error (1 , errno , "inet_aton\n" );
228
+ if (bind (s_rcv , (struct sockaddr * )& si_other , sizeof (si_other )) == -1 )
229
+ error (1 , errno , "bind\n" );
230
+ s_send = socket (PF_INET , SOCK_DGRAM , 0 );
231
+ if (s_send < 0 )
232
+ error (1 , errno , "send socket creat failed!\n" );
233
+ res = getsockopt (s_send , SOL_SOCKET , SO_COOKIE , & cookie , & cookie_len );
234
+ if (res < 0 )
235
+ printf ("get cookie failed: %s\n" , strerror (errno ));
236
+ res = bpf_map_lookup_elem (map_fd , & cookie , & dataEntry );
237
+ if (res != -1 )
238
+ error (1 , errno , "socket stat found while flow not active\n" );
239
+ for (i = 0 ; i < 10 ; i ++ ) {
240
+ res = sendto (s_send , & message , sizeof (message ), 0 ,
241
+ (struct sockaddr * )& si_other , slen );
242
+ if (res == -1 )
243
+ error (1 , errno , "send\n" );
244
+ if (res != sizeof (message ))
245
+ error (1 , 0 , "%uB != %luB\n" , res , sizeof (message ));
246
+ recv_len = recvfrom (s_rcv , & buf , sizeof (buf ), 0 ,
247
+ (struct sockaddr * )& si_me , & slen );
248
+ if (recv_len < 0 )
249
+ error (1 , errno , "revieve\n" );
250
+ res = memcmp (& (si_other .sin_addr ), & (si_me .sin_addr ),
251
+ sizeof (si_me .sin_addr ));
252
+ if (res != 0 )
253
+ error (1 , EFAULT , "sender addr error: %d\n" , res );
254
+ printf ("Message received: %c\n" , buf );
255
+ res = bpf_map_lookup_elem (map_fd , & cookie , & dataEntry );
256
+ if (res < 0 )
257
+ error (1 , errno , "lookup sk stat failed, cookie: %lu\n" ,
258
+ cookie );
259
+ printf ("cookie: %lu, uid: 0x%x, Packet Count: %lu,"
260
+ " Bytes Count: %lu\n\n" , cookie , dataEntry .uid ,
261
+ dataEntry .packets , dataEntry .bytes );
204
262
}
263
+ close (s_send );
264
+ close (s_rcv );
265
+ }
205
266
206
- maps_create ();
207
- prog_load ();
208
- prog_attach_iptables (argv [1 ]);
267
+ static int usage (void )
268
+ {
269
+ printf ("Usage: ./run_cookie_uid_helper_example.sh"
270
+ " bpfObjName -option\n"
271
+ " -t traffic monitor test\n"
272
+ " -s getsockopt cookie test\n" );
273
+ return 1 ;
274
+ }
209
275
210
- while (true) {
211
- print_table ();
212
- printf ("\n" );
213
- sleep (1 );
214
- };
276
+ void finish (int ret )
277
+ {
278
+ test_finish = true;
279
+ }
280
+
281
+ int main (int argc , char * argv [])
282
+ {
283
+ int opt ;
284
+ bool cfg_test_traffic = false;
285
+ bool cfg_test_cookie = false;
286
+
287
+ if (argc != 3 )
288
+ return usage ();
289
+ while ((opt = getopt (argc , argv , "ts" )) != -1 ) {
290
+ switch (opt ) {
291
+ case 't' :
292
+ cfg_test_traffic = true;
293
+ break ;
294
+ case 's' :
295
+ cfg_test_cookie = true;
296
+ break ;
215
297
298
+ default :
299
+ printf ("unknown option %c\n" , opt );
300
+ usage ();
301
+ return -1 ;
302
+ }
303
+ }
304
+ maps_create ();
305
+ prog_load ();
306
+ prog_attach_iptables (argv [2 ]);
307
+ if (cfg_test_traffic ) {
308
+ if (signal (SIGINT , finish ) == SIG_ERR )
309
+ error (1 , errno , "register handler failed" );
310
+ while (!test_finish ) {
311
+ print_table ();
312
+ printf ("\n" );
313
+ sleep (1 );
314
+ };
315
+ } else if (cfg_test_cookie ) {
316
+ udp_client ();
317
+ }
318
+ close (prog_fd );
319
+ close (map_fd );
216
320
return 0 ;
217
321
}
0 commit comments