|
|
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.