Skip to content

Commit 1e40d75

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following patchset contains Netfilter fixes for net: 1) Extend nf_queue selftest to cover re-queueing, non-gso mode and delayed queueing, from Florian Westphal. 2) Clear skb->tstamp in IPVS forwarding path, from Julian Anastasov. 3) Provide netlink extended error reporting for EEXIST case. 4) Missing VLAN offload tag and proto in log target. ==================== Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents fdafed4 + 0d9826b commit 1e40d75

9 files changed

Lines changed: 168 additions & 34 deletions

File tree

include/net/netfilter/nf_log.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ int nf_log_dump_tcp_header(struct nf_log_buf *m, const struct sk_buff *skb,
108108
unsigned int logflags);
109109
void nf_log_dump_sk_uid_gid(struct net *net, struct nf_log_buf *m,
110110
struct sock *sk);
111+
void nf_log_dump_vlan(struct nf_log_buf *m, const struct sk_buff *skb);
111112
void nf_log_dump_packet_common(struct nf_log_buf *m, u_int8_t pf,
112113
unsigned int hooknum, const struct sk_buff *skb,
113114
const struct net_device *in,

net/ipv4/netfilter/nf_log_arp.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,31 @@ static void dump_arp_packet(struct nf_log_buf *m,
4343
const struct nf_loginfo *info,
4444
const struct sk_buff *skb, unsigned int nhoff)
4545
{
46-
const struct arphdr *ah;
47-
struct arphdr _arph;
4846
const struct arppayload *ap;
4947
struct arppayload _arpp;
48+
const struct arphdr *ah;
49+
unsigned int logflags;
50+
struct arphdr _arph;
5051

5152
ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
5253
if (ah == NULL) {
5354
nf_log_buf_add(m, "TRUNCATED");
5455
return;
5556
}
57+
58+
if (info->type == NF_LOG_TYPE_LOG)
59+
logflags = info->u.log.logflags;
60+
else
61+
logflags = NF_LOG_DEFAULT_MASK;
62+
63+
if (logflags & NF_LOG_MACDECODE) {
64+
nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM ",
65+
eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest);
66+
nf_log_dump_vlan(m, skb);
67+
nf_log_buf_add(m, "MACPROTO=%04x ",
68+
ntohs(eth_hdr(skb)->h_proto));
69+
}
70+
5671
nf_log_buf_add(m, "ARP HTYPE=%d PTYPE=0x%04x OPCODE=%d",
5772
ntohs(ah->ar_hrd), ntohs(ah->ar_pro), ntohs(ah->ar_op));
5873

net/ipv4/netfilter/nf_log_ipv4.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,10 @@ static void dump_ipv4_mac_header(struct nf_log_buf *m,
284284

285285
switch (dev->type) {
286286
case ARPHRD_ETHER:
287-
nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
288-
eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
287+
nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM ",
288+
eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest);
289+
nf_log_dump_vlan(m, skb);
290+
nf_log_buf_add(m, "MACPROTO=%04x ",
289291
ntohs(eth_hdr(skb)->h_proto));
290292
return;
291293
default:

net/ipv6/netfilter/nf_log_ipv6.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,9 +297,11 @@ static void dump_ipv6_mac_header(struct nf_log_buf *m,
297297

298298
switch (dev->type) {
299299
case ARPHRD_ETHER:
300-
nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
301-
eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
302-
ntohs(eth_hdr(skb)->h_proto));
300+
nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM ",
301+
eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest);
302+
nf_log_dump_vlan(m, skb);
303+
nf_log_buf_add(m, "MACPROTO=%04x ",
304+
ntohs(eth_hdr(skb)->h_proto));
303305
return;
304306
default:
305307
break;

net/netfilter/ipvs/ip_vs_xmit.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,8 @@ static inline int ip_vs_tunnel_xmit_prepare(struct sk_buff *skb,
609609
if (ret == NF_ACCEPT) {
610610
nf_reset_ct(skb);
611611
skb_forward_csum(skb);
612+
if (skb->dev)
613+
skb->tstamp = 0;
612614
}
613615
return ret;
614616
}
@@ -649,6 +651,8 @@ static inline int ip_vs_nat_send_or_cont(int pf, struct sk_buff *skb,
649651

650652
if (!local) {
651653
skb_forward_csum(skb);
654+
if (skb->dev)
655+
skb->tstamp = 0;
652656
NF_HOOK(pf, NF_INET_LOCAL_OUT, cp->ipvs->net, NULL, skb,
653657
NULL, skb_dst(skb)->dev, dst_output);
654658
} else
@@ -669,6 +673,8 @@ static inline int ip_vs_send_or_cont(int pf, struct sk_buff *skb,
669673
if (!local) {
670674
ip_vs_drop_early_demux_sk(skb);
671675
skb_forward_csum(skb);
676+
if (skb->dev)
677+
skb->tstamp = 0;
672678
NF_HOOK(pf, NF_INET_LOCAL_OUT, cp->ipvs->net, NULL, skb,
673679
NULL, skb_dst(skb)->dev, dst_output);
674680
} else

net/netfilter/nf_log_common.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,18 @@ nf_log_dump_packet_common(struct nf_log_buf *m, u_int8_t pf,
171171
}
172172
EXPORT_SYMBOL_GPL(nf_log_dump_packet_common);
173173

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+
174186
/* bridge and netdev logging families share this code. */
175187
void nf_log_l2packet(struct net *net, u_int8_t pf,
176188
__be16 protocol,

net/netfilter/nf_tables_api.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2103,7 +2103,8 @@ static bool nft_hook_list_equal(struct list_head *hook_list1,
21032103
}
21042104

21052105
static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
2106-
u32 flags)
2106+
u32 flags, const struct nlattr *attr,
2107+
struct netlink_ext_ack *extack)
21072108
{
21082109
const struct nlattr * const *nla = ctx->nla;
21092110
struct nft_table *table = ctx->table;
@@ -2119,9 +2120,10 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
21192120
return -EOPNOTSUPP;
21202121

21212122
if (nla[NFTA_CHAIN_HOOK]) {
2122-
if (!nft_is_base_chain(chain))
2123+
if (!nft_is_base_chain(chain)) {
2124+
NL_SET_BAD_ATTR(extack, attr);
21232125
return -EEXIST;
2124-
2126+
}
21252127
err = nft_chain_parse_hook(ctx->net, nla, &hook, ctx->family,
21262128
false);
21272129
if (err < 0)
@@ -2130,20 +2132,23 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
21302132
basechain = nft_base_chain(chain);
21312133
if (basechain->type != hook.type) {
21322134
nft_chain_release_hook(&hook);
2135+
NL_SET_BAD_ATTR(extack, attr);
21332136
return -EEXIST;
21342137
}
21352138

21362139
if (ctx->family == NFPROTO_NETDEV) {
21372140
if (!nft_hook_list_equal(&basechain->hook_list,
21382141
&hook.list)) {
21392142
nft_chain_release_hook(&hook);
2143+
NL_SET_BAD_ATTR(extack, attr);
21402144
return -EEXIST;
21412145
}
21422146
} else {
21432147
ops = &basechain->ops;
21442148
if (ops->hooknum != hook.num ||
21452149
ops->priority != hook.priority) {
21462150
nft_chain_release_hook(&hook);
2151+
NL_SET_BAD_ATTR(extack, attr);
21472152
return -EEXIST;
21482153
}
21492154
}
@@ -2156,8 +2161,10 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
21562161

21572162
chain2 = nft_chain_lookup(ctx->net, table,
21582163
nla[NFTA_CHAIN_NAME], genmask);
2159-
if (!IS_ERR(chain2))
2164+
if (!IS_ERR(chain2)) {
2165+
NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_NAME]);
21602166
return -EEXIST;
2167+
}
21612168
}
21622169

21632170
if (nla[NFTA_CHAIN_COUNTERS]) {
@@ -2200,6 +2207,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
22002207
nft_trans_chain_update(tmp) &&
22012208
nft_trans_chain_name(tmp) &&
22022209
strcmp(name, nft_trans_chain_name(tmp)) == 0) {
2210+
NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_NAME]);
22032211
kfree(name);
22042212
goto err;
22052213
}
@@ -2322,7 +2330,8 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
23222330
return -EOPNOTSUPP;
23232331

23242332
flags |= chain->flags & NFT_CHAIN_BASE;
2325-
return nf_tables_updchain(&ctx, genmask, policy, flags);
2333+
return nf_tables_updchain(&ctx, genmask, policy, flags, attr,
2334+
extack);
23262335
}
23272336

23282337
return nf_tables_addchain(&ctx, family, genmask, policy, flags);

tools/testing/selftests/netfilter/nf-queue.c

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,20 @@
1717

1818
struct options {
1919
bool count_packets;
20+
bool gso_enabled;
2021
int verbose;
2122
unsigned int queue_num;
2223
unsigned int timeout;
24+
uint32_t verdict;
25+
uint32_t delay_ms;
2326
};
2427

2528
static unsigned int queue_stats[5];
2629
static struct options opts;
2730

2831
static void help(const char *p)
2932
{
30-
printf("Usage: %s [-c|-v [-vv] ] [-t timeout] [-q queue_num]\n", p);
33+
printf("Usage: %s [-c|-v [-vv] ] [-t timeout] [-q queue_num] [-Qdst_queue ] [ -d ms_delay ] [-G]\n", p);
3134
}
3235

3336
static int parse_attr_cb(const struct nlattr *attr, void *data)
@@ -162,7 +165,7 @@ nfq_build_cfg_params(char *buf, uint8_t mode, int range, int queue_num)
162165
}
163166

164167
static struct nlmsghdr *
165-
nfq_build_verdict(char *buf, int id, int queue_num, int verd)
168+
nfq_build_verdict(char *buf, int id, int queue_num, uint32_t verd)
166169
{
167170
struct nfqnl_msg_verdict_hdr vh = {
168171
.verdict = htonl(verd),
@@ -189,9 +192,6 @@ static void print_stats(void)
189192
unsigned int last, total;
190193
int i;
191194

192-
if (!opts.count_packets)
193-
return;
194-
195195
total = 0;
196196
last = queue_stats[0];
197197

@@ -234,7 +234,8 @@ struct mnl_socket *open_queue(void)
234234

235235
nlh = nfq_build_cfg_params(buf, NFQNL_COPY_PACKET, 0xFFFF, queue_num);
236236

237-
flags = NFQA_CFG_F_GSO | NFQA_CFG_F_UID_GID;
237+
flags = opts.gso_enabled ? NFQA_CFG_F_GSO : 0;
238+
flags |= NFQA_CFG_F_UID_GID;
238239
mnl_attr_put_u32(nlh, NFQA_CFG_FLAGS, htonl(flags));
239240
mnl_attr_put_u32(nlh, NFQA_CFG_MASK, htonl(flags));
240241

@@ -255,6 +256,17 @@ struct mnl_socket *open_queue(void)
255256
return nl;
256257
}
257258

259+
static void sleep_ms(uint32_t delay)
260+
{
261+
struct timespec ts = { .tv_sec = delay / 1000 };
262+
263+
delay %= 1000;
264+
265+
ts.tv_nsec = delay * 1000llu * 1000llu;
266+
267+
nanosleep(&ts, NULL);
268+
}
269+
258270
static int mainloop(void)
259271
{
260272
unsigned int buflen = 64 * 1024 + MNL_SOCKET_BUFFER_SIZE;
@@ -278,7 +290,7 @@ static int mainloop(void)
278290

279291
ret = mnl_socket_recvfrom(nl, buf, buflen);
280292
if (ret == -1) {
281-
if (errno == ENOBUFS)
293+
if (errno == ENOBUFS || errno == EINTR)
282294
continue;
283295

284296
if (errno == EAGAIN) {
@@ -298,7 +310,10 @@ static int mainloop(void)
298310
}
299311

300312
id = ret - MNL_CB_OK;
301-
nlh = nfq_build_verdict(buf, id, opts.queue_num, NF_ACCEPT);
313+
if (opts.delay_ms)
314+
sleep_ms(opts.delay_ms);
315+
316+
nlh = nfq_build_verdict(buf, id, opts.queue_num, opts.verdict);
302317
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
303318
perror("mnl_socket_sendto");
304319
exit(EXIT_FAILURE);
@@ -314,7 +329,7 @@ static void parse_opts(int argc, char **argv)
314329
{
315330
int c;
316331

317-
while ((c = getopt(argc, argv, "chvt:q:")) != -1) {
332+
while ((c = getopt(argc, argv, "chvt:q:Q:d:G")) != -1) {
318333
switch (c) {
319334
case 'c':
320335
opts.count_packets = true;
@@ -328,20 +343,48 @@ static void parse_opts(int argc, char **argv)
328343
if (opts.queue_num > 0xffff)
329344
opts.queue_num = 0;
330345
break;
346+
case 'Q':
347+
opts.verdict = atoi(optarg);
348+
if (opts.verdict > 0xffff) {
349+
fprintf(stderr, "Expected destination queue number\n");
350+
exit(1);
351+
}
352+
353+
opts.verdict <<= 16;
354+
opts.verdict |= NF_QUEUE;
355+
break;
356+
case 'd':
357+
opts.delay_ms = atoi(optarg);
358+
if (opts.delay_ms == 0) {
359+
fprintf(stderr, "Expected nonzero delay (in milliseconds)\n");
360+
exit(1);
361+
}
362+
break;
331363
case 't':
332364
opts.timeout = atoi(optarg);
333365
break;
366+
case 'G':
367+
opts.gso_enabled = false;
368+
break;
334369
case 'v':
335370
opts.verbose++;
336371
break;
337372
}
338373
}
374+
375+
if (opts.verdict != NF_ACCEPT && (opts.verdict >> 16 == opts.queue_num)) {
376+
fprintf(stderr, "Cannot use same destination and source queue\n");
377+
exit(1);
378+
}
339379
}
340380

341381
int main(int argc, char *argv[])
342382
{
343383
int ret;
344384

385+
opts.verdict = NF_ACCEPT;
386+
opts.gso_enabled = true;
387+
345388
parse_opts(argc, argv);
346389

347390
ret = mainloop();

0 commit comments

Comments
 (0)