📄 nf_conntrack_h323_main.c
字号:
if (ret < 0) return -1; } return 0;}/****************************************************************************/static int process_olca(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned char **data, int dataoff, OpenLogicalChannelAck *olca){ H2250LogicalChannelAckParameters *ack; int ret; pr_debug("nf_ct_h323: OpenLogicalChannelAck\n"); if ((olca->options & eOpenLogicalChannelAck_reverseLogicalChannelParameters) && (olca->reverseLogicalChannelParameters.options & eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters) && (olca->reverseLogicalChannelParameters.multiplexParameters. choice == eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) { ret = process_h245_channel(skb, ct, ctinfo, data, dataoff, &olca-> reverseLogicalChannelParameters. multiplexParameters. h2250LogicalChannelParameters); if (ret < 0) return -1; } if ((olca->options & eOpenLogicalChannelAck_forwardMultiplexAckParameters) && (olca->forwardMultiplexAckParameters.choice == eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters)) { ack = &olca->forwardMultiplexAckParameters. h2250LogicalChannelAckParameters; if (ack->options & eH2250LogicalChannelAckParameters_mediaChannel) { /* RTP */ ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff, &ack->mediaChannel); if (ret < 0) return -1; } if (ack->options & eH2250LogicalChannelAckParameters_mediaControlChannel) { /* RTCP */ ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff, &ack->mediaControlChannel); if (ret < 0) return -1; } } if ((olca->options & eOpenLogicalChannelAck_separateStack) && olca->separateStack.networkAddress.choice == eNetworkAccessParameters_networkAddress_localAreaAddress) { ret = expect_t120(skb, ct, ctinfo, data, dataoff, &olca->separateStack.networkAddress. localAreaAddress); if (ret < 0) return -1; } return 0;}/****************************************************************************/static int process_h245(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned char **data, int dataoff, MultimediaSystemControlMessage *mscm){ switch (mscm->choice) { case eMultimediaSystemControlMessage_request: if (mscm->request.choice == eRequestMessage_openLogicalChannel) { return process_olc(skb, ct, ctinfo, data, dataoff, &mscm->request.openLogicalChannel); } pr_debug("nf_ct_h323: H.245 Request %d\n", mscm->request.choice); break; case eMultimediaSystemControlMessage_response: if (mscm->response.choice == eResponseMessage_openLogicalChannelAck) { return process_olca(skb, ct, ctinfo, data, dataoff, &mscm->response. openLogicalChannelAck); } pr_debug("nf_ct_h323: H.245 Response %d\n", mscm->response.choice); break; default: pr_debug("nf_ct_h323: H.245 signal %d\n", mscm->choice); break; } return 0;}/****************************************************************************/static int h245_help(struct sk_buff *skb, unsigned int protoff, struct nf_conn *ct, enum ip_conntrack_info ctinfo){ static MultimediaSystemControlMessage mscm; unsigned char *data = NULL; int datalen; int dataoff; int ret; /* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { return NF_ACCEPT; } pr_debug("nf_ct_h245: skblen = %u\n", skb->len); spin_lock_bh(&nf_h323_lock); /* Process each TPKT */ while (get_tpkt_data(skb, protoff, ct, ctinfo, &data, &datalen, &dataoff)) { pr_debug("nf_ct_h245: TPKT len=%d ", datalen); NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); /* Decode H.245 signal */ ret = DecodeMultimediaSystemControlMessage(data, datalen, &mscm); if (ret < 0) { pr_debug("nf_ct_h245: decoding error: %s\n", ret == H323_ERROR_BOUND ? "out of bound" : "out of range"); /* We don't drop when decoding error */ break; } /* Process H.245 signal */ if (process_h245(skb, ct, ctinfo, &data, dataoff, &mscm) < 0) goto drop; } spin_unlock_bh(&nf_h323_lock); return NF_ACCEPT; drop: spin_unlock_bh(&nf_h323_lock); if (net_ratelimit()) printk("nf_ct_h245: packet dropped\n"); return NF_DROP;}/****************************************************************************/static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = { .name = "H.245", .me = THIS_MODULE, .max_expected = H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */, .timeout = 240, .tuple.dst.protonum = IPPROTO_UDP, .help = h245_help};/****************************************************************************/int get_h225_addr(struct nf_conn *ct, unsigned char *data, TransportAddress *taddr, union nf_conntrack_address *addr, __be16 *port){ unsigned char *p; int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; int len; switch (taddr->choice) { case eTransportAddress_ipAddress: if (family != AF_INET) return 0; p = data + taddr->ipAddress.ip; len = 4; break; case eTransportAddress_ip6Address: if (family != AF_INET6) return 0; p = data + taddr->ip6Address.ip; len = 16; break; default: return 0; } memcpy(addr, p, len); memset((void *)addr + len, 0, sizeof(*addr) - len); memcpy(port, p + len, sizeof(__be16)); return 1;}/****************************************************************************/static int expect_h245(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned char **data, int dataoff, TransportAddress *taddr){ int dir = CTINFO2DIR(ctinfo); int ret = 0; __be16 port; union nf_conntrack_address addr; struct nf_conntrack_expect *exp; typeof(nat_h245_hook) nat_h245; /* Read h245Address */ if (!get_h225_addr(ct, *data, taddr, &addr, &port) || memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) || port == 0) return 0; /* Create expect for h245 connection */ if ((exp = nf_ct_expect_alloc(ct)) == NULL) return -1; nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, &ct->tuplehash[!dir].tuple.src.u3, &ct->tuplehash[!dir].tuple.dst.u3, IPPROTO_TCP, NULL, &port); exp->helper = &nf_conntrack_helper_h245; if (memcmp(&ct->tuplehash[dir].tuple.src.u3, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(ct->tuplehash[dir].tuple.src.u3)) && (nat_h245 = rcu_dereference(nat_h245_hook)) && ct->status & IPS_NAT_MASK) { /* NAT needed */ ret = nat_h245(skb, ct, ctinfo, data, dataoff, taddr, port, exp); } else { /* Conntrack only */ if (nf_ct_expect_related(exp) == 0) { pr_debug("nf_ct_q931: expect H.245 "); NF_CT_DUMP_TUPLE(&exp->tuple); } else ret = -1; } nf_ct_expect_put(exp); return ret;}/* If the calling party is on the same side of the forward-to party, * we don't need to track the second call */static int callforward_do_filter(union nf_conntrack_address *src, union nf_conntrack_address *dst, int family){ struct flowi fl1, fl2; int ret = 0; memset(&fl1, 0, sizeof(fl1)); memset(&fl2, 0, sizeof(fl2)); switch (family) { case AF_INET: { struct rtable *rt1, *rt2; fl1.fl4_dst = src->ip; fl2.fl4_dst = dst->ip; if (ip_route_output_key(&rt1, &fl1) == 0) { if (ip_route_output_key(&rt2, &fl2) == 0) { if (rt1->rt_gateway == rt2->rt_gateway && rt1->u.dst.dev == rt2->u.dst.dev) ret = 1; dst_release(&rt2->u.dst); } dst_release(&rt1->u.dst); } break; }#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: { struct rt6_info *rt1, *rt2; memcpy(&fl1.fl6_dst, src, sizeof(fl1.fl6_dst)); memcpy(&fl2.fl6_dst, dst, sizeof(fl2.fl6_dst)); rt1 = (struct rt6_info *)ip6_route_output(NULL, &fl1); if (rt1) { rt2 = (struct rt6_info *)ip6_route_output(NULL, &fl2); if (rt2) { if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway, sizeof(rt1->rt6i_gateway)) && rt1->u.dst.dev == rt2->u.dst.dev) ret = 1; dst_release(&rt2->u.dst); } dst_release(&rt1->u.dst); } break; }#endif } return ret;}/****************************************************************************/static int expect_callforwarding(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned char **data, int dataoff, TransportAddress *taddr){ int dir = CTINFO2DIR(ctinfo); int ret = 0; __be16 port; union nf_conntrack_address addr; struct nf_conntrack_expect *exp; typeof(nat_callforwarding_hook) nat_callforwarding; /* Read alternativeAddress */ if (!get_h225_addr(ct, *data, taddr, &addr, &port) || port == 0) return 0; /* If the calling party is on the same side of the forward-to party, * we don't need to track the second call */ if (callforward_filter && callforward_do_filter(&addr, &ct->tuplehash[!dir].tuple.src.u3, ct->tuplehash[!dir].tuple.src.l3num)) { pr_debug("nf_ct_q931: Call Forwarding not tracked\n"); return 0; } /* Create expect for the second call leg */ if ((exp = nf_ct_expect_alloc(ct)) == NULL) return -1; nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, &ct->tuplehash[!dir].tuple.src.u3, &addr, IPPROTO_TCP, NULL, &port); exp->helper = nf_conntrack_helper_q931; if (memcmp(&ct->tuplehash[dir].tuple.src.u3, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(ct->tuplehash[dir].tuple.src.u3)) && (nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) && ct->status & IPS_NAT_MASK) { /* Need NAT */ ret = nat_callforwarding(skb, ct, ctinfo, data, dataoff, taddr, port, exp); } else { /* Conntrack only */ if (nf_ct_expect_related(exp) == 0) { pr_debug("nf_ct_q931: expect Call Forwarding "); NF_CT_DUMP_TUPLE(&exp->tuple); } else ret = -1; } nf_ct_expect_put(exp); return ret;}/****************************************************************************/static int process_setup(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned char **data, int dataoff, Setup_UUIE *setup){ int dir = CTINFO2DIR(ctinfo); int ret; int i; __be16 port; union nf_conntrack_address addr; typeof(set_h225_addr_hook) set_h225_addr; pr_debug("nf_ct_q931: Setup\n"); if (setup->options & eSetup_UUIE_h245Address) { ret = expect_h245(skb, ct, ctinfo, data, dataoff, &setup->h245Address); if (ret < 0) return -1; } set_h225_addr = rcu_dereference(set_h225_addr_hook); if ((setup->options & eSetup_UUIE_destCallSignalAddress) && (set_h225_addr) && ct->status && IPS_NAT_MASK && get_h225_addr(ct, *data, &setup->destCallSignalAddress, &addr, &port) && memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) { pr_debug("nf_ct_q931: set destCallSignalAddress " NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n", NIP6(*(struct in6_addr *)&addr), ntohs(port), NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3), ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port)); ret = set_h225_addr(skb, data, dataoff, &setup->destCallSignalAddress, &ct->tuplehash[!dir].tuple.src.u3, ct->tuplehash[!dir].tuple.src.u.tcp.port); if (ret < 0) return -1; } if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) && (set_h225_addr) && ct->status & IPS_NAT_MASK && get_h225_addr(ct, *data, &setup->sourceCallSignalAddress, &addr, &port) && memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) { pr_debug("nf_ct_q931: set sourceCallSignalAddress " NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n", NIP6(*(struct in6_addr *)&addr), ntohs(port), NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3), ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port)); ret = set_h225_addr(skb, data, dataoff, &setup->sourceCallSignalAddress, &ct->tuplehash[!dir].tuple.dst.u3, ct->tuplehash[!dir].tuple.dst.u.tcp.port); if (ret < 0) return -1; } if (setup->options & eSetup_UUIE_fastStart) { for (i = 0; i < setup->fastStart.count; i++) { ret = process_olc(skb, ct, ctinfo, data, dataoff, &setup->fastStart.item[i]); if (ret < 0) return -1; } } return 0;}/****************************************************************************/static int process_callproceeding(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo, unsigned char **data, int dataoff, CallProceeding_UUIE *callproc){ int ret; int i; pr_debug("nf_ct_q931: CallProceeding\n"); if (callproc->options & eCallProceeding_UUIE_h245Address) { ret = expect_h245(skb, ct, ctinfo, data, dataoff, &callproc->h245Address); if (ret < 0) return -1; } if (callproc->options & eCallProceeding_UUIE_fastStart) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -