1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #ifndef NET_FIREWALL_EVENT_H
16 #define NET_FIREWALL_EVENT_H
17
18 #include "netfirewall_types.h"
19 #include "netfirewall_event_map.h"
20
21 /**
22 * @brief output event to ring buffer for user polling
23 *
24 * @param type enum event_type
25 * @param data event data
26 * @param len event data len
27 */
output_to_user(enum event_type type,void * data,__u32 len)28 static __always_inline void output_to_user(enum event_type type, void *data, __u32 len)
29 {
30 if (data && len > 0) {
31 struct event *e = bpf_ringbuf_reserve(&EVENT_MAP, sizeof(struct event), 0);
32 if (!e) {
33 return;
34 }
35
36 e->type = type;
37 e->len = len;
38
39 switch (type) {
40 case EVENT_DEBUG:
41 memcpy(&(e->debug), data, len);
42 break;
43 case EVENT_INTERCEPT:
44 memcpy(&(e->intercept), data, len);
45 break;
46 case EVENT_TUPLE_DEBUG:
47 memcpy(&(e->tuple), data, len);
48 break;
49 default:
50 break;
51 }
52
53 bpf_ringbuf_submit(e, 0);
54 }
55 }
56
57 /**
58 * @brief send intercept info to ring buffer for user polling
59 *
60 * @param tuple struct match_tuple
61 */
log_intercept(struct match_tuple * tuple)62 static __always_inline void log_intercept(struct match_tuple *tuple)
63 {
64 if (!tuple) {
65 return;
66 }
67
68 struct intercept_event ev = {
69 .dir = tuple->dir,
70 .family = tuple->family,
71 .protocol = tuple->protocol,
72 .sport = tuple->sport,
73 .dport = tuple->dport,
74 .appuid = tuple->appuid,
75 };
76
77 if (AF_INET == tuple->family) {
78 ev.ipv4.saddr = tuple->ipv4.saddr;
79 ev.ipv4.daddr = tuple->ipv4.daddr;
80 } else if (AF_INET6 == tuple->family) {
81 ev.ipv6.saddr = tuple->ipv6.saddr;
82 ev.ipv6.daddr = tuple->ipv6.daddr;
83 }
84 output_to_user(EVENT_INTERCEPT, &ev, sizeof(struct intercept_event));
85 }
86
87 #if NET_FIREWALL_DEBUG_TUPLE
88 /**
89 * @brief send match tuple to ring buffer for user polling
90 *
91 * @param tuple struct match_tuple
92 */
log_tuple(struct match_tuple * tuple)93 static __always_inline void log_tuple(struct match_tuple *tuple)
94 {
95 if (!tuple) {
96 return;
97 }
98
99 output_to_user(EVENT_TUPLE_DEBUG, tuple, sizeof(struct match_tuple));
100 }
101
102 #else // NET_FIREWALL_DEBUG_TUPLE
103
104 #define log_tuple(tuple)
105
106 #endif // NET_FIREWALL_DEBUG_TUPLE
107
108 #if NET_FIREWALL_DEBUG
log_dbg_any(enum debug_type type,__u32 arg1)109 static __always_inline void log_dbg_any(enum debug_type type, __u32 arg1)
110 {
111 struct debug_event ev = {
112 .type = type,
113 .arg1 = arg1,
114 };
115
116 output_to_user(EVENT_DEBUG, &ev, sizeof(struct debug_event));
117 }
118
log_dbg(enum debug_type type,enum stream_dir dir,__u32 arg1)119 static __always_inline void log_dbg(enum debug_type type, enum stream_dir dir, __u32 arg1)
120 {
121 struct debug_event ev = {
122 .type = type,
123 .dir = dir,
124 .arg1 = arg1,
125 };
126
127 output_to_user(EVENT_DEBUG, &ev, sizeof(struct debug_event));
128 }
129
log_dbg2(enum debug_type type,enum stream_dir dir,__u32 arg1,__u32 arg2)130 static __always_inline void log_dbg2(enum debug_type type, enum stream_dir dir, __u32 arg1, __u32 arg2)
131 {
132 struct debug_event ev = {
133 .type = type,
134 .dir = dir,
135 .arg1 = arg1,
136 .arg2 = arg2,
137 };
138
139 output_to_user(EVENT_DEBUG, &ev, sizeof(struct debug_event));
140 }
141
log_dbg3(enum debug_type type,enum stream_dir dir,__u32 arg1,__u32 arg2,__u32 arg3)142 static __always_inline void log_dbg3(enum debug_type type, enum stream_dir dir, __u32 arg1, __u32 arg2, __u32 arg3)
143 {
144 struct debug_event ev = {
145 .type = type,
146 .dir = dir,
147 .arg1 = arg1,
148 .arg2 = arg2,
149 .arg3 = arg3,
150 };
151
152 output_to_user(EVENT_DEBUG, &ev, sizeof(struct debug_event));
153 }
154
log_dbg4(enum debug_type type,enum stream_dir dir,__u32 arg1,__u32 arg2,__u32 arg3,__u32 arg4)155 static __always_inline void log_dbg4(enum debug_type type, enum stream_dir dir, __u32 arg1, __u32 arg2, __u32 arg3,
156 __u32 arg4)
157 {
158 struct debug_event ev = {
159 .type = type,
160 .dir = dir,
161 .arg1 = arg1,
162 .arg2 = arg2,
163 .arg3 = arg3,
164 .arg4 = arg4,
165 };
166
167 output_to_user(EVENT_DEBUG, &ev, sizeof(struct debug_event));
168 }
169
log_dbg5(enum debug_type type,enum stream_dir dir,__u32 arg1,__u32 arg2,__u32 arg3,__u32 arg4,__u32 arg5)170 static __always_inline void log_dbg5(enum debug_type type, enum stream_dir dir, __u32 arg1, __u32 arg2, __u32 arg3,
171 __u32 arg4, __u32 arg5)
172 {
173 struct debug_event ev = {
174 .type = type,
175 .dir = dir,
176 .arg1 = arg1,
177 .arg2 = arg2,
178 .arg3 = arg3,
179 .arg4 = arg4,
180 .arg5 = arg5,
181 };
182
183 output_to_user(EVENT_DEBUG, &ev, sizeof(struct debug_event));
184 }
185
186 #else // NET_FIREWALL_DEBUG
187
188 #define log_dbg_any(type, arg1)
189 #define log_dbg(type, dir, arg1)
190 #define log_dbg2(type, dir, arg1, arg2)
191 #define log_dbg3(type, dir, arg1, arg2, arg3)
192 #define log_dbg4(type, dir, arg1, arg2, arg3, arg4)
193 #define log_dbg5(type, dir, arg1, arg2, arg3, arg4, arg5)
194
195 #endif // NET_FIREWALL_DEBUG
196 #endif // NET_FIREWALL_EVENT_H