|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Copyright (C) 1997 by Darren Reed.
24: *
25: * Redistribution and use in source and binary forms are permitted
26: * provided that this notice is preserved and due credit is given
27: * to the original author and the contributors.
28: */
29: #if !defined(lint)
30: #endif
31:
32: #if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL)
33: # define _KERNEL
34: #endif
35:
36: #if !defined(_KERNEL) && !defined(KERNEL)
37: # include <stdio.h>
38: # include <string.h>
39: # include <stdlib.h>
40: #endif
41: #include <sys/errno.h>
42: #include <sys/types.h>
43: #include <sys/param.h>
44: #include <sys/time.h>
45: #include <sys/file.h>
46: #if !defined(__FreeBSD__)
47: # include <sys/ioctl.h>
48: #endif
49: #include <sys/fcntl.h>
50: #include <sys/uio.h>
51: #ifndef linux
52: # include <sys/protosw.h>
53: #endif
54: #include <sys/socket.h>
55: #if defined(_KERNEL)
56: # if !defined(linux)
57: # include <sys/systm.h>
58: # else
59: # include <linux/string.h>
60: # endif
61: #endif
62: #if !defined(__SVR4) && !defined(__svr4__)
63: # ifndef linux
64: # include <sys/mbuf.h>
65: # endif
66: #else
67: # include <sys/byteorder.h>
68: # include <sys/dditypes.h>
69: # include <sys/stream.h>
70: # include <sys/kmem.h>
71: #endif
72: #if __FreeBSD__ > 2
73: # include <sys/queue.h>
74: # include <sys/malloc.h>
75: #endif
76: #include <net/if.h>
77: #ifdef sun
78: # include <net/af.h>
79: #endif
80: #include <net/route.h>
81: #include <netinet/in.h>
82: #include <netinet/in_systm.h>
83: #include <netinet/ip.h>
84: #ifndef linux
85: # include <netinet/ip_var.h>
86: #endif
87: #include <netinet/tcp.h>
88: #include <netinet/udp.h>
89: #include <netinet/ip_icmp.h>
90: #include "netinet/ip_compat.h"
91: #include <netinet/tcpip.h>
92: #include "netinet/ip_fil.h"
93: #include "netinet/ip_proxy.h"
94: #include "netinet/ip_nat.h"
95: #include "netinet/ip_state.h"
96:
97: #ifndef MIN
98: #define MIN(a,b) (((a)<(b))?(a):(b))
99: #endif
100:
101: static ap_session_t *ap_find __P((ip_t *, tcphdr_t *));
102: static ap_session_t *ap_new_session __P((aproxy_t *, ip_t *, tcphdr_t *,
103: fr_info_t *, nat_t *));
104:
105: static int ap_matchsrcdst __P((ap_session_t *aps, struct in_addr src,
106: struct in_addr dst, void *tcp, u_short sport,
107: u_short dport));
108:
109: #define AP_SESS_SIZE 53
110:
111: #if defined(_KERNEL) && !defined(linux)
112: #include "netinet/ip_ftp_pxy.c"
113: #endif
114:
115: ap_session_t *ap_sess_tab[AP_SESS_SIZE];
116: aproxy_t ap_proxies[] = {
117: #if IPF_FTP_PROXY
118: { "ftp", (char)IPPROTO_TCP, 0, 0, ippr_ftp_init, ippr_ftp_in, ippr_ftp_out },
119: #endif
120: { "", '\0', 0, 0, NULL, NULL }
121: };
122:
123:
124: int ap_ok(ip, tcp, nat)
125: ip_t *ip;
126: tcphdr_t *tcp;
127: ipnat_t *nat;
128: {
129: aproxy_t *apr = nat->in_apr;
130: u_short dport = nat->in_dport;
131:
132: if (!apr || (apr && (apr->apr_flags & APR_DELETE)) ||
133: (ip->ip_p != apr->apr_p))
134: return 0;
135: if ((tcp && (tcp->th_dport != dport)) || (!tcp && dport))
136: return 0;
137: return 1;
138: }
139:
140:
141: static int
142: ap_matchsrcdst(aps, src, dst, tcp, sport, dport)
143: ap_session_t *aps;
144: struct in_addr src, dst;
145: void *tcp;
146: u_short sport, dport;
147: {
148: if (aps->aps_dst.s_addr == dst.s_addr) {
149: if ((aps->aps_src.s_addr == src.s_addr) &&
150: (!tcp || (sport == aps->aps_sport) &&
151: (dport == aps->aps_dport)))
152: return 1;
153: } else if (aps->aps_dst.s_addr == src.s_addr) {
154: if ((aps->aps_src.s_addr == dst.s_addr) &&
155: (!tcp || (sport == aps->aps_dport) &&
156: (dport == aps->aps_sport)))
157: return 1;
158: }
159: return 0;
160: }
161:
162:
163: static ap_session_t *ap_find(ip, tcp)
164: ip_t *ip;
165: tcphdr_t *tcp;
166: {
167: register u_char p = ip->ip_p;
168: register ap_session_t *aps;
169: register u_short sp, dp;
170: register u_long hv;
171: struct in_addr src, dst;
172:
173: src = ip->ip_src, dst = ip->ip_dst;
174: sp = dp = 0; /* XXX gcc -Wunitialized */
175:
176: hv = ip->ip_src.s_addr ^ ip->ip_dst.s_addr;
177: hv *= 651733;
178: if (tcp) {
179: sp = tcp->th_sport;
180: dp = tcp->th_dport;
181: hv ^= (sp + dp);
182: hv *= 5;
183: }
184: hv %= AP_SESS_SIZE;
185:
186: for (aps = ap_sess_tab[hv]; aps; aps = aps->aps_next)
187: if ((aps->aps_p == p) &&
188: ap_matchsrcdst(aps, src, dst, tcp, sp, dp))
189: break;
190: return aps;
191: }
192:
193:
194: /*
195: * Allocate a new application proxy structure and fill it in with the
196: * relevant details. call the init function once complete, prior to
197: * returning.
198: */
199: static ap_session_t *ap_new_session(apr, ip, tcp, fin, nat)
200: aproxy_t *apr;
201: ip_t *ip;
202: tcphdr_t *tcp;
203: fr_info_t *fin;
204: nat_t *nat;
205: {
206: register ap_session_t *aps;
207: u_short dport;
208: u_long hv;
209:
210: if (!apr || (apr && (apr->apr_flags & APR_DELETE)) ||
211: (ip->ip_p != apr->apr_p))
212: return NULL;
213: dport = nat->nat_ptr->in_dport;
214: if ((tcp && (tcp->th_dport != dport)) || (!tcp && dport))
215: return NULL;
216:
217: hv = ip->ip_src.s_addr ^ ip->ip_dst.s_addr;
218: hv *= 651733;
219: if (tcp) {
220: hv ^= (tcp->th_sport + tcp->th_dport);
221: hv *= 5;
222: }
223: hv %= AP_SESS_SIZE;
224:
225: KMALLOC(aps, ap_session_t *, sizeof(*aps));
226: if (!aps)
227: return NULL;
228: bzero((char *)aps, sizeof(*aps));
229: aps->aps_apr = apr;
230: aps->aps_src = ip->ip_src;
231: aps->aps_dst = ip->ip_dst;
232: aps->aps_p = ip->ip_p;
233: aps->aps_tout = 1200; /* XXX */
234: if (tcp) {
235: aps->aps_sport = tcp->th_sport;
236: aps->aps_dport = tcp->th_dport;
237: }
238: aps->aps_data = NULL;
239: aps->aps_psiz = 0;
240: aps->aps_next = ap_sess_tab[hv];
241: ap_sess_tab[hv] = aps;
242: (void) (*apr->apr_init)(fin, ip, tcp, aps, nat);
243: return aps;
244: }
245:
246:
247: /*
248: * check to see if a packet should be passed through an active proxy routine
249: * if one has been setup for it.
250: */
251: int ap_check(ip, tcp, fin, nat)
252: ip_t *ip;
253: tcphdr_t *tcp;
254: fr_info_t *fin;
255: nat_t *nat;
256: {
257: ap_session_t *aps;
258: aproxy_t *apr;
259: int err;
260:
261: if (!(fin->fin_fi.fi_fl & FI_TCPUDP))
262: tcp = NULL;
263:
264: if ((aps = ap_find(ip, tcp)) ||
265: (aps = ap_new_session(nat->nat_ptr->in_apr, ip, tcp, fin, nat))) {
266: if (ip->ip_p == IPPROTO_TCP) {
267: /*
268: * verify that the checksum is correct. If not, then
269: * don't do anything with this packet.
270: */
271: if (tcp->th_sum != fr_tcpsum(*(mb_t **)fin->fin_mp,
272: ip, tcp, ip->ip_len)) {
273: frstats[fin->fin_out].fr_tcpbad++;
274: return -1;
275: }
276: fr_tcp_age(&aps->aps_tout, aps->aps_state, ip, fin,
277: tcp->th_sport == aps->aps_sport);
278: }
279:
280: apr = aps->aps_apr;
281: err = 0;
282: if (fin->fin_out) {
283: if (apr->apr_outpkt)
284: err = (*apr->apr_outpkt)(fin, ip, tcp,
285: aps, nat);
286: } else {
287: if (apr->apr_inpkt)
288: err = (*apr->apr_inpkt)(fin, ip, tcp,
289: aps, nat);
290: }
291: if (err == 2) {
292: tcp->th_sum = fr_tcpsum(*(mb_t **)fin->fin_mp, ip,
293: tcp, ip->ip_len);
294: err = 0;
295: }
296: return err;
297: }
298: return -1;
299: }
300:
301:
302: aproxy_t *ap_match(pr, name)
303: u_char pr;
304: char *name;
305: {
306: aproxy_t *ap;
307:
308: for (ap = ap_proxies; ap->apr_p; ap++)
309: if ((ap->apr_p == pr) &&
310: !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) {
311: ap->apr_ref++;
312: return ap;
313: }
314: return NULL;
315: }
316:
317:
318: void ap_free(ap)
319: aproxy_t *ap;
320: {
321: ap->apr_ref--;
322: }
323:
324:
325: void aps_free(aps)
326: ap_session_t *aps;
327: {
328: if (aps->aps_data && aps->aps_psiz)
329: KFREES(aps->aps_data, aps->aps_psiz);
330: KFREE(aps);
331: }
332:
333:
334: void ap_unload()
335: {
336: ap_session_t *aps;
337: int i;
338:
339: for (i = 0; i < AP_SESS_SIZE; i++)
340: while ((aps = ap_sess_tab[i])) {
341: ap_sess_tab[i] = aps->aps_next;
342: aps_free(aps);
343: }
344: }
345:
346:
347: void ap_expire()
348: {
349: ap_session_t *aps, **apsp;
350: int i;
351:
352: for (i = 0; i < AP_SESS_SIZE; i++)
353: for (apsp = &ap_sess_tab[i]; (aps = *apsp); ) {
354: aps->aps_tout--;
355: if (!aps->aps_tout) {
356: ap_sess_tab[i] = aps->aps_next;
357: aps_free(aps);
358: *apsp = aps->aps_next;
359: } else
360: apsp = &aps->aps_next;
361: }
362: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.