~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/ipv4/netfilter/nf_nat_h323.c

Version: ~ [ linux-6.0 ] ~ [ linux-5.19.12 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.71 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.146 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.215 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.260 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.295 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.330 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.302 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * H.323 extension for NAT alteration.
  4  *
  5  * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
  6  * Copyright (c) 2006-2012 Patrick McHardy <kaber@trash.net>
  7  *
  8  * Based on the 'brute force' H.323 NAT module by
  9  * Jozsef Kadlecsik <kadlec@netfilter.org>
 10  */
 11 
 12 #include <linux/module.h>
 13 #include <linux/tcp.h>
 14 #include <net/tcp.h>
 15 
 16 #include <net/netfilter/nf_nat.h>
 17 #include <net/netfilter/nf_nat_helper.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 
 22 /****************************************************************************/
 23 static int set_addr(struct sk_buff *skb, unsigned int protoff,
 24                     unsigned char **data, int dataoff,
 25                     unsigned int addroff, __be32 ip, __be16 port)
 26 {
 27         enum ip_conntrack_info ctinfo;
 28         struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 29         struct {
 30                 __be32 ip;
 31                 __be16 port;
 32         } __attribute__ ((__packed__)) buf;
 33         const struct tcphdr *th;
 34         struct tcphdr _tcph;
 35 
 36         buf.ip = ip;
 37         buf.port = port;
 38         addroff += dataoff;
 39 
 40         if (ip_hdr(skb)->protocol == IPPROTO_TCP) {
 41                 if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
 42                                               protoff, addroff, sizeof(buf),
 43                                               (char *) &buf, sizeof(buf))) {
 44                         net_notice_ratelimited("nf_nat_h323: nf_nat_mangle_tcp_packet error\n");
 45                         return -1;
 46                 }
 47 
 48                 /* Relocate data pointer */
 49                 th = skb_header_pointer(skb, ip_hdrlen(skb),
 50                                         sizeof(_tcph), &_tcph);
 51                 if (th == NULL)
 52                         return -1;
 53                 *data = skb->data + ip_hdrlen(skb) + th->doff * 4 + dataoff;
 54         } else {
 55                 if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
 56                                               protoff, addroff, sizeof(buf),
 57                                               (char *) &buf, sizeof(buf))) {
 58                         net_notice_ratelimited("nf_nat_h323: nf_nat_mangle_udp_packet error\n");
 59                         return -1;
 60                 }
 61                 /* nf_nat_mangle_udp_packet uses skb_ensure_writable() to copy
 62                  * or pull everything in a linear buffer, so we can safely
 63                  * use the skb pointers now */
 64                 *data = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr);
 65         }
 66 
 67         return 0;
 68 }
 69 
 70 /****************************************************************************/
 71 static int set_h225_addr(struct sk_buff *skb, unsigned int protoff,
 72                          unsigned char **data, int dataoff,
 73                          TransportAddress *taddr,
 74                          union nf_inet_addr *addr, __be16 port)
 75 {
 76         return set_addr(skb, protoff, data, dataoff, taddr->ipAddress.ip,
 77                         addr->ip, port);
 78 }
 79 
 80 /****************************************************************************/
 81 static int set_h245_addr(struct sk_buff *skb, unsigned protoff,
 82                          unsigned char **data, int dataoff,
 83                          H245_TransportAddress *taddr,
 84                          union nf_inet_addr *addr, __be16 port)
 85 {
 86         return set_addr(skb, protoff, data, dataoff,
 87                         taddr->unicastAddress.iPAddress.network,
 88                         addr->ip, port);
 89 }
 90 
 91 /****************************************************************************/
 92 static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct,
 93                         enum ip_conntrack_info ctinfo,
 94                         unsigned int protoff, unsigned char **data,
 95                         TransportAddress *taddr, int count)
 96 {
 97         const struct nf_ct_h323_master *info = nfct_help_data(ct);
 98         int dir = CTINFO2DIR(ctinfo);
 99         int i;
100         __be16 port;
101         union nf_inet_addr addr;
102 
103         for (i = 0; i < count; i++) {
104                 if (get_h225_addr(ct, *data, &taddr[i], &addr, &port)) {
105                         if (addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
106                             port == info->sig_port[dir]) {
107                                 /* GW->GK */
108 
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 
116                                 pr_debug("nf_nat_ras: set signal address %pI4:%hu->%pI4:%hu\n",
117                                          &addr.ip, port,
118                                          &ct->tuplehash[!dir].tuple.dst.u3.ip,
119                                          info->sig_port[!dir]);
120                                 return set_h225_addr(skb, protoff, data, 0,
121                                                      &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                                 pr_debug("nf_nat_ras: set signal address %pI4:%hu->%pI4:%hu\n",
129                                          &addr.ip, port,
130                                          &ct->tuplehash[!dir].tuple.src.u3.ip,
131                                          info->sig_port[!dir]);
132                                 return set_h225_addr(skb, protoff, data, 0,
133                                                      &taddr[i],
134                                                      &ct->tuplehash[!dir].
135                                                      tuple.src.u3,
136                                                      info->sig_port[!dir]);
137                         }
138                 }
139         }
140 
141         return 0;
142 }
143 
144 /****************************************************************************/
145 static int set_ras_addr(struct sk_buff *skb, struct nf_conn *ct,
146                         enum ip_conntrack_info ctinfo,
147                         unsigned int protoff, unsigned char **data,
148                         TransportAddress *taddr, int count)
149 {
150         int dir = CTINFO2DIR(ctinfo);
151         int i;
152         __be16 port;
153         union nf_inet_addr addr;
154 
155         for (i = 0; i < count; i++) {
156                 if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&
157                     addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
158                     port == ct->tuplehash[dir].tuple.src.u.udp.port) {
159                         pr_debug("nf_nat_ras: set rasAddress %pI4:%hu->%pI4:%hu\n",
160                                  &addr.ip, ntohs(port),
161                                  &ct->tuplehash[!dir].tuple.dst.u3.ip,
162                                  ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port));
163                         return set_h225_addr(skb, protoff, data, 0, &taddr[i],
164                                              &ct->tuplehash[!dir].tuple.dst.u3,
165                                              ct->tuplehash[!dir].tuple.
166                                                                 dst.u.udp.port);
167                 }
168         }
169 
170         return 0;
171 }
172 
173 /****************************************************************************/
174 static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
175                         enum ip_conntrack_info ctinfo,
176                         unsigned int protoff, unsigned char **data, int dataoff,
177                         H245_TransportAddress *taddr,
178                         __be16 port, __be16 rtp_port,
179                         struct nf_conntrack_expect *rtp_exp,
180                         struct nf_conntrack_expect *rtcp_exp)
181 {
182         struct nf_ct_h323_master *info = nfct_help_data(ct);
183         int dir = CTINFO2DIR(ctinfo);
184         int i;
185         u_int16_t nated_port;
186 
187         /* Set expectations for NAT */
188         rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
189         rtp_exp->expectfn = nf_nat_follow_master;
190         rtp_exp->dir = !dir;
191         rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
192         rtcp_exp->expectfn = nf_nat_follow_master;
193         rtcp_exp->dir = !dir;
194 
195         /* Lookup existing expects */
196         for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) {
197                 if (info->rtp_port[i][dir] == rtp_port) {
198                         /* Expected */
199 
200                         /* Use allocated ports first. This will refresh
201                          * the expects */
202                         rtp_exp->tuple.dst.u.udp.port = info->rtp_port[i][dir];
203                         rtcp_exp->tuple.dst.u.udp.port =
204                             htons(ntohs(info->rtp_port[i][dir]) + 1);
205                         break;
206                 } else if (info->rtp_port[i][dir] == 0) {
207                         /* Not expected */
208                         break;
209                 }
210         }
211 
212         /* Run out of expectations */
213         if (i >= H323_RTP_CHANNEL_MAX) {
214                 net_notice_ratelimited("nf_nat_h323: out of expectations\n");
215                 return 0;
216         }
217 
218         /* Try to get a pair of ports. */
219         for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);
220              nated_port != 0; nated_port += 2) {
221                 int ret;
222 
223                 rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
224                 ret = nf_ct_expect_related(rtp_exp, 0);
225                 if (ret == 0) {
226                         rtcp_exp->tuple.dst.u.udp.port =
227                             htons(nated_port + 1);
228                         ret = nf_ct_expect_related(rtcp_exp, 0);
229                         if (ret == 0)
230                                 break;
231                         else if (ret == -EBUSY) {
232                                 nf_ct_unexpect_related(rtp_exp);
233                                 continue;
234                         } else if (ret < 0) {
235                                 nf_ct_unexpect_related(rtp_exp);
236                                 nated_port = 0;
237                                 break;
238                         }
239                 } else if (ret != -EBUSY) {
240                         nated_port = 0;
241                         break;
242                 }
243         }
244 
245         if (nated_port == 0) {  /* No port available */
246                 net_notice_ratelimited("nf_nat_h323: out of RTP ports\n");
247                 return 0;
248         }
249 
250         /* Modify signal */
251         if (set_h245_addr(skb, protoff, data, dataoff, taddr,
252                           &ct->tuplehash[!dir].tuple.dst.u3,
253                           htons((port & htons(1)) ? nated_port + 1 :
254                                                     nated_port))) {
255                 nf_ct_unexpect_related(rtp_exp);
256                 nf_ct_unexpect_related(rtcp_exp);
257                 return -1;
258         }
259 
260         /* Save ports */
261         info->rtp_port[i][dir] = rtp_port;
262         info->rtp_port[i][!dir] = htons(nated_port);
263 
264         /* Success */
265         pr_debug("nf_nat_h323: expect RTP %pI4:%hu->%pI4:%hu\n",
266                  &rtp_exp->tuple.src.u3.ip,
267                  ntohs(rtp_exp->tuple.src.u.udp.port),
268                  &rtp_exp->tuple.dst.u3.ip,
269                  ntohs(rtp_exp->tuple.dst.u.udp.port));
270         pr_debug("nf_nat_h323: expect RTCP %pI4:%hu->%pI4:%hu\n",
271                  &rtcp_exp->tuple.src.u3.ip,
272                  ntohs(rtcp_exp->tuple.src.u.udp.port),
273                  &rtcp_exp->tuple.dst.u3.ip,
274                  ntohs(rtcp_exp->tuple.dst.u.udp.port));
275 
276         return 0;
277 }
278 
279 /****************************************************************************/
280 static int nat_t120(struct sk_buff *skb, struct nf_conn *ct,
281                     enum ip_conntrack_info ctinfo,
282                     unsigned int protoff, unsigned char **data, int dataoff,
283                     H245_TransportAddress *taddr, __be16 port,
284                     struct nf_conntrack_expect *exp)
285 {
286         int dir = CTINFO2DIR(ctinfo);
287         u_int16_t nated_port = ntohs(port);
288 
289         /* Set expectations for NAT */
290         exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
291         exp->expectfn = nf_nat_follow_master;
292         exp->dir = !dir;
293 
294         /* Try to get same port: if not, try to change it. */
295         for (; nated_port != 0; nated_port++) {
296                 int ret;
297 
298                 exp->tuple.dst.u.tcp.port = htons(nated_port);
299                 ret = nf_ct_expect_related(exp, 0);
300                 if (ret == 0)
301                         break;
302                 else if (ret != -EBUSY) {
303                         nated_port = 0;
304                         break;
305                 }
306         }
307 
308         if (nated_port == 0) {  /* No port available */
309                 net_notice_ratelimited("nf_nat_h323: out of TCP ports\n");
310                 return 0;
311         }
312 
313         /* Modify signal */
314         if (set_h245_addr(skb, protoff, data, dataoff, taddr,
315                           &ct->tuplehash[!dir].tuple.dst.u3,
316                           htons(nated_port)) < 0) {
317                 nf_ct_unexpect_related(exp);
318                 return -1;
319         }
320 
321         pr_debug("nf_nat_h323: expect T.120 %pI4:%hu->%pI4:%hu\n",
322                  &exp->tuple.src.u3.ip,
323                  ntohs(exp->tuple.src.u.tcp.port),
324                  &exp->tuple.dst.u3.ip,
325                  ntohs(exp->tuple.dst.u.tcp.port));
326 
327         return 0;
328 }
329 
330 /****************************************************************************/
331 static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
332                     enum ip_conntrack_info ctinfo,
333                     unsigned int protoff, unsigned char **data, int dataoff,
334                     TransportAddress *taddr, __be16 port,
335                     struct nf_conntrack_expect *exp)
336 {
337         struct nf_ct_h323_master *info = nfct_help_data(ct);
338         int dir = CTINFO2DIR(ctinfo);
339         u_int16_t nated_port = ntohs(port);
340 
341         /* Set expectations for NAT */
342         exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
343         exp->expectfn = nf_nat_follow_master;
344         exp->dir = !dir;
345 
346         /* Check existing expects */
347         if (info->sig_port[dir] == port)
348                 nated_port = ntohs(info->sig_port[!dir]);
349 
350         /* Try to get same port: if not, try to change it. */
351         for (; nated_port != 0; nated_port++) {
352                 int ret;
353 
354                 exp->tuple.dst.u.tcp.port = htons(nated_port);
355                 ret = nf_ct_expect_related(exp, 0);
356                 if (ret == 0)
357                         break;
358                 else if (ret != -EBUSY) {
359                         nated_port = 0;
360                         break;
361                 }
362         }
363 
364         if (nated_port == 0) {  /* No port available */
365                 net_notice_ratelimited("nf_nat_q931: out of TCP ports\n");
366                 return 0;
367         }
368 
369         /* Modify signal */
370         if (set_h225_addr(skb, protoff, data, dataoff, taddr,
371                           &ct->tuplehash[!dir].tuple.dst.u3,
372                           htons(nated_port))) {
373                 nf_ct_unexpect_related(exp);
374                 return -1;
375         }
376 
377         /* Save ports */
378         info->sig_port[dir] = port;
379         info->sig_port[!dir] = htons(nated_port);
380 
381         pr_debug("nf_nat_q931: expect H.245 %pI4:%hu->%pI4:%hu\n",
382                  &exp->tuple.src.u3.ip,
383                  ntohs(exp->tuple.src.u.tcp.port),
384                  &exp->tuple.dst.u3.ip,
385                  ntohs(exp->tuple.dst.u.tcp.port));
386 
387         return 0;
388 }
389 
390 /****************************************************************************
391  * This conntrack expect function replaces nf_conntrack_q931_expect()
392  * which was set by nf_conntrack_h323.c.
393  ****************************************************************************/
394 static void ip_nat_q931_expect(struct nf_conn *new,
395                                struct nf_conntrack_expect *this)
396 {
397         struct nf_nat_range2 range;
398 
399         if (this->tuple.src.u3.ip != 0) {       /* Only accept calls from GK */
400                 nf_nat_follow_master(new, this);
401                 return;
402         }
403 
404         /* This must be a fresh one. */
405         BUG_ON(new->status & IPS_NAT_DONE_MASK);
406 
407         /* Change src to where master sends to */
408         range.flags = NF_NAT_RANGE_MAP_IPS;
409         range.min_addr = range.max_addr =
410             new->tuplehash[!this->dir].tuple.src.u3;
411         nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC);
412 
413         /* For DST manip, map port here to where it's expected. */
414         range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
415         range.min_proto = range.max_proto = this->saved_proto;
416         range.min_addr = range.max_addr =
417             new->master->tuplehash[!this->dir].tuple.src.u3;
418         nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST);
419 }
420 
421 /****************************************************************************/
422 static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
423                     enum ip_conntrack_info ctinfo,
424                     unsigned int protoff, unsigned char **data,
425                     TransportAddress *taddr, int idx,
426                     __be16 port, struct nf_conntrack_expect *exp)
427 {
428         struct nf_ct_h323_master *info = nfct_help_data(ct);
429         int dir = CTINFO2DIR(ctinfo);
430         u_int16_t nated_port = ntohs(port);
431         union nf_inet_addr addr;
432 
433         /* Set expectations for NAT */
434         exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
435         exp->expectfn = ip_nat_q931_expect;
436         exp->dir = !dir;
437 
438         /* Check existing expects */
439         if (info->sig_port[dir] == port)
440                 nated_port = ntohs(info->sig_port[!dir]);
441 
442         /* Try to get same port: if not, try to change it. */
443         for (; nated_port != 0; nated_port++) {
444                 int ret;
445 
446                 exp->tuple.dst.u.tcp.port = htons(nated_port);
447                 ret = nf_ct_expect_related(exp, 0);
448                 if (ret == 0)
449                         break;
450                 else if (ret != -EBUSY) {
451                         nated_port = 0;
452                         break;
453                 }
454         }
455 
456         if (nated_port == 0) {  /* No port available */
457                 net_notice_ratelimited("nf_nat_ras: out of TCP ports\n");
458                 return 0;
459         }
460 
461         /* Modify signal */
462         if (set_h225_addr(skb, protoff, data, 0, &taddr[idx],
463                           &ct->tuplehash[!dir].tuple.dst.u3,
464                           htons(nated_port))) {
465                 nf_ct_unexpect_related(exp);
466                 return -1;
467         }
468 
469         /* Save ports */
470         info->sig_port[dir] = port;
471         info->sig_port[!dir] = htons(nated_port);
472 
473         /* Fix for Gnomemeeting */
474         if (idx > 0 &&
475             get_h225_addr(ct, *data, &taddr[0], &addr, &port) &&
476             (ntohl(addr.ip) & 0xff000000) == 0x7f000000) {
477                 if (set_h225_addr(skb, protoff, data, 0, &taddr[0],
478                                   &ct->tuplehash[!dir].tuple.dst.u3,
479                                   info->sig_port[!dir])) {
480                         nf_ct_unexpect_related(exp);
481                         return -1;
482                 }
483         }
484 
485         /* Success */
486         pr_debug("nf_nat_ras: expect Q.931 %pI4:%hu->%pI4:%hu\n",
487                  &exp->tuple.src.u3.ip,
488                  ntohs(exp->tuple.src.u.tcp.port),
489                  &exp->tuple.dst.u3.ip,
490                  ntohs(exp->tuple.dst.u.tcp.port));
491 
492         return 0;
493 }
494 
495 /****************************************************************************/
496 static void ip_nat_callforwarding_expect(struct nf_conn *new,
497                                          struct nf_conntrack_expect *this)
498 {
499         struct nf_nat_range2 range;
500 
501         /* This must be a fresh one. */
502         BUG_ON(new->status & IPS_NAT_DONE_MASK);
503 
504         /* Change src to where master sends to */
505         range.flags = NF_NAT_RANGE_MAP_IPS;
506         range.min_addr = range.max_addr =
507             new->tuplehash[!this->dir].tuple.src.u3;
508         nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC);
509 
510         /* For DST manip, map port here to where it's expected. */
511         range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
512         range.min_proto = range.max_proto = this->saved_proto;
513         range.min_addr = range.max_addr = this->saved_addr;
514         nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST);
515 }
516 
517 /****************************************************************************/
518 static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct,
519                               enum ip_conntrack_info ctinfo,
520                               unsigned int protoff,
521                               unsigned char **data, int dataoff,
522                               TransportAddress *taddr, __be16 port,
523                               struct nf_conntrack_expect *exp)
524 {
525         int dir = CTINFO2DIR(ctinfo);
526         u_int16_t nated_port;
527 
528         /* Set expectations for NAT */
529         exp->saved_addr = exp->tuple.dst.u3;
530         exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
531         exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
532         exp->expectfn = ip_nat_callforwarding_expect;
533         exp->dir = !dir;
534 
535         /* Try to get same port: if not, try to change it. */
536         for (nated_port = ntohs(port); nated_port != 0; nated_port++) {
537                 int ret;
538 
539                 exp->tuple.dst.u.tcp.port = htons(nated_port);
540                 ret = nf_ct_expect_related(exp, 0);
541                 if (ret == 0)
542                         break;
543                 else if (ret != -EBUSY) {
544                         nated_port = 0;
545                         break;
546                 }
547         }
548 
549         if (nated_port == 0) {  /* No port available */
550                 net_notice_ratelimited("nf_nat_q931: out of TCP ports\n");
551                 return 0;
552         }
553 
554         /* Modify signal */
555         if (set_h225_addr(skb, protoff, data, dataoff, taddr,
556                           &ct->tuplehash[!dir].tuple.dst.u3,
557                           htons(nated_port))) {
558                 nf_ct_unexpect_related(exp);
559                 return -1;
560         }
561 
562         /* Success */
563         pr_debug("nf_nat_q931: expect Call Forwarding %pI4:%hu->%pI4:%hu\n",
564                  &exp->tuple.src.u3.ip,
565                  ntohs(exp->tuple.src.u.tcp.port),
566                  &exp->tuple.dst.u3.ip,
567                  ntohs(exp->tuple.dst.u.tcp.port));
568 
569         return 0;
570 }
571 
572 static struct nf_ct_helper_expectfn q931_nat = {
573         .name           = "Q.931",
574         .expectfn       = ip_nat_q931_expect,
575 };
576 
577 static struct nf_ct_helper_expectfn callforwarding_nat = {
578         .name           = "callforwarding",
579         .expectfn       = ip_nat_callforwarding_expect,
580 };
581 
582 /****************************************************************************/
583 static int __init init(void)
584 {
585         BUG_ON(set_h245_addr_hook != NULL);
586         BUG_ON(set_h225_addr_hook != NULL);
587         BUG_ON(set_sig_addr_hook != NULL);
588         BUG_ON(set_ras_addr_hook != NULL);
589         BUG_ON(nat_rtp_rtcp_hook != NULL);
590         BUG_ON(nat_t120_hook != NULL);
591         BUG_ON(nat_h245_hook != NULL);
592         BUG_ON(nat_callforwarding_hook != NULL);
593         BUG_ON(nat_q931_hook != NULL);
594 
595         RCU_INIT_POINTER(set_h245_addr_hook, set_h245_addr);
596         RCU_INIT_POINTER(set_h225_addr_hook, set_h225_addr);
597         RCU_INIT_POINTER(set_sig_addr_hook, set_sig_addr);
598         RCU_INIT_POINTER(set_ras_addr_hook, set_ras_addr);
599         RCU_INIT_POINTER(nat_rtp_rtcp_hook, nat_rtp_rtcp);
600         RCU_INIT_POINTER(nat_t120_hook, nat_t120);
601         RCU_INIT_POINTER(nat_h245_hook, nat_h245);
602         RCU_INIT_POINTER(nat_callforwarding_hook, nat_callforwarding);
603         RCU_INIT_POINTER(nat_q931_hook, nat_q931);
604         nf_ct_helper_expectfn_register(&q931_nat);
605         nf_ct_helper_expectfn_register(&callforwarding_nat);
606         return 0;
607 }
608 
609 /****************************************************************************/
610 static void __exit fini(void)
611 {
612         RCU_INIT_POINTER(set_h245_addr_hook, NULL);
613         RCU_INIT_POINTER(set_h225_addr_hook, NULL);
614         RCU_INIT_POINTER(set_sig_addr_hook, NULL);
615         RCU_INIT_POINTER(set_ras_addr_hook, NULL);
616         RCU_INIT_POINTER(nat_rtp_rtcp_hook, NULL);
617         RCU_INIT_POINTER(nat_t120_hook, NULL);
618         RCU_INIT_POINTER(nat_h245_hook, NULL);
619         RCU_INIT_POINTER(nat_callforwarding_hook, NULL);
620         RCU_INIT_POINTER(nat_q931_hook, NULL);
621         nf_ct_helper_expectfn_unregister(&q931_nat);
622         nf_ct_helper_expectfn_unregister(&callforwarding_nat);
623         synchronize_rcu();
624 }
625 
626 /****************************************************************************/
627 module_init(init);
628 module_exit(fini);
629 
630 MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
631 MODULE_DESCRIPTION("H.323 NAT helper");
632 MODULE_LICENSE("GPL");
633 MODULE_ALIAS_NF_NAT_HELPER("h323");
634 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp