• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* (C) 1999-2001 Paul `Rusty' Russell
2  * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
8 
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10 
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/spinlock.h>
14 #include <linux/skbuff.h>
15 #include <linux/if_arp.h>
16 #include <linux/ip.h>
17 #include <net/ipv6.h>
18 #include <net/icmp.h>
19 #include <net/udp.h>
20 #include <net/tcp.h>
21 #include <net/route.h>
22 
23 #include <linux/netfilter.h>
24 #include <linux/netfilter/xt_LOG.h>
25 #include <net/netfilter/nf_log.h>
26 
27 static struct nf_loginfo default_loginfo = {
28 	.type	= NF_LOG_TYPE_LOG,
29 	.u = {
30 		.log = {
31 			.level	  = LOGLEVEL_NOTICE,
32 			.logflags = NF_LOG_DEFAULT_MASK,
33 		},
34 	},
35 };
36 
37 /* One level of recursion won't kill us */
dump_ipv4_packet(struct nf_log_buf * m,const struct nf_loginfo * info,const struct sk_buff * skb,unsigned int iphoff)38 static void dump_ipv4_packet(struct nf_log_buf *m,
39 			     const struct nf_loginfo *info,
40 			     const struct sk_buff *skb, unsigned int iphoff)
41 {
42 	struct iphdr _iph;
43 	const struct iphdr *ih;
44 	unsigned int logflags;
45 
46 	if (info->type == NF_LOG_TYPE_LOG)
47 		logflags = info->u.log.logflags;
48 	else
49 		logflags = NF_LOG_DEFAULT_MASK;
50 
51 	ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph);
52 	if (ih == NULL) {
53 		nf_log_buf_add(m, "TRUNCATED");
54 		return;
55 	}
56 
57 	/* Important fields:
58 	 * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
59 	/* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
60 	nf_log_buf_add(m, "SRC=%pI4 DST=%pI4 ", &ih->saddr, &ih->daddr);
61 
62 	/* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
63 	nf_log_buf_add(m, "LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
64 		       ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK,
65 		       ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id));
66 
67 	/* Max length: 6 "CE DF MF " */
68 	if (ntohs(ih->frag_off) & IP_CE)
69 		nf_log_buf_add(m, "CE ");
70 	if (ntohs(ih->frag_off) & IP_DF)
71 		nf_log_buf_add(m, "DF ");
72 	if (ntohs(ih->frag_off) & IP_MF)
73 		nf_log_buf_add(m, "MF ");
74 
75 	/* Max length: 11 "FRAG:65535 " */
76 	if (ntohs(ih->frag_off) & IP_OFFSET)
77 		nf_log_buf_add(m, "FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET);
78 
79 	if ((logflags & NF_LOG_IPOPT) &&
80 	    ih->ihl * 4 > sizeof(struct iphdr)) {
81 		const unsigned char *op;
82 		unsigned char _opt[4 * 15 - sizeof(struct iphdr)];
83 		unsigned int i, optsize;
84 
85 		optsize = ih->ihl * 4 - sizeof(struct iphdr);
86 		op = skb_header_pointer(skb, iphoff+sizeof(_iph),
87 					optsize, _opt);
88 		if (op == NULL) {
89 			nf_log_buf_add(m, "TRUNCATED");
90 			return;
91 		}
92 
93 		/* Max length: 127 "OPT (" 15*4*2chars ") " */
94 		nf_log_buf_add(m, "OPT (");
95 		for (i = 0; i < optsize; i++)
96 			nf_log_buf_add(m, "%02X", op[i]);
97 		nf_log_buf_add(m, ") ");
98 	}
99 
100 	switch (ih->protocol) {
101 	case IPPROTO_TCP:
102 		if (nf_log_dump_tcp_header(m, skb, ih->protocol,
103 					   ntohs(ih->frag_off) & IP_OFFSET,
104 					   iphoff+ih->ihl*4, logflags))
105 			return;
106 		break;
107 	case IPPROTO_UDP:
108 	case IPPROTO_UDPLITE:
109 		if (nf_log_dump_udp_header(m, skb, ih->protocol,
110 					   ntohs(ih->frag_off) & IP_OFFSET,
111 					   iphoff+ih->ihl*4))
112 			return;
113 		break;
114 	case IPPROTO_ICMP: {
115 		struct icmphdr _icmph;
116 		const struct icmphdr *ich;
117 		static const size_t required_len[NR_ICMP_TYPES+1]
118 			= { [ICMP_ECHOREPLY] = 4,
119 			    [ICMP_DEST_UNREACH]
120 			    = 8 + sizeof(struct iphdr),
121 			    [ICMP_SOURCE_QUENCH]
122 			    = 8 + sizeof(struct iphdr),
123 			    [ICMP_REDIRECT]
124 			    = 8 + sizeof(struct iphdr),
125 			    [ICMP_ECHO] = 4,
126 			    [ICMP_TIME_EXCEEDED]
127 			    = 8 + sizeof(struct iphdr),
128 			    [ICMP_PARAMETERPROB]
129 			    = 8 + sizeof(struct iphdr),
130 			    [ICMP_TIMESTAMP] = 20,
131 			    [ICMP_TIMESTAMPREPLY] = 20,
132 			    [ICMP_ADDRESS] = 12,
133 			    [ICMP_ADDRESSREPLY] = 12 };
134 
135 		/* Max length: 11 "PROTO=ICMP " */
136 		nf_log_buf_add(m, "PROTO=ICMP ");
137 
138 		if (ntohs(ih->frag_off) & IP_OFFSET)
139 			break;
140 
141 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
142 		ich = skb_header_pointer(skb, iphoff + ih->ihl * 4,
143 					 sizeof(_icmph), &_icmph);
144 		if (ich == NULL) {
145 			nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
146 				       skb->len - iphoff - ih->ihl*4);
147 			break;
148 		}
149 
150 		/* Max length: 18 "TYPE=255 CODE=255 " */
151 		nf_log_buf_add(m, "TYPE=%u CODE=%u ", ich->type, ich->code);
152 
153 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
154 		if (ich->type <= NR_ICMP_TYPES &&
155 		    required_len[ich->type] &&
156 		    skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) {
157 			nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
158 				       skb->len - iphoff - ih->ihl*4);
159 			break;
160 		}
161 
162 		switch (ich->type) {
163 		case ICMP_ECHOREPLY:
164 		case ICMP_ECHO:
165 			/* Max length: 19 "ID=65535 SEQ=65535 " */
166 			nf_log_buf_add(m, "ID=%u SEQ=%u ",
167 				       ntohs(ich->un.echo.id),
168 				       ntohs(ich->un.echo.sequence));
169 			break;
170 
171 		case ICMP_PARAMETERPROB:
172 			/* Max length: 14 "PARAMETER=255 " */
173 			nf_log_buf_add(m, "PARAMETER=%u ",
174 				       ntohl(ich->un.gateway) >> 24);
175 			break;
176 		case ICMP_REDIRECT:
177 			/* Max length: 24 "GATEWAY=255.255.255.255 " */
178 			nf_log_buf_add(m, "GATEWAY=%pI4 ", &ich->un.gateway);
179 			/* Fall through */
180 		case ICMP_DEST_UNREACH:
181 		case ICMP_SOURCE_QUENCH:
182 		case ICMP_TIME_EXCEEDED:
183 			/* Max length: 3+maxlen */
184 			if (!iphoff) { /* Only recurse once. */
185 				nf_log_buf_add(m, "[");
186 				dump_ipv4_packet(m, info, skb,
187 					    iphoff + ih->ihl*4+sizeof(_icmph));
188 				nf_log_buf_add(m, "] ");
189 			}
190 
191 			/* Max length: 10 "MTU=65535 " */
192 			if (ich->type == ICMP_DEST_UNREACH &&
193 			    ich->code == ICMP_FRAG_NEEDED) {
194 				nf_log_buf_add(m, "MTU=%u ",
195 					       ntohs(ich->un.frag.mtu));
196 			}
197 		}
198 		break;
199 	}
200 	/* Max Length */
201 	case IPPROTO_AH: {
202 		struct ip_auth_hdr _ahdr;
203 		const struct ip_auth_hdr *ah;
204 
205 		if (ntohs(ih->frag_off) & IP_OFFSET)
206 			break;
207 
208 		/* Max length: 9 "PROTO=AH " */
209 		nf_log_buf_add(m, "PROTO=AH ");
210 
211 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
212 		ah = skb_header_pointer(skb, iphoff+ih->ihl*4,
213 					sizeof(_ahdr), &_ahdr);
214 		if (ah == NULL) {
215 			nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
216 				       skb->len - iphoff - ih->ihl*4);
217 			break;
218 		}
219 
220 		/* Length: 15 "SPI=0xF1234567 " */
221 		nf_log_buf_add(m, "SPI=0x%x ", ntohl(ah->spi));
222 		break;
223 	}
224 	case IPPROTO_ESP: {
225 		struct ip_esp_hdr _esph;
226 		const struct ip_esp_hdr *eh;
227 
228 		/* Max length: 10 "PROTO=ESP " */
229 		nf_log_buf_add(m, "PROTO=ESP ");
230 
231 		if (ntohs(ih->frag_off) & IP_OFFSET)
232 			break;
233 
234 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
235 		eh = skb_header_pointer(skb, iphoff+ih->ihl*4,
236 					sizeof(_esph), &_esph);
237 		if (eh == NULL) {
238 			nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
239 				       skb->len - iphoff - ih->ihl*4);
240 			break;
241 		}
242 
243 		/* Length: 15 "SPI=0xF1234567 " */
244 		nf_log_buf_add(m, "SPI=0x%x ", ntohl(eh->spi));
245 		break;
246 	}
247 	/* Max length: 10 "PROTO 255 " */
248 	default:
249 		nf_log_buf_add(m, "PROTO=%u ", ih->protocol);
250 	}
251 
252 	/* Max length: 15 "UID=4294967295 " */
253 	if ((logflags & NF_LOG_UID) && !iphoff)
254 		nf_log_dump_sk_uid_gid(m, skb->sk);
255 
256 	/* Max length: 16 "MARK=0xFFFFFFFF " */
257 	if (!iphoff && skb->mark)
258 		nf_log_buf_add(m, "MARK=0x%x ", skb->mark);
259 
260 	/* Proto    Max log string length */
261 	/* IP:	    40+46+6+11+127 = 230 */
262 	/* TCP:     10+max(25,20+30+13+9+32+11+127) = 252 */
263 	/* UDP:     10+max(25,20) = 35 */
264 	/* UDPLITE: 14+max(25,20) = 39 */
265 	/* ICMP:    11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */
266 	/* ESP:     10+max(25)+15 = 50 */
267 	/* AH:	    9+max(25)+15 = 49 */
268 	/* unknown: 10 */
269 
270 	/* (ICMP allows recursion one level deep) */
271 	/* maxlen =  IP + ICMP +  IP + max(TCP,UDP,ICMP,unknown) */
272 	/* maxlen = 230+   91  + 230 + 252 = 803 */
273 }
274 
dump_ipv4_mac_header(struct nf_log_buf * m,const struct nf_loginfo * info,const struct sk_buff * skb)275 static void dump_ipv4_mac_header(struct nf_log_buf *m,
276 			    const struct nf_loginfo *info,
277 			    const struct sk_buff *skb)
278 {
279 	struct net_device *dev = skb->dev;
280 	unsigned int logflags = 0;
281 
282 	if (info->type == NF_LOG_TYPE_LOG)
283 		logflags = info->u.log.logflags;
284 
285 	if (!(logflags & NF_LOG_MACDECODE))
286 		goto fallback;
287 
288 	switch (dev->type) {
289 	case ARPHRD_ETHER:
290 		nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
291 			       eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
292 			       ntohs(eth_hdr(skb)->h_proto));
293 		return;
294 	default:
295 		break;
296 	}
297 
298 fallback:
299 	nf_log_buf_add(m, "MAC=");
300 	if (dev->hard_header_len &&
301 	    skb->mac_header != skb->network_header) {
302 		const unsigned char *p = skb_mac_header(skb);
303 		unsigned int i;
304 
305 		nf_log_buf_add(m, "%02x", *p++);
306 		for (i = 1; i < dev->hard_header_len; i++, p++)
307 			nf_log_buf_add(m, ":%02x", *p);
308 	}
309 	nf_log_buf_add(m, " ");
310 }
311 
nf_log_ip_packet(struct net * net,u_int8_t pf,unsigned int hooknum,const struct sk_buff * skb,const struct net_device * in,const struct net_device * out,const struct nf_loginfo * loginfo,const char * prefix)312 static void nf_log_ip_packet(struct net *net, u_int8_t pf,
313 			     unsigned int hooknum, const struct sk_buff *skb,
314 			     const struct net_device *in,
315 			     const struct net_device *out,
316 			     const struct nf_loginfo *loginfo,
317 			     const char *prefix)
318 {
319 	struct nf_log_buf *m;
320 
321 	/* FIXME: Disabled from containers until syslog ns is supported */
322 	if (!net_eq(net, &init_net))
323 		return;
324 
325 	m = nf_log_buf_open();
326 
327 	if (!loginfo)
328 		loginfo = &default_loginfo;
329 
330 	nf_log_dump_packet_common(m, pf, hooknum, skb, in,
331 				  out, loginfo, prefix);
332 
333 	if (in != NULL)
334 		dump_ipv4_mac_header(m, loginfo, skb);
335 
336 	dump_ipv4_packet(m, loginfo, skb, 0);
337 
338 	nf_log_buf_close(m);
339 }
340 
341 static struct nf_logger nf_ip_logger __read_mostly = {
342 	.name		= "nf_log_ipv4",
343 	.type		= NF_LOG_TYPE_LOG,
344 	.logfn		= nf_log_ip_packet,
345 	.me		= THIS_MODULE,
346 };
347 
nf_log_ipv4_net_init(struct net * net)348 static int __net_init nf_log_ipv4_net_init(struct net *net)
349 {
350 	return nf_log_set(net, NFPROTO_IPV4, &nf_ip_logger);
351 }
352 
nf_log_ipv4_net_exit(struct net * net)353 static void __net_exit nf_log_ipv4_net_exit(struct net *net)
354 {
355 	nf_log_unset(net, &nf_ip_logger);
356 }
357 
358 static struct pernet_operations nf_log_ipv4_net_ops = {
359 	.init = nf_log_ipv4_net_init,
360 	.exit = nf_log_ipv4_net_exit,
361 };
362 
nf_log_ipv4_init(void)363 static int __init nf_log_ipv4_init(void)
364 {
365 	int ret;
366 
367 	ret = register_pernet_subsys(&nf_log_ipv4_net_ops);
368 	if (ret < 0)
369 		return ret;
370 
371 	ret = nf_log_register(NFPROTO_IPV4, &nf_ip_logger);
372 	if (ret < 0) {
373 		pr_err("failed to register logger\n");
374 		goto err1;
375 	}
376 
377 	return 0;
378 
379 err1:
380 	unregister_pernet_subsys(&nf_log_ipv4_net_ops);
381 	return ret;
382 }
383 
nf_log_ipv4_exit(void)384 static void __exit nf_log_ipv4_exit(void)
385 {
386 	unregister_pernet_subsys(&nf_log_ipv4_net_ops);
387 	nf_log_unregister(&nf_ip_logger);
388 }
389 
390 module_init(nf_log_ipv4_init);
391 module_exit(nf_log_ipv4_exit);
392 
393 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
394 MODULE_DESCRIPTION("Netfilter IPv4 packet logging");
395 MODULE_LICENSE("GPL");
396 MODULE_ALIAS_NF_LOGGER(AF_INET, 0);
397