diff options
author | Patrick McHardy <kaber@trash.net> | 2006-11-28 20:35:25 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-03 00:31:22 -0500 |
commit | 337fbc4166967a72c3cc71c597bdde7e6a8633ab (patch) | |
tree | 95b2d47e55db3991f66090525b7e28455a6ca39b | |
parent | 468ec44bd5a863736d955f78b8c38896f26864a1 (diff) |
[NETFILTER]: ip_conntrack: fix NAT helper unload races
The NAT helpr hooks are protected by RCU, but all of the
conntrack helpers test and use the global pointers instead
of copying them first using rcu_dereference()
Also replace synchronize_net() by synchronize_rcu() for clarity
since sychronizing only with packet receive processing is
insufficient to prevent races.
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_amanda.c | 9 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_ftp.c | 8 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_helper_h323.c | 164 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_helper_pptp.c | 29 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_irc.c | 12 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_sip.c | 12 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_tftp.c | 6 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_amanda.c | 9 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_ftp.c | 9 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_helper_h323.c | 58 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_helper_pptp.c | 27 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_irc.c | 9 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_sip.c | 15 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_nat_tftp.c | 9 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_ftp.c | 9 |
15 files changed, 216 insertions, 169 deletions
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c index 7fca246615d5..ad246ba7790b 100644 --- a/net/ipv4/netfilter/ip_conntrack_amanda.c +++ b/net/ipv4/netfilter/ip_conntrack_amanda.c | |||
@@ -92,6 +92,7 @@ static int help(struct sk_buff **pskb, | |||
92 | char pbuf[sizeof("65535")], *tmp; | 92 | char pbuf[sizeof("65535")], *tmp; |
93 | u_int16_t port, len; | 93 | u_int16_t port, len; |
94 | int ret = NF_ACCEPT; | 94 | int ret = NF_ACCEPT; |
95 | typeof(ip_nat_amanda_hook) ip_nat_amanda; | ||
95 | 96 | ||
96 | /* Only look at packets from the Amanda server */ | 97 | /* Only look at packets from the Amanda server */ |
97 | if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) | 98 | if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) |
@@ -161,9 +162,11 @@ static int help(struct sk_buff **pskb, | |||
161 | exp->mask.dst.protonum = 0xFF; | 162 | exp->mask.dst.protonum = 0xFF; |
162 | exp->mask.dst.u.tcp.port = htons(0xFFFF); | 163 | exp->mask.dst.u.tcp.port = htons(0xFFFF); |
163 | 164 | ||
164 | if (ip_nat_amanda_hook) | 165 | /* RCU read locked by nf_hook_slow */ |
165 | ret = ip_nat_amanda_hook(pskb, ctinfo, off - dataoff, | 166 | ip_nat_amanda = rcu_dereference(ip_nat_amanda_hook); |
166 | len, exp); | 167 | if (ip_nat_amanda) |
168 | ret = ip_nat_amanda(pskb, ctinfo, off - dataoff, | ||
169 | len, exp); | ||
167 | else if (ip_conntrack_expect_related(exp) != 0) | 170 | else if (ip_conntrack_expect_related(exp) != 0) |
168 | ret = NF_DROP; | 171 | ret = NF_DROP; |
169 | ip_conntrack_expect_put(exp); | 172 | ip_conntrack_expect_put(exp); |
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c index 93dcf960662f..0410c99cacae 100644 --- a/net/ipv4/netfilter/ip_conntrack_ftp.c +++ b/net/ipv4/netfilter/ip_conntrack_ftp.c | |||
@@ -310,6 +310,7 @@ static int help(struct sk_buff **pskb, | |||
310 | struct ip_conntrack_expect *exp; | 310 | struct ip_conntrack_expect *exp; |
311 | unsigned int i; | 311 | unsigned int i; |
312 | int found = 0, ends_in_nl; | 312 | int found = 0, ends_in_nl; |
313 | typeof(ip_nat_ftp_hook) ip_nat_ftp; | ||
313 | 314 | ||
314 | /* Until there's been traffic both ways, don't look in packets. */ | 315 | /* Until there's been traffic both ways, don't look in packets. */ |
315 | if (ctinfo != IP_CT_ESTABLISHED | 316 | if (ctinfo != IP_CT_ESTABLISHED |
@@ -433,9 +434,10 @@ static int help(struct sk_buff **pskb, | |||
433 | 434 | ||
434 | /* Now, NAT might want to mangle the packet, and register the | 435 | /* Now, NAT might want to mangle the packet, and register the |
435 | * (possibly changed) expectation itself. */ | 436 | * (possibly changed) expectation itself. */ |
436 | if (ip_nat_ftp_hook) | 437 | ip_nat_ftp = rcu_dereference(ip_nat_ftp_hook); |
437 | ret = ip_nat_ftp_hook(pskb, ctinfo, search[dir][i].ftptype, | 438 | if (ip_nat_ftp) |
438 | matchoff, matchlen, exp, &seq); | 439 | ret = ip_nat_ftp(pskb, ctinfo, search[dir][i].ftptype, |
440 | matchoff, matchlen, exp, &seq); | ||
439 | else { | 441 | else { |
440 | /* Can't expect this? Best to drop packet now. */ | 442 | /* Can't expect this? Best to drop packet now. */ |
441 | if (ip_conntrack_expect_related(exp) != 0) | 443 | if (ip_conntrack_expect_related(exp) != 0) |
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c index a06b340ea414..aabfe1c06905 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c | |||
@@ -237,6 +237,7 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
237 | u_int16_t rtp_port; | 237 | u_int16_t rtp_port; |
238 | struct ip_conntrack_expect *rtp_exp; | 238 | struct ip_conntrack_expect *rtp_exp; |
239 | struct ip_conntrack_expect *rtcp_exp; | 239 | struct ip_conntrack_expect *rtcp_exp; |
240 | typeof(nat_rtp_rtcp_hook) nat_rtp_rtcp; | ||
240 | 241 | ||
241 | /* Read RTP or RTCP address */ | 242 | /* Read RTP or RTCP address */ |
242 | if (!get_h245_addr(*data, addr, &ip, &port) || | 243 | if (!get_h245_addr(*data, addr, &ip, &port) || |
@@ -279,11 +280,11 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
279 | rtcp_exp->flags = 0; | 280 | rtcp_exp->flags = 0; |
280 | 281 | ||
281 | if (ct->tuplehash[dir].tuple.src.ip != | 282 | if (ct->tuplehash[dir].tuple.src.ip != |
282 | ct->tuplehash[!dir].tuple.dst.ip && nat_rtp_rtcp_hook) { | 283 | ct->tuplehash[!dir].tuple.dst.ip && |
284 | (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook))) { | ||
283 | /* NAT needed */ | 285 | /* NAT needed */ |
284 | ret = nat_rtp_rtcp_hook(pskb, ct, ctinfo, data, dataoff, | 286 | ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, |
285 | addr, port, rtp_port, rtp_exp, | 287 | addr, port, rtp_port, rtp_exp, rtcp_exp); |
286 | rtcp_exp); | ||
287 | } else { /* Conntrack only */ | 288 | } else { /* Conntrack only */ |
288 | rtp_exp->expectfn = NULL; | 289 | rtp_exp->expectfn = NULL; |
289 | rtcp_exp->expectfn = NULL; | 290 | rtcp_exp->expectfn = NULL; |
@@ -328,6 +329,7 @@ static int expect_t120(struct sk_buff **pskb, | |||
328 | __be32 ip; | 329 | __be32 ip; |
329 | u_int16_t port; | 330 | u_int16_t port; |
330 | struct ip_conntrack_expect *exp = NULL; | 331 | struct ip_conntrack_expect *exp = NULL; |
332 | typeof(nat_t120_hook) nat_t120; | ||
331 | 333 | ||
332 | /* Read T.120 address */ | 334 | /* Read T.120 address */ |
333 | if (!get_h245_addr(*data, addr, &ip, &port) || | 335 | if (!get_h245_addr(*data, addr, &ip, &port) || |
@@ -350,10 +352,11 @@ static int expect_t120(struct sk_buff **pskb, | |||
350 | exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple channels */ | 352 | exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple channels */ |
351 | 353 | ||
352 | if (ct->tuplehash[dir].tuple.src.ip != | 354 | if (ct->tuplehash[dir].tuple.src.ip != |
353 | ct->tuplehash[!dir].tuple.dst.ip && nat_t120_hook) { | 355 | ct->tuplehash[!dir].tuple.dst.ip && |
356 | (nat_t120 = rcu_dereference(nat_t120_hook))) { | ||
354 | /* NAT needed */ | 357 | /* NAT needed */ |
355 | ret = nat_t120_hook(pskb, ct, ctinfo, data, dataoff, addr, | 358 | ret = nat_t120(pskb, ct, ctinfo, data, dataoff, addr, |
356 | port, exp); | 359 | port, exp); |
357 | } else { /* Conntrack only */ | 360 | } else { /* Conntrack only */ |
358 | exp->expectfn = NULL; | 361 | exp->expectfn = NULL; |
359 | if (ip_conntrack_expect_related(exp) == 0) { | 362 | if (ip_conntrack_expect_related(exp) == 0) { |
@@ -651,6 +654,7 @@ static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
651 | __be32 ip; | 654 | __be32 ip; |
652 | u_int16_t port; | 655 | u_int16_t port; |
653 | struct ip_conntrack_expect *exp = NULL; | 656 | struct ip_conntrack_expect *exp = NULL; |
657 | typeof(nat_h245_hook) nat_h245; | ||
654 | 658 | ||
655 | /* Read h245Address */ | 659 | /* Read h245Address */ |
656 | if (!get_h225_addr(*data, addr, &ip, &port) || | 660 | if (!get_h225_addr(*data, addr, &ip, &port) || |
@@ -673,10 +677,11 @@ static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
673 | exp->flags = 0; | 677 | exp->flags = 0; |
674 | 678 | ||
675 | if (ct->tuplehash[dir].tuple.src.ip != | 679 | if (ct->tuplehash[dir].tuple.src.ip != |
676 | ct->tuplehash[!dir].tuple.dst.ip && nat_h245_hook) { | 680 | ct->tuplehash[!dir].tuple.dst.ip && |
681 | (nat_h245 = rcu_dereference(nat_h245_hook))) { | ||
677 | /* NAT needed */ | 682 | /* NAT needed */ |
678 | ret = nat_h245_hook(pskb, ct, ctinfo, data, dataoff, addr, | 683 | ret = nat_h245(pskb, ct, ctinfo, data, dataoff, addr, |
679 | port, exp); | 684 | port, exp); |
680 | } else { /* Conntrack only */ | 685 | } else { /* Conntrack only */ |
681 | exp->expectfn = ip_conntrack_h245_expect; | 686 | exp->expectfn = ip_conntrack_h245_expect; |
682 | 687 | ||
@@ -712,6 +717,7 @@ static int expect_callforwarding(struct sk_buff **pskb, | |||
712 | __be32 ip; | 717 | __be32 ip; |
713 | u_int16_t port; | 718 | u_int16_t port; |
714 | struct ip_conntrack_expect *exp = NULL; | 719 | struct ip_conntrack_expect *exp = NULL; |
720 | typeof(nat_callforwarding_hook) nat_callforwarding; | ||
715 | 721 | ||
716 | /* Read alternativeAddress */ | 722 | /* Read alternativeAddress */ |
717 | if (!get_h225_addr(*data, addr, &ip, &port) || port == 0) | 723 | if (!get_h225_addr(*data, addr, &ip, &port) || port == 0) |
@@ -759,10 +765,11 @@ static int expect_callforwarding(struct sk_buff **pskb, | |||
759 | exp->flags = 0; | 765 | exp->flags = 0; |
760 | 766 | ||
761 | if (ct->tuplehash[dir].tuple.src.ip != | 767 | if (ct->tuplehash[dir].tuple.src.ip != |
762 | ct->tuplehash[!dir].tuple.dst.ip && nat_callforwarding_hook) { | 768 | ct->tuplehash[!dir].tuple.dst.ip && |
769 | (nat_callforwarding = rcu_dereference(nat_callforwarding_hook))) { | ||
763 | /* Need NAT */ | 770 | /* Need NAT */ |
764 | ret = nat_callforwarding_hook(pskb, ct, ctinfo, data, dataoff, | 771 | ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff, |
765 | addr, port, exp); | 772 | addr, port, exp); |
766 | } else { /* Conntrack only */ | 773 | } else { /* Conntrack only */ |
767 | exp->expectfn = ip_conntrack_q931_expect; | 774 | exp->expectfn = ip_conntrack_q931_expect; |
768 | 775 | ||
@@ -793,6 +800,7 @@ static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
793 | int i; | 800 | int i; |
794 | __be32 ip; | 801 | __be32 ip; |
795 | u_int16_t port; | 802 | u_int16_t port; |
803 | typeof(set_h225_addr_hook) set_h225_addr; | ||
796 | 804 | ||
797 | DEBUGP("ip_ct_q931: Setup\n"); | 805 | DEBUGP("ip_ct_q931: Setup\n"); |
798 | 806 | ||
@@ -803,8 +811,10 @@ static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
803 | return -1; | 811 | return -1; |
804 | } | 812 | } |
805 | 813 | ||
814 | set_h225_addr = rcu_dereference(set_h225_addr_hook); | ||
815 | |||
806 | if ((setup->options & eSetup_UUIE_destCallSignalAddress) && | 816 | if ((setup->options & eSetup_UUIE_destCallSignalAddress) && |
807 | (set_h225_addr_hook) && | 817 | (set_h225_addr) && |
808 | get_h225_addr(*data, &setup->destCallSignalAddress, &ip, &port) && | 818 | get_h225_addr(*data, &setup->destCallSignalAddress, &ip, &port) && |
809 | ip != ct->tuplehash[!dir].tuple.src.ip) { | 819 | ip != ct->tuplehash[!dir].tuple.src.ip) { |
810 | DEBUGP("ip_ct_q931: set destCallSignalAddress " | 820 | DEBUGP("ip_ct_q931: set destCallSignalAddress " |
@@ -812,17 +822,17 @@ static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
812 | NIPQUAD(ip), port, | 822 | NIPQUAD(ip), port, |
813 | NIPQUAD(ct->tuplehash[!dir].tuple.src.ip), | 823 | NIPQUAD(ct->tuplehash[!dir].tuple.src.ip), |
814 | ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port)); | 824 | ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port)); |
815 | ret = set_h225_addr_hook(pskb, data, dataoff, | 825 | ret = set_h225_addr(pskb, data, dataoff, |
816 | &setup->destCallSignalAddress, | 826 | &setup->destCallSignalAddress, |
817 | ct->tuplehash[!dir].tuple.src.ip, | 827 | ct->tuplehash[!dir].tuple.src.ip, |
818 | ntohs(ct->tuplehash[!dir].tuple.src. | 828 | ntohs(ct->tuplehash[!dir].tuple.src. |
819 | u.tcp.port)); | 829 | u.tcp.port)); |
820 | if (ret < 0) | 830 | if (ret < 0) |
821 | return -1; | 831 | return -1; |
822 | } | 832 | } |
823 | 833 | ||
824 | if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) && | 834 | if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) && |
825 | (set_h225_addr_hook) && | 835 | (set_h225_addr) && |
826 | get_h225_addr(*data, &setup->sourceCallSignalAddress, &ip, &port) | 836 | get_h225_addr(*data, &setup->sourceCallSignalAddress, &ip, &port) |
827 | && ip != ct->tuplehash[!dir].tuple.dst.ip) { | 837 | && ip != ct->tuplehash[!dir].tuple.dst.ip) { |
828 | DEBUGP("ip_ct_q931: set sourceCallSignalAddress " | 838 | DEBUGP("ip_ct_q931: set sourceCallSignalAddress " |
@@ -830,11 +840,11 @@ static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
830 | NIPQUAD(ip), port, | 840 | NIPQUAD(ip), port, |
831 | NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip), | 841 | NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip), |
832 | ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port)); | 842 | ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port)); |
833 | ret = set_h225_addr_hook(pskb, data, dataoff, | 843 | ret = set_h225_addr(pskb, data, dataoff, |
834 | &setup->sourceCallSignalAddress, | 844 | &setup->sourceCallSignalAddress, |
835 | ct->tuplehash[!dir].tuple.dst.ip, | 845 | ct->tuplehash[!dir].tuple.dst.ip, |
836 | ntohs(ct->tuplehash[!dir].tuple.dst. | 846 | ntohs(ct->tuplehash[!dir].tuple.dst. |
837 | u.tcp.port)); | 847 | u.tcp.port)); |
838 | if (ret < 0) | 848 | if (ret < 0) |
839 | return -1; | 849 | return -1; |
840 | } | 850 | } |
@@ -1231,6 +1241,7 @@ static int expect_q931(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
1231 | __be32 ip; | 1241 | __be32 ip; |
1232 | u_int16_t port; | 1242 | u_int16_t port; |
1233 | struct ip_conntrack_expect *exp; | 1243 | struct ip_conntrack_expect *exp; |
1244 | typeof(nat_q931_hook) nat_q931; | ||
1234 | 1245 | ||
1235 | /* Look for the first related address */ | 1246 | /* Look for the first related address */ |
1236 | for (i = 0; i < count; i++) { | 1247 | for (i = 0; i < count; i++) { |
@@ -1258,9 +1269,9 @@ static int expect_q931(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
1258 | exp->mask.dst.protonum = 0xFF; | 1269 | exp->mask.dst.protonum = 0xFF; |
1259 | exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple calls */ | 1270 | exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple calls */ |
1260 | 1271 | ||
1261 | if (nat_q931_hook) { /* Need NAT */ | 1272 | nat_q931 = rcu_dereference(nat_q931_hook); |
1262 | ret = nat_q931_hook(pskb, ct, ctinfo, data, addr, i, | 1273 | if (nat_q931) { /* Need NAT */ |
1263 | port, exp); | 1274 | ret = nat_q931(pskb, ct, ctinfo, data, addr, i, port, exp); |
1264 | } else { /* Conntrack only */ | 1275 | } else { /* Conntrack only */ |
1265 | exp->expectfn = ip_conntrack_q931_expect; | 1276 | exp->expectfn = ip_conntrack_q931_expect; |
1266 | 1277 | ||
@@ -1288,11 +1299,14 @@ static int process_grq(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
1288 | enum ip_conntrack_info ctinfo, | 1299 | enum ip_conntrack_info ctinfo, |
1289 | unsigned char **data, GatekeeperRequest * grq) | 1300 | unsigned char **data, GatekeeperRequest * grq) |
1290 | { | 1301 | { |
1302 | typeof(set_ras_addr_hook) set_ras_addr; | ||
1303 | |||
1291 | DEBUGP("ip_ct_ras: GRQ\n"); | 1304 | DEBUGP("ip_ct_ras: GRQ\n"); |
1292 | 1305 | ||
1293 | if (set_ras_addr_hook) /* NATed */ | 1306 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
1294 | return set_ras_addr_hook(pskb, ct, ctinfo, data, | 1307 | if (set_ras_addr) /* NATed */ |
1295 | &grq->rasAddress, 1); | 1308 | return set_ras_addr(pskb, ct, ctinfo, data, |
1309 | &grq->rasAddress, 1); | ||
1296 | return 0; | 1310 | return 0; |
1297 | } | 1311 | } |
1298 | 1312 | ||
@@ -1362,6 +1376,7 @@ static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
1362 | { | 1376 | { |
1363 | struct ip_ct_h323_master *info = &ct->help.ct_h323_info; | 1377 | struct ip_ct_h323_master *info = &ct->help.ct_h323_info; |
1364 | int ret; | 1378 | int ret; |
1379 | typeof(set_ras_addr_hook) set_ras_addr; | ||
1365 | 1380 | ||
1366 | DEBUGP("ip_ct_ras: RRQ\n"); | 1381 | DEBUGP("ip_ct_ras: RRQ\n"); |
1367 | 1382 | ||
@@ -1371,10 +1386,11 @@ static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
1371 | if (ret < 0) | 1386 | if (ret < 0) |
1372 | return -1; | 1387 | return -1; |
1373 | 1388 | ||
1374 | if (set_ras_addr_hook) { | 1389 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
1375 | ret = set_ras_addr_hook(pskb, ct, ctinfo, data, | 1390 | if (set_ras_addr) { |
1376 | rrq->rasAddress.item, | 1391 | ret = set_ras_addr(pskb, ct, ctinfo, data, |
1377 | rrq->rasAddress.count); | 1392 | rrq->rasAddress.item, |
1393 | rrq->rasAddress.count); | ||
1378 | if (ret < 0) | 1394 | if (ret < 0) |
1379 | return -1; | 1395 | return -1; |
1380 | } | 1396 | } |
@@ -1397,13 +1413,15 @@ static int process_rcf(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
1397 | int dir = CTINFO2DIR(ctinfo); | 1413 | int dir = CTINFO2DIR(ctinfo); |
1398 | int ret; | 1414 | int ret; |
1399 | struct ip_conntrack_expect *exp; | 1415 | struct ip_conntrack_expect *exp; |
1416 | typeof(set_sig_addr_hook) set_sig_addr; | ||
1400 | 1417 | ||
1401 | DEBUGP("ip_ct_ras: RCF\n"); | 1418 | DEBUGP("ip_ct_ras: RCF\n"); |
1402 | 1419 | ||
1403 | if (set_sig_addr_hook) { | 1420 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
1404 | ret = set_sig_addr_hook(pskb, ct, ctinfo, data, | 1421 | if (set_sig_addr) { |
1405 | rcf->callSignalAddress.item, | 1422 | ret = set_sig_addr(pskb, ct, ctinfo, data, |
1406 | rcf->callSignalAddress.count); | 1423 | rcf->callSignalAddress.item, |
1424 | rcf->callSignalAddress.count); | ||
1407 | if (ret < 0) | 1425 | if (ret < 0) |
1408 | return -1; | 1426 | return -1; |
1409 | } | 1427 | } |
@@ -1448,13 +1466,15 @@ static int process_urq(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
1448 | struct ip_ct_h323_master *info = &ct->help.ct_h323_info; | 1466 | struct ip_ct_h323_master *info = &ct->help.ct_h323_info; |
1449 | int dir = CTINFO2DIR(ctinfo); | 1467 | int dir = CTINFO2DIR(ctinfo); |
1450 | int ret; | 1468 | int ret; |
1469 | typeof(set_sig_addr_hook) set_sig_addr; | ||
1451 | 1470 | ||
1452 | DEBUGP("ip_ct_ras: URQ\n"); | 1471 | DEBUGP("ip_ct_ras: URQ\n"); |
1453 | 1472 | ||
1454 | if (set_sig_addr_hook) { | 1473 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
1455 | ret = set_sig_addr_hook(pskb, ct, ctinfo, data, | 1474 | if (set_sig_addr) { |
1456 | urq->callSignalAddress.item, | 1475 | ret = set_sig_addr(pskb, ct, ctinfo, data, |
1457 | urq->callSignalAddress.count); | 1476 | urq->callSignalAddress.item, |
1477 | urq->callSignalAddress.count); | ||
1458 | if (ret < 0) | 1478 | if (ret < 0) |
1459 | return -1; | 1479 | return -1; |
1460 | } | 1480 | } |
@@ -1479,28 +1499,30 @@ static int process_arq(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
1479 | int dir = CTINFO2DIR(ctinfo); | 1499 | int dir = CTINFO2DIR(ctinfo); |
1480 | __be32 ip; | 1500 | __be32 ip; |
1481 | u_int16_t port; | 1501 | u_int16_t port; |
1502 | typeof(set_h225_addr_hook) set_h225_addr; | ||
1482 | 1503 | ||
1483 | DEBUGP("ip_ct_ras: ARQ\n"); | 1504 | DEBUGP("ip_ct_ras: ARQ\n"); |
1484 | 1505 | ||
1506 | set_h225_addr = rcu_dereference(set_h225_addr_hook); | ||
1485 | if ((arq->options & eAdmissionRequest_destCallSignalAddress) && | 1507 | if ((arq->options & eAdmissionRequest_destCallSignalAddress) && |
1486 | get_h225_addr(*data, &arq->destCallSignalAddress, &ip, &port) && | 1508 | get_h225_addr(*data, &arq->destCallSignalAddress, &ip, &port) && |
1487 | ip == ct->tuplehash[dir].tuple.src.ip && | 1509 | ip == ct->tuplehash[dir].tuple.src.ip && |
1488 | port == info->sig_port[dir] && set_h225_addr_hook) { | 1510 | port == info->sig_port[dir] && set_h225_addr) { |
1489 | /* Answering ARQ */ | 1511 | /* Answering ARQ */ |
1490 | return set_h225_addr_hook(pskb, data, 0, | 1512 | return set_h225_addr(pskb, data, 0, |
1491 | &arq->destCallSignalAddress, | 1513 | &arq->destCallSignalAddress, |
1492 | ct->tuplehash[!dir].tuple.dst.ip, | 1514 | ct->tuplehash[!dir].tuple.dst.ip, |
1493 | info->sig_port[!dir]); | 1515 | info->sig_port[!dir]); |
1494 | } | 1516 | } |
1495 | 1517 | ||
1496 | if ((arq->options & eAdmissionRequest_srcCallSignalAddress) && | 1518 | if ((arq->options & eAdmissionRequest_srcCallSignalAddress) && |
1497 | get_h225_addr(*data, &arq->srcCallSignalAddress, &ip, &port) && | 1519 | get_h225_addr(*data, &arq->srcCallSignalAddress, &ip, &port) && |
1498 | ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr_hook) { | 1520 | ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr) { |
1499 | /* Calling ARQ */ | 1521 | /* Calling ARQ */ |
1500 | return set_h225_addr_hook(pskb, data, 0, | 1522 | return set_h225_addr(pskb, data, 0, |
1501 | &arq->srcCallSignalAddress, | 1523 | &arq->srcCallSignalAddress, |
1502 | ct->tuplehash[!dir].tuple.dst.ip, | 1524 | ct->tuplehash[!dir].tuple.dst.ip, |
1503 | port); | 1525 | port); |
1504 | } | 1526 | } |
1505 | 1527 | ||
1506 | return 0; | 1528 | return 0; |
@@ -1516,6 +1538,7 @@ static int process_acf(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
1516 | __be32 ip; | 1538 | __be32 ip; |
1517 | u_int16_t port; | 1539 | u_int16_t port; |
1518 | struct ip_conntrack_expect *exp; | 1540 | struct ip_conntrack_expect *exp; |
1541 | typeof(set_sig_addr_hook) set_sig_addr; | ||
1519 | 1542 | ||
1520 | DEBUGP("ip_ct_ras: ACF\n"); | 1543 | DEBUGP("ip_ct_ras: ACF\n"); |
1521 | 1544 | ||
@@ -1523,10 +1546,10 @@ static int process_acf(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
1523 | return 0; | 1546 | return 0; |
1524 | 1547 | ||
1525 | if (ip == ct->tuplehash[dir].tuple.dst.ip) { /* Answering ACF */ | 1548 | if (ip == ct->tuplehash[dir].tuple.dst.ip) { /* Answering ACF */ |
1526 | if (set_sig_addr_hook) | 1549 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
1527 | return set_sig_addr_hook(pskb, ct, ctinfo, data, | 1550 | if (set_sig_addr) |
1528 | &acf->destCallSignalAddress, | 1551 | return set_sig_addr(pskb, ct, ctinfo, data, |
1529 | 1); | 1552 | &acf->destCallSignalAddress, 1); |
1530 | return 0; | 1553 | return 0; |
1531 | } | 1554 | } |
1532 | 1555 | ||
@@ -1566,11 +1589,14 @@ static int process_lrq(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
1566 | enum ip_conntrack_info ctinfo, | 1589 | enum ip_conntrack_info ctinfo, |
1567 | unsigned char **data, LocationRequest * lrq) | 1590 | unsigned char **data, LocationRequest * lrq) |
1568 | { | 1591 | { |
1592 | typeof(set_ras_addr_hook) set_ras_addr; | ||
1593 | |||
1569 | DEBUGP("ip_ct_ras: LRQ\n"); | 1594 | DEBUGP("ip_ct_ras: LRQ\n"); |
1570 | 1595 | ||
1571 | if (set_ras_addr_hook) | 1596 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
1572 | return set_ras_addr_hook(pskb, ct, ctinfo, data, | 1597 | if (set_ras_addr) |
1573 | &lrq->replyAddress, 1); | 1598 | return set_ras_addr(pskb, ct, ctinfo, data, |
1599 | &lrq->replyAddress, 1); | ||
1574 | return 0; | 1600 | return 0; |
1575 | } | 1601 | } |
1576 | 1602 | ||
@@ -1629,20 +1655,24 @@ static int process_irr(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
1629 | unsigned char **data, InfoRequestResponse * irr) | 1655 | unsigned char **data, InfoRequestResponse * irr) |
1630 | { | 1656 | { |
1631 | int ret; | 1657 | int ret; |
1658 | typeof(set_ras_addr_hook) set_ras_addr; | ||
1659 | typeof(set_sig_addr_hook) set_sig_addr; | ||
1632 | 1660 | ||
1633 | DEBUGP("ip_ct_ras: IRR\n"); | 1661 | DEBUGP("ip_ct_ras: IRR\n"); |
1634 | 1662 | ||
1635 | if (set_ras_addr_hook) { | 1663 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
1636 | ret = set_ras_addr_hook(pskb, ct, ctinfo, data, | 1664 | if (set_ras_addr) { |
1637 | &irr->rasAddress, 1); | 1665 | ret = set_ras_addr(pskb, ct, ctinfo, data, |
1666 | &irr->rasAddress, 1); | ||
1638 | if (ret < 0) | 1667 | if (ret < 0) |
1639 | return -1; | 1668 | return -1; |
1640 | } | 1669 | } |
1641 | 1670 | ||
1642 | if (set_sig_addr_hook) { | 1671 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
1643 | ret = set_sig_addr_hook(pskb, ct, ctinfo, data, | 1672 | if (set_sig_addr) { |
1644 | irr->callSignalAddress.item, | 1673 | ret = set_sig_addr(pskb, ct, ctinfo, data, |
1645 | irr->callSignalAddress.count); | 1674 | irr->callSignalAddress.item, |
1675 | irr->callSignalAddress.count); | ||
1646 | if (ret < 0) | 1676 | if (ret < 0) |
1647 | return -1; | 1677 | return -1; |
1648 | } | 1678 | } |
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c index a5c057bcecf4..4d19373bbf0d 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c | |||
@@ -124,6 +124,8 @@ EXPORT_SYMBOL(pptp_msg_name); | |||
124 | static void pptp_expectfn(struct ip_conntrack *ct, | 124 | static void pptp_expectfn(struct ip_conntrack *ct, |
125 | struct ip_conntrack_expect *exp) | 125 | struct ip_conntrack_expect *exp) |
126 | { | 126 | { |
127 | typeof(ip_nat_pptp_hook_expectfn) ip_nat_pptp_expectfn; | ||
128 | |||
127 | DEBUGP("increasing timeouts\n"); | 129 | DEBUGP("increasing timeouts\n"); |
128 | 130 | ||
129 | /* increase timeout of GRE data channel conntrack entry */ | 131 | /* increase timeout of GRE data channel conntrack entry */ |
@@ -133,7 +135,9 @@ static void pptp_expectfn(struct ip_conntrack *ct, | |||
133 | /* Can you see how rusty this code is, compared with the pre-2.6.11 | 135 | /* Can you see how rusty this code is, compared with the pre-2.6.11 |
134 | * one? That's what happened to my shiny newnat of 2002 ;( -HW */ | 136 | * one? That's what happened to my shiny newnat of 2002 ;( -HW */ |
135 | 137 | ||
136 | if (!ip_nat_pptp_hook_expectfn) { | 138 | rcu_read_lock(); |
139 | ip_nat_pptp_expectfn = rcu_dereference(ip_nat_pptp_hook_expectfn); | ||
140 | if (!ip_nat_pptp_expectfn) { | ||
137 | struct ip_conntrack_tuple inv_t; | 141 | struct ip_conntrack_tuple inv_t; |
138 | struct ip_conntrack_expect *exp_other; | 142 | struct ip_conntrack_expect *exp_other; |
139 | 143 | ||
@@ -153,8 +157,9 @@ static void pptp_expectfn(struct ip_conntrack *ct, | |||
153 | } | 157 | } |
154 | } else { | 158 | } else { |
155 | /* we need more than simple inversion */ | 159 | /* we need more than simple inversion */ |
156 | ip_nat_pptp_hook_expectfn(ct, exp); | 160 | ip_nat_pptp_expectfn(ct, exp); |
157 | } | 161 | } |
162 | rcu_read_unlock(); | ||
158 | } | 163 | } |
159 | 164 | ||
160 | static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t) | 165 | static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t) |
@@ -226,6 +231,7 @@ exp_gre(struct ip_conntrack *ct, | |||
226 | { | 231 | { |
227 | struct ip_conntrack_expect *exp_orig, *exp_reply; | 232 | struct ip_conntrack_expect *exp_orig, *exp_reply; |
228 | int ret = 1; | 233 | int ret = 1; |
234 | typeof(ip_nat_pptp_hook_exp_gre) ip_nat_pptp_exp_gre; | ||
229 | 235 | ||
230 | exp_orig = ip_conntrack_expect_alloc(ct); | 236 | exp_orig = ip_conntrack_expect_alloc(ct); |
231 | if (exp_orig == NULL) | 237 | if (exp_orig == NULL) |
@@ -262,8 +268,9 @@ exp_gre(struct ip_conntrack *ct, | |||
262 | exp_reply->tuple.dst.u.gre.key = peer_callid; | 268 | exp_reply->tuple.dst.u.gre.key = peer_callid; |
263 | exp_reply->tuple.dst.protonum = IPPROTO_GRE; | 269 | exp_reply->tuple.dst.protonum = IPPROTO_GRE; |
264 | 270 | ||
265 | if (ip_nat_pptp_hook_exp_gre) | 271 | ip_nat_pptp_exp_gre = rcu_dereference(ip_nat_pptp_hook_exp_gre); |
266 | ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply); | 272 | if (ip_nat_pptp_exp_gre) |
273 | ip_nat_pptp_exp_gre(exp_orig, exp_reply); | ||
267 | if (ip_conntrack_expect_related(exp_orig) != 0) | 274 | if (ip_conntrack_expect_related(exp_orig) != 0) |
268 | goto out_put_both; | 275 | goto out_put_both; |
269 | if (ip_conntrack_expect_related(exp_reply) != 0) | 276 | if (ip_conntrack_expect_related(exp_reply) != 0) |
@@ -303,6 +310,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
303 | struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; | 310 | struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; |
304 | u_int16_t msg; | 311 | u_int16_t msg; |
305 | __be16 cid = 0, pcid = 0; | 312 | __be16 cid = 0, pcid = 0; |
313 | typeof(ip_nat_pptp_hook_inbound) ip_nat_pptp_inbound; | ||
306 | 314 | ||
307 | msg = ntohs(ctlh->messageType); | 315 | msg = ntohs(ctlh->messageType); |
308 | DEBUGP("inbound control message %s\n", pptp_msg_name[msg]); | 316 | DEBUGP("inbound control message %s\n", pptp_msg_name[msg]); |
@@ -402,9 +410,9 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
402 | goto invalid; | 410 | goto invalid; |
403 | } | 411 | } |
404 | 412 | ||
405 | if (ip_nat_pptp_hook_inbound) | 413 | ip_nat_pptp_inbound = rcu_dereference(ip_nat_pptp_hook_inbound); |
406 | return ip_nat_pptp_hook_inbound(pskb, ct, ctinfo, ctlh, | 414 | if (ip_nat_pptp_inbound) |
407 | pptpReq); | 415 | return ip_nat_pptp_inbound(pskb, ct, ctinfo, ctlh, pptpReq); |
408 | return NF_ACCEPT; | 416 | return NF_ACCEPT; |
409 | 417 | ||
410 | invalid: | 418 | invalid: |
@@ -427,6 +435,7 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
427 | struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; | 435 | struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; |
428 | u_int16_t msg; | 436 | u_int16_t msg; |
429 | __be16 cid = 0, pcid = 0; | 437 | __be16 cid = 0, pcid = 0; |
438 | typeof(ip_nat_pptp_hook_outbound) ip_nat_pptp_outbound; | ||
430 | 439 | ||
431 | msg = ntohs(ctlh->messageType); | 440 | msg = ntohs(ctlh->messageType); |
432 | DEBUGP("outbound control message %s\n", pptp_msg_name[msg]); | 441 | DEBUGP("outbound control message %s\n", pptp_msg_name[msg]); |
@@ -492,9 +501,9 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
492 | goto invalid; | 501 | goto invalid; |
493 | } | 502 | } |
494 | 503 | ||
495 | if (ip_nat_pptp_hook_outbound) | 504 | ip_nat_pptp_outbound = rcu_dereference(ip_nat_pptp_hook_outbound); |
496 | return ip_nat_pptp_hook_outbound(pskb, ct, ctinfo, ctlh, | 505 | if (ip_nat_pptp_outbound) |
497 | pptpReq); | 506 | return ip_nat_pptp_outbound(pskb, ct, ctinfo, ctlh, pptpReq); |
498 | return NF_ACCEPT; | 507 | return NF_ACCEPT; |
499 | 508 | ||
500 | invalid: | 509 | invalid: |
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c index 75f7c3db1619..91832eca4106 100644 --- a/net/ipv4/netfilter/ip_conntrack_irc.c +++ b/net/ipv4/netfilter/ip_conntrack_irc.c | |||
@@ -114,6 +114,7 @@ static int help(struct sk_buff **pskb, | |||
114 | u_int16_t dcc_port; | 114 | u_int16_t dcc_port; |
115 | int i, ret = NF_ACCEPT; | 115 | int i, ret = NF_ACCEPT; |
116 | char *addr_beg_p, *addr_end_p; | 116 | char *addr_beg_p, *addr_end_p; |
117 | typeof(ip_nat_irc_hook) ip_nat_irc; | ||
117 | 118 | ||
118 | DEBUGP("entered\n"); | 119 | DEBUGP("entered\n"); |
119 | 120 | ||
@@ -222,11 +223,12 @@ static int help(struct sk_buff **pskb, | |||
222 | { .tcp = { htons(0xFFFF) } }, 0xFF }}); | 223 | { .tcp = { htons(0xFFFF) } }, 0xFF }}); |
223 | exp->expectfn = NULL; | 224 | exp->expectfn = NULL; |
224 | exp->flags = 0; | 225 | exp->flags = 0; |
225 | if (ip_nat_irc_hook) | 226 | ip_nat_irc = rcu_dereference(ip_nat_irc_hook); |
226 | ret = ip_nat_irc_hook(pskb, ctinfo, | 227 | if (ip_nat_irc) |
227 | addr_beg_p - ib_ptr, | 228 | ret = ip_nat_irc(pskb, ctinfo, |
228 | addr_end_p - addr_beg_p, | 229 | addr_beg_p - ib_ptr, |
229 | exp); | 230 | addr_end_p - addr_beg_p, |
231 | exp); | ||
230 | else if (ip_conntrack_expect_related(exp) != 0) | 232 | else if (ip_conntrack_expect_related(exp) != 0) |
231 | ret = NF_DROP; | 233 | ret = NF_DROP; |
232 | ip_conntrack_expect_put(exp); | 234 | ip_conntrack_expect_put(exp); |
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c index f4f75995a9e4..bf423db4ed46 100644 --- a/net/ipv4/netfilter/ip_conntrack_sip.c +++ b/net/ipv4/netfilter/ip_conntrack_sip.c | |||
@@ -308,6 +308,7 @@ static int set_expected_rtp(struct sk_buff **pskb, | |||
308 | struct ip_conntrack_expect *exp; | 308 | struct ip_conntrack_expect *exp; |
309 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 309 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
310 | int ret; | 310 | int ret; |
311 | typeof(ip_nat_sdp_hook) ip_nat_sdp; | ||
311 | 312 | ||
312 | exp = ip_conntrack_expect_alloc(ct); | 313 | exp = ip_conntrack_expect_alloc(ct); |
313 | if (exp == NULL) | 314 | if (exp == NULL) |
@@ -328,8 +329,9 @@ static int set_expected_rtp(struct sk_buff **pskb, | |||
328 | exp->expectfn = NULL; | 329 | exp->expectfn = NULL; |
329 | exp->flags = 0; | 330 | exp->flags = 0; |
330 | 331 | ||
331 | if (ip_nat_sdp_hook) | 332 | ip_nat_sdp = rcu_dereference(ip_nat_sdp_hook); |
332 | ret = ip_nat_sdp_hook(pskb, ctinfo, exp, dptr); | 333 | if (ip_nat_sdp) |
334 | ret = ip_nat_sdp(pskb, ctinfo, exp, dptr); | ||
333 | else { | 335 | else { |
334 | if (ip_conntrack_expect_related(exp) != 0) | 336 | if (ip_conntrack_expect_related(exp) != 0) |
335 | ret = NF_DROP; | 337 | ret = NF_DROP; |
@@ -351,6 +353,7 @@ static int sip_help(struct sk_buff **pskb, | |||
351 | int matchoff, matchlen; | 353 | int matchoff, matchlen; |
352 | __be32 ipaddr; | 354 | __be32 ipaddr; |
353 | u_int16_t port; | 355 | u_int16_t port; |
356 | typeof(ip_nat_sip_hook) ip_nat_sip; | ||
354 | 357 | ||
355 | /* No Data ? */ | 358 | /* No Data ? */ |
356 | dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); | 359 | dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); |
@@ -368,8 +371,9 @@ static int sip_help(struct sk_buff **pskb, | |||
368 | goto out; | 371 | goto out; |
369 | } | 372 | } |
370 | 373 | ||
371 | if (ip_nat_sip_hook) { | 374 | ip_nat_sip = rcu_dereference(ip_nat_sip_hook); |
372 | if (!ip_nat_sip_hook(pskb, ctinfo, ct, &dptr)) { | 375 | if (ip_nat_sip) { |
376 | if (!ip_nat_sip(pskb, ctinfo, ct, &dptr)) { | ||
373 | ret = NF_DROP; | 377 | ret = NF_DROP; |
374 | goto out; | 378 | goto out; |
375 | } | 379 | } |
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c index fe0b634dd377..ef56de2eff0c 100644 --- a/net/ipv4/netfilter/ip_conntrack_tftp.c +++ b/net/ipv4/netfilter/ip_conntrack_tftp.c | |||
@@ -50,6 +50,7 @@ static int tftp_help(struct sk_buff **pskb, | |||
50 | struct tftphdr _tftph, *tfh; | 50 | struct tftphdr _tftph, *tfh; |
51 | struct ip_conntrack_expect *exp; | 51 | struct ip_conntrack_expect *exp; |
52 | unsigned int ret = NF_ACCEPT; | 52 | unsigned int ret = NF_ACCEPT; |
53 | typeof(ip_nat_tftp_hook) ip_nat_tftp; | ||
53 | 54 | ||
54 | tfh = skb_header_pointer(*pskb, | 55 | tfh = skb_header_pointer(*pskb, |
55 | (*pskb)->nh.iph->ihl*4+sizeof(struct udphdr), | 56 | (*pskb)->nh.iph->ihl*4+sizeof(struct udphdr), |
@@ -81,8 +82,9 @@ static int tftp_help(struct sk_buff **pskb, | |||
81 | DEBUGP("expect: "); | 82 | DEBUGP("expect: "); |
82 | DUMP_TUPLE(&exp->tuple); | 83 | DUMP_TUPLE(&exp->tuple); |
83 | DUMP_TUPLE(&exp->mask); | 84 | DUMP_TUPLE(&exp->mask); |
84 | if (ip_nat_tftp_hook) | 85 | ip_nat_tftp = rcu_dereference(ip_nat_tftp_hook); |
85 | ret = ip_nat_tftp_hook(pskb, ctinfo, exp); | 86 | if (ip_nat_tftp) |
87 | ret = ip_nat_tftp(pskb, ctinfo, exp); | ||
86 | else if (ip_conntrack_expect_related(exp) != 0) | 88 | else if (ip_conntrack_expect_related(exp) != 0) |
87 | ret = NF_DROP; | 89 | ret = NF_DROP; |
88 | ip_conntrack_expect_put(exp); | 90 | ip_conntrack_expect_put(exp); |
diff --git a/net/ipv4/netfilter/ip_nat_amanda.c b/net/ipv4/netfilter/ip_nat_amanda.c index 3a888715bbf3..85df1a9aed33 100644 --- a/net/ipv4/netfilter/ip_nat_amanda.c +++ b/net/ipv4/netfilter/ip_nat_amanda.c | |||
@@ -70,15 +70,14 @@ static unsigned int help(struct sk_buff **pskb, | |||
70 | 70 | ||
71 | static void __exit ip_nat_amanda_fini(void) | 71 | static void __exit ip_nat_amanda_fini(void) |
72 | { | 72 | { |
73 | ip_nat_amanda_hook = NULL; | 73 | rcu_assign_pointer(ip_nat_amanda_hook, NULL); |
74 | /* Make sure noone calls it, meanwhile. */ | 74 | synchronize_rcu(); |
75 | synchronize_net(); | ||
76 | } | 75 | } |
77 | 76 | ||
78 | static int __init ip_nat_amanda_init(void) | 77 | static int __init ip_nat_amanda_init(void) |
79 | { | 78 | { |
80 | BUG_ON(ip_nat_amanda_hook); | 79 | BUG_ON(rcu_dereference(ip_nat_amanda_hook)); |
81 | ip_nat_amanda_hook = help; | 80 | rcu_assign_pointer(ip_nat_amanda_hook, help); |
82 | return 0; | 81 | return 0; |
83 | } | 82 | } |
84 | 83 | ||
diff --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c index a71c233d8112..913960e1380f 100644 --- a/net/ipv4/netfilter/ip_nat_ftp.c +++ b/net/ipv4/netfilter/ip_nat_ftp.c | |||
@@ -156,15 +156,14 @@ static unsigned int ip_nat_ftp(struct sk_buff **pskb, | |||
156 | 156 | ||
157 | static void __exit ip_nat_ftp_fini(void) | 157 | static void __exit ip_nat_ftp_fini(void) |
158 | { | 158 | { |
159 | ip_nat_ftp_hook = NULL; | 159 | rcu_assign_pointer(ip_nat_ftp_hook, NULL); |
160 | /* Make sure noone calls it, meanwhile. */ | 160 | synchronize_rcu(); |
161 | synchronize_net(); | ||
162 | } | 161 | } |
163 | 162 | ||
164 | static int __init ip_nat_ftp_init(void) | 163 | static int __init ip_nat_ftp_init(void) |
165 | { | 164 | { |
166 | BUG_ON(ip_nat_ftp_hook); | 165 | BUG_ON(rcu_dereference(ip_nat_ftp_hook)); |
167 | ip_nat_ftp_hook = ip_nat_ftp; | 166 | rcu_assign_pointer(ip_nat_ftp_hook, ip_nat_ftp); |
168 | return 0; | 167 | return 0; |
169 | } | 168 | } |
170 | 169 | ||
diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c index 4a7d34466ee2..bdc99ef6159e 100644 --- a/net/ipv4/netfilter/ip_nat_helper_h323.c +++ b/net/ipv4/netfilter/ip_nat_helper_h323.c | |||
@@ -563,25 +563,25 @@ static int nat_callforwarding(struct sk_buff **pskb, struct ip_conntrack *ct, | |||
563 | /****************************************************************************/ | 563 | /****************************************************************************/ |
564 | static int __init init(void) | 564 | static int __init init(void) |
565 | { | 565 | { |
566 | BUG_ON(set_h245_addr_hook != NULL); | 566 | BUG_ON(rcu_dereference(set_h245_addr_hook) != NULL); |
567 | BUG_ON(set_h225_addr_hook != NULL); | 567 | BUG_ON(rcu_dereference(set_h225_addr_hook) != NULL); |
568 | BUG_ON(set_sig_addr_hook != NULL); | 568 | BUG_ON(rcu_dereference(set_sig_addr_hook) != NULL); |
569 | BUG_ON(set_ras_addr_hook != NULL); | 569 | BUG_ON(rcu_dereference(set_ras_addr_hook) != NULL); |
570 | BUG_ON(nat_rtp_rtcp_hook != NULL); | 570 | BUG_ON(rcu_dereference(nat_rtp_rtcp_hook) != NULL); |
571 | BUG_ON(nat_t120_hook != NULL); | 571 | BUG_ON(rcu_dereference(nat_t120_hook) != NULL); |
572 | BUG_ON(nat_h245_hook != NULL); | 572 | BUG_ON(rcu_dereference(nat_h245_hook) != NULL); |
573 | BUG_ON(nat_callforwarding_hook != NULL); | 573 | BUG_ON(rcu_dereference(nat_callforwarding_hook) != NULL); |
574 | BUG_ON(nat_q931_hook != NULL); | 574 | BUG_ON(rcu_dereference(nat_q931_hook) != NULL); |
575 | 575 | ||
576 | set_h245_addr_hook = set_h245_addr; | 576 | rcu_assign_pointer(set_h245_addr_hook, set_h245_addr); |
577 | set_h225_addr_hook = set_h225_addr; | 577 | rcu_assign_pointer(set_h225_addr_hook, set_h225_addr); |
578 | set_sig_addr_hook = set_sig_addr; | 578 | rcu_assign_pointer(set_sig_addr_hook, set_sig_addr); |
579 | set_ras_addr_hook = set_ras_addr; | 579 | rcu_assign_pointer(set_ras_addr_hook, set_ras_addr); |
580 | nat_rtp_rtcp_hook = nat_rtp_rtcp; | 580 | rcu_assign_pointer(nat_rtp_rtcp_hook, nat_rtp_rtcp); |
581 | nat_t120_hook = nat_t120; | 581 | rcu_assign_pointer(nat_t120_hook, nat_t120); |
582 | nat_h245_hook = nat_h245; | 582 | rcu_assign_pointer(nat_h245_hook, nat_h245); |
583 | nat_callforwarding_hook = nat_callforwarding; | 583 | rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding); |
584 | nat_q931_hook = nat_q931; | 584 | rcu_assign_pointer(nat_q931_hook, nat_q931); |
585 | 585 | ||
586 | DEBUGP("ip_nat_h323: init success\n"); | 586 | DEBUGP("ip_nat_h323: init success\n"); |
587 | return 0; | 587 | return 0; |
@@ -590,16 +590,16 @@ static int __init init(void) | |||
590 | /****************************************************************************/ | 590 | /****************************************************************************/ |
591 | static void __exit fini(void) | 591 | static void __exit fini(void) |
592 | { | 592 | { |
593 | set_h245_addr_hook = NULL; | 593 | rcu_assign_pointer(set_h245_addr_hook, NULL); |
594 | set_h225_addr_hook = NULL; | 594 | rcu_assign_pointer(set_h225_addr_hook, NULL); |
595 | set_sig_addr_hook = NULL; | 595 | rcu_assign_pointer(set_sig_addr_hook, NULL); |
596 | set_ras_addr_hook = NULL; | 596 | rcu_assign_pointer(set_ras_addr_hook, NULL); |
597 | nat_rtp_rtcp_hook = NULL; | 597 | rcu_assign_pointer(nat_rtp_rtcp_hook, NULL); |
598 | nat_t120_hook = NULL; | 598 | rcu_assign_pointer(nat_t120_hook, NULL); |
599 | nat_h245_hook = NULL; | 599 | rcu_assign_pointer(nat_h245_hook, NULL); |
600 | nat_callforwarding_hook = NULL; | 600 | rcu_assign_pointer(nat_callforwarding_hook, NULL); |
601 | nat_q931_hook = NULL; | 601 | rcu_assign_pointer(nat_q931_hook, NULL); |
602 | synchronize_net(); | 602 | synchronize_rcu(); |
603 | } | 603 | } |
604 | 604 | ||
605 | /****************************************************************************/ | 605 | /****************************************************************************/ |
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c index acf55d863100..ec957bbb5366 100644 --- a/net/ipv4/netfilter/ip_nat_helper_pptp.c +++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c | |||
@@ -315,17 +315,17 @@ static int __init ip_nat_helper_pptp_init(void) | |||
315 | if (ret < 0) | 315 | if (ret < 0) |
316 | return ret; | 316 | return ret; |
317 | 317 | ||
318 | BUG_ON(ip_nat_pptp_hook_outbound); | 318 | BUG_ON(rcu_dereference(ip_nat_pptp_hook_outbound)); |
319 | ip_nat_pptp_hook_outbound = &pptp_outbound_pkt; | 319 | rcu_assign_pointer(ip_nat_pptp_hook_outbound, pptp_outbound_pkt); |
320 | 320 | ||
321 | BUG_ON(ip_nat_pptp_hook_inbound); | 321 | BUG_ON(rcu_dereference(ip_nat_pptp_hook_inbound)); |
322 | ip_nat_pptp_hook_inbound = &pptp_inbound_pkt; | 322 | rcu_assign_pointer(ip_nat_pptp_hook_inbound, pptp_inbound_pkt); |
323 | 323 | ||
324 | BUG_ON(ip_nat_pptp_hook_exp_gre); | 324 | BUG_ON(rcu_dereference(ip_nat_pptp_hook_exp_gre)); |
325 | ip_nat_pptp_hook_exp_gre = &pptp_exp_gre; | 325 | rcu_assign_pointer(ip_nat_pptp_hook_exp_gre, pptp_exp_gre); |
326 | 326 | ||
327 | BUG_ON(ip_nat_pptp_hook_expectfn); | 327 | BUG_ON(rcu_dereference(ip_nat_pptp_hook_expectfn)); |
328 | ip_nat_pptp_hook_expectfn = &pptp_nat_expected; | 328 | rcu_assign_pointer(ip_nat_pptp_hook_expectfn, pptp_nat_expected); |
329 | 329 | ||
330 | printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION); | 330 | printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION); |
331 | return 0; | 331 | return 0; |
@@ -335,14 +335,13 @@ static void __exit ip_nat_helper_pptp_fini(void) | |||
335 | { | 335 | { |
336 | DEBUGP("cleanup_module\n" ); | 336 | DEBUGP("cleanup_module\n" ); |
337 | 337 | ||
338 | ip_nat_pptp_hook_expectfn = NULL; | 338 | rcu_assign_pointer(ip_nat_pptp_hook_expectfn, NULL); |
339 | ip_nat_pptp_hook_exp_gre = NULL; | 339 | rcu_assign_pointer(ip_nat_pptp_hook_exp_gre, NULL); |
340 | ip_nat_pptp_hook_inbound = NULL; | 340 | rcu_assign_pointer(ip_nat_pptp_hook_inbound, NULL); |
341 | ip_nat_pptp_hook_outbound = NULL; | 341 | rcu_assign_pointer(ip_nat_pptp_hook_outbound, NULL); |
342 | synchronize_rcu(); | ||
342 | 343 | ||
343 | ip_nat_proto_gre_fini(); | 344 | ip_nat_proto_gre_fini(); |
344 | /* Make sure noone calls it, meanwhile */ | ||
345 | synchronize_net(); | ||
346 | 345 | ||
347 | printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION); | 346 | printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION); |
348 | } | 347 | } |
diff --git a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c index a767123e082c..feb26b48f1d5 100644 --- a/net/ipv4/netfilter/ip_nat_irc.c +++ b/net/ipv4/netfilter/ip_nat_irc.c | |||
@@ -98,15 +98,14 @@ static unsigned int help(struct sk_buff **pskb, | |||
98 | 98 | ||
99 | static void __exit ip_nat_irc_fini(void) | 99 | static void __exit ip_nat_irc_fini(void) |
100 | { | 100 | { |
101 | ip_nat_irc_hook = NULL; | 101 | rcu_assign_pointer(ip_nat_irc_hook, NULL); |
102 | /* Make sure noone calls it, meanwhile. */ | 102 | synchronize_rcu(); |
103 | synchronize_net(); | ||
104 | } | 103 | } |
105 | 104 | ||
106 | static int __init ip_nat_irc_init(void) | 105 | static int __init ip_nat_irc_init(void) |
107 | { | 106 | { |
108 | BUG_ON(ip_nat_irc_hook); | 107 | BUG_ON(rcu_dereference(ip_nat_irc_hook)); |
109 | ip_nat_irc_hook = help; | 108 | rcu_assign_pointer(ip_nat_irc_hook, help); |
110 | return 0; | 109 | return 0; |
111 | } | 110 | } |
112 | 111 | ||
diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c index 71fc2730a007..9fad98099532 100644 --- a/net/ipv4/netfilter/ip_nat_sip.c +++ b/net/ipv4/netfilter/ip_nat_sip.c | |||
@@ -230,18 +230,17 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb, | |||
230 | 230 | ||
231 | static void __exit fini(void) | 231 | static void __exit fini(void) |
232 | { | 232 | { |
233 | ip_nat_sip_hook = NULL; | 233 | rcu_assign_pointer(ip_nat_sip_hook, NULL); |
234 | ip_nat_sdp_hook = NULL; | 234 | rcu_assign_pointer(ip_nat_sdp_hook, NULL); |
235 | /* Make sure noone calls it, meanwhile. */ | 235 | synchronize_rcu(); |
236 | synchronize_net(); | ||
237 | } | 236 | } |
238 | 237 | ||
239 | static int __init init(void) | 238 | static int __init init(void) |
240 | { | 239 | { |
241 | BUG_ON(ip_nat_sip_hook); | 240 | BUG_ON(rcu_dereference(ip_nat_sip_hook)); |
242 | BUG_ON(ip_nat_sdp_hook); | 241 | BUG_ON(rcu_dereference(ip_nat_sdp_hook)); |
243 | ip_nat_sip_hook = ip_nat_sip; | 242 | rcu_assign_pointer(ip_nat_sip_hook, ip_nat_sip); |
244 | ip_nat_sdp_hook = ip_nat_sdp; | 243 | rcu_assign_pointer(ip_nat_sdp_hook, ip_nat_sdp); |
245 | return 0; | 244 | return 0; |
246 | } | 245 | } |
247 | 246 | ||
diff --git a/net/ipv4/netfilter/ip_nat_tftp.c b/net/ipv4/netfilter/ip_nat_tftp.c index 94a78015451c..604793536fc1 100644 --- a/net/ipv4/netfilter/ip_nat_tftp.c +++ b/net/ipv4/netfilter/ip_nat_tftp.c | |||
@@ -55,15 +55,14 @@ static unsigned int help(struct sk_buff **pskb, | |||
55 | 55 | ||
56 | static void __exit ip_nat_tftp_fini(void) | 56 | static void __exit ip_nat_tftp_fini(void) |
57 | { | 57 | { |
58 | ip_nat_tftp_hook = NULL; | 58 | rcu_assign_pointer(ip_nat_tftp_hook, NULL); |
59 | /* Make sure noone calls it, meanwhile. */ | 59 | synchronize_rcu(); |
60 | synchronize_net(); | ||
61 | } | 60 | } |
62 | 61 | ||
63 | static int __init ip_nat_tftp_init(void) | 62 | static int __init ip_nat_tftp_init(void) |
64 | { | 63 | { |
65 | BUG_ON(ip_nat_tftp_hook); | 64 | BUG_ON(rcu_dereference(ip_nat_tftp_hook)); |
66 | ip_nat_tftp_hook = help; | 65 | rcu_assign_pointer(ip_nat_tftp_hook, help); |
67 | return 0; | 66 | return 0; |
68 | } | 67 | } |
69 | 68 | ||
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 05cb78ca90ae..2d2350152b90 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c | |||
@@ -369,9 +369,9 @@ static int help(struct sk_buff **pskb, | |||
369 | struct ip_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info; | 369 | struct ip_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info; |
370 | struct nf_conntrack_expect *exp; | 370 | struct nf_conntrack_expect *exp; |
371 | struct nf_conntrack_man cmd = {}; | 371 | struct nf_conntrack_man cmd = {}; |
372 | |||
373 | unsigned int i; | 372 | unsigned int i; |
374 | int found = 0, ends_in_nl; | 373 | int found = 0, ends_in_nl; |
374 | typeof(nf_nat_ftp_hook) nf_nat_ftp; | ||
375 | 375 | ||
376 | /* Until there's been traffic both ways, don't look in packets. */ | 376 | /* Until there's been traffic both ways, don't look in packets. */ |
377 | if (ctinfo != IP_CT_ESTABLISHED | 377 | if (ctinfo != IP_CT_ESTABLISHED |
@@ -520,9 +520,10 @@ static int help(struct sk_buff **pskb, | |||
520 | 520 | ||
521 | /* Now, NAT might want to mangle the packet, and register the | 521 | /* Now, NAT might want to mangle the packet, and register the |
522 | * (possibly changed) expectation itself. */ | 522 | * (possibly changed) expectation itself. */ |
523 | if (nf_nat_ftp_hook) | 523 | nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook); |
524 | ret = nf_nat_ftp_hook(pskb, ctinfo, search[dir][i].ftptype, | 524 | if (nf_nat_ftp) |
525 | matchoff, matchlen, exp, &seq); | 525 | ret = nf_nat_ftp(pskb, ctinfo, search[dir][i].ftptype, |
526 | matchoff, matchlen, exp, &seq); | ||
526 | else { | 527 | else { |
527 | /* Can't expect this? Best to drop packet now. */ | 528 | /* Can't expect this? Best to drop packet now. */ |
528 | if (nf_conntrack_expect_related(exp) != 0) | 529 | if (nf_conntrack_expect_related(exp) != 0) |