1 /*
2  * lib/netfilter/log_msg.c	Netfilter Log Message
3  *
4  *	This library is free software; you can redistribute it and/or
5  *	modify it under the terms of the GNU Lesser General Public
6  *	License as published by the Free Software Foundation version 2.1
7  *	of the License.
8  *
9  * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
10  * Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
11  * Copyright (c) 2007 Secure Computing Corporation
12  * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
13  */
14 
15 /**
16  * @ingroup nfnl
17  * @defgroup log Log
18  * @brief
19  * @{
20  */
21 
22 #include <sys/types.h>
23 #include <linux/netfilter/nfnetlink_log.h>
24 
25 #include <netlink-private/netlink.h>
26 #include <netlink/attr.h>
27 #include <netlink/netfilter/nfnl.h>
28 #include <netlink/netfilter/log_msg.h>
29 #include <byteswap.h>
30 
31 #if __BYTE_ORDER == __BIG_ENDIAN
ntohll(uint64_t x)32 static uint64_t ntohll(uint64_t x)
33 {
34 	return x;
35 }
36 #elif __BYTE_ORDER == __LITTLE_ENDIAN
ntohll(uint64_t x)37 static uint64_t ntohll(uint64_t x)
38 {
39 	return bswap_64(x);
40 }
41 #endif
42 
43 static struct nla_policy log_msg_policy[NFULA_MAX+1] = {
44 	[NFULA_PACKET_HDR]		= {
45 		.minlen = sizeof(struct nfulnl_msg_packet_hdr)
46 	},
47 	[NFULA_MARK]			= { .type = NLA_U32 },
48 	[NFULA_TIMESTAMP]		= {
49 		.minlen = sizeof(struct nfulnl_msg_packet_timestamp)
50 	},
51 	[NFULA_IFINDEX_INDEV]		= { .type = NLA_U32 },
52 	[NFULA_IFINDEX_OUTDEV]		= { .type = NLA_U32 },
53 	[NFULA_IFINDEX_PHYSINDEV]	= { .type = NLA_U32 },
54 	[NFULA_IFINDEX_PHYSOUTDEV]	= { .type = NLA_U32 },
55 	[NFULA_HWADDR]			= {
56 		.minlen = sizeof(struct nfulnl_msg_packet_hw)
57 	},
58 	//[NFULA_PAYLOAD]
59 	[NFULA_PREFIX]			= { .type = NLA_STRING, },
60 	[NFULA_UID]			= { .type = NLA_U32 },
61 	[NFULA_GID]			= { .type = NLA_U32 },
62 	[NFULA_SEQ]			= { .type = NLA_U32 },
63 	[NFULA_SEQ_GLOBAL]		= { .type = NLA_U32 },
64 };
65 
nfnlmsg_log_msg_parse(struct nlmsghdr * nlh,struct nfnl_log_msg ** result)66 int nfnlmsg_log_msg_parse(struct nlmsghdr *nlh, struct nfnl_log_msg **result)
67 {
68 	struct nfnl_log_msg *msg;
69 	struct nlattr *tb[NFULA_MAX+1];
70 	struct nlattr *attr;
71 	int err;
72 
73 	msg = nfnl_log_msg_alloc();
74 	if (!msg)
75 		return -NLE_NOMEM;
76 
77 	msg->ce_msgtype = nlh->nlmsg_type;
78 
79 	err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, NFULA_MAX,
80 			  log_msg_policy);
81 	if (err < 0)
82 		goto errout;
83 
84 	nfnl_log_msg_set_family(msg, nfnlmsg_family(nlh));
85 
86 	attr = tb[NFULA_PACKET_HDR];
87 	if (attr) {
88 		struct nfulnl_msg_packet_hdr *hdr = nla_data(attr);
89 
90 		if (hdr->hw_protocol)
91 			nfnl_log_msg_set_hwproto(msg, hdr->hw_protocol);
92 		nfnl_log_msg_set_hook(msg, hdr->hook);
93 	}
94 
95 	attr = tb[NFULA_MARK];
96 	if (attr)
97 		nfnl_log_msg_set_mark(msg, ntohl(nla_get_u32(attr)));
98 
99 	attr = tb[NFULA_TIMESTAMP];
100 	if (attr) {
101 		struct nfulnl_msg_packet_timestamp *timestamp = nla_data(attr);
102 		struct timeval tv;
103 
104 		tv.tv_sec = ntohll(timestamp->sec);
105 		tv.tv_usec = ntohll(timestamp->usec);
106 		nfnl_log_msg_set_timestamp(msg, &tv);
107 	}
108 
109 	attr = tb[NFULA_IFINDEX_INDEV];
110 	if (attr)
111 		nfnl_log_msg_set_indev(msg, ntohl(nla_get_u32(attr)));
112 
113 	attr = tb[NFULA_IFINDEX_OUTDEV];
114 	if (attr)
115 		nfnl_log_msg_set_outdev(msg, ntohl(nla_get_u32(attr)));
116 
117 	attr = tb[NFULA_IFINDEX_PHYSINDEV];
118 	if (attr)
119 		nfnl_log_msg_set_physindev(msg, ntohl(nla_get_u32(attr)));
120 
121 	attr = tb[NFULA_IFINDEX_PHYSOUTDEV];
122 	if (attr)
123 		nfnl_log_msg_set_physoutdev(msg, ntohl(nla_get_u32(attr)));
124 
125 	attr = tb[NFULA_HWADDR];
126 	if (attr) {
127 		struct nfulnl_msg_packet_hw *hw = nla_data(attr);
128 
129 		nfnl_log_msg_set_hwaddr(msg, hw->hw_addr, ntohs(hw->hw_addrlen));
130 	}
131 
132 	attr = tb[NFULA_PAYLOAD];
133 	if (attr) {
134 		err = nfnl_log_msg_set_payload(msg, nla_data(attr), nla_len(attr));
135 		if (err < 0)
136 			goto errout;
137 	}
138 
139 	attr = tb[NFULA_PREFIX];
140 	if (attr) {
141 		err = nfnl_log_msg_set_prefix(msg, nla_data(attr));
142 		if (err < 0)
143 			goto errout;
144 	}
145 
146 	attr = tb[NFULA_UID];
147 	if (attr)
148 		nfnl_log_msg_set_uid(msg, ntohl(nla_get_u32(attr)));
149 
150 	attr = tb[NFULA_GID];
151 	if (attr)
152 		nfnl_log_msg_set_gid(msg, ntohl(nla_get_u32(attr)));
153 
154 	attr = tb[NFULA_SEQ];
155 	if (attr)
156 		nfnl_log_msg_set_seq(msg, ntohl(nla_get_u32(attr)));
157 
158 	attr = tb[NFULA_SEQ_GLOBAL];
159 	if (attr)
160 		nfnl_log_msg_set_seq_global(msg, ntohl(nla_get_u32(attr)));
161 
162 	*result = msg;
163 	return 0;
164 
165 errout:
166 	nfnl_log_msg_put(msg);
167 	return err;
168 }
169 
log_msg_parser(struct nl_cache_ops * ops,struct sockaddr_nl * who,struct nlmsghdr * nlh,struct nl_parser_param * pp)170 static int log_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
171 			  struct nlmsghdr *nlh, struct nl_parser_param *pp)
172 {
173 	struct nfnl_log_msg *msg;
174 	int err;
175 
176 	if ((err = nfnlmsg_log_msg_parse(nlh, &msg)) < 0)
177 		return err;
178 
179 	err = pp->pp_cb((struct nl_object *) msg, pp);
180 	nfnl_log_msg_put(msg);
181 	return err;
182 }
183 
184 /** @} */
185 
186 #define NFNLMSG_LOG_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_ULOG, (type))
187 static struct nl_cache_ops nfnl_log_msg_ops = {
188 	.co_name		= "netfilter/log_msg",
189 	.co_hdrsize		= NFNL_HDRLEN,
190 	.co_msgtypes		= {
191 		{ NFNLMSG_LOG_TYPE(NFULNL_MSG_PACKET), NL_ACT_NEW, "new" },
192 		END_OF_MSGTYPES_LIST,
193 	},
194 	.co_protocol		= NETLINK_NETFILTER,
195 	.co_msg_parser		= log_msg_parser,
196 	.co_obj_ops		= &log_msg_obj_ops,
197 };
198 
log_msg_init(void)199 static void __init log_msg_init(void)
200 {
201 	nl_cache_mngt_register(&nfnl_log_msg_ops);
202 }
203 
log_msg_exit(void)204 static void __exit log_msg_exit(void)
205 {
206 	nl_cache_mngt_unregister(&nfnl_log_msg_ops);
207 }
208 
209 /** @} */
210