|
|
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: * Initialize send and receive queues on an interface. ! 639: */ ! 640: void if_init_queues(ifp) ! 641: register struct ifnet *ifp; ! 642: { ! 643: #if 0 ! 644: IFQ_INIT(&ifp->if_snd); ! 645: #endif ! 646: queue_init(&ifp->if_rcv_port_list); ! 647: simple_lock_init(&ifp->if_rcv_port_list_lock); ! 648: } ! 649: ! 650: ! 651: /* ! 652: * Incoming packet. Header has already been moved to proper place. ! 653: * We are already at splimp. ! 654: */ ! 655: void ! 656: net_packet(ifp, kmsg, count, priority) ! 657: register struct ifnet *ifp; ! 658: register ipc_kmsg_t kmsg; ! 659: unsigned int count; ! 660: boolean_t priority; ! 661: { ! 662: boolean_t awake; ! 663: ! 664: #if NORMA_ETHER ! 665: if (netipc_net_packet(kmsg, count)) { ! 666: return; ! 667: } ! 668: #endif /* NORMA_ETHER */ ! 669: ! 670: #if MACH_TTD ! 671: /* ! 672: * Do a quick check to see if it is a kernel TTD packet. ! 673: * ! 674: * Only check if KernelTTD is enabled, ie. the current ! 675: * device driver supports TTD, and the bootp succeded. ! 676: */ ! 677: if (kttd_enabled && kttd_handle_async(kmsg)) { ! 678: /* ! 679: * Packet was a valid ttd packet and ! 680: * doesn't need to be passed up to filter. ! 681: * The ttd code put the used kmsg buffer ! 682: * back onto the free list. ! 683: */ ! 684: if (kttd_debug) ! 685: printf("**%x**", kttd_async_counter++); ! 686: return; ! 687: } ! 688: #endif /* MACH_TTD */ ! 689: ! 690: kmsg->ikm_header.msgh_remote_port = (mach_port_t) ifp; ! 691: net_kmsg(kmsg)->net_rcv_msg_packet_count = count; ! 692: ! 693: simple_lock(&net_queue_lock); ! 694: if (priority) { ! 695: ipc_kmsg_enqueue(&net_queue_high, kmsg); ! 696: if (++net_queue_high_size > net_queue_high_max) ! 697: net_queue_high_max = net_queue_high_size; ! 698: } else { ! 699: ipc_kmsg_enqueue(&net_queue_low, kmsg); ! 700: if (++net_queue_low_size > net_queue_low_max) ! 701: net_queue_low_max = net_queue_low_size; ! 702: } ! 703: /* ! 704: * If the network thread is awake, then we don't ! 705: * need to take an AST, because the thread will ! 706: * deliver the packet. ! 707: */ ! 708: awake = net_thread_awake; ! 709: simple_unlock(&net_queue_lock); ! 710: ! 711: if (!awake) { ! 712: spl_t s = splsched(); ! 713: ast_on(cpu_number(), AST_NETWORK); ! 714: (void) splx(s); ! 715: } ! 716: } ! 717: ! 718: int net_filter_queue_reorder = 0; /* non-zero to enable reordering */ ! 719: ! 720: /* ! 721: * Run a packet through the filters, returning a list of messages. ! 722: * We are *not* called at interrupt level. ! 723: */ ! 724: void ! 725: net_filter(kmsg, send_list) ! 726: register ipc_kmsg_t kmsg; ! 727: ipc_kmsg_queue_t send_list; ! 728: { ! 729: register struct ifnet *ifp; ! 730: register net_rcv_port_t infp, nextfp; ! 731: register ipc_kmsg_t new_kmsg; ! 732: ! 733: net_hash_entry_t entp, *hash_headp; ! 734: ipc_port_t dest; ! 735: queue_entry_t dead_infp = (queue_entry_t) 0; ! 736: queue_entry_t dead_entp = (queue_entry_t) 0; ! 737: unsigned int ret_count; ! 738: ! 739: int count = net_kmsg(kmsg)->net_rcv_msg_packet_count; ! 740: ifp = (struct ifnet *) kmsg->ikm_header.msgh_remote_port; ! 741: ipc_kmsg_queue_init(send_list); ! 742: ! 743: /* ! 744: * Unfortunately we can't allocate or deallocate memory ! 745: * while holding this lock. And we can't drop the lock ! 746: * while examining the filter list. ! 747: */ ! 748: simple_lock(&ifp->if_rcv_port_list_lock); ! 749: FILTER_ITERATE(ifp, infp, nextfp) ! 750: { ! 751: entp = (net_hash_entry_t) 0; ! 752: if (infp->filter[0] == NETF_BPF) { ! 753: ret_count = bpf_do_filter(infp, net_kmsg(kmsg)->packet, count, ! 754: net_kmsg(kmsg)->header, ! 755: &hash_headp, &entp); ! 756: if (entp == (net_hash_entry_t) 0) ! 757: dest = infp->rcv_port; ! 758: else ! 759: dest = entp->rcv_port; ! 760: } else { ! 761: ret_count = net_do_filter(infp, net_kmsg(kmsg)->packet, count, ! 762: net_kmsg(kmsg)->header); ! 763: if (ret_count) ! 764: ret_count = count; ! 765: dest = infp->rcv_port; ! 766: } ! 767: ! 768: if (ret_count) { ! 769: ! 770: /* ! 771: * Make a send right for the destination. ! 772: */ ! 773: ! 774: dest = ipc_port_copy_send(dest); ! 775: if (!IP_VALID(dest)) { ! 776: /* ! 777: * This filter is dead. We remove it from the ! 778: * filter list and set it aside for deallocation. ! 779: */ ! 780: ! 781: if (entp == (net_hash_entry_t) 0) { ! 782: queue_remove(&ifp->if_rcv_port_list, infp, ! 783: net_rcv_port_t, chain); ! 784: ENQUEUE_DEAD(dead_infp, infp); ! 785: continue; ! 786: } else { ! 787: hash_ent_remove (ifp, ! 788: (net_hash_header_t)infp, ! 789: FALSE, /* no longer used */ ! 790: hash_headp, ! 791: entp, ! 792: &dead_entp); ! 793: continue; ! 794: } ! 795: } ! 796: ! 797: /* ! 798: * Deliver copy of packet to this channel. ! 799: */ ! 800: if (ipc_kmsg_queue_empty(send_list)) { ! 801: /* ! 802: * Only receiver, so far ! 803: */ ! 804: new_kmsg = kmsg; ! 805: } else { ! 806: /* ! 807: * Other receivers - must allocate message and copy. ! 808: */ ! 809: new_kmsg = net_kmsg_get(); ! 810: if (new_kmsg == IKM_NULL) { ! 811: ipc_port_release_send(dest); ! 812: break; ! 813: } ! 814: ! 815: bcopy( ! 816: net_kmsg(kmsg)->packet, ! 817: net_kmsg(new_kmsg)->packet, ! 818: ret_count); ! 819: bcopy( ! 820: net_kmsg(kmsg)->header, ! 821: net_kmsg(new_kmsg)->header, ! 822: NET_HDW_HDR_MAX); ! 823: } ! 824: net_kmsg(new_kmsg)->net_rcv_msg_packet_count = ret_count; ! 825: new_kmsg->ikm_header.msgh_remote_port = (mach_port_t) dest; ! 826: ipc_kmsg_enqueue(send_list, new_kmsg); ! 827: ! 828: { ! 829: register net_rcv_port_t prevfp; ! 830: int rcount = ++infp->rcv_count; ! 831: ! 832: /* ! 833: * See if ordering of filters is wrong ! 834: */ ! 835: if (infp->priority >= NET_HI_PRI) { ! 836: prevfp = (net_rcv_port_t) queue_prev(&infp->chain); ! 837: /* ! 838: * If infp is not the first element on the queue, ! 839: * and the previous element is at equal priority ! 840: * but has a lower count, then promote infp to ! 841: * be in front of prevfp. ! 842: */ ! 843: if ((queue_t)prevfp != &ifp->if_rcv_port_list && ! 844: infp->priority == prevfp->priority) { ! 845: /* ! 846: * Threshold difference to prevent thrashing ! 847: */ ! 848: if (net_filter_queue_reorder ! 849: && (100 + prevfp->rcv_count < rcount)) ! 850: reorder_queue(&prevfp->chain, &infp->chain); ! 851: } ! 852: /* ! 853: * High-priority filter -> no more deliveries ! 854: */ ! 855: break; ! 856: } ! 857: } ! 858: } ! 859: } ! 860: FILTER_ITERATE_END ! 861: ! 862: simple_unlock(&ifp->if_rcv_port_list_lock); ! 863: ! 864: /* ! 865: * Deallocate dead filters. ! 866: */ ! 867: if (dead_infp != 0) ! 868: net_free_dead_infp(dead_infp); ! 869: if (dead_entp != 0) ! 870: net_free_dead_entp(dead_entp); ! 871: ! 872: if (ipc_kmsg_queue_empty(send_list)) { ! 873: /* Not sent - recycle */ ! 874: net_kmsg_put(kmsg); ! 875: } ! 876: } ! 877: ! 878: boolean_t ! 879: net_do_filter(infp, data, data_count, header) ! 880: net_rcv_port_t infp; ! 881: char * data; ! 882: unsigned int data_count; ! 883: char * header; ! 884: { ! 885: int stack[NET_FILTER_STACK_DEPTH+1]; ! 886: register int *sp; ! 887: register filter_t *fp, *fpe; ! 888: register unsigned int op, arg; ! 889: ! 890: /* ! 891: * The filter accesses the header and data ! 892: * as unsigned short words. ! 893: */ ! 894: data_count /= sizeof(unsigned short); ! 895: ! 896: #define data_word ((unsigned short *)data) ! 897: #define header_word ((unsigned short *)header) ! 898: ! 899: sp = &stack[NET_FILTER_STACK_DEPTH]; ! 900: fp = &infp->filter[0]; ! 901: fpe = infp->filter_end; ! 902: ! 903: *sp = TRUE; ! 904: ! 905: while (fp < fpe) { ! 906: arg = *fp++; ! 907: op = NETF_OP(arg); ! 908: arg = NETF_ARG(arg); ! 909: ! 910: switch (arg) { ! 911: case NETF_NOPUSH: ! 912: arg = *sp++; ! 913: break; ! 914: case NETF_PUSHZERO: ! 915: arg = 0; ! 916: break; ! 917: case NETF_PUSHLIT: ! 918: arg = *fp++; ! 919: break; ! 920: case NETF_PUSHIND: ! 921: arg = *sp++; ! 922: if (arg >= data_count) ! 923: return FALSE; ! 924: arg = data_word[arg]; ! 925: break; ! 926: case NETF_PUSHHDRIND: ! 927: arg = *sp++; ! 928: if (arg >= NET_HDW_HDR_MAX/sizeof(unsigned short)) ! 929: return FALSE; ! 930: arg = header_word[arg]; ! 931: break; ! 932: default: ! 933: if (arg >= NETF_PUSHSTK) { ! 934: arg = sp[arg - NETF_PUSHSTK]; ! 935: } ! 936: else if (arg >= NETF_PUSHHDR) { ! 937: arg = header_word[arg - NETF_PUSHHDR]; ! 938: } ! 939: else { ! 940: arg -= NETF_PUSHWORD; ! 941: if (arg >= data_count) ! 942: return FALSE; ! 943: arg = data_word[arg]; ! 944: } ! 945: break; ! 946: ! 947: } ! 948: switch (op) { ! 949: case NETF_OP(NETF_NOP): ! 950: *--sp = arg; ! 951: break; ! 952: case NETF_OP(NETF_AND): ! 953: *sp &= arg; ! 954: break; ! 955: case NETF_OP(NETF_OR): ! 956: *sp |= arg; ! 957: break; ! 958: case NETF_OP(NETF_XOR): ! 959: *sp ^= arg; ! 960: break; ! 961: case NETF_OP(NETF_EQ): ! 962: *sp = (*sp == arg); ! 963: break; ! 964: case NETF_OP(NETF_NEQ): ! 965: *sp = (*sp != arg); ! 966: break; ! 967: case NETF_OP(NETF_LT): ! 968: *sp = (*sp < arg); ! 969: break; ! 970: case NETF_OP(NETF_LE): ! 971: *sp = (*sp <= arg); ! 972: break; ! 973: case NETF_OP(NETF_GT): ! 974: *sp = (*sp > arg); ! 975: break; ! 976: case NETF_OP(NETF_GE): ! 977: *sp = (*sp >= arg); ! 978: break; ! 979: case NETF_OP(NETF_COR): ! 980: if (*sp++ == arg) ! 981: return (TRUE); ! 982: break; ! 983: case NETF_OP(NETF_CAND): ! 984: if (*sp++ != arg) ! 985: return (FALSE); ! 986: break; ! 987: case NETF_OP(NETF_CNOR): ! 988: if (*sp++ == arg) ! 989: return (FALSE); ! 990: break; ! 991: case NETF_OP(NETF_CNAND): ! 992: if (*sp++ != arg) ! 993: return (TRUE); ! 994: break; ! 995: case NETF_OP(NETF_LSH): ! 996: *sp <<= arg; ! 997: break; ! 998: case NETF_OP(NETF_RSH): ! 999: *sp >>= arg; ! 1000: break; ! 1001: case NETF_OP(NETF_ADD): ! 1002: *sp += arg; ! 1003: break; ! 1004: case NETF_OP(NETF_SUB): ! 1005: *sp -= arg; ! 1006: break; ! 1007: } ! 1008: } ! 1009: return ((*sp) ? TRUE : FALSE); ! 1010: ! 1011: #undef data_word ! 1012: #undef header_word ! 1013: } ! 1014: ! 1015: /* ! 1016: * Check filter for invalid operations or stack over/under-flow. ! 1017: */ ! 1018: boolean_t ! 1019: parse_net_filter(filter, count) ! 1020: register filter_t *filter; ! 1021: unsigned int count; ! 1022: { ! 1023: register int sp; ! 1024: register filter_t *fpe = &filter[count]; ! 1025: register filter_t op, arg; ! 1026: ! 1027: sp = NET_FILTER_STACK_DEPTH; ! 1028: ! 1029: for (; filter < fpe; filter++) { ! 1030: op = NETF_OP(*filter); ! 1031: arg = NETF_ARG(*filter); ! 1032: ! 1033: switch (arg) { ! 1034: case NETF_NOPUSH: ! 1035: break; ! 1036: case NETF_PUSHZERO: ! 1037: sp--; ! 1038: break; ! 1039: case NETF_PUSHLIT: ! 1040: filter++; ! 1041: if (filter >= fpe) ! 1042: return (FALSE); /* literal value not in filter */ ! 1043: sp--; ! 1044: break; ! 1045: case NETF_PUSHIND: ! 1046: case NETF_PUSHHDRIND: ! 1047: break; ! 1048: default: ! 1049: if (arg >= NETF_PUSHSTK) { ! 1050: if (arg - NETF_PUSHSTK + sp > NET_FILTER_STACK_DEPTH) ! 1051: return FALSE; ! 1052: } ! 1053: else if (arg >= NETF_PUSHHDR) { ! 1054: if (arg - NETF_PUSHHDR >= ! 1055: NET_HDW_HDR_MAX/sizeof(unsigned short)) ! 1056: return FALSE; ! 1057: } ! 1058: /* else... cannot check for packet bounds ! 1059: without packet */ ! 1060: sp--; ! 1061: break; ! 1062: } ! 1063: if (sp < 2) { ! 1064: return (FALSE); /* stack overflow */ ! 1065: } ! 1066: if (op == NETF_OP(NETF_NOP)) ! 1067: continue; ! 1068: ! 1069: /* ! 1070: * all non-NOP operators are binary. ! 1071: */ ! 1072: if (sp > NET_MAX_FILTER-2) ! 1073: return (FALSE); ! 1074: ! 1075: sp++; ! 1076: switch (op) { ! 1077: case NETF_OP(NETF_AND): ! 1078: case NETF_OP(NETF_OR): ! 1079: case NETF_OP(NETF_XOR): ! 1080: case NETF_OP(NETF_EQ): ! 1081: case NETF_OP(NETF_NEQ): ! 1082: case NETF_OP(NETF_LT): ! 1083: case NETF_OP(NETF_LE): ! 1084: case NETF_OP(NETF_GT): ! 1085: case NETF_OP(NETF_GE): ! 1086: case NETF_OP(NETF_COR): ! 1087: case NETF_OP(NETF_CAND): ! 1088: case NETF_OP(NETF_CNOR): ! 1089: case NETF_OP(NETF_CNAND): ! 1090: case NETF_OP(NETF_LSH): ! 1091: case NETF_OP(NETF_RSH): ! 1092: case NETF_OP(NETF_ADD): ! 1093: case NETF_OP(NETF_SUB): ! 1094: break; ! 1095: default: ! 1096: return (FALSE); ! 1097: } ! 1098: } ! 1099: return (TRUE); ! 1100: } ! 1101: ! 1102: /* ! 1103: * Set a filter for a network interface. ! 1104: * ! 1105: * We are given a naked send right for the rcv_port. ! 1106: * If we are successful, we must consume that right. ! 1107: */ ! 1108: io_return_t ! 1109: net_set_filter(ifp, rcv_port, priority, filter, filter_count) ! 1110: struct ifnet *ifp; ! 1111: ipc_port_t rcv_port; ! 1112: int priority; ! 1113: filter_t *filter; ! 1114: unsigned int filter_count; ! 1115: { ! 1116: int filter_bytes; ! 1117: bpf_insn_t match; ! 1118: register net_rcv_port_t infp, my_infp; ! 1119: net_rcv_port_t nextfp; ! 1120: net_hash_header_t hhp; ! 1121: register net_hash_entry_t entp, hash_entp; ! 1122: net_hash_entry_t *head, nextentp; ! 1123: queue_entry_t dead_infp, dead_entp; ! 1124: int i; ! 1125: int ret, is_new_infp; ! 1126: io_return_t rval; ! 1127: ! 1128: /* ! 1129: * Check the filter syntax. ! 1130: */ ! 1131: ! 1132: filter_bytes = CSPF_BYTES(filter_count); ! 1133: match = (bpf_insn_t) 0; ! 1134: ! 1135: if (filter_count > 0 && filter[0] == NETF_BPF) { ! 1136: ret = bpf_validate((bpf_insn_t)filter, filter_bytes, &match); ! 1137: if (!ret) ! 1138: return (D_INVALID_OPERATION); ! 1139: } else { ! 1140: if (!parse_net_filter(filter, filter_count)) ! 1141: return (D_INVALID_OPERATION); ! 1142: } ! 1143: ! 1144: rval = D_SUCCESS; /* default return value */ ! 1145: dead_infp = dead_entp = 0; ! 1146: ! 1147: if (match == (bpf_insn_t) 0) { ! 1148: /* ! 1149: * If there is no match instruction, we allocate ! 1150: * a normal packet filter structure. ! 1151: */ ! 1152: my_infp = (net_rcv_port_t) zalloc(net_rcv_zone); ! 1153: my_infp->rcv_port = rcv_port; ! 1154: is_new_infp = TRUE; ! 1155: } else { ! 1156: /* ! 1157: * If there is a match instruction, we assume there will ! 1158: * multiple session with a common substructure and allocate ! 1159: * a hash table to deal with them. ! 1160: */ ! 1161: my_infp = 0; ! 1162: hash_entp = (net_hash_entry_t) zalloc(net_hash_entry_zone); ! 1163: is_new_infp = FALSE; ! 1164: } ! 1165: ! 1166: /* ! 1167: * Look for an existing filter on the same reply port. ! 1168: * Look for filters with dead ports (for GC). ! 1169: * Look for a filter with the same code except KEY insns. ! 1170: */ ! 1171: ! 1172: simple_lock(&ifp->if_rcv_port_list_lock); ! 1173: ! 1174: FILTER_ITERATE(ifp, infp, nextfp) ! 1175: { ! 1176: if (infp->rcv_port == MACH_PORT_NULL) { ! 1177: if (match != 0 ! 1178: && infp->priority == priority ! 1179: && my_infp == 0 ! 1180: && (infp->filter_end - infp->filter) == filter_count ! 1181: && bpf_eq((bpf_insn_t)infp->filter, ! 1182: filter, filter_bytes)) ! 1183: { ! 1184: my_infp = infp; ! 1185: } ! 1186: ! 1187: for (i = 0; i < NET_HASH_SIZE; i++) { ! 1188: head = &((net_hash_header_t) infp)->table[i]; ! 1189: if (*head == 0) ! 1190: continue; ! 1191: ! 1192: /* ! 1193: * Check each hash entry to make sure the ! 1194: * destination port is still valid. Remove ! 1195: * any invalid entries. ! 1196: */ ! 1197: entp = *head; ! 1198: do { ! 1199: nextentp = (net_hash_entry_t) entp->he_next; ! 1200: ! 1201: /* checked without ! 1202: ip_lock(entp->rcv_port) */ ! 1203: if (entp->rcv_port == rcv_port ! 1204: || !IP_VALID(entp->rcv_port) ! 1205: || !ip_active(entp->rcv_port)) { ! 1206: ! 1207: ret = hash_ent_remove (ifp, ! 1208: (net_hash_header_t)infp, ! 1209: (my_infp == infp), ! 1210: head, ! 1211: entp, ! 1212: &dead_entp); ! 1213: if (ret) ! 1214: goto hash_loop_end; ! 1215: } ! 1216: ! 1217: entp = nextentp; ! 1218: /* While test checks head since hash_ent_remove ! 1219: might modify it. ! 1220: */ ! 1221: } while (*head != 0 && entp != *head); ! 1222: } ! 1223: hash_loop_end: ! 1224: ; ! 1225: ! 1226: } else if (infp->rcv_port == rcv_port ! 1227: || !IP_VALID(infp->rcv_port) ! 1228: || !ip_active(infp->rcv_port)) { ! 1229: /* Remove the old filter from list */ ! 1230: remqueue(&ifp->if_rcv_port_list, (queue_entry_t)infp); ! 1231: ENQUEUE_DEAD(dead_infp, infp); ! 1232: } ! 1233: } ! 1234: FILTER_ITERATE_END ! 1235: ! 1236: if (my_infp == 0) { ! 1237: /* Allocate a dummy infp */ ! 1238: simple_lock(&net_hash_header_lock); ! 1239: for (i = 0; i < N_NET_HASH; i++) { ! 1240: if (filter_hash_header[i].n_keys == 0) ! 1241: break; ! 1242: } ! 1243: if (i == N_NET_HASH) { ! 1244: simple_unlock(&net_hash_header_lock); ! 1245: simple_unlock(&ifp->if_rcv_port_list_lock); ! 1246: ! 1247: ipc_port_release_send(rcv_port); ! 1248: if (match != 0) ! 1249: zfree (net_hash_entry_zone, (vm_offset_t)hash_entp); ! 1250: ! 1251: rval = D_NO_MEMORY; ! 1252: goto clean_and_return; ! 1253: } ! 1254: ! 1255: hhp = &filter_hash_header[i]; ! 1256: hhp->n_keys = match->jt; ! 1257: simple_unlock(&net_hash_header_lock); ! 1258: ! 1259: hhp->ref_count = 0; ! 1260: for (i = 0; i < NET_HASH_SIZE; i++) ! 1261: hhp->table[i] = 0; ! 1262: ! 1263: my_infp = (net_rcv_port_t)hhp; ! 1264: my_infp->rcv_port = MACH_PORT_NULL; /* indication of dummy */ ! 1265: is_new_infp = TRUE; ! 1266: } ! 1267: ! 1268: if (is_new_infp) { ! 1269: my_infp->priority = priority; ! 1270: my_infp->rcv_count = 0; ! 1271: ! 1272: /* Copy filter program. */ ! 1273: bcopy ((vm_offset_t)filter, (vm_offset_t)my_infp->filter, ! 1274: filter_bytes); ! 1275: my_infp->filter_end = ! 1276: (filter_t *)((char *)my_infp->filter + filter_bytes); ! 1277: ! 1278: if (match == 0) { ! 1279: my_infp->rcv_qlimit = net_add_q_info(rcv_port); ! 1280: } else { ! 1281: my_infp->rcv_qlimit = 0; ! 1282: } ! 1283: ! 1284: /* Insert my_infp according to priority */ ! 1285: queue_iterate(&ifp->if_rcv_port_list, infp, net_rcv_port_t, chain) ! 1286: if (priority > infp->priority) ! 1287: break; ! 1288: enqueue_tail((queue_t)&infp->chain, (queue_entry_t)my_infp); ! 1289: } ! 1290: ! 1291: if (match != 0) ! 1292: { /* Insert to hash list */ ! 1293: net_hash_entry_t *p; ! 1294: int j; ! 1295: ! 1296: hash_entp->rcv_port = rcv_port; ! 1297: for (i = 0; i < match->jt; i++) /* match->jt is n_keys */ ! 1298: hash_entp->keys[i] = match[i+1].k; ! 1299: p = &((net_hash_header_t)my_infp)-> ! 1300: table[bpf_hash(match->jt, hash_entp->keys)]; ! 1301: ! 1302: /* Not checking for the same key values */ ! 1303: if (*p == 0) { ! 1304: queue_init ((queue_t) hash_entp); ! 1305: *p = hash_entp; ! 1306: } else { ! 1307: enqueue_tail((queue_t)*p, hash_entp); ! 1308: } ! 1309: ! 1310: ((net_hash_header_t)my_infp)->ref_count++; ! 1311: hash_entp->rcv_qlimit = net_add_q_info(rcv_port); ! 1312: ! 1313: } ! 1314: ! 1315: simple_unlock(&ifp->if_rcv_port_list_lock); ! 1316: ! 1317: clean_and_return: ! 1318: /* No locks are held at this point. */ ! 1319: ! 1320: if (dead_infp != 0) ! 1321: net_free_dead_infp(dead_infp); ! 1322: if (dead_entp != 0) ! 1323: net_free_dead_entp(dead_entp); ! 1324: ! 1325: if (rval == D_SUCCESS) ! 1326: /* ! 1327: * Make sure now that we have some buffers allocated. ! 1328: * Before any packets at all have been received, the ! 1329: * net_thread has never run to allocate buffers. ! 1330: * The very first packet received will be dropped before ! 1331: * waking up the net_thread to allocate buffers. ! 1332: * Now that someone is actually listening for packets, ! 1333: * we should eagerly allocate so we don't drop any. ! 1334: */ ! 1335: net_kmsg_more(); ! 1336: ! 1337: return (rval); ! 1338: } ! 1339: ! 1340: #if 0 ! 1341: /* ! 1342: * Other network operations ! 1343: */ ! 1344: io_return_t ! 1345: net_getstat(ifp, flavor, status, count) ! 1346: struct ifnet *ifp; ! 1347: dev_flavor_t flavor; ! 1348: dev_status_t status; /* pointer to OUT array */ ! 1349: natural_t *count; /* OUT */ ! 1350: { ! 1351: switch (flavor) { ! 1352: case NET_STATUS: ! 1353: { ! 1354: register struct net_status *ns = (struct net_status *)status; ! 1355: ! 1356: if (*count < NET_STATUS_COUNT) ! 1357: return (D_INVALID_OPERATION); ! 1358: ! 1359: ns->min_packet_size = ifp->if_header_size; ! 1360: ns->max_packet_size = ifp->if_header_size + ifp->if_mtu; ! 1361: ns->header_format = ifp->if_header_format; ! 1362: ns->header_size = ifp->if_header_size; ! 1363: ns->address_size = ifp->if_address_size; ! 1364: ns->flags = ifp->if_flags; ! 1365: ns->mapped_size = 0; ! 1366: ! 1367: *count = NET_STATUS_COUNT; ! 1368: break; ! 1369: } ! 1370: case NET_ADDRESS: ! 1371: { ! 1372: register int addr_byte_count; ! 1373: register int addr_int_count; ! 1374: register int i; ! 1375: ! 1376: addr_byte_count = ifp->if_address_size; ! 1377: addr_int_count = (addr_byte_count + (sizeof(int)-1)) ! 1378: / sizeof(int); ! 1379: ! 1380: if (*count < addr_int_count) ! 1381: { ! 1382: /* XXX debug hack. */ ! 1383: printf ("net_getstat: count: %d, addr_int_count: %d\n", ! 1384: *count, addr_int_count); ! 1385: return (D_INVALID_OPERATION); ! 1386: } ! 1387: ! 1388: bcopy((char *)ifp->if_address, ! 1389: (char *)status, ! 1390: (unsigned) addr_byte_count); ! 1391: if (addr_byte_count < addr_int_count * sizeof(int)) ! 1392: bzero((char *)status + addr_byte_count, ! 1393: (unsigned) (addr_int_count * sizeof(int) ! 1394: - addr_byte_count)); ! 1395: ! 1396: for (i = 0; i < addr_int_count; i++) { ! 1397: register int word; ! 1398: ! 1399: word = status[i]; ! 1400: status[i] = htonl(word); ! 1401: } ! 1402: *count = addr_int_count; ! 1403: break; ! 1404: } ! 1405: default: ! 1406: return (D_INVALID_OPERATION); ! 1407: } ! 1408: return (D_SUCCESS); ! 1409: } ! 1410: ! 1411: io_return_t ! 1412: net_write(ifp, start, ior) ! 1413: register struct ifnet *ifp; ! 1414: int (*start)(); ! 1415: io_req_t ior; ! 1416: { ! 1417: spl_t s; ! 1418: kern_return_t rc; ! 1419: boolean_t wait; ! 1420: ! 1421: /* ! 1422: * Reject the write if the interface is down. ! 1423: */ ! 1424: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) ! 1425: return (D_DEVICE_DOWN); ! 1426: ! 1427: /* ! 1428: * Reject the write if the packet is too large or too small. ! 1429: */ ! 1430: if (ior->io_count < ifp->if_header_size || ! 1431: ior->io_count > ifp->if_header_size + ifp->if_mtu) ! 1432: return (D_INVALID_SIZE); ! 1433: ! 1434: /* ! 1435: * Wire down the memory. ! 1436: */ ! 1437: ! 1438: rc = device_write_get(ior, &wait); ! 1439: if (rc != KERN_SUCCESS) ! 1440: return (rc); ! 1441: ! 1442: /* ! 1443: * Network interfaces can't cope with VM continuations. ! 1444: * If wait is set, just panic. ! 1445: */ ! 1446: if (wait) { ! 1447: panic("net_write: VM continuation"); ! 1448: } ! 1449: ! 1450: /* ! 1451: * Queue the packet on the output queue, and ! 1452: * start the device. ! 1453: */ ! 1454: s = splimp(); ! 1455: IF_ENQUEUE(&ifp->if_snd, ior); ! 1456: (*start)(ifp->if_unit); ! 1457: splx(s); ! 1458: ! 1459: return (D_IO_QUEUED); ! 1460: } ! 1461: ! 1462: #ifdef FIPC ! 1463: /* This gets called by nefoutput for dev_ops->d_port_death ... */ ! 1464: ! 1465: io_return_t ! 1466: net_fwrite(ifp, start, ior) ! 1467: register struct ifnet *ifp; ! 1468: int (*start)(); ! 1469: io_req_t ior; ! 1470: { ! 1471: spl_t s; ! 1472: kern_return_t rc; ! 1473: boolean_t wait; ! 1474: ! 1475: /* ! 1476: * Reject the write if the interface is down. ! 1477: */ ! 1478: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) ! 1479: return (D_DEVICE_DOWN); ! 1480: ! 1481: /* ! 1482: * Reject the write if the packet is too large or too small. ! 1483: */ ! 1484: if (ior->io_count < ifp->if_header_size || ! 1485: ior->io_count > ifp->if_header_size + ifp->if_mtu) ! 1486: return (D_INVALID_SIZE); ! 1487: ! 1488: /* ! 1489: * DON'T Wire down the memory. ! 1490: */ ! 1491: #if 0 ! 1492: rc = device_write_get(ior, &wait); ! 1493: if (rc != KERN_SUCCESS) ! 1494: return (rc); ! 1495: #endif ! 1496: /* ! 1497: * Network interfaces can't cope with VM continuations. ! 1498: * If wait is set, just panic. ! 1499: */ ! 1500: /* I'll have to figure out who was setting wait...*/ ! 1501: #if 0 ! 1502: if (wait) { ! 1503: panic("net_write: VM continuation"); ! 1504: } ! 1505: #endif ! 1506: /* ! 1507: * Queue the packet on the output queue, and ! 1508: * start the device. ! 1509: */ ! 1510: s = splimp(); ! 1511: IF_ENQUEUE(&ifp->if_snd, ior); ! 1512: (*start)(ifp->if_unit); ! 1513: splx(s); ! 1514: ! 1515: return (D_IO_QUEUED); ! 1516: } ! 1517: #endif /* FIPC */ ! 1518: ! 1519: #endif ! 1520: ! 1521: ! 1522: /* ! 1523: * Initialize the whole package. ! 1524: */ ! 1525: void ! 1526: net_io_init() ! 1527: { ! 1528: register vm_size_t size; ! 1529: ! 1530: size = sizeof(struct net_rcv_port); ! 1531: net_rcv_zone = zinit(size, ! 1532: size * 1000, ! 1533: PAGE_SIZE, ! 1534: FALSE, ! 1535: "net_rcv_port"); ! 1536: ! 1537: size = sizeof(struct net_hash_entry); ! 1538: net_hash_entry_zone = zinit(size, ! 1539: size * 100, ! 1540: PAGE_SIZE, ! 1541: FALSE, ! 1542: "net_hash_entry"); ! 1543: ! 1544: size = ikm_plus_overhead(sizeof(struct net_rcv_msg)); ! 1545: net_kmsg_size = round_page(size); ! 1546: ! 1547: /* ! 1548: * net_kmsg_max caps the number of buffers ! 1549: * we are willing to allocate. By default, ! 1550: * we allow for net_queue_free_min plus ! 1551: * the queue limit for each filter. ! 1552: * (Added as the filters are added.) ! 1553: */ ! 1554: ! 1555: simple_lock_init(&net_kmsg_total_lock); ! 1556: if (net_kmsg_max == 0) ! 1557: net_kmsg_max = net_queue_free_min; ! 1558: ! 1559: simple_lock_init(&net_queue_free_lock); ! 1560: ipc_kmsg_queue_init(&net_queue_free); ! 1561: ! 1562: simple_lock_init(&net_queue_lock); ! 1563: ipc_kmsg_queue_init(&net_queue_high); ! 1564: ipc_kmsg_queue_init(&net_queue_low); ! 1565: ! 1566: simple_lock_init(&net_hash_header_lock); ! 1567: } ! 1568: ! 1569: ! 1570: /* ======== BPF: Berkeley Packet Filter ======== */ ! 1571: ! 1572: /*- ! 1573: * Copyright (c) 1990-1991 The Regents of the University of California. ! 1574: * All rights reserved. ! 1575: * ! 1576: * This code is derived from the Stanford/CMU enet packet filter, ! 1577: * (net/enet.c) distributed as part of 4.3BSD, and code contributed ! 1578: * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence ! 1579: * Berkeley Laboratory. ! 1580: * ! 1581: * Redistribution and use in source and binary forms, with or without ! 1582: * modification, are permitted provided that the following conditions ! 1583: * are met: ! 1584: * 1. Redistributions of source code must retain the above copyright ! 1585: * notice, this list of conditions and the following disclaimer. ! 1586: * 2. Redistributions in binary form must reproduce the above copyright ! 1587: * notice, this list of conditions and the following disclaimer in the ! 1588: * documentation and/or other materials provided with the distribution. ! 1589: * 4. Neither the name of the University nor the names of its contributors ! 1590: * may be used to endorse or promote products derived from this software ! 1591: * without specific prior written permission. ! 1592: * ! 1593: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 1594: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 1595: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 1596: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 1597: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 1598: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 1599: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 1600: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 1601: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 1602: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 1603: * SUCH DAMAGE. ! 1604: * ! 1605: * @(#)bpf.c 7.5 (Berkeley) 7/15/91 ! 1606: */ ! 1607: ! 1608: #include <oskit/types.h> ! 1609: ! 1610: #if defined(sparc) || defined(mips) || defined(ibm032) || defined(alpha) ! 1611: #define BPF_ALIGN ! 1612: #endif ! 1613: ! 1614: #ifndef BPF_ALIGN ! 1615: #define EXTRACT_SHORT(p) ((oskit_u16_t)ntohs(*(oskit_u16_t *)p)) ! 1616: #define EXTRACT_LONG(p) (ntohl(*(oskit_u32_t *)p)) ! 1617: #else ! 1618: #define EXTRACT_SHORT(p)\ ! 1619: ((oskit_u16_t)\ ! 1620: ((oskit_u16_t)*((u_char *)p+0)<<8|\ ! 1621: (oskit_u16_t)*((u_char *)p+1)<<0)) ! 1622: #define EXTRACT_LONG(p)\ ! 1623: ((oskit_u32_t)*((u_char *)p+0)<<24|\ ! 1624: (oskit_u32_t)*((u_char *)p+1)<<16|\ ! 1625: (oskit_u32_t)*((u_char *)p+2)<<8|\ ! 1626: (oskit_u32_t)*((u_char *)p+3)<<0) ! 1627: #endif ! 1628: ! 1629: /* ! 1630: * Execute the filter program starting at pc on the packet p ! 1631: * wirelen is the length of the original packet ! 1632: * buflen is the amount of data present ! 1633: */ ! 1634: ! 1635: int ! 1636: bpf_do_filter(infp, p, wirelen, header, hash_headpp, entpp) ! 1637: net_rcv_port_t infp; ! 1638: char * p; /* packet data */ ! 1639: unsigned int wirelen; /* data_count (in bytes) */ ! 1640: char * header; ! 1641: net_hash_entry_t **hash_headpp, *entpp; /* out */ ! 1642: { ! 1643: register bpf_insn_t pc, pc_end; ! 1644: register unsigned int buflen; ! 1645: ! 1646: register oskit_u32_t A, X; ! 1647: register int k; ! 1648: oskit_s32_t mem[BPF_MEMWORDS]; ! 1649: ! 1650: pc = ((bpf_insn_t) infp->filter) + 1; ! 1651: /* filter[0].code is BPF_BEGIN */ ! 1652: pc_end = (bpf_insn_t)infp->filter_end; ! 1653: buflen = NET_RCV_MAX; ! 1654: *entpp = 0; /* default */ ! 1655: ! 1656: #ifdef lint ! 1657: A = 0; ! 1658: X = 0; ! 1659: #endif ! 1660: for (; pc < pc_end; ++pc) { ! 1661: switch (pc->code) { ! 1662: ! 1663: default: ! 1664: #ifdef KERNEL ! 1665: return 0; ! 1666: #else ! 1667: abort(); ! 1668: #endif ! 1669: case BPF_RET|BPF_K: ! 1670: if (infp->rcv_port == MACH_PORT_NULL && ! 1671: *entpp == 0) { ! 1672: return 0; ! 1673: } ! 1674: return ((u_int)pc->k <= wirelen) ? ! 1675: pc->k : wirelen; ! 1676: ! 1677: case BPF_RET|BPF_A: ! 1678: if (infp->rcv_port == MACH_PORT_NULL && ! 1679: *entpp == 0) { ! 1680: return 0; ! 1681: } ! 1682: return ((u_int)A <= wirelen) ? ! 1683: A : wirelen; ! 1684: ! 1685: case BPF_RET|BPF_MATCH_IMM: ! 1686: if (bpf_match ((net_hash_header_t)infp, pc->jt, mem, ! 1687: hash_headpp, entpp)) { ! 1688: return ((u_int)pc->k <= wirelen) ? ! 1689: pc->k : wirelen; ! 1690: } ! 1691: return 0; ! 1692: ! 1693: case BPF_LD|BPF_W|BPF_ABS: ! 1694: k = pc->k; ! 1695: if ((u_int)k + sizeof(oskit_s32_t) <= buflen) { ! 1696: #ifdef BPF_ALIGN ! 1697: if (((int)(p + k) & 3) != 0) ! 1698: A = EXTRACT_LONG(&p[k]); ! 1699: else ! 1700: #endif ! 1701: A = ntohl(*(oskit_s32_t *)(p + k)); ! 1702: continue; ! 1703: } ! 1704: ! 1705: k -= BPF_DLBASE; ! 1706: if ((u_int)k + sizeof(oskit_s32_t) <= NET_HDW_HDR_MAX) { ! 1707: #ifdef BPF_ALIGN ! 1708: if (((int)(header + k) & 3) != 0) ! 1709: A = EXTRACT_LONG(&header[k]); ! 1710: else ! 1711: #endif ! 1712: A = ntohl(*(oskit_s32_t *)(header + k)); ! 1713: continue; ! 1714: } else { ! 1715: return 0; ! 1716: } ! 1717: ! 1718: case BPF_LD|BPF_H|BPF_ABS: ! 1719: k = pc->k; ! 1720: if ((u_int)k + sizeof(short) <= buflen) { ! 1721: A = EXTRACT_SHORT(&p[k]); ! 1722: continue; ! 1723: } ! 1724: ! 1725: k -= BPF_DLBASE; ! 1726: if ((u_int)k + sizeof(short) <= NET_HDW_HDR_MAX) { ! 1727: A = EXTRACT_SHORT(&header[k]); ! 1728: continue; ! 1729: } else { ! 1730: return 0; ! 1731: } ! 1732: ! 1733: case BPF_LD|BPF_B|BPF_ABS: ! 1734: k = pc->k; ! 1735: if ((u_int)k < buflen) { ! 1736: A = p[k]; ! 1737: continue; ! 1738: } ! 1739: ! 1740: k -= BPF_DLBASE; ! 1741: if ((u_int)k < NET_HDW_HDR_MAX) { ! 1742: A = header[k]; ! 1743: continue; ! 1744: } else { ! 1745: return 0; ! 1746: } ! 1747: ! 1748: case BPF_LD|BPF_W|BPF_LEN: ! 1749: A = wirelen; ! 1750: continue; ! 1751: ! 1752: case BPF_LDX|BPF_W|BPF_LEN: ! 1753: X = wirelen; ! 1754: continue; ! 1755: ! 1756: case BPF_LD|BPF_W|BPF_IND: ! 1757: k = X + pc->k; ! 1758: if (k + sizeof(oskit_s32_t) > buflen) ! 1759: return 0; ! 1760: #ifdef BPF_ALIGN ! 1761: if (((int)(p + k) & 3) != 0) ! 1762: A = EXTRACT_LONG(&p[k]); ! 1763: else ! 1764: #endif ! 1765: A = ntohl(*(oskit_s32_t *)(p + k)); ! 1766: continue; ! 1767: ! 1768: case BPF_LD|BPF_H|BPF_IND: ! 1769: k = X + pc->k; ! 1770: if (k + sizeof(short) > buflen) ! 1771: return 0; ! 1772: A = EXTRACT_SHORT(&p[k]); ! 1773: continue; ! 1774: ! 1775: case BPF_LD|BPF_B|BPF_IND: ! 1776: k = X + pc->k; ! 1777: if (k >= buflen) ! 1778: return 0; ! 1779: A = p[k]; ! 1780: continue; ! 1781: ! 1782: case BPF_LDX|BPF_MSH|BPF_B: ! 1783: k = pc->k; ! 1784: if (k >= buflen) ! 1785: return 0; ! 1786: X = (p[pc->k] & 0xf) << 2; ! 1787: continue; ! 1788: ! 1789: case BPF_LD|BPF_IMM: ! 1790: A = pc->k; ! 1791: continue; ! 1792: ! 1793: case BPF_LDX|BPF_IMM: ! 1794: X = pc->k; ! 1795: continue; ! 1796: ! 1797: case BPF_LD|BPF_MEM: ! 1798: A = mem[pc->k]; ! 1799: continue; ! 1800: ! 1801: case BPF_LDX|BPF_MEM: ! 1802: X = mem[pc->k]; ! 1803: continue; ! 1804: ! 1805: case BPF_ST: ! 1806: mem[pc->k] = A; ! 1807: continue; ! 1808: ! 1809: case BPF_STX: ! 1810: mem[pc->k] = X; ! 1811: continue; ! 1812: ! 1813: case BPF_JMP|BPF_JA: ! 1814: pc += pc->k; ! 1815: continue; ! 1816: ! 1817: case BPF_JMP|BPF_JGT|BPF_K: ! 1818: pc += (A > pc->k) ? pc->jt : pc->jf; ! 1819: continue; ! 1820: ! 1821: case BPF_JMP|BPF_JGE|BPF_K: ! 1822: pc += (A >= pc->k) ? pc->jt : pc->jf; ! 1823: continue; ! 1824: ! 1825: case BPF_JMP|BPF_JEQ|BPF_K: ! 1826: pc += (A == pc->k) ? pc->jt : pc->jf; ! 1827: continue; ! 1828: ! 1829: case BPF_JMP|BPF_JSET|BPF_K: ! 1830: pc += (A & pc->k) ? pc->jt : pc->jf; ! 1831: continue; ! 1832: ! 1833: case BPF_JMP|BPF_JGT|BPF_X: ! 1834: pc += (A > X) ? pc->jt : pc->jf; ! 1835: continue; ! 1836: ! 1837: case BPF_JMP|BPF_JGE|BPF_X: ! 1838: pc += (A >= X) ? pc->jt : pc->jf; ! 1839: continue; ! 1840: ! 1841: case BPF_JMP|BPF_JEQ|BPF_X: ! 1842: pc += (A == X) ? pc->jt : pc->jf; ! 1843: continue; ! 1844: ! 1845: case BPF_JMP|BPF_JSET|BPF_X: ! 1846: pc += (A & X) ? pc->jt : pc->jf; ! 1847: continue; ! 1848: ! 1849: case BPF_ALU|BPF_ADD|BPF_X: ! 1850: A += X; ! 1851: continue; ! 1852: ! 1853: case BPF_ALU|BPF_SUB|BPF_X: ! 1854: A -= X; ! 1855: continue; ! 1856: ! 1857: case BPF_ALU|BPF_MUL|BPF_X: ! 1858: A *= X; ! 1859: continue; ! 1860: ! 1861: case BPF_ALU|BPF_DIV|BPF_X: ! 1862: if (X == 0) ! 1863: return 0; ! 1864: A /= X; ! 1865: continue; ! 1866: ! 1867: case BPF_ALU|BPF_AND|BPF_X: ! 1868: A &= X; ! 1869: continue; ! 1870: ! 1871: case BPF_ALU|BPF_OR|BPF_X: ! 1872: A |= X; ! 1873: continue; ! 1874: ! 1875: case BPF_ALU|BPF_LSH|BPF_X: ! 1876: A <<= X; ! 1877: continue; ! 1878: ! 1879: case BPF_ALU|BPF_RSH|BPF_X: ! 1880: A >>= X; ! 1881: continue; ! 1882: ! 1883: case BPF_ALU|BPF_ADD|BPF_K: ! 1884: A += pc->k; ! 1885: continue; ! 1886: ! 1887: case BPF_ALU|BPF_SUB|BPF_K: ! 1888: A -= pc->k; ! 1889: continue; ! 1890: ! 1891: case BPF_ALU|BPF_MUL|BPF_K: ! 1892: A *= pc->k; ! 1893: continue; ! 1894: ! 1895: case BPF_ALU|BPF_DIV|BPF_K: ! 1896: A /= pc->k; ! 1897: continue; ! 1898: ! 1899: case BPF_ALU|BPF_AND|BPF_K: ! 1900: A &= pc->k; ! 1901: continue; ! 1902: ! 1903: case BPF_ALU|BPF_OR|BPF_K: ! 1904: A |= pc->k; ! 1905: continue; ! 1906: ! 1907: case BPF_ALU|BPF_LSH|BPF_K: ! 1908: A <<= pc->k; ! 1909: continue; ! 1910: ! 1911: case BPF_ALU|BPF_RSH|BPF_K: ! 1912: A >>= pc->k; ! 1913: continue; ! 1914: ! 1915: case BPF_ALU|BPF_NEG: ! 1916: A = -A; ! 1917: continue; ! 1918: ! 1919: case BPF_MISC|BPF_TAX: ! 1920: X = A; ! 1921: continue; ! 1922: ! 1923: case BPF_MISC|BPF_TXA: ! 1924: A = X; ! 1925: continue; ! 1926: } ! 1927: } ! 1928: ! 1929: return 0; ! 1930: } ! 1931: ! 1932: /* ! 1933: * Return 1 if the 'f' is a valid filter program without a MATCH ! 1934: * instruction. Return 2 if it is a valid filter program with a MATCH ! 1935: * instruction. Otherwise, return 0. ! 1936: * The constraints are that each jump be forward and to a valid ! 1937: * code. The code must terminate with either an accept or reject. ! 1938: * 'valid' is an array for use by the routine (it must be at least ! 1939: * 'len' bytes long). ! 1940: * ! 1941: * The kernel needs to be able to verify an application's filter code. ! 1942: * Otherwise, a bogus program could easily crash the system. ! 1943: */ ! 1944: int ! 1945: bpf_validate(f, bytes, match) ! 1946: bpf_insn_t f; ! 1947: int bytes; ! 1948: bpf_insn_t *match; ! 1949: { ! 1950: register int i, j, len; ! 1951: register bpf_insn_t p; ! 1952: ! 1953: len = BPF_BYTES2LEN(bytes); ! 1954: /* f[0].code is already checked to be BPF_BEGIN. So skip f[0]. */ ! 1955: ! 1956: for (i = 1; i < len; ++i) { ! 1957: /* ! 1958: * Check that that jumps are forward, and within ! 1959: * the code block. ! 1960: */ ! 1961: p = &f[i]; ! 1962: if (BPF_CLASS(p->code) == BPF_JMP) { ! 1963: register int from = i + 1; ! 1964: ! 1965: if (BPF_OP(p->code) == BPF_JA) { ! 1966: if (from + p->k >= len) ! 1967: return 0; ! 1968: } ! 1969: else if (from + p->jt >= len || from + p->jf >= len) ! 1970: return 0; ! 1971: } ! 1972: /* ! 1973: * Check that memory operations use valid addresses. ! 1974: */ ! 1975: if ((BPF_CLASS(p->code) == BPF_ST || ! 1976: (BPF_CLASS(p->code) == BPF_LD && ! 1977: (p->code & 0xe0) == BPF_MEM)) && ! 1978: (p->k >= BPF_MEMWORDS || p->k < 0)) ! 1979: return 0; ! 1980: /* ! 1981: * Check for constant division by 0. ! 1982: */ ! 1983: if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) ! 1984: return 0; ! 1985: /* ! 1986: * Check for match instruction. ! 1987: * Only one match instruction per filter is allowed. ! 1988: */ ! 1989: if (p->code == (BPF_RET|BPF_MATCH_IMM)) { ! 1990: if (*match != 0 || ! 1991: p->jt == 0 || ! 1992: p->jt > N_NET_HASH_KEYS) ! 1993: return 0; ! 1994: i += p->jt; /* skip keys */ ! 1995: if (i + 1 > len) ! 1996: return 0; ! 1997: ! 1998: for (j = 1; j <= p->jt; j++) { ! 1999: if (p[j].code != (BPF_MISC|BPF_KEY)) ! 2000: return 0; ! 2001: } ! 2002: ! 2003: *match = p; ! 2004: } ! 2005: } ! 2006: if (BPF_CLASS(f[len - 1].code) == BPF_RET) ! 2007: return ((*match == 0) ? 1 : 2); ! 2008: else ! 2009: return 0; ! 2010: } ! 2011: ! 2012: int ! 2013: bpf_eq (f1, f2, bytes) ! 2014: register bpf_insn_t f1, f2; ! 2015: register int bytes; ! 2016: { ! 2017: register int count; ! 2018: ! 2019: count = BPF_BYTES2LEN(bytes); ! 2020: for (; count--; f1++, f2++) { ! 2021: if (!BPF_INSN_EQ(f1, f2)) { ! 2022: if ( f1->code == (BPF_MISC|BPF_KEY) && ! 2023: f2->code == (BPF_MISC|BPF_KEY) ) ! 2024: continue; ! 2025: return FALSE; ! 2026: } ! 2027: }; ! 2028: return TRUE; ! 2029: } ! 2030: ! 2031: unsigned int ! 2032: bpf_hash (n, keys) ! 2033: register int n; ! 2034: register unsigned int *keys; ! 2035: { ! 2036: register unsigned int hval = 0; ! 2037: ! 2038: while (n--) { ! 2039: hval += *keys++; ! 2040: } ! 2041: return (hval % NET_HASH_SIZE); ! 2042: } ! 2043: ! 2044: ! 2045: int ! 2046: bpf_match (hash, n_keys, keys, hash_headpp, entpp) ! 2047: net_hash_header_t hash; ! 2048: register int n_keys; ! 2049: register unsigned int *keys; ! 2050: net_hash_entry_t **hash_headpp, *entpp; ! 2051: { ! 2052: register net_hash_entry_t head, entp; ! 2053: register int i; ! 2054: ! 2055: if (n_keys != hash->n_keys) ! 2056: return FALSE; ! 2057: ! 2058: *hash_headpp = &hash->table[bpf_hash(n_keys, keys)]; ! 2059: head = **hash_headpp; ! 2060: ! 2061: if (head == 0) ! 2062: return FALSE; ! 2063: ! 2064: HASH_ITERATE (head, entp) ! 2065: { ! 2066: for (i = 0; i < n_keys; i++) { ! 2067: if (keys[i] != entp->keys[i]) ! 2068: break; ! 2069: } ! 2070: if (i == n_keys) { ! 2071: *entpp = entp; ! 2072: return TRUE; ! 2073: } ! 2074: } ! 2075: HASH_ITERATE_END (head, entp) ! 2076: return FALSE; ! 2077: } ! 2078: ! 2079: ! 2080: /* ! 2081: * Removes a hash entry (ENTP) from its queue (HEAD). ! 2082: * If the reference count of filter (HP) becomes zero and not USED, ! 2083: * HP is removed from ifp->if_rcv_port_list and is freed. ! 2084: */ ! 2085: ! 2086: int ! 2087: hash_ent_remove (ifp, hp, used, head, entp, dead_p) ! 2088: struct ifnet *ifp; ! 2089: net_hash_header_t hp; ! 2090: int used; ! 2091: net_hash_entry_t *head, entp; ! 2092: queue_entry_t *dead_p; ! 2093: { ! 2094: hp->ref_count--; ! 2095: ! 2096: if (*head == entp) { ! 2097: ! 2098: if (queue_empty((queue_t) entp)) { ! 2099: *head = 0; ! 2100: ENQUEUE_DEAD(*dead_p, entp); ! 2101: if (hp->ref_count == 0 && !used) { ! 2102: remqueue((queue_t) &ifp->if_rcv_port_list, ! 2103: (queue_entry_t)hp); ! 2104: hp->n_keys = 0; ! 2105: return TRUE; ! 2106: } ! 2107: return FALSE; ! 2108: } else { ! 2109: *head = (net_hash_entry_t)queue_next((queue_t) entp); ! 2110: } ! 2111: } ! 2112: ! 2113: remqueue((queue_t)*head, (queue_entry_t)entp); ! 2114: ENQUEUE_DEAD(*dead_p, entp); ! 2115: return FALSE; ! 2116: } ! 2117: ! 2118: int ! 2119: net_add_q_info (rcv_port) ! 2120: ipc_port_t rcv_port; ! 2121: { ! 2122: mach_port_msgcount_t qlimit = 0; ! 2123: ! 2124: /* ! 2125: * We use a new port, so increase net_queue_free_min ! 2126: * and net_kmsg_max to allow for more queued messages. ! 2127: */ ! 2128: ! 2129: if (IP_VALID(rcv_port)) { ! 2130: ip_lock(rcv_port); ! 2131: if (ip_active(rcv_port)) ! 2132: qlimit = rcv_port->ip_qlimit; ! 2133: ip_unlock(rcv_port); ! 2134: } ! 2135: ! 2136: simple_lock(&net_kmsg_total_lock); ! 2137: net_queue_free_min++; ! 2138: net_kmsg_max += qlimit + 1; ! 2139: simple_unlock(&net_kmsg_total_lock); ! 2140: ! 2141: return (int)qlimit; ! 2142: } ! 2143: ! 2144: net_del_q_info (qlimit) ! 2145: int qlimit; ! 2146: { ! 2147: simple_lock(&net_kmsg_total_lock); ! 2148: net_queue_free_min--; ! 2149: net_kmsg_max -= qlimit + 1; ! 2150: simple_unlock(&net_kmsg_total_lock); ! 2151: } ! 2152: ! 2153: ! 2154: /* ! 2155: * net_free_dead_infp (dead_infp) ! 2156: * queue_entry_t dead_infp; list of dead net_rcv_port_t. ! 2157: * ! 2158: * Deallocates dead net_rcv_port_t. ! 2159: * No locks should be held when called. ! 2160: */ ! 2161: net_free_dead_infp (dead_infp) ! 2162: queue_entry_t dead_infp; ! 2163: { ! 2164: register net_rcv_port_t infp, nextfp; ! 2165: ! 2166: for (infp = (net_rcv_port_t) dead_infp; infp != 0; infp = nextfp) ! 2167: { ! 2168: nextfp = (net_rcv_port_t) queue_next(&infp->chain); ! 2169: ipc_port_release_send(infp->rcv_port); ! 2170: net_del_q_info(infp->rcv_qlimit); ! 2171: zfree(net_rcv_zone, (vm_offset_t) infp); ! 2172: } ! 2173: } ! 2174: ! 2175: /* ! 2176: * net_free_dead_entp (dead_entp) ! 2177: * queue_entry_t dead_entp; list of dead net_hash_entry_t. ! 2178: * ! 2179: * Deallocates dead net_hash_entry_t. ! 2180: * No locks should be held when called. ! 2181: */ ! 2182: net_free_dead_entp (dead_entp) ! 2183: queue_entry_t dead_entp; ! 2184: { ! 2185: register net_hash_entry_t entp, nextentp; ! 2186: ! 2187: for (entp = (net_hash_entry_t)dead_entp; entp != 0; entp = nextentp) ! 2188: { ! 2189: nextentp = (net_hash_entry_t) queue_next(&entp->chain); ! 2190: ! 2191: ipc_port_release_send(entp->rcv_port); ! 2192: net_del_q_info(entp->rcv_qlimit); ! 2193: zfree(net_hash_entry_zone, (vm_offset_t) entp); ! 2194: } ! 2195: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.