]>
Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
83e96d44 PNA |
2 | /* (C) 1999-2001 Paul `Rusty' Russell |
3 | * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> | |
83e96d44 PNA |
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> | |
c737b7c4 | 17 | #include <linux/netfilter_bridge.h> |
83e96d44 PNA |
18 | #include <linux/netfilter/xt_LOG.h> |
19 | #include <net/netfilter/nf_log.h> | |
20 | ||
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 | ||
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 " */ | |
8cb2a7d5 | 77 | if (logflags & NF_LOG_TCPSEQ) { |
83e96d44 PNA |
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 | ||
8cb2a7d5 | 107 | if ((logflags & NF_LOG_TCPOPT) && th->doff*4 > sizeof(struct tcphdr)) { |
83e96d44 PNA |
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 | ||
f5646501 FL |
132 | void nf_log_dump_sk_uid_gid(struct net *net, struct nf_log_buf *m, |
133 | struct sock *sk) | |
83e96d44 | 134 | { |
f5646501 | 135 | if (!sk || !sk_fullsock(sk) || !net_eq(net, sock_net(sk))) |
83e96d44 PNA |
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 | |
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 | { | |
c4b0e771 FW |
156 | const struct net_device *physoutdev __maybe_unused; |
157 | const struct net_device *physindev __maybe_unused; | |
158 | ||
83e96d44 PNA |
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 : ""); | |
1109a90c | 163 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
c4b0e771 FW |
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); | |
83e96d44 PNA |
170 | #endif |
171 | } | |
172 | EXPORT_SYMBOL_GPL(nf_log_dump_packet_common); | |
173 | ||
1fddf4ba PNA |
174 | /* bridge and netdev logging families share this code. */ |
175 | void nf_log_l2packet(struct net *net, u_int8_t pf, | |
673ab46f | 176 | __be16 protocol, |
1fddf4ba PNA |
177 | unsigned int hooknum, |
178 | const struct sk_buff *skb, | |
179 | const struct net_device *in, | |
180 | const struct net_device *out, | |
181 | const struct nf_loginfo *loginfo, | |
182 | const char *prefix) | |
183 | { | |
673ab46f | 184 | switch (protocol) { |
1fddf4ba PNA |
185 | case htons(ETH_P_IP): |
186 | nf_log_packet(net, NFPROTO_IPV4, hooknum, skb, in, out, | |
187 | loginfo, "%s", prefix); | |
188 | break; | |
189 | case htons(ETH_P_IPV6): | |
190 | nf_log_packet(net, NFPROTO_IPV6, hooknum, skb, in, out, | |
191 | loginfo, "%s", prefix); | |
192 | break; | |
193 | case htons(ETH_P_ARP): | |
194 | case htons(ETH_P_RARP): | |
195 | nf_log_packet(net, NFPROTO_ARP, hooknum, skb, in, out, | |
196 | loginfo, "%s", prefix); | |
197 | break; | |
198 | } | |
199 | } | |
200 | EXPORT_SYMBOL_GPL(nf_log_l2packet); | |
201 | ||
83e96d44 PNA |
202 | static int __init nf_log_common_init(void) |
203 | { | |
204 | return 0; | |
205 | } | |
206 | ||
207 | static void __exit nf_log_common_exit(void) {} | |
208 | ||
209 | module_init(nf_log_common_init); | |
210 | module_exit(nf_log_common_exit); | |
211 | ||
212 | MODULE_LICENSE("GPL"); |