0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <stdio.h>
0018 #include <unistd.h>
0019 #include <assert.h>
0020 #include <linux/bpf.h>
0021 #include <string.h>
0022 #include <stdlib.h>
0023 #include <errno.h>
0024 #include <sys/socket.h>
0025 #include <arpa/inet.h>
0026 #include <linux/if_ether.h>
0027 #include <linux/ip.h>
0028 #include <stddef.h>
0029 #include <bpf/bpf.h>
0030 #include "bpf_insn.h"
0031 #include "sock_example.h"
0032 #include "bpf_util.h"
0033
0034 char bpf_log_buf[BPF_LOG_BUF_SIZE];
0035
0036 static int test_sock(void)
0037 {
0038 int sock = -1, map_fd, prog_fd, i, key;
0039 long long value = 0, tcp_cnt, udp_cnt, icmp_cnt;
0040
0041 map_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, sizeof(key), sizeof(value),
0042 256, NULL);
0043 if (map_fd < 0) {
0044 printf("failed to create map '%s'\n", strerror(errno));
0045 goto cleanup;
0046 }
0047
0048 struct bpf_insn prog[] = {
0049 BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
0050 BPF_LD_ABS(BPF_B, ETH_HLEN + offsetof(struct iphdr, protocol) ),
0051 BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4),
0052 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
0053 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4),
0054 BPF_LD_MAP_FD(BPF_REG_1, map_fd),
0055 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
0056 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
0057 BPF_MOV64_IMM(BPF_REG_1, 1),
0058 BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_0, BPF_REG_1, 0),
0059 BPF_MOV64_IMM(BPF_REG_0, 0),
0060 BPF_EXIT_INSN(),
0061 };
0062 size_t insns_cnt = ARRAY_SIZE(prog);
0063 LIBBPF_OPTS(bpf_prog_load_opts, opts,
0064 .log_buf = bpf_log_buf,
0065 .log_size = BPF_LOG_BUF_SIZE,
0066 );
0067
0068 prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL",
0069 prog, insns_cnt, &opts);
0070 if (prog_fd < 0) {
0071 printf("failed to load prog '%s'\n", strerror(errno));
0072 goto cleanup;
0073 }
0074
0075 sock = open_raw_sock("lo");
0076
0077 if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd,
0078 sizeof(prog_fd)) < 0) {
0079 printf("setsockopt %s\n", strerror(errno));
0080 goto cleanup;
0081 }
0082
0083 for (i = 0; i < 10; i++) {
0084 key = IPPROTO_TCP;
0085 assert(bpf_map_lookup_elem(map_fd, &key, &tcp_cnt) == 0);
0086
0087 key = IPPROTO_UDP;
0088 assert(bpf_map_lookup_elem(map_fd, &key, &udp_cnt) == 0);
0089
0090 key = IPPROTO_ICMP;
0091 assert(bpf_map_lookup_elem(map_fd, &key, &icmp_cnt) == 0);
0092
0093 printf("TCP %lld UDP %lld ICMP %lld packets\n",
0094 tcp_cnt, udp_cnt, icmp_cnt);
0095 sleep(1);
0096 }
0097
0098 cleanup:
0099
0100 return 0;
0101 }
0102
0103 int main(void)
0104 {
0105 FILE *f;
0106
0107 f = popen("ping -4 -c5 localhost", "r");
0108 (void)f;
0109
0110 return test_sock();
0111 }