4 * Copyright (C) 1998-2003 by Darren Reed
6 * See the IPFILTER.LICENCE file for details on licencing.
8 * Id: ip_raudio_pxy.c,v 1.40.2.7 2008/11/06 21:18:36 darrenr Exp
11 #include <sys/cdefs.h>
12 __KERNEL_RCSID(1, "$NetBSD$");
14 #define IPF_RAUDIO_PROXY
17 int ippr_raudio_init
__P((void));
18 void ippr_raudio_fini
__P((void));
19 int ippr_raudio_new
__P((fr_info_t
*, ap_session_t
*, nat_t
*));
20 int ippr_raudio_in
__P((fr_info_t
*, ap_session_t
*, nat_t
*));
21 int ippr_raudio_out
__P((fr_info_t
*, ap_session_t
*, nat_t
*));
23 static frentry_t raudiofr
;
25 int raudio_proxy_init
= 0;
29 * Real Audio application proxy initialization.
31 int ippr_raudio_init()
33 bzero((char *)&raudiofr
, sizeof(raudiofr
));
35 raudiofr
.fr_flags
= FR_INQUE
|FR_PASS
|FR_QUICK
|FR_KEEPSTATE
;
36 MUTEX_INIT(&raudiofr
.fr_lock
, "Real Audio proxy rule lock");
37 raudio_proxy_init
= 1;
43 void ippr_raudio_fini()
45 if (raudio_proxy_init
== 1) {
46 MUTEX_DESTROY(&raudiofr
.fr_lock
);
47 raudio_proxy_init
= 0;
53 * Setup for a new proxy to handle Real Audio.
55 int ippr_raudio_new(fin
, aps
, nat
)
62 KMALLOCS(aps
->aps_data
, void *, sizeof(raudio_t
));
63 if (aps
->aps_data
== NULL
)
69 bzero(aps
->aps_data
, sizeof(raudio_t
));
71 aps
->aps_psiz
= sizeof(raudio_t
);
72 rap
->rap_mode
= RAP_M_TCP
; /* default is for TCP */
78 int ippr_raudio_out(fin
, aps
, nat
)
83 raudio_t
*rap
= aps
->aps_data
;
84 unsigned char membuf
[512 + 1], *s
;
94 * If we've already processed the start messages, then nothing left
95 * for the proxy to do.
97 if (rap
->rap_eos
== 1)
101 tcp
= (tcphdr_t
*)fin
->fin_dp
;
102 off
= (char *)tcp
- (char *)fin
->fin_ip
;
103 off
+= (TCP_OFF(tcp
) << 2) + fin
->fin_ipoff
;
106 dlen
= fin
->fin_plen
- off
;
108 dlen
= MSGDSIZE(m
) - off
;
113 if (dlen
> sizeof(membuf
))
114 dlen
= sizeof(membuf
);
116 bzero((char *)membuf
, sizeof(membuf
));
117 COPYDATA(m
, off
, dlen
, (char *)membuf
);
119 * In all the startup parsing, ensure that we don't go outside
120 * the packet buffer boundary.
123 * Look for the start of connection "PNA" string if not seen yet.
125 if (rap
->rap_seenpna
== 0) {
126 s
= (u_char
*)memstr("PNA", (char *)membuf
, 3, dlen
);
130 rap
->rap_seenpna
= 1;
135 * Directly after the PNA will be the version number of this
138 if (rap
->rap_seenpna
== 1 && rap
->rap_seenver
== 0) {
139 if ((s
+ 1) - membuf
< dlen
) {
140 rap
->rap_version
= (*s
<< 8) | *(s
+ 1);
142 rap
->rap_seenver
= 1;
148 * Now that we've been past the PNA and version number, we're into the
149 * startup messages block. This ends when a message with an ID of 0.
151 while ((rap
->rap_eos
== 0) && ((s
+ 1) - membuf
< dlen
)) {
152 if (rap
->rap_gotid
== 0) {
153 id
= (*s
<< 8) | *(s
+ 1);
156 if (id
== RA_ID_END
) {
160 } else if (rap
->rap_gotlen
== 0) {
161 len
= (*s
<< 8) | *(s
+ 1);
166 if (rap
->rap_gotid
== 1 && rap
->rap_gotlen
== 1) {
167 if (id
== RA_ID_UDP
) {
168 rap
->rap_mode
&= ~RAP_M_TCP
;
169 rap
->rap_mode
|= RAP_M_UDP
;
170 rap
->rap_plport
= (*s
<< 8) | *(s
+ 1);
171 } else if (id
== RA_ID_ROBUST
) {
172 rap
->rap_mode
|= RAP_M_ROBUST
;
173 rap
->rap_prport
= (*s
<< 8) | *(s
+ 1);
184 int ippr_raudio_in(fin
, aps
, nat
)
189 unsigned char membuf
[IPF_MAXPORTLEN
+ 1], *s
;
190 tcphdr_t
*tcp
, tcph
, *tcp2
= &tcph
;
191 raudio_t
*rap
= aps
->aps_data
;
192 struct in_addr swa
, swb
;
204 * Wait until we've seen the end of the start messages and even then
205 * only proceed further if we're using UDP. If they want to use TCP
206 * then data is sent back on the same channel that is already open.
208 if (rap
->rap_sdone
!= 0)
212 tcp
= (tcphdr_t
*)fin
->fin_dp
;
213 off
= (char *)tcp
- (char *)fin
->fin_ip
;
214 off
+= (TCP_OFF(tcp
) << 2) + fin
->fin_ipoff
;
217 dlen
= fin
->fin_plen
- off
;
219 dlen
= MSGDSIZE(m
) - off
;
224 if (dlen
> sizeof(membuf
))
225 dlen
= sizeof(membuf
);
227 bzero((char *)membuf
, sizeof(membuf
));
228 COPYDATA(m
, off
, dlen
, (char *)membuf
);
230 seq
= ntohl(tcp
->th_seq
);
232 * Check to see if the data in this packet is of interest to us.
233 * We only care for the first 19 bytes coming back from the server.
235 if (rap
->rap_sseq
== 0) {
236 s
= (u_char
*)memstr("PNA", (char *)membuf
, 3, dlen
);
243 a2
= MIN(dlen
, sizeof(rap
->rap_svr
));
244 } else if (seq
<= rap
->rap_sseq
+ sizeof(rap
->rap_svr
)) {
246 * seq # which is the start of data and from that the offset
247 * into the buffer array.
249 a1
= seq
- rap
->rap_sseq
;
250 a2
= MIN(dlen
, sizeof(rap
->rap_svr
));
256 for (a3
= a1
, a4
= a2
; (a4
> 0) && (a3
< 19) && (a3
>= 0); a4
--,a3
++) {
257 rap
->rap_sbf
|= (1 << a3
);
258 rap
->rap_svr
[a3
] = *s
++;
261 if ((rap
->rap_sbf
!= 0x7ffff) || (!rap
->rap_eos
)) /* 19 bits */
265 s
= (u_char
*)rap
->rap_svr
+ 11;
266 if (((*s
<< 8) | *(s
+ 1)) == RA_ID_ROBUST
) {
268 rap
->rap_srport
= (*s
<< 8) | *(s
+ 1);
276 ip
->ip_p
= IPPROTO_UDP
;
277 ip
->ip_src
= nat
->nat_inip
;
278 ip
->ip_dst
= nat
->nat_oip
;
280 bcopy((char *)fin
, (char *)&fi
, sizeof(fi
));
281 bzero((char *)tcp2
, sizeof(*tcp2
));
283 fi
.fin_flx
|= FI_IGNORE
;
284 fi
.fin_dp
= (char *)tcp2
;
285 fi
.fin_fr
= &raudiofr
;
286 fi
.fin_dlen
= sizeof(*tcp2
);
287 fi
.fin_plen
= fi
.fin_hlen
+ sizeof(*tcp2
);
288 tcp2
->th_win
= htons(8192);
290 ip
->ip_len
= fin
->fin_hlen
+ sizeof(*tcp
);
292 if (((rap
->rap_mode
& RAP_M_UDP_ROBUST
) == RAP_M_UDP_ROBUST
) &&
293 (rap
->rap_srport
!= 0)) {
294 dp
= rap
->rap_srport
;
295 sp
= rap
->rap_prport
;
296 tcp2
->th_sport
= htons(sp
);
297 tcp2
->th_dport
= htons(dp
);
301 MUTEX_ENTER(&ipf_nat_new
);
302 nat2
= nat_new(&fi
, nat
->nat_ptr
, NULL
,
303 NAT_SLAVE
|IPN_UDP
| (sp
? 0 : SI_W_SPORT
),
305 MUTEX_EXIT(&ipf_nat_new
);
307 (void) nat_proto(&fi
, nat2
, IPN_UDP
);
308 MUTEX_ENTER(&nat2
->nat_lock
);
309 nat_update(&fi
, nat2
);
310 MUTEX_EXIT(&nat2
->nat_lock
);
312 (void) fr_addstate(&fi
, NULL
, (sp
? 0 : SI_W_SPORT
));
316 if ((rap
->rap_mode
& RAP_M_UDP
) == RAP_M_UDP
) {
317 sp
= rap
->rap_plport
;
318 tcp2
->th_sport
= htons(sp
);
319 tcp2
->th_dport
= 0; /* XXX - don't specify remote port */
323 MUTEX_ENTER(&ipf_nat_new
);
324 nat2
= nat_new(&fi
, nat
->nat_ptr
, NULL
,
325 NAT_SLAVE
|IPN_UDP
|SI_W_DPORT
,
327 MUTEX_EXIT(&ipf_nat_new
);
329 (void) nat_proto(&fi
, nat2
, IPN_UDP
);
330 MUTEX_ENTER(&nat2
->nat_lock
);
331 nat_update(&fi
, nat2
);
332 MUTEX_EXIT(&nat2
->nat_lock
);
334 (void) fr_addstate(&fi
, NULL
, SI_W_DPORT
);