2 * Copyright 2001, QNX Software Systems Ltd. All Rights Reserved
4 * This source code has been published by QNX Software Systems Ltd. (QSSL).
5 * However, any use, reproduction, modification, distribution or transfer of
6 * this software, or any software which includes or is based upon any of this
7 * code, is only permitted under the terms of the QNX Open Community License
8 * version 1.0 (see licensing.qnx.com for details) or as otherwise expressly
9 * authorized by a written license agreement from QSSL. For more information,
10 * please email licensing@qnx.com.
12 * For more details, see QNX_OCL.txt provided with this distribution.
19 * ported to ipfilter 3.4.20 by Michael Grant mg-ipf@grant.org
22 #if __FreeBSD_version >= 220000 && defined(_KERNEL)
23 # include <sys/fcntl.h>
24 # include <sys/filio.h>
26 # include <sys/ioctl.h>
29 #define IPF_H323_PROXY
31 int ippr_h323_init
__P((void));
32 int ippr_h323_new
__P((fr_info_t
*, ip_t
*, ap_session_t
*, nat_t
*));
33 void ippr_h323_del
__P((ap_session_t
*));
34 int ippr_h323_out
__P((fr_info_t
*, ip_t
*, ap_session_t
*, nat_t
*));
35 int ippr_h323_in
__P((fr_info_t
*, ip_t
*, ap_session_t
*, nat_t
*));
37 int ippr_h245_init
__P((void));
38 int ippr_h245_new
__P((fr_info_t
*, ip_t
*, ap_session_t
*, nat_t
*));
39 int ippr_h245_out
__P((fr_info_t
*, ip_t
*, ap_session_t
*, nat_t
*));
40 int ippr_h245_in
__P((fr_info_t
*, ip_t
*, ap_session_t
*, nat_t
*));
42 static frentry_t h323_fr
;
43 #if (SOLARIS || defined(__sgi)) && defined(_KERNEL)
44 extern KRWLOCK_T ipf_nat
;
47 static int find_port
__P((int, u_char
*, int datlen
, int *, u_short
*));
50 static int find_port(ipaddr
, data
, datlen
, off
, port
)
66 netaddr
= ntohl(ipaddr
);
68 for (offset
= 0; offset
<= datlen
- 6; offset
++, dp
++) {
69 addr
= (dp
[0] << 24) | (dp
[1] << 16) | (dp
[2] << 8) | dp
[3];
72 *port
= (*(dp
+ 4) << 8) | *(dp
+ 5);
77 return (offset
> datlen
- 6) ? -1 : 0;
81 * Initialize local structures.
85 bzero((char *)&h323_fr
, sizeof(h323_fr
));
87 h323_fr
.fr_flags
= FR_INQUE
|FR_PASS
|FR_QUICK
|FR_KEEPSTATE
;
93 int ippr_h323_new(fin
, ip
, aps
, nat
)
106 void ippr_h323_del(aps
)
113 for (i
= 0, ipn
= aps
->aps_data
;
114 i
< (aps
->aps_psiz
/ sizeof(ipnat_t
));
115 i
++, ipn
= (ipnat_t
*)((char *)ipn
+ sizeof(*ipn
)))
118 * Check the comment in ippr_h323_in() function,
119 * just above nat_ioctl() call.
120 * We are lucky here because this function is not
121 * called with ipf_nat locked.
123 if (nat_ioctl((caddr_t
)ipn
, SIOCRMNAT
, NAT_SYSSPACE
|
124 NAT_LOCKHELD
|FWRITE
) == -1) {
128 KFREES(aps
->aps_data
, aps
->aps_psiz
);
129 /* avoid double free */
130 aps
->aps_data
= NULL
;
137 int ippr_h323_out(fin
, ip
, aps
, nat
)
147 int ippr_h323_in(fin
, ip
, aps
, nat
)
153 int ipaddr
, off
, datlen
;
158 tcp
= (tcphdr_t
*)fin
->fin_dp
;
159 ipaddr
= ip
->ip_src
.s_addr
;
161 data
= (unsigned char *)tcp
+ (tcp
->th_off
<< 2);
162 datlen
= fin
->fin_dlen
- (tcp
->th_off
<< 2);
163 if (find_port(ipaddr
, data
, datlen
, &off
, &port
) == 0) {
167 /* setup a nat rule to set a h245 proxy on tcp-port "port"
169 * map <if> <inter_ip>/<mask> -> <gate_ip>/<mask> proxy port <port> <port>/tcp
171 KMALLOCS(newarray
, char *, aps
->aps_psiz
+ sizeof(*ipn
));
172 if (newarray
== NULL
) {
175 ipn
= (ipnat_t
*)&newarray
[aps
->aps_psiz
];
176 bcopy(nat
->nat_ptr
, ipn
, sizeof(ipnat_t
));
177 strncpy(ipn
->in_plabel
, "h245", APR_LABELLEN
);
179 ipn
->in_inip
= nat
->nat_inip
.s_addr
;
180 ipn
->in_inmsk
= 0xffffffff;
181 ipn
->in_dport
= htons(port
);
183 * we got a problem here. we need to call nat_ioctl() to add
184 * the h245 proxy rule, but since we already hold (READ locked)
185 * the nat table rwlock (ipf_nat), if we go into nat_ioctl(),
186 * it will try to WRITE lock it. This will causing dead lock
189 * The quick & dirty solution here is release the read lock,
190 * call nat_ioctl() and re-lock it.
191 * A (maybe better) solution is do a UPGRADE(), and instead
192 * of calling nat_ioctl(), we add the nat rule ourself.
194 RWLOCK_EXIT(&ipf_nat
);
195 if (nat_ioctl((caddr_t
)ipn
, SIOCADNAT
,
196 NAT_SYSSPACE
|FWRITE
) == -1) {
197 READ_ENTER(&ipf_nat
);
200 READ_ENTER(&ipf_nat
);
201 if (aps
->aps_data
!= NULL
&& aps
->aps_psiz
> 0) {
202 bcopy(aps
->aps_data
, newarray
, aps
->aps_psiz
);
203 KFREES(aps
->aps_data
, aps
->aps_psiz
);
205 aps
->aps_data
= newarray
;
206 aps
->aps_psiz
+= sizeof(*ipn
);
218 int ippr_h245_new(fin
, ip
, aps
, nat
)
224 aps
->aps_data
= NULL
;
230 int ippr_h245_out(fin
, ip
, aps
, nat
)
236 int ipaddr
, off
, datlen
;
241 tcp
= (tcphdr_t
*)fin
->fin_dp
;
242 ipaddr
= nat
->nat_inip
.s_addr
;
243 data
= (unsigned char *)tcp
+ (tcp
->th_off
<< 2);
244 datlen
= ip
->ip_len
- fin
->fin_hlen
- (tcp
->th_off
<< 2);
245 if (find_port(ipaddr
, data
, datlen
, &off
, &port
) == 0) {
249 /* port = htons(port); */
250 ipn
= nat_outlookup(fin
->fin_ifp
, IPN_UDP
, IPPROTO_UDP
,
251 ip
->ip_src
, ip
->ip_dst
, 1);
256 bcopy(ip
, &newip
, sizeof(newip
));
257 newip
.ip_len
= fin
->fin_hlen
+ sizeof(udp
);
258 newip
.ip_p
= IPPROTO_UDP
;
259 newip
.ip_src
= nat
->nat_inip
;
261 bzero(&udp
, sizeof(udp
));
264 bcopy(fin
, &fi
, sizeof(fi
));
265 fi
.fin_fi
.fi_p
= IPPROTO_UDP
;
266 fi
.fin_data
[0] = port
;
268 fi
.fin_dp
= (char *)&udp
;
270 ipn
= nat_new(&fi
, &newip
, nat
->nat_ptr
, NULL
,
271 IPN_UDP
|FI_W_DPORT
, NAT_OUTBOUND
);
273 ipn
->nat_ptr
->in_hits
++;
275 nat_log(ipn
, (u_int
)(nat
->nat_ptr
->in_redir
));
277 bcopy((u_char
*)&ip
->ip_src
.s_addr
,
279 bcopy((u_char
*)&ipn
->nat_outport
,
288 int ippr_h245_in(fin
, ip
, aps
, nat
)