nf_nat_h323.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. /*
  2. * H.323 extension for NAT alteration.
  3. *
  4. * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
  5. *
  6. * This source code is licensed under General Public License version 2.
  7. *
  8. * Based on the 'brute force' H.323 NAT module by
  9. * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  10. */
  11. #include <linux/module.h>
  12. #include <linux/moduleparam.h>
  13. #include <linux/tcp.h>
  14. #include <net/tcp.h>
  15. #include <net/netfilter/nf_nat.h>
  16. #include <net/netfilter/nf_nat_helper.h>
  17. #include <net/netfilter/nf_nat_rule.h>
  18. #include <net/netfilter/nf_conntrack_helper.h>
  19. #include <net/netfilter/nf_conntrack_expect.h>
  20. #include <linux/netfilter/nf_conntrack_h323.h>
  21. #if 0
  22. #define DEBUGP printk
  23. #else
  24. #define DEBUGP(format, args...)
  25. #endif
  26. /****************************************************************************/
  27. static int set_addr(struct sk_buff **pskb,
  28. unsigned char **data, int dataoff,
  29. unsigned int addroff, __be32 ip, __be16 port)
  30. {
  31. enum ip_conntrack_info ctinfo;
  32. struct nf_conn *ct = ip_conntrack_get(*pskb, &ctinfo);
  33. struct {
  34. __be32 ip;
  35. __be16 port;
  36. } __attribute__ ((__packed__)) buf;
  37. struct tcphdr _tcph, *th;
  38. buf.ip = ip;
  39. buf.port = port;
  40. addroff += dataoff;
  41. if ((*pskb)->nh.iph->protocol == IPPROTO_TCP) {
  42. if (!nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
  43. addroff, sizeof(buf),
  44. (char *) &buf, sizeof(buf))) {
  45. if (net_ratelimit())
  46. printk("nf_nat_h323: nf_nat_mangle_tcp_packet"
  47. " error\n");
  48. return -1;
  49. }
  50. /* Relocate data pointer */
  51. th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4,
  52. sizeof(_tcph), &_tcph);
  53. if (th == NULL)
  54. return -1;
  55. *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
  56. th->doff * 4 + dataoff;
  57. } else {
  58. if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
  59. addroff, sizeof(buf),
  60. (char *) &buf, sizeof(buf))) {
  61. if (net_ratelimit())
  62. printk("nf_nat_h323: nf_nat_mangle_udp_packet"
  63. " error\n");
  64. return -1;
  65. }
  66. /* nf_nat_mangle_udp_packet uses skb_make_writable() to copy
  67. * or pull everything in a linear buffer, so we can safely
  68. * use the skb pointers now */
  69. *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
  70. sizeof(struct udphdr);
  71. }
  72. return 0;
  73. }
  74. /****************************************************************************/
  75. static int set_h225_addr(struct sk_buff **pskb,
  76. unsigned char **data, int dataoff,
  77. TransportAddress *taddr,
  78. union nf_conntrack_address *addr, __be16 port)
  79. {
  80. return set_addr(pskb, data, dataoff, taddr->ipAddress.ip,
  81. addr->ip, port);
  82. }
  83. /****************************************************************************/
  84. static int set_h245_addr(struct sk_buff **pskb,
  85. unsigned char **data, int dataoff,
  86. H245_TransportAddress *taddr,
  87. union nf_conntrack_address *addr, __be16 port)
  88. {
  89. return set_addr(pskb, data, dataoff,
  90. taddr->unicastAddress.iPAddress.network,
  91. addr->ip, port);
  92. }
  93. /****************************************************************************/
  94. static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct,
  95. enum ip_conntrack_info ctinfo,
  96. unsigned char **data,
  97. TransportAddress *taddr, int count)
  98. {
  99. struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
  100. int dir = CTINFO2DIR(ctinfo);
  101. int i;
  102. __be16 port;
  103. union nf_conntrack_address addr;
  104. for (i = 0; i < count; i++) {
  105. if (get_h225_addr(ct, *data, &taddr[i], &addr, &port)) {
  106. if (addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
  107. port == info->sig_port[dir]) {
  108. /* GW->GK */
  109. /* Fix for Gnomemeeting */
  110. if (i > 0 &&
  111. get_h225_addr(ct, *data, &taddr[0],
  112. &addr, &port) &&
  113. (ntohl(addr.ip) & 0xff000000) == 0x7f000000)
  114. i = 0;
  115. DEBUGP
  116. ("nf_nat_ras: set signal address "
  117. "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
  118. NIPQUAD(ip), port,
  119. NIPQUAD(ct->tuplehash[!dir].tuple.dst.
  120. ip), info->sig_port[!dir]);
  121. return set_h225_addr(pskb, data, 0, &taddr[i],
  122. &ct->tuplehash[!dir].
  123. tuple.dst.u3,
  124. info->sig_port[!dir]);
  125. } else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
  126. port == info->sig_port[dir]) {
  127. /* GK->GW */
  128. DEBUGP
  129. ("nf_nat_ras: set signal address "
  130. "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
  131. NIPQUAD(ip), port,
  132. NIPQUAD(ct->tuplehash[!dir].tuple.src.
  133. ip), info->sig_port[!dir]);
  134. return set_h225_addr(pskb, data, 0, &taddr[i],
  135. &ct->tuplehash[!dir].
  136. tuple.src.u3,
  137. info->sig_port[!dir]);
  138. }
  139. }
  140. }
  141. return 0;
  142. }
  143. /****************************************************************************/
  144. static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct,
  145. enum ip_conntrack_info ctinfo,
  146. unsigned char **data,
  147. TransportAddress *taddr, int count)
  148. {
  149. int dir = CTINFO2DIR(ctinfo);
  150. int i;
  151. __be16 port;
  152. union nf_conntrack_address addr;
  153. for (i = 0; i < count; i++) {
  154. if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&
  155. addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
  156. port == ct->tuplehash[dir].tuple.src.u.udp.port) {
  157. DEBUGP("nf_nat_ras: set rasAddress "
  158. "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
  159. NIPQUAD(ip), ntohs(port),
  160. NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
  161. ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.
  162. port));
  163. return set_h225_addr(pskb, data, 0, &taddr[i],
  164. &ct->tuplehash[!dir].tuple.dst.u3,
  165. ct->tuplehash[!dir].tuple.
  166. dst.u.udp.port);
  167. }
  168. }
  169. return 0;
  170. }
  171. /****************************************************************************/
  172. static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
  173. enum ip_conntrack_info ctinfo,
  174. unsigned char **data, int dataoff,
  175. H245_TransportAddress *taddr,
  176. __be16 port, __be16 rtp_port,
  177. struct nf_conntrack_expect *rtp_exp,
  178. struct nf_conntrack_expect *rtcp_exp)
  179. {
  180. struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
  181. int dir = CTINFO2DIR(ctinfo);
  182. int i;
  183. u_int16_t nated_port;
  184. /* Set expectations for NAT */
  185. rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
  186. rtp_exp->expectfn = nf_nat_follow_master;
  187. rtp_exp->dir = !dir;
  188. rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
  189. rtcp_exp->expectfn = nf_nat_follow_master;
  190. rtcp_exp->dir = !dir;
  191. /* Lookup existing expects */
  192. for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) {
  193. if (info->rtp_port[i][dir] == rtp_port) {
  194. /* Expected */
  195. /* Use allocated ports first. This will refresh
  196. * the expects */
  197. rtp_exp->tuple.dst.u.udp.port = info->rtp_port[i][dir];
  198. rtcp_exp->tuple.dst.u.udp.port =
  199. htons(ntohs(info->rtp_port[i][dir]) + 1);
  200. break;
  201. } else if (info->rtp_port[i][dir] == 0) {
  202. /* Not expected */
  203. break;
  204. }
  205. }
  206. /* Run out of expectations */
  207. if (i >= H323_RTP_CHANNEL_MAX) {
  208. if (net_ratelimit())
  209. printk("nf_nat_h323: out of expectations\n");
  210. return 0;
  211. }
  212. /* Try to get a pair of ports. */
  213. for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);
  214. nated_port != 0; nated_port += 2) {
  215. rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
  216. if (nf_conntrack_expect_related(rtp_exp) == 0) {
  217. rtcp_exp->tuple.dst.u.udp.port =
  218. htons(nated_port + 1);
  219. if (nf_conntrack_expect_related(rtcp_exp) == 0)
  220. break;
  221. nf_conntrack_unexpect_related(rtp_exp);
  222. }
  223. }
  224. if (nated_port == 0) { /* No port available */
  225. if (net_ratelimit())
  226. printk("nf_nat_h323: out of RTP ports\n");
  227. return 0;
  228. }
  229. /* Modify signal */
  230. if (set_h245_addr(pskb, data, dataoff, taddr,
  231. &ct->tuplehash[!dir].tuple.dst.u3,
  232. htons((port & htons(1)) ? nated_port + 1 :
  233. nated_port)) == 0) {
  234. /* Save ports */
  235. info->rtp_port[i][dir] = rtp_port;
  236. info->rtp_port[i][!dir] = htons(nated_port);
  237. } else {
  238. nf_conntrack_unexpect_related(rtp_exp);
  239. nf_conntrack_unexpect_related(rtcp_exp);
  240. return -1;
  241. }
  242. /* Success */
  243. DEBUGP("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
  244. NIPQUAD(rtp_exp->tuple.src.ip),
  245. ntohs(rtp_exp->tuple.src.u.udp.port),
  246. NIPQUAD(rtp_exp->tuple.dst.ip),
  247. ntohs(rtp_exp->tuple.dst.u.udp.port));
  248. DEBUGP("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
  249. NIPQUAD(rtcp_exp->tuple.src.ip),
  250. ntohs(rtcp_exp->tuple.src.u.udp.port),
  251. NIPQUAD(rtcp_exp->tuple.dst.ip),
  252. ntohs(rtcp_exp->tuple.dst.u.udp.port));
  253. return 0;
  254. }
  255. /****************************************************************************/
  256. static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct,
  257. enum ip_conntrack_info ctinfo,
  258. unsigned char **data, int dataoff,
  259. H245_TransportAddress *taddr, __be16 port,
  260. struct nf_conntrack_expect *exp)
  261. {
  262. int dir = CTINFO2DIR(ctinfo);
  263. u_int16_t nated_port = ntohs(port);
  264. /* Set expectations for NAT */
  265. exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
  266. exp->expectfn = nf_nat_follow_master;
  267. exp->dir = !dir;
  268. /* Try to get same port: if not, try to change it. */
  269. for (; nated_port != 0; nated_port++) {
  270. exp->tuple.dst.u.tcp.port = htons(nated_port);
  271. if (nf_conntrack_expect_related(exp) == 0)
  272. break;
  273. }
  274. if (nated_port == 0) { /* No port available */
  275. if (net_ratelimit())
  276. printk("nf_nat_h323: out of TCP ports\n");
  277. return 0;
  278. }
  279. /* Modify signal */
  280. if (set_h245_addr(pskb, data, dataoff, taddr,
  281. &ct->tuplehash[!dir].tuple.dst.u3,
  282. htons(nated_port)) < 0) {
  283. nf_conntrack_unexpect_related(exp);
  284. return -1;
  285. }
  286. DEBUGP("nf_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
  287. NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
  288. NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
  289. return 0;
  290. }
  291. /****************************************************************************/
  292. static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct,
  293. enum ip_conntrack_info ctinfo,
  294. unsigned char **data, int dataoff,
  295. TransportAddress *taddr, __be16 port,
  296. struct nf_conntrack_expect *exp)
  297. {
  298. struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
  299. int dir = CTINFO2DIR(ctinfo);
  300. u_int16_t nated_port = ntohs(port);
  301. /* Set expectations for NAT */
  302. exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
  303. exp->expectfn = nf_nat_follow_master;
  304. exp->dir = !dir;
  305. /* Check existing expects */
  306. if (info->sig_port[dir] == port)
  307. nated_port = ntohs(info->sig_port[!dir]);
  308. /* Try to get same port: if not, try to change it. */
  309. for (; nated_port != 0; nated_port++) {
  310. exp->tuple.dst.u.tcp.port = htons(nated_port);
  311. if (nf_conntrack_expect_related(exp) == 0)
  312. break;
  313. }
  314. if (nated_port == 0) { /* No port available */
  315. if (net_ratelimit())
  316. printk("nf_nat_q931: out of TCP ports\n");
  317. return 0;
  318. }
  319. /* Modify signal */
  320. if (set_h225_addr(pskb, data, dataoff, taddr,
  321. &ct->tuplehash[!dir].tuple.dst.u3,
  322. htons(nated_port)) == 0) {
  323. /* Save ports */
  324. info->sig_port[dir] = port;
  325. info->sig_port[!dir] = htons(nated_port);
  326. } else {
  327. nf_conntrack_unexpect_related(exp);
  328. return -1;
  329. }
  330. DEBUGP("nf_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
  331. NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
  332. NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
  333. return 0;
  334. }
  335. /****************************************************************************
  336. * This conntrack expect function replaces nf_conntrack_q931_expect()
  337. * which was set by nf_conntrack_h323.c.
  338. ****************************************************************************/
  339. static void ip_nat_q931_expect(struct nf_conn *new,
  340. struct nf_conntrack_expect *this)
  341. {
  342. struct ip_nat_range range;
  343. if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */
  344. nf_nat_follow_master(new, this);
  345. return;
  346. }
  347. /* This must be a fresh one. */
  348. BUG_ON(new->status & IPS_NAT_DONE_MASK);
  349. /* Change src to where master sends to */
  350. range.flags = IP_NAT_RANGE_MAP_IPS;
  351. range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip;
  352. /* hook doesn't matter, but it has to do source manip */
  353. nf_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
  354. /* For DST manip, map port here to where it's expected. */
  355. range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
  356. range.min = range.max = this->saved_proto;
  357. range.min_ip = range.max_ip =
  358. new->master->tuplehash[!this->dir].tuple.src.u3.ip;
  359. /* hook doesn't matter, but it has to do destination manip */
  360. nf_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
  361. }
  362. /****************************************************************************/
  363. static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct,
  364. enum ip_conntrack_info ctinfo,
  365. unsigned char **data, TransportAddress *taddr, int idx,
  366. __be16 port, struct nf_conntrack_expect *exp)
  367. {
  368. struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
  369. int dir = CTINFO2DIR(ctinfo);
  370. u_int16_t nated_port = ntohs(port);
  371. union nf_conntrack_address addr;
  372. /* Set expectations for NAT */
  373. exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
  374. exp->expectfn = ip_nat_q931_expect;
  375. exp->dir = !dir;
  376. /* Check existing expects */
  377. if (info->sig_port[dir] == port)
  378. nated_port = ntohs(info->sig_port[!dir]);
  379. /* Try to get same port: if not, try to change it. */
  380. for (; nated_port != 0; nated_port++) {
  381. exp->tuple.dst.u.tcp.port = htons(nated_port);
  382. if (nf_conntrack_expect_related(exp) == 0)
  383. break;
  384. }
  385. if (nated_port == 0) { /* No port available */
  386. if (net_ratelimit())
  387. printk("nf_nat_ras: out of TCP ports\n");
  388. return 0;
  389. }
  390. /* Modify signal */
  391. if (set_h225_addr(pskb, data, 0, &taddr[idx],
  392. &ct->tuplehash[!dir].tuple.dst.u3,
  393. htons(nated_port)) == 0) {
  394. /* Save ports */
  395. info->sig_port[dir] = port;
  396. info->sig_port[!dir] = htons(nated_port);
  397. /* Fix for Gnomemeeting */
  398. if (idx > 0 &&
  399. get_h225_addr(ct, *data, &taddr[0], &addr, &port) &&
  400. (ntohl(addr.ip) & 0xff000000) == 0x7f000000) {
  401. set_h225_addr_hook(pskb, data, 0, &taddr[0],
  402. &ct->tuplehash[!dir].tuple.dst.u3,
  403. info->sig_port[!dir]);
  404. }
  405. } else {
  406. nf_conntrack_unexpect_related(exp);
  407. return -1;
  408. }
  409. /* Success */
  410. DEBUGP("nf_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
  411. NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
  412. NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
  413. return 0;
  414. }
  415. /****************************************************************************/
  416. static void ip_nat_callforwarding_expect(struct nf_conn *new,
  417. struct nf_conntrack_expect *this)
  418. {
  419. struct nf_nat_range range;
  420. /* This must be a fresh one. */
  421. BUG_ON(new->status & IPS_NAT_DONE_MASK);
  422. /* Change src to where master sends to */
  423. range.flags = IP_NAT_RANGE_MAP_IPS;
  424. range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip;
  425. /* hook doesn't matter, but it has to do source manip */
  426. nf_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
  427. /* For DST manip, map port here to where it's expected. */
  428. range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
  429. range.min = range.max = this->saved_proto;
  430. range.min_ip = range.max_ip = this->saved_ip;
  431. /* hook doesn't matter, but it has to do destination manip */
  432. nf_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
  433. }
  434. /****************************************************************************/
  435. static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct,
  436. enum ip_conntrack_info ctinfo,
  437. unsigned char **data, int dataoff,
  438. TransportAddress *taddr, __be16 port,
  439. struct nf_conntrack_expect *exp)
  440. {
  441. int dir = CTINFO2DIR(ctinfo);
  442. u_int16_t nated_port;
  443. /* Set expectations for NAT */
  444. exp->saved_ip = exp->tuple.dst.u3.ip;
  445. exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
  446. exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
  447. exp->expectfn = ip_nat_callforwarding_expect;
  448. exp->dir = !dir;
  449. /* Try to get same port: if not, try to change it. */
  450. for (nated_port = ntohs(port); nated_port != 0; nated_port++) {
  451. exp->tuple.dst.u.tcp.port = htons(nated_port);
  452. if (nf_conntrack_expect_related(exp) == 0)
  453. break;
  454. }
  455. if (nated_port == 0) { /* No port available */
  456. if (net_ratelimit())
  457. printk("nf_nat_q931: out of TCP ports\n");
  458. return 0;
  459. }
  460. /* Modify signal */
  461. if (!set_h225_addr(pskb, data, dataoff, taddr,
  462. &ct->tuplehash[!dir].tuple.dst.u3,
  463. htons(nated_port)) == 0) {
  464. nf_conntrack_unexpect_related(exp);
  465. return -1;
  466. }
  467. /* Success */
  468. DEBUGP("nf_nat_q931: expect Call Forwarding "
  469. "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
  470. NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
  471. NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
  472. return 0;
  473. }
  474. /****************************************************************************/
  475. static int __init init(void)
  476. {
  477. BUG_ON(rcu_dereference(set_h245_addr_hook) != NULL);
  478. BUG_ON(rcu_dereference(set_h225_addr_hook) != NULL);
  479. BUG_ON(rcu_dereference(set_sig_addr_hook) != NULL);
  480. BUG_ON(rcu_dereference(set_ras_addr_hook) != NULL);
  481. BUG_ON(rcu_dereference(nat_rtp_rtcp_hook) != NULL);
  482. BUG_ON(rcu_dereference(nat_t120_hook) != NULL);
  483. BUG_ON(rcu_dereference(nat_h245_hook) != NULL);
  484. BUG_ON(rcu_dereference(nat_callforwarding_hook) != NULL);
  485. BUG_ON(rcu_dereference(nat_q931_hook) != NULL);
  486. rcu_assign_pointer(set_h245_addr_hook, set_h245_addr);
  487. rcu_assign_pointer(set_h225_addr_hook, set_h225_addr);
  488. rcu_assign_pointer(set_sig_addr_hook, set_sig_addr);
  489. rcu_assign_pointer(set_ras_addr_hook, set_ras_addr);
  490. rcu_assign_pointer(nat_rtp_rtcp_hook, nat_rtp_rtcp);
  491. rcu_assign_pointer(nat_t120_hook, nat_t120);
  492. rcu_assign_pointer(nat_h245_hook, nat_h245);
  493. rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding);
  494. rcu_assign_pointer(nat_q931_hook, nat_q931);
  495. DEBUGP("nf_nat_h323: init success\n");
  496. return 0;
  497. }
  498. /****************************************************************************/
  499. static void __exit fini(void)
  500. {
  501. rcu_assign_pointer(set_h245_addr_hook, NULL);
  502. rcu_assign_pointer(set_h225_addr_hook, NULL);
  503. rcu_assign_pointer(set_sig_addr_hook, NULL);
  504. rcu_assign_pointer(set_ras_addr_hook, NULL);
  505. rcu_assign_pointer(nat_rtp_rtcp_hook, NULL);
  506. rcu_assign_pointer(nat_t120_hook, NULL);
  507. rcu_assign_pointer(nat_h245_hook, NULL);
  508. rcu_assign_pointer(nat_callforwarding_hook, NULL);
  509. rcu_assign_pointer(nat_q931_hook, NULL);
  510. synchronize_rcu();
  511. }
  512. /****************************************************************************/
  513. module_init(init);
  514. module_exit(fini);
  515. MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
  516. MODULE_DESCRIPTION("H.323 NAT helper");
  517. MODULE_LICENSE("GPL");
  518. MODULE_ALIAS("ip_nat_h323");