aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-11-28 20:35:25 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:31:22 -0500
commit337fbc4166967a72c3cc71c597bdde7e6a8633ab (patch)
tree95b2d47e55db3991f66090525b7e28455a6ca39b
parent468ec44bd5a863736d955f78b8c38896f26864a1 (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.c9
-rw-r--r--net/ipv4/netfilter/ip_conntrack_ftp.c8
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323.c164
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_pptp.c29
-rw-r--r--net/ipv4/netfilter/ip_conntrack_irc.c12
-rw-r--r--net/ipv4/netfilter/ip_conntrack_sip.c12
-rw-r--r--net/ipv4/netfilter/ip_conntrack_tftp.c6
-rw-r--r--net/ipv4/netfilter/ip_nat_amanda.c9
-rw-r--r--net/ipv4/netfilter/ip_nat_ftp.c9
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_h323.c58
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_pptp.c27
-rw-r--r--net/ipv4/netfilter/ip_nat_irc.c9
-rw-r--r--net/ipv4/netfilter/ip_nat_sip.c15
-rw-r--r--net/ipv4/netfilter/ip_nat_tftp.c9
-rw-r--r--net/netfilter/nf_conntrack_ftp.c9
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);
124static void pptp_expectfn(struct ip_conntrack *ct, 124static 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
160static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t) 165static 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
410invalid: 418invalid:
@@ -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
500invalid: 509invalid:
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
71static void __exit ip_nat_amanda_fini(void) 71static 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
78static int __init ip_nat_amanda_init(void) 77static 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
157static void __exit ip_nat_ftp_fini(void) 157static 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
164static int __init ip_nat_ftp_init(void) 163static 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/****************************************************************************/
564static int __init init(void) 564static 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/****************************************************************************/
591static void __exit fini(void) 591static 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
99static void __exit ip_nat_irc_fini(void) 99static 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
106static int __init ip_nat_irc_init(void) 105static 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
231static void __exit fini(void) 231static 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
239static int __init init(void) 238static 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
56static void __exit ip_nat_tftp_fini(void) 56static 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
63static int __init ip_nat_tftp_init(void) 62static 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)