📄 ip_conntrack_helper_h323.c
字号:
return 0;}/****************************************************************************/static int process_rcf(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, unsigned char **data, RegistrationConfirm * rcf){ struct ip_ct_h323_master *info = &ct->help.ct_h323_info; int dir = CTINFO2DIR(ctinfo); int ret; struct ip_conntrack_expect *exp; DEBUGP("ip_ct_ras: RCF\n"); if (set_sig_addr_hook) { ret = set_sig_addr_hook(pskb, ct, ctinfo, data, rcf->callSignalAddress.item, rcf->callSignalAddress.count); if (ret < 0) return -1; } if (rcf->options & eRegistrationConfirm_timeToLive) { DEBUGP("ip_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive); info->timeout = rcf->timeToLive; } if (info->timeout > 0) { DEBUGP ("ip_ct_ras: set RAS connection timeout to %u seconds\n", info->timeout); ip_ct_refresh_acct(ct, ctinfo, NULL, info->timeout * HZ); /* Set expect timeout */ read_lock_bh(&ip_conntrack_lock); exp = find_expect(ct, ct->tuplehash[dir].tuple.dst.ip, info->sig_port[!dir]); if (exp) { DEBUGP("ip_ct_ras: set Q.931 expect " "(%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu) " "timeout to %u seconds\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), info->timeout); set_expect_timeout(exp, info->timeout); } read_unlock_bh(&ip_conntrack_lock); } return 0;}/****************************************************************************/static int process_urq(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, unsigned char **data, UnregistrationRequest * urq){ struct ip_ct_h323_master *info = &ct->help.ct_h323_info; int dir = CTINFO2DIR(ctinfo); int ret; DEBUGP("ip_ct_ras: URQ\n"); if (set_sig_addr_hook) { ret = set_sig_addr_hook(pskb, ct, ctinfo, data, urq->callSignalAddress.item, urq->callSignalAddress.count); if (ret < 0) return -1; } /* Clear old expect */ ip_ct_remove_expectations(ct); info->sig_port[dir] = 0; info->sig_port[!dir] = 0; /* Give it 30 seconds for UCF or URJ */ ip_ct_refresh_acct(ct, ctinfo, NULL, 30 * HZ); return 0;}/****************************************************************************/static int process_arq(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, unsigned char **data, AdmissionRequest * arq){ struct ip_ct_h323_master *info = &ct->help.ct_h323_info; int dir = CTINFO2DIR(ctinfo); u_int32_t ip; u_int16_t port; DEBUGP("ip_ct_ras: ARQ\n"); if ((arq->options & eAdmissionRequest_destCallSignalAddress) && get_h225_addr(*data, &arq->destCallSignalAddress, &ip, &port) && ip == ct->tuplehash[dir].tuple.src.ip && port == info->sig_port[dir] && set_h225_addr_hook) { /* Answering ARQ */ return set_h225_addr_hook(pskb, data, 0, &arq->destCallSignalAddress, ct->tuplehash[!dir].tuple.dst.ip, info->sig_port[!dir]); } if ((arq->options & eAdmissionRequest_srcCallSignalAddress) && get_h225_addr(*data, &arq->srcCallSignalAddress, &ip, &port) && ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr_hook) { /* Calling ARQ */ return set_h225_addr_hook(pskb, data, 0, &arq->srcCallSignalAddress, ct->tuplehash[!dir].tuple.dst.ip, port); } return 0;}/****************************************************************************/static int process_acf(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, unsigned char **data, AdmissionConfirm * acf){ int dir = CTINFO2DIR(ctinfo); int ret = 0; u_int32_t ip; u_int16_t port; struct ip_conntrack_expect *exp; DEBUGP("ip_ct_ras: ACF\n"); if (!get_h225_addr(*data, &acf->destCallSignalAddress, &ip, &port)) return 0; if (ip == ct->tuplehash[dir].tuple.dst.ip) { /* Answering ACF */ if (set_sig_addr_hook) return set_sig_addr_hook(pskb, ct, ctinfo, data, &acf->destCallSignalAddress, 1); return 0; } /* Need new expect */ if ((exp = ip_conntrack_expect_alloc(ct)) == NULL) return -1; exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip; exp->tuple.src.u.tcp.port = 0; exp->tuple.dst.ip = ip; exp->tuple.dst.u.tcp.port = htons(port); exp->tuple.dst.protonum = IPPROTO_TCP; exp->mask.src.ip = 0xFFFFFFFF; exp->mask.src.u.tcp.port = 0; exp->mask.dst.ip = 0xFFFFFFFF; exp->mask.dst.u.tcp.port = 0xFFFF; exp->mask.dst.protonum = 0xFF; exp->flags = IP_CT_EXPECT_PERMANENT; exp->expectfn = ip_conntrack_q931_expect; if (ip_conntrack_expect_related(exp) == 0) { DEBUGP("ip_ct_ras: expect Q.931 " "%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)); } else ret = -1; ip_conntrack_expect_put(exp); return ret;}/****************************************************************************/static int process_lrq(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, unsigned char **data, LocationRequest * lrq){ DEBUGP("ip_ct_ras: LRQ\n"); if (set_ras_addr_hook) return set_ras_addr_hook(pskb, ct, ctinfo, data, &lrq->replyAddress, 1); return 0;}/****************************************************************************/static int process_lcf(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, unsigned char **data, LocationConfirm * lcf){ int dir = CTINFO2DIR(ctinfo); int ret = 0; u_int32_t ip; u_int16_t port; struct ip_conntrack_expect *exp = NULL; DEBUGP("ip_ct_ras: LCF\n"); if (!get_h225_addr(*data, &lcf->callSignalAddress, &ip, &port)) return 0; /* Need new expect for call signal */ if ((exp = ip_conntrack_expect_alloc(ct)) == NULL) return -1; exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip; exp->tuple.src.u.tcp.port = 0; exp->tuple.dst.ip = ip; exp->tuple.dst.u.tcp.port = htons(port); exp->tuple.dst.protonum = IPPROTO_TCP; exp->mask.src.ip = 0xFFFFFFFF; exp->mask.src.u.tcp.port = 0; exp->mask.dst.ip = 0xFFFFFFFF; exp->mask.dst.u.tcp.port = 0xFFFF; exp->mask.dst.protonum = 0xFF; exp->flags = IP_CT_EXPECT_PERMANENT; exp->expectfn = ip_conntrack_q931_expect; if (ip_conntrack_expect_related(exp) == 0) { DEBUGP("ip_ct_ras: expect Q.931 " "%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)); } else ret = -1; ip_conntrack_expect_put(exp); /* Ignore rasAddress */ return ret;}/****************************************************************************/static int process_irr(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, unsigned char **data, InfoRequestResponse * irr){ int ret; DEBUGP("ip_ct_ras: IRR\n"); if (set_ras_addr_hook) { ret = set_ras_addr_hook(pskb, ct, ctinfo, data, &irr->rasAddress, 1); if (ret < 0) return -1; } if (set_sig_addr_hook) { ret = set_sig_addr_hook(pskb, ct, ctinfo, data, irr->callSignalAddress.item, irr->callSignalAddress.count); if (ret < 0) return -1; } return 0;}/****************************************************************************/static int process_ras(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, unsigned char **data, RasMessage * ras){ switch (ras->choice) { case eRasMessage_gatekeeperRequest: return process_grq(pskb, ct, ctinfo, data, &ras->gatekeeperRequest); case eRasMessage_gatekeeperConfirm: return process_gcf(pskb, ct, ctinfo, data, &ras->gatekeeperConfirm); case eRasMessage_registrationRequest: return process_rrq(pskb, ct, ctinfo, data, &ras->registrationRequest); case eRasMessage_registrationConfirm: return process_rcf(pskb, ct, ctinfo, data, &ras->registrationConfirm); case eRasMessage_unregistrationRequest: return process_urq(pskb, ct, ctinfo, data, &ras->unregistrationRequest); case eRasMessage_admissionRequest: return process_arq(pskb, ct, ctinfo, data, &ras->admissionRequest); case eRasMessage_admissionConfirm: return process_acf(pskb, ct, ctinfo, data, &ras->admissionConfirm); case eRasMessage_locationRequest: return process_lrq(pskb, ct, ctinfo, data, &ras->locationRequest); case eRasMessage_locationConfirm: return process_lcf(pskb, ct, ctinfo, data, &ras->locationConfirm); case eRasMessage_infoRequestResponse: return process_irr(pskb, ct, ctinfo, data, &ras->infoRequestResponse); default: DEBUGP("ip_ct_ras: RAS message %d\n", ras->choice); break; } return 0;}/****************************************************************************/static int ras_help(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo){ static RasMessage ras; unsigned char *data; int datalen = 0; int ret; DEBUGP("ip_ct_ras: skblen = %u\n", (*pskb)->len); spin_lock_bh(&ip_h323_lock); /* Get UDP data */ data = get_udp_data(pskb, &datalen); if (data == NULL) goto accept; DEBUGP("ip_ct_ras: RAS message %u.%u.%u.%u->%u.%u.%u.%u, len=%d\n", NIPQUAD((*pskb)->nh.iph->saddr), NIPQUAD((*pskb)->nh.iph->daddr), datalen); /* Decode RAS message */ ret = DecodeRasMessage(data, datalen, &ras); if (ret < 0) { if (net_ratelimit()) printk("ip_ct_ras: decoding error: %s\n", ret == H323_ERROR_BOUND ? "out of bound" : "out of range"); goto accept; } /* Process RAS message */ if (process_ras(pskb, ct, ctinfo, &data, &ras) < 0) goto drop; accept: spin_unlock_bh(&ip_h323_lock); return NF_ACCEPT; drop: spin_unlock_bh(&ip_h323_lock); if (net_ratelimit()) printk("ip_ct_ras: packet dropped\n"); return NF_DROP;}/****************************************************************************/static struct ip_conntrack_helper ip_conntrack_helper_ras = { .name = "RAS", .me = THIS_MODULE, .max_expected = 32, .timeout = 240, .tuple = {.src = {.u = {__constant_htons(RAS_PORT)}}, .dst = {.protonum = IPPROTO_UDP}}, .mask = {.src = {.u = {0xFFFE}}, .dst = {.protonum = 0xFF}}, .help = ras_help,};/****************************************************************************/static void ip_conntrack_ras_expect(struct ip_conntrack *new, struct ip_conntrack_expect *this){ write_lock_bh(&ip_conntrack_lock); new->helper = &ip_conntrack_helper_ras; write_unlock_bh(&ip_conntrack_lock);}/****************************************************************************//* Not __exit - called from init() */static void fini(void){ ip_conntrack_helper_unregister(&ip_conntrack_helper_ras); ip_conntrack_helper_unregister(&ip_conntrack_helper_q931); kfree(h323_buffer); DEBUGP("ip_ct_h323: fini\n");}/****************************************************************************/static int __init init(void){ int ret; h323_buffer = kmalloc(65536, GFP_KERNEL); if (!h323_buffer) return -ENOMEM; if ((ret = ip_conntrack_helper_register(&ip_conntrack_helper_q931)) || (ret = ip_conntrack_helper_register(&ip_conntrack_helper_ras))) { fini(); return ret; } DEBUGP("ip_ct_h323: init success\n"); return 0;}/****************************************************************************/module_init(init);module_exit(fini);EXPORT_SYMBOL_GPL(get_h225_addr);EXPORT_SYMBOL_GPL(ip_conntrack_h245_expect);EXPORT_SYMBOL_GPL(ip_conntrack_q931_expect);EXPORT_SYMBOL_GPL(set_h245_addr_hook);EXPORT_SYMBOL_GPL(set_h225_addr_hook);EXPORT_SYMBOL_GPL(set_sig_addr_hook);EXPORT_SYMBOL_GPL(set_ras_addr_hook);EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook);EXPORT_SYMBOL_GPL(nat_t120_hook);EXPORT_SYMBOL_GPL(nat_h245_hook);EXPORT_SYMBOL_GPL(nat_q931_hook);MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");MODULE_DESCRIPTION("H.323 connection tracking helper");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -