static int nat_t120(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned char **data, int dataoff, H245_TransportAddress *taddr, __be16 port, struct nf_conntrack_expect *exp) { int dir = CTINFO2DIR(ctinfo); u_int16_t nated_port = ntohs(port); /* Set expectations for NAT */ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; exp->expectfn = nf_nat_follow_master; exp->dir = !dir; /* Try to get same port: if not, try to change it. */ for (; nated_port != 0; nated_port++) { int ret; exp->tuple.dst.u.tcp.port = htons(nated_port); ret = nf_ct_expect_related(exp); if (ret == 0) break; else if (ret != -EBUSY) { nated_port = 0; break; } } if (nated_port == 0) { /* No port available */ if (net_ratelimit()) pr_notice("nf_nat_h323: out of TCP ports\n"); return 0; } /* Modify signal */ if (set_h245_addr(skb, data, dataoff, taddr, &ct->tuplehash[!dir].tuple.dst.u3, htons(nated_port)) < 0) { nf_ct_unexpect_related(exp); return -1; } pr_debug("nf_nat_h323: expect T.120 %pI4:%hu->%pI4:%hu\n", &exp->tuple.src.u3.ip, ntohs(exp->tuple.src.u.tcp.port), &exp->tuple.dst.u3.ip, ntohs(exp->tuple.dst.u.tcp.port)); return 0; }
static int nat_t120(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, unsigned char **data, int dataoff, H245_TransportAddress * addr, u_int16_t port, struct ip_conntrack_expect *exp) { int dir = CTINFO2DIR(ctinfo); u_int16_t nated_port = port; /* Set expectations for NAT */ exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; exp->expectfn = ip_nat_follow_master; exp->dir = !dir; /* Try to get same port: if not, try to change it. */ for (; nated_port != 0; nated_port++) { exp->tuple.dst.u.tcp.port = htons(nated_port); if (ip_conntrack_expect_related(exp) == 0) break; } if (nated_port == 0) { /* No port available */ if (net_ratelimit()) printk("ip_nat_h323: out of TCP ports\n"); return 0; } /* Modify signal */ if (set_h245_addr(pskb, data, dataoff, addr, ct->tuplehash[!dir].tuple.dst.ip, nated_port) < 0) { ip_conntrack_unexpect_related(exp); return -1; } DEBUGP("ip_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port), NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port)); return 0; }
static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned char **data, int dataoff, H245_TransportAddress *taddr, __be16 port, __be16 rtp_port, struct nf_conntrack_expect *rtp_exp, struct nf_conntrack_expect *rtcp_exp) { struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; int dir = CTINFO2DIR(ctinfo); int i; u_int16_t nated_port; /* Set expectations for NAT */ rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port; rtp_exp->expectfn = nf_nat_follow_master; rtp_exp->dir = !dir; rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port; rtcp_exp->expectfn = nf_nat_follow_master; rtcp_exp->dir = !dir; /* Lookup existing expects */ for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) { if (info->rtp_port[i][dir] == rtp_port) { /* Expected */ /* Use allocated ports first. This will refresh * the expects */ rtp_exp->tuple.dst.u.udp.port = info->rtp_port[i][dir]; rtcp_exp->tuple.dst.u.udp.port = htons(ntohs(info->rtp_port[i][dir]) + 1); break; } else if (info->rtp_port[i][dir] == 0) { /* Not expected */ break; } } /* Run out of expectations */ if (i >= H323_RTP_CHANNEL_MAX) { if (net_ratelimit()) printk("nf_nat_h323: out of expectations\n"); return 0; } /* Try to get a pair of ports. */ for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port); nated_port != 0; nated_port += 2) { rtp_exp->tuple.dst.u.udp.port = htons(nated_port); if (nf_conntrack_expect_related(rtp_exp) == 0) { rtcp_exp->tuple.dst.u.udp.port = htons(nated_port + 1); if (nf_conntrack_expect_related(rtcp_exp) == 0) break; nf_conntrack_unexpect_related(rtp_exp); } } if (nated_port == 0) { /* No port available */ if (net_ratelimit()) printk("nf_nat_h323: out of RTP ports\n"); return 0; } /* Modify signal */ if (set_h245_addr(skb, data, dataoff, taddr, &ct->tuplehash[!dir].tuple.dst.u3, htons((port & htons(1)) ? nated_port + 1 : nated_port)) == 0) { /* Save ports */ info->rtp_port[i][dir] = rtp_port; info->rtp_port[i][!dir] = htons(nated_port); } else { nf_conntrack_unexpect_related(rtp_exp); nf_conntrack_unexpect_related(rtcp_exp); return -1; } /* Success */ DEBUGP("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", NIPQUAD(rtp_exp->tuple.src.ip), ntohs(rtp_exp->tuple.src.u.udp.port), NIPQUAD(rtp_exp->tuple.dst.ip), ntohs(rtp_exp->tuple.dst.u.udp.port)); DEBUGP("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", NIPQUAD(rtcp_exp->tuple.src.ip), ntohs(rtcp_exp->tuple.src.u.udp.port), NIPQUAD(rtcp_exp->tuple.dst.ip), ntohs(rtcp_exp->tuple.dst.u.udp.port)); return 0; }