Commit 93e66024b0249cec81e91328c55a754efd3192e0
Committed by
Pablo Neira Ayuso
1 parent
c8204cab9c
netfilter: conntrack: pass nf_hook_state to packet and error handlers
nf_hook_state contains all the hook meta-information: netns, protocol family, hook location, and so on. Instead of only passing selected information, pass a pointer to entire structure. This will allow to merge the error and the packet handlers and remove the ->new() function in followup patches. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Showing 13 changed files with 142 additions and 115 deletions Side-by-side Diff
- include/net/netfilter/nf_conntrack_core.h
- include/net/netfilter/nf_conntrack_l4proto.h
- net/netfilter/nf_conntrack_core.c
- net/netfilter/nf_conntrack_proto.c
- net/netfilter/nf_conntrack_proto_dccp.c
- net/netfilter/nf_conntrack_proto_generic.c
- net/netfilter/nf_conntrack_proto_gre.c
- net/netfilter/nf_conntrack_proto_icmp.c
- net/netfilter/nf_conntrack_proto_icmpv6.c
- net/netfilter/nf_conntrack_proto_sctp.c
- net/netfilter/nf_conntrack_proto_tcp.c
- net/netfilter/nf_conntrack_proto_udp.c
- net/openvswitch/conntrack.c
include/net/netfilter/nf_conntrack_core.h
... | ... | @@ -20,8 +20,7 @@ |
20 | 20 | /* This header is used to share core functionality between the |
21 | 21 | standalone connection tracking module, and the compatibility layer's use |
22 | 22 | of connection tracking. */ |
23 | -unsigned int nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |
24 | - struct sk_buff *skb); | |
23 | +unsigned int nf_conntrack_in(struct sk_buff *skb, const struct nf_hook_state *state); | |
25 | 24 | |
26 | 25 | int nf_conntrack_init_net(struct net *net); |
27 | 26 | void nf_conntrack_cleanup_net(struct net *net); |
include/net/netfilter/nf_conntrack_l4proto.h
... | ... | @@ -45,7 +45,8 @@ |
45 | 45 | int (*packet)(struct nf_conn *ct, |
46 | 46 | const struct sk_buff *skb, |
47 | 47 | unsigned int dataoff, |
48 | - enum ip_conntrack_info ctinfo); | |
48 | + enum ip_conntrack_info ctinfo, | |
49 | + const struct nf_hook_state *state); | |
49 | 50 | |
50 | 51 | /* Called when a new connection for this protocol found; |
51 | 52 | * returns TRUE if it's OK. If so, packet() called next. */ |
52 | 53 | |
... | ... | @@ -55,9 +56,9 @@ |
55 | 56 | /* Called when a conntrack entry is destroyed */ |
56 | 57 | void (*destroy)(struct nf_conn *ct); |
57 | 58 | |
58 | - int (*error)(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, | |
59 | + int (*error)(struct nf_conn *tmpl, struct sk_buff *skb, | |
59 | 60 | unsigned int dataoff, |
60 | - u_int8_t pf, unsigned int hooknum); | |
61 | + const struct nf_hook_state *state); | |
61 | 62 | |
62 | 63 | /* called by gc worker if table is full */ |
63 | 64 | bool (*can_early_drop)(const struct nf_conn *ct); |
net/netfilter/nf_conntrack_core.c
... | ... | @@ -1436,12 +1436,12 @@ |
1436 | 1436 | |
1437 | 1437 | /* On success, returns 0, sets skb->_nfct | ctinfo */ |
1438 | 1438 | static int |
1439 | -resolve_normal_ct(struct net *net, struct nf_conn *tmpl, | |
1439 | +resolve_normal_ct(struct nf_conn *tmpl, | |
1440 | 1440 | struct sk_buff *skb, |
1441 | 1441 | unsigned int dataoff, |
1442 | - u_int16_t l3num, | |
1443 | 1442 | u_int8_t protonum, |
1444 | - const struct nf_conntrack_l4proto *l4proto) | |
1443 | + const struct nf_conntrack_l4proto *l4proto, | |
1444 | + const struct nf_hook_state *state) | |
1445 | 1445 | { |
1446 | 1446 | const struct nf_conntrack_zone *zone; |
1447 | 1447 | struct nf_conntrack_tuple tuple; |
1448 | 1448 | |
1449 | 1449 | |
... | ... | @@ -1452,17 +1452,18 @@ |
1452 | 1452 | u32 hash; |
1453 | 1453 | |
1454 | 1454 | if (!nf_ct_get_tuple(skb, skb_network_offset(skb), |
1455 | - dataoff, l3num, protonum, net, &tuple, l4proto)) { | |
1455 | + dataoff, state->pf, protonum, state->net, | |
1456 | + &tuple, l4proto)) { | |
1456 | 1457 | pr_debug("Can't get tuple\n"); |
1457 | 1458 | return 0; |
1458 | 1459 | } |
1459 | 1460 | |
1460 | 1461 | /* look for tuple match */ |
1461 | 1462 | zone = nf_ct_zone_tmpl(tmpl, skb, &tmp); |
1462 | - hash = hash_conntrack_raw(&tuple, net); | |
1463 | - h = __nf_conntrack_find_get(net, zone, &tuple, hash); | |
1463 | + hash = hash_conntrack_raw(&tuple, state->net); | |
1464 | + h = __nf_conntrack_find_get(state->net, zone, &tuple, hash); | |
1464 | 1465 | if (!h) { |
1465 | - h = init_conntrack(net, tmpl, &tuple, l4proto, | |
1466 | + h = init_conntrack(state->net, tmpl, &tuple, l4proto, | |
1466 | 1467 | skb, dataoff, hash); |
1467 | 1468 | if (!h) |
1468 | 1469 | return 0; |
1469 | 1470 | |
1470 | 1471 | |
... | ... | @@ -1492,12 +1493,11 @@ |
1492 | 1493 | } |
1493 | 1494 | |
1494 | 1495 | unsigned int |
1495 | -nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |
1496 | - struct sk_buff *skb) | |
1496 | +nf_conntrack_in(struct sk_buff *skb, const struct nf_hook_state *state) | |
1497 | 1497 | { |
1498 | 1498 | const struct nf_conntrack_l4proto *l4proto; |
1499 | - struct nf_conn *ct, *tmpl; | |
1500 | 1499 | enum ip_conntrack_info ctinfo; |
1500 | + struct nf_conn *ct, *tmpl; | |
1501 | 1501 | u_int8_t protonum; |
1502 | 1502 | int dataoff, ret; |
1503 | 1503 | |
1504 | 1504 | |
1505 | 1505 | |
1506 | 1506 | |
1507 | 1507 | |
1508 | 1508 | |
... | ... | @@ -1506,32 +1506,32 @@ |
1506 | 1506 | /* Previously seen (loopback or untracked)? Ignore. */ |
1507 | 1507 | if ((tmpl && !nf_ct_is_template(tmpl)) || |
1508 | 1508 | ctinfo == IP_CT_UNTRACKED) { |
1509 | - NF_CT_STAT_INC_ATOMIC(net, ignore); | |
1509 | + NF_CT_STAT_INC_ATOMIC(state->net, ignore); | |
1510 | 1510 | return NF_ACCEPT; |
1511 | 1511 | } |
1512 | 1512 | skb->_nfct = 0; |
1513 | 1513 | } |
1514 | 1514 | |
1515 | 1515 | /* rcu_read_lock()ed by nf_hook_thresh */ |
1516 | - dataoff = get_l4proto(skb, skb_network_offset(skb), pf, &protonum); | |
1516 | + dataoff = get_l4proto(skb, skb_network_offset(skb), state->pf, &protonum); | |
1517 | 1517 | if (dataoff <= 0) { |
1518 | 1518 | pr_debug("not prepared to track yet or error occurred\n"); |
1519 | - NF_CT_STAT_INC_ATOMIC(net, error); | |
1520 | - NF_CT_STAT_INC_ATOMIC(net, invalid); | |
1519 | + NF_CT_STAT_INC_ATOMIC(state->net, error); | |
1520 | + NF_CT_STAT_INC_ATOMIC(state->net, invalid); | |
1521 | 1521 | ret = NF_ACCEPT; |
1522 | 1522 | goto out; |
1523 | 1523 | } |
1524 | 1524 | |
1525 | - l4proto = __nf_ct_l4proto_find(pf, protonum); | |
1525 | + l4proto = __nf_ct_l4proto_find(state->pf, protonum); | |
1526 | 1526 | |
1527 | 1527 | /* It may be an special packet, error, unclean... |
1528 | 1528 | * inverse of the return code tells to the netfilter |
1529 | 1529 | * core what to do with the packet. */ |
1530 | 1530 | if (l4proto->error != NULL) { |
1531 | - ret = l4proto->error(net, tmpl, skb, dataoff, pf, hooknum); | |
1531 | + ret = l4proto->error(tmpl, skb, dataoff, state); | |
1532 | 1532 | if (ret <= 0) { |
1533 | - NF_CT_STAT_INC_ATOMIC(net, error); | |
1534 | - NF_CT_STAT_INC_ATOMIC(net, invalid); | |
1533 | + NF_CT_STAT_INC_ATOMIC(state->net, error); | |
1534 | + NF_CT_STAT_INC_ATOMIC(state->net, invalid); | |
1535 | 1535 | ret = -ret; |
1536 | 1536 | goto out; |
1537 | 1537 | } |
1538 | 1538 | |
... | ... | @@ -1540,10 +1540,11 @@ |
1540 | 1540 | goto out; |
1541 | 1541 | } |
1542 | 1542 | repeat: |
1543 | - ret = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum, l4proto); | |
1543 | + ret = resolve_normal_ct(tmpl, skb, dataoff, | |
1544 | + protonum, l4proto, state); | |
1544 | 1545 | if (ret < 0) { |
1545 | 1546 | /* Too stressed to deal. */ |
1546 | - NF_CT_STAT_INC_ATOMIC(net, drop); | |
1547 | + NF_CT_STAT_INC_ATOMIC(state->net, drop); | |
1547 | 1548 | ret = NF_DROP; |
1548 | 1549 | goto out; |
1549 | 1550 | } |
1550 | 1551 | |
1551 | 1552 | |
1552 | 1553 | |
... | ... | @@ -1551,21 +1552,21 @@ |
1551 | 1552 | ct = nf_ct_get(skb, &ctinfo); |
1552 | 1553 | if (!ct) { |
1553 | 1554 | /* Not valid part of a connection */ |
1554 | - NF_CT_STAT_INC_ATOMIC(net, invalid); | |
1555 | + NF_CT_STAT_INC_ATOMIC(state->net, invalid); | |
1555 | 1556 | ret = NF_ACCEPT; |
1556 | 1557 | goto out; |
1557 | 1558 | } |
1558 | 1559 | |
1559 | - ret = l4proto->packet(ct, skb, dataoff, ctinfo); | |
1560 | + ret = l4proto->packet(ct, skb, dataoff, ctinfo, state); | |
1560 | 1561 | if (ret <= 0) { |
1561 | 1562 | /* Invalid: inverse of the return code tells |
1562 | 1563 | * the netfilter core what to do */ |
1563 | 1564 | pr_debug("nf_conntrack_in: Can't track with proto module\n"); |
1564 | 1565 | nf_conntrack_put(&ct->ct_general); |
1565 | 1566 | skb->_nfct = 0; |
1566 | - NF_CT_STAT_INC_ATOMIC(net, invalid); | |
1567 | + NF_CT_STAT_INC_ATOMIC(state->net, invalid); | |
1567 | 1568 | if (ret == -NF_DROP) |
1568 | - NF_CT_STAT_INC_ATOMIC(net, drop); | |
1569 | + NF_CT_STAT_INC_ATOMIC(state->net, drop); | |
1569 | 1570 | /* Special case: TCP tracker reports an attempt to reopen a |
1570 | 1571 | * closed/aborted connection. We have to go back and create a |
1571 | 1572 | * fresh conntrack. |
net/netfilter/nf_conntrack_proto.c
... | ... | @@ -455,7 +455,7 @@ |
455 | 455 | struct sk_buff *skb, |
456 | 456 | const struct nf_hook_state *state) |
457 | 457 | { |
458 | - return nf_conntrack_in(state->net, PF_INET, state->hook, skb); | |
458 | + return nf_conntrack_in(skb, state); | |
459 | 459 | } |
460 | 460 | |
461 | 461 | static unsigned int ipv4_conntrack_local(void *priv, |
... | ... | @@ -477,7 +477,7 @@ |
477 | 477 | return NF_ACCEPT; |
478 | 478 | } |
479 | 479 | |
480 | - return nf_conntrack_in(state->net, PF_INET, state->hook, skb); | |
480 | + return nf_conntrack_in(skb, state); | |
481 | 481 | } |
482 | 482 | |
483 | 483 | /* Connection tracking may drop packets, but never alters them, so |
484 | 484 | |
... | ... | @@ -690,14 +690,14 @@ |
690 | 690 | struct sk_buff *skb, |
691 | 691 | const struct nf_hook_state *state) |
692 | 692 | { |
693 | - return nf_conntrack_in(state->net, PF_INET6, state->hook, skb); | |
693 | + return nf_conntrack_in(skb, state); | |
694 | 694 | } |
695 | 695 | |
696 | 696 | static unsigned int ipv6_conntrack_local(void *priv, |
697 | 697 | struct sk_buff *skb, |
698 | 698 | const struct nf_hook_state *state) |
699 | 699 | { |
700 | - return nf_conntrack_in(state->net, PF_INET6, state->hook, skb); | |
700 | + return nf_conntrack_in(skb, state); | |
701 | 701 | } |
702 | 702 | |
703 | 703 | static unsigned int ipv6_helper(void *priv, |
net/netfilter/nf_conntrack_proto_dccp.c
... | ... | @@ -439,7 +439,8 @@ |
439 | 439 | } |
440 | 440 | |
441 | 441 | static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, |
442 | - unsigned int dataoff, enum ip_conntrack_info ctinfo) | |
442 | + unsigned int dataoff, enum ip_conntrack_info ctinfo, | |
443 | + const struct nf_hook_state *state) | |
443 | 444 | { |
444 | 445 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
445 | 446 | struct dccp_hdr _dh, *dh; |
446 | 447 | |
... | ... | @@ -527,9 +528,9 @@ |
527 | 528 | return NF_ACCEPT; |
528 | 529 | } |
529 | 530 | |
530 | -static int dccp_error(struct net *net, struct nf_conn *tmpl, | |
531 | +static int dccp_error(struct nf_conn *tmpl, | |
531 | 532 | struct sk_buff *skb, unsigned int dataoff, |
532 | - u_int8_t pf, unsigned int hooknum) | |
533 | + const struct nf_hook_state *state) | |
533 | 534 | { |
534 | 535 | struct dccp_hdr _dh, *dh; |
535 | 536 | unsigned int dccp_len = skb->len - dataoff; |
... | ... | @@ -557,9 +558,10 @@ |
557 | 558 | } |
558 | 559 | } |
559 | 560 | |
560 | - if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && | |
561 | - nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_DCCP, | |
562 | - pf)) { | |
561 | + if (state->hook == NF_INET_PRE_ROUTING && | |
562 | + state->net->ct.sysctl_checksum && | |
563 | + nf_checksum_partial(skb, state->hook, dataoff, cscov, | |
564 | + IPPROTO_DCCP, state->pf)) { | |
563 | 565 | msg = "nf_ct_dccp: bad checksum "; |
564 | 566 | goto out_invalid; |
565 | 567 | } |
... | ... | @@ -572,7 +574,8 @@ |
572 | 574 | return NF_ACCEPT; |
573 | 575 | |
574 | 576 | out_invalid: |
575 | - nf_l4proto_log_invalid(skb, net, pf, IPPROTO_DCCP, "%s", msg); | |
577 | + nf_l4proto_log_invalid(skb, state->net, state->pf, | |
578 | + IPPROTO_DCCP, "%s", msg); | |
576 | 579 | return -NF_ACCEPT; |
577 | 580 | } |
578 | 581 |
net/netfilter/nf_conntrack_proto_generic.c
... | ... | @@ -46,7 +46,8 @@ |
46 | 46 | static int generic_packet(struct nf_conn *ct, |
47 | 47 | const struct sk_buff *skb, |
48 | 48 | unsigned int dataoff, |
49 | - enum ip_conntrack_info ctinfo) | |
49 | + enum ip_conntrack_info ctinfo, | |
50 | + const struct nf_hook_state *state) | |
50 | 51 | { |
51 | 52 | const unsigned int *timeout = nf_ct_timeout_lookup(ct); |
52 | 53 |
net/netfilter/nf_conntrack_proto_gre.c
... | ... | @@ -235,7 +235,8 @@ |
235 | 235 | static int gre_packet(struct nf_conn *ct, |
236 | 236 | const struct sk_buff *skb, |
237 | 237 | unsigned int dataoff, |
238 | - enum ip_conntrack_info ctinfo) | |
238 | + enum ip_conntrack_info ctinfo, | |
239 | + const struct nf_hook_state *state) | |
239 | 240 | { |
240 | 241 | /* If we've seen traffic both ways, this is a GRE connection. |
241 | 242 | * Extend timeout. */ |
net/netfilter/nf_conntrack_proto_icmp.c
... | ... | @@ -81,7 +81,8 @@ |
81 | 81 | static int icmp_packet(struct nf_conn *ct, |
82 | 82 | const struct sk_buff *skb, |
83 | 83 | unsigned int dataoff, |
84 | - enum ip_conntrack_info ctinfo) | |
84 | + enum ip_conntrack_info ctinfo, | |
85 | + const struct nf_hook_state *state) | |
85 | 86 | { |
86 | 87 | /* Do not immediately delete the connection after the first |
87 | 88 | successful reply to avoid excessive conntrackd traffic |
... | ... | @@ -120,8 +121,8 @@ |
120 | 121 | |
121 | 122 | /* Returns conntrack if it dealt with ICMP, and filled in skb fields */ |
122 | 123 | static int |
123 | -icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, | |
124 | - unsigned int hooknum) | |
124 | +icmp_error_message(struct nf_conn *tmpl, struct sk_buff *skb, | |
125 | + const struct nf_hook_state *state) | |
125 | 126 | { |
126 | 127 | struct nf_conntrack_tuple innertuple, origtuple; |
127 | 128 | const struct nf_conntrack_l4proto *innerproto; |
... | ... | @@ -137,7 +138,7 @@ |
137 | 138 | if (!nf_ct_get_tuplepr(skb, |
138 | 139 | skb_network_offset(skb) + ip_hdrlen(skb) |
139 | 140 | + sizeof(struct icmphdr), |
140 | - PF_INET, net, &origtuple)) { | |
141 | + PF_INET, state->net, &origtuple)) { | |
141 | 142 | pr_debug("icmp_error_message: failed to get tuple\n"); |
142 | 143 | return -NF_ACCEPT; |
143 | 144 | } |
... | ... | @@ -154,7 +155,7 @@ |
154 | 155 | |
155 | 156 | ctinfo = IP_CT_RELATED; |
156 | 157 | |
157 | - h = nf_conntrack_find_get(net, zone, &innertuple); | |
158 | + h = nf_conntrack_find_get(state->net, zone, &innertuple); | |
158 | 159 | if (!h) { |
159 | 160 | pr_debug("icmp_error_message: no match\n"); |
160 | 161 | return -NF_ACCEPT; |
161 | 162 | |
162 | 163 | |
163 | 164 | |
... | ... | @@ -168,17 +169,19 @@ |
168 | 169 | return NF_ACCEPT; |
169 | 170 | } |
170 | 171 | |
171 | -static void icmp_error_log(const struct sk_buff *skb, struct net *net, | |
172 | - u8 pf, const char *msg) | |
172 | +static void icmp_error_log(const struct sk_buff *skb, | |
173 | + const struct nf_hook_state *state, | |
174 | + const char *msg) | |
173 | 175 | { |
174 | - nf_l4proto_log_invalid(skb, net, pf, IPPROTO_ICMP, "%s", msg); | |
176 | + nf_l4proto_log_invalid(skb, state->net, state->pf, | |
177 | + IPPROTO_ICMP, "%s", msg); | |
175 | 178 | } |
176 | 179 | |
177 | 180 | /* Small and modified version of icmp_rcv */ |
178 | 181 | static int |
179 | -icmp_error(struct net *net, struct nf_conn *tmpl, | |
182 | +icmp_error(struct nf_conn *tmpl, | |
180 | 183 | struct sk_buff *skb, unsigned int dataoff, |
181 | - u8 pf, unsigned int hooknum) | |
184 | + const struct nf_hook_state *state) | |
182 | 185 | { |
183 | 186 | const struct icmphdr *icmph; |
184 | 187 | struct icmphdr _ih; |
185 | 188 | |
... | ... | @@ -186,14 +189,15 @@ |
186 | 189 | /* Not enough header? */ |
187 | 190 | icmph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_ih), &_ih); |
188 | 191 | if (icmph == NULL) { |
189 | - icmp_error_log(skb, net, pf, "short packet"); | |
192 | + icmp_error_log(skb, state, "short packet"); | |
190 | 193 | return -NF_ACCEPT; |
191 | 194 | } |
192 | 195 | |
193 | 196 | /* See ip_conntrack_proto_tcp.c */ |
194 | - if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && | |
195 | - nf_ip_checksum(skb, hooknum, dataoff, 0)) { | |
196 | - icmp_error_log(skb, net, pf, "bad hw icmp checksum"); | |
197 | + if (state->net->ct.sysctl_checksum && | |
198 | + state->hook == NF_INET_PRE_ROUTING && | |
199 | + nf_ip_checksum(skb, state->hook, dataoff, 0)) { | |
200 | + icmp_error_log(skb, state, "bad hw icmp checksum"); | |
197 | 201 | return -NF_ACCEPT; |
198 | 202 | } |
199 | 203 | |
... | ... | @@ -204,7 +208,7 @@ |
204 | 208 | * discarded. |
205 | 209 | */ |
206 | 210 | if (icmph->type > NR_ICMP_TYPES) { |
207 | - icmp_error_log(skb, net, pf, "invalid icmp type"); | |
211 | + icmp_error_log(skb, state, "invalid icmp type"); | |
208 | 212 | return -NF_ACCEPT; |
209 | 213 | } |
210 | 214 | |
... | ... | @@ -216,7 +220,7 @@ |
216 | 220 | icmph->type != ICMP_REDIRECT) |
217 | 221 | return NF_ACCEPT; |
218 | 222 | |
219 | - return icmp_error_message(net, tmpl, skb, hooknum); | |
223 | + return icmp_error_message(tmpl, skb, state); | |
220 | 224 | } |
221 | 225 | |
222 | 226 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
net/netfilter/nf_conntrack_proto_icmpv6.c
... | ... | @@ -94,7 +94,8 @@ |
94 | 94 | static int icmpv6_packet(struct nf_conn *ct, |
95 | 95 | const struct sk_buff *skb, |
96 | 96 | unsigned int dataoff, |
97 | - enum ip_conntrack_info ctinfo) | |
97 | + enum ip_conntrack_info ctinfo, | |
98 | + const struct nf_hook_state *state) | |
98 | 99 | { |
99 | 100 | unsigned int *timeout = nf_ct_timeout_lookup(ct); |
100 | 101 | |
101 | 102 | |
102 | 103 | |
... | ... | @@ -179,16 +180,19 @@ |
179 | 180 | return NF_ACCEPT; |
180 | 181 | } |
181 | 182 | |
182 | -static void icmpv6_error_log(const struct sk_buff *skb, struct net *net, | |
183 | - u8 pf, const char *msg) | |
183 | +static void icmpv6_error_log(const struct sk_buff *skb, | |
184 | + const struct nf_hook_state *state, | |
185 | + const char *msg) | |
184 | 186 | { |
185 | - nf_l4proto_log_invalid(skb, net, pf, IPPROTO_ICMPV6, "%s", msg); | |
187 | + nf_l4proto_log_invalid(skb, state->net, state->pf, | |
188 | + IPPROTO_ICMPV6, "%s", msg); | |
186 | 189 | } |
187 | 190 | |
188 | 191 | static int |
189 | -icmpv6_error(struct net *net, struct nf_conn *tmpl, | |
190 | - struct sk_buff *skb, unsigned int dataoff, | |
191 | - u8 pf, unsigned int hooknum) | |
192 | +icmpv6_error(struct nf_conn *tmpl, | |
193 | + struct sk_buff *skb, | |
194 | + unsigned int dataoff, | |
195 | + const struct nf_hook_state *state) | |
192 | 196 | { |
193 | 197 | const struct icmp6hdr *icmp6h; |
194 | 198 | struct icmp6hdr _ih; |
195 | 199 | |
... | ... | @@ -196,13 +200,14 @@ |
196 | 200 | |
197 | 201 | icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih); |
198 | 202 | if (icmp6h == NULL) { |
199 | - icmpv6_error_log(skb, net, pf, "short packet"); | |
203 | + icmpv6_error_log(skb, state, "short packet"); | |
200 | 204 | return -NF_ACCEPT; |
201 | 205 | } |
202 | 206 | |
203 | - if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && | |
204 | - nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) { | |
205 | - icmpv6_error_log(skb, net, pf, "ICMPv6 checksum failed"); | |
207 | + if (state->hook == NF_INET_PRE_ROUTING && | |
208 | + state->net->ct.sysctl_checksum && | |
209 | + nf_ip6_checksum(skb, state->hook, dataoff, IPPROTO_ICMPV6)) { | |
210 | + icmpv6_error_log(skb, state, "ICMPv6 checksum failed"); | |
206 | 211 | return -NF_ACCEPT; |
207 | 212 | } |
208 | 213 | |
... | ... | @@ -217,7 +222,7 @@ |
217 | 222 | if (icmp6h->icmp6_type >= 128) |
218 | 223 | return NF_ACCEPT; |
219 | 224 | |
220 | - return icmpv6_error_message(net, tmpl, skb, dataoff); | |
225 | + return icmpv6_error_message(state->net, tmpl, skb, dataoff); | |
221 | 226 | } |
222 | 227 | |
223 | 228 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
net/netfilter/nf_conntrack_proto_sctp.c
... | ... | @@ -277,7 +277,8 @@ |
277 | 277 | static int sctp_packet(struct nf_conn *ct, |
278 | 278 | const struct sk_buff *skb, |
279 | 279 | unsigned int dataoff, |
280 | - enum ip_conntrack_info ctinfo) | |
280 | + enum ip_conntrack_info ctinfo, | |
281 | + const struct nf_hook_state *state) | |
281 | 282 | { |
282 | 283 | enum sctp_conntrack new_state, old_state; |
283 | 284 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
284 | 285 | |
... | ... | @@ -471,9 +472,9 @@ |
471 | 472 | return true; |
472 | 473 | } |
473 | 474 | |
474 | -static int sctp_error(struct net *net, struct nf_conn *tpl, struct sk_buff *skb, | |
475 | +static int sctp_error(struct nf_conn *tpl, struct sk_buff *skb, | |
475 | 476 | unsigned int dataoff, |
476 | - u8 pf, unsigned int hooknum) | |
477 | + const struct nf_hook_state *state) | |
477 | 478 | { |
478 | 479 | const struct sctphdr *sh; |
479 | 480 | const char *logmsg; |
... | ... | @@ -482,7 +483,8 @@ |
482 | 483 | logmsg = "nf_ct_sctp: short packet "; |
483 | 484 | goto out_invalid; |
484 | 485 | } |
485 | - if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && | |
486 | + if (state->hook == NF_INET_PRE_ROUTING && | |
487 | + state->net->ct.sysctl_checksum && | |
486 | 488 | skb->ip_summed == CHECKSUM_NONE) { |
487 | 489 | if (!skb_make_writable(skb, dataoff + sizeof(struct sctphdr))) { |
488 | 490 | logmsg = "nf_ct_sctp: failed to read header "; |
... | ... | @@ -497,7 +499,7 @@ |
497 | 499 | } |
498 | 500 | return NF_ACCEPT; |
499 | 501 | out_invalid: |
500 | - nf_l4proto_log_invalid(skb, net, pf, IPPROTO_SCTP, "%s", logmsg); | |
502 | + nf_l4proto_log_invalid(skb, state->net, state->pf, IPPROTO_SCTP, "%s", logmsg); | |
501 | 503 | return -NF_ACCEPT; |
502 | 504 | } |
503 | 505 |
net/netfilter/nf_conntrack_proto_tcp.c
... | ... | @@ -717,18 +717,18 @@ |
717 | 717 | [TCPHDR_ACK|TCPHDR_URG] = 1, |
718 | 718 | }; |
719 | 719 | |
720 | -static void tcp_error_log(const struct sk_buff *skb, struct net *net, | |
721 | - u8 pf, const char *msg) | |
720 | +static void tcp_error_log(const struct sk_buff *skb, | |
721 | + const struct nf_hook_state *state, | |
722 | + const char *msg) | |
722 | 723 | { |
723 | - nf_l4proto_log_invalid(skb, net, pf, IPPROTO_TCP, "%s", msg); | |
724 | + nf_l4proto_log_invalid(skb, state->net, state->pf, IPPROTO_TCP, "%s", msg); | |
724 | 725 | } |
725 | 726 | |
726 | 727 | /* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c. */ |
727 | -static int tcp_error(struct net *net, struct nf_conn *tmpl, | |
728 | +static int tcp_error(struct nf_conn *tmpl, | |
728 | 729 | struct sk_buff *skb, |
729 | 730 | unsigned int dataoff, |
730 | - u_int8_t pf, | |
731 | - unsigned int hooknum) | |
731 | + const struct nf_hook_state *state) | |
732 | 732 | { |
733 | 733 | const struct tcphdr *th; |
734 | 734 | struct tcphdr _tcph; |
735 | 735 | |
... | ... | @@ -738,13 +738,13 @@ |
738 | 738 | /* Smaller that minimal TCP header? */ |
739 | 739 | th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph); |
740 | 740 | if (th == NULL) { |
741 | - tcp_error_log(skb, net, pf, "short packet"); | |
741 | + tcp_error_log(skb, state, "short packet"); | |
742 | 742 | return -NF_ACCEPT; |
743 | 743 | } |
744 | 744 | |
745 | 745 | /* Not whole TCP header or malformed packet */ |
746 | 746 | if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) { |
747 | - tcp_error_log(skb, net, pf, "truncated packet"); | |
747 | + tcp_error_log(skb, state, "truncated packet"); | |
748 | 748 | return -NF_ACCEPT; |
749 | 749 | } |
750 | 750 | |
751 | 751 | |
... | ... | @@ -753,16 +753,17 @@ |
753 | 753 | * because the checksum is assumed to be correct. |
754 | 754 | */ |
755 | 755 | /* FIXME: Source route IP option packets --RR */ |
756 | - if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && | |
757 | - nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) { | |
758 | - tcp_error_log(skb, net, pf, "bad checksum"); | |
756 | + if (state->net->ct.sysctl_checksum && | |
757 | + state->hook == NF_INET_PRE_ROUTING && | |
758 | + nf_checksum(skb, state->hook, dataoff, IPPROTO_TCP, state->pf)) { | |
759 | + tcp_error_log(skb, state, "bad checksum"); | |
759 | 760 | return -NF_ACCEPT; |
760 | 761 | } |
761 | 762 | |
762 | 763 | /* Check TCP flags. */ |
763 | 764 | tcpflags = (tcp_flag_byte(th) & ~(TCPHDR_ECE|TCPHDR_CWR|TCPHDR_PSH)); |
764 | 765 | if (!tcp_valid_flags[tcpflags]) { |
765 | - tcp_error_log(skb, net, pf, "invalid tcp flag combination"); | |
766 | + tcp_error_log(skb, state, "invalid tcp flag combination"); | |
766 | 767 | return -NF_ACCEPT; |
767 | 768 | } |
768 | 769 | |
... | ... | @@ -773,7 +774,8 @@ |
773 | 774 | static int tcp_packet(struct nf_conn *ct, |
774 | 775 | const struct sk_buff *skb, |
775 | 776 | unsigned int dataoff, |
776 | - enum ip_conntrack_info ctinfo) | |
777 | + enum ip_conntrack_info ctinfo, | |
778 | + const struct nf_hook_state *state) | |
777 | 779 | { |
778 | 780 | struct net *net = nf_ct_net(ct); |
779 | 781 | struct nf_tcp_net *tn = tcp_pernet(net); |
net/netfilter/nf_conntrack_proto_udp.c
... | ... | @@ -46,7 +46,8 @@ |
46 | 46 | static int udp_packet(struct nf_conn *ct, |
47 | 47 | const struct sk_buff *skb, |
48 | 48 | unsigned int dataoff, |
49 | - enum ip_conntrack_info ctinfo) | |
49 | + enum ip_conntrack_info ctinfo, | |
50 | + const struct nf_hook_state *state) | |
50 | 51 | { |
51 | 52 | unsigned int *timeouts; |
52 | 53 | |
53 | 54 | |
54 | 55 | |
55 | 56 | |
... | ... | @@ -77,16 +78,17 @@ |
77 | 78 | } |
78 | 79 | |
79 | 80 | #ifdef CONFIG_NF_CT_PROTO_UDPLITE |
80 | -static void udplite_error_log(const struct sk_buff *skb, struct net *net, | |
81 | - u8 pf, const char *msg) | |
81 | +static void udplite_error_log(const struct sk_buff *skb, | |
82 | + const struct nf_hook_state *state, | |
83 | + const char *msg) | |
82 | 84 | { |
83 | - nf_l4proto_log_invalid(skb, net, pf, IPPROTO_UDPLITE, "%s", msg); | |
85 | + nf_l4proto_log_invalid(skb, state->net, state->pf, | |
86 | + IPPROTO_UDPLITE, "%s", msg); | |
84 | 87 | } |
85 | 88 | |
86 | -static int udplite_error(struct net *net, struct nf_conn *tmpl, | |
87 | - struct sk_buff *skb, | |
89 | +static int udplite_error(struct nf_conn *tmpl, struct sk_buff *skb, | |
88 | 90 | unsigned int dataoff, |
89 | - u8 pf, unsigned int hooknum) | |
91 | + const struct nf_hook_state *state) | |
90 | 92 | { |
91 | 93 | unsigned int udplen = skb->len - dataoff; |
92 | 94 | const struct udphdr *hdr; |
... | ... | @@ -96,7 +98,7 @@ |
96 | 98 | /* Header is too small? */ |
97 | 99 | hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); |
98 | 100 | if (!hdr) { |
99 | - udplite_error_log(skb, net, pf, "short packet"); | |
101 | + udplite_error_log(skb, state, "short packet"); | |
100 | 102 | return -NF_ACCEPT; |
101 | 103 | } |
102 | 104 | |
103 | 105 | |
104 | 106 | |
... | ... | @@ -104,21 +106,22 @@ |
104 | 106 | if (cscov == 0) { |
105 | 107 | cscov = udplen; |
106 | 108 | } else if (cscov < sizeof(*hdr) || cscov > udplen) { |
107 | - udplite_error_log(skb, net, pf, "invalid checksum coverage"); | |
109 | + udplite_error_log(skb, state, "invalid checksum coverage"); | |
108 | 110 | return -NF_ACCEPT; |
109 | 111 | } |
110 | 112 | |
111 | 113 | /* UDPLITE mandates checksums */ |
112 | 114 | if (!hdr->check) { |
113 | - udplite_error_log(skb, net, pf, "checksum missing"); | |
115 | + udplite_error_log(skb, state, "checksum missing"); | |
114 | 116 | return -NF_ACCEPT; |
115 | 117 | } |
116 | 118 | |
117 | 119 | /* Checksum invalid? Ignore. */ |
118 | - if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && | |
119 | - nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_UDP, | |
120 | - pf)) { | |
121 | - udplite_error_log(skb, net, pf, "bad checksum"); | |
120 | + if (state->hook == NF_INET_PRE_ROUTING && | |
121 | + state->net->ct.sysctl_checksum && | |
122 | + nf_checksum_partial(skb, state->hook, dataoff, cscov, IPPROTO_UDP, | |
123 | + state->pf)) { | |
124 | + udplite_error_log(skb, state, "bad checksum"); | |
122 | 125 | return -NF_ACCEPT; |
123 | 126 | } |
124 | 127 | |
125 | 128 | |
126 | 129 | |
127 | 130 | |
... | ... | @@ -126,16 +129,17 @@ |
126 | 129 | } |
127 | 130 | #endif |
128 | 131 | |
129 | -static void udp_error_log(const struct sk_buff *skb, struct net *net, | |
130 | - u8 pf, const char *msg) | |
132 | +static void udp_error_log(const struct sk_buff *skb, | |
133 | + const struct nf_hook_state *state, | |
134 | + const char *msg) | |
131 | 135 | { |
132 | - nf_l4proto_log_invalid(skb, net, pf, IPPROTO_UDP, "%s", msg); | |
136 | + nf_l4proto_log_invalid(skb, state->net, state->pf, | |
137 | + IPPROTO_UDP, "%s", msg); | |
133 | 138 | } |
134 | 139 | |
135 | -static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, | |
140 | +static int udp_error(struct nf_conn *tmpl, struct sk_buff *skb, | |
136 | 141 | unsigned int dataoff, |
137 | - u_int8_t pf, | |
138 | - unsigned int hooknum) | |
142 | + const struct nf_hook_state *state) | |
139 | 143 | { |
140 | 144 | unsigned int udplen = skb->len - dataoff; |
141 | 145 | const struct udphdr *hdr; |
142 | 146 | |
... | ... | @@ -144,13 +148,13 @@ |
144 | 148 | /* Header is too small? */ |
145 | 149 | hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); |
146 | 150 | if (hdr == NULL) { |
147 | - udp_error_log(skb, net, pf, "short packet"); | |
151 | + udp_error_log(skb, state, "short packet"); | |
148 | 152 | return -NF_ACCEPT; |
149 | 153 | } |
150 | 154 | |
151 | 155 | /* Truncated/malformed packets */ |
152 | 156 | if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) { |
153 | - udp_error_log(skb, net, pf, "truncated/malformed packet"); | |
157 | + udp_error_log(skb, state, "truncated/malformed packet"); | |
154 | 158 | return -NF_ACCEPT; |
155 | 159 | } |
156 | 160 | |
... | ... | @@ -162,9 +166,9 @@ |
162 | 166 | * We skip checking packets on the outgoing path |
163 | 167 | * because the checksum is assumed to be correct. |
164 | 168 | * FIXME: Source route IP option packets --RR */ |
165 | - if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && | |
166 | - nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) { | |
167 | - udp_error_log(skb, net, pf, "bad checksum"); | |
169 | + if (state->net->ct.sysctl_checksum && state->hook == NF_INET_PRE_ROUTING && | |
170 | + nf_checksum(skb, state->hook, dataoff, IPPROTO_UDP, state->pf)) { | |
171 | + udp_error_log(skb, state, "bad checksum"); | |
168 | 172 | return -NF_ACCEPT; |
169 | 173 | } |
170 | 174 |
net/openvswitch/conntrack.c
... | ... | @@ -933,6 +933,11 @@ |
933 | 933 | struct nf_conn *ct; |
934 | 934 | |
935 | 935 | if (!cached) { |
936 | + struct nf_hook_state state = { | |
937 | + .hook = NF_INET_PRE_ROUTING, | |
938 | + .pf = info->family, | |
939 | + .net = net, | |
940 | + }; | |
936 | 941 | struct nf_conn *tmpl = info->ct; |
937 | 942 | int err; |
938 | 943 | |
... | ... | @@ -944,8 +949,7 @@ |
944 | 949 | nf_ct_set(skb, tmpl, IP_CT_NEW); |
945 | 950 | } |
946 | 951 | |
947 | - err = nf_conntrack_in(net, info->family, | |
948 | - NF_INET_PRE_ROUTING, skb); | |
952 | + err = nf_conntrack_in(skb, &state); | |
949 | 953 | if (err != NF_ACCEPT) |
950 | 954 | return -ENOENT; |
951 | 955 |