Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[NETFILTER]: nf_conntrack/nf_nat: add H.323 helper port

Add IPv4 and IPv6 capable nf_conntrack port of the H.323 conntrack/NAT helper.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Patrick McHardy and committed by
David S. Miller
f587de0e 16958900

+2600 -14
+92
include/linux/netfilter/nf_conntrack_h323.h
··· 1 + #ifndef _NF_CONNTRACK_H323_H 2 + #define _NF_CONNTRACK_H323_H 3 + 4 + #ifdef __KERNEL__ 5 + 6 + #include <linux/netfilter/nf_conntrack_h323_asn1.h> 7 + 8 + #define RAS_PORT 1719 9 + #define Q931_PORT 1720 10 + #define H323_RTP_CHANNEL_MAX 4 /* Audio, video, FAX and other */ 11 + 12 + /* This structure exists only once per master */ 13 + struct nf_ct_h323_master { 14 + 15 + /* Original and NATed Q.931 or H.245 signal ports */ 16 + __be16 sig_port[IP_CT_DIR_MAX]; 17 + 18 + /* Original and NATed RTP ports */ 19 + __be16 rtp_port[H323_RTP_CHANNEL_MAX][IP_CT_DIR_MAX]; 20 + 21 + union { 22 + /* RAS connection timeout */ 23 + u_int32_t timeout; 24 + 25 + /* Next TPKT length (for separate TPKT header and data) */ 26 + u_int16_t tpkt_len[IP_CT_DIR_MAX]; 27 + }; 28 + }; 29 + 30 + struct nf_conn; 31 + 32 + extern int get_h225_addr(struct nf_conn *ct, unsigned char *data, 33 + TransportAddress *taddr, 34 + union nf_conntrack_address *addr, __be16 *port); 35 + extern void nf_conntrack_h245_expect(struct nf_conn *new, 36 + struct nf_conntrack_expect *this); 37 + extern void nf_conntrack_q931_expect(struct nf_conn *new, 38 + struct nf_conntrack_expect *this); 39 + extern int (*set_h245_addr_hook) (struct sk_buff **pskb, 40 + unsigned char **data, int dataoff, 41 + H245_TransportAddress *taddr, 42 + union nf_conntrack_address *addr, 43 + __be16 port); 44 + extern int (*set_h225_addr_hook) (struct sk_buff **pskb, 45 + unsigned char **data, int dataoff, 46 + TransportAddress *taddr, 47 + union nf_conntrack_address *addr, 48 + __be16 port); 49 + extern int (*set_sig_addr_hook) (struct sk_buff **pskb, 50 + struct nf_conn *ct, 51 + enum ip_conntrack_info ctinfo, 52 + unsigned char **data, 53 + TransportAddress *taddr, int count); 54 + extern int (*set_ras_addr_hook) (struct sk_buff **pskb, 55 + struct nf_conn *ct, 56 + enum ip_conntrack_info ctinfo, 57 + unsigned char **data, 58 + TransportAddress *taddr, int count); 59 + extern int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb, 60 + struct nf_conn *ct, 61 + enum ip_conntrack_info ctinfo, 62 + unsigned char **data, int dataoff, 63 + H245_TransportAddress *taddr, 64 + __be16 port, __be16 rtp_port, 65 + struct nf_conntrack_expect *rtp_exp, 66 + struct nf_conntrack_expect *rtcp_exp); 67 + extern int (*nat_t120_hook) (struct sk_buff **pskb, struct nf_conn *ct, 68 + enum ip_conntrack_info ctinfo, 69 + unsigned char **data, int dataoff, 70 + H245_TransportAddress *taddr, __be16 port, 71 + struct nf_conntrack_expect *exp); 72 + extern int (*nat_h245_hook) (struct sk_buff **pskb, struct nf_conn *ct, 73 + enum ip_conntrack_info ctinfo, 74 + unsigned char **data, int dataoff, 75 + TransportAddress *taddr, __be16 port, 76 + struct nf_conntrack_expect *exp); 77 + extern int (*nat_callforwarding_hook) (struct sk_buff **pskb, 78 + struct nf_conn *ct, 79 + enum ip_conntrack_info ctinfo, 80 + unsigned char **data, int dataoff, 81 + TransportAddress *taddr, 82 + __be16 port, 83 + struct nf_conntrack_expect *exp); 84 + extern int (*nat_q931_hook) (struct sk_buff **pskb, struct nf_conn *ct, 85 + enum ip_conntrack_info ctinfo, 86 + unsigned char **data, TransportAddress *taddr, 87 + int idx, __be16 port, 88 + struct nf_conntrack_expect *exp); 89 + 90 + #endif 91 + 92 + #endif
-2
include/linux/netfilter_ipv4/Kbuild
··· 1 1 header-y += ip_conntrack_helper.h 2 - header-y += ip_conntrack_helper_h323_asn1.h 3 - header-y += ip_conntrack_helper_h323_types.h 4 2 header-y += ip_conntrack_protocol.h 5 3 header-y += ip_conntrack_sctp.h 6 4 header-y += ip_conntrack_tcp.h
+1 -1
include/linux/netfilter_ipv4/ip_conntrack_h323.h
··· 3 3 4 4 #ifdef __KERNEL__ 5 5 6 - #include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h> 6 + #include <linux/netfilter/nf_conntrack_h323_asn1.h> 7 7 8 8 #define RAS_PORT 1719 9 9 #define Q931_PORT 1720
+5 -5
include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h include/linux/netfilter/nf_conntrack_h323_asn1.h
··· 1 1 /**************************************************************************** 2 - * ip_conntrack_helper_h323_asn1.h - BER and PER decoding library for H.323 3 - * conntrack/NAT module. 2 + * ip_conntrack_h323_asn1.h - BER and PER decoding library for H.323 3 + * conntrack/NAT module. 4 4 * 5 5 * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net> 6 6 * ··· 34 34 * 35 35 ****************************************************************************/ 36 36 37 - #ifndef _IP_CONNTRACK_HELPER_H323_ASN1_H_ 38 - #define _IP_CONNTRACK_HELPER_H323_ASN1_H_ 37 + #ifndef _NF_CONNTRACK_HELPER_H323_ASN1_H_ 38 + #define _NF_CONNTRACK_HELPER_H323_ASN1_H_ 39 39 40 40 /***************************************************************************** 41 41 * H.323 Types 42 42 ****************************************************************************/ 43 - #include "ip_conntrack_helper_h323_types.h" 43 + #include "nf_conntrack_h323_types.h" 44 44 45 45 typedef struct { 46 46 enum {
+12
include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h include/linux/netfilter/nf_conntrack_h323_types.h
··· 10 10 unsigned ip; 11 11 } TransportAddress_ipAddress; 12 12 13 + typedef struct TransportAddress_ip6Address { /* SEQUENCE */ 14 + int options; /* No use */ 15 + unsigned ip6; 16 + } TransportAddress_ip6Address; 17 + 13 18 typedef struct TransportAddress { /* CHOICE */ 14 19 enum { 15 20 eTransportAddress_ipAddress, ··· 27 22 } choice; 28 23 union { 29 24 TransportAddress_ipAddress ipAddress; 25 + TransportAddress_ip6Address ip6Address; 30 26 }; 31 27 } TransportAddress; 32 28 ··· 99 93 unsigned network; 100 94 } UnicastAddress_iPAddress; 101 95 96 + typedef struct UnicastAddress_iP6Address { /* SEQUENCE */ 97 + int options; /* No use */ 98 + unsigned network; 99 + } UnicastAddress_iP6Address; 100 + 102 101 typedef struct UnicastAddress { /* CHOICE */ 103 102 enum { 104 103 eUnicastAddress_iPAddress, ··· 116 105 } choice; 117 106 union { 118 107 UnicastAddress_iPAddress iPAddress; 108 + UnicastAddress_iP6Address iP6Address; 119 109 }; 120 110 } UnicastAddress; 121 111
+2
include/net/netfilter/nf_conntrack.h
··· 41 41 42 42 /* Add protocol helper include file here */ 43 43 #include <linux/netfilter/nf_conntrack_ftp.h> 44 + #include <linux/netfilter/nf_conntrack_h323.h> 44 45 45 46 /* per conntrack: application helper private data */ 46 47 union nf_conntrack_help { 47 48 /* insert conntrack helper private data (master) here */ 48 49 struct nf_ct_ftp_master ct_ftp_info; 50 + struct nf_ct_h323_master ct_h323_info; 49 51 }; 50 52 51 53 #include <linux/types.h>
+1
include/net/netfilter/nf_conntrack_expect.h
··· 41 41 unsigned int flags; 42 42 43 43 #ifdef CONFIG_NF_NAT_NEEDED 44 + __be32 saved_ip; 44 45 /* This is the original per-proto part, used to map the 45 46 * expected connection the way the recipient expects. */ 46 47 union nf_conntrack_man_proto saved_proto;
+5
net/ipv4/netfilter/Kconfig
··· 529 529 default IP_NF_NAT if IP_NF_H323=y 530 530 default m if IP_NF_H323=m 531 531 532 + config NF_NAT_H323 533 + tristate 534 + depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 535 + default NF_NAT && NF_CONNTRACK_H323 536 + 532 537 config IP_NF_NAT_SIP 533 538 tristate 534 539 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
+2 -1
net/ipv4/netfilter/Makefile
··· 15 15 ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o 16 16 ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o 17 17 18 - ip_conntrack_h323-objs := ip_conntrack_helper_h323.o ip_conntrack_helper_h323_asn1.o 18 + ip_conntrack_h323-objs := ip_conntrack_helper_h323.o ../../netfilter/nf_conntrack_h323_asn1.o 19 19 ip_nat_h323-objs := ip_nat_helper_h323.o 20 20 21 21 # connection tracking ··· 52 52 # NAT helpers (nf_conntrack) 53 53 obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o 54 54 obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o 55 + obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o 55 56 56 57 # generic IP tables 57 58 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
+2 -2
net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c net/netfilter/nf_conntrack_h323_asn1.c
··· 15 15 #else 16 16 #include <stdio.h> 17 17 #endif 18 - #include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h> 18 + #include <linux/netfilter/nf_conntrack_h323_asn1.h> 19 19 20 20 /* Trace Flag */ 21 21 #ifndef H323_TRACE ··· 144 144 /**************************************************************************** 145 145 * H.323 Types 146 146 ****************************************************************************/ 147 - #include "ip_conntrack_helper_h323_types.c" 147 + #include "nf_conntrack_h323_types.c" 148 148 149 149 /**************************************************************************** 150 150 * Functions
+4 -3
net/ipv4/netfilter/ip_conntrack_helper_h323_types.c net/netfilter/nf_conntrack_h323_types.c
··· 36 36 }; 37 37 38 38 static field_t _TransportAddress_ip6Address[] = { /* SEQUENCE */ 39 - {FNAME("ip") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, 39 + {FNAME("ip") OCTSTR, FIXD, 16, 0, DECODE, 40 + offsetof(TransportAddress_ip6Address, ip6), NULL}, 40 41 {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL}, 41 42 }; 42 43 ··· 66 65 _TransportAddress_ipSourceRoute}, 67 66 {FNAME("ipxAddress") SEQ, 0, 3, 3, SKIP, 0, 68 67 _TransportAddress_ipxAddress}, 69 - {FNAME("ip6Address") SEQ, 0, 2, 2, SKIP | EXT, 0, 70 - _TransportAddress_ip6Address}, 68 + {FNAME("ip6Address") SEQ, 0, 2, 2, DECODE | EXT, 69 + offsetof(TransportAddress, ip6Address), _TransportAddress_ip6Address}, 71 70 {FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL}, 72 71 {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL}, 73 72 {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0,
+596
net/ipv4/netfilter/nf_nat_h323.c
··· 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 + 12 + #include <linux/module.h> 13 + #include <linux/moduleparam.h> 14 + #include <linux/tcp.h> 15 + #include <net/tcp.h> 16 + 17 + #include <net/netfilter/nf_nat.h> 18 + #include <net/netfilter/nf_nat_helper.h> 19 + #include <net/netfilter/nf_nat_rule.h> 20 + #include <net/netfilter/nf_conntrack_helper.h> 21 + #include <net/netfilter/nf_conntrack_expect.h> 22 + #include <linux/netfilter/nf_conntrack_h323.h> 23 + 24 + #if 0 25 + #define DEBUGP printk 26 + #else 27 + #define DEBUGP(format, args...) 28 + #endif 29 + 30 + /****************************************************************************/ 31 + static int set_addr(struct sk_buff **pskb, 32 + unsigned char **data, int dataoff, 33 + unsigned int addroff, __be32 ip, __be16 port) 34 + { 35 + enum ip_conntrack_info ctinfo; 36 + struct nf_conn *ct = ip_conntrack_get(*pskb, &ctinfo); 37 + struct { 38 + __be32 ip; 39 + __be16 port; 40 + } __attribute__ ((__packed__)) buf; 41 + struct tcphdr _tcph, *th; 42 + 43 + buf.ip = ip; 44 + buf.port = port; 45 + addroff += dataoff; 46 + 47 + if ((*pskb)->nh.iph->protocol == IPPROTO_TCP) { 48 + if (!nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, 49 + addroff, sizeof(buf), 50 + (char *) &buf, sizeof(buf))) { 51 + if (net_ratelimit()) 52 + printk("nf_nat_h323: nf_nat_mangle_tcp_packet" 53 + " error\n"); 54 + return -1; 55 + } 56 + 57 + /* Relocate data pointer */ 58 + th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4, 59 + sizeof(_tcph), &_tcph); 60 + if (th == NULL) 61 + return -1; 62 + *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 + 63 + th->doff * 4 + dataoff; 64 + } else { 65 + if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo, 66 + addroff, sizeof(buf), 67 + (char *) &buf, sizeof(buf))) { 68 + if (net_ratelimit()) 69 + printk("nf_nat_h323: nf_nat_mangle_udp_packet" 70 + " error\n"); 71 + return -1; 72 + } 73 + /* nf_nat_mangle_udp_packet uses skb_make_writable() to copy 74 + * or pull everything in a linear buffer, so we can safely 75 + * use the skb pointers now */ 76 + *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 + 77 + sizeof(struct udphdr); 78 + } 79 + 80 + return 0; 81 + } 82 + 83 + /****************************************************************************/ 84 + static int set_h225_addr(struct sk_buff **pskb, 85 + unsigned char **data, int dataoff, 86 + TransportAddress *taddr, 87 + union nf_conntrack_address *addr, __be16 port) 88 + { 89 + return set_addr(pskb, data, dataoff, taddr->ipAddress.ip, 90 + addr->ip, port); 91 + } 92 + 93 + /****************************************************************************/ 94 + static int set_h245_addr(struct sk_buff **pskb, 95 + unsigned char **data, int dataoff, 96 + H245_TransportAddress *taddr, 97 + union nf_conntrack_address *addr, __be16 port) 98 + { 99 + return set_addr(pskb, data, dataoff, 100 + taddr->unicastAddress.iPAddress.network, 101 + addr->ip, port); 102 + } 103 + 104 + /****************************************************************************/ 105 + static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct, 106 + enum ip_conntrack_info ctinfo, 107 + unsigned char **data, 108 + TransportAddress *taddr, int count) 109 + { 110 + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; 111 + int dir = CTINFO2DIR(ctinfo); 112 + int i; 113 + __be16 port; 114 + union nf_conntrack_address addr; 115 + 116 + for (i = 0; i < count; i++) { 117 + if (get_h225_addr(ct, *data, &taddr[i], &addr, &port)) { 118 + if (addr.ip == ct->tuplehash[dir].tuple.src.u3.ip && 119 + port == info->sig_port[dir]) { 120 + /* GW->GK */ 121 + 122 + /* Fix for Gnomemeeting */ 123 + if (i > 0 && 124 + get_h225_addr(ct, *data, &taddr[0], 125 + &addr, &port) && 126 + (ntohl(addr.ip) & 0xff000000) == 0x7f000000) 127 + i = 0; 128 + 129 + DEBUGP 130 + ("nf_nat_ras: set signal address " 131 + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", 132 + NIPQUAD(ip), port, 133 + NIPQUAD(ct->tuplehash[!dir].tuple.dst. 134 + ip), info->sig_port[!dir]); 135 + return set_h225_addr(pskb, data, 0, &taddr[i], 136 + &ct->tuplehash[!dir]. 137 + tuple.dst.u3, 138 + info->sig_port[!dir]); 139 + } else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip && 140 + port == info->sig_port[dir]) { 141 + /* GK->GW */ 142 + DEBUGP 143 + ("nf_nat_ras: set signal address " 144 + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", 145 + NIPQUAD(ip), port, 146 + NIPQUAD(ct->tuplehash[!dir].tuple.src. 147 + ip), info->sig_port[!dir]); 148 + return set_h225_addr(pskb, data, 0, &taddr[i], 149 + &ct->tuplehash[!dir]. 150 + tuple.src.u3, 151 + info->sig_port[!dir]); 152 + } 153 + } 154 + } 155 + 156 + return 0; 157 + } 158 + 159 + /****************************************************************************/ 160 + static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct, 161 + enum ip_conntrack_info ctinfo, 162 + unsigned char **data, 163 + TransportAddress *taddr, int count) 164 + { 165 + int dir = CTINFO2DIR(ctinfo); 166 + int i; 167 + __be16 port; 168 + union nf_conntrack_address addr; 169 + 170 + for (i = 0; i < count; i++) { 171 + if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) && 172 + addr.ip == ct->tuplehash[dir].tuple.src.u3.ip && 173 + port == ct->tuplehash[dir].tuple.src.u.udp.port) { 174 + DEBUGP("nf_nat_ras: set rasAddress " 175 + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", 176 + NIPQUAD(ip), ntohs(port), 177 + NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip), 178 + ntohs(ct->tuplehash[!dir].tuple.dst.u.udp. 179 + port)); 180 + return set_h225_addr(pskb, data, 0, &taddr[i], 181 + &ct->tuplehash[!dir].tuple.dst.u3, 182 + ct->tuplehash[!dir].tuple. 183 + dst.u.udp.port); 184 + } 185 + } 186 + 187 + return 0; 188 + } 189 + 190 + /****************************************************************************/ 191 + static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, 192 + enum ip_conntrack_info ctinfo, 193 + unsigned char **data, int dataoff, 194 + H245_TransportAddress *taddr, 195 + __be16 port, __be16 rtp_port, 196 + struct nf_conntrack_expect *rtp_exp, 197 + struct nf_conntrack_expect *rtcp_exp) 198 + { 199 + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; 200 + int dir = CTINFO2DIR(ctinfo); 201 + int i; 202 + u_int16_t nated_port; 203 + 204 + /* Set expectations for NAT */ 205 + rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port; 206 + rtp_exp->expectfn = nf_nat_follow_master; 207 + rtp_exp->dir = !dir; 208 + rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port; 209 + rtcp_exp->expectfn = nf_nat_follow_master; 210 + rtcp_exp->dir = !dir; 211 + 212 + /* Lookup existing expects */ 213 + for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) { 214 + if (info->rtp_port[i][dir] == rtp_port) { 215 + /* Expected */ 216 + 217 + /* Use allocated ports first. This will refresh 218 + * the expects */ 219 + rtp_exp->tuple.dst.u.udp.port = info->rtp_port[i][dir]; 220 + rtcp_exp->tuple.dst.u.udp.port = 221 + htons(ntohs(info->rtp_port[i][dir]) + 1); 222 + break; 223 + } else if (info->rtp_port[i][dir] == 0) { 224 + /* Not expected */ 225 + break; 226 + } 227 + } 228 + 229 + /* Run out of expectations */ 230 + if (i >= H323_RTP_CHANNEL_MAX) { 231 + if (net_ratelimit()) 232 + printk("nf_nat_h323: out of expectations\n"); 233 + return 0; 234 + } 235 + 236 + /* Try to get a pair of ports. */ 237 + for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port); 238 + nated_port != 0; nated_port += 2) { 239 + rtp_exp->tuple.dst.u.udp.port = htons(nated_port); 240 + if (nf_conntrack_expect_related(rtp_exp) == 0) { 241 + rtcp_exp->tuple.dst.u.udp.port = 242 + htons(nated_port + 1); 243 + if (nf_conntrack_expect_related(rtcp_exp) == 0) 244 + break; 245 + nf_conntrack_unexpect_related(rtp_exp); 246 + } 247 + } 248 + 249 + if (nated_port == 0) { /* No port available */ 250 + if (net_ratelimit()) 251 + printk("nf_nat_h323: out of RTP ports\n"); 252 + return 0; 253 + } 254 + 255 + /* Modify signal */ 256 + if (set_h245_addr(pskb, data, dataoff, taddr, 257 + &ct->tuplehash[!dir].tuple.dst.u3, 258 + htons((port & htons(1)) ? nated_port + 1 : 259 + nated_port)) == 0) { 260 + /* Save ports */ 261 + info->rtp_port[i][dir] = rtp_port; 262 + info->rtp_port[i][!dir] = htons(nated_port); 263 + } else { 264 + nf_conntrack_unexpect_related(rtp_exp); 265 + nf_conntrack_unexpect_related(rtcp_exp); 266 + return -1; 267 + } 268 + 269 + /* Success */ 270 + DEBUGP("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", 271 + NIPQUAD(rtp_exp->tuple.src.ip), 272 + ntohs(rtp_exp->tuple.src.u.udp.port), 273 + NIPQUAD(rtp_exp->tuple.dst.ip), 274 + ntohs(rtp_exp->tuple.dst.u.udp.port)); 275 + DEBUGP("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", 276 + NIPQUAD(rtcp_exp->tuple.src.ip), 277 + ntohs(rtcp_exp->tuple.src.u.udp.port), 278 + NIPQUAD(rtcp_exp->tuple.dst.ip), 279 + ntohs(rtcp_exp->tuple.dst.u.udp.port)); 280 + 281 + return 0; 282 + } 283 + 284 + /****************************************************************************/ 285 + static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct, 286 + enum ip_conntrack_info ctinfo, 287 + unsigned char **data, int dataoff, 288 + H245_TransportAddress *taddr, __be16 port, 289 + struct nf_conntrack_expect *exp) 290 + { 291 + int dir = CTINFO2DIR(ctinfo); 292 + u_int16_t nated_port = ntohs(port); 293 + 294 + /* Set expectations for NAT */ 295 + exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; 296 + exp->expectfn = nf_nat_follow_master; 297 + exp->dir = !dir; 298 + 299 + /* Try to get same port: if not, try to change it. */ 300 + for (; nated_port != 0; nated_port++) { 301 + exp->tuple.dst.u.tcp.port = htons(nated_port); 302 + if (nf_conntrack_expect_related(exp) == 0) 303 + break; 304 + } 305 + 306 + if (nated_port == 0) { /* No port available */ 307 + if (net_ratelimit()) 308 + printk("nf_nat_h323: out of TCP ports\n"); 309 + return 0; 310 + } 311 + 312 + /* Modify signal */ 313 + if (set_h245_addr(pskb, data, dataoff, taddr, 314 + &ct->tuplehash[!dir].tuple.dst.u3, 315 + htons(nated_port)) < 0) { 316 + nf_conntrack_unexpect_related(exp); 317 + return -1; 318 + } 319 + 320 + DEBUGP("nf_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", 321 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port), 322 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port)); 323 + 324 + return 0; 325 + } 326 + 327 + /****************************************************************************/ 328 + static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct, 329 + enum ip_conntrack_info ctinfo, 330 + unsigned char **data, int dataoff, 331 + TransportAddress *taddr, __be16 port, 332 + struct nf_conntrack_expect *exp) 333 + { 334 + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; 335 + int dir = CTINFO2DIR(ctinfo); 336 + u_int16_t nated_port = ntohs(port); 337 + 338 + /* Set expectations for NAT */ 339 + exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; 340 + exp->expectfn = nf_nat_follow_master; 341 + exp->dir = !dir; 342 + 343 + /* Check existing expects */ 344 + if (info->sig_port[dir] == port) 345 + nated_port = ntohs(info->sig_port[!dir]); 346 + 347 + /* Try to get same port: if not, try to change it. */ 348 + for (; nated_port != 0; nated_port++) { 349 + exp->tuple.dst.u.tcp.port = htons(nated_port); 350 + if (nf_conntrack_expect_related(exp) == 0) 351 + break; 352 + } 353 + 354 + if (nated_port == 0) { /* No port available */ 355 + if (net_ratelimit()) 356 + printk("nf_nat_q931: out of TCP ports\n"); 357 + return 0; 358 + } 359 + 360 + /* Modify signal */ 361 + if (set_h225_addr(pskb, data, dataoff, taddr, 362 + &ct->tuplehash[!dir].tuple.dst.u3, 363 + htons(nated_port)) == 0) { 364 + /* Save ports */ 365 + info->sig_port[dir] = port; 366 + info->sig_port[!dir] = htons(nated_port); 367 + } else { 368 + nf_conntrack_unexpect_related(exp); 369 + return -1; 370 + } 371 + 372 + DEBUGP("nf_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", 373 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port), 374 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port)); 375 + 376 + return 0; 377 + } 378 + 379 + /**************************************************************************** 380 + * This conntrack expect function replaces nf_conntrack_q931_expect() 381 + * which was set by nf_conntrack_h323.c. 382 + ****************************************************************************/ 383 + static void ip_nat_q931_expect(struct nf_conn *new, 384 + struct nf_conntrack_expect *this) 385 + { 386 + struct ip_nat_range range; 387 + 388 + if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */ 389 + nf_nat_follow_master(new, this); 390 + return; 391 + } 392 + 393 + /* This must be a fresh one. */ 394 + BUG_ON(new->status & IPS_NAT_DONE_MASK); 395 + 396 + /* Change src to where master sends to */ 397 + range.flags = IP_NAT_RANGE_MAP_IPS; 398 + range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip; 399 + 400 + /* hook doesn't matter, but it has to do source manip */ 401 + nf_nat_setup_info(new, &range, NF_IP_POST_ROUTING); 402 + 403 + /* For DST manip, map port here to where it's expected. */ 404 + range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); 405 + range.min = range.max = this->saved_proto; 406 + range.min_ip = range.max_ip = 407 + new->master->tuplehash[!this->dir].tuple.src.u3.ip; 408 + 409 + /* hook doesn't matter, but it has to do destination manip */ 410 + nf_nat_setup_info(new, &range, NF_IP_PRE_ROUTING); 411 + } 412 + 413 + /****************************************************************************/ 414 + static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct, 415 + enum ip_conntrack_info ctinfo, 416 + unsigned char **data, TransportAddress *taddr, int idx, 417 + __be16 port, struct nf_conntrack_expect *exp) 418 + { 419 + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; 420 + int dir = CTINFO2DIR(ctinfo); 421 + u_int16_t nated_port = ntohs(port); 422 + union nf_conntrack_address addr; 423 + 424 + /* Set expectations for NAT */ 425 + exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; 426 + exp->expectfn = ip_nat_q931_expect; 427 + exp->dir = !dir; 428 + 429 + /* Check existing expects */ 430 + if (info->sig_port[dir] == port) 431 + nated_port = ntohs(info->sig_port[!dir]); 432 + 433 + /* Try to get same port: if not, try to change it. */ 434 + for (; nated_port != 0; nated_port++) { 435 + exp->tuple.dst.u.tcp.port = htons(nated_port); 436 + if (nf_conntrack_expect_related(exp) == 0) 437 + break; 438 + } 439 + 440 + if (nated_port == 0) { /* No port available */ 441 + if (net_ratelimit()) 442 + printk("nf_nat_ras: out of TCP ports\n"); 443 + return 0; 444 + } 445 + 446 + /* Modify signal */ 447 + if (set_h225_addr(pskb, data, 0, &taddr[idx], 448 + &ct->tuplehash[!dir].tuple.dst.u3, 449 + htons(nated_port)) == 0) { 450 + /* Save ports */ 451 + info->sig_port[dir] = port; 452 + info->sig_port[!dir] = htons(nated_port); 453 + 454 + /* Fix for Gnomemeeting */ 455 + if (idx > 0 && 456 + get_h225_addr(ct, *data, &taddr[0], &addr, &port) && 457 + (ntohl(addr.ip) & 0xff000000) == 0x7f000000) { 458 + set_h225_addr_hook(pskb, data, 0, &taddr[0], 459 + &ct->tuplehash[!dir].tuple.dst.u3, 460 + info->sig_port[!dir]); 461 + } 462 + } else { 463 + nf_conntrack_unexpect_related(exp); 464 + return -1; 465 + } 466 + 467 + /* Success */ 468 + DEBUGP("nf_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", 469 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port), 470 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port)); 471 + 472 + return 0; 473 + } 474 + 475 + /****************************************************************************/ 476 + static void ip_nat_callforwarding_expect(struct nf_conn *new, 477 + struct nf_conntrack_expect *this) 478 + { 479 + struct nf_nat_range range; 480 + 481 + /* This must be a fresh one. */ 482 + BUG_ON(new->status & IPS_NAT_DONE_MASK); 483 + 484 + /* Change src to where master sends to */ 485 + range.flags = IP_NAT_RANGE_MAP_IPS; 486 + range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip; 487 + 488 + /* hook doesn't matter, but it has to do source manip */ 489 + nf_nat_setup_info(new, &range, NF_IP_POST_ROUTING); 490 + 491 + /* For DST manip, map port here to where it's expected. */ 492 + range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); 493 + range.min = range.max = this->saved_proto; 494 + range.min_ip = range.max_ip = this->saved_ip; 495 + 496 + /* hook doesn't matter, but it has to do destination manip */ 497 + nf_nat_setup_info(new, &range, NF_IP_PRE_ROUTING); 498 + } 499 + 500 + /****************************************************************************/ 501 + static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct, 502 + enum ip_conntrack_info ctinfo, 503 + unsigned char **data, int dataoff, 504 + TransportAddress *taddr, __be16 port, 505 + struct nf_conntrack_expect *exp) 506 + { 507 + int dir = CTINFO2DIR(ctinfo); 508 + u_int16_t nated_port; 509 + 510 + /* Set expectations for NAT */ 511 + exp->saved_ip = exp->tuple.dst.u3.ip; 512 + exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip; 513 + exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; 514 + exp->expectfn = ip_nat_callforwarding_expect; 515 + exp->dir = !dir; 516 + 517 + /* Try to get same port: if not, try to change it. */ 518 + for (nated_port = ntohs(port); nated_port != 0; nated_port++) { 519 + exp->tuple.dst.u.tcp.port = htons(nated_port); 520 + if (nf_conntrack_expect_related(exp) == 0) 521 + break; 522 + } 523 + 524 + if (nated_port == 0) { /* No port available */ 525 + if (net_ratelimit()) 526 + printk("nf_nat_q931: out of TCP ports\n"); 527 + return 0; 528 + } 529 + 530 + /* Modify signal */ 531 + if (!set_h225_addr(pskb, data, dataoff, taddr, 532 + &ct->tuplehash[!dir].tuple.dst.u3, 533 + htons(nated_port)) == 0) { 534 + nf_conntrack_unexpect_related(exp); 535 + return -1; 536 + } 537 + 538 + /* Success */ 539 + DEBUGP("nf_nat_q931: expect Call Forwarding " 540 + "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n", 541 + NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port), 542 + NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port)); 543 + 544 + return 0; 545 + } 546 + 547 + /****************************************************************************/ 548 + static int __init init(void) 549 + { 550 + BUG_ON(rcu_dereference(set_h245_addr_hook) != NULL); 551 + BUG_ON(rcu_dereference(set_h225_addr_hook) != NULL); 552 + BUG_ON(rcu_dereference(set_sig_addr_hook) != NULL); 553 + BUG_ON(rcu_dereference(set_ras_addr_hook) != NULL); 554 + BUG_ON(rcu_dereference(nat_rtp_rtcp_hook) != NULL); 555 + BUG_ON(rcu_dereference(nat_t120_hook) != NULL); 556 + BUG_ON(rcu_dereference(nat_h245_hook) != NULL); 557 + BUG_ON(rcu_dereference(nat_callforwarding_hook) != NULL); 558 + BUG_ON(rcu_dereference(nat_q931_hook) != NULL); 559 + 560 + rcu_assign_pointer(set_h245_addr_hook, set_h245_addr); 561 + rcu_assign_pointer(set_h225_addr_hook, set_h225_addr); 562 + rcu_assign_pointer(set_sig_addr_hook, set_sig_addr); 563 + rcu_assign_pointer(set_ras_addr_hook, set_ras_addr); 564 + rcu_assign_pointer(nat_rtp_rtcp_hook, nat_rtp_rtcp); 565 + rcu_assign_pointer(nat_t120_hook, nat_t120); 566 + rcu_assign_pointer(nat_h245_hook, nat_h245); 567 + rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding); 568 + rcu_assign_pointer(nat_q931_hook, nat_q931); 569 + 570 + DEBUGP("nf_nat_h323: init success\n"); 571 + return 0; 572 + } 573 + 574 + /****************************************************************************/ 575 + static void __exit fini(void) 576 + { 577 + rcu_assign_pointer(set_h245_addr_hook, NULL); 578 + rcu_assign_pointer(set_h225_addr_hook, NULL); 579 + rcu_assign_pointer(set_sig_addr_hook, NULL); 580 + rcu_assign_pointer(set_ras_addr_hook, NULL); 581 + rcu_assign_pointer(nat_rtp_rtcp_hook, NULL); 582 + rcu_assign_pointer(nat_t120_hook, NULL); 583 + rcu_assign_pointer(nat_h245_hook, NULL); 584 + rcu_assign_pointer(nat_callforwarding_hook, NULL); 585 + rcu_assign_pointer(nat_q931_hook, NULL); 586 + synchronize_rcu(); 587 + } 588 + 589 + /****************************************************************************/ 590 + module_init(init); 591 + module_exit(fini); 592 + 593 + MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>"); 594 + MODULE_DESCRIPTION("H.323 NAT helper"); 595 + MODULE_LICENSE("GPL"); 596 + MODULE_ALIAS("ip_nat_h323");
+19
net/netfilter/Kconfig
··· 160 160 161 161 To compile it as a module, choose M here. If unsure, say N. 162 162 163 + config NF_CONNTRACK_H323 164 + tristate "H.323 protocol support (EXPERIMENTAL)" 165 + depends on EXPERIMENTAL && NF_CONNTRACK 166 + help 167 + H.323 is a VoIP signalling protocol from ITU-T. As one of the most 168 + important VoIP protocols, it is widely used by voice hardware and 169 + software including voice gateways, IP phones, Netmeeting, OpenPhone, 170 + Gnomemeeting, etc. 171 + 172 + With this module you can support H.323 on a connection tracking/NAT 173 + firewall. 174 + 175 + This module supports RAS, Fast Start, H.245 Tunnelling, Call 176 + Forwarding, RTP/RTCP and T.120 based audio, video, fax, chat, 177 + whiteboard, file transfer, etc. For more information, please 178 + visit http://nath323.sourceforge.net/. 179 + 180 + To compile it as a module, choose M here. If unsure, say N. 181 + 163 182 config NF_CT_NETLINK 164 183 tristate 'Connection tracking netlink interface (EXPERIMENTAL)' 165 184 depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK
+3
net/netfilter/Makefile
··· 20 20 obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o 21 21 22 22 # connection tracking helpers 23 + nf_conntrack_h323-objs := nf_conntrack_h323_main.o nf_conntrack_h323_asn1.o 24 + 23 25 obj-$(CONFIG_NF_CONNTRACK_AMANDA) += nf_conntrack_amanda.o 24 26 obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o 27 + obj-$(CONFIG_NF_CONNTRACK_H323) += nf_conntrack_h323.o 25 28 26 29 # generic X tables 27 30 obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
+1856
net/netfilter/nf_conntrack_h323_main.c
··· 1 + /* 2 + * H.323 connection tracking helper 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 connection tracking module by 9 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 10 + * 11 + * For more information, please see http://nath323.sourceforge.net/ 12 + */ 13 + 14 + #include <linux/module.h> 15 + #include <linux/moduleparam.h> 16 + #include <linux/ctype.h> 17 + #include <linux/inet.h> 18 + #include <linux/in.h> 19 + #include <linux/ip.h> 20 + #include <linux/udp.h> 21 + #include <linux/tcp.h> 22 + #include <linux/skbuff.h> 23 + #include <net/route.h> 24 + #include <net/ip6_route.h> 25 + 26 + #include <net/netfilter/nf_conntrack.h> 27 + #include <net/netfilter/nf_conntrack_core.h> 28 + #include <net/netfilter/nf_conntrack_tuple.h> 29 + #include <net/netfilter/nf_conntrack_expect.h> 30 + #include <net/netfilter/nf_conntrack_ecache.h> 31 + #include <net/netfilter/nf_conntrack_helper.h> 32 + #include <linux/netfilter/nf_conntrack_h323.h> 33 + 34 + #if 0 35 + #define DEBUGP printk 36 + #else 37 + #define DEBUGP(format, args...) 38 + #endif 39 + 40 + /* Parameters */ 41 + static unsigned int default_rrq_ttl __read_mostly = 300; 42 + module_param(default_rrq_ttl, uint, 0600); 43 + MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ"); 44 + 45 + static int gkrouted_only __read_mostly = 1; 46 + module_param(gkrouted_only, int, 0600); 47 + MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper"); 48 + 49 + static int callforward_filter __read_mostly = 1; 50 + module_param(callforward_filter, bool, 0600); 51 + MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations " 52 + "if both endpoints are on different sides " 53 + "(determined by routing information)"); 54 + 55 + /* Hooks for NAT */ 56 + int (*set_h245_addr_hook) (struct sk_buff **pskb, 57 + unsigned char **data, int dataoff, 58 + H245_TransportAddress *taddr, 59 + union nf_conntrack_address *addr, __be16 port) 60 + __read_mostly; 61 + int (*set_h225_addr_hook) (struct sk_buff **pskb, 62 + unsigned char **data, int dataoff, 63 + TransportAddress *taddr, 64 + union nf_conntrack_address *addr, __be16 port) 65 + __read_mostly; 66 + int (*set_sig_addr_hook) (struct sk_buff **pskb, 67 + struct nf_conn *ct, 68 + enum ip_conntrack_info ctinfo, 69 + unsigned char **data, 70 + TransportAddress *taddr, int count) __read_mostly; 71 + int (*set_ras_addr_hook) (struct sk_buff **pskb, 72 + struct nf_conn *ct, 73 + enum ip_conntrack_info ctinfo, 74 + unsigned char **data, 75 + TransportAddress *taddr, int count) __read_mostly; 76 + int (*nat_rtp_rtcp_hook) (struct sk_buff **pskb, 77 + struct nf_conn *ct, 78 + enum ip_conntrack_info ctinfo, 79 + unsigned char **data, int dataoff, 80 + H245_TransportAddress *taddr, 81 + __be16 port, __be16 rtp_port, 82 + struct nf_conntrack_expect *rtp_exp, 83 + struct nf_conntrack_expect *rtcp_exp) __read_mostly; 84 + int (*nat_t120_hook) (struct sk_buff **pskb, 85 + struct nf_conn *ct, 86 + enum ip_conntrack_info ctinfo, 87 + unsigned char **data, int dataoff, 88 + H245_TransportAddress *taddr, __be16 port, 89 + struct nf_conntrack_expect *exp) __read_mostly; 90 + int (*nat_h245_hook) (struct sk_buff **pskb, 91 + struct nf_conn *ct, 92 + enum ip_conntrack_info ctinfo, 93 + unsigned char **data, int dataoff, 94 + TransportAddress *taddr, __be16 port, 95 + struct nf_conntrack_expect *exp) __read_mostly; 96 + int (*nat_callforwarding_hook) (struct sk_buff **pskb, 97 + struct nf_conn *ct, 98 + enum ip_conntrack_info ctinfo, 99 + unsigned char **data, int dataoff, 100 + TransportAddress *taddr, __be16 port, 101 + struct nf_conntrack_expect *exp) __read_mostly; 102 + int (*nat_q931_hook) (struct sk_buff **pskb, 103 + struct nf_conn *ct, 104 + enum ip_conntrack_info ctinfo, 105 + unsigned char **data, TransportAddress *taddr, int idx, 106 + __be16 port, struct nf_conntrack_expect *exp) 107 + __read_mostly; 108 + 109 + static DEFINE_SPINLOCK(nf_h323_lock); 110 + static char *h323_buffer; 111 + 112 + static struct nf_conntrack_helper nf_conntrack_helper_h245; 113 + static struct nf_conntrack_helper nf_conntrack_helper_q931[]; 114 + static struct nf_conntrack_helper nf_conntrack_helper_ras[]; 115 + 116 + /****************************************************************************/ 117 + static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff, 118 + struct nf_conn *ct, enum ip_conntrack_info ctinfo, 119 + unsigned char **data, int *datalen, int *dataoff) 120 + { 121 + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; 122 + int dir = CTINFO2DIR(ctinfo); 123 + struct tcphdr _tcph, *th; 124 + int tcpdatalen; 125 + int tcpdataoff; 126 + unsigned char *tpkt; 127 + int tpktlen; 128 + int tpktoff; 129 + 130 + /* Get TCP header */ 131 + th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph); 132 + if (th == NULL) 133 + return 0; 134 + 135 + /* Get TCP data offset */ 136 + tcpdataoff = protoff + th->doff * 4; 137 + 138 + /* Get TCP data length */ 139 + tcpdatalen = (*pskb)->len - tcpdataoff; 140 + if (tcpdatalen <= 0) /* No TCP data */ 141 + goto clear_out; 142 + 143 + if (*data == NULL) { /* first TPKT */ 144 + /* Get first TPKT pointer */ 145 + tpkt = skb_header_pointer(*pskb, tcpdataoff, tcpdatalen, 146 + h323_buffer); 147 + BUG_ON(tpkt == NULL); 148 + 149 + /* Validate TPKT identifier */ 150 + if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) { 151 + /* Netmeeting sends TPKT header and data separately */ 152 + if (info->tpkt_len[dir] > 0) { 153 + DEBUGP("nf_ct_h323: previous packet " 154 + "indicated separate TPKT data of %hu " 155 + "bytes\n", info->tpkt_len[dir]); 156 + if (info->tpkt_len[dir] <= tcpdatalen) { 157 + /* Yes, there was a TPKT header 158 + * received */ 159 + *data = tpkt; 160 + *datalen = info->tpkt_len[dir]; 161 + *dataoff = 0; 162 + goto out; 163 + } 164 + 165 + /* Fragmented TPKT */ 166 + if (net_ratelimit()) 167 + printk("nf_ct_h323: " 168 + "fragmented TPKT\n"); 169 + goto clear_out; 170 + } 171 + 172 + /* It is not even a TPKT */ 173 + return 0; 174 + } 175 + tpktoff = 0; 176 + } else { /* Next TPKT */ 177 + tpktoff = *dataoff + *datalen; 178 + tcpdatalen -= tpktoff; 179 + if (tcpdatalen <= 4) /* No more TPKT */ 180 + goto clear_out; 181 + tpkt = *data + *datalen; 182 + 183 + /* Validate TPKT identifier */ 184 + if (tpkt[0] != 0x03 || tpkt[1] != 0) 185 + goto clear_out; 186 + } 187 + 188 + /* Validate TPKT length */ 189 + tpktlen = tpkt[2] * 256 + tpkt[3]; 190 + if (tpktlen < 4) 191 + goto clear_out; 192 + if (tpktlen > tcpdatalen) { 193 + if (tcpdatalen == 4) { /* Separate TPKT header */ 194 + /* Netmeeting sends TPKT header and data separately */ 195 + DEBUGP("nf_ct_h323: separate TPKT header indicates " 196 + "there will be TPKT data of %hu bytes\n", 197 + tpktlen - 4); 198 + info->tpkt_len[dir] = tpktlen - 4; 199 + return 0; 200 + } 201 + 202 + if (net_ratelimit()) 203 + printk("nf_ct_h323: incomplete TPKT (fragmented?)\n"); 204 + goto clear_out; 205 + } 206 + 207 + /* This is the encapsulated data */ 208 + *data = tpkt + 4; 209 + *datalen = tpktlen - 4; 210 + *dataoff = tpktoff + 4; 211 + 212 + out: 213 + /* Clear TPKT length */ 214 + info->tpkt_len[dir] = 0; 215 + return 1; 216 + 217 + clear_out: 218 + info->tpkt_len[dir] = 0; 219 + return 0; 220 + } 221 + 222 + /****************************************************************************/ 223 + static int get_h245_addr(struct nf_conn *ct, unsigned char *data, 224 + H245_TransportAddress *taddr, 225 + union nf_conntrack_address *addr, __be16 *port) 226 + { 227 + unsigned char *p; 228 + int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; 229 + int len; 230 + 231 + if (taddr->choice != eH245_TransportAddress_unicastAddress) 232 + return 0; 233 + 234 + switch (taddr->unicastAddress.choice) { 235 + case eUnicastAddress_iPAddress: 236 + if (family != AF_INET) 237 + return 0; 238 + p = data + taddr->unicastAddress.iPAddress.network; 239 + len = 4; 240 + break; 241 + case eUnicastAddress_iP6Address: 242 + if (family != AF_INET6) 243 + return 0; 244 + p = data + taddr->unicastAddress.iP6Address.network; 245 + len = 16; 246 + break; 247 + default: 248 + return 0; 249 + } 250 + 251 + memcpy(addr, p, len); 252 + memset((void *)addr + len, 0, sizeof(*addr) - len); 253 + memcpy(port, p + len, sizeof(__be16)); 254 + 255 + return 1; 256 + } 257 + 258 + /****************************************************************************/ 259 + static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct, 260 + enum ip_conntrack_info ctinfo, 261 + unsigned char **data, int dataoff, 262 + H245_TransportAddress *taddr) 263 + { 264 + int dir = CTINFO2DIR(ctinfo); 265 + int ret = 0; 266 + __be16 port; 267 + __be16 rtp_port, rtcp_port; 268 + union nf_conntrack_address addr; 269 + struct nf_conntrack_expect *rtp_exp; 270 + struct nf_conntrack_expect *rtcp_exp; 271 + typeof(nat_rtp_rtcp_hook) nat_rtp_rtcp; 272 + 273 + /* Read RTP or RTCP address */ 274 + if (!get_h245_addr(ct, *data, taddr, &addr, &port) || 275 + memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) || 276 + port == 0) 277 + return 0; 278 + 279 + /* RTP port is even */ 280 + port &= htons(~1); 281 + rtp_port = port; 282 + rtcp_port = htons(ntohs(port) + 1); 283 + 284 + /* Create expect for RTP */ 285 + if ((rtp_exp = nf_conntrack_expect_alloc(ct)) == NULL) 286 + return -1; 287 + nf_conntrack_expect_init(rtp_exp, ct->tuplehash[!dir].tuple.src.l3num, 288 + &ct->tuplehash[!dir].tuple.src.u3, 289 + &ct->tuplehash[!dir].tuple.dst.u3, 290 + IPPROTO_UDP, NULL, &rtp_port); 291 + 292 + /* Create expect for RTCP */ 293 + if ((rtcp_exp = nf_conntrack_expect_alloc(ct)) == NULL) { 294 + nf_conntrack_expect_put(rtp_exp); 295 + return -1; 296 + } 297 + nf_conntrack_expect_init(rtcp_exp, ct->tuplehash[!dir].tuple.src.l3num, 298 + &ct->tuplehash[!dir].tuple.src.u3, 299 + &ct->tuplehash[!dir].tuple.dst.u3, 300 + IPPROTO_UDP, NULL, &rtcp_port); 301 + 302 + if (memcmp(&ct->tuplehash[dir].tuple.src.u3, 303 + &ct->tuplehash[!dir].tuple.dst.u3, 304 + sizeof(ct->tuplehash[dir].tuple.src.u3)) && 305 + (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook)) && 306 + ct->status & IPS_NAT_MASK) { 307 + /* NAT needed */ 308 + ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, 309 + taddr, port, rtp_port, rtp_exp, rtcp_exp); 310 + } else { /* Conntrack only */ 311 + if (nf_conntrack_expect_related(rtp_exp) == 0) { 312 + if (nf_conntrack_expect_related(rtcp_exp) == 0) { 313 + DEBUGP("nf_ct_h323: expect RTP "); 314 + NF_CT_DUMP_TUPLE(&rtp_exp->tuple); 315 + DEBUGP("nf_ct_h323: expect RTCP "); 316 + NF_CT_DUMP_TUPLE(&rtcp_exp->tuple); 317 + } else { 318 + nf_conntrack_unexpect_related(rtp_exp); 319 + ret = -1; 320 + } 321 + } else 322 + ret = -1; 323 + } 324 + 325 + nf_conntrack_expect_put(rtp_exp); 326 + nf_conntrack_expect_put(rtcp_exp); 327 + 328 + return ret; 329 + } 330 + 331 + /****************************************************************************/ 332 + static int expect_t120(struct sk_buff **pskb, 333 + struct nf_conn *ct, 334 + enum ip_conntrack_info ctinfo, 335 + unsigned char **data, int dataoff, 336 + H245_TransportAddress *taddr) 337 + { 338 + int dir = CTINFO2DIR(ctinfo); 339 + int ret = 0; 340 + __be16 port; 341 + union nf_conntrack_address addr; 342 + struct nf_conntrack_expect *exp; 343 + typeof(nat_t120_hook) nat_t120; 344 + 345 + /* Read T.120 address */ 346 + if (!get_h245_addr(ct, *data, taddr, &addr, &port) || 347 + memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) || 348 + port == 0) 349 + return 0; 350 + 351 + /* Create expect for T.120 connections */ 352 + if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) 353 + return -1; 354 + nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, 355 + &ct->tuplehash[!dir].tuple.src.u3, 356 + &ct->tuplehash[!dir].tuple.dst.u3, 357 + IPPROTO_TCP, NULL, &port); 358 + exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple channels */ 359 + 360 + if (memcmp(&ct->tuplehash[dir].tuple.src.u3, 361 + &ct->tuplehash[!dir].tuple.dst.u3, 362 + sizeof(ct->tuplehash[dir].tuple.src.u3)) && 363 + (nat_t120 = rcu_dereference(nat_t120_hook)) && 364 + ct->status & IPS_NAT_MASK) { 365 + /* NAT needed */ 366 + ret = nat_t120(pskb, ct, ctinfo, data, dataoff, taddr, 367 + port, exp); 368 + } else { /* Conntrack only */ 369 + if (nf_conntrack_expect_related(exp) == 0) { 370 + DEBUGP("nf_ct_h323: expect T.120 "); 371 + NF_CT_DUMP_TUPLE(&exp->tuple); 372 + } else 373 + ret = -1; 374 + } 375 + 376 + nf_conntrack_expect_put(exp); 377 + 378 + return ret; 379 + } 380 + 381 + /****************************************************************************/ 382 + static int process_h245_channel(struct sk_buff **pskb, 383 + struct nf_conn *ct, 384 + enum ip_conntrack_info ctinfo, 385 + unsigned char **data, int dataoff, 386 + H2250LogicalChannelParameters *channel) 387 + { 388 + int ret; 389 + 390 + if (channel->options & eH2250LogicalChannelParameters_mediaChannel) { 391 + /* RTP */ 392 + ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, 393 + &channel->mediaChannel); 394 + if (ret < 0) 395 + return -1; 396 + } 397 + 398 + if (channel-> 399 + options & eH2250LogicalChannelParameters_mediaControlChannel) { 400 + /* RTCP */ 401 + ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, 402 + &channel->mediaControlChannel); 403 + if (ret < 0) 404 + return -1; 405 + } 406 + 407 + return 0; 408 + } 409 + 410 + /****************************************************************************/ 411 + static int process_olc(struct sk_buff **pskb, struct nf_conn *ct, 412 + enum ip_conntrack_info ctinfo, 413 + unsigned char **data, int dataoff, 414 + OpenLogicalChannel *olc) 415 + { 416 + int ret; 417 + 418 + DEBUGP("nf_ct_h323: OpenLogicalChannel\n"); 419 + 420 + if (olc->forwardLogicalChannelParameters.multiplexParameters.choice == 421 + eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters) 422 + { 423 + ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff, 424 + &olc-> 425 + forwardLogicalChannelParameters. 426 + multiplexParameters. 427 + h2250LogicalChannelParameters); 428 + if (ret < 0) 429 + return -1; 430 + } 431 + 432 + if ((olc->options & 433 + eOpenLogicalChannel_reverseLogicalChannelParameters) && 434 + (olc->reverseLogicalChannelParameters.options & 435 + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters) 436 + && (olc->reverseLogicalChannelParameters.multiplexParameters. 437 + choice == 438 + eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) 439 + { 440 + ret = 441 + process_h245_channel(pskb, ct, ctinfo, data, dataoff, 442 + &olc-> 443 + reverseLogicalChannelParameters. 444 + multiplexParameters. 445 + h2250LogicalChannelParameters); 446 + if (ret < 0) 447 + return -1; 448 + } 449 + 450 + if ((olc->options & eOpenLogicalChannel_separateStack) && 451 + olc->forwardLogicalChannelParameters.dataType.choice == 452 + eDataType_data && 453 + olc->forwardLogicalChannelParameters.dataType.data.application. 454 + choice == eDataApplicationCapability_application_t120 && 455 + olc->forwardLogicalChannelParameters.dataType.data.application. 456 + t120.choice == eDataProtocolCapability_separateLANStack && 457 + olc->separateStack.networkAddress.choice == 458 + eNetworkAccessParameters_networkAddress_localAreaAddress) { 459 + ret = expect_t120(pskb, ct, ctinfo, data, dataoff, 460 + &olc->separateStack.networkAddress. 461 + localAreaAddress); 462 + if (ret < 0) 463 + return -1; 464 + } 465 + 466 + return 0; 467 + } 468 + 469 + /****************************************************************************/ 470 + static int process_olca(struct sk_buff **pskb, struct nf_conn *ct, 471 + enum ip_conntrack_info ctinfo, 472 + unsigned char **data, int dataoff, 473 + OpenLogicalChannelAck *olca) 474 + { 475 + H2250LogicalChannelAckParameters *ack; 476 + int ret; 477 + 478 + DEBUGP("nf_ct_h323: OpenLogicalChannelAck\n"); 479 + 480 + if ((olca->options & 481 + eOpenLogicalChannelAck_reverseLogicalChannelParameters) && 482 + (olca->reverseLogicalChannelParameters.options & 483 + eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters) 484 + && (olca->reverseLogicalChannelParameters.multiplexParameters. 485 + choice == 486 + eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) 487 + { 488 + ret = process_h245_channel(pskb, ct, ctinfo, data, dataoff, 489 + &olca-> 490 + reverseLogicalChannelParameters. 491 + multiplexParameters. 492 + h2250LogicalChannelParameters); 493 + if (ret < 0) 494 + return -1; 495 + } 496 + 497 + if ((olca->options & 498 + eOpenLogicalChannelAck_forwardMultiplexAckParameters) && 499 + (olca->forwardMultiplexAckParameters.choice == 500 + eOpenLogicalChannelAck_forwardMultiplexAckParameters_h2250LogicalChannelAckParameters)) 501 + { 502 + ack = &olca->forwardMultiplexAckParameters. 503 + h2250LogicalChannelAckParameters; 504 + if (ack->options & 505 + eH2250LogicalChannelAckParameters_mediaChannel) { 506 + /* RTP */ 507 + ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, 508 + &ack->mediaChannel); 509 + if (ret < 0) 510 + return -1; 511 + } 512 + 513 + if (ack->options & 514 + eH2250LogicalChannelAckParameters_mediaControlChannel) { 515 + /* RTCP */ 516 + ret = expect_rtp_rtcp(pskb, ct, ctinfo, data, dataoff, 517 + &ack->mediaControlChannel); 518 + if (ret < 0) 519 + return -1; 520 + } 521 + } 522 + 523 + return 0; 524 + } 525 + 526 + /****************************************************************************/ 527 + static int process_h245(struct sk_buff **pskb, struct nf_conn *ct, 528 + enum ip_conntrack_info ctinfo, 529 + unsigned char **data, int dataoff, 530 + MultimediaSystemControlMessage *mscm) 531 + { 532 + switch (mscm->choice) { 533 + case eMultimediaSystemControlMessage_request: 534 + if (mscm->request.choice == 535 + eRequestMessage_openLogicalChannel) { 536 + return process_olc(pskb, ct, ctinfo, data, dataoff, 537 + &mscm->request.openLogicalChannel); 538 + } 539 + DEBUGP("nf_ct_h323: H.245 Request %d\n", 540 + mscm->request.choice); 541 + break; 542 + case eMultimediaSystemControlMessage_response: 543 + if (mscm->response.choice == 544 + eResponseMessage_openLogicalChannelAck) { 545 + return process_olca(pskb, ct, ctinfo, data, dataoff, 546 + &mscm->response. 547 + openLogicalChannelAck); 548 + } 549 + DEBUGP("nf_ct_h323: H.245 Response %d\n", 550 + mscm->response.choice); 551 + break; 552 + default: 553 + DEBUGP("nf_ct_h323: H.245 signal %d\n", mscm->choice); 554 + break; 555 + } 556 + 557 + return 0; 558 + } 559 + 560 + /****************************************************************************/ 561 + static int h245_help(struct sk_buff **pskb, unsigned int protoff, 562 + struct nf_conn *ct, enum ip_conntrack_info ctinfo) 563 + { 564 + static MultimediaSystemControlMessage mscm; 565 + unsigned char *data = NULL; 566 + int datalen; 567 + int dataoff; 568 + int ret; 569 + 570 + /* Until there's been traffic both ways, don't look in packets. */ 571 + if (ctinfo != IP_CT_ESTABLISHED && 572 + ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { 573 + return NF_ACCEPT; 574 + } 575 + DEBUGP("nf_ct_h245: skblen = %u\n", (*pskb)->len); 576 + 577 + spin_lock_bh(&nf_h323_lock); 578 + 579 + /* Process each TPKT */ 580 + while (get_tpkt_data(pskb, protoff, ct, ctinfo, 581 + &data, &datalen, &dataoff)) { 582 + DEBUGP("nf_ct_h245: TPKT len=%d ", datalen); 583 + NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); 584 + 585 + /* Decode H.245 signal */ 586 + ret = DecodeMultimediaSystemControlMessage(data, datalen, 587 + &mscm); 588 + if (ret < 0) { 589 + if (net_ratelimit()) 590 + printk("nf_ct_h245: decoding error: %s\n", 591 + ret == H323_ERROR_BOUND ? 592 + "out of bound" : "out of range"); 593 + /* We don't drop when decoding error */ 594 + break; 595 + } 596 + 597 + /* Process H.245 signal */ 598 + if (process_h245(pskb, ct, ctinfo, &data, dataoff, &mscm) < 0) 599 + goto drop; 600 + } 601 + 602 + spin_unlock_bh(&nf_h323_lock); 603 + return NF_ACCEPT; 604 + 605 + drop: 606 + spin_unlock_bh(&nf_h323_lock); 607 + if (net_ratelimit()) 608 + printk("nf_ct_h245: packet dropped\n"); 609 + return NF_DROP; 610 + } 611 + 612 + /****************************************************************************/ 613 + static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = { 614 + .name = "H.245", 615 + .me = THIS_MODULE, 616 + .max_expected = H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */, 617 + .timeout = 240, 618 + .tuple.dst.protonum = IPPROTO_UDP, 619 + .mask.src.u.udp.port = __constant_htons(0xFFFF), 620 + .mask.dst.protonum = 0xFF, 621 + .help = h245_help 622 + }; 623 + 624 + /****************************************************************************/ 625 + int get_h225_addr(struct nf_conn *ct, unsigned char *data, 626 + TransportAddress *taddr, 627 + union nf_conntrack_address *addr, __be16 *port) 628 + { 629 + unsigned char *p; 630 + int family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; 631 + int len; 632 + 633 + switch (taddr->choice) { 634 + case eTransportAddress_ipAddress: 635 + if (family != AF_INET) 636 + return 0; 637 + p = data + taddr->ipAddress.ip; 638 + len = 4; 639 + break; 640 + case eTransportAddress_ip6Address: 641 + if (family != AF_INET6) 642 + return 0; 643 + p = data + taddr->ip6Address.ip6; 644 + len = 16; 645 + break; 646 + default: 647 + return 0; 648 + } 649 + 650 + memcpy(addr, p, len); 651 + memset((void *)addr + len, 0, sizeof(*addr) - len); 652 + memcpy(port, p + len, sizeof(__be16)); 653 + 654 + return 1; 655 + } 656 + 657 + /****************************************************************************/ 658 + static int expect_h245(struct sk_buff **pskb, struct nf_conn *ct, 659 + enum ip_conntrack_info ctinfo, 660 + unsigned char **data, int dataoff, 661 + TransportAddress *taddr) 662 + { 663 + int dir = CTINFO2DIR(ctinfo); 664 + int ret = 0; 665 + __be16 port; 666 + union nf_conntrack_address addr; 667 + struct nf_conntrack_expect *exp; 668 + typeof(nat_h245_hook) nat_h245; 669 + 670 + /* Read h245Address */ 671 + if (!get_h225_addr(ct, *data, taddr, &addr, &port) || 672 + memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) || 673 + port == 0) 674 + return 0; 675 + 676 + /* Create expect for h245 connection */ 677 + if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) 678 + return -1; 679 + nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, 680 + &ct->tuplehash[!dir].tuple.src.u3, 681 + &ct->tuplehash[!dir].tuple.dst.u3, 682 + IPPROTO_TCP, NULL, &port); 683 + exp->helper = &nf_conntrack_helper_h245; 684 + 685 + if (memcmp(&ct->tuplehash[dir].tuple.src.u3, 686 + &ct->tuplehash[!dir].tuple.dst.u3, 687 + sizeof(ct->tuplehash[dir].tuple.src.u3)) && 688 + (nat_h245 = rcu_dereference(nat_h245_hook)) && 689 + ct->status & IPS_NAT_MASK) { 690 + /* NAT needed */ 691 + ret = nat_h245(pskb, ct, ctinfo, data, dataoff, taddr, 692 + port, exp); 693 + } else { /* Conntrack only */ 694 + if (nf_conntrack_expect_related(exp) == 0) { 695 + DEBUGP("nf_ct_q931: expect H.245 "); 696 + NF_CT_DUMP_TUPLE(&exp->tuple); 697 + } else 698 + ret = -1; 699 + } 700 + 701 + nf_conntrack_expect_put(exp); 702 + 703 + return ret; 704 + } 705 + 706 + /* If the calling party is on the same side of the forward-to party, 707 + * we don't need to track the second call */ 708 + static int callforward_do_filter(union nf_conntrack_address *src, 709 + union nf_conntrack_address *dst, 710 + int family) 711 + { 712 + struct flowi fl1, fl2; 713 + int ret = 0; 714 + 715 + memset(&fl1, 0, sizeof(fl1)); 716 + memset(&fl2, 0, sizeof(fl2)); 717 + 718 + switch (family) { 719 + case AF_INET: { 720 + struct rtable *rt1, *rt2; 721 + 722 + fl1.fl4_dst = src->ip; 723 + fl2.fl4_dst = dst->ip; 724 + if (ip_route_output_key(&rt1, &fl1) == 0) { 725 + if (ip_route_output_key(&rt2, &fl2) == 0) { 726 + if (rt1->rt_gateway == rt2->rt_gateway && 727 + rt1->u.dst.dev == rt2->u.dst.dev) 728 + ret = 1; 729 + dst_release(&rt2->u.dst); 730 + } 731 + dst_release(&rt1->u.dst); 732 + } 733 + break; 734 + } 735 + #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 736 + case AF_INET6: { 737 + struct rt6_info *rt1, *rt2; 738 + 739 + memcpy(&fl1.fl6_dst, src, sizeof(fl1.fl6_dst)); 740 + memcpy(&fl2.fl6_dst, dst, sizeof(fl2.fl6_dst)); 741 + rt1 = (struct rt6_info *)ip6_route_output(NULL, &fl1); 742 + if (rt1) { 743 + rt2 = (struct rt6_info *)ip6_route_output(NULL, &fl2); 744 + if (rt2) { 745 + if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway, 746 + sizeof(rt1->rt6i_gateway)) && 747 + rt1->u.dst.dev == rt2->u.dst.dev) 748 + ret = 1; 749 + dst_release(&rt2->u.dst); 750 + } 751 + dst_release(&rt1->u.dst); 752 + } 753 + break; 754 + } 755 + #endif 756 + } 757 + return ret; 758 + 759 + } 760 + 761 + /****************************************************************************/ 762 + static int expect_callforwarding(struct sk_buff **pskb, 763 + struct nf_conn *ct, 764 + enum ip_conntrack_info ctinfo, 765 + unsigned char **data, int dataoff, 766 + TransportAddress *taddr) 767 + { 768 + int dir = CTINFO2DIR(ctinfo); 769 + int ret = 0; 770 + __be16 port; 771 + union nf_conntrack_address addr; 772 + struct nf_conntrack_expect *exp; 773 + typeof(nat_callforwarding_hook) nat_callforwarding; 774 + 775 + /* Read alternativeAddress */ 776 + if (!get_h225_addr(ct, *data, taddr, &addr, &port) || port == 0) 777 + return 0; 778 + 779 + /* If the calling party is on the same side of the forward-to party, 780 + * we don't need to track the second call */ 781 + if (callforward_filter && 782 + callforward_do_filter(&addr, &ct->tuplehash[!dir].tuple.src.u3, 783 + ct->tuplehash[!dir].tuple.src.l3num)) { 784 + DEBUGP("nf_ct_q931: Call Forwarding not tracked\n"); 785 + return 0; 786 + } 787 + 788 + /* Create expect for the second call leg */ 789 + if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) 790 + return -1; 791 + nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, 792 + &ct->tuplehash[!dir].tuple.src.u3, &addr, 793 + IPPROTO_TCP, NULL, &port); 794 + exp->helper = nf_conntrack_helper_q931; 795 + 796 + if (memcmp(&ct->tuplehash[dir].tuple.src.u3, 797 + &ct->tuplehash[!dir].tuple.dst.u3, 798 + sizeof(ct->tuplehash[dir].tuple.src.u3)) && 799 + (nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) && 800 + ct->status & IPS_NAT_MASK) { 801 + /* Need NAT */ 802 + ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff, 803 + taddr, port, exp); 804 + } else { /* Conntrack only */ 805 + if (nf_conntrack_expect_related(exp) == 0) { 806 + DEBUGP("nf_ct_q931: expect Call Forwarding "); 807 + NF_CT_DUMP_TUPLE(&exp->tuple); 808 + } else 809 + ret = -1; 810 + } 811 + 812 + nf_conntrack_expect_put(exp); 813 + 814 + return ret; 815 + } 816 + 817 + /****************************************************************************/ 818 + static int process_setup(struct sk_buff **pskb, struct nf_conn *ct, 819 + enum ip_conntrack_info ctinfo, 820 + unsigned char **data, int dataoff, 821 + Setup_UUIE *setup) 822 + { 823 + int dir = CTINFO2DIR(ctinfo); 824 + int ret; 825 + int i; 826 + __be16 port; 827 + union nf_conntrack_address addr; 828 + typeof(set_h225_addr_hook) set_h225_addr; 829 + 830 + DEBUGP("nf_ct_q931: Setup\n"); 831 + 832 + if (setup->options & eSetup_UUIE_h245Address) { 833 + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, 834 + &setup->h245Address); 835 + if (ret < 0) 836 + return -1; 837 + } 838 + 839 + set_h225_addr = rcu_dereference(set_h225_addr_hook); 840 + if ((setup->options & eSetup_UUIE_destCallSignalAddress) && 841 + (set_h225_addr) && ct->status && IPS_NAT_MASK && 842 + get_h225_addr(ct, *data, &setup->destCallSignalAddress, 843 + &addr, &port) && 844 + memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) { 845 + DEBUGP("nf_ct_q931: set destCallSignalAddress " 846 + NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n", 847 + NIP6(*(struct in6_addr *)&addr), ntohs(port), 848 + NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3), 849 + ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port)); 850 + ret = set_h225_addr(pskb, data, dataoff, 851 + &setup->destCallSignalAddress, 852 + &ct->tuplehash[!dir].tuple.src.u3, 853 + ct->tuplehash[!dir].tuple.src.u.tcp.port); 854 + if (ret < 0) 855 + return -1; 856 + } 857 + 858 + if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) && 859 + (set_h225_addr) && ct->status & IPS_NAT_MASK && 860 + get_h225_addr(ct, *data, &setup->sourceCallSignalAddress, 861 + &addr, &port) && 862 + memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) { 863 + DEBUGP("nf_ct_q931: set sourceCallSignalAddress " 864 + NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n", 865 + NIP6(*(struct in6_addr *)&addr), ntohs(port), 866 + NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3), 867 + ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port)); 868 + ret = set_h225_addr(pskb, data, dataoff, 869 + &setup->sourceCallSignalAddress, 870 + &ct->tuplehash[!dir].tuple.dst.u3, 871 + ct->tuplehash[!dir].tuple.dst.u.tcp.port); 872 + if (ret < 0) 873 + return -1; 874 + } 875 + 876 + if (setup->options & eSetup_UUIE_fastStart) { 877 + for (i = 0; i < setup->fastStart.count; i++) { 878 + ret = process_olc(pskb, ct, ctinfo, data, dataoff, 879 + &setup->fastStart.item[i]); 880 + if (ret < 0) 881 + return -1; 882 + } 883 + } 884 + 885 + return 0; 886 + } 887 + 888 + /****************************************************************************/ 889 + static int process_callproceeding(struct sk_buff **pskb, 890 + struct nf_conn *ct, 891 + enum ip_conntrack_info ctinfo, 892 + unsigned char **data, int dataoff, 893 + CallProceeding_UUIE *callproc) 894 + { 895 + int ret; 896 + int i; 897 + 898 + DEBUGP("nf_ct_q931: CallProceeding\n"); 899 + 900 + if (callproc->options & eCallProceeding_UUIE_h245Address) { 901 + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, 902 + &callproc->h245Address); 903 + if (ret < 0) 904 + return -1; 905 + } 906 + 907 + if (callproc->options & eCallProceeding_UUIE_fastStart) { 908 + for (i = 0; i < callproc->fastStart.count; i++) { 909 + ret = process_olc(pskb, ct, ctinfo, data, dataoff, 910 + &callproc->fastStart.item[i]); 911 + if (ret < 0) 912 + return -1; 913 + } 914 + } 915 + 916 + return 0; 917 + } 918 + 919 + /****************************************************************************/ 920 + static int process_connect(struct sk_buff **pskb, struct nf_conn *ct, 921 + enum ip_conntrack_info ctinfo, 922 + unsigned char **data, int dataoff, 923 + Connect_UUIE *connect) 924 + { 925 + int ret; 926 + int i; 927 + 928 + DEBUGP("nf_ct_q931: Connect\n"); 929 + 930 + if (connect->options & eConnect_UUIE_h245Address) { 931 + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, 932 + &connect->h245Address); 933 + if (ret < 0) 934 + return -1; 935 + } 936 + 937 + if (connect->options & eConnect_UUIE_fastStart) { 938 + for (i = 0; i < connect->fastStart.count; i++) { 939 + ret = process_olc(pskb, ct, ctinfo, data, dataoff, 940 + &connect->fastStart.item[i]); 941 + if (ret < 0) 942 + return -1; 943 + } 944 + } 945 + 946 + return 0; 947 + } 948 + 949 + /****************************************************************************/ 950 + static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct, 951 + enum ip_conntrack_info ctinfo, 952 + unsigned char **data, int dataoff, 953 + Alerting_UUIE *alert) 954 + { 955 + int ret; 956 + int i; 957 + 958 + DEBUGP("nf_ct_q931: Alerting\n"); 959 + 960 + if (alert->options & eAlerting_UUIE_h245Address) { 961 + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, 962 + &alert->h245Address); 963 + if (ret < 0) 964 + return -1; 965 + } 966 + 967 + if (alert->options & eAlerting_UUIE_fastStart) { 968 + for (i = 0; i < alert->fastStart.count; i++) { 969 + ret = process_olc(pskb, ct, ctinfo, data, dataoff, 970 + &alert->fastStart.item[i]); 971 + if (ret < 0) 972 + return -1; 973 + } 974 + } 975 + 976 + return 0; 977 + } 978 + 979 + /****************************************************************************/ 980 + static int process_information(struct sk_buff **pskb, 981 + struct nf_conn *ct, 982 + enum ip_conntrack_info ctinfo, 983 + unsigned char **data, int dataoff, 984 + Information_UUIE *info) 985 + { 986 + int ret; 987 + int i; 988 + 989 + DEBUGP("nf_ct_q931: Information\n"); 990 + 991 + if (info->options & eInformation_UUIE_fastStart) { 992 + for (i = 0; i < info->fastStart.count; i++) { 993 + ret = process_olc(pskb, ct, ctinfo, data, dataoff, 994 + &info->fastStart.item[i]); 995 + if (ret < 0) 996 + return -1; 997 + } 998 + } 999 + 1000 + return 0; 1001 + } 1002 + 1003 + /****************************************************************************/ 1004 + static int process_facility(struct sk_buff **pskb, struct nf_conn *ct, 1005 + enum ip_conntrack_info ctinfo, 1006 + unsigned char **data, int dataoff, 1007 + Facility_UUIE *facility) 1008 + { 1009 + int ret; 1010 + int i; 1011 + 1012 + DEBUGP("nf_ct_q931: Facility\n"); 1013 + 1014 + if (facility->reason.choice == eFacilityReason_callForwarded) { 1015 + if (facility->options & eFacility_UUIE_alternativeAddress) 1016 + return expect_callforwarding(pskb, ct, ctinfo, data, 1017 + dataoff, 1018 + &facility-> 1019 + alternativeAddress); 1020 + return 0; 1021 + } 1022 + 1023 + if (facility->options & eFacility_UUIE_h245Address) { 1024 + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, 1025 + &facility->h245Address); 1026 + if (ret < 0) 1027 + return -1; 1028 + } 1029 + 1030 + if (facility->options & eFacility_UUIE_fastStart) { 1031 + for (i = 0; i < facility->fastStart.count; i++) { 1032 + ret = process_olc(pskb, ct, ctinfo, data, dataoff, 1033 + &facility->fastStart.item[i]); 1034 + if (ret < 0) 1035 + return -1; 1036 + } 1037 + } 1038 + 1039 + return 0; 1040 + } 1041 + 1042 + /****************************************************************************/ 1043 + static int process_progress(struct sk_buff **pskb, struct nf_conn *ct, 1044 + enum ip_conntrack_info ctinfo, 1045 + unsigned char **data, int dataoff, 1046 + Progress_UUIE *progress) 1047 + { 1048 + int ret; 1049 + int i; 1050 + 1051 + DEBUGP("nf_ct_q931: Progress\n"); 1052 + 1053 + if (progress->options & eProgress_UUIE_h245Address) { 1054 + ret = expect_h245(pskb, ct, ctinfo, data, dataoff, 1055 + &progress->h245Address); 1056 + if (ret < 0) 1057 + return -1; 1058 + } 1059 + 1060 + if (progress->options & eProgress_UUIE_fastStart) { 1061 + for (i = 0; i < progress->fastStart.count; i++) { 1062 + ret = process_olc(pskb, ct, ctinfo, data, dataoff, 1063 + &progress->fastStart.item[i]); 1064 + if (ret < 0) 1065 + return -1; 1066 + } 1067 + } 1068 + 1069 + return 0; 1070 + } 1071 + 1072 + /****************************************************************************/ 1073 + static int process_q931(struct sk_buff **pskb, struct nf_conn *ct, 1074 + enum ip_conntrack_info ctinfo, 1075 + unsigned char **data, int dataoff, Q931 *q931) 1076 + { 1077 + H323_UU_PDU *pdu = &q931->UUIE.h323_uu_pdu; 1078 + int i; 1079 + int ret = 0; 1080 + 1081 + switch (pdu->h323_message_body.choice) { 1082 + case eH323_UU_PDU_h323_message_body_setup: 1083 + ret = process_setup(pskb, ct, ctinfo, data, dataoff, 1084 + &pdu->h323_message_body.setup); 1085 + break; 1086 + case eH323_UU_PDU_h323_message_body_callProceeding: 1087 + ret = process_callproceeding(pskb, ct, ctinfo, data, dataoff, 1088 + &pdu->h323_message_body. 1089 + callProceeding); 1090 + break; 1091 + case eH323_UU_PDU_h323_message_body_connect: 1092 + ret = process_connect(pskb, ct, ctinfo, data, dataoff, 1093 + &pdu->h323_message_body.connect); 1094 + break; 1095 + case eH323_UU_PDU_h323_message_body_alerting: 1096 + ret = process_alerting(pskb, ct, ctinfo, data, dataoff, 1097 + &pdu->h323_message_body.alerting); 1098 + break; 1099 + case eH323_UU_PDU_h323_message_body_information: 1100 + ret = process_information(pskb, ct, ctinfo, data, dataoff, 1101 + &pdu->h323_message_body. 1102 + information); 1103 + break; 1104 + case eH323_UU_PDU_h323_message_body_facility: 1105 + ret = process_facility(pskb, ct, ctinfo, data, dataoff, 1106 + &pdu->h323_message_body.facility); 1107 + break; 1108 + case eH323_UU_PDU_h323_message_body_progress: 1109 + ret = process_progress(pskb, ct, ctinfo, data, dataoff, 1110 + &pdu->h323_message_body.progress); 1111 + break; 1112 + default: 1113 + DEBUGP("nf_ct_q931: Q.931 signal %d\n", 1114 + pdu->h323_message_body.choice); 1115 + break; 1116 + } 1117 + 1118 + if (ret < 0) 1119 + return -1; 1120 + 1121 + if (pdu->options & eH323_UU_PDU_h245Control) { 1122 + for (i = 0; i < pdu->h245Control.count; i++) { 1123 + ret = process_h245(pskb, ct, ctinfo, data, dataoff, 1124 + &pdu->h245Control.item[i]); 1125 + if (ret < 0) 1126 + return -1; 1127 + } 1128 + } 1129 + 1130 + return 0; 1131 + } 1132 + 1133 + /****************************************************************************/ 1134 + static int q931_help(struct sk_buff **pskb, unsigned int protoff, 1135 + struct nf_conn *ct, enum ip_conntrack_info ctinfo) 1136 + { 1137 + static Q931 q931; 1138 + unsigned char *data = NULL; 1139 + int datalen; 1140 + int dataoff; 1141 + int ret; 1142 + 1143 + /* Until there's been traffic both ways, don't look in packets. */ 1144 + if (ctinfo != IP_CT_ESTABLISHED && 1145 + ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { 1146 + return NF_ACCEPT; 1147 + } 1148 + DEBUGP("nf_ct_q931: skblen = %u\n", (*pskb)->len); 1149 + 1150 + spin_lock_bh(&nf_h323_lock); 1151 + 1152 + /* Process each TPKT */ 1153 + while (get_tpkt_data(pskb, protoff, ct, ctinfo, 1154 + &data, &datalen, &dataoff)) { 1155 + DEBUGP("nf_ct_q931: TPKT len=%d ", datalen); 1156 + NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); 1157 + 1158 + /* Decode Q.931 signal */ 1159 + ret = DecodeQ931(data, datalen, &q931); 1160 + if (ret < 0) { 1161 + if (net_ratelimit()) 1162 + printk("nf_ct_q931: decoding error: %s\n", 1163 + ret == H323_ERROR_BOUND ? 1164 + "out of bound" : "out of range"); 1165 + /* We don't drop when decoding error */ 1166 + break; 1167 + } 1168 + 1169 + /* Process Q.931 signal */ 1170 + if (process_q931(pskb, ct, ctinfo, &data, dataoff, &q931) < 0) 1171 + goto drop; 1172 + } 1173 + 1174 + spin_unlock_bh(&nf_h323_lock); 1175 + return NF_ACCEPT; 1176 + 1177 + drop: 1178 + spin_unlock_bh(&nf_h323_lock); 1179 + if (net_ratelimit()) 1180 + printk("nf_ct_q931: packet dropped\n"); 1181 + return NF_DROP; 1182 + } 1183 + 1184 + /****************************************************************************/ 1185 + static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = { 1186 + { 1187 + .name = "Q.931", 1188 + .me = THIS_MODULE, 1189 + /* T.120 and H.245 */ 1190 + .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4, 1191 + .timeout = 240, 1192 + .tuple.src.l3num = AF_INET, 1193 + .tuple.src.u.tcp.port = __constant_htons(Q931_PORT), 1194 + .tuple.dst.protonum = IPPROTO_TCP, 1195 + .mask.src.l3num = 0xFFFF, 1196 + .mask.src.u.tcp.port = __constant_htons(0xFFFF), 1197 + .mask.dst.protonum = 0xFF, 1198 + .help = q931_help 1199 + }, 1200 + { 1201 + .name = "Q.931", 1202 + .me = THIS_MODULE, 1203 + /* T.120 and H.245 */ 1204 + .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4, 1205 + .timeout = 240, 1206 + .tuple.src.l3num = AF_INET6, 1207 + .tuple.src.u.tcp.port = __constant_htons(Q931_PORT), 1208 + .tuple.dst.protonum = IPPROTO_TCP, 1209 + .mask.src.l3num = 0xFFFF, 1210 + .mask.src.u.tcp.port = __constant_htons(0xFFFF), 1211 + .mask.dst.protonum = 0xFF, 1212 + .help = q931_help 1213 + }, 1214 + }; 1215 + 1216 + /****************************************************************************/ 1217 + static unsigned char *get_udp_data(struct sk_buff **pskb, unsigned int protoff, 1218 + int *datalen) 1219 + { 1220 + struct udphdr _uh, *uh; 1221 + int dataoff; 1222 + 1223 + uh = skb_header_pointer(*pskb, protoff, sizeof(_uh), &_uh); 1224 + if (uh == NULL) 1225 + return NULL; 1226 + dataoff = protoff + sizeof(_uh); 1227 + if (dataoff >= (*pskb)->len) 1228 + return NULL; 1229 + *datalen = (*pskb)->len - dataoff; 1230 + return skb_header_pointer(*pskb, dataoff, *datalen, h323_buffer); 1231 + } 1232 + 1233 + /****************************************************************************/ 1234 + static struct nf_conntrack_expect *find_expect(struct nf_conn *ct, 1235 + union nf_conntrack_address *addr, 1236 + __be16 port) 1237 + { 1238 + struct nf_conntrack_expect *exp; 1239 + struct nf_conntrack_tuple tuple; 1240 + 1241 + memset(&tuple.src.u3, 0, sizeof(tuple.src.u3)); 1242 + tuple.src.u.tcp.port = 0; 1243 + memcpy(&tuple.dst.u3, addr, sizeof(tuple.dst.u3)); 1244 + tuple.dst.u.tcp.port = port; 1245 + tuple.dst.protonum = IPPROTO_TCP; 1246 + 1247 + exp = __nf_conntrack_expect_find(&tuple); 1248 + if (exp && exp->master == ct) 1249 + return exp; 1250 + return NULL; 1251 + } 1252 + 1253 + /****************************************************************************/ 1254 + static int set_expect_timeout(struct nf_conntrack_expect *exp, 1255 + unsigned timeout) 1256 + { 1257 + if (!exp || !del_timer(&exp->timeout)) 1258 + return 0; 1259 + 1260 + exp->timeout.expires = jiffies + timeout * HZ; 1261 + add_timer(&exp->timeout); 1262 + 1263 + return 1; 1264 + } 1265 + 1266 + /****************************************************************************/ 1267 + static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct, 1268 + enum ip_conntrack_info ctinfo, 1269 + unsigned char **data, 1270 + TransportAddress *taddr, int count) 1271 + { 1272 + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; 1273 + int dir = CTINFO2DIR(ctinfo); 1274 + int ret = 0; 1275 + int i; 1276 + __be16 port; 1277 + union nf_conntrack_address addr; 1278 + struct nf_conntrack_expect *exp; 1279 + typeof(nat_q931_hook) nat_q931; 1280 + 1281 + /* Look for the first related address */ 1282 + for (i = 0; i < count; i++) { 1283 + if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) && 1284 + memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, 1285 + sizeof(addr)) == 0 && port != 0) 1286 + break; 1287 + } 1288 + 1289 + if (i >= count) /* Not found */ 1290 + return 0; 1291 + 1292 + /* Create expect for Q.931 */ 1293 + if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) 1294 + return -1; 1295 + nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, 1296 + gkrouted_only ? /* only accept calls from GK? */ 1297 + &ct->tuplehash[!dir].tuple.src.u3 : 1298 + NULL, 1299 + &ct->tuplehash[!dir].tuple.dst.u3, 1300 + IPPROTO_TCP, NULL, &port); 1301 + exp->helper = nf_conntrack_helper_q931; 1302 + exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple calls */ 1303 + 1304 + nat_q931 = rcu_dereference(nat_q931_hook); 1305 + if (nat_q931 && ct->status & IPS_NAT_MASK) { /* Need NAT */ 1306 + ret = nat_q931(pskb, ct, ctinfo, data, taddr, i, port, exp); 1307 + } else { /* Conntrack only */ 1308 + if (nf_conntrack_expect_related(exp) == 0) { 1309 + DEBUGP("nf_ct_ras: expect Q.931 "); 1310 + NF_CT_DUMP_TUPLE(&exp->tuple); 1311 + 1312 + /* Save port for looking up expect in processing RCF */ 1313 + info->sig_port[dir] = port; 1314 + } else 1315 + ret = -1; 1316 + } 1317 + 1318 + nf_conntrack_expect_put(exp); 1319 + 1320 + return ret; 1321 + } 1322 + 1323 + /****************************************************************************/ 1324 + static int process_grq(struct sk_buff **pskb, struct nf_conn *ct, 1325 + enum ip_conntrack_info ctinfo, 1326 + unsigned char **data, GatekeeperRequest *grq) 1327 + { 1328 + typeof(set_ras_addr_hook) set_ras_addr; 1329 + 1330 + DEBUGP("nf_ct_ras: GRQ\n"); 1331 + 1332 + set_ras_addr = rcu_dereference(set_ras_addr_hook); 1333 + if (set_ras_addr && ct->status & IPS_NAT_MASK) /* NATed */ 1334 + return set_ras_addr(pskb, ct, ctinfo, data, 1335 + &grq->rasAddress, 1); 1336 + return 0; 1337 + } 1338 + 1339 + /****************************************************************************/ 1340 + static int process_gcf(struct sk_buff **pskb, struct nf_conn *ct, 1341 + enum ip_conntrack_info ctinfo, 1342 + unsigned char **data, GatekeeperConfirm *gcf) 1343 + { 1344 + int dir = CTINFO2DIR(ctinfo); 1345 + int ret = 0; 1346 + __be16 port; 1347 + union nf_conntrack_address addr; 1348 + struct nf_conntrack_expect *exp; 1349 + 1350 + DEBUGP("nf_ct_ras: GCF\n"); 1351 + 1352 + if (!get_h225_addr(ct, *data, &gcf->rasAddress, &addr, &port)) 1353 + return 0; 1354 + 1355 + /* Registration port is the same as discovery port */ 1356 + if (!memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) && 1357 + port == ct->tuplehash[dir].tuple.src.u.udp.port) 1358 + return 0; 1359 + 1360 + /* Avoid RAS expectation loops. A GCF is never expected. */ 1361 + if (test_bit(IPS_EXPECTED_BIT, &ct->status)) 1362 + return 0; 1363 + 1364 + /* Need new expect */ 1365 + if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) 1366 + return -1; 1367 + nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, 1368 + &ct->tuplehash[!dir].tuple.src.u3, &addr, 1369 + IPPROTO_UDP, NULL, &port); 1370 + exp->helper = nf_conntrack_helper_ras; 1371 + 1372 + if (nf_conntrack_expect_related(exp) == 0) { 1373 + DEBUGP("nf_ct_ras: expect RAS "); 1374 + NF_CT_DUMP_TUPLE(&exp->tuple); 1375 + } else 1376 + ret = -1; 1377 + 1378 + nf_conntrack_expect_put(exp); 1379 + 1380 + return ret; 1381 + } 1382 + 1383 + /****************************************************************************/ 1384 + static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct, 1385 + enum ip_conntrack_info ctinfo, 1386 + unsigned char **data, RegistrationRequest *rrq) 1387 + { 1388 + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; 1389 + int ret; 1390 + typeof(set_ras_addr_hook) set_ras_addr; 1391 + 1392 + DEBUGP("nf_ct_ras: RRQ\n"); 1393 + 1394 + ret = expect_q931(pskb, ct, ctinfo, data, 1395 + rrq->callSignalAddress.item, 1396 + rrq->callSignalAddress.count); 1397 + if (ret < 0) 1398 + return -1; 1399 + 1400 + set_ras_addr = rcu_dereference(set_ras_addr_hook); 1401 + if (set_ras_addr && ct->status & IPS_NAT_MASK) { 1402 + ret = set_ras_addr(pskb, ct, ctinfo, data, 1403 + rrq->rasAddress.item, 1404 + rrq->rasAddress.count); 1405 + if (ret < 0) 1406 + return -1; 1407 + } 1408 + 1409 + if (rrq->options & eRegistrationRequest_timeToLive) { 1410 + DEBUGP("nf_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive); 1411 + info->timeout = rrq->timeToLive; 1412 + } else 1413 + info->timeout = default_rrq_ttl; 1414 + 1415 + return 0; 1416 + } 1417 + 1418 + /****************************************************************************/ 1419 + static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct, 1420 + enum ip_conntrack_info ctinfo, 1421 + unsigned char **data, RegistrationConfirm *rcf) 1422 + { 1423 + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; 1424 + int dir = CTINFO2DIR(ctinfo); 1425 + int ret; 1426 + struct nf_conntrack_expect *exp; 1427 + typeof(set_sig_addr_hook) set_sig_addr; 1428 + 1429 + DEBUGP("nf_ct_ras: RCF\n"); 1430 + 1431 + set_sig_addr = rcu_dereference(set_sig_addr_hook); 1432 + if (set_sig_addr && ct->status & IPS_NAT_MASK) { 1433 + ret = set_sig_addr(pskb, ct, ctinfo, data, 1434 + rcf->callSignalAddress.item, 1435 + rcf->callSignalAddress.count); 1436 + if (ret < 0) 1437 + return -1; 1438 + } 1439 + 1440 + if (rcf->options & eRegistrationConfirm_timeToLive) { 1441 + DEBUGP("nf_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive); 1442 + info->timeout = rcf->timeToLive; 1443 + } 1444 + 1445 + if (info->timeout > 0) { 1446 + DEBUGP 1447 + ("nf_ct_ras: set RAS connection timeout to %u seconds\n", 1448 + info->timeout); 1449 + nf_ct_refresh(ct, *pskb, info->timeout * HZ); 1450 + 1451 + /* Set expect timeout */ 1452 + read_lock_bh(&nf_conntrack_lock); 1453 + exp = find_expect(ct, &ct->tuplehash[dir].tuple.dst.u3, 1454 + info->sig_port[!dir]); 1455 + if (exp) { 1456 + DEBUGP("nf_ct_ras: set Q.931 expect " 1457 + "timeout to %u seconds for", 1458 + info->timeout); 1459 + NF_CT_DUMP_TUPLE(&exp->tuple); 1460 + set_expect_timeout(exp, info->timeout); 1461 + } 1462 + read_unlock_bh(&nf_conntrack_lock); 1463 + } 1464 + 1465 + return 0; 1466 + } 1467 + 1468 + /****************************************************************************/ 1469 + static int process_urq(struct sk_buff **pskb, struct nf_conn *ct, 1470 + enum ip_conntrack_info ctinfo, 1471 + unsigned char **data, UnregistrationRequest *urq) 1472 + { 1473 + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; 1474 + int dir = CTINFO2DIR(ctinfo); 1475 + int ret; 1476 + typeof(set_sig_addr_hook) set_sig_addr; 1477 + 1478 + DEBUGP("nf_ct_ras: URQ\n"); 1479 + 1480 + set_sig_addr = rcu_dereference(set_sig_addr_hook); 1481 + if (set_sig_addr && ct->status & IPS_NAT_MASK) { 1482 + ret = set_sig_addr(pskb, ct, ctinfo, data, 1483 + urq->callSignalAddress.item, 1484 + urq->callSignalAddress.count); 1485 + if (ret < 0) 1486 + return -1; 1487 + } 1488 + 1489 + /* Clear old expect */ 1490 + nf_ct_remove_expectations(ct); 1491 + info->sig_port[dir] = 0; 1492 + info->sig_port[!dir] = 0; 1493 + 1494 + /* Give it 30 seconds for UCF or URJ */ 1495 + nf_ct_refresh(ct, *pskb, 30 * HZ); 1496 + 1497 + return 0; 1498 + } 1499 + 1500 + /****************************************************************************/ 1501 + static int process_arq(struct sk_buff **pskb, struct nf_conn *ct, 1502 + enum ip_conntrack_info ctinfo, 1503 + unsigned char **data, AdmissionRequest *arq) 1504 + { 1505 + struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info; 1506 + int dir = CTINFO2DIR(ctinfo); 1507 + __be16 port; 1508 + union nf_conntrack_address addr; 1509 + typeof(set_h225_addr_hook) set_h225_addr; 1510 + 1511 + DEBUGP("nf_ct_ras: ARQ\n"); 1512 + 1513 + set_h225_addr = rcu_dereference(set_h225_addr_hook); 1514 + if ((arq->options & eAdmissionRequest_destCallSignalAddress) && 1515 + get_h225_addr(ct, *data, &arq->destCallSignalAddress, 1516 + &addr, &port) && 1517 + !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) && 1518 + port == info->sig_port[dir] && 1519 + set_h225_addr && ct->status & IPS_NAT_MASK) { 1520 + /* Answering ARQ */ 1521 + return set_h225_addr(pskb, data, 0, 1522 + &arq->destCallSignalAddress, 1523 + &ct->tuplehash[!dir].tuple.dst.u3, 1524 + info->sig_port[!dir]); 1525 + } 1526 + 1527 + if ((arq->options & eAdmissionRequest_srcCallSignalAddress) && 1528 + get_h225_addr(ct, *data, &arq->srcCallSignalAddress, 1529 + &addr, &port) && 1530 + !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) && 1531 + set_h225_addr && ct->status & IPS_NAT_MASK) { 1532 + /* Calling ARQ */ 1533 + return set_h225_addr(pskb, data, 0, 1534 + &arq->srcCallSignalAddress, 1535 + &ct->tuplehash[!dir].tuple.dst.u3, 1536 + port); 1537 + } 1538 + 1539 + return 0; 1540 + } 1541 + 1542 + /****************************************************************************/ 1543 + static int process_acf(struct sk_buff **pskb, struct nf_conn *ct, 1544 + enum ip_conntrack_info ctinfo, 1545 + unsigned char **data, AdmissionConfirm *acf) 1546 + { 1547 + int dir = CTINFO2DIR(ctinfo); 1548 + int ret = 0; 1549 + __be16 port; 1550 + union nf_conntrack_address addr; 1551 + struct nf_conntrack_expect *exp; 1552 + typeof(set_sig_addr_hook) set_sig_addr; 1553 + 1554 + DEBUGP("nf_ct_ras: ACF\n"); 1555 + 1556 + if (!get_h225_addr(ct, *data, &acf->destCallSignalAddress, 1557 + &addr, &port)) 1558 + return 0; 1559 + 1560 + if (!memcmp(&addr, &ct->tuplehash[dir].tuple.dst.u3, sizeof(addr))) { 1561 + /* Answering ACF */ 1562 + set_sig_addr = rcu_dereference(set_sig_addr_hook); 1563 + if (set_sig_addr && ct->status & IPS_NAT_MASK) 1564 + return set_sig_addr(pskb, ct, ctinfo, data, 1565 + &acf->destCallSignalAddress, 1); 1566 + return 0; 1567 + } 1568 + 1569 + /* Need new expect */ 1570 + if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) 1571 + return -1; 1572 + nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, 1573 + &ct->tuplehash[!dir].tuple.src.u3, &addr, 1574 + IPPROTO_TCP, NULL, &port); 1575 + exp->flags = NF_CT_EXPECT_PERMANENT; 1576 + exp->helper = nf_conntrack_helper_q931; 1577 + 1578 + if (nf_conntrack_expect_related(exp) == 0) { 1579 + DEBUGP("nf_ct_ras: expect Q.931 "); 1580 + NF_CT_DUMP_TUPLE(&exp->tuple); 1581 + } else 1582 + ret = -1; 1583 + 1584 + nf_conntrack_expect_put(exp); 1585 + 1586 + return ret; 1587 + } 1588 + 1589 + /****************************************************************************/ 1590 + static int process_lrq(struct sk_buff **pskb, struct nf_conn *ct, 1591 + enum ip_conntrack_info ctinfo, 1592 + unsigned char **data, LocationRequest *lrq) 1593 + { 1594 + typeof(set_ras_addr_hook) set_ras_addr; 1595 + 1596 + DEBUGP("nf_ct_ras: LRQ\n"); 1597 + 1598 + set_ras_addr = rcu_dereference(set_ras_addr_hook); 1599 + if (set_ras_addr && ct->status & IPS_NAT_MASK) 1600 + return set_ras_addr(pskb, ct, ctinfo, data, 1601 + &lrq->replyAddress, 1); 1602 + return 0; 1603 + } 1604 + 1605 + /****************************************************************************/ 1606 + static int process_lcf(struct sk_buff **pskb, struct nf_conn *ct, 1607 + enum ip_conntrack_info ctinfo, 1608 + unsigned char **data, LocationConfirm *lcf) 1609 + { 1610 + int dir = CTINFO2DIR(ctinfo); 1611 + int ret = 0; 1612 + __be16 port; 1613 + union nf_conntrack_address addr; 1614 + struct nf_conntrack_expect *exp; 1615 + 1616 + DEBUGP("nf_ct_ras: LCF\n"); 1617 + 1618 + if (!get_h225_addr(ct, *data, &lcf->callSignalAddress, 1619 + &addr, &port)) 1620 + return 0; 1621 + 1622 + /* Need new expect for call signal */ 1623 + if ((exp = nf_conntrack_expect_alloc(ct)) == NULL) 1624 + return -1; 1625 + nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num, 1626 + &ct->tuplehash[!dir].tuple.src.u3, &addr, 1627 + IPPROTO_TCP, NULL, &port); 1628 + exp->flags = NF_CT_EXPECT_PERMANENT; 1629 + exp->helper = nf_conntrack_helper_q931; 1630 + 1631 + if (nf_conntrack_expect_related(exp) == 0) { 1632 + DEBUGP("nf_ct_ras: expect Q.931 "); 1633 + NF_CT_DUMP_TUPLE(&exp->tuple); 1634 + } else 1635 + ret = -1; 1636 + 1637 + nf_conntrack_expect_put(exp); 1638 + 1639 + /* Ignore rasAddress */ 1640 + 1641 + return ret; 1642 + } 1643 + 1644 + /****************************************************************************/ 1645 + static int process_irr(struct sk_buff **pskb, struct nf_conn *ct, 1646 + enum ip_conntrack_info ctinfo, 1647 + unsigned char **data, InfoRequestResponse *irr) 1648 + { 1649 + int ret; 1650 + typeof(set_ras_addr_hook) set_ras_addr; 1651 + typeof(set_sig_addr_hook) set_sig_addr; 1652 + 1653 + DEBUGP("nf_ct_ras: IRR\n"); 1654 + 1655 + set_ras_addr = rcu_dereference(set_ras_addr_hook); 1656 + if (set_ras_addr && ct->status & IPS_NAT_MASK) { 1657 + ret = set_ras_addr(pskb, ct, ctinfo, data, 1658 + &irr->rasAddress, 1); 1659 + if (ret < 0) 1660 + return -1; 1661 + } 1662 + 1663 + set_sig_addr = rcu_dereference(set_sig_addr_hook); 1664 + if (set_sig_addr && ct->status & IPS_NAT_MASK) { 1665 + ret = set_sig_addr(pskb, ct, ctinfo, data, 1666 + irr->callSignalAddress.item, 1667 + irr->callSignalAddress.count); 1668 + if (ret < 0) 1669 + return -1; 1670 + } 1671 + 1672 + return 0; 1673 + } 1674 + 1675 + /****************************************************************************/ 1676 + static int process_ras(struct sk_buff **pskb, struct nf_conn *ct, 1677 + enum ip_conntrack_info ctinfo, 1678 + unsigned char **data, RasMessage *ras) 1679 + { 1680 + switch (ras->choice) { 1681 + case eRasMessage_gatekeeperRequest: 1682 + return process_grq(pskb, ct, ctinfo, data, 1683 + &ras->gatekeeperRequest); 1684 + case eRasMessage_gatekeeperConfirm: 1685 + return process_gcf(pskb, ct, ctinfo, data, 1686 + &ras->gatekeeperConfirm); 1687 + case eRasMessage_registrationRequest: 1688 + return process_rrq(pskb, ct, ctinfo, data, 1689 + &ras->registrationRequest); 1690 + case eRasMessage_registrationConfirm: 1691 + return process_rcf(pskb, ct, ctinfo, data, 1692 + &ras->registrationConfirm); 1693 + case eRasMessage_unregistrationRequest: 1694 + return process_urq(pskb, ct, ctinfo, data, 1695 + &ras->unregistrationRequest); 1696 + case eRasMessage_admissionRequest: 1697 + return process_arq(pskb, ct, ctinfo, data, 1698 + &ras->admissionRequest); 1699 + case eRasMessage_admissionConfirm: 1700 + return process_acf(pskb, ct, ctinfo, data, 1701 + &ras->admissionConfirm); 1702 + case eRasMessage_locationRequest: 1703 + return process_lrq(pskb, ct, ctinfo, data, 1704 + &ras->locationRequest); 1705 + case eRasMessage_locationConfirm: 1706 + return process_lcf(pskb, ct, ctinfo, data, 1707 + &ras->locationConfirm); 1708 + case eRasMessage_infoRequestResponse: 1709 + return process_irr(pskb, ct, ctinfo, data, 1710 + &ras->infoRequestResponse); 1711 + default: 1712 + DEBUGP("nf_ct_ras: RAS message %d\n", ras->choice); 1713 + break; 1714 + } 1715 + 1716 + return 0; 1717 + } 1718 + 1719 + /****************************************************************************/ 1720 + static int ras_help(struct sk_buff **pskb, unsigned int protoff, 1721 + struct nf_conn *ct, enum ip_conntrack_info ctinfo) 1722 + { 1723 + static RasMessage ras; 1724 + unsigned char *data; 1725 + int datalen = 0; 1726 + int ret; 1727 + 1728 + DEBUGP("nf_ct_ras: skblen = %u\n", (*pskb)->len); 1729 + 1730 + spin_lock_bh(&nf_h323_lock); 1731 + 1732 + /* Get UDP data */ 1733 + data = get_udp_data(pskb, protoff, &datalen); 1734 + if (data == NULL) 1735 + goto accept; 1736 + DEBUGP("nf_ct_ras: RAS message len=%d ", datalen); 1737 + NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple); 1738 + 1739 + /* Decode RAS message */ 1740 + ret = DecodeRasMessage(data, datalen, &ras); 1741 + if (ret < 0) { 1742 + if (net_ratelimit()) 1743 + printk("nf_ct_ras: decoding error: %s\n", 1744 + ret == H323_ERROR_BOUND ? 1745 + "out of bound" : "out of range"); 1746 + goto accept; 1747 + } 1748 + 1749 + /* Process RAS message */ 1750 + if (process_ras(pskb, ct, ctinfo, &data, &ras) < 0) 1751 + goto drop; 1752 + 1753 + accept: 1754 + spin_unlock_bh(&nf_h323_lock); 1755 + return NF_ACCEPT; 1756 + 1757 + drop: 1758 + spin_unlock_bh(&nf_h323_lock); 1759 + if (net_ratelimit()) 1760 + printk("nf_ct_ras: packet dropped\n"); 1761 + return NF_DROP; 1762 + } 1763 + 1764 + /****************************************************************************/ 1765 + static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = { 1766 + { 1767 + .name = "RAS", 1768 + .me = THIS_MODULE, 1769 + .max_expected = 32, 1770 + .timeout = 240, 1771 + .tuple.src.l3num = AF_INET, 1772 + .tuple.src.u.udp.port = __constant_htons(RAS_PORT), 1773 + .tuple.dst.protonum = IPPROTO_UDP, 1774 + .mask.src.l3num = 0xFFFF, 1775 + .mask.src.u.udp.port = __constant_htons(0xFFFF), 1776 + .mask.dst.protonum = 0xFF, 1777 + .help = ras_help, 1778 + }, 1779 + { 1780 + .name = "RAS", 1781 + .me = THIS_MODULE, 1782 + .max_expected = 32, 1783 + .timeout = 240, 1784 + .tuple.src.l3num = AF_INET6, 1785 + .tuple.src.u.udp.port = __constant_htons(RAS_PORT), 1786 + .tuple.dst.protonum = IPPROTO_UDP, 1787 + .mask.src.l3num = 0xFFFF, 1788 + .mask.src.u.udp.port = __constant_htons(0xFFFF), 1789 + .mask.dst.protonum = 0xFF, 1790 + .help = ras_help, 1791 + }, 1792 + }; 1793 + 1794 + /****************************************************************************/ 1795 + static void __exit nf_conntrack_h323_fini(void) 1796 + { 1797 + nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[1]); 1798 + nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[0]); 1799 + nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]); 1800 + nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]); 1801 + kfree(h323_buffer); 1802 + DEBUGP("nf_ct_h323: fini\n"); 1803 + } 1804 + 1805 + /****************************************************************************/ 1806 + static int __init nf_conntrack_h323_init(void) 1807 + { 1808 + int ret; 1809 + 1810 + h323_buffer = kmalloc(65536, GFP_KERNEL); 1811 + if (!h323_buffer) 1812 + return -ENOMEM; 1813 + ret = nf_conntrack_helper_register(&nf_conntrack_helper_q931[0]); 1814 + if (ret < 0) 1815 + goto err1; 1816 + ret = nf_conntrack_helper_register(&nf_conntrack_helper_q931[1]); 1817 + if (ret < 0) 1818 + goto err2; 1819 + ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[0]); 1820 + if (ret < 0) 1821 + goto err3; 1822 + ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[1]); 1823 + if (ret < 0) 1824 + goto err4; 1825 + DEBUGP("nf_ct_h323: init success\n"); 1826 + return 0; 1827 + 1828 + err4: 1829 + nf_conntrack_helper_unregister(&nf_conntrack_helper_ras[0]); 1830 + err3: 1831 + nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]); 1832 + err2: 1833 + nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]); 1834 + err1: 1835 + return ret; 1836 + } 1837 + 1838 + /****************************************************************************/ 1839 + module_init(nf_conntrack_h323_init); 1840 + module_exit(nf_conntrack_h323_fini); 1841 + 1842 + EXPORT_SYMBOL_GPL(get_h225_addr); 1843 + EXPORT_SYMBOL_GPL(set_h245_addr_hook); 1844 + EXPORT_SYMBOL_GPL(set_h225_addr_hook); 1845 + EXPORT_SYMBOL_GPL(set_sig_addr_hook); 1846 + EXPORT_SYMBOL_GPL(set_ras_addr_hook); 1847 + EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook); 1848 + EXPORT_SYMBOL_GPL(nat_t120_hook); 1849 + EXPORT_SYMBOL_GPL(nat_h245_hook); 1850 + EXPORT_SYMBOL_GPL(nat_callforwarding_hook); 1851 + EXPORT_SYMBOL_GPL(nat_q931_hook); 1852 + 1853 + MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>"); 1854 + MODULE_DESCRIPTION("H.323 connection tracking helper"); 1855 + MODULE_LICENSE("GPL"); 1856 + MODULE_ALIAS("ip_conntrack_h323");