diff options
-rw-r--r-- | include/uapi/linux/netfilter/nfnetlink_queue.h | 2 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_queue_core.c | 16 |
2 files changed, 16 insertions, 2 deletions
diff --git a/include/uapi/linux/netfilter/nfnetlink_queue.h b/include/uapi/linux/netfilter/nfnetlink_queue.h index a2308ae5a73d..3a9b92147339 100644 --- a/include/uapi/linux/netfilter/nfnetlink_queue.h +++ b/include/uapi/linux/netfilter/nfnetlink_queue.h | |||
@@ -105,5 +105,7 @@ enum nfqnl_attr_config { | |||
105 | #define NFQA_SKB_CSUMNOTREADY (1 << 0) | 105 | #define NFQA_SKB_CSUMNOTREADY (1 << 0) |
106 | /* packet is GSO (i.e., exceeds device mtu) */ | 106 | /* packet is GSO (i.e., exceeds device mtu) */ |
107 | #define NFQA_SKB_GSO (1 << 1) | 107 | #define NFQA_SKB_GSO (1 << 1) |
108 | /* csum not validated (incoming device doesn't support hw checksum, etc.) */ | ||
109 | #define NFQA_SKB_CSUM_NOTVERIFIED (1 << 2) | ||
108 | 110 | ||
109 | #endif /* _NFNETLINK_QUEUE_H */ | 111 | #endif /* _NFNETLINK_QUEUE_H */ |
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index 299a48ae5dc9..971ea145ab3e 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c | |||
@@ -280,12 +280,17 @@ nfqnl_zcopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen) | |||
280 | skb_shinfo(to)->nr_frags = j; | 280 | skb_shinfo(to)->nr_frags = j; |
281 | } | 281 | } |
282 | 282 | ||
283 | static int nfqnl_put_packet_info(struct sk_buff *nlskb, struct sk_buff *packet) | 283 | static int |
284 | nfqnl_put_packet_info(struct sk_buff *nlskb, struct sk_buff *packet, | ||
285 | bool csum_verify) | ||
284 | { | 286 | { |
285 | __u32 flags = 0; | 287 | __u32 flags = 0; |
286 | 288 | ||
287 | if (packet->ip_summed == CHECKSUM_PARTIAL) | 289 | if (packet->ip_summed == CHECKSUM_PARTIAL) |
288 | flags = NFQA_SKB_CSUMNOTREADY; | 290 | flags = NFQA_SKB_CSUMNOTREADY; |
291 | else if (csum_verify) | ||
292 | flags = NFQA_SKB_CSUM_NOTVERIFIED; | ||
293 | |||
289 | if (skb_is_gso(packet)) | 294 | if (skb_is_gso(packet)) |
290 | flags |= NFQA_SKB_GSO; | 295 | flags |= NFQA_SKB_GSO; |
291 | 296 | ||
@@ -310,6 +315,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, | |||
310 | struct net_device *outdev; | 315 | struct net_device *outdev; |
311 | struct nf_conn *ct = NULL; | 316 | struct nf_conn *ct = NULL; |
312 | enum ip_conntrack_info uninitialized_var(ctinfo); | 317 | enum ip_conntrack_info uninitialized_var(ctinfo); |
318 | bool csum_verify; | ||
313 | 319 | ||
314 | size = nlmsg_total_size(sizeof(struct nfgenmsg)) | 320 | size = nlmsg_total_size(sizeof(struct nfgenmsg)) |
315 | + nla_total_size(sizeof(struct nfqnl_msg_packet_hdr)) | 321 | + nla_total_size(sizeof(struct nfqnl_msg_packet_hdr)) |
@@ -327,6 +333,12 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, | |||
327 | if (entskb->tstamp.tv64) | 333 | if (entskb->tstamp.tv64) |
328 | size += nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)); | 334 | size += nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)); |
329 | 335 | ||
336 | if (entry->hook <= NF_INET_FORWARD || | ||
337 | (entry->hook == NF_INET_POST_ROUTING && entskb->sk == NULL)) | ||
338 | csum_verify = !skb_csum_unnecessary(entskb); | ||
339 | else | ||
340 | csum_verify = false; | ||
341 | |||
330 | outdev = entry->outdev; | 342 | outdev = entry->outdev; |
331 | 343 | ||
332 | switch ((enum nfqnl_config_mode)ACCESS_ONCE(queue->copy_mode)) { | 344 | switch ((enum nfqnl_config_mode)ACCESS_ONCE(queue->copy_mode)) { |
@@ -476,7 +488,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, | |||
476 | nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len))) | 488 | nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len))) |
477 | goto nla_put_failure; | 489 | goto nla_put_failure; |
478 | 490 | ||
479 | if (nfqnl_put_packet_info(skb, entskb)) | 491 | if (nfqnl_put_packet_info(skb, entskb, csum_verify)) |
480 | goto nla_put_failure; | 492 | goto nla_put_failure; |
481 | 493 | ||
482 | if (data_len) { | 494 | if (data_len) { |