Line data Source code
1 : /* SPDX-License-Identifier: GPL-2.0-only */
2 : /*
3 : * Copyright (c) 2022 Meta Platforms, Inc. and affiliates.
4 : */
5 :
6 : #include "cgen/matcher/udp.h"
7 :
8 : #include <linux/bpf.h>
9 : #include <linux/bpf_common.h>
10 : #include <linux/in.h> // NOLINT
11 : #include <linux/udp.h>
12 :
13 : #include <endian.h>
14 : #include <errno.h>
15 : #include <stddef.h>
16 : #include <stdint.h>
17 :
18 : #include <bpfilter/logger.h>
19 : #include <bpfilter/matcher.h>
20 :
21 : #include "cgen/program.h"
22 : #include "filter.h"
23 :
24 0 : static int _bf_matcher_generate_udp_port(struct bf_program *program,
25 : const struct bf_matcher *matcher)
26 : {
27 0 : uint16_t *port = (uint16_t *)bf_matcher_payload(matcher);
28 0 : size_t offset = bf_matcher_get_type(matcher) == BF_MATCHER_UDP_SPORT ?
29 0 : offsetof(struct udphdr, source) :
30 : offsetof(struct udphdr, dest);
31 :
32 0 : EMIT(program, BPF_LDX_MEM(BPF_H, BPF_REG_1, BPF_REG_6, offset));
33 :
34 0 : switch (bf_matcher_get_op(matcher)) {
35 0 : case BF_MATCHER_EQ:
36 0 : EMIT_FIXUP_JMP_NEXT_RULE(
37 : program, BPF_JMP_IMM(BPF_JNE, BPF_REG_1, htobe16(*port), 0));
38 0 : break;
39 0 : case BF_MATCHER_NE:
40 0 : EMIT_FIXUP_JMP_NEXT_RULE(
41 : program, BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, htobe16(*port), 0));
42 0 : break;
43 0 : case BF_MATCHER_RANGE:
44 : /* Convert the big-endian value stored in the packet into a
45 : * little-endian value for x86 and arm before comparing it to the
46 : * reference value. This is a JLT/JGT comparison, we need to have the
47 : * MSB where the machine expects then. */
48 0 : EMIT(program, BPF_BSWAP(BPF_REG_1, 16));
49 0 : EMIT_FIXUP_JMP_NEXT_RULE(program,
50 : BPF_JMP_IMM(BPF_JLT, BPF_REG_1, port[0], 0));
51 0 : EMIT_FIXUP_JMP_NEXT_RULE(program,
52 : BPF_JMP_IMM(BPF_JGT, BPF_REG_1, port[1], 0));
53 0 : break;
54 0 : default:
55 0 : return bf_err_r(-EINVAL, "unknown matcher operator '%s' (%d)",
56 : bf_matcher_op_to_str(bf_matcher_get_op(matcher)),
57 : bf_matcher_get_op(matcher));
58 : }
59 :
60 : return 0;
61 : }
62 :
63 0 : int bf_matcher_generate_udp(struct bf_program *program,
64 : const struct bf_matcher *matcher)
65 : {
66 : int r;
67 :
68 0 : EMIT_FIXUP_JMP_NEXT_RULE(program,
69 : BPF_JMP_IMM(BPF_JNE, BPF_REG_8, IPPROTO_UDP, 0));
70 0 : EMIT(program,
71 : BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_10, BF_PROG_CTX_OFF(l4_hdr)));
72 :
73 0 : switch (bf_matcher_get_type(matcher)) {
74 0 : case BF_MATCHER_UDP_SPORT:
75 : case BF_MATCHER_UDP_DPORT:
76 0 : r = _bf_matcher_generate_udp_port(program, matcher);
77 : break;
78 0 : default:
79 0 : return bf_err_r(-EINVAL, "unknown matcher type %d",
80 : bf_matcher_get_type(matcher));
81 : };
82 :
83 0 : return r;
84 : }
|