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