Blame view

net/netfilter/nf_log_common.c 5.84 KB
83e96d443   Pablo Neira Ayuso   netfilter: log: s...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  /* (C) 1999-2001 Paul `Rusty' Russell
   * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   */
  
  #include <linux/module.h>
  #include <linux/spinlock.h>
  #include <linux/skbuff.h>
  #include <linux/if_arp.h>
  #include <linux/ip.h>
  #include <net/icmp.h>
  #include <net/udp.h>
  #include <net/tcp.h>
  #include <net/route.h>
  
  #include <linux/netfilter.h>
c737b7c45   Florian Westphal   netfilter: bridge...
20
  #include <linux/netfilter_bridge.h>
83e96d443   Pablo Neira Ayuso   netfilter: log: s...
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
  #include <linux/netfilter/xt_LOG.h>
  #include <net/netfilter/nf_log.h>
  
  int nf_log_dump_udp_header(struct nf_log_buf *m, const struct sk_buff *skb,
  			   u8 proto, int fragment, unsigned int offset)
  {
  	struct udphdr _udph;
  	const struct udphdr *uh;
  
  	if (proto == IPPROTO_UDP)
  		/* Max length: 10 "PROTO=UDP "     */
  		nf_log_buf_add(m, "PROTO=UDP ");
  	else	/* Max length: 14 "PROTO=UDPLITE " */
  		nf_log_buf_add(m, "PROTO=UDPLITE ");
  
  	if (fragment)
  		goto out;
  
  	/* Max length: 25 "INCOMPLETE [65535 bytes] " */
  	uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
  	if (uh == NULL) {
  		nf_log_buf_add(m, "INCOMPLETE [%u bytes] ", skb->len - offset);
  
  		return 1;
  	}
  
  	/* Max length: 20 "SPT=65535 DPT=65535 " */
  	nf_log_buf_add(m, "SPT=%u DPT=%u LEN=%u ",
  		       ntohs(uh->source), ntohs(uh->dest), ntohs(uh->len));
  
  out:
  	return 0;
  }
  EXPORT_SYMBOL_GPL(nf_log_dump_udp_header);
  
  int nf_log_dump_tcp_header(struct nf_log_buf *m, const struct sk_buff *skb,
  			   u8 proto, int fragment, unsigned int offset,
  			   unsigned int logflags)
  {
  	struct tcphdr _tcph;
  	const struct tcphdr *th;
  
  	/* Max length: 10 "PROTO=TCP " */
  	nf_log_buf_add(m, "PROTO=TCP ");
  
  	if (fragment)
  		return 0;
  
  	/* Max length: 25 "INCOMPLETE [65535 bytes] " */
  	th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
  	if (th == NULL) {
  		nf_log_buf_add(m, "INCOMPLETE [%u bytes] ", skb->len - offset);
  		return 1;
  	}
  
  	/* Max length: 20 "SPT=65535 DPT=65535 " */
  	nf_log_buf_add(m, "SPT=%u DPT=%u ",
  		       ntohs(th->source), ntohs(th->dest));
  	/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
8cb2a7d56   Liping Zhang   netfilter: nf_log...
80
  	if (logflags & NF_LOG_TCPSEQ) {
83e96d443   Pablo Neira Ayuso   netfilter: log: s...
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
  		nf_log_buf_add(m, "SEQ=%u ACK=%u ",
  			       ntohl(th->seq), ntohl(th->ack_seq));
  	}
  
  	/* Max length: 13 "WINDOW=65535 " */
  	nf_log_buf_add(m, "WINDOW=%u ", ntohs(th->window));
  	/* Max length: 9 "RES=0x3C " */
  	nf_log_buf_add(m, "RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) &
  					    TCP_RESERVED_BITS) >> 22));
  	/* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
  	if (th->cwr)
  		nf_log_buf_add(m, "CWR ");
  	if (th->ece)
  		nf_log_buf_add(m, "ECE ");
  	if (th->urg)
  		nf_log_buf_add(m, "URG ");
  	if (th->ack)
  		nf_log_buf_add(m, "ACK ");
  	if (th->psh)
  		nf_log_buf_add(m, "PSH ");
  	if (th->rst)
  		nf_log_buf_add(m, "RST ");
  	if (th->syn)
  		nf_log_buf_add(m, "SYN ");
  	if (th->fin)
  		nf_log_buf_add(m, "FIN ");
  	/* Max length: 11 "URGP=65535 " */
  	nf_log_buf_add(m, "URGP=%u ", ntohs(th->urg_ptr));
8cb2a7d56   Liping Zhang   netfilter: nf_log...
109
  	if ((logflags & NF_LOG_TCPOPT) && th->doff*4 > sizeof(struct tcphdr)) {
83e96d443   Pablo Neira Ayuso   netfilter: log: s...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
  		u_int8_t _opt[60 - sizeof(struct tcphdr)];
  		const u_int8_t *op;
  		unsigned int i;
  		unsigned int optsize = th->doff*4 - sizeof(struct tcphdr);
  
  		op = skb_header_pointer(skb, offset + sizeof(struct tcphdr),
  					optsize, _opt);
  		if (op == NULL) {
  			nf_log_buf_add(m, "OPT (TRUNCATED)");
  			return 1;
  		}
  
  		/* Max length: 127 "OPT (" 15*4*2chars ") " */
  		nf_log_buf_add(m, "OPT (");
  		for (i = 0; i < optsize; i++)
  			nf_log_buf_add(m, "%02X", op[i]);
  
  		nf_log_buf_add(m, ") ");
  	}
  
  	return 0;
  }
  EXPORT_SYMBOL_GPL(nf_log_dump_tcp_header);
  
  void nf_log_dump_sk_uid_gid(struct nf_log_buf *m, struct sock *sk)
  {
a8399231f   Eric Dumazet   netfilter: use sk...
136
  	if (!sk || !sk_fullsock(sk))
83e96d443   Pablo Neira Ayuso   netfilter: log: s...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  		return;
  
  	read_lock_bh(&sk->sk_callback_lock);
  	if (sk->sk_socket && sk->sk_socket->file) {
  		const struct cred *cred = sk->sk_socket->file->f_cred;
  		nf_log_buf_add(m, "UID=%u GID=%u ",
  			from_kuid_munged(&init_user_ns, cred->fsuid),
  			from_kgid_munged(&init_user_ns, cred->fsgid));
  	}
  	read_unlock_bh(&sk->sk_callback_lock);
  }
  EXPORT_SYMBOL_GPL(nf_log_dump_sk_uid_gid);
  
  void
  nf_log_dump_packet_common(struct nf_log_buf *m, 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)
  {
  	nf_log_buf_add(m, KERN_SOH "%c%sIN=%s OUT=%s ",
  	       '0' + loginfo->u.log.level, prefix,
  	       in ? in->name : "",
  	       out ? out->name : "");
1109a90c0   Pablo Neira Ayuso   netfilter: use IS...
161
  #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
83e96d443   Pablo Neira Ayuso   netfilter: log: s...
162
163
164
  	if (skb->nf_bridge) {
  		const struct net_device *physindev;
  		const struct net_device *physoutdev;
c737b7c45   Florian Westphal   netfilter: bridge...
165
  		physindev = nf_bridge_get_physindev(skb);
83e96d443   Pablo Neira Ayuso   netfilter: log: s...
166
167
  		if (physindev && in != physindev)
  			nf_log_buf_add(m, "PHYSIN=%s ", physindev->name);
c737b7c45   Florian Westphal   netfilter: bridge...
168
  		physoutdev = nf_bridge_get_physoutdev(skb);
83e96d443   Pablo Neira Ayuso   netfilter: log: s...
169
170
171
172
173
174
  		if (physoutdev && out != physoutdev)
  			nf_log_buf_add(m, "PHYSOUT=%s ", physoutdev->name);
  	}
  #endif
  }
  EXPORT_SYMBOL_GPL(nf_log_dump_packet_common);
1fddf4bad   Pablo Neira Ayuso   netfilter: nf_log...
175
176
  /* bridge and netdev logging families share this code. */
  void nf_log_l2packet(struct net *net, u_int8_t pf,
673ab46f3   Liping Zhang   netfilter: nf_log...
177
  		     __be16 protocol,
1fddf4bad   Pablo Neira Ayuso   netfilter: nf_log...
178
179
180
181
182
183
184
  		     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)
  {
673ab46f3   Liping Zhang   netfilter: nf_log...
185
  	switch (protocol) {
1fddf4bad   Pablo Neira Ayuso   netfilter: nf_log...
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
  	case htons(ETH_P_IP):
  		nf_log_packet(net, NFPROTO_IPV4, hooknum, skb, in, out,
  			      loginfo, "%s", prefix);
  		break;
  	case htons(ETH_P_IPV6):
  		nf_log_packet(net, NFPROTO_IPV6, hooknum, skb, in, out,
  			      loginfo, "%s", prefix);
  		break;
  	case htons(ETH_P_ARP):
  	case htons(ETH_P_RARP):
  		nf_log_packet(net, NFPROTO_ARP, hooknum, skb, in, out,
  			      loginfo, "%s", prefix);
  		break;
  	}
  }
  EXPORT_SYMBOL_GPL(nf_log_l2packet);
83e96d443   Pablo Neira Ayuso   netfilter: log: s...
202
203
204
205
206
207
208
209
210
211
212
  static int __init nf_log_common_init(void)
  {
  	return 0;
  }
  
  static void __exit nf_log_common_exit(void) {}
  
  module_init(nf_log_common_init);
  module_exit(nf_log_common_exit);
  
  MODULE_LICENSE("GPL");