|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1993-1989 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /* ! 27: * Author: David B. Golub, Carnegie Mellon University ! 28: * Date: 3/98 ! 29: * ! 30: * Network IO. ! 31: * ! 32: * Packet filter code taken from vaxif/enet.c written ! 33: * CMU and Stanford. ! 34: */ ! 35: ! 36: /* ! 37: * Note: don't depend on anything in this file. ! 38: * It may change a lot real soon. -cmaeda 11 June 1993 ! 39: */ ! 40: ! 41: #include <norma_ether.h> ! 42: #include <mach_ttd.h> ! 43: ! 44: #include <sys/types.h> ! 45: #include <device/net_status.h> ! 46: #include <machine/machspl.h> /* spl definitions */ ! 47: #include <device/net_io.h> ! 48: #include <device/if_hdr.h> ! 49: #include <device/io_req.h> ! 50: #include <device/ds_routines.h> ! 51: ! 52: #include <mach/boolean.h> ! 53: #include <mach/vm_param.h> ! 54: ! 55: #include <ipc/ipc_port.h> ! 56: #include <ipc/ipc_kmsg.h> ! 57: #include <ipc/ipc_mqueue.h> ! 58: ! 59: #include <kern/counters.h> ! 60: #include <kern/lock.h> ! 61: #include <kern/queue.h> ! 62: #include <kern/sched_prim.h> ! 63: #include <kern/thread.h> ! 64: ! 65: #if NORMA_ETHER ! 66: #include <norma/ipc_ether.h> ! 67: #endif /*NORMA_ETHER*/ ! 68: ! 69: #include <machine/machspl.h> ! 70: ! 71: #if MACH_TTD ! 72: #include <ttd/ttd_stub.h> ! 73: #endif /* MACH_TTD */ ! 74: ! 75: #if MACH_TTD ! 76: int kttd_async_counter= 0; ! 77: #endif /* MACH_TTD */ ! 78: ! 79: ! 80: /* ! 81: * Packet Buffer Management ! 82: * ! 83: * This module manages a private pool of kmsg buffers. ! 84: */ ! 85: ! 86: /* ! 87: * List of net kmsgs queued to be sent to users. ! 88: * Messages can be high priority or low priority. ! 89: * The network thread processes high priority messages first. ! 90: */ ! 91: decl_simple_lock_data(,net_queue_lock) ! 92: boolean_t net_thread_awake = FALSE; ! 93: struct ipc_kmsg_queue net_queue_high; ! 94: int net_queue_high_size = 0; ! 95: int net_queue_high_max = 0; /* for debugging */ ! 96: struct ipc_kmsg_queue net_queue_low; ! 97: int net_queue_low_size = 0; ! 98: int net_queue_low_max = 0; /* for debugging */ ! 99: ! 100: /* ! 101: * List of net kmsgs that can be touched at interrupt level. ! 102: * If it is empty, we will also steal low priority messages. ! 103: */ ! 104: decl_simple_lock_data(,net_queue_free_lock) ! 105: struct ipc_kmsg_queue net_queue_free; ! 106: int net_queue_free_size = 0; /* on free list */ ! 107: int net_queue_free_max = 0; /* for debugging */ ! 108: ! 109: /* ! 110: * This value is critical to network performance. ! 111: * At least this many buffers should be sitting in net_queue_free. ! 112: * If this is set too small, we will drop network packets. ! 113: * Even a low drop rate (<1%) can cause severe network throughput problems. ! 114: * We add one to net_queue_free_min for every filter. ! 115: */ ! 116: int net_queue_free_min = 3; ! 117: ! 118: int net_queue_free_hits = 0; /* for debugging */ ! 119: int net_queue_free_steals = 0; /* for debugging */ ! 120: int net_queue_free_misses = 0; /* for debugging */ ! 121: ! 122: int net_kmsg_send_high_hits = 0; /* for debugging */ ! 123: int net_kmsg_send_low_hits = 0; /* for debugging */ ! 124: int net_kmsg_send_high_misses = 0; /* for debugging */ ! 125: int net_kmsg_send_low_misses = 0; /* for debugging */ ! 126: ! 127: int net_thread_awaken = 0; /* for debugging */ ! 128: int net_ast_taken = 0; /* for debugging */ ! 129: ! 130: decl_simple_lock_data(,net_kmsg_total_lock) ! 131: int net_kmsg_total = 0; /* total allocated */ ! 132: int net_kmsg_max; /* initialized below */ ! 133: ! 134: vm_size_t net_kmsg_size; /* initialized below */ ! 135: ! 136: /* ! 137: * We want more buffers when there aren't enough in the free queue ! 138: * and the low priority queue. However, we don't want to allocate ! 139: * more than net_kmsg_max. ! 140: */ ! 141: ! 142: #define net_kmsg_want_more() \ ! 143: (((net_queue_free_size + net_queue_low_size) < net_queue_free_min) && \ ! 144: (net_kmsg_total < net_kmsg_max)) ! 145: ! 146: ipc_kmsg_t ! 147: net_kmsg_get(void) ! 148: { ! 149: register ipc_kmsg_t kmsg; ! 150: spl_t s; ! 151: ! 152: /* ! 153: * First check the list of free buffers. ! 154: */ ! 155: s = splimp(); ! 156: simple_lock(&net_queue_free_lock); ! 157: kmsg = ipc_kmsg_queue_first(&net_queue_free); ! 158: if (kmsg != IKM_NULL) { ! 159: ipc_kmsg_rmqueue_first_macro(&net_queue_free, kmsg); ! 160: net_queue_free_size--; ! 161: net_queue_free_hits++; ! 162: } ! 163: simple_unlock(&net_queue_free_lock); ! 164: ! 165: if (kmsg == IKM_NULL) { ! 166: /* ! 167: * Try to steal from the low priority queue. ! 168: */ ! 169: simple_lock(&net_queue_lock); ! 170: kmsg = ipc_kmsg_queue_first(&net_queue_low); ! 171: if (kmsg != IKM_NULL) { ! 172: ipc_kmsg_rmqueue_first_macro(&net_queue_low, kmsg); ! 173: net_queue_low_size--; ! 174: net_queue_free_steals++; ! 175: } ! 176: simple_unlock(&net_queue_lock); ! 177: } ! 178: ! 179: if (kmsg == IKM_NULL) ! 180: net_queue_free_misses++; ! 181: (void) splx(s); ! 182: ! 183: if (net_kmsg_want_more() || (kmsg == IKM_NULL)) { ! 184: boolean_t awake; ! 185: ! 186: s = splimp(); ! 187: simple_lock(&net_queue_lock); ! 188: awake = net_thread_awake; ! 189: net_thread_awake = TRUE; ! 190: simple_unlock(&net_queue_lock); ! 191: (void) splx(s); ! 192: ! 193: if (!awake) ! 194: thread_wakeup((event_t) &net_thread_awake); ! 195: } ! 196: ! 197: return kmsg; ! 198: } ! 199: ! 200: void ! 201: net_kmsg_put(register ipc_kmsg_t kmsg) ! 202: { ! 203: spl_t s; ! 204: ! 205: s = splimp(); ! 206: simple_lock(&net_queue_free_lock); ! 207: ipc_kmsg_enqueue_macro(&net_queue_free, kmsg); ! 208: if (++net_queue_free_size > net_queue_free_max) ! 209: net_queue_free_max = net_queue_free_size; ! 210: simple_unlock(&net_queue_free_lock); ! 211: (void) splx(s); ! 212: } ! 213: ! 214: void ! 215: net_kmsg_collect(void) ! 216: { ! 217: register ipc_kmsg_t kmsg; ! 218: spl_t s; ! 219: ! 220: s = splimp(); ! 221: simple_lock(&net_queue_free_lock); ! 222: while (net_queue_free_size > net_queue_free_min) { ! 223: kmsg = ipc_kmsg_dequeue(&net_queue_free); ! 224: net_queue_free_size--; ! 225: simple_unlock(&net_queue_free_lock); ! 226: (void) splx(s); ! 227: ! 228: net_kmsg_free(kmsg); ! 229: simple_lock(&net_kmsg_total_lock); ! 230: net_kmsg_total--; ! 231: simple_unlock(&net_kmsg_total_lock); ! 232: ! 233: s = splimp(); ! 234: simple_lock(&net_queue_free_lock); ! 235: } ! 236: simple_unlock(&net_queue_free_lock); ! 237: (void) splx(s); ! 238: } ! 239: ! 240: void ! 241: net_kmsg_more(void) ! 242: { ! 243: register ipc_kmsg_t kmsg; ! 244: ! 245: /* ! 246: * Replenish net kmsg pool if low. We don't have the locks ! 247: * necessary to look at these variables, but that's OK because ! 248: * misread values aren't critical. The danger in this code is ! 249: * that while we allocate buffers, interrupts are happening ! 250: * which take buffers out of the free list. If we are not ! 251: * careful, we will sit in the loop and allocate a zillion ! 252: * buffers while a burst of packets arrives. So we count ! 253: * buffers in the low priority queue as available, because ! 254: * net_kmsg_get will make use of them, and we cap the total ! 255: * number of buffers we are willing to allocate. ! 256: */ ! 257: ! 258: while (net_kmsg_want_more()) { ! 259: simple_lock(&net_kmsg_total_lock); ! 260: net_kmsg_total++; ! 261: simple_unlock(&net_kmsg_total_lock); ! 262: kmsg = net_kmsg_alloc(); ! 263: net_kmsg_put(kmsg); ! 264: } ! 265: } ! 266: ! 267: /* ! 268: * Packet Filter Data Structures ! 269: * ! 270: * Each network interface has a set of packet filters ! 271: * that are run on incoming packets. ! 272: * ! 273: * Each packet filter may represent a single network ! 274: * session or multiple network sessions. For example, ! 275: * all application level TCP sessions would be represented ! 276: * by a single packet filter data structure. ! 277: * ! 278: * If a packet filter has a single session, we use a ! 279: * struct net_rcv_port to represent it. If the packet ! 280: * filter represents multiple sessions, we use a ! 281: * struct net_hash_header to represent it. ! 282: */ ! 283: ! 284: /* ! 285: * Each interface has a write port and a set of read ports. ! 286: * Each read port has one or more filters to determine what packets ! 287: * should go to that port. ! 288: */ ! 289: ! 290: /* ! 291: * Receive port for net, with packet filter. ! 292: * This data structure by itself represents a packet ! 293: * filter for a single session. ! 294: */ ! 295: struct net_rcv_port { ! 296: queue_chain_t chain; /* list of open_descriptors */ ! 297: ipc_port_t rcv_port; /* port to send packet to */ ! 298: int rcv_qlimit; /* port's qlimit */ ! 299: int rcv_count; /* number of packets received */ ! 300: int priority; /* priority for filter */ ! 301: filter_t *filter_end; /* pointer to end of filter */ ! 302: filter_t filter[NET_MAX_FILTER]; ! 303: /* filter operations */ ! 304: }; ! 305: typedef struct net_rcv_port *net_rcv_port_t; ! 306: ! 307: zone_t net_rcv_zone; /* zone of net_rcv_port structs */ ! 308: ! 309: ! 310: #define NET_HASH_SIZE 256 ! 311: #define N_NET_HASH 4 ! 312: #define N_NET_HASH_KEYS 4 ! 313: ! 314: unsigned int bpf_hash (int, unsigned int *); ! 315: ! 316: /* ! 317: * A single hash entry. ! 318: */ ! 319: struct net_hash_entry { ! 320: queue_chain_t chain; /* list of entries with same hval */ ! 321: #define he_next chain.next ! 322: #define he_prev chain.prev ! 323: ipc_port_t rcv_port; /* destination port */ ! 324: int rcv_qlimit; /* qlimit for the port */ ! 325: unsigned int keys[N_NET_HASH_KEYS]; ! 326: }; ! 327: typedef struct net_hash_entry *net_hash_entry_t; ! 328: ! 329: zone_t net_hash_entry_zone; ! 330: ! 331: /* ! 332: * This structure represents a packet filter with multiple sessions. ! 333: * ! 334: * For example, all application level TCP sessions might be ! 335: * represented by one of these structures. It looks like a ! 336: * net_rcv_port struct so that both types can live on the ! 337: * same packet filter queues. ! 338: */ ! 339: struct net_hash_header { ! 340: struct net_rcv_port rcv; ! 341: int n_keys; /* zero if not used */ ! 342: int ref_count; /* reference count */ ! 343: net_hash_entry_t table[NET_HASH_SIZE]; ! 344: } filter_hash_header[N_NET_HASH]; ! 345: ! 346: typedef struct net_hash_header *net_hash_header_t; ! 347: ! 348: decl_simple_lock_data(,net_hash_header_lock) ! 349: ! 350: #define HASH_ITERATE(head, elt) (elt) = (net_hash_entry_t) (head); do { ! 351: #define HASH_ITERATE_END(head, elt) \ ! 352: (elt) = (net_hash_entry_t) queue_next((queue_entry_t) (elt)); \ ! 353: } while ((elt) != (head)); ! 354: ! 355: ! 356: #define FILTER_ITERATE(ifp, fp, nextfp) \ ! 357: for ((fp) = (net_rcv_port_t) queue_first(&(ifp)->if_rcv_port_list);\ ! 358: !queue_end(&(ifp)->if_rcv_port_list, (queue_entry_t)(fp)); \ ! 359: (fp) = (nextfp)) { \ ! 360: (nextfp) = (net_rcv_port_t) queue_next(&(fp)->chain); ! 361: #define FILTER_ITERATE_END } ! 362: ! 363: /* entry_p must be net_rcv_port_t or net_hash_entry_t */ ! 364: #define ENQUEUE_DEAD(dead, entry_p) { \ ! 365: queue_next(&(entry_p)->chain) = (queue_entry_t) (dead); \ ! 366: (dead) = (queue_entry_t)(entry_p); \ ! 367: } ! 368: ! 369: extern boolean_t net_do_filter(); /* CSPF */ ! 370: extern int bpf_do_filter(); /* BPF */ ! 371: ! 372: ! 373: /* ! 374: * ethernet_priority: ! 375: * ! 376: * This function properly belongs in the ethernet interfaces; ! 377: * it should not be called by this module. (We get packet ! 378: * priorities as an argument to net_filter.) It is here ! 379: * to avoid massive code duplication. ! 380: * ! 381: * Returns TRUE for high-priority packets. ! 382: */ ! 383: ! 384: boolean_t ethernet_priority(kmsg) ! 385: ipc_kmsg_t kmsg; ! 386: { ! 387: register unsigned char *addr = ! 388: (unsigned char *) net_kmsg(kmsg)->header; ! 389: ! 390: /* ! 391: * A simplistic check for broadcast packets. ! 392: */ ! 393: ! 394: if ((addr[0] == 0xff) && (addr[1] == 0xff) && ! 395: (addr[2] == 0xff) && (addr[3] == 0xff) && ! 396: (addr[4] == 0xff) && (addr[5] == 0xff)) ! 397: return FALSE; ! 398: else ! 399: return TRUE; ! 400: } ! 401: ! 402: mach_msg_type_t header_type = { ! 403: MACH_MSG_TYPE_BYTE, ! 404: 8, ! 405: NET_HDW_HDR_MAX, ! 406: TRUE, ! 407: FALSE, ! 408: FALSE, ! 409: 0 ! 410: }; ! 411: ! 412: mach_msg_type_t packet_type = { ! 413: MACH_MSG_TYPE_BYTE, /* name */ ! 414: 8, /* size */ ! 415: 0, /* number */ ! 416: TRUE, /* inline */ ! 417: FALSE, /* longform */ ! 418: FALSE /* deallocate */ ! 419: }; ! 420: ! 421: /* ! 422: * net_deliver: ! 423: * ! 424: * Called and returns holding net_queue_lock, at splimp. ! 425: * Dequeues a message and delivers it at spl0. ! 426: * Returns FALSE if no messages. ! 427: */ ! 428: boolean_t net_deliver(nonblocking) ! 429: boolean_t nonblocking; ! 430: { ! 431: register ipc_kmsg_t kmsg; ! 432: boolean_t high_priority; ! 433: struct ipc_kmsg_queue send_list; ! 434: ! 435: /* ! 436: * Pick up a pending network message and deliver it. ! 437: * Deliver high priority messages before low priority. ! 438: */ ! 439: ! 440: if ((kmsg = ipc_kmsg_dequeue(&net_queue_high)) != IKM_NULL) { ! 441: net_queue_high_size--; ! 442: high_priority = TRUE; ! 443: } else if ((kmsg = ipc_kmsg_dequeue(&net_queue_low)) != IKM_NULL) { ! 444: net_queue_low_size--; ! 445: high_priority = FALSE; ! 446: } else ! 447: return FALSE; ! 448: simple_unlock(&net_queue_lock); ! 449: (void) spl0(); ! 450: ! 451: /* ! 452: * Run the packet through the filters, ! 453: * getting back a queue of packets to send. ! 454: */ ! 455: net_filter(kmsg, &send_list); ! 456: ! 457: if (!nonblocking) { ! 458: /* ! 459: * There is a danger of running out of available buffers ! 460: * because they all get moved into the high priority queue ! 461: * or a port queue. In particular, we might need to ! 462: * allocate more buffers as we pull (previously available) ! 463: * buffers out of the low priority queue. But we can only ! 464: * allocate if we are allowed to block. ! 465: */ ! 466: net_kmsg_more(); ! 467: } ! 468: ! 469: while ((kmsg = ipc_kmsg_dequeue(&send_list)) != IKM_NULL) { ! 470: int count; ! 471: ! 472: /* ! 473: * Fill in the rest of the kmsg. ! 474: */ ! 475: count = net_kmsg(kmsg)->net_rcv_msg_packet_count; ! 476: ! 477: ikm_init_special(kmsg, IKM_SIZE_NETWORK); ! 478: ! 479: kmsg->ikm_header.msgh_bits = ! 480: MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0); ! 481: /* remember message sizes must be rounded up */ ! 482: kmsg->ikm_header.msgh_size = ! 483: ((mach_msg_size_t) (sizeof(struct net_rcv_msg) ! 484: - NET_RCV_MAX + count))+3 &~ 3; ! 485: kmsg->ikm_header.msgh_local_port = MACH_PORT_NULL; ! 486: kmsg->ikm_header.msgh_kind = MACH_MSGH_KIND_NORMAL; ! 487: kmsg->ikm_header.msgh_id = NET_RCV_MSG_ID; ! 488: ! 489: net_kmsg(kmsg)->header_type = header_type; ! 490: net_kmsg(kmsg)->packet_type = packet_type; ! 491: net_kmsg(kmsg)->net_rcv_msg_packet_count = count; ! 492: ! 493: /* ! 494: * Send the packet to the destination port. Drop it ! 495: * if the destination port is over its backlog. ! 496: */ ! 497: ! 498: if (ipc_mqueue_send(kmsg, MACH_SEND_TIMEOUT, 0) == ! 499: MACH_MSG_SUCCESS) { ! 500: if (high_priority) ! 501: net_kmsg_send_high_hits++; ! 502: else ! 503: net_kmsg_send_low_hits++; ! 504: /* the receiver is responsible for the message now */ ! 505: } else { ! 506: if (high_priority) ! 507: net_kmsg_send_high_misses++; ! 508: else ! 509: net_kmsg_send_low_misses++; ! 510: ipc_kmsg_destroy(kmsg); ! 511: } ! 512: } ! 513: ! 514: (void) splimp(); ! 515: simple_lock(&net_queue_lock); ! 516: return TRUE; ! 517: } ! 518: ! 519: /* ! 520: * We want to deliver packets using ASTs, so we can avoid the ! 521: * thread_wakeup/thread_block needed to get to the network ! 522: * thread. However, we can't allocate memory in the AST handler, ! 523: * because memory allocation might block. Hence we have the ! 524: * network thread to allocate memory. The network thread also ! 525: * delivers packets, so it can be allocating and delivering for a ! 526: * burst. net_thread_awake is protected by net_queue_lock ! 527: * (instead of net_queue_free_lock) so that net_packet and ! 528: * net_ast can safely determine if the network thread is running. ! 529: * This prevents a race that might leave a packet sitting without ! 530: * being delivered. It is possible for net_kmsg_get to think ! 531: * the network thread is awake, and so avoid a wakeup, and then ! 532: * have the network thread sleep without allocating. The next ! 533: * net_kmsg_get will do a wakeup. ! 534: */ ! 535: ! 536: void net_ast() ! 537: { ! 538: spl_t s; ! 539: ! 540: net_ast_taken++; ! 541: ! 542: /* ! 543: * If the network thread is awake, then we would ! 544: * rather deliver messages from it, because ! 545: * it can also allocate memory. ! 546: */ ! 547: ! 548: s = splimp(); ! 549: simple_lock(&net_queue_lock); ! 550: while (!net_thread_awake && net_deliver(TRUE)) ! 551: continue; ! 552: ! 553: /* ! 554: * Prevent an unnecessary AST. Either the network ! 555: * thread will deliver the messages, or there are ! 556: * no messages left to deliver. ! 557: */ ! 558: ! 559: simple_unlock(&net_queue_lock); ! 560: (void) splsched(); ! 561: ast_off(cpu_number(), AST_NETWORK); ! 562: (void) splx(s); ! 563: } ! 564: ! 565: void net_thread_continue() ! 566: { ! 567: for (;;) { ! 568: spl_t s; ! 569: ! 570: net_thread_awaken++; ! 571: ! 572: /* ! 573: * First get more buffers. ! 574: */ ! 575: net_kmsg_more(); ! 576: ! 577: s = splimp(); ! 578: simple_lock(&net_queue_lock); ! 579: while (net_deliver(FALSE)) ! 580: continue; ! 581: ! 582: net_thread_awake = FALSE; ! 583: assert_wait(&net_thread_awake, FALSE); ! 584: simple_unlock(&net_queue_lock); ! 585: (void) splx(s); ! 586: counter(c_net_thread_block++); ! 587: thread_block(net_thread_continue); ! 588: } ! 589: } ! 590: ! 591: void net_thread() ! 592: { ! 593: spl_t s; ! 594: ! 595: /* ! 596: * We should be very high priority. ! 597: */ ! 598: ! 599: thread_set_own_priority(0); ! 600: ! 601: /* ! 602: * We sleep initially, so that we don't allocate any buffers ! 603: * unless the network is really in use and they are needed. ! 604: */ ! 605: ! 606: s = splimp(); ! 607: simple_lock(&net_queue_lock); ! 608: net_thread_awake = FALSE; ! 609: assert_wait(&net_thread_awake, FALSE); ! 610: simple_unlock(&net_queue_lock); ! 611: (void) splx(s); ! 612: counter(c_net_thread_block++); ! 613: thread_block(net_thread_continue); ! 614: net_thread_continue(); ! 615: /*NOTREACHED*/ ! 616: } ! 617: ! 618: void ! 619: reorder_queue(first, last) ! 620: register queue_t first, last; ! 621: { ! 622: register queue_entry_t prev, next; ! 623: ! 624: prev = first->prev; ! 625: next = last->next; ! 626: ! 627: prev->next = last; ! 628: next->prev = first; ! 629: ! 630: last->prev = prev; ! 631: last->next = first; ! 632: ! 633: first->next = next; ! 634: first->prev = last; ! 635: } ! 636: ! 637: /* ! 638: * Incoming packet. Header has already been moved to proper place. ! 639: * We are already at splimp. ! 640: */ ! 641: void ! 642: net_packet(ifp, kmsg, count, priority) ! 643: register struct ifnet *ifp; ! 644: register ipc_kmsg_t kmsg; ! 645: unsigned int count; ! 646: boolean_t priority; ! 647: { ! 648: boolean_t awake; ! 649: ! 650: #if NORMA_ETHER ! 651: if (netipc_net_packet(kmsg, count)) { ! 652: return; ! 653: } ! 654: #endif NORMA_ETHER ! 655: ! 656: #if MACH_TTD ! 657: /* ! 658: * Do a quick check to see if it is a kernel TTD packet. ! 659: * ! 660: * Only check if KernelTTD is enabled, ie. the current ! 661: * device driver supports TTD, and the bootp succeded. ! 662: */ ! 663: if (kttd_enabled && kttd_handle_async(kmsg)) { ! 664: /* ! 665: * Packet was a valid ttd packet and ! 666: * doesn't need to be passed up to filter. ! 667: * The ttd code put the used kmsg buffer ! 668: * back onto the free list. ! 669: */ ! 670: if (kttd_debug) ! 671: printf("**%x**", kttd_async_counter++); ! 672: return; ! 673: } ! 674: #endif /* MACH_TTD */ ! 675: ! 676: kmsg->ikm_header.msgh_remote_port = (mach_port_t) ifp; ! 677: net_kmsg(kmsg)->net_rcv_msg_packet_count = count; ! 678: ! 679: simple_lock(&net_queue_lock); ! 680: if (priority) { ! 681: ipc_kmsg_enqueue(&net_queue_high, kmsg); ! 682: if (++net_queue_high_size > net_queue_high_max) ! 683: net_queue_high_max = net_queue_high_size; ! 684: } else { ! 685: ipc_kmsg_enqueue(&net_queue_low, kmsg); ! 686: if (++net_queue_low_size > net_queue_low_max) ! 687: net_queue_low_max = net_queue_low_size; ! 688: } ! 689: /* ! 690: * If the network thread is awake, then we don't ! 691: * need to take an AST, because the thread will ! 692: * deliver the packet. ! 693: */ ! 694: awake = net_thread_awake; ! 695: simple_unlock(&net_queue_lock); ! 696: ! 697: if (!awake) { ! 698: spl_t s = splsched(); ! 699: ast_on(cpu_number(), AST_NETWORK); ! 700: (void) splx(s); ! 701: } ! 702: } ! 703: ! 704: int net_filter_queue_reorder = 0; /* non-zero to enable reordering */ ! 705: ! 706: /* ! 707: * Run a packet through the filters, returning a list of messages. ! 708: * We are *not* called at interrupt level. ! 709: */ ! 710: void ! 711: net_filter(kmsg, send_list) ! 712: register ipc_kmsg_t kmsg; ! 713: ipc_kmsg_queue_t send_list; ! 714: { ! 715: register struct ifnet *ifp; ! 716: register net_rcv_port_t infp, nextfp; ! 717: register ipc_kmsg_t new_kmsg; ! 718: ! 719: net_hash_entry_t entp, *hash_headp; ! 720: ipc_port_t dest; ! 721: queue_entry_t dead_infp = (queue_entry_t) 0; ! 722: queue_entry_t dead_entp = (queue_entry_t) 0; ! 723: unsigned int ret_count; ! 724: ! 725: int count = net_kmsg(kmsg)->net_rcv_msg_packet_count; ! 726: ifp = (struct ifnet *) kmsg->ikm_header.msgh_remote_port; ! 727: ipc_kmsg_queue_init(send_list); ! 728: ! 729: /* ! 730: * Unfortunately we can't allocate or deallocate memory ! 731: * while holding this lock. And we can't drop the lock ! 732: * while examining the filter list. ! 733: */ ! 734: simple_lock(&ifp->if_rcv_port_list_lock); ! 735: FILTER_ITERATE(ifp, infp, nextfp) ! 736: { ! 737: entp = (net_hash_entry_t) 0; ! 738: if (infp->filter[0] == NETF_BPF) { ! 739: ret_count = bpf_do_filter(infp, net_kmsg(kmsg)->packet, count, ! 740: net_kmsg(kmsg)->header, ! 741: &hash_headp, &entp); ! 742: if (entp == (net_hash_entry_t) 0) ! 743: dest = infp->rcv_port; ! 744: else ! 745: dest = entp->rcv_port; ! 746: } else { ! 747: ret_count = net_do_filter(infp, net_kmsg(kmsg)->packet, count, ! 748: net_kmsg(kmsg)->header); ! 749: if (ret_count) ! 750: ret_count = count; ! 751: dest = infp->rcv_port; ! 752: } ! 753: ! 754: if (ret_count) { ! 755: ! 756: /* ! 757: * Make a send right for the destination. ! 758: */ ! 759: ! 760: dest = ipc_port_copy_send(dest); ! 761: if (!IP_VALID(dest)) { ! 762: /* ! 763: * This filter is dead. We remove it from the ! 764: * filter list and set it aside for deallocation. ! 765: */ ! 766: ! 767: if (entp == (net_hash_entry_t) 0) { ! 768: queue_remove(&ifp->if_rcv_port_list, infp, ! 769: net_rcv_port_t, chain); ! 770: ENQUEUE_DEAD(dead_infp, infp); ! 771: continue; ! 772: } else { ! 773: hash_ent_remove (ifp, ! 774: (net_hash_header_t)infp, ! 775: FALSE, /* no longer used */ ! 776: hash_headp, ! 777: entp, ! 778: &dead_entp); ! 779: continue; ! 780: } ! 781: } ! 782: ! 783: /* ! 784: * Deliver copy of packet to this channel. ! 785: */ ! 786: if (ipc_kmsg_queue_empty(send_list)) { ! 787: /* ! 788: * Only receiver, so far ! 789: */ ! 790: new_kmsg = kmsg; ! 791: } else { ! 792: /* ! 793: * Other receivers - must allocate message and copy. ! 794: */ ! 795: new_kmsg = net_kmsg_get(); ! 796: if (new_kmsg == IKM_NULL) { ! 797: ipc_port_release_send(dest); ! 798: break; ! 799: } ! 800: ! 801: bcopy( ! 802: net_kmsg(kmsg)->packet, ! 803: net_kmsg(new_kmsg)->packet, ! 804: ret_count); ! 805: bcopy( ! 806: net_kmsg(kmsg)->header, ! 807: net_kmsg(new_kmsg)->header, ! 808: NET_HDW_HDR_MAX); ! 809: } ! 810: net_kmsg(new_kmsg)->net_rcv_msg_packet_count = ret_count; ! 811: new_kmsg->ikm_header.msgh_remote_port = (mach_port_t) dest; ! 812: ipc_kmsg_enqueue(send_list, new_kmsg); ! 813: ! 814: { ! 815: register net_rcv_port_t prevfp; ! 816: int rcount = ++infp->rcv_count; ! 817: ! 818: /* ! 819: * See if ordering of filters is wrong ! 820: */ ! 821: if (infp->priority >= NET_HI_PRI) { ! 822: prevfp = (net_rcv_port_t) queue_prev(&infp->chain); ! 823: /* ! 824: * If infp is not the first element on the queue, ! 825: * and the previous element is at equal priority ! 826: * but has a lower count, then promote infp to ! 827: * be in front of prevfp. ! 828: */ ! 829: if ((queue_t)prevfp != &ifp->if_rcv_port_list && ! 830: infp->priority == prevfp->priority) { ! 831: /* ! 832: * Threshold difference to prevent thrashing ! 833: */ ! 834: if (net_filter_queue_reorder ! 835: && (100 + prevfp->rcv_count < rcount)) ! 836: reorder_queue(&prevfp->chain, &infp->chain); ! 837: } ! 838: /* ! 839: * High-priority filter -> no more deliveries ! 840: */ ! 841: break; ! 842: } ! 843: } ! 844: } ! 845: } ! 846: FILTER_ITERATE_END ! 847: ! 848: simple_unlock(&ifp->if_rcv_port_list_lock); ! 849: ! 850: /* ! 851: * Deallocate dead filters. ! 852: */ ! 853: if (dead_infp != 0) ! 854: net_free_dead_infp(dead_infp); ! 855: if (dead_entp != 0) ! 856: net_free_dead_entp(dead_entp); ! 857: ! 858: if (ipc_kmsg_queue_empty(send_list)) { ! 859: /* Not sent - recycle */ ! 860: net_kmsg_put(kmsg); ! 861: } ! 862: } ! 863: ! 864: boolean_t ! 865: net_do_filter(infp, data, data_count, header) ! 866: net_rcv_port_t infp; ! 867: char * data; ! 868: unsigned int data_count; ! 869: char * header; ! 870: { ! 871: int stack[NET_FILTER_STACK_DEPTH+1]; ! 872: register int *sp; ! 873: register filter_t *fp, *fpe; ! 874: register unsigned int op, arg; ! 875: ! 876: /* ! 877: * The filter accesses the header and data ! 878: * as unsigned short words. ! 879: */ ! 880: data_count /= sizeof(unsigned short); ! 881: ! 882: #define data_word ((unsigned short *)data) ! 883: #define header_word ((unsigned short *)header) ! 884: ! 885: sp = &stack[NET_FILTER_STACK_DEPTH]; ! 886: fp = &infp->filter[0]; ! 887: fpe = infp->filter_end; ! 888: ! 889: *sp = TRUE; ! 890: ! 891: while (fp < fpe) { ! 892: arg = *fp++; ! 893: op = NETF_OP(arg); ! 894: arg = NETF_ARG(arg); ! 895: ! 896: switch (arg) { ! 897: case NETF_NOPUSH: ! 898: arg = *sp++; ! 899: break; ! 900: case NETF_PUSHZERO: ! 901: arg = 0; ! 902: break; ! 903: case NETF_PUSHLIT: ! 904: arg = *fp++; ! 905: break; ! 906: case NETF_PUSHIND: ! 907: arg = *sp++; ! 908: if (arg >= data_count) ! 909: return FALSE; ! 910: arg = data_word[arg]; ! 911: break; ! 912: case NETF_PUSHHDRIND: ! 913: arg = *sp++; ! 914: if (arg >= NET_HDW_HDR_MAX/sizeof(unsigned short)) ! 915: return FALSE; ! 916: arg = header_word[arg]; ! 917: break; ! 918: default: ! 919: if (arg >= NETF_PUSHSTK) { ! 920: arg = sp[arg - NETF_PUSHSTK]; ! 921: } ! 922: else if (arg >= NETF_PUSHHDR) { ! 923: arg = header_word[arg - NETF_PUSHHDR]; ! 924: } ! 925: else { ! 926: arg -= NETF_PUSHWORD; ! 927: if (arg >= data_count) ! 928: return FALSE; ! 929: arg = data_word[arg]; ! 930: } ! 931: break; ! 932: ! 933: } ! 934: switch (op) { ! 935: case NETF_OP(NETF_NOP): ! 936: *--sp = arg; ! 937: break; ! 938: case NETF_OP(NETF_AND): ! 939: *sp &= arg; ! 940: break; ! 941: case NETF_OP(NETF_OR): ! 942: *sp |= arg; ! 943: break; ! 944: case NETF_OP(NETF_XOR): ! 945: *sp ^= arg; ! 946: break; ! 947: case NETF_OP(NETF_EQ): ! 948: *sp = (*sp == arg); ! 949: break; ! 950: case NETF_OP(NETF_NEQ): ! 951: *sp = (*sp != arg); ! 952: break; ! 953: case NETF_OP(NETF_LT): ! 954: *sp = (*sp < arg); ! 955: break; ! 956: case NETF_OP(NETF_LE): ! 957: *sp = (*sp <= arg); ! 958: break; ! 959: case NETF_OP(NETF_GT): ! 960: *sp = (*sp > arg); ! 961: break; ! 962: case NETF_OP(NETF_GE): ! 963: *sp = (*sp >= arg); ! 964: break; ! 965: case NETF_OP(NETF_COR): ! 966: if (*sp++ == arg) ! 967: return (TRUE); ! 968: break; ! 969: case NETF_OP(NETF_CAND): ! 970: if (*sp++ != arg) ! 971: return (FALSE); ! 972: break; ! 973: case NETF_OP(NETF_CNOR): ! 974: if (*sp++ == arg) ! 975: return (FALSE); ! 976: break; ! 977: case NETF_OP(NETF_CNAND): ! 978: if (*sp++ != arg) ! 979: return (TRUE); ! 980: break; ! 981: case NETF_OP(NETF_LSH): ! 982: *sp <<= arg; ! 983: break; ! 984: case NETF_OP(NETF_RSH): ! 985: *sp >>= arg; ! 986: break; ! 987: case NETF_OP(NETF_ADD): ! 988: *sp += arg; ! 989: break; ! 990: case NETF_OP(NETF_SUB): ! 991: *sp -= arg; ! 992: break; ! 993: } ! 994: } ! 995: return ((*sp) ? TRUE : FALSE); ! 996: ! 997: #undef data_word ! 998: #undef header_word ! 999: } ! 1000: ! 1001: /* ! 1002: * Check filter for invalid operations or stack over/under-flow. ! 1003: */ ! 1004: boolean_t ! 1005: parse_net_filter(filter, count) ! 1006: register filter_t *filter; ! 1007: unsigned int count; ! 1008: { ! 1009: register int sp; ! 1010: register filter_t *fpe = &filter[count]; ! 1011: register filter_t op, arg; ! 1012: ! 1013: sp = NET_FILTER_STACK_DEPTH; ! 1014: ! 1015: for (; filter < fpe; filter++) { ! 1016: op = NETF_OP(*filter); ! 1017: arg = NETF_ARG(*filter); ! 1018: ! 1019: switch (arg) { ! 1020: case NETF_NOPUSH: ! 1021: break; ! 1022: case NETF_PUSHZERO: ! 1023: sp--; ! 1024: break; ! 1025: case NETF_PUSHLIT: ! 1026: filter++; ! 1027: if (filter >= fpe) ! 1028: return (FALSE); /* literal value not in filter */ ! 1029: sp--; ! 1030: break; ! 1031: case NETF_PUSHIND: ! 1032: case NETF_PUSHHDRIND: ! 1033: break; ! 1034: default: ! 1035: if (arg >= NETF_PUSHSTK) { ! 1036: if (arg - NETF_PUSHSTK + sp > NET_FILTER_STACK_DEPTH) ! 1037: return FALSE; ! 1038: } ! 1039: else if (arg >= NETF_PUSHHDR) { ! 1040: if (arg - NETF_PUSHHDR >= ! 1041: NET_HDW_HDR_MAX/sizeof(unsigned short)) ! 1042: return FALSE; ! 1043: } ! 1044: /* else... cannot check for packet bounds ! 1045: without packet */ ! 1046: sp--; ! 1047: break; ! 1048: } ! 1049: if (sp < 2) { ! 1050: return (FALSE); /* stack overflow */ ! 1051: } ! 1052: if (op == NETF_OP(NETF_NOP)) ! 1053: continue; ! 1054: ! 1055: /* ! 1056: * all non-NOP operators are binary. ! 1057: */ ! 1058: if (sp > NET_MAX_FILTER-2) ! 1059: return (FALSE); ! 1060: ! 1061: sp++; ! 1062: switch (op) { ! 1063: case NETF_OP(NETF_AND): ! 1064: case NETF_OP(NETF_OR): ! 1065: case NETF_OP(NETF_XOR): ! 1066: case NETF_OP(NETF_EQ): ! 1067: case NETF_OP(NETF_NEQ): ! 1068: case NETF_OP(NETF_LT): ! 1069: case NETF_OP(NETF_LE): ! 1070: case NETF_OP(NETF_GT): ! 1071: case NETF_OP(NETF_GE): ! 1072: case NETF_OP(NETF_COR): ! 1073: case NETF_OP(NETF_CAND): ! 1074: case NETF_OP(NETF_CNOR): ! 1075: case NETF_OP(NETF_CNAND): ! 1076: case NETF_OP(NETF_LSH): ! 1077: case NETF_OP(NETF_RSH): ! 1078: case NETF_OP(NETF_ADD): ! 1079: case NETF_OP(NETF_SUB): ! 1080: break; ! 1081: default: ! 1082: return (FALSE); ! 1083: } ! 1084: } ! 1085: return (TRUE); ! 1086: } ! 1087: ! 1088: /* ! 1089: * Set a filter for a network interface. ! 1090: * ! 1091: * We are given a naked send right for the rcv_port. ! 1092: * If we are successful, we must consume that right. ! 1093: */ ! 1094: io_return_t ! 1095: net_set_filter(ifp, rcv_port, priority, filter, filter_count) ! 1096: struct ifnet *ifp; ! 1097: ipc_port_t rcv_port; ! 1098: int priority; ! 1099: filter_t *filter; ! 1100: unsigned int filter_count; ! 1101: { ! 1102: int filter_bytes; ! 1103: bpf_insn_t match; ! 1104: register net_rcv_port_t infp, my_infp; ! 1105: net_rcv_port_t nextfp; ! 1106: net_hash_header_t hhp; ! 1107: register net_hash_entry_t entp, hash_entp; ! 1108: net_hash_entry_t *head, nextentp; ! 1109: queue_entry_t dead_infp, dead_entp; ! 1110: int i; ! 1111: int ret, is_new_infp; ! 1112: io_return_t rval; ! 1113: ! 1114: /* ! 1115: * Check the filter syntax. ! 1116: */ ! 1117: ! 1118: filter_bytes = CSPF_BYTES(filter_count); ! 1119: match = (bpf_insn_t) 0; ! 1120: ! 1121: if (filter_count > 0 && filter[0] == NETF_BPF) { ! 1122: ret = bpf_validate((bpf_insn_t)filter, filter_bytes, &match); ! 1123: if (!ret) ! 1124: return (D_INVALID_OPERATION); ! 1125: } else { ! 1126: if (!parse_net_filter(filter, filter_count)) ! 1127: return (D_INVALID_OPERATION); ! 1128: } ! 1129: ! 1130: rval = D_SUCCESS; /* default return value */ ! 1131: dead_infp = dead_entp = 0; ! 1132: ! 1133: if (match == (bpf_insn_t) 0) { ! 1134: /* ! 1135: * If there is no match instruction, we allocate ! 1136: * a normal packet filter structure. ! 1137: */ ! 1138: my_infp = (net_rcv_port_t) zalloc(net_rcv_zone); ! 1139: my_infp->rcv_port = rcv_port; ! 1140: is_new_infp = TRUE; ! 1141: } else { ! 1142: /* ! 1143: * If there is a match instruction, we assume there will ! 1144: * multiple session with a common substructure and allocate ! 1145: * a hash table to deal with them. ! 1146: */ ! 1147: my_infp = 0; ! 1148: hash_entp = (net_hash_entry_t) zalloc(net_hash_entry_zone); ! 1149: is_new_infp = FALSE; ! 1150: } ! 1151: ! 1152: /* ! 1153: * Look for an existing filter on the same reply port. ! 1154: * Look for filters with dead ports (for GC). ! 1155: * Look for a filter with the same code except KEY insns. ! 1156: */ ! 1157: ! 1158: simple_lock(&ifp->if_rcv_port_list_lock); ! 1159: ! 1160: FILTER_ITERATE(ifp, infp, nextfp) ! 1161: { ! 1162: if (infp->rcv_port == MACH_PORT_NULL) { ! 1163: if (match != 0 ! 1164: && infp->priority == priority ! 1165: && my_infp == 0 ! 1166: && (infp->filter_end - infp->filter) == filter_count ! 1167: && bpf_eq((bpf_insn_t)infp->filter, ! 1168: filter, filter_bytes)) ! 1169: { ! 1170: my_infp = infp; ! 1171: } ! 1172: ! 1173: for (i = 0; i < NET_HASH_SIZE; i++) { ! 1174: head = &((net_hash_header_t) infp)->table[i]; ! 1175: if (*head == 0) ! 1176: continue; ! 1177: ! 1178: /* ! 1179: * Check each hash entry to make sure the ! 1180: * destination port is still valid. Remove ! 1181: * any invalid entries. ! 1182: */ ! 1183: entp = *head; ! 1184: do { ! 1185: nextentp = (net_hash_entry_t) entp->he_next; ! 1186: ! 1187: /* checked without ! 1188: ip_lock(entp->rcv_port) */ ! 1189: if (entp->rcv_port == rcv_port ! 1190: || !IP_VALID(entp->rcv_port) ! 1191: || !ip_active(entp->rcv_port)) { ! 1192: ! 1193: ret = hash_ent_remove (ifp, ! 1194: (net_hash_header_t)infp, ! 1195: (my_infp == infp), ! 1196: head, ! 1197: entp, ! 1198: &dead_entp); ! 1199: if (ret) ! 1200: goto hash_loop_end; ! 1201: } ! 1202: ! 1203: entp = nextentp; ! 1204: /* While test checks head since hash_ent_remove ! 1205: might modify it. ! 1206: */ ! 1207: } while (*head != 0 && entp != *head); ! 1208: } ! 1209: hash_loop_end: ! 1210: ; ! 1211: ! 1212: } else if (infp->rcv_port == rcv_port ! 1213: || !IP_VALID(infp->rcv_port) ! 1214: || !ip_active(infp->rcv_port)) { ! 1215: /* Remove the old filter from list */ ! 1216: remqueue(&ifp->if_rcv_port_list, (queue_entry_t)infp); ! 1217: ENQUEUE_DEAD(dead_infp, infp); ! 1218: } ! 1219: } ! 1220: FILTER_ITERATE_END ! 1221: ! 1222: if (my_infp == 0) { ! 1223: /* Allocate a dummy infp */ ! 1224: simple_lock(&net_hash_header_lock); ! 1225: for (i = 0; i < N_NET_HASH; i++) { ! 1226: if (filter_hash_header[i].n_keys == 0) ! 1227: break; ! 1228: } ! 1229: if (i == N_NET_HASH) { ! 1230: simple_unlock(&net_hash_header_lock); ! 1231: simple_unlock(&ifp->if_rcv_port_list_lock); ! 1232: ! 1233: ipc_port_release_send(rcv_port); ! 1234: if (match != 0) ! 1235: zfree (net_hash_entry_zone, (vm_offset_t)hash_entp); ! 1236: ! 1237: rval = D_NO_MEMORY; ! 1238: goto clean_and_return; ! 1239: } ! 1240: ! 1241: hhp = &filter_hash_header[i]; ! 1242: hhp->n_keys = match->jt; ! 1243: simple_unlock(&net_hash_header_lock); ! 1244: ! 1245: hhp->ref_count = 0; ! 1246: for (i = 0; i < NET_HASH_SIZE; i++) ! 1247: hhp->table[i] = 0; ! 1248: ! 1249: my_infp = (net_rcv_port_t)hhp; ! 1250: my_infp->rcv_port = MACH_PORT_NULL; /* indication of dummy */ ! 1251: is_new_infp = TRUE; ! 1252: } ! 1253: ! 1254: if (is_new_infp) { ! 1255: my_infp->priority = priority; ! 1256: my_infp->rcv_count = 0; ! 1257: ! 1258: /* Copy filter program. */ ! 1259: bcopy ((vm_offset_t)filter, (vm_offset_t)my_infp->filter, ! 1260: filter_bytes); ! 1261: my_infp->filter_end = ! 1262: (filter_t *)((char *)my_infp->filter + filter_bytes); ! 1263: ! 1264: if (match == 0) { ! 1265: my_infp->rcv_qlimit = net_add_q_info(rcv_port); ! 1266: } else { ! 1267: my_infp->rcv_qlimit = 0; ! 1268: } ! 1269: ! 1270: /* Insert my_infp according to priority */ ! 1271: queue_iterate(&ifp->if_rcv_port_list, infp, net_rcv_port_t, chain) ! 1272: if (priority > infp->priority) ! 1273: break; ! 1274: enqueue_tail((queue_t)&infp->chain, (queue_entry_t)my_infp); ! 1275: } ! 1276: ! 1277: if (match != 0) ! 1278: { /* Insert to hash list */ ! 1279: net_hash_entry_t *p; ! 1280: int j; ! 1281: ! 1282: hash_entp->rcv_port = rcv_port; ! 1283: for (i = 0; i < match->jt; i++) /* match->jt is n_keys */ ! 1284: hash_entp->keys[i] = match[i+1].k; ! 1285: p = &((net_hash_header_t)my_infp)-> ! 1286: table[bpf_hash(match->jt, hash_entp->keys)]; ! 1287: ! 1288: /* Not checking for the same key values */ ! 1289: if (*p == 0) { ! 1290: queue_init ((queue_t) hash_entp); ! 1291: *p = hash_entp; ! 1292: } else { ! 1293: enqueue_tail((queue_t)*p, hash_entp); ! 1294: } ! 1295: ! 1296: ((net_hash_header_t)my_infp)->ref_count++; ! 1297: hash_entp->rcv_qlimit = net_add_q_info(rcv_port); ! 1298: ! 1299: } ! 1300: ! 1301: simple_unlock(&ifp->if_rcv_port_list_lock); ! 1302: ! 1303: clean_and_return: ! 1304: /* No locks are held at this point. */ ! 1305: ! 1306: if (dead_infp != 0) ! 1307: net_free_dead_infp(dead_infp); ! 1308: if (dead_entp != 0) ! 1309: net_free_dead_entp(dead_entp); ! 1310: ! 1311: return (rval); ! 1312: } ! 1313: ! 1314: /* ! 1315: * Other network operations ! 1316: */ ! 1317: io_return_t ! 1318: net_getstat(ifp, flavor, status, count) ! 1319: struct ifnet *ifp; ! 1320: dev_flavor_t flavor; ! 1321: dev_status_t status; /* pointer to OUT array */ ! 1322: natural_t *count; /* OUT */ ! 1323: { ! 1324: switch (flavor) { ! 1325: case NET_STATUS: ! 1326: { ! 1327: register struct net_status *ns = (struct net_status *)status; ! 1328: ! 1329: if (*count < NET_STATUS_COUNT) ! 1330: return (D_INVALID_OPERATION); ! 1331: ! 1332: ns->min_packet_size = ifp->if_header_size; ! 1333: ns->max_packet_size = ifp->if_header_size + ifp->if_mtu; ! 1334: ns->header_format = ifp->if_header_format; ! 1335: ns->header_size = ifp->if_header_size; ! 1336: ns->address_size = ifp->if_address_size; ! 1337: ns->flags = ifp->if_flags; ! 1338: ns->mapped_size = 0; ! 1339: ! 1340: *count = NET_STATUS_COUNT; ! 1341: break; ! 1342: } ! 1343: case NET_ADDRESS: ! 1344: { ! 1345: register int addr_byte_count; ! 1346: register int addr_int_count; ! 1347: register int i; ! 1348: ! 1349: addr_byte_count = ifp->if_address_size; ! 1350: addr_int_count = (addr_byte_count + (sizeof(int)-1)) ! 1351: / sizeof(int); ! 1352: ! 1353: if (*count < addr_int_count) ! 1354: { ! 1355: /* XXX debug hack. */ ! 1356: printf ("net_getstat: count: %d, addr_int_count: %d\n", ! 1357: *count, addr_int_count); ! 1358: return (D_INVALID_OPERATION); ! 1359: } ! 1360: ! 1361: bcopy((char *)ifp->if_address, ! 1362: (char *)status, ! 1363: (unsigned) addr_byte_count); ! 1364: if (addr_byte_count < addr_int_count * sizeof(int)) ! 1365: bzero((char *)status + addr_byte_count, ! 1366: (unsigned) (addr_int_count * sizeof(int) ! 1367: - addr_byte_count)); ! 1368: ! 1369: for (i = 0; i < addr_int_count; i++) { ! 1370: register int word; ! 1371: ! 1372: word = status[i]; ! 1373: status[i] = htonl(word); ! 1374: } ! 1375: *count = addr_int_count; ! 1376: break; ! 1377: } ! 1378: default: ! 1379: return (D_INVALID_OPERATION); ! 1380: } ! 1381: return (D_SUCCESS); ! 1382: } ! 1383: ! 1384: io_return_t ! 1385: net_write(ifp, start, ior) ! 1386: register struct ifnet *ifp; ! 1387: int (*start)(); ! 1388: io_req_t ior; ! 1389: { ! 1390: spl_t s; ! 1391: kern_return_t rc; ! 1392: boolean_t wait; ! 1393: ! 1394: /* ! 1395: * Reject the write if the interface is down. ! 1396: */ ! 1397: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) ! 1398: return (D_DEVICE_DOWN); ! 1399: ! 1400: /* ! 1401: * Reject the write if the packet is too large or too small. ! 1402: */ ! 1403: if (ior->io_count < ifp->if_header_size || ! 1404: ior->io_count > ifp->if_header_size + ifp->if_mtu) ! 1405: return (D_INVALID_SIZE); ! 1406: ! 1407: /* ! 1408: * Wire down the memory. ! 1409: */ ! 1410: ! 1411: rc = device_write_get(ior, &wait); ! 1412: if (rc != KERN_SUCCESS) ! 1413: return (rc); ! 1414: ! 1415: /* ! 1416: * Network interfaces can't cope with VM continuations. ! 1417: * If wait is set, just panic. ! 1418: */ ! 1419: if (wait) { ! 1420: panic("net_write: VM continuation"); ! 1421: } ! 1422: ! 1423: /* ! 1424: * Queue the packet on the output queue, and ! 1425: * start the device. ! 1426: */ ! 1427: s = splimp(); ! 1428: IF_ENQUEUE(&ifp->if_snd, ior); ! 1429: (*start)(ifp->if_unit); ! 1430: splx(s); ! 1431: ! 1432: return (D_IO_QUEUED); ! 1433: } ! 1434: ! 1435: #ifdef FIPC ! 1436: /* This gets called by nefoutput for dev_ops->d_port_death ... */ ! 1437: ! 1438: io_return_t ! 1439: net_fwrite(ifp, start, ior) ! 1440: register struct ifnet *ifp; ! 1441: int (*start)(); ! 1442: io_req_t ior; ! 1443: { ! 1444: spl_t s; ! 1445: kern_return_t rc; ! 1446: boolean_t wait; ! 1447: ! 1448: /* ! 1449: * Reject the write if the interface is down. ! 1450: */ ! 1451: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) ! 1452: return (D_DEVICE_DOWN); ! 1453: ! 1454: /* ! 1455: * Reject the write if the packet is too large or too small. ! 1456: */ ! 1457: if (ior->io_count < ifp->if_header_size || ! 1458: ior->io_count > ifp->if_header_size + ifp->if_mtu) ! 1459: return (D_INVALID_SIZE); ! 1460: ! 1461: /* ! 1462: * DON'T Wire down the memory. ! 1463: */ ! 1464: #if 0 ! 1465: rc = device_write_get(ior, &wait); ! 1466: if (rc != KERN_SUCCESS) ! 1467: return (rc); ! 1468: #endif ! 1469: /* ! 1470: * Network interfaces can't cope with VM continuations. ! 1471: * If wait is set, just panic. ! 1472: */ ! 1473: /* I'll have to figure out who was setting wait...*/ ! 1474: #if 0 ! 1475: if (wait) { ! 1476: panic("net_write: VM continuation"); ! 1477: } ! 1478: #endif ! 1479: /* ! 1480: * Queue the packet on the output queue, and ! 1481: * start the device. ! 1482: */ ! 1483: s = splimp(); ! 1484: IF_ENQUEUE(&ifp->if_snd, ior); ! 1485: (*start)(ifp->if_unit); ! 1486: splx(s); ! 1487: ! 1488: return (D_IO_QUEUED); ! 1489: } ! 1490: #endif /* FIPC */ ! 1491: ! 1492: /* ! 1493: * Initialize the whole package. ! 1494: */ ! 1495: void ! 1496: net_io_init() ! 1497: { ! 1498: register vm_size_t size; ! 1499: ! 1500: size = sizeof(struct net_rcv_port); ! 1501: net_rcv_zone = zinit(size, ! 1502: size * 1000, ! 1503: PAGE_SIZE, ! 1504: FALSE, ! 1505: "net_rcv_port"); ! 1506: ! 1507: size = sizeof(struct net_hash_entry); ! 1508: net_hash_entry_zone = zinit(size, ! 1509: size * 100, ! 1510: PAGE_SIZE, ! 1511: FALSE, ! 1512: "net_hash_entry"); ! 1513: ! 1514: size = ikm_plus_overhead(sizeof(struct net_rcv_msg)); ! 1515: net_kmsg_size = round_page(size); ! 1516: ! 1517: /* ! 1518: * net_kmsg_max caps the number of buffers ! 1519: * we are willing to allocate. By default, ! 1520: * we allow for net_queue_free_min plus ! 1521: * the queue limit for each filter. ! 1522: * (Added as the filters are added.) ! 1523: */ ! 1524: ! 1525: simple_lock_init(&net_kmsg_total_lock); ! 1526: if (net_kmsg_max == 0) ! 1527: net_kmsg_max = net_queue_free_min; ! 1528: ! 1529: simple_lock_init(&net_queue_free_lock); ! 1530: ipc_kmsg_queue_init(&net_queue_free); ! 1531: ! 1532: simple_lock_init(&net_queue_lock); ! 1533: ipc_kmsg_queue_init(&net_queue_high); ! 1534: ipc_kmsg_queue_init(&net_queue_low); ! 1535: ! 1536: simple_lock_init(&net_hash_header_lock); ! 1537: } ! 1538: ! 1539: ! 1540: /* ======== BPF: Berkeley Packet Filter ======== */ ! 1541: ! 1542: /*- ! 1543: * Copyright (c) 1990-1991 The Regents of the University of California. ! 1544: * All rights reserved. ! 1545: * ! 1546: * This code is derived from the Stanford/CMU enet packet filter, ! 1547: * (net/enet.c) distributed as part of 4.3BSD, and code contributed ! 1548: * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence ! 1549: * Berkeley Laboratory. ! 1550: * ! 1551: * Redistribution and use in source and binary forms, with or without ! 1552: * modification, are permitted provided that the following conditions ! 1553: * are met: ! 1554: * 1. Redistributions of source code must retain the above copyright ! 1555: * notice, this list of conditions and the following disclaimer. ! 1556: * 2. Redistributions in binary form must reproduce the above copyright ! 1557: * notice, this list of conditions and the following disclaimer in the ! 1558: * documentation and/or other materials provided with the distribution. ! 1559: * 3. All advertising materials mentioning features or use of this software ! 1560: * must display the following acknowledgement: ! 1561: * This product includes software developed by the University of ! 1562: * California, Berkeley and its contributors. ! 1563: * 4. Neither the name of the University nor the names of its contributors ! 1564: * may be used to endorse or promote products derived from this software ! 1565: * without specific prior written permission. ! 1566: * ! 1567: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 1568: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 1569: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 1570: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 1571: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 1572: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 1573: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 1574: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 1575: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 1576: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 1577: * SUCH DAMAGE. ! 1578: * ! 1579: * @(#)bpf.c 7.5 (Berkeley) 7/15/91 ! 1580: */ ! 1581: ! 1582: #if defined(sparc) || defined(mips) || defined(ibm032) || defined(alpha) ! 1583: #define BPF_ALIGN ! 1584: #endif ! 1585: ! 1586: #ifndef BPF_ALIGN ! 1587: #define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p)) ! 1588: #define EXTRACT_LONG(p) (ntohl(*(u_long *)p)) ! 1589: #else ! 1590: #define EXTRACT_SHORT(p)\ ! 1591: ((u_short)\ ! 1592: ((u_short)*((u_char *)p+0)<<8|\ ! 1593: (u_short)*((u_char *)p+1)<<0)) ! 1594: #define EXTRACT_LONG(p)\ ! 1595: ((u_long)*((u_char *)p+0)<<24|\ ! 1596: (u_long)*((u_char *)p+1)<<16|\ ! 1597: (u_long)*((u_char *)p+2)<<8|\ ! 1598: (u_long)*((u_char *)p+3)<<0) ! 1599: #endif ! 1600: ! 1601: /* ! 1602: * Execute the filter program starting at pc on the packet p ! 1603: * wirelen is the length of the original packet ! 1604: * buflen is the amount of data present ! 1605: */ ! 1606: ! 1607: int ! 1608: bpf_do_filter(infp, p, wirelen, header, hash_headpp, entpp) ! 1609: net_rcv_port_t infp; ! 1610: char * p; /* packet data */ ! 1611: unsigned int wirelen; /* data_count (in bytes) */ ! 1612: char * header; ! 1613: net_hash_entry_t **hash_headpp, *entpp; /* out */ ! 1614: { ! 1615: register bpf_insn_t pc, pc_end; ! 1616: register unsigned int buflen; ! 1617: ! 1618: register unsigned long A, X; ! 1619: register int k; ! 1620: long mem[BPF_MEMWORDS]; ! 1621: ! 1622: pc = ((bpf_insn_t) infp->filter) + 1; ! 1623: /* filter[0].code is BPF_BEGIN */ ! 1624: pc_end = (bpf_insn_t)infp->filter_end; ! 1625: buflen = NET_RCV_MAX; ! 1626: *entpp = 0; /* default */ ! 1627: ! 1628: #ifdef lint ! 1629: A = 0; ! 1630: X = 0; ! 1631: #endif ! 1632: for (; pc < pc_end; ++pc) { ! 1633: switch (pc->code) { ! 1634: ! 1635: default: ! 1636: #ifdef KERNEL ! 1637: return 0; ! 1638: #else ! 1639: abort(); ! 1640: #endif ! 1641: case BPF_RET|BPF_K: ! 1642: if (infp->rcv_port == MACH_PORT_NULL && ! 1643: *entpp == 0) { ! 1644: return 0; ! 1645: } ! 1646: return ((u_int)pc->k <= wirelen) ? ! 1647: pc->k : wirelen; ! 1648: ! 1649: case BPF_RET|BPF_A: ! 1650: if (infp->rcv_port == MACH_PORT_NULL && ! 1651: *entpp == 0) { ! 1652: return 0; ! 1653: } ! 1654: return ((u_int)A <= wirelen) ? ! 1655: A : wirelen; ! 1656: ! 1657: case BPF_RET|BPF_MATCH_IMM: ! 1658: if (bpf_match ((net_hash_header_t)infp, pc->jt, mem, ! 1659: hash_headpp, entpp)) { ! 1660: return ((u_int)pc->k <= wirelen) ? ! 1661: pc->k : wirelen; ! 1662: } ! 1663: return 0; ! 1664: ! 1665: case BPF_LD|BPF_W|BPF_ABS: ! 1666: k = pc->k; ! 1667: if ((u_int)k + sizeof(long) <= buflen) { ! 1668: #ifdef BPF_ALIGN ! 1669: if (((int)(p + k) & 3) != 0) ! 1670: A = EXTRACT_LONG(&p[k]); ! 1671: else ! 1672: #endif ! 1673: A = ntohl(*(long *)(p + k)); ! 1674: continue; ! 1675: } ! 1676: ! 1677: k -= BPF_DLBASE; ! 1678: if ((u_int)k + sizeof(long) <= NET_HDW_HDR_MAX) { ! 1679: #ifdef BPF_ALIGN ! 1680: if (((int)(header + k) & 3) != 0) ! 1681: A = EXTRACT_LONG(&header[k]); ! 1682: else ! 1683: #endif ! 1684: A = ntohl(*(long *)(header + k)); ! 1685: continue; ! 1686: } else { ! 1687: return 0; ! 1688: } ! 1689: ! 1690: case BPF_LD|BPF_H|BPF_ABS: ! 1691: k = pc->k; ! 1692: if ((u_int)k + sizeof(short) <= buflen) { ! 1693: A = EXTRACT_SHORT(&p[k]); ! 1694: continue; ! 1695: } ! 1696: ! 1697: k -= BPF_DLBASE; ! 1698: if ((u_int)k + sizeof(short) <= NET_HDW_HDR_MAX) { ! 1699: A = EXTRACT_SHORT(&header[k]); ! 1700: continue; ! 1701: } else { ! 1702: return 0; ! 1703: } ! 1704: ! 1705: case BPF_LD|BPF_B|BPF_ABS: ! 1706: k = pc->k; ! 1707: if ((u_int)k < buflen) { ! 1708: A = p[k]; ! 1709: continue; ! 1710: } ! 1711: ! 1712: k -= BPF_DLBASE; ! 1713: if ((u_int)k < NET_HDW_HDR_MAX) { ! 1714: A = header[k]; ! 1715: continue; ! 1716: } else { ! 1717: return 0; ! 1718: } ! 1719: ! 1720: case BPF_LD|BPF_W|BPF_LEN: ! 1721: A = wirelen; ! 1722: continue; ! 1723: ! 1724: case BPF_LDX|BPF_W|BPF_LEN: ! 1725: X = wirelen; ! 1726: continue; ! 1727: ! 1728: case BPF_LD|BPF_W|BPF_IND: ! 1729: k = X + pc->k; ! 1730: if (k + sizeof(long) > buflen) ! 1731: return 0; ! 1732: #ifdef BPF_ALIGN ! 1733: if (((int)(p + k) & 3) != 0) ! 1734: A = EXTRACT_LONG(&p[k]); ! 1735: else ! 1736: #endif ! 1737: A = ntohl(*(long *)(p + k)); ! 1738: continue; ! 1739: ! 1740: case BPF_LD|BPF_H|BPF_IND: ! 1741: k = X + pc->k; ! 1742: if (k + sizeof(short) > buflen) ! 1743: return 0; ! 1744: A = EXTRACT_SHORT(&p[k]); ! 1745: continue; ! 1746: ! 1747: case BPF_LD|BPF_B|BPF_IND: ! 1748: k = X + pc->k; ! 1749: if (k >= buflen) ! 1750: return 0; ! 1751: A = p[k]; ! 1752: continue; ! 1753: ! 1754: case BPF_LDX|BPF_MSH|BPF_B: ! 1755: k = pc->k; ! 1756: if (k >= buflen) ! 1757: return 0; ! 1758: X = (p[pc->k] & 0xf) << 2; ! 1759: continue; ! 1760: ! 1761: case BPF_LD|BPF_IMM: ! 1762: A = pc->k; ! 1763: continue; ! 1764: ! 1765: case BPF_LDX|BPF_IMM: ! 1766: X = pc->k; ! 1767: continue; ! 1768: ! 1769: case BPF_LD|BPF_MEM: ! 1770: A = mem[pc->k]; ! 1771: continue; ! 1772: ! 1773: case BPF_LDX|BPF_MEM: ! 1774: X = mem[pc->k]; ! 1775: continue; ! 1776: ! 1777: case BPF_ST: ! 1778: mem[pc->k] = A; ! 1779: continue; ! 1780: ! 1781: case BPF_STX: ! 1782: mem[pc->k] = X; ! 1783: continue; ! 1784: ! 1785: case BPF_JMP|BPF_JA: ! 1786: pc += pc->k; ! 1787: continue; ! 1788: ! 1789: case BPF_JMP|BPF_JGT|BPF_K: ! 1790: pc += (A > pc->k) ? pc->jt : pc->jf; ! 1791: continue; ! 1792: ! 1793: case BPF_JMP|BPF_JGE|BPF_K: ! 1794: pc += (A >= pc->k) ? pc->jt : pc->jf; ! 1795: continue; ! 1796: ! 1797: case BPF_JMP|BPF_JEQ|BPF_K: ! 1798: pc += (A == pc->k) ? pc->jt : pc->jf; ! 1799: continue; ! 1800: ! 1801: case BPF_JMP|BPF_JSET|BPF_K: ! 1802: pc += (A & pc->k) ? pc->jt : pc->jf; ! 1803: continue; ! 1804: ! 1805: case BPF_JMP|BPF_JGT|BPF_X: ! 1806: pc += (A > X) ? pc->jt : pc->jf; ! 1807: continue; ! 1808: ! 1809: case BPF_JMP|BPF_JGE|BPF_X: ! 1810: pc += (A >= X) ? pc->jt : pc->jf; ! 1811: continue; ! 1812: ! 1813: case BPF_JMP|BPF_JEQ|BPF_X: ! 1814: pc += (A == X) ? pc->jt : pc->jf; ! 1815: continue; ! 1816: ! 1817: case BPF_JMP|BPF_JSET|BPF_X: ! 1818: pc += (A & X) ? pc->jt : pc->jf; ! 1819: continue; ! 1820: ! 1821: case BPF_ALU|BPF_ADD|BPF_X: ! 1822: A += X; ! 1823: continue; ! 1824: ! 1825: case BPF_ALU|BPF_SUB|BPF_X: ! 1826: A -= X; ! 1827: continue; ! 1828: ! 1829: case BPF_ALU|BPF_MUL|BPF_X: ! 1830: A *= X; ! 1831: continue; ! 1832: ! 1833: case BPF_ALU|BPF_DIV|BPF_X: ! 1834: if (X == 0) ! 1835: return 0; ! 1836: A /= X; ! 1837: continue; ! 1838: ! 1839: case BPF_ALU|BPF_AND|BPF_X: ! 1840: A &= X; ! 1841: continue; ! 1842: ! 1843: case BPF_ALU|BPF_OR|BPF_X: ! 1844: A |= X; ! 1845: continue; ! 1846: ! 1847: case BPF_ALU|BPF_LSH|BPF_X: ! 1848: A <<= X; ! 1849: continue; ! 1850: ! 1851: case BPF_ALU|BPF_RSH|BPF_X: ! 1852: A >>= X; ! 1853: continue; ! 1854: ! 1855: case BPF_ALU|BPF_ADD|BPF_K: ! 1856: A += pc->k; ! 1857: continue; ! 1858: ! 1859: case BPF_ALU|BPF_SUB|BPF_K: ! 1860: A -= pc->k; ! 1861: continue; ! 1862: ! 1863: case BPF_ALU|BPF_MUL|BPF_K: ! 1864: A *= pc->k; ! 1865: continue; ! 1866: ! 1867: case BPF_ALU|BPF_DIV|BPF_K: ! 1868: A /= pc->k; ! 1869: continue; ! 1870: ! 1871: case BPF_ALU|BPF_AND|BPF_K: ! 1872: A &= pc->k; ! 1873: continue; ! 1874: ! 1875: case BPF_ALU|BPF_OR|BPF_K: ! 1876: A |= pc->k; ! 1877: continue; ! 1878: ! 1879: case BPF_ALU|BPF_LSH|BPF_K: ! 1880: A <<= pc->k; ! 1881: continue; ! 1882: ! 1883: case BPF_ALU|BPF_RSH|BPF_K: ! 1884: A >>= pc->k; ! 1885: continue; ! 1886: ! 1887: case BPF_ALU|BPF_NEG: ! 1888: A = -A; ! 1889: continue; ! 1890: ! 1891: case BPF_MISC|BPF_TAX: ! 1892: X = A; ! 1893: continue; ! 1894: ! 1895: case BPF_MISC|BPF_TXA: ! 1896: A = X; ! 1897: continue; ! 1898: } ! 1899: } ! 1900: ! 1901: return 0; ! 1902: } ! 1903: ! 1904: /* ! 1905: * Return 1 if the 'f' is a valid filter program without a MATCH ! 1906: * instruction. Return 2 if it is a valid filter program with a MATCH ! 1907: * instruction. Otherwise, return 0. ! 1908: * The constraints are that each jump be forward and to a valid ! 1909: * code. The code must terminate with either an accept or reject. ! 1910: * 'valid' is an array for use by the routine (it must be at least ! 1911: * 'len' bytes long). ! 1912: * ! 1913: * The kernel needs to be able to verify an application's filter code. ! 1914: * Otherwise, a bogus program could easily crash the system. ! 1915: */ ! 1916: int ! 1917: bpf_validate(f, bytes, match) ! 1918: bpf_insn_t f; ! 1919: int bytes; ! 1920: bpf_insn_t *match; ! 1921: { ! 1922: register int i, j, len; ! 1923: register bpf_insn_t p; ! 1924: ! 1925: len = BPF_BYTES2LEN(bytes); ! 1926: /* f[0].code is already checked to be BPF_BEGIN. So skip f[0]. */ ! 1927: ! 1928: for (i = 1; i < len; ++i) { ! 1929: /* ! 1930: * Check that that jumps are forward, and within ! 1931: * the code block. ! 1932: */ ! 1933: p = &f[i]; ! 1934: if (BPF_CLASS(p->code) == BPF_JMP) { ! 1935: register int from = i + 1; ! 1936: ! 1937: if (BPF_OP(p->code) == BPF_JA) { ! 1938: if (from + p->k >= len) ! 1939: return 0; ! 1940: } ! 1941: else if (from + p->jt >= len || from + p->jf >= len) ! 1942: return 0; ! 1943: } ! 1944: /* ! 1945: * Check that memory operations use valid addresses. ! 1946: */ ! 1947: if ((BPF_CLASS(p->code) == BPF_ST || ! 1948: (BPF_CLASS(p->code) == BPF_LD && ! 1949: (p->code & 0xe0) == BPF_MEM)) && ! 1950: (p->k >= BPF_MEMWORDS || p->k < 0)) ! 1951: return 0; ! 1952: /* ! 1953: * Check for constant division by 0. ! 1954: */ ! 1955: if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) ! 1956: return 0; ! 1957: /* ! 1958: * Check for match instruction. ! 1959: * Only one match instruction per filter is allowed. ! 1960: */ ! 1961: if (p->code == (BPF_RET|BPF_MATCH_IMM)) { ! 1962: if (*match != 0 || ! 1963: p->jt == 0 || ! 1964: p->jt > N_NET_HASH_KEYS) ! 1965: return 0; ! 1966: i += p->jt; /* skip keys */ ! 1967: if (i + 1 > len) ! 1968: return 0; ! 1969: ! 1970: for (j = 1; j <= p->jt; j++) { ! 1971: if (p[j].code != (BPF_MISC|BPF_KEY)) ! 1972: return 0; ! 1973: } ! 1974: ! 1975: *match = p; ! 1976: } ! 1977: } ! 1978: if (BPF_CLASS(f[len - 1].code) == BPF_RET) ! 1979: return ((*match == 0) ? 1 : 2); ! 1980: else ! 1981: return 0; ! 1982: } ! 1983: ! 1984: int ! 1985: bpf_eq (f1, f2, bytes) ! 1986: register bpf_insn_t f1, f2; ! 1987: register int bytes; ! 1988: { ! 1989: register int count; ! 1990: ! 1991: count = BPF_BYTES2LEN(bytes); ! 1992: for (; count--; f1++, f2++) { ! 1993: if (!BPF_INSN_EQ(f1, f2)) { ! 1994: if ( f1->code == (BPF_MISC|BPF_KEY) && ! 1995: f2->code == (BPF_MISC|BPF_KEY) ) ! 1996: continue; ! 1997: return FALSE; ! 1998: } ! 1999: }; ! 2000: return TRUE; ! 2001: } ! 2002: ! 2003: unsigned int ! 2004: bpf_hash (n, keys) ! 2005: register int n; ! 2006: register unsigned int *keys; ! 2007: { ! 2008: register unsigned int hval = 0; ! 2009: ! 2010: while (n--) { ! 2011: hval += *keys++; ! 2012: } ! 2013: return (hval % NET_HASH_SIZE); ! 2014: } ! 2015: ! 2016: ! 2017: int ! 2018: bpf_match (hash, n_keys, keys, hash_headpp, entpp) ! 2019: net_hash_header_t hash; ! 2020: register int n_keys; ! 2021: register unsigned int *keys; ! 2022: net_hash_entry_t **hash_headpp, *entpp; ! 2023: { ! 2024: register net_hash_entry_t head, entp; ! 2025: register int i; ! 2026: ! 2027: if (n_keys != hash->n_keys) ! 2028: return FALSE; ! 2029: ! 2030: *hash_headpp = &hash->table[bpf_hash(n_keys, keys)]; ! 2031: head = **hash_headpp; ! 2032: ! 2033: if (head == 0) ! 2034: return FALSE; ! 2035: ! 2036: HASH_ITERATE (head, entp) ! 2037: { ! 2038: for (i = 0; i < n_keys; i++) { ! 2039: if (keys[i] != entp->keys[i]) ! 2040: break; ! 2041: } ! 2042: if (i == n_keys) { ! 2043: *entpp = entp; ! 2044: return TRUE; ! 2045: } ! 2046: } ! 2047: HASH_ITERATE_END (head, entp) ! 2048: return FALSE; ! 2049: } ! 2050: ! 2051: ! 2052: /* ! 2053: * Removes a hash entry (ENTP) from its queue (HEAD). ! 2054: * If the reference count of filter (HP) becomes zero and not USED, ! 2055: * HP is removed from ifp->if_rcv_port_list and is freed. ! 2056: */ ! 2057: ! 2058: int ! 2059: hash_ent_remove (ifp, hp, used, head, entp, dead_p) ! 2060: struct ifnet *ifp; ! 2061: net_hash_header_t hp; ! 2062: int used; ! 2063: net_hash_entry_t *head, entp; ! 2064: queue_entry_t *dead_p; ! 2065: { ! 2066: hp->ref_count--; ! 2067: ! 2068: if (*head == entp) { ! 2069: ! 2070: if (queue_empty((queue_t) entp)) { ! 2071: *head = 0; ! 2072: ENQUEUE_DEAD(*dead_p, entp); ! 2073: if (hp->ref_count == 0 && !used) { ! 2074: remqueue((queue_t) &ifp->if_rcv_port_list, ! 2075: (queue_entry_t)hp); ! 2076: hp->n_keys = 0; ! 2077: return TRUE; ! 2078: } ! 2079: return FALSE; ! 2080: } else { ! 2081: *head = (net_hash_entry_t)queue_next((queue_t) entp); ! 2082: } ! 2083: } ! 2084: ! 2085: remqueue((queue_t)*head, (queue_entry_t)entp); ! 2086: ENQUEUE_DEAD(*dead_p, entp); ! 2087: return FALSE; ! 2088: } ! 2089: ! 2090: int ! 2091: net_add_q_info (rcv_port) ! 2092: ipc_port_t rcv_port; ! 2093: { ! 2094: mach_port_msgcount_t qlimit = 0; ! 2095: ! 2096: /* ! 2097: * We use a new port, so increase net_queue_free_min ! 2098: * and net_kmsg_max to allow for more queued messages. ! 2099: */ ! 2100: ! 2101: if (IP_VALID(rcv_port)) { ! 2102: ip_lock(rcv_port); ! 2103: if (ip_active(rcv_port)) ! 2104: qlimit = rcv_port->ip_qlimit; ! 2105: ip_unlock(rcv_port); ! 2106: } ! 2107: ! 2108: simple_lock(&net_kmsg_total_lock); ! 2109: net_queue_free_min++; ! 2110: net_kmsg_max += qlimit + 1; ! 2111: simple_unlock(&net_kmsg_total_lock); ! 2112: ! 2113: return (int)qlimit; ! 2114: } ! 2115: ! 2116: net_del_q_info (qlimit) ! 2117: int qlimit; ! 2118: { ! 2119: simple_lock(&net_kmsg_total_lock); ! 2120: net_queue_free_min--; ! 2121: net_kmsg_max -= qlimit + 1; ! 2122: simple_unlock(&net_kmsg_total_lock); ! 2123: } ! 2124: ! 2125: ! 2126: /* ! 2127: * net_free_dead_infp (dead_infp) ! 2128: * queue_entry_t dead_infp; list of dead net_rcv_port_t. ! 2129: * ! 2130: * Deallocates dead net_rcv_port_t. ! 2131: * No locks should be held when called. ! 2132: */ ! 2133: net_free_dead_infp (dead_infp) ! 2134: queue_entry_t dead_infp; ! 2135: { ! 2136: register net_rcv_port_t infp, nextfp; ! 2137: ! 2138: for (infp = (net_rcv_port_t) dead_infp; infp != 0; infp = nextfp) ! 2139: { ! 2140: nextfp = (net_rcv_port_t) queue_next(&infp->chain); ! 2141: ipc_port_release_send(infp->rcv_port); ! 2142: net_del_q_info(infp->rcv_qlimit); ! 2143: zfree(net_rcv_zone, (vm_offset_t) infp); ! 2144: } ! 2145: } ! 2146: ! 2147: /* ! 2148: * net_free_dead_entp (dead_entp) ! 2149: * queue_entry_t dead_entp; list of dead net_hash_entry_t. ! 2150: * ! 2151: * Deallocates dead net_hash_entry_t. ! 2152: * No locks should be held when called. ! 2153: */ ! 2154: net_free_dead_entp (dead_entp) ! 2155: queue_entry_t dead_entp; ! 2156: { ! 2157: register net_hash_entry_t entp, nextentp; ! 2158: ! 2159: for (entp = (net_hash_entry_t)dead_entp; entp != 0; entp = nextentp) ! 2160: { ! 2161: nextentp = (net_hash_entry_t) queue_next(&entp->chain); ! 2162: ! 2163: ipc_port_release_send(entp->rcv_port); ! 2164: net_del_q_info(entp->rcv_qlimit); ! 2165: zfree(net_hash_entry_zone, (vm_offset_t) entp); ! 2166: } ! 2167: } ! 2168:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.