|
|
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 & Guido van Rooij.
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:
30: #define __FreeBSD_version 300000 /* just a hack - no <sys/osreldate.h> */
31:
32: #if !defined(KERNEL)
33: # include <stdlib.h>
34: # include <string.h>
35: #endif
36: #include <sys/errno.h>
37: #include <sys/types.h>
38: #include <sys/param.h>
39: #include <sys/time.h>
40: #include <sys/file.h>
41: #if defined(KERNEL) && (__FreeBSD_version >= 220000)
42: # include <sys/filio.h>
43: # include <sys/fcntl.h>
44: #else
45: # include <sys/ioctl.h>
46: #endif
47: #include <sys/uio.h>
48: #ifndef linux
49: # include <sys/protosw.h>
50: #endif
51: #include <sys/socket.h>
52: #if defined(KERNEL)
53: # include <sys/systm.h>
54: #endif
55: #if !defined(__SVR4) && !defined(__svr4__)
56: # ifndef linux
57: # include <sys/mbuf.h>
58: # endif
59: #else
60: # include <sys/filio.h>
61: # include <sys/byteorder.h>
62: # include <sys/dditypes.h>
63: # include <sys/stream.h>
64: # include <sys/kmem.h>
65: #endif
66: #if defined(KERNEL) && (__FreeBSD_version >= 300000)
67: # include <sys/malloc.h>
68: #endif
69: #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(bsdi)
70: # include <kern/cpu_number.h>
71: #endif
72: #include <net/if.h>
73: #ifdef sun
74: #include <net/af.h>
75: #endif
76: #if !defined(KERNEL) && (__FreeBSD_version >= 300000)
77: # include <net/if_var.h>
78: #endif
79: #include <net/route.h>
80: #include <netinet/in.h>
81: #include <netinet/in_systm.h>
82: #include <netinet/ip.h>
83: #ifndef KERNEL
84: #define KERNEL
85: #define NOT_KERNEL
86: #endif
87: #ifndef linux
88: # include <netinet/ip_var.h>
89: #endif
90: #ifdef NOT_KERNEL
91: #undef KERNEL
92: #endif
93: #ifdef __sgi
94: # ifdef IFF_DRVRLOCK /* IRIX6 */
95: #include <sys/hashing.h>
96: # endif
97: #endif
98: #include <netinet/tcp.h>
99: #if defined(__sgi) && !defined(IFF_DRVRLOCK) /* IRIX < 6 */
100: extern struct ifqueue ipintrq; /* ip packet input queue */
101: #else
102: # ifndef linux
103: # include <netinet/in_var.h>
104: # include <netinet/tcp_fsm.h>
105: # endif
106: #endif
107: #include <netinet/udp.h>
108: #include <netinet/ip_icmp.h>
109: #include "netinet/ip_compat.h"
110: #include <netinet/tcpip.h>
111: #include "netinet/ip_fil.h"
112: #include "netinet/ip_auth.h"
113: #if !SOLARIS && !defined(linux)
114: # include <net/netisr.h>
115: # ifdef __FreeBSD__
116: # include <machine/cpufunc.h>
117: # endif
118: #endif
119:
120:
121: #if (SOLARIS || defined(__sgi)) && defined(_KERNEL)
122: extern kmutex_t ipf_auth;
123: # if SOLARIS
124: extern kcondvar_t ipfauthwait;
125: # endif
126: #endif
127: #ifdef linux
128: static struct wait_queue *ipfauthwait = NULL;
129: #endif
130:
131: int fr_authsize = FR_NUMAUTH;
132: int fr_authused = 0;
133: int fr_defaultauthage = 600;
134: fr_authstat_t fr_authstats;
135: static frauth_t fr_auth[FR_NUMAUTH];
136: mb_t *fr_authpkts[FR_NUMAUTH];
137: static int fr_authstart = 0, fr_authend = 0, fr_authnext = 0;
138: static frauthent_t *fae_list = NULL;
139: frentry_t *ipauth = NULL;
140:
141:
142: /*
143: * Check if a packet has authorization. If the packet is found to match an
144: * authorization result and that would result in a feedback loop (i.e. it
145: * will end up returning FR_AUTH) then return FR_BLOCK instead.
146: */
147: int fr_checkauth(ip, fin)
148: ip_t *ip;
149: fr_info_t *fin;
150: {
151: u_short id = ip->ip_id;
152: u_32_t pass;
153: int i;
154:
155: MUTEX_ENTER(&ipf_auth);
156: for (i = fr_authstart; i != fr_authend; ) {
157: /*
158: * index becomes -2 only after an SIOCAUTHW. Check this in
159: * case the same packet gets sent again and it hasn't yet been
160: * auth'd.
161: */
162: if ((fr_auth[i].fra_index == -2) &&
163: (id == fr_auth[i].fra_info.fin_id) &&
164: !bcmp((char *)fin,(char *)&fr_auth[i].fra_info,FI_CSIZE)) {
165: /*
166: * Avoid feedback loop.
167: */
168: if (!(pass = fr_auth[i].fra_pass) || (pass & FR_AUTH))
169: pass = FR_BLOCK;
170: fr_authstats.fas_hits++;
171: fr_auth[i].fra_index = -1;
172: fr_authused--;
173: if (i == fr_authstart) {
174: while (fr_auth[i].fra_index == -1) {
175: i++;
176: if (i == FR_NUMAUTH)
177: i = 0;
178: fr_authstart = i;
179: if (i == fr_authend)
180: break;
181: }
182: if (fr_authstart == fr_authend) {
183: fr_authnext = 0;
184: fr_authstart = fr_authend = 0;
185: }
186: }
187: MUTEX_EXIT(&ipf_auth);
188: return pass;
189: }
190: i++;
191: if (i == FR_NUMAUTH)
192: i = 0;
193: }
194: fr_authstats.fas_miss++;
195: MUTEX_EXIT(&ipf_auth);
196: return 0;
197: }
198:
199:
200: /*
201: * Check if we have room in the auth array to hold details for another packet.
202: * If we do, store it and wake up any user programs which are waiting to
203: * hear about these events.
204: */
205: int fr_newauth(m, fin, ip
206: #if defined(_KERNEL) && SOLARIS
207: , qif)
208: qif_t *qif;
209: #else
210: )
211: #endif
212: mb_t *m;
213: fr_info_t *fin;
214: ip_t *ip;
215: {
216: int i;
217:
218: MUTEX_ENTER(&ipf_auth);
219: if ((fr_authstart > fr_authend) && (fr_authstart - fr_authend == -1)) {
220: fr_authstats.fas_nospace++;
221: MUTEX_EXIT(&ipf_auth);
222: return 0;
223: }
224: if (fr_authend - fr_authstart == FR_NUMAUTH - 1) {
225: fr_authstats.fas_nospace++;
226: MUTEX_EXIT(&ipf_auth);
227: return 0;
228: }
229:
230: fr_authstats.fas_added++;
231: fr_authused++;
232: i = fr_authend++;
233: if (fr_authend == FR_NUMAUTH)
234: fr_authend = 0;
235: MUTEX_EXIT(&ipf_auth);
236: fr_auth[i].fra_index = i;
237: fr_auth[i].fra_pass = 0;
238: fr_auth[i].fra_age = fr_defaultauthage;
239: bcopy((char *)fin, (char *)&fr_auth[i].fra_info, sizeof(*fin));
240: #if !defined(sparc) && !defined(m68k)
241: /*
242: * No need to copyback here as we want to undo the changes, not keep
243: * them.
244: */
245: # if SOLARIS && defined(KERNEL)
246: if (ip == (ip_t *)m->b_rptr)
247: # endif
248: {
249: register u_short bo;
250:
251: bo = ip->ip_len;
252: ip->ip_len = htons(bo);
253: # if !SOLARIS /* 4.4BSD converts this ip_input.c, but I don't in solaris.c */
254: bo = ip->ip_id;
255: ip->ip_id = htons(bo);
256: # endif
257: bo = ip->ip_off;
258: ip->ip_off = htons(bo);
259: }
260: #endif
261: #if SOLARIS && defined(KERNEL)
262: m->b_rptr -= qif->qf_off;
263: fr_authpkts[i] = *(mblk_t **)fin->fin_mp;
264: fr_auth[i].fra_q = qif->qf_q;
265: cv_signal(&ipfauthwait);
266: #else
267: fr_authpkts[i] = m;
268: # if defined(linux) && defined(KERNEL)
269: wake_up_interruptible(&ipfauthwait);
270: # else
271: WAKEUP(&fr_authnext);
272: # endif
273: #endif
274: return 1;
275: }
276:
277:
278: int fr_auth_ioctl(data, cmd, fr, frptr)
279: caddr_t data;
280: #if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003)
281: u_long cmd;
282: #else
283: int cmd;
284: #endif
285: frentry_t *fr, **frptr;
286: {
287: mb_t *m;
288: #if defined(KERNEL)
289: # if !SOLARIS
290: struct ifqueue *ifq;
291: int s;
292: # endif
293: #endif
294: frauth_t auth, *au = &auth;
295: frauthent_t *fae, **faep;
296: int i, error = 0;
297:
298: switch (cmd)
299: {
300: case SIOCINIFR :
301: case SIOCRMIFR :
302: case SIOCADIFR :
303: error = EINVAL;
304: break;
305: case SIOCINAFR :
306: case SIOCRMAFR :
307: case SIOCADAFR :
308: for (faep = &fae_list; (fae = *faep); )
309: if (&fae->fae_fr == fr)
310: break;
311: else
312: faep = &fae->fae_next;
313: if (cmd == SIOCRMAFR) {
314: if (!fae)
315: error = ESRCH;
316: else {
317: *faep = fae->fae_next;
318: *frptr = fr->fr_next;
319: KFREE(fae);
320: }
321: } else {
322: KMALLOC(fae, frauthent_t *, sizeof(*fae));
323: if (fae != NULL) {
324: IRCOPY((char *)data, (char *)&fae->fae_fr,
325: sizeof(fae->fae_fr));
326: if (!fae->fae_age)
327: fae->fae_age = fr_defaultauthage;
328: fae->fae_fr.fr_hits = 0;
329: fae->fae_fr.fr_next = *frptr;
330: *frptr = &fae->fae_fr;
331: fae->fae_next = *faep;
332: *faep = fae;
333: } else
334: error = ENOMEM;
335: }
336: break;
337: case SIOCATHST:
338: IWCOPY((char *)&fr_authstats, data, sizeof(fr_authstats));
339: break;
340: case SIOCAUTHW:
341: fr_authioctlloop:
342: MUTEX_ENTER(&ipf_auth);
343: if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) {
344: IWCOPY((char *)&fr_auth[fr_authnext++], data,
345: sizeof(fr_info_t));
346: if (fr_authnext == FR_NUMAUTH)
347: fr_authnext = 0;
348: MUTEX_EXIT(&ipf_auth);
349: return 0;
350: }
351: #ifdef KERNEL
352: # if SOLARIS
353: if (!cv_wait_sig(&ipfauthwait, &ipf_auth)) {
354: mutex_exit(&ipf_auth);
355: return EINTR;
356: }
357: # else
358: # ifdef linux
359: interruptible_sleep_on(&ipfauthwait);
360: if (current->signal & ~current->blocked)
361: error = -EINTR;
362: # else
363: error = SLEEP(&fr_authnext, "fr_authnext");
364: # endif
365: # endif
366: #endif
367: MUTEX_EXIT(&ipf_auth);
368: if (!error)
369: goto fr_authioctlloop;
370: break;
371: case SIOCAUTHR:
372: IRCOPY(data, (caddr_t)&auth, sizeof(auth));
373: MUTEX_ENTER(&ipf_auth);
374: i = au->fra_index;
375: if ((i < 0) || (i > FR_NUMAUTH) ||
376: (fr_auth[i].fra_info.fin_id != au->fra_info.fin_id)) {
377: MUTEX_EXIT(&ipf_auth);
378: return EINVAL;
379: }
380: m = fr_authpkts[i];
381: fr_auth[i].fra_index = -2;
382: fr_auth[i].fra_pass = au->fra_pass;
383: fr_authpkts[i] = NULL;
384: #ifdef KERNEL
385: MUTEX_EXIT(&ipf_auth);
386: SPL_NET(s);
387: # ifndef linux
388: if (m && au->fra_info.fin_out) {
389: # if SOLARIS
390: error = fr_qout(fr_auth[i].fra_q, m);
391: # else /* SOLARIS */
392: error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL);
393: # endif /* SOLARIS */
394: if (error)
395: fr_authstats.fas_sendfail++;
396: else
397: fr_authstats.fas_sendok++;
398: } else if (m) {
399: # if SOLARIS
400: error = fr_qin(fr_auth[i].fra_q, m);
401: # else /* SOLARIS */
402: ifq = &ipintrq;
403: if (IF_QFULL(ifq)) {
404: IF_DROP(ifq);
405: m_freem(m);
406: error = ENOBUFS;
407: } else {
408: IF_ENQUEUE(ifq, m);
409: schednetisr(NETISR_IP);
410: }
411: # endif /* SOLARIS */
412: if (error)
413: fr_authstats.fas_quefail++;
414: else
415: fr_authstats.fas_queok++;
416: } else
417: error = EINVAL;
418: # endif
419: # if SOLARIS
420: if (error)
421: error = EINVAL;
422: # else
423: /*
424: * If we experience an error which will result in the packet
425: * not being processed, make sure we advance to the next one.
426: */
427: if (error == ENOBUFS) {
428: fr_authused--;
429: fr_auth[i].fra_index = -1;
430: fr_auth[i].fra_pass = 0;
431: if (i == fr_authstart) {
432: while (fr_auth[i].fra_index == -1) {
433: i++;
434: if (i == FR_NUMAUTH)
435: i = 0;
436: fr_authstart = i;
437: if (i == fr_authend)
438: break;
439: }
440: if (fr_authstart == fr_authend) {
441: fr_authnext = 0;
442: fr_authstart = fr_authend = 0;
443: }
444: }
445: }
446: # endif
447: SPL_X(s);
448: #endif /* KERNEL */
449: break;
450: default :
451: error = EINVAL;
452: break;
453: }
454: return error;
455: }
456:
457:
458: #ifdef KERNEL
459: /*
460: * Free all network buffer memory used to keep saved packets.
461: */
462: void fr_authunload()
463: {
464: register int i;
465: register frauthent_t *fae, **faep;
466: mb_t *m;
467:
468: MUTEX_ENTER(&ipf_auth);
469: for (i = 0; i < FR_NUMAUTH; i++) {
470: if ((m = fr_authpkts[i])) {
471: FREE_MB_T(m);
472: fr_authpkts[i] = NULL;
473: fr_auth[i].fra_index = -1;
474: }
475: }
476:
477:
478: for (faep = &fae_list; (fae = *faep); ) {
479: *faep = fae->fae_next;
480: KFREE(fae);
481: }
482: MUTEX_EXIT(&ipf_auth);
483: }
484:
485:
486: /*
487: * Slowly expire held auth records. Timeouts are set
488: * in expectation of this being called twice per second.
489: */
490: void fr_authexpire()
491: {
492: register int i;
493: register frauth_t *fra;
494: register frauthent_t *fae, **faep;
495: mb_t *m;
496: #if !SOLARIS
497: int s;
498: #endif
499:
500: SPL_NET(s);
501: MUTEX_ENTER(&ipf_auth);
502: for (i = 0, fra = fr_auth; i < FR_NUMAUTH; i++, fra++) {
503: if ((!--fra->fra_age) && (m = fr_authpkts[i])) {
504: FREE_MB_T(m);
505: fr_authpkts[i] = NULL;
506: fr_auth[i].fra_index = -1;
507: fr_authstats.fas_expire++;
508: fr_authused--;
509: }
510: }
511:
512: for (faep = &fae_list; (fae = *faep); ) {
513: if (!--fra->fra_age) {
514: *faep = fae->fae_next;
515: KFREE(fae);
516: fr_authstats.fas_expire++;
517: } else
518: faep = &fae->fae_next;
519: }
520: MUTEX_EXIT(&ipf_auth);
521: SPL_X(s);
522: }
523: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.