4 * Copyright (C) 1998-2003 by Darren Reed
6 * See the IPFILTER.LICENCE file for details on licencing.
8 * Id: ip_rcmd_pxy.c,v 1.41.2.10 2008/11/06 21:18:36 darrenr Exp
10 * Simple RCMD transparent proxy for in-kernel use. For use with the NAT
14 #include <sys/cdefs.h>
15 __KERNEL_RCSID(1, "$NetBSD$");
17 #define IPF_RCMD_PROXY
20 int ippr_rcmd_init
__P((void));
21 void ippr_rcmd_fini
__P((void));
22 int ippr_rcmd_new
__P((fr_info_t
*, ap_session_t
*, nat_t
*));
23 int ippr_rcmd_out
__P((fr_info_t
*, ap_session_t
*, nat_t
*));
24 int ippr_rcmd_in
__P((fr_info_t
*, ap_session_t
*, nat_t
*));
25 u_short ipf_rcmd_atoi
__P((char *));
26 int ippr_rcmd_portmsg
__P((fr_info_t
*, ap_session_t
*, nat_t
*));
28 static frentry_t rcmdfr
;
30 int rcmd_proxy_init
= 0;
34 * RCMD application proxy initialization.
38 bzero((char *)&rcmdfr
, sizeof(rcmdfr
));
40 rcmdfr
.fr_flags
= FR_INQUE
|FR_PASS
|FR_QUICK
|FR_KEEPSTATE
;
41 MUTEX_INIT(&rcmdfr
.fr_lock
, "RCMD proxy rule lock");
50 if (rcmd_proxy_init
== 1) {
51 MUTEX_DESTROY(&rcmdfr
.fr_lock
);
58 * Setup for a new RCMD proxy.
60 int ippr_rcmd_new(fin
, aps
, nat
)
65 tcphdr_t
*tcp
= (tcphdr_t
*)fin
->fin_dp
;
70 aps
->aps_psiz
= sizeof(u_32_t
);
71 KMALLOCS(aps
->aps_data
, u_32_t
*, sizeof(u_32_t
));
72 if (aps
->aps_data
== NULL
) {
73 #ifdef IP_RCMD_PROXY_DEBUG
74 printf("ippr_rcmd_new:KMALLOCS(%d) failed\n", sizeof(u_32_t
));
78 *(u_32_t
*)aps
->aps_data
= 0;
79 aps
->aps_sport
= tcp
->th_sport
;
80 aps
->aps_dport
= tcp
->th_dport
;
86 * ipf_rcmd_atoi - implement a simple version of atoi
88 u_short
ipf_rcmd_atoi(ptr
)
91 register char *s
= ptr
, c
;
92 register u_short i
= 0;
94 while (((c
= *s
++) != '\0') && ISDIGIT(c
)) {
102 int ippr_rcmd_portmsg(fin
, aps
, nat
)
107 tcphdr_t
*tcp
, tcph
, *tcp2
= &tcph
;
108 struct in_addr swip
, swip2
;
109 int off
, dlen
, nflags
;
117 tcp
= (tcphdr_t
*)fin
->fin_dp
;
119 if (tcp
->th_flags
& TH_SYN
) {
120 *(u_32_t
*)aps
->aps_data
= htonl(ntohl(tcp
->th_seq
) + 1);
124 if ((*(u_32_t
*)aps
->aps_data
!= 0) &&
125 (tcp
->th_seq
!= *(u_32_t
*)aps
->aps_data
))
130 off
= (char *)tcp
- (char *)ip
+ (TCP_OFF(tcp
) << 2) + fin
->fin_ipoff
;
133 dlen
= fin
->fin_plen
- off
;
135 dlen
= MSGDSIZE(m
) - off
;
140 bzero(portbuf
, sizeof(portbuf
));
141 COPYDATA(m
, off
, MIN(sizeof(portbuf
), dlen
), portbuf
);
143 portbuf
[sizeof(portbuf
) - 1] = '\0';
145 sp
= ipf_rcmd_atoi(s
);
147 #ifdef IP_RCMD_PROXY_DEBUG
148 printf("ippr_rcmd_portmsg:sp == 0 dlen %d [%s]\n",
155 * Add skeleton NAT entry for connection which will come back the
158 bcopy((char *)fin
, (char *)&fi
, sizeof(fi
));
159 fi
.fin_flx
|= FI_IGNORE
;
162 if (nat
->nat_dir
== NAT_OUTBOUND
)
163 nat2
= nat_outlookup(&fi
, NAT_SEARCH
|IPN_TCP
, nat
->nat_p
,
164 nat
->nat_inip
, nat
->nat_oip
);
166 nat2
= nat_inlookup(&fi
, NAT_SEARCH
|IPN_TCP
, nat
->nat_p
,
167 nat
->nat_inip
, nat
->nat_oip
);
172 ip
->ip_len
= fin
->fin_hlen
+ sizeof(*tcp
);
173 bzero((char *)tcp2
, sizeof(*tcp2
));
174 tcp2
->th_win
= htons(8192);
175 tcp2
->th_sport
= htons(sp
);
176 tcp2
->th_dport
= 0; /* XXX - don't specify remote port */
178 tcp2
->th_flags
= TH_SYN
;
179 fi
.fin_dp
= (char *)tcp2
;
181 fi
.fin_dlen
= sizeof(*tcp2
);
182 fi
.fin_plen
= fi
.fin_hlen
+ sizeof(*tcp2
);
183 fi
.fin_flx
&= FI_LOWTTL
|FI_FRAG
|FI_TCPUDP
|FI_OPTIONS
|FI_IGNORE
;
184 nflags
= NAT_SLAVE
|IPN_TCP
|SI_W_DPORT
;
189 if (nat
->nat_dir
== NAT_OUTBOUND
) {
190 fi
.fin_fi
.fi_saddr
= nat
->nat_inip
.s_addr
;
191 ip
->ip_src
= nat
->nat_inip
;
193 fi
.fin_fi
.fi_saddr
= nat
->nat_oip
.s_addr
;
194 ip
->ip_src
= nat
->nat_oip
;
195 nflags
|= NAT_NOTRULEPORT
;
198 MUTEX_ENTER(&ipf_nat_new
);
199 nat2
= nat_new(&fi
, nat
->nat_ptr
, NULL
, nflags
, nat
->nat_dir
);
200 MUTEX_EXIT(&ipf_nat_new
);
203 (void) nat_proto(&fi
, nat2
, IPN_TCP
);
204 MUTEX_ENTER(&nat2
->nat_lock
);
205 nat_update(&fi
, nat2
);
206 MUTEX_EXIT(&nat2
->nat_lock
);
208 if (nat
->nat_dir
== NAT_INBOUND
) {
209 fi
.fin_fi
.fi_daddr
= nat
->nat_inip
.s_addr
;
210 ip
->ip_dst
= nat
->nat_inip
;
212 (void) fr_addstate(&fi
, NULL
, SI_W_DPORT
);
222 int ippr_rcmd_out(fin
, aps
, nat
)
227 if (nat
->nat_dir
== NAT_OUTBOUND
)
228 return ippr_rcmd_portmsg(fin
, aps
, nat
);
233 int ippr_rcmd_in(fin
, aps
, nat
)
238 if (nat
->nat_dir
== NAT_INBOUND
)
239 return ippr_rcmd_portmsg(fin
, aps
, nat
);