Commit 93e66024b0249cec81e91328c55a754efd3192e0

Authored by Florian Westphal
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
... ... @@ -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