4 * Copyright 2001, QNX Software Systems Ltd. All Rights Reserved
6 * This source code has been published by QNX Software Systems Ltd. (QSSL).
7 * However, any use, reproduction, modification, distribution or transfer of
8 * this software, or any software which includes or is based upon any of this
9 * code, is only permitted under the terms of the QNX Open Community License
10 * version 1.0 (see licensing.qnx.com for details) or as otherwise expressly
11 * authorized by a written license agreement from QSSL. For more information,
12 * please email licensing@qnx.com.
14 * For more details, see QNX_OCL.txt provided with this distribution.
21 * ported to ipfilter 3.4.20 by Michael Grant mg-ipf@grant.org
24 #include <sys/cdefs.h>
25 __KERNEL_RCSID(1, "$NetBSD$");
27 #define IPF_H323_PROXY
29 int ippr_h323_init
__P((void));
30 void ippr_h323_fini
__P((void));
31 int ippr_h323_new
__P((fr_info_t
*, ap_session_t
*, nat_t
*));
32 void ippr_h323_del
__P((ap_session_t
*));
33 int ippr_h323_out
__P((fr_info_t
*, ap_session_t
*, nat_t
*));
34 int ippr_h323_in
__P((fr_info_t
*, ap_session_t
*, nat_t
*));
36 int ippr_h245_new
__P((fr_info_t
*, ap_session_t
*, nat_t
*));
37 int ippr_h245_out
__P((fr_info_t
*, ap_session_t
*, nat_t
*));
38 int ippr_h245_in
__P((fr_info_t
*, ap_session_t
*, nat_t
*));
40 static frentry_t h323_fr
;
42 int h323_proxy_init
= 0;
44 static int find_port
__P((int, void *, int datlen
, int *, u_short
*));
47 static int find_port(ipaddr
, data
, datlen
, off
, port
)
63 netaddr
= ntohl(ipaddr
);
65 for (offset
= 0; offset
<= datlen
- 6; offset
++, dp
++) {
66 addr
= (dp
[0] << 24) | (dp
[1] << 16) | (dp
[2] << 8) | dp
[3];
69 *port
= (*(dp
+ 4) << 8) | *(dp
+ 5);
74 return (offset
> datlen
- 6) ? -1 : 0;
78 * Initialize local structures.
82 bzero((char *)&h323_fr
, sizeof(h323_fr
));
84 h323_fr
.fr_flags
= FR_INQUE
|FR_PASS
|FR_QUICK
|FR_KEEPSTATE
;
85 MUTEX_INIT(&h323_fr
.fr_lock
, "H323 proxy rule lock");
94 if (h323_proxy_init
== 1) {
95 MUTEX_DESTROY(&h323_fr
.fr_lock
);
101 int ippr_h323_new(fin
, aps
, nat
)
106 fin
= fin
; /* LINT */
107 nat
= nat
; /* LINT */
109 aps
->aps_data
= NULL
;
116 void ippr_h323_del(aps
)
123 for (i
= 0, ipn
= aps
->aps_data
;
124 i
< (aps
->aps_psiz
/ sizeof(ipnat_t
));
125 i
++, ipn
= (ipnat_t
*)((char *)ipn
+ sizeof(*ipn
)))
128 * Check the comment in ippr_h323_in() function,
129 * just above fr_nat_ioctl() call.
130 * We are lucky here because this function is not
131 * called with ipf_nat locked.
133 if (fr_nat_ioctl((void *)ipn
, SIOCRMNAT
, NAT_SYSSPACE
|
134 NAT_LOCKHELD
|FWRITE
, 0, NULL
) == -1) {
139 KFREES(aps
->aps_data
, aps
->aps_psiz
);
140 /* avoid double free */
141 aps
->aps_data
= NULL
;
148 int ippr_h323_in(fin
, aps
, nat
)
153 int ipaddr
, off
, datlen
;
160 tcp
= (tcphdr_t
*)fin
->fin_dp
;
161 ipaddr
= ip
->ip_src
.s_addr
;
163 data
= (char *)tcp
+ (TCP_OFF(tcp
) << 2);
164 datlen
= fin
->fin_dlen
- (TCP_OFF(tcp
) << 2);
165 if (find_port(ipaddr
, data
, datlen
, &off
, &port
) == 0) {
169 /* setup a nat rule to set a h245 proxy on tcp-port "port"
171 * map <if> <inter_ip>/<mask> -> <gate_ip>/<mask> proxy port <port> <port>/tcp
173 KMALLOCS(newarray
, char *, aps
->aps_psiz
+ sizeof(*ipn
));
174 if (newarray
== NULL
) {
177 ipn
= (ipnat_t
*)&newarray
[aps
->aps_psiz
];
178 bcopy((void *)nat
->nat_ptr
, (void *)ipn
, sizeof(ipnat_t
));
179 (void) strncpy(ipn
->in_plabel
, "h245", APR_LABELLEN
);
181 ipn
->in_inip
= nat
->nat_inip
.s_addr
;
182 ipn
->in_inmsk
= 0xffffffff;
183 ipn
->in_dport
= htons(port
);
185 * we got a problem here. we need to call fr_nat_ioctl() to add
186 * the h245 proxy rule, but since we already hold (READ locked)
187 * the nat table rwlock (ipf_nat), if we go into fr_nat_ioctl(),
188 * it will try to WRITE lock it. This will causing dead lock
191 * The quick & dirty solution here is release the read lock,
192 * call fr_nat_ioctl() and re-lock it.
193 * A (maybe better) solution is do a UPGRADE(), and instead
194 * of calling fr_nat_ioctl(), we add the nat rule ourself.
196 RWLOCK_EXIT(&ipf_nat
);
197 if (fr_nat_ioctl((void *)ipn
, SIOCADNAT
,
198 NAT_SYSSPACE
|FWRITE
, 0, NULL
) == -1) {
199 READ_ENTER(&ipf_nat
);
202 READ_ENTER(&ipf_nat
);
203 if (aps
->aps_data
!= NULL
&& aps
->aps_psiz
> 0) {
204 bcopy(aps
->aps_data
, newarray
, aps
->aps_psiz
);
205 KFREES(aps
->aps_data
, aps
->aps_psiz
);
207 aps
->aps_data
= newarray
;
208 aps
->aps_psiz
+= sizeof(*ipn
);
214 int ippr_h245_new(fin
, aps
, nat
)
219 fin
= fin
; /* LINT */
220 nat
= nat
; /* LINT */
222 aps
->aps_data
= NULL
;
228 int ippr_h245_out(fin
, aps
, nat
)
233 int ipaddr
, off
, datlen
;
239 aps
= aps
; /* LINT */
242 tcp
= (tcphdr_t
*)fin
->fin_dp
;
243 ipaddr
= nat
->nat_inip
.s_addr
;
244 data
= (char *)tcp
+ (TCP_OFF(tcp
) << 2);
245 datlen
= fin
->fin_dlen
- (TCP_OFF(tcp
) << 2);
246 if (find_port(ipaddr
, data
, datlen
, &off
, &port
) == 0) {
250 /* port = htons(port); */
251 nat2
= nat_outlookup(fin
, IPN_UDP
, IPPROTO_UDP
,
252 ip
->ip_src
, ip
->ip_dst
);
257 bcopy((void *)ip
, (void *)&newip
, sizeof(newip
));
258 newip
.ip_len
= fin
->fin_hlen
+ sizeof(udp
);
259 newip
.ip_p
= IPPROTO_UDP
;
260 newip
.ip_src
= nat
->nat_inip
;
262 bzero((char *)&udp
, sizeof(udp
));
265 memcpy(&fi
, fin
, sizeof(fi
));
266 fi
.fin_fi
.fi_p
= IPPROTO_UDP
;
267 fi
.fin_data
[0] = port
;
269 fi
.fin_dp
= (char *)&udp
;
271 MUTEX_ENTER(&ipf_nat_new
);
272 nat2
= nat_new(&fi
, nat
->nat_ptr
, NULL
,
273 NAT_SLAVE
|IPN_UDP
|SI_W_DPORT
,
275 MUTEX_EXIT(&ipf_nat_new
);
277 (void) nat_proto(&fi
, nat2
, IPN_UDP
);
278 MUTEX_ENTER(&nat2
->nat_lock
);
279 nat_update(&fi
, nat2
);
280 MUTEX_EXIT(&nat2
->nat_lock
);
282 nat2
->nat_ptr
->in_hits
++;
284 nat_log(nat2
, (u_int
)(nat
->nat_ptr
->in_redir
));
286 memcpy((char *)data
+ off
, &ip
->ip_src
.s_addr
, 4);
287 memcpy((char *)data
+ off
+ 4, &nat2
->nat_outport
, 2);