1 /* $NetBSD: ip_pptp_pxy.c,v 1.1.1.1.2.1 2004/08/13 03:55:49 jmc Exp $ */
2
3 /*
4 * Copyright (C) 2002-2003 by Darren Reed
5 *
6 * Simple PPTP transparent proxy for in-kernel use. For use with the NAT
7 * code.
8 *
9 * Id: ip_pptp_pxy.c,v 2.10.2.5 2004/06/07 14:20:05 darrenr Exp
10 *
11 */
12 #define IPF_PPTP_PROXY
13
14 typedef struct pptp_pxy {
15 ipnat_t pptp_rule;
16 nat_t *pptp_nat;
17 ipstate_t *pptp_state;
18 int pptp_seencookie;
19 u_32_t pptp_cookie;
20 } pptp_pxy_t;
21
22
23 int ippr_pptp_init __P((void));
24 void ippr_pptp_fini __P((void));
25 int ippr_pptp_new __P((fr_info_t *, ap_session_t *, nat_t *));
26 void ippr_pptp_del __P((ap_session_t *));
27 int ippr_pptp_inout __P((fr_info_t *, ap_session_t *, nat_t *));
28 int ippr_pptp_match __P((fr_info_t *, ap_session_t *, nat_t *));
29
30 static frentry_t pptpfr;
31
32 int pptp_proxy_init = 0;
33
34
35 /*
36 * PPTP application proxy initialization.
37 */
38 int ippr_pptp_init()
39 {
40 bzero((char *)&pptpfr, sizeof(pptpfr));
41 pptpfr.fr_ref = 1;
42 pptpfr.fr_flags = FR_OUTQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
43 MUTEX_INIT(&pptpfr.fr_lock, "PPTP proxy rule lock");
44 pptp_proxy_init = 1;
45
46 return 0;
47 }
48
49
50 void ippr_pptp_fini()
51 {
52 if (pptp_proxy_init == 1) {
53 MUTEX_DESTROY(&pptpfr.fr_lock);
54 pptp_proxy_init = 0;
55 }
56 }
57
58
59 /*
60 * Setup for a new PPTP proxy.
61 */
62 int ippr_pptp_new(fin, aps, nat)
63 fr_info_t *fin;
64 ap_session_t *aps;
65 nat_t *nat;
66 {
67 pptp_pxy_t *pptp;
68 fr_info_t fi;
69 ipnat_t *ipn;
70 nat_t *nat2;
71 int p, off;
72 ip_t *ip;
73
74 ip = fin->fin_ip;
75 off = fin->fin_hlen + sizeof(udphdr_t);
76
77 if (nat_outlookup(fin, 0, IPPROTO_GRE, nat->nat_inip,
78 ip->ip_dst) != NULL)
79 return -1;
80
81 aps->aps_psiz = sizeof(*pptp);
82 KMALLOCS(aps->aps_data, pptp_pxy_t *, sizeof(*pptp));
83 if (aps->aps_data == NULL)
84 return -1;
85
86 ip = fin->fin_ip;
87 pptp = aps->aps_data;
88 bzero((char *)pptp, sizeof(*pptp));
89
90 /*
91 * Create NAT rule against which the tunnel/transport mapping is
92 * created. This is required because the current NAT rule does not
93 * describe GRE but TCP instead.
94 */
95 ipn = &pptp->pptp_rule;
96 ipn->in_ifps[0] = fin->fin_ifp;
97 ipn->in_apr = NULL;
98 ipn->in_use = 1;
99 ipn->in_hits = 1;
100 ipn->in_nip = ntohl(nat->nat_outip.s_addr);
101 ipn->in_ippip = 1;
102 ipn->in_inip = nat->nat_inip.s_addr;
103 ipn->in_inmsk = 0xffffffff;
104 ipn->in_outip = fin->fin_saddr;
105 ipn->in_outmsk = nat->nat_outip.s_addr;
106 ipn->in_srcip = fin->fin_saddr;
107 ipn->in_srcmsk = 0xffffffff;
108 ipn->in_redir = NAT_MAP;
109 bcopy(nat->nat_ptr->in_ifnames[0], ipn->in_ifnames[0],
110 sizeof(ipn->in_ifnames[0]));
111 ipn->in_p = IPPROTO_GRE;
112
113 bcopy((char *)fin, (char *)&fi, sizeof(fi));
114 fi.fin_fi.fi_p = IPPROTO_GRE;
115 fi.fin_fr = &pptpfr;
116 fi.fin_data[0] = 0;
117 fi.fin_data[1] = 0;
118 p = ip->ip_p;
119 ip->ip_p = IPPROTO_GRE;
120 fi.fin_flx &= ~FI_TCPUDP;
121 fi.fin_flx |= FI_IGNORE;
122
123 nat2 = nat_new(&fi, ipn, &pptp->pptp_nat, 0, NAT_OUTBOUND);
124 pptp->pptp_nat = nat2;
125 if (nat2 != NULL) {
126 (void) nat_proto(&fi, nat2, 0);
127 nat_update(&fi, nat2, nat2->nat_ptr);
128
129 fi.fin_data[0] = 0;
130 fi.fin_data[1] = 0;
131 pptp->pptp_state = fr_addstate(&fi, &pptp->pptp_state, 0);
132 }
133 ip->ip_p = p;
134 return 0;
135 }
136
137
138 /*
139 * For outgoing PPTP packets. refresh timeouts for NAT & state entries, if
140 * we can. If they have disappeared, recreate them.
141 */
142 int ippr_pptp_inout(fin, aps, nat)
143 fr_info_t *fin;
144 ap_session_t *aps;
145 nat_t *nat;
146 {
147 pptp_pxy_t *pptp;
148 fr_info_t fi;
149 nat_t *nat2;
150 ip_t *ip;
151 int p;
152
153 if ((fin->fin_out == 1) && (nat->nat_dir == NAT_INBOUND))
154 return 0;
155
156 if ((fin->fin_out == 0) && (nat->nat_dir == NAT_OUTBOUND))
157 return 0;
158
159 pptp = aps->aps_data;
160
161 if (pptp != NULL) {
162 ip = fin->fin_ip;
163 p = ip->ip_p;
164
165 if ((pptp->pptp_nat == NULL) || (pptp->pptp_state == NULL)) {
166 bcopy((char *)fin, (char *)&fi, sizeof(fi));
167 fi.fin_fi.fi_p = IPPROTO_GRE;
168 fi.fin_fr = &pptpfr;
169 fi.fin_data[0] = 0;
170 fi.fin_data[1] = 0;
171 ip->ip_p = IPPROTO_GRE;
172 fi.fin_flx &= ~FI_TCPUDP;
173 fi.fin_flx |= FI_IGNORE;
174 }
175
176 /*
177 * Update NAT timeout/create NAT if missing.
178 */
179 if (pptp->pptp_nat != NULL)
180 fr_queueback(&pptp->pptp_nat->nat_tqe);
181 else {
182 nat2 = nat_new(&fi, &pptp->pptp_rule, &pptp->pptp_nat,
183 NAT_SLAVE, nat->nat_dir);
184 pptp->pptp_nat = nat2;
185 if (nat2 != NULL) {
186 (void) nat_proto(&fi, nat2, 0);
187 nat_update(&fi, nat2, nat2->nat_ptr);
188 }
189 }
190
191 /*
192 * Update state timeout/create state if missing.
193 */
194 READ_ENTER(&ipf_state);
195 if (pptp->pptp_state != NULL) {
196 fr_queueback(&pptp->pptp_state->is_sti);
197 RWLOCK_EXIT(&ipf_state);
198 } else {
199 RWLOCK_EXIT(&ipf_state);
200 fi.fin_data[0] = 0;
201 fi.fin_data[1] = 0;
202 pptp->pptp_state = fr_addstate(&fi, &pptp->pptp_state,
203 0);
204 }
205 ip->ip_p = p;
206 }
207 return 0;
208 }
209
210
211 /*
212 * clean up after ourselves.
213 */
214 void ippr_pptp_del(aps)
215 ap_session_t *aps;
216 {
217 pptp_pxy_t *pptp;
218
219 pptp = aps->aps_data;
220
221 if (pptp != NULL) {
222 /*
223 * Don't bother changing any of the NAT structure details,
224 * *_del() is on a callback from aps_free(), from nat_delete()
225 */
226
227 READ_ENTER(&ipf_state);
228 if (pptp->pptp_state != NULL) {
229 pptp->pptp_state->is_die = fr_ticks + 1;
230 pptp->pptp_state->is_me = NULL;
231 fr_queuefront(&pptp->pptp_state->is_sti);
232 }
233 RWLOCK_EXIT(&ipf_state);
234
235 pptp->pptp_state = NULL;
236 pptp->pptp_nat = NULL;
237 }
238 }
239
240
241 int ippr_pptp_match(fin, aps, nat)
242 fr_info_t *fin;
243 ap_session_t *aps;
244 nat_t *nat;
245 {
246 pptp_pxy_t *pptp;
247 tcphdr_t *tcp;
248 u_32_t cookie;
249
250 pptp = aps->aps_data;
251 tcp = fin->fin_dp;
252
253 if ((pptp != NULL) && (fin->fin_dlen - (TCP_OFF(tcp) << 2) >= 8)) {
254 u_char *cs;
255
256 cs = (u_char *)tcp + (TCP_OFF(tcp) << 2) + 4;
257
258 if (pptp->pptp_seencookie == 0) {
259 pptp->pptp_seencookie = 1;
260 pptp->pptp_cookie = (cs[0] << 24) | (cs[1] << 16) |
261 (cs[2] << 8) | cs[3];
262 } else {
263 cookie = (cs[0] << 24) | (cs[1] << 16) |
264 (cs[2] << 8) | cs[3];
265 if (cookie != pptp->pptp_cookie)
266 return -1;
267 }
268
269 }
270 return 0;
271 }
Cache object: 4dbfe7ac28f0b0d8f9dd1a1c29fb1e20
|