1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
4 * Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
5 * Copyright (c) 2007 Secure Computing Corporation
6 * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
7 */
8
9 /**
10 * @ingroup nfnl
11 * @defgroup log Log
12 * @brief
13 * @{
14 */
15
16 #include "nl-default.h"
17
18 #include <sys/types.h>
19
20 #include <linux/netfilter/nfnetlink_log.h>
21
22 #include <netlink/attr.h>
23 #include <netlink/netfilter/nfnl.h>
24 #include <netlink/netfilter/log_msg.h>
25
26 #include "nl-netfilter.h"
27 #include "nl-priv-dynamic-core/cache-api.h"
28
29 static struct nla_policy log_msg_policy[NFULA_MAX+1] = {
30 [NFULA_PACKET_HDR] = {
31 .minlen = sizeof(struct nfulnl_msg_packet_hdr)
32 },
33 [NFULA_MARK] = { .type = NLA_U32 },
34 [NFULA_TIMESTAMP] = {
35 .minlen = sizeof(struct nfulnl_msg_packet_timestamp)
36 },
37 [NFULA_IFINDEX_INDEV] = { .type = NLA_U32 },
38 [NFULA_IFINDEX_OUTDEV] = { .type = NLA_U32 },
39 [NFULA_IFINDEX_PHYSINDEV] = { .type = NLA_U32 },
40 [NFULA_IFINDEX_PHYSOUTDEV] = { .type = NLA_U32 },
41 [NFULA_HWADDR] = {
42 .minlen = sizeof(struct nfulnl_msg_packet_hw)
43 },
44 //[NFULA_PAYLOAD]
45 [NFULA_PREFIX] = { .type = NLA_STRING, },
46 [NFULA_UID] = { .type = NLA_U32 },
47 [NFULA_GID] = { .type = NLA_U32 },
48 [NFULA_SEQ] = { .type = NLA_U32 },
49 [NFULA_SEQ_GLOBAL] = { .type = NLA_U32 },
50 [NFULA_HWTYPE] = { .type = NLA_U16 },
51 [NFULA_HWLEN] = { .type = NLA_U16 },
52 [NFULA_VLAN] = { .type = NLA_NESTED },
53 [NFULA_CT] = { .type = NLA_NESTED },
54 [NFULA_CT_INFO] = { .type = NLA_U32 },
55 };
56
57 static struct nla_policy log_msg_vlan_policy[NFULA_VLAN_MAX+1] = {
58 [NFULA_VLAN_PROTO] = { .type = NLA_U16 },
59 [NFULA_VLAN_TCI] = { .type = NLA_U16 },
60 };
61
62 static int
nfnlmsg_log_msg_parse_vlan(struct nlattr * attr_full,struct nfnl_log_msg * msg)63 nfnlmsg_log_msg_parse_vlan(struct nlattr *attr_full, struct nfnl_log_msg *msg)
64 {
65 struct nlattr *tb[NFULA_VLAN_MAX+1];
66 struct nlattr *attr;
67 int err;
68
69 err = nla_parse_nested(tb, NFULA_VLAN_MAX, attr_full,
70 log_msg_vlan_policy);
71 if (err < 0)
72 return err;
73
74 attr = tb[NFULA_VLAN_PROTO];
75 if (attr)
76 nfnl_log_msg_set_vlan_proto(msg, nla_get_u16(attr));
77
78 attr = tb[NFULA_VLAN_TCI];
79 if (attr)
80 nfnl_log_msg_set_vlan_tag(msg, ntohs(nla_get_u16(attr)));
81
82 return 0;
83 }
84
nfnlmsg_log_msg_parse(struct nlmsghdr * nlh,struct nfnl_log_msg ** result)85 int nfnlmsg_log_msg_parse(struct nlmsghdr *nlh, struct nfnl_log_msg **result)
86 {
87 struct nfnl_log_msg *msg;
88 struct nlattr *tb[NFULA_MAX+1];
89 struct nlattr *attr;
90 int err;
91
92 msg = nfnl_log_msg_alloc();
93 if (!msg)
94 return -NLE_NOMEM;
95
96 msg->ce_msgtype = nlh->nlmsg_type;
97
98 err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, NFULA_MAX,
99 log_msg_policy);
100 if (err < 0)
101 goto errout;
102
103 nfnl_log_msg_set_family(msg, nfnlmsg_family(nlh));
104
105 attr = tb[NFULA_PACKET_HDR];
106 if (attr) {
107 struct nfulnl_msg_packet_hdr *hdr = nla_data(attr);
108
109 if (hdr->hw_protocol)
110 nfnl_log_msg_set_hwproto(msg, hdr->hw_protocol);
111 nfnl_log_msg_set_hook(msg, hdr->hook);
112 }
113
114 attr = tb[NFULA_MARK];
115 if (attr)
116 nfnl_log_msg_set_mark(msg, ntohl(nla_get_u32(attr)));
117
118 attr = tb[NFULA_TIMESTAMP];
119 if (attr) {
120 struct nfulnl_msg_packet_timestamp *timestamp = nla_data(attr);
121 struct timeval tv;
122
123 tv.tv_sec = ntohll(timestamp->sec);
124 tv.tv_usec = ntohll(timestamp->usec);
125 nfnl_log_msg_set_timestamp(msg, &tv);
126 }
127
128 attr = tb[NFULA_IFINDEX_INDEV];
129 if (attr)
130 nfnl_log_msg_set_indev(msg, ntohl(nla_get_u32(attr)));
131
132 attr = tb[NFULA_IFINDEX_OUTDEV];
133 if (attr)
134 nfnl_log_msg_set_outdev(msg, ntohl(nla_get_u32(attr)));
135
136 attr = tb[NFULA_IFINDEX_PHYSINDEV];
137 if (attr)
138 nfnl_log_msg_set_physindev(msg, ntohl(nla_get_u32(attr)));
139
140 attr = tb[NFULA_IFINDEX_PHYSOUTDEV];
141 if (attr)
142 nfnl_log_msg_set_physoutdev(msg, ntohl(nla_get_u32(attr)));
143
144 attr = tb[NFULA_HWADDR];
145 if (attr) {
146 struct nfulnl_msg_packet_hw *hw = nla_data(attr);
147
148 nfnl_log_msg_set_hwaddr(msg, hw->hw_addr, ntohs(hw->hw_addrlen));
149 }
150
151 attr = tb[NFULA_PAYLOAD];
152 if (attr) {
153 err = nfnl_log_msg_set_payload(msg, nla_data(attr), nla_len(attr));
154 if (err < 0)
155 goto errout;
156 }
157
158 attr = tb[NFULA_PREFIX];
159 if (attr) {
160 err = nfnl_log_msg_set_prefix(msg, nla_data(attr));
161 if (err < 0)
162 goto errout;
163 }
164
165 attr = tb[NFULA_UID];
166 if (attr)
167 nfnl_log_msg_set_uid(msg, ntohl(nla_get_u32(attr)));
168
169 attr = tb[NFULA_GID];
170 if (attr)
171 nfnl_log_msg_set_gid(msg, ntohl(nla_get_u32(attr)));
172
173 attr = tb[NFULA_SEQ];
174 if (attr)
175 nfnl_log_msg_set_seq(msg, ntohl(nla_get_u32(attr)));
176
177 attr = tb[NFULA_SEQ_GLOBAL];
178 if (attr)
179 nfnl_log_msg_set_seq_global(msg, ntohl(nla_get_u32(attr)));
180
181 attr = tb[NFULA_HWTYPE];
182 if (attr)
183 nfnl_log_msg_set_hwtype(msg, ntohs(nla_get_u16(attr)));
184
185 attr = tb[NFULA_HWLEN];
186 if (attr)
187 nfnl_log_msg_set_hwlen(msg, ntohs(nla_get_u16(attr)));
188
189 attr = tb[NFULA_HWHEADER];
190 if (attr)
191 nfnl_log_msg_set_hwheader(msg, nla_data(attr), nla_len(attr));
192
193 attr = tb[NFULA_VLAN];
194 if (attr) {
195 err = nfnlmsg_log_msg_parse_vlan(attr, msg);
196 if (err < 0)
197 goto errout;
198 }
199
200 attr = tb[NFULA_CT];
201 if (attr) {
202 struct nfnl_ct *ct = NULL;
203 err = nfnlmsg_ct_parse_nested(attr, &ct);
204 if (err < 0)
205 goto errout;
206 nfnl_log_msg_set_ct(msg, ct);
207 nfnl_ct_put(ct);
208 }
209
210 attr = tb[NFULA_CT_INFO];
211 if (attr)
212 nfnl_log_msg_set_ct_info(msg, ntohl(nla_get_u32(attr)));
213
214 *result = msg;
215 return 0;
216
217 errout:
218 nfnl_log_msg_put(msg);
219 return err;
220 }
221
log_msg_parser(struct nl_cache_ops * ops,struct sockaddr_nl * who,struct nlmsghdr * nlh,struct nl_parser_param * pp)222 static int log_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
223 struct nlmsghdr *nlh, struct nl_parser_param *pp)
224 {
225 struct nfnl_log_msg *msg;
226 int err;
227
228 if ((err = nfnlmsg_log_msg_parse(nlh, &msg)) < 0)
229 return err;
230
231 err = pp->pp_cb((struct nl_object *) msg, pp);
232 nfnl_log_msg_put(msg);
233 return err;
234 }
235
236 /** @} */
237
238 #define NFNLMSG_LOG_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_ULOG, (type))
239 static struct nl_cache_ops nfnl_log_msg_ops = {
240 .co_name = "netfilter/log_msg",
241 .co_hdrsize = NFNL_HDRLEN,
242 .co_msgtypes = {
243 { NFNLMSG_LOG_TYPE(NFULNL_MSG_PACKET), NL_ACT_NEW, "new" },
244 END_OF_MSGTYPES_LIST,
245 },
246 .co_protocol = NETLINK_NETFILTER,
247 .co_msg_parser = log_msg_parser,
248 .co_obj_ops = &log_msg_obj_ops,
249 };
250
log_msg_init(void)251 static void _nl_init log_msg_init(void)
252 {
253 nl_cache_mngt_register(&nfnl_log_msg_ops);
254 }
255
log_msg_exit(void)256 static void _nl_exit log_msg_exit(void)
257 {
258 nl_cache_mngt_unregister(&nfnl_log_msg_ops);
259 }
260
261 /** @} */
262