|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* ! 26: * Copyright (c) 1995, 1994, 1993, 1992, 1991, 1990 ! 27: * Open Software Foundation, Inc. ! 28: * ! 29: * Permission to use, copy, modify, and distribute this software and ! 30: * its documentation for any purpose and without fee is hereby granted, ! 31: * provided that the above copyright notice appears in all copies and ! 32: * that both the copyright notice and this permission notice appear in ! 33: * supporting documentation, and that the name of ("OSF") or Open Software ! 34: * Foundation not be used in advertising or publicity pertaining to ! 35: * distribution of the software without specific, written prior permission. ! 36: * ! 37: * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE ! 38: * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ! 39: * FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL OSF BE LIABLE FOR ANY ! 40: * SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ! 41: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN ! 42: * ACTION OF CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING ! 43: * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE ! 44: */ ! 45: /* ! 46: * OSF Research Institute MK6.1 (unencumbered) 1/31/1995 ! 47: */ ! 48: /* ! 49: * Mach Operating System ! 50: * Copyright (c) 1991,1990,1989 Carnegie Mellon University ! 51: * All Rights Reserved. ! 52: * ! 53: * Permission to use, copy, modify and distribute this software and its ! 54: * documentation is hereby granted, provided that both the copyright ! 55: * notice and this permission notice appear in all copies of the ! 56: * software, derivative works or modified versions, and any portions ! 57: * thereof, and that both notices appear in supporting documentation. ! 58: * ! 59: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 60: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 61: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 62: * ! 63: * Carnegie Mellon requests users of this software to return to ! 64: * ! 65: * Software Distribution Coordinator or [email protected] ! 66: * School of Computer Science ! 67: * Carnegie Mellon University ! 68: * Pittsburgh PA 15213-3890 ! 69: * ! 70: * any improvements or extensions that they make and grant Carnegie Mellon ! 71: * the rights to redistribute these changes. ! 72: */ ! 73: /* ! 74: * File: ipc/mach_port.c ! 75: * Author: Rich Draves ! 76: * Date: 1989 ! 77: * ! 78: * Exported kernel calls. See mach/mach_port.defs. ! 79: */ ! 80: ! 81: #import <mach/features.h> ! 82: ! 83: #include <mach/port.h> ! 84: #include <mach/kern_return.h> ! 85: #include <mach/notify.h> ! 86: #include <mach/vm_param.h> ! 87: #include <mach/vm_prot.h> ! 88: #include <vm/vm_map.h> ! 89: #include <vm/vm_kern.h> ! 90: #include <vm/vm_user.h> ! 91: #include <ipc/ipc_entry.h> ! 92: #include <ipc/ipc_space.h> ! 93: #include <ipc/ipc_object.h> ! 94: #include <ipc/ipc_notify.h> ! 95: #include <ipc/ipc_port.h> ! 96: #include <ipc/ipc_pset.h> ! 97: #include <ipc/ipc_right.h> ! 98: ! 99: /* ! 100: * Forward declarations ! 101: */ ! 102: void mach_port_names_helper( ! 103: ipc_port_timestamp_t timestamp, ! 104: ipc_entry_t entry, ! 105: mach_port_t name, ! 106: mach_port_t *names, ! 107: mach_port_type_t *types, ! 108: ipc_entry_num_t *actualp); ! 109: ! 110: void mach_port_gst_helper( ! 111: ipc_pset_t pset, ! 112: ipc_port_t port, ! 113: ipc_entry_num_t maxnames, ! 114: mach_port_t *names, ! 115: ipc_entry_num_t *actualp); ! 116: ! 117: ! 118: /* ! 119: * Routine: mach_port_names_helper ! 120: * Purpose: ! 121: * A helper function for mach_port_names. ! 122: */ ! 123: ! 124: void ! 125: mach_port_names_helper( ! 126: ipc_port_timestamp_t timestamp, ! 127: ipc_entry_t entry, ! 128: mach_port_t name, ! 129: mach_port_t *names, ! 130: mach_port_type_t *types, ! 131: ipc_entry_num_t *actualp) ! 132: { ! 133: ipc_entry_bits_t bits = entry->ie_bits; ! 134: ipc_port_request_index_t request = entry->ie_request; ! 135: mach_port_type_t type; ! 136: ipc_entry_num_t actual; ! 137: ! 138: if (bits & MACH_PORT_TYPE_SEND_RIGHTS) { ! 139: ipc_port_t port; ! 140: boolean_t died; ! 141: ! 142: port = (ipc_port_t) entry->ie_object; ! 143: assert(port != IP_NULL); ! 144: ! 145: /* ! 146: * The timestamp serializes mach_port_names ! 147: * with ipc_port_destroy. If the port died, ! 148: * but after mach_port_names started, pretend ! 149: * that it isn't dead. ! 150: */ ! 151: ! 152: ip_lock(port); ! 153: died = (!ip_active(port) && ! 154: IP_TIMESTAMP_ORDER(port->ip_timestamp, timestamp)); ! 155: ip_unlock(port); ! 156: ! 157: if (died) { ! 158: #if MACH_IPC_COMPAT ! 159: if (bits & IE_BITS_COMPAT) ! 160: return; ! 161: #endif /* MACH_IPC_COMPAT */ ! 162: ! 163: /* pretend this is a dead-name entry */ ! 164: ! 165: bits &= ~(IE_BITS_TYPE_MASK|IE_BITS_MAREQUEST); ! 166: bits |= MACH_PORT_TYPE_DEAD_NAME; ! 167: if (request != 0) ! 168: bits++; ! 169: request = 0; ! 170: } ! 171: } ! 172: ! 173: type = IE_BITS_TYPE(bits); ! 174: #if MACH_IPC_COMPAT ! 175: if (bits & IE_BITS_COMPAT) ! 176: type |= MACH_PORT_TYPE_COMPAT; ! 177: else ! 178: #endif /* MACH_IPC_COMPAT */ ! 179: if (request != 0) ! 180: type |= MACH_PORT_TYPE_DNREQUEST; ! 181: if (bits & IE_BITS_MAREQUEST) ! 182: type |= MACH_PORT_TYPE_MAREQUEST; ! 183: ! 184: actual = *actualp; ! 185: names[actual] = name; ! 186: types[actual] = type; ! 187: *actualp = actual+1; ! 188: } ! 189: ! 190: /* ! 191: * Routine: mach_port_names [kernel call] ! 192: * Purpose: ! 193: * Retrieves a list of the rights present in the space, ! 194: * along with type information. (Same as returned ! 195: * by mach_port_type.) The names are returned in ! 196: * no particular order, but they (and the type info) ! 197: * are an accurate snapshot of the space. ! 198: * Conditions: ! 199: * Nothing locked. ! 200: * Returns: ! 201: * KERN_SUCCESS Arrays of names and types returned. ! 202: * KERN_INVALID_TASK The space is null. ! 203: * KERN_INVALID_TASK The space is dead. ! 204: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 205: */ ! 206: ! 207: kern_return_t ! 208: mach_port_names( ! 209: ipc_space_t space, ! 210: mach_port_t **namesp, ! 211: mach_msg_type_number_t *namesCnt, ! 212: mach_port_type_t **typesp, ! 213: mach_msg_type_number_t *typesCnt) ! 214: { ! 215: ipc_tree_entry_t tentry; ! 216: ipc_entry_t table; ! 217: ipc_entry_num_t tsize; ! 218: mach_port_index_t index; ! 219: ipc_entry_num_t actual; /* this many names */ ! 220: ipc_port_timestamp_t timestamp; /* logical time of this operation */ ! 221: mach_port_t *names; ! 222: mach_port_type_t *types; ! 223: kern_return_t kr; ! 224: ! 225: vm_size_t size; /* size of allocated memory */ ! 226: vm_offset_t addr1; /* allocated memory, for names */ ! 227: vm_offset_t addr2; /* allocated memory, for types */ ! 228: #if MACH_OLD_VM_COPY ! 229: vm_offset_t memory1; /* copied-in memory, for names */ ! 230: vm_offset_t memory2; /* copied-in memory, for types */ ! 231: #else /* MACH_OLD_VM_COPY */ ! 232: vm_map_copy_t memory1; /* copied-in memory, for names */ ! 233: vm_map_copy_t memory2; /* copied-in memory, for types */ ! 234: #endif /* MACH_OLD_VM_COPY */ ! 235: ! 236: /* safe simplifying assumption */ ! 237: assert_static(sizeof(mach_port_t) == sizeof(mach_port_type_t)); ! 238: ! 239: if (space == IS_NULL) ! 240: return KERN_INVALID_TASK; ! 241: ! 242: size = 0; ! 243: ! 244: for (;;) { ! 245: ipc_entry_num_t bound; ! 246: vm_size_t size_needed; ! 247: ! 248: is_read_lock(space); ! 249: if (!space->is_active) { ! 250: is_read_unlock(space); ! 251: if (size != 0) { ! 252: kmem_free(ipc_kernel_map, addr1, size); ! 253: kmem_free(ipc_kernel_map, addr2, size); ! 254: } ! 255: return KERN_INVALID_TASK; ! 256: } ! 257: ! 258: /* upper bound on number of names in the space */ ! 259: ! 260: bound = space->is_table_size + space->is_tree_total; ! 261: size_needed = round_page(bound * sizeof(mach_port_t)); ! 262: ! 263: if (size_needed <= size) ! 264: break; ! 265: ! 266: is_read_unlock(space); ! 267: ! 268: if (size != 0) { ! 269: kmem_free(ipc_kernel_map, addr1, size); ! 270: kmem_free(ipc_kernel_map, addr2, size); ! 271: } ! 272: size = size_needed; ! 273: ! 274: kr = vm_allocate(ipc_kernel_map, &addr1, size, TRUE); ! 275: if (kr != KERN_SUCCESS) ! 276: return KERN_RESOURCE_SHORTAGE; ! 277: ! 278: kr = vm_allocate(ipc_kernel_map, &addr2, size, TRUE); ! 279: if (kr != KERN_SUCCESS) { ! 280: kmem_free(ipc_kernel_map, addr1, size); ! 281: return KERN_RESOURCE_SHORTAGE; ! 282: } ! 283: ! 284: /* can't fault while we hold locks */ ! 285: ! 286: #if MACH_OLD_VM_COPY ! 287: kr = vm_map_pageable(ipc_kernel_map, addr1, addr1 + size, ! 288: FALSE); ! 289: assert(kr == KERN_SUCCESS); ! 290: ! 291: kr = vm_map_pageable(ipc_kernel_map, addr2, addr2 + size, ! 292: FALSE); ! 293: assert(kr == KERN_SUCCESS); ! 294: #else /* MACH_OLD_VM_COPY */ ! 295: kr = vm_map_wire(ipc_kernel_map, addr1, addr1 + size, ! 296: VM_PROT_READ|VM_PROT_WRITE, FALSE); ! 297: assert(kr == KERN_SUCCESS); ! 298: ! 299: kr = vm_map_wire(ipc_kernel_map, addr2, addr2 + size, ! 300: VM_PROT_READ|VM_PROT_WRITE, FALSE); ! 301: assert(kr == KERN_SUCCESS); ! 302: #endif /* MACH_OLD_VM_COPY */ ! 303: } ! 304: /* space is read-locked and active */ ! 305: ! 306: names = (mach_port_t *) addr1; ! 307: types = (mach_port_type_t *) addr2; ! 308: actual = 0; ! 309: ! 310: timestamp = ipc_port_timestamp(); ! 311: ! 312: table = space->is_table; ! 313: tsize = space->is_table_size; ! 314: ! 315: for (index = 0; index < tsize; index++) { ! 316: ipc_entry_t entry = &table[index]; ! 317: ipc_entry_bits_t bits = entry->ie_bits; ! 318: ! 319: if (IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE) { ! 320: mach_port_t name = MACH_PORT_MAKEB(index, bits); ! 321: ! 322: mach_port_names_helper(timestamp, entry, name, ! 323: names, types, &actual); ! 324: } ! 325: } ! 326: ! 327: for (tentry = ipc_splay_traverse_start(&space->is_tree); ! 328: tentry != ITE_NULL; ! 329: tentry = ipc_splay_traverse_next(&space->is_tree, FALSE)) { ! 330: ipc_entry_t entry = &tentry->ite_entry; ! 331: mach_port_t name = tentry->ite_name; ! 332: ! 333: assert(IE_BITS_TYPE(tentry->ite_bits) != ! 334: MACH_PORT_TYPE_NONE); ! 335: ! 336: mach_port_names_helper(timestamp, entry, name, ! 337: names, types, &actual); ! 338: } ! 339: ipc_splay_traverse_finish(&space->is_tree); ! 340: is_read_unlock(space); ! 341: ! 342: if (actual == 0) { ! 343: #if MACH_OLD_VM_COPY ! 344: memory1 = 0; ! 345: memory2 = 0; ! 346: #else /* MACH_OLD_VM_COPY */ ! 347: memory1 = VM_MAP_COPY_NULL; ! 348: memory2 = VM_MAP_COPY_NULL; ! 349: #endif /* MACH_OLD_VM_COPY */ ! 350: ! 351: if (size != 0) { ! 352: kmem_free(ipc_kernel_map, addr1, size); ! 353: kmem_free(ipc_kernel_map, addr2, size); ! 354: } ! 355: } else { ! 356: vm_size_t size_used; ! 357: vm_size_t vm_size_used; ! 358: ! 359: size_used = actual * sizeof(mach_port_t); ! 360: vm_size_used = round_page(size_used); ! 361: ! 362: /* ! 363: * Make used memory pageable and get it into ! 364: * copied-in form. Free any unused memory. ! 365: */ ! 366: ! 367: #if MACH_OLD_VM_COPY ! 368: kr = vm_map_pageable(ipc_kernel_map, ! 369: addr1, addr1 + vm_size_used, ! 370: TRUE); ! 371: assert(kr == KERN_SUCCESS); ! 372: ! 373: kr = vm_map_pageable(ipc_kernel_map, ! 374: addr2, addr2 + vm_size_used, ! 375: TRUE); ! 376: assert(kr == KERN_SUCCESS); ! 377: ! 378: kr = vm_move( ! 379: ipc_kernel_map, addr1, ! 380: ipc_soft_map, size_used, ! 381: TRUE, &memory1); ! 382: assert(kr == KERN_SUCCESS); ! 383: ! 384: kr = vm_move( ! 385: ipc_kernel_map, addr2, ! 386: ipc_soft_map, size_used, ! 387: TRUE, &memory2); ! 388: assert(kr == KERN_SUCCESS); ! 389: #else /* MACH_OLD_VM_COPY */ ! 390: kr = vm_map_unwire(ipc_kernel_map, ! 391: addr1, addr1 + vm_size_used, FALSE); ! 392: assert(kr == KERN_SUCCESS); ! 393: ! 394: kr = vm_map_unwire(ipc_kernel_map, ! 395: addr2, addr2 + vm_size_used, FALSE); ! 396: assert(kr == KERN_SUCCESS); ! 397: ! 398: kr = vm_map_copyin(ipc_kernel_map, addr1, size_used, ! 399: TRUE, &memory1); ! 400: assert(kr == KERN_SUCCESS); ! 401: ! 402: kr = vm_map_copyin(ipc_kernel_map, addr2, size_used, ! 403: TRUE, &memory2); ! 404: assert(kr == KERN_SUCCESS); ! 405: #endif /* MACH_OLD_VM_COPY */ ! 406: ! 407: if (vm_size_used != size) { ! 408: kmem_free(ipc_kernel_map, ! 409: addr1 + vm_size_used, size - vm_size_used); ! 410: kmem_free(ipc_kernel_map, ! 411: addr2 + vm_size_used, size - vm_size_used); ! 412: } ! 413: } ! 414: ! 415: *namesp = (mach_port_t *) memory1; ! 416: *namesCnt = actual; ! 417: *typesp = (mach_port_type_t *) memory2; ! 418: *typesCnt = actual; ! 419: return KERN_SUCCESS; ! 420: } ! 421: ! 422: /* ! 423: * Routine: mach_port_type [kernel call] ! 424: * Purpose: ! 425: * Retrieves the type of a right in the space. ! 426: * The type is a bitwise combination of one or more ! 427: * of the following type bits: ! 428: * MACH_PORT_TYPE_SEND ! 429: * MACH_PORT_TYPE_RECEIVE ! 430: * MACH_PORT_TYPE_SEND_ONCE ! 431: * MACH_PORT_TYPE_PORT_SET ! 432: * MACH_PORT_TYPE_DEAD_NAME ! 433: * In addition, the following pseudo-type bits may be present: ! 434: * MACH_PORT_TYPE_DNREQUEST ! 435: * A dead-name notification is requested. ! 436: * MACH_PORT_TYPE_MAREQUEST ! 437: * The send/receive right is blocked; ! 438: * a msg-accepted notification is outstanding. ! 439: * MACH_PORT_TYPE_COMPAT ! 440: * This is a compatibility-mode right; ! 441: * when the port dies, it will disappear ! 442: * instead of turning into a dead-name. ! 443: * Conditions: ! 444: * Nothing locked. ! 445: * Returns: ! 446: * KERN_SUCCESS Type is returned. ! 447: * KERN_INVALID_TASK The space is null. ! 448: * KERN_INVALID_TASK The space is dead. ! 449: * KERN_INVALID_NAME The name doesn't denote a right. ! 450: */ ! 451: ! 452: kern_return_t ! 453: mach_port_type( ! 454: ipc_space_t space, ! 455: mach_port_t name, ! 456: mach_port_type_t *typep) ! 457: { ! 458: mach_port_urefs_t urefs; ! 459: ipc_entry_t entry; ! 460: kern_return_t kr; ! 461: ! 462: if (space == IS_NULL) ! 463: return KERN_INVALID_TASK; ! 464: ! 465: kr = ipc_right_lookup_write(space, name, &entry); ! 466: if (kr != KERN_SUCCESS) ! 467: return kr; ! 468: /* space is write-locked and active */ ! 469: ! 470: kr = ipc_right_info(space, name, entry, typep, &urefs); ! 471: if (kr == KERN_SUCCESS) ! 472: is_write_unlock(space); ! 473: /* space is unlocked */ ! 474: return kr; ! 475: } ! 476: ! 477: /* ! 478: * Routine: mach_port_rename [kernel call] ! 479: * Purpose: ! 480: * Changes the name denoting a right, ! 481: * from oname to nname. ! 482: * Conditions: ! 483: * Nothing locked. ! 484: * Returns: ! 485: * KERN_SUCCESS The right is renamed. ! 486: * KERN_INVALID_TASK The space is null. ! 487: * KERN_INVALID_TASK The space is dead. ! 488: * KERN_INVALID_NAME The oname doesn't denote a right. ! 489: * KERN_INVALID_VALUE The nname isn't a legal name. ! 490: * KERN_NAME_EXISTS The nname already denotes a right. ! 491: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 492: */ ! 493: ! 494: kern_return_t ! 495: mach_port_rename( ! 496: ipc_space_t space, ! 497: mach_port_t oname, ! 498: mach_port_t nname) ! 499: { ! 500: if (space == IS_NULL) ! 501: return KERN_INVALID_TASK; ! 502: ! 503: if (!MACH_PORT_VALID(nname)) ! 504: return KERN_INVALID_VALUE; ! 505: ! 506: return ipc_object_rename(space, oname, nname); ! 507: } ! 508: ! 509: /* ! 510: * Routine: mach_port_allocate_name [kernel call] ! 511: * Purpose: ! 512: * Allocates a right in a space, using a specific name ! 513: * for the new right. Possible rights: ! 514: * MACH_PORT_RIGHT_RECEIVE ! 515: * MACH_PORT_RIGHT_PORT_SET ! 516: * MACH_PORT_RIGHT_DEAD_NAME ! 517: * ! 518: * A new port (allocated with MACH_PORT_RIGHT_RECEIVE) ! 519: * has no extant send or send-once rights and no queued ! 520: * messages. Its queue limit is MACH_PORT_QLIMIT_DEFAULT ! 521: * and its make-send count is 0. It is not a member of ! 522: * a port set. It has no registered no-senders or ! 523: * port-destroyed notification requests. ! 524: * ! 525: * A new port set has no members. ! 526: * ! 527: * A new dead name has one user reference. ! 528: * Conditions: ! 529: * Nothing locked. ! 530: * Returns: ! 531: * KERN_SUCCESS The right is allocated. ! 532: * KERN_INVALID_TASK The space is null. ! 533: * KERN_INVALID_TASK The space is dead. ! 534: * KERN_INVALID_VALUE The name isn't a legal name. ! 535: * KERN_INVALID_VALUE "right" isn't a legal kind of right. ! 536: * KERN_NAME_EXISTS The name already denotes a right. ! 537: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 538: */ ! 539: ! 540: kern_return_t ! 541: mach_port_allocate_name( ! 542: ipc_space_t space, ! 543: mach_port_right_t right, ! 544: mach_port_t name) ! 545: { ! 546: kern_return_t kr; ! 547: ! 548: if (space == IS_NULL) ! 549: return KERN_INVALID_TASK; ! 550: ! 551: if (!MACH_PORT_VALID(name)) ! 552: return KERN_INVALID_VALUE; ! 553: ! 554: switch (right) { ! 555: case MACH_PORT_RIGHT_RECEIVE: { ! 556: ipc_port_t port; ! 557: ! 558: kr = ipc_port_alloc_name(space, name, &port); ! 559: if (kr == KERN_SUCCESS) ! 560: ip_unlock(port); ! 561: break; ! 562: } ! 563: ! 564: case MACH_PORT_RIGHT_PORT_SET: { ! 565: ipc_pset_t pset; ! 566: ! 567: kr = ipc_pset_alloc_name(space, name, &pset); ! 568: if (kr == KERN_SUCCESS) ! 569: ips_unlock(pset); ! 570: break; ! 571: } ! 572: ! 573: case MACH_PORT_RIGHT_DEAD_NAME: ! 574: kr = ipc_object_alloc_dead_name(space, name); ! 575: break; ! 576: ! 577: default: ! 578: kr = KERN_INVALID_VALUE; ! 579: break; ! 580: } ! 581: ! 582: return kr; ! 583: } ! 584: ! 585: /* ! 586: * Routine: mach_port_allocate [kernel call] ! 587: * Purpose: ! 588: * Allocates a right in a space. Like mach_port_allocate_name, ! 589: * except that the implementation picks a name for the right. ! 590: * The name may be any legal name in the space that doesn't ! 591: * currently denote a right. ! 592: * Conditions: ! 593: * Nothing locked. ! 594: * Returns: ! 595: * KERN_SUCCESS The right is allocated. ! 596: * KERN_INVALID_TASK The space is null. ! 597: * KERN_INVALID_TASK The space is dead. ! 598: * KERN_INVALID_VALUE "right" isn't a legal kind of right. ! 599: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 600: * KERN_NO_SPACE No room in space for another right. ! 601: */ ! 602: ! 603: kern_return_t ! 604: mach_port_allocate( ! 605: ipc_space_t space, ! 606: mach_port_right_t right, ! 607: mach_port_t *namep) ! 608: { ! 609: kern_return_t kr; ! 610: ! 611: if (space == IS_NULL) ! 612: return KERN_INVALID_TASK; ! 613: ! 614: switch (right) { ! 615: case MACH_PORT_RIGHT_RECEIVE: { ! 616: ipc_port_t port; ! 617: ! 618: kr = ipc_port_alloc(space, namep, &port); ! 619: if (kr == KERN_SUCCESS) ! 620: ip_unlock(port); ! 621: break; ! 622: } ! 623: ! 624: case MACH_PORT_RIGHT_PORT_SET: { ! 625: ipc_pset_t pset; ! 626: ! 627: kr = ipc_pset_alloc(space, namep, &pset); ! 628: if (kr == KERN_SUCCESS) ! 629: ips_unlock(pset); ! 630: break; ! 631: } ! 632: ! 633: case MACH_PORT_RIGHT_DEAD_NAME: ! 634: kr = ipc_object_alloc_dead(space, namep); ! 635: break; ! 636: ! 637: default: ! 638: kr = KERN_INVALID_VALUE; ! 639: break; ! 640: } ! 641: ! 642: return kr; ! 643: } ! 644: ! 645: /* ! 646: * Routine: mach_port_destroy [kernel call] ! 647: * Purpose: ! 648: * Cleans up and destroys all rights denoted by a name ! 649: * in a space. The destruction of a receive right ! 650: * destroys the port, unless a port-destroyed request ! 651: * has been made for it; the destruction of a port-set right ! 652: * destroys the port set. ! 653: * Conditions: ! 654: * Nothing locked. ! 655: * Returns: ! 656: * KERN_SUCCESS The name is destroyed. ! 657: * KERN_INVALID_TASK The space is null. ! 658: * KERN_INVALID_TASK The space is dead. ! 659: * KERN_INVALID_NAME The name doesn't denote a right. ! 660: */ ! 661: ! 662: kern_return_t ! 663: mach_port_destroy( ! 664: ipc_space_t space, ! 665: mach_port_t name) ! 666: { ! 667: ipc_entry_t entry; ! 668: kern_return_t kr; ! 669: ! 670: if (space == IS_NULL) ! 671: return KERN_INVALID_TASK; ! 672: ! 673: kr = ipc_right_lookup_write(space, name, &entry); ! 674: if (kr != KERN_SUCCESS) ! 675: return kr; ! 676: /* space is write-locked and active */ ! 677: ! 678: kr = ipc_right_destroy(space, name, entry); /* unlocks space */ ! 679: return kr; ! 680: } ! 681: ! 682: /* ! 683: * Routine: mach_port_deallocate [kernel call] ! 684: * Purpose: ! 685: * Deallocates a user reference from a send right, ! 686: * send-once right, or a dead-name right. May ! 687: * deallocate the right, if this is the last uref, ! 688: * and destroy the name, if it doesn't denote ! 689: * other rights. ! 690: * Conditions: ! 691: * Nothing locked. ! 692: * Returns: ! 693: * KERN_SUCCESS The uref is deallocated. ! 694: * KERN_INVALID_TASK The space is null. ! 695: * KERN_INVALID_TASK The space is dead. ! 696: * KERN_INVALID_NAME The name doesn't denote a right. ! 697: * KERN_INVALID_RIGHT The right isn't correct. ! 698: */ ! 699: ! 700: kern_return_t ! 701: mach_port_deallocate( ! 702: ipc_space_t space, ! 703: mach_port_t name) ! 704: { ! 705: ipc_entry_t entry; ! 706: kern_return_t kr; ! 707: ! 708: if (space == IS_NULL) ! 709: return KERN_INVALID_TASK; ! 710: ! 711: kr = ipc_right_lookup_write(space, name, &entry); ! 712: if (kr != KERN_SUCCESS) ! 713: return kr; ! 714: /* space is write-locked */ ! 715: ! 716: kr = ipc_right_dealloc(space, name, entry); /* unlocks space */ ! 717: return kr; ! 718: } ! 719: ! 720: /* ! 721: * Routine: mach_port_get_refs [kernel call] ! 722: * Purpose: ! 723: * Retrieves the number of user references held by a right. ! 724: * Receive rights, port-set rights, and send-once rights ! 725: * always have one user reference. Returns zero if the ! 726: * name denotes a right, but not the queried right. ! 727: * Conditions: ! 728: * Nothing locked. ! 729: * Returns: ! 730: * KERN_SUCCESS Number of urefs returned. ! 731: * KERN_INVALID_TASK The space is null. ! 732: * KERN_INVALID_TASK The space is dead. ! 733: * KERN_INVALID_VALUE "right" isn't a legal value. ! 734: * KERN_INVALID_NAME The name doesn't denote a right. ! 735: */ ! 736: ! 737: kern_return_t ! 738: mach_port_get_refs( ! 739: ipc_space_t space, ! 740: mach_port_t name, ! 741: mach_port_right_t right, ! 742: mach_port_urefs_t *urefsp) ! 743: { ! 744: mach_port_type_t type; ! 745: mach_port_urefs_t urefs; ! 746: ipc_entry_t entry; ! 747: kern_return_t kr; ! 748: ! 749: if (space == IS_NULL) ! 750: return KERN_INVALID_TASK; ! 751: ! 752: if (right >= MACH_PORT_RIGHT_NUMBER) ! 753: return KERN_INVALID_VALUE; ! 754: ! 755: kr = ipc_right_lookup_write(space, name, &entry); ! 756: if (kr != KERN_SUCCESS) ! 757: return kr; ! 758: /* space is write-locked and active */ ! 759: ! 760: kr = ipc_right_info(space, name, entry, &type, &urefs); /* unlocks */ ! 761: if (kr != KERN_SUCCESS) ! 762: return kr; /* space is unlocked */ ! 763: is_write_unlock(space); ! 764: ! 765: if (type & MACH_PORT_TYPE(right)) ! 766: switch (right) { ! 767: case MACH_PORT_RIGHT_SEND_ONCE: ! 768: assert(urefs == 1); ! 769: /* fall-through */ ! 770: ! 771: case MACH_PORT_RIGHT_PORT_SET: ! 772: case MACH_PORT_RIGHT_RECEIVE: ! 773: *urefsp = 1; ! 774: break; ! 775: ! 776: case MACH_PORT_RIGHT_DEAD_NAME: ! 777: case MACH_PORT_RIGHT_SEND: ! 778: assert(urefs > 0); ! 779: *urefsp = urefs; ! 780: break; ! 781: ! 782: default: ! 783: panic("mach_port_get_refs: strange rights"); ! 784: } ! 785: else ! 786: *urefsp = 0; ! 787: ! 788: return kr; ! 789: } ! 790: ! 791: /* ! 792: * Routine: mach_port_mod_refs ! 793: * Purpose: ! 794: * Modifies the number of user references held by a right. ! 795: * The resulting number of user references must be non-negative. ! 796: * If it is zero, the right is deallocated. If the name ! 797: * doesn't denote other rights, it is destroyed. ! 798: * Conditions: ! 799: * Nothing locked. ! 800: * Returns: ! 801: * KERN_SUCCESS Modified number of urefs. ! 802: * KERN_INVALID_TASK The space is null. ! 803: * KERN_INVALID_TASK The space is dead. ! 804: * KERN_INVALID_VALUE "right" isn't a legal value. ! 805: * KERN_INVALID_NAME The name doesn't denote a right. ! 806: * KERN_INVALID_RIGHT Name doesn't denote specified right. ! 807: * KERN_INVALID_VALUE Impossible modification to urefs. ! 808: * KERN_UREFS_OVERFLOW Urefs would overflow. ! 809: */ ! 810: ! 811: kern_return_t ! 812: mach_port_mod_refs( ! 813: ipc_space_t space, ! 814: mach_port_t name, ! 815: mach_port_right_t right, ! 816: mach_port_delta_t delta) ! 817: { ! 818: ipc_entry_t entry; ! 819: kern_return_t kr; ! 820: ! 821: if (space == IS_NULL) ! 822: return KERN_INVALID_TASK; ! 823: ! 824: if (right >= MACH_PORT_RIGHT_NUMBER) ! 825: return KERN_INVALID_VALUE; ! 826: ! 827: kr = ipc_right_lookup_write(space, name, &entry); ! 828: if (kr != KERN_SUCCESS) ! 829: return kr; ! 830: /* space is write-locked and active */ ! 831: ! 832: kr = ipc_right_delta(space, name, entry, right, delta); /* unlocks */ ! 833: return kr; ! 834: } ! 835: ! 836: /* ! 837: * Routine: mach_port_set_qlimit [kernel call] ! 838: * Purpose: ! 839: * Changes a receive right's queue limit. ! 840: * The new queue limit must be between 0 and ! 841: * MACH_PORT_QLIMIT_MAX, inclusive. ! 842: * Conditions: ! 843: * Nothing locked. ! 844: * Returns: ! 845: * KERN_SUCCESS Set queue limit. ! 846: * KERN_INVALID_TASK The space is null. ! 847: * KERN_INVALID_TASK The space is dead. ! 848: * KERN_INVALID_NAME The name doesn't denote a right. ! 849: * KERN_INVALID_RIGHT Name doesn't denote receive rights. ! 850: * KERN_INVALID_VALUE Illegal queue limit. ! 851: */ ! 852: ! 853: kern_return_t ! 854: mach_port_set_qlimit( ! 855: ipc_space_t space, ! 856: mach_port_t name, ! 857: mach_port_msgcount_t qlimit) ! 858: { ! 859: ipc_port_t port; ! 860: kern_return_t kr; ! 861: ! 862: if (space == IS_NULL) ! 863: return KERN_INVALID_TASK; ! 864: ! 865: if (qlimit > MACH_PORT_QLIMIT_MAX) ! 866: return KERN_INVALID_VALUE; ! 867: ! 868: kr = ipc_port_translate_receive(space, name, &port); ! 869: if (kr != KERN_SUCCESS) ! 870: return kr; ! 871: /* port is locked and active */ ! 872: ! 873: ipc_port_set_qlimit(port, qlimit); ! 874: ! 875: ip_unlock(port); ! 876: return KERN_SUCCESS; ! 877: } ! 878: ! 879: /* ! 880: * Routine: mach_port_set_mscount [kernel call] ! 881: * Purpose: ! 882: * Changes a receive right's make-send count. ! 883: * Conditions: ! 884: * Nothing locked. ! 885: * Returns: ! 886: * KERN_SUCCESS Set make-send count. ! 887: * KERN_INVALID_TASK The space is null. ! 888: * KERN_INVALID_TASK The space is dead. ! 889: * KERN_INVALID_NAME The name doesn't denote a right. ! 890: * KERN_INVALID_RIGHT Name doesn't denote receive rights. ! 891: */ ! 892: ! 893: kern_return_t ! 894: mach_port_set_mscount( ! 895: ipc_space_t space, ! 896: mach_port_t name, ! 897: mach_port_mscount_t mscount) ! 898: { ! 899: ipc_port_t port; ! 900: kern_return_t kr; ! 901: ! 902: if (space == IS_NULL) ! 903: return KERN_INVALID_TASK; ! 904: ! 905: kr = ipc_port_translate_receive(space, name, &port); ! 906: if (kr != KERN_SUCCESS) ! 907: return kr; ! 908: /* port is locked and active */ ! 909: ! 910: ipc_port_set_mscount(port, mscount); ! 911: ! 912: ip_unlock(port); ! 913: return KERN_SUCCESS; ! 914: } ! 915: ! 916: /* ! 917: * Routine: mach_port_set_seqno [kernel call] ! 918: * Purpose: ! 919: * Changes a receive right's sequence number. ! 920: * Conditions: ! 921: * Nothing locked. ! 922: * Returns: ! 923: * KERN_SUCCESS Set sequence number. ! 924: * KERN_INVALID_TASK The space is null. ! 925: * KERN_INVALID_TASK The space is dead. ! 926: * KERN_INVALID_NAME The name doesn't denote a right. ! 927: * KERN_INVALID_RIGHT Name doesn't denote receive rights. ! 928: */ ! 929: ! 930: kern_return_t ! 931: mach_port_set_seqno( ! 932: ipc_space_t space, ! 933: mach_port_t name, ! 934: mach_port_seqno_t seqno) ! 935: { ! 936: ipc_port_t port; ! 937: kern_return_t kr; ! 938: ! 939: if (space == IS_NULL) ! 940: return KERN_INVALID_TASK; ! 941: ! 942: kr = ipc_port_translate_receive(space, name, &port); ! 943: if (kr != KERN_SUCCESS) ! 944: return kr; ! 945: /* port is locked and active */ ! 946: ! 947: ipc_port_set_seqno(port, seqno); ! 948: ! 949: ip_unlock(port); ! 950: return KERN_SUCCESS; ! 951: } ! 952: ! 953: /* ! 954: * Routine: mach_port_gst_helper ! 955: * Purpose: ! 956: * A helper function for mach_port_get_set_status. ! 957: */ ! 958: ! 959: void ! 960: mach_port_gst_helper( ! 961: ipc_pset_t pset, ! 962: ipc_port_t port, ! 963: ipc_entry_num_t maxnames, ! 964: mach_port_t *names, ! 965: ipc_entry_num_t *actualp) ! 966: { ! 967: ipc_pset_t ip_pset; ! 968: mach_port_t name; ! 969: ! 970: assert(port != IP_NULL); ! 971: ! 972: ip_lock(port); ! 973: assert(ip_active(port)); ! 974: ! 975: name = port->ip_receiver_name; ! 976: assert(name != MACH_PORT_NULL); ! 977: ip_pset = port->ip_pset; ! 978: ! 979: ip_unlock(port); ! 980: ! 981: if (pset == ip_pset) { ! 982: ipc_entry_num_t actual = *actualp; ! 983: ! 984: if (actual < maxnames) ! 985: names[actual] = name; ! 986: ! 987: *actualp = actual+1; ! 988: } ! 989: } ! 990: ! 991: /* ! 992: * Routine: mach_port_get_set_status [kernel call] ! 993: * Purpose: ! 994: * Retrieves a list of members in a port set. ! 995: * Returns the space's name for each receive right member. ! 996: * Conditions: ! 997: * Nothing locked. ! 998: * Returns: ! 999: * KERN_SUCCESS Retrieved list of members. ! 1000: * KERN_INVALID_TASK The space is null. ! 1001: * KERN_INVALID_TASK The space is dead. ! 1002: * KERN_INVALID_NAME The name doesn't denote a right. ! 1003: * KERN_INVALID_RIGHT Name doesn't denote a port set. ! 1004: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 1005: */ ! 1006: ! 1007: kern_return_t ! 1008: mach_port_get_set_status( ! 1009: ipc_space_t space, ! 1010: mach_port_t name, ! 1011: mach_port_t **members, ! 1012: mach_msg_type_number_t *membersCnt) ! 1013: { ! 1014: ipc_entry_num_t actual; /* this many members */ ! 1015: ipc_entry_num_t maxnames; /* space for this many members */ ! 1016: kern_return_t kr; ! 1017: ! 1018: vm_size_t size; /* size of allocated memory */ ! 1019: vm_offset_t addr; /* allocated memory */ ! 1020: #if MACH_OLD_VM_COPY ! 1021: vm_offset_t memory; /* copied-in memory */ ! 1022: #else /* MACH_OLD_VM_COPY */ ! 1023: vm_map_copy_t memory; /* copied-in memory */ ! 1024: #endif /* MACH_OLD_VM_COPY */ ! 1025: ! 1026: if (space == IS_NULL) ! 1027: return KERN_INVALID_TASK; ! 1028: ! 1029: size = PAGE_SIZE; /* initial guess */ ! 1030: ! 1031: for (;;) { ! 1032: ipc_tree_entry_t tentry; ! 1033: ipc_entry_t entry, table; ! 1034: ipc_entry_num_t tsize; ! 1035: mach_port_index_t index; ! 1036: mach_port_t *names; ! 1037: ipc_pset_t pset; ! 1038: ! 1039: kr = vm_allocate(ipc_kernel_map, &addr, size, TRUE); ! 1040: if (kr != KERN_SUCCESS) ! 1041: return KERN_RESOURCE_SHORTAGE; ! 1042: ! 1043: /* can't fault while we hold locks */ ! 1044: ! 1045: #if MACH_OLD_VM_COPY ! 1046: kr = vm_map_pageable(ipc_kernel_map, addr, addr + size, ! 1047: FALSE); ! 1048: assert(kr == KERN_SUCCESS); ! 1049: #else /* MACH_OLD_VM_COPY */ ! 1050: kr = vm_map_wire(ipc_kernel_map, addr, addr + size, ! 1051: VM_PROT_READ|VM_PROT_WRITE, FALSE); ! 1052: assert(kr == KERN_SUCCESS); ! 1053: #endif /* MACH_OLD_VM_COPY */ ! 1054: ! 1055: kr = ipc_right_lookup_read(space, name, &entry); ! 1056: if (kr != KERN_SUCCESS) { ! 1057: kmem_free(ipc_kernel_map, addr, size); ! 1058: return kr; ! 1059: } ! 1060: /* space is read-locked and active */ ! 1061: ! 1062: if (IE_BITS_TYPE(entry->ie_bits) != MACH_PORT_TYPE_PORT_SET) { ! 1063: is_read_unlock(space); ! 1064: kmem_free(ipc_kernel_map, addr, size); ! 1065: return KERN_INVALID_RIGHT; ! 1066: } ! 1067: ! 1068: pset = (ipc_pset_t) entry->ie_object; ! 1069: assert(pset != IPS_NULL); ! 1070: /* the port set must be active */ ! 1071: ! 1072: names = (mach_port_t *) addr; ! 1073: maxnames = size / sizeof(mach_port_t); ! 1074: actual = 0; ! 1075: ! 1076: table = space->is_table; ! 1077: tsize = space->is_table_size; ! 1078: ! 1079: for (index = 0; index < tsize; index++) { ! 1080: ipc_entry_t ientry = &table[index]; ! 1081: ipc_entry_bits_t bits = ientry->ie_bits; ! 1082: ! 1083: if (bits & MACH_PORT_TYPE_RECEIVE) { ! 1084: ipc_port_t port = ! 1085: (ipc_port_t) ientry->ie_object; ! 1086: ! 1087: mach_port_gst_helper(pset, port, ! 1088: maxnames, ! 1089: names, &actual); ! 1090: } ! 1091: } ! 1092: ! 1093: for (tentry = ipc_splay_traverse_start(&space->is_tree); ! 1094: tentry != ITE_NULL; ! 1095: tentry = ipc_splay_traverse_next(&space->is_tree, ! 1096: FALSE)) { ! 1097: ipc_entry_bits_t bits = tentry->ite_bits; ! 1098: ! 1099: assert(IE_BITS_TYPE(bits) != ! 1100: MACH_PORT_TYPE_NONE); ! 1101: ! 1102: if (bits & MACH_PORT_TYPE_RECEIVE) { ! 1103: ipc_port_t port = ! 1104: (ipc_port_t) tentry->ite_object; ! 1105: ! 1106: mach_port_gst_helper(pset, port, ! 1107: maxnames, ! 1108: names, &actual); ! 1109: } ! 1110: } ! 1111: ipc_splay_traverse_finish(&space->is_tree); ! 1112: is_read_unlock(space); ! 1113: ! 1114: if (actual <= maxnames) ! 1115: break; ! 1116: ! 1117: /* didn't have enough memory; allocate more */ ! 1118: ! 1119: kmem_free(ipc_kernel_map, addr, size); ! 1120: size = round_page(actual * sizeof(mach_port_t)) + PAGE_SIZE; ! 1121: } ! 1122: ! 1123: if (actual == 0) { ! 1124: #if MACH_OLD_VM_COPY ! 1125: memory = 0; ! 1126: #else /* MACH_OLD_VM_COPY */ ! 1127: memory = VM_MAP_COPY_NULL; ! 1128: #endif /* MACH_OLD_VM_COPY */ ! 1129: ! 1130: kmem_free(ipc_kernel_map, addr, size); ! 1131: } else { ! 1132: vm_size_t size_used; ! 1133: vm_size_t vm_size_used; ! 1134: ! 1135: size_used = actual * sizeof(mach_port_t); ! 1136: vm_size_used = round_page(size_used); ! 1137: ! 1138: /* ! 1139: * Make used memory pageable and get it into ! 1140: * copied-in form. Free any unused memory. ! 1141: */ ! 1142: ! 1143: #if MACH_OLD_VM_COPY ! 1144: kr = vm_map_pageable(ipc_kernel_map, ! 1145: addr, addr + vm_size_used, ! 1146: TRUE); ! 1147: assert(kr == KERN_SUCCESS); ! 1148: ! 1149: kr = vm_move( ! 1150: ipc_kernel_map, addr, ! 1151: ipc_soft_map, size_used, ! 1152: TRUE, &memory); ! 1153: assert(kr == KERN_SUCCESS); ! 1154: #else /* MACH_OLD_VM_COPY */ ! 1155: kr = vm_map_unwire(ipc_kernel_map, ! 1156: addr, addr + vm_size_used, FALSE); ! 1157: assert(kr == KERN_SUCCESS); ! 1158: ! 1159: kr = vm_map_copyin(ipc_kernel_map, addr, size_used, ! 1160: TRUE, &memory); ! 1161: assert(kr == KERN_SUCCESS); ! 1162: #endif /* MACH_OLD_VM_COPY */ ! 1163: ! 1164: if (vm_size_used != size) ! 1165: kmem_free(ipc_kernel_map, ! 1166: addr + vm_size_used, size - vm_size_used); ! 1167: } ! 1168: ! 1169: *members = (mach_port_t *) memory; ! 1170: *membersCnt = actual; ! 1171: return KERN_SUCCESS; ! 1172: } ! 1173: ! 1174: /* ! 1175: * Routine: mach_port_move_member [kernel call] ! 1176: * Purpose: ! 1177: * If after is MACH_PORT_NULL, removes member ! 1178: * from the port set it is in. Otherwise, adds ! 1179: * member to after, removing it from any set ! 1180: * it might already be in. ! 1181: * Conditions: ! 1182: * Nothing locked. ! 1183: * Returns: ! 1184: * KERN_SUCCESS Moved the port. ! 1185: * KERN_INVALID_TASK The space is null. ! 1186: * KERN_INVALID_TASK The space is dead. ! 1187: * KERN_INVALID_NAME Member didn't denote a right. ! 1188: * KERN_INVALID_RIGHT Member didn't denote a receive right. ! 1189: * KERN_INVALID_NAME After didn't denote a right. ! 1190: * KERN_INVALID_RIGHT After didn't denote a port set right. ! 1191: * KERN_NOT_IN_SET ! 1192: * After is MACH_PORT_NULL and Member isn't in a port set. ! 1193: */ ! 1194: ! 1195: kern_return_t ! 1196: mach_port_move_member( ! 1197: ipc_space_t space, ! 1198: mach_port_t member, ! 1199: mach_port_t after) ! 1200: { ! 1201: ipc_entry_t entry; ! 1202: ipc_port_t port; ! 1203: ipc_pset_t nset; ! 1204: kern_return_t kr; ! 1205: ! 1206: if (space == IS_NULL) ! 1207: return KERN_INVALID_TASK; ! 1208: ! 1209: kr = ipc_right_lookup_read(space, member, &entry); ! 1210: if (kr != KERN_SUCCESS) ! 1211: return kr; ! 1212: /* space is read-locked and active */ ! 1213: ! 1214: if ((entry->ie_bits & MACH_PORT_TYPE_RECEIVE) == 0) { ! 1215: is_read_unlock(space); ! 1216: return KERN_INVALID_RIGHT; ! 1217: } ! 1218: ! 1219: port = (ipc_port_t) entry->ie_object; ! 1220: assert(port != IP_NULL); ! 1221: ! 1222: if (after == MACH_PORT_NULL) ! 1223: nset = IPS_NULL; ! 1224: else { ! 1225: entry = ipc_entry_lookup(space, after); ! 1226: if (entry == IE_NULL) { ! 1227: is_read_unlock(space); ! 1228: return KERN_INVALID_NAME; ! 1229: } ! 1230: ! 1231: if ((entry->ie_bits & MACH_PORT_TYPE_PORT_SET) == 0) { ! 1232: is_read_unlock(space); ! 1233: return KERN_INVALID_RIGHT; ! 1234: } ! 1235: ! 1236: nset = (ipc_pset_t) entry->ie_object; ! 1237: assert(nset != IPS_NULL); ! 1238: } ! 1239: ! 1240: kr = ipc_pset_move(space, port, nset); ! 1241: /* space is unlocked */ ! 1242: return kr; ! 1243: } ! 1244: ! 1245: /* ! 1246: * Routine: mach_port_request_notification [kernel call] ! 1247: * Purpose: ! 1248: * Requests a notification. The caller supplies ! 1249: * a send-once right for the notification to use, ! 1250: * and the call returns the previously registered ! 1251: * send-once right, if any. Possible types: ! 1252: * ! 1253: * MACH_NOTIFY_PORT_DESTROYED ! 1254: * Requests a port-destroyed notification ! 1255: * for a receive right. Sync should be zero. ! 1256: * MACH_NOTIFY_NO_SENDERS ! 1257: * Requests a no-senders notification for a ! 1258: * receive right. If there are currently no ! 1259: * senders, sync is less than or equal to the ! 1260: * current make-send count, and a send-once right ! 1261: * is supplied, then an immediate no-senders ! 1262: * notification is generated. ! 1263: * MACH_NOTIFY_DEAD_NAME ! 1264: * Requests a dead-name notification for a send ! 1265: * or receive right. If the name is already a ! 1266: * dead name, sync is non-zero, and a send-once ! 1267: * right is supplied, then an immediate dead-name ! 1268: * notification is generated. ! 1269: * Conditions: ! 1270: * Nothing locked. ! 1271: * Returns: ! 1272: * KERN_SUCCESS Requested a notification. ! 1273: * KERN_INVALID_TASK The space is null. ! 1274: * KERN_INVALID_TASK The space is dead. ! 1275: * KERN_INVALID_VALUE Bad id value. ! 1276: * KERN_INVALID_NAME Name doesn't denote a right. ! 1277: * KERN_INVALID_RIGHT Name doesn't denote appropriate right. ! 1278: * KERN_INVALID_CAPABILITY The notify port is dead. ! 1279: * MACH_NOTIFY_PORT_DESTROYED: ! 1280: * KERN_INVALID_VALUE Sync isn't zero. ! 1281: * MACH_NOTIFY_DEAD_NAME: ! 1282: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 1283: * KERN_INVALID_ARGUMENT Name denotes dead name, but ! 1284: * sync is zero or notify is IP_NULL. ! 1285: * KERN_UREFS_OVERFLOW Name denotes dead name, but ! 1286: * generating immediate notif. would overflow urefs. ! 1287: */ ! 1288: ! 1289: kern_return_t ! 1290: mach_port_request_notification( ! 1291: ipc_space_t space, ! 1292: mach_port_t name, ! 1293: mach_msg_id_t id, ! 1294: mach_port_mscount_t sync, ! 1295: ipc_port_t notify, ! 1296: ipc_port_t *previousp) ! 1297: { ! 1298: kern_return_t kr; ! 1299: ! 1300: if (space == IS_NULL) ! 1301: return KERN_INVALID_TASK; ! 1302: ! 1303: if (notify == IP_DEAD) ! 1304: return KERN_INVALID_CAPABILITY; ! 1305: ! 1306: switch (id) { ! 1307: case MACH_NOTIFY_PORT_DESTROYED: { ! 1308: ipc_port_t port, previous; ! 1309: ! 1310: if (sync != 0) ! 1311: return KERN_INVALID_VALUE; ! 1312: ! 1313: kr = ipc_port_translate_receive(space, name, &port); ! 1314: if (kr != KERN_SUCCESS) ! 1315: return kr; ! 1316: /* port is locked and active */ ! 1317: ! 1318: ipc_port_pdrequest(port, notify, &previous); ! 1319: /* port is unlocked */ ! 1320: ! 1321: #if MACH_IPC_COMPAT ! 1322: /* ! 1323: * If previous was a send right instead of a send-once ! 1324: * right, we can't return it in the reply message. ! 1325: * So destroy it instead. ! 1326: */ ! 1327: ! 1328: if ((previous != IP_NULL) && ip_pdsendp(previous)) { ! 1329: ipc_port_release_send(ip_pdsend(previous)); ! 1330: previous = IP_NULL; ! 1331: } ! 1332: #endif /* MACH_IPC_COMPAT */ ! 1333: ! 1334: *previousp = previous; ! 1335: break; ! 1336: } ! 1337: ! 1338: case MACH_NOTIFY_NO_SENDERS: { ! 1339: ipc_port_t port; ! 1340: ! 1341: kr = ipc_port_translate_receive(space, name, &port); ! 1342: if (kr != KERN_SUCCESS) ! 1343: return kr; ! 1344: /* port is locked and active */ ! 1345: ! 1346: ipc_port_nsrequest(port, sync, notify, previousp); ! 1347: /* port is unlocked */ ! 1348: break; ! 1349: } ! 1350: ! 1351: case MACH_NOTIFY_DEAD_NAME: ! 1352: kr = ipc_right_dnrequest(space, name, sync != 0, ! 1353: notify, previousp); ! 1354: if (kr != KERN_SUCCESS) ! 1355: return kr; ! 1356: break; ! 1357: ! 1358: default: ! 1359: return KERN_INVALID_VALUE; ! 1360: } ! 1361: ! 1362: return KERN_SUCCESS; ! 1363: } ! 1364: ! 1365: /* ! 1366: * Routine: mach_port_insert_right [kernel call] ! 1367: * Purpose: ! 1368: * Inserts a right into a space, as if the space ! 1369: * voluntarily received the right in a message, ! 1370: * except that the right gets the specified name. ! 1371: * Conditions: ! 1372: * Nothing locked. ! 1373: * Returns: ! 1374: * KERN_SUCCESS Inserted the right. ! 1375: * KERN_INVALID_TASK The space is null. ! 1376: * KERN_INVALID_TASK The space is dead. ! 1377: * KERN_INVALID_VALUE The name isn't a legal name. ! 1378: * KERN_NAME_EXISTS The name already denotes a right. ! 1379: * KERN_INVALID_VALUE Message doesn't carry a port right. ! 1380: * KERN_INVALID_CAPABILITY Port is null or dead. ! 1381: * KERN_UREFS_OVERFLOW Urefs limit would be exceeded. ! 1382: * KERN_RIGHT_EXISTS Space has rights under another name. ! 1383: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 1384: */ ! 1385: ! 1386: kern_return_t ! 1387: mach_port_insert_right( ! 1388: ipc_space_t space, ! 1389: mach_port_t name, ! 1390: ipc_port_t poly, ! 1391: mach_msg_type_name_t polyPoly) ! 1392: { ! 1393: if (space == IS_NULL) ! 1394: return KERN_INVALID_TASK; ! 1395: ! 1396: if (!MACH_PORT_VALID(name) || ! 1397: !MACH_MSG_TYPE_PORT_ANY_RIGHT(polyPoly)) ! 1398: return KERN_INVALID_VALUE; ! 1399: ! 1400: if (!IO_VALID((ipc_object_t) poly)) ! 1401: return KERN_INVALID_CAPABILITY; ! 1402: ! 1403: return ipc_object_copyout_name(space, (ipc_object_t) poly, ! 1404: polyPoly, FALSE, name); ! 1405: } ! 1406: ! 1407: /* ! 1408: * Routine: mach_port_extract_right [kernel call] ! 1409: * Purpose: ! 1410: * Extracts a right from a space, as if the space ! 1411: * voluntarily sent the right to the caller. ! 1412: * Conditions: ! 1413: * Nothing locked. ! 1414: * Returns: ! 1415: * KERN_SUCCESS Extracted the right. ! 1416: * KERN_INVALID_TASK The space is null. ! 1417: * KERN_INVALID_TASK The space is dead. ! 1418: * KERN_INVALID_VALUE Requested type isn't a port right. ! 1419: * KERN_INVALID_NAME Name doesn't denote a right. ! 1420: * KERN_INVALID_RIGHT Name doesn't denote appropriate right. ! 1421: */ ! 1422: ! 1423: kern_return_t ! 1424: mach_port_extract_right( ! 1425: ipc_space_t space, ! 1426: mach_port_t name, ! 1427: mach_msg_type_name_t msgt_name, ! 1428: ipc_port_t *poly, ! 1429: mach_msg_type_name_t *polyPoly) ! 1430: { ! 1431: kern_return_t kr; ! 1432: ! 1433: if (space == IS_NULL) ! 1434: return KERN_INVALID_TASK; ! 1435: ! 1436: if (!MACH_MSG_TYPE_PORT_ANY(msgt_name)) ! 1437: return KERN_INVALID_VALUE; ! 1438: ! 1439: kr = ipc_object_copyin(space, name, msgt_name, (ipc_object_t *) poly); ! 1440: ! 1441: if (kr == KERN_SUCCESS) ! 1442: *polyPoly = ipc_object_copyin_type(msgt_name); ! 1443: return kr; ! 1444: } ! 1445: ! 1446: /* ! 1447: * Routine: mach_port_get_receive_status [kernel call] ! 1448: * Purpose: ! 1449: * Retrieves mucho info about a receive right. ! 1450: * Conditions: ! 1451: * Nothing locked. ! 1452: * Returns: ! 1453: * KERN_SUCCESS Retrieved status. ! 1454: * KERN_INVALID_TASK The space is null. ! 1455: * KERN_INVALID_TASK The space is dead. ! 1456: * KERN_INVALID_NAME The name doesn't denote a right. ! 1457: * KERN_INVALID_RIGHT Name doesn't denote receive rights. ! 1458: */ ! 1459: ! 1460: kern_return_t ! 1461: mach_port_get_receive_status(space, name, statusp) ! 1462: ipc_space_t space; ! 1463: mach_port_t name; ! 1464: mach_port_status_t *statusp; ! 1465: { ! 1466: ipc_port_t port; ! 1467: kern_return_t kr; ! 1468: ! 1469: if (space == IS_NULL) ! 1470: return KERN_INVALID_TASK; ! 1471: ! 1472: kr = ipc_port_translate_receive(space, name, &port); ! 1473: if (kr != KERN_SUCCESS) ! 1474: return kr; ! 1475: /* port is locked and active */ ! 1476: ! 1477: if (port->ip_pset != IPS_NULL) { ! 1478: ipc_pset_t pset = port->ip_pset; ! 1479: ! 1480: ips_lock(pset); ! 1481: if (!ips_active(pset)) { ! 1482: ipc_pset_remove(pset, port); ! 1483: ips_check_unlock(pset); ! 1484: goto no_port_set; ! 1485: } else { ! 1486: statusp->mps_pset = pset->ips_local_name; ! 1487: imq_lock(&pset->ips_messages); ! 1488: statusp->mps_seqno = port->ip_seqno; ! 1489: imq_unlock(&pset->ips_messages); ! 1490: ips_unlock(pset); ! 1491: assert(MACH_PORT_VALID(statusp->mps_pset)); ! 1492: } ! 1493: } else { ! 1494: no_port_set: ! 1495: statusp->mps_pset = MACH_PORT_NULL; ! 1496: imq_lock(&port->ip_messages); ! 1497: statusp->mps_seqno = port->ip_seqno; ! 1498: imq_unlock(&port->ip_messages); ! 1499: } ! 1500: ! 1501: statusp->mps_mscount = port->ip_mscount; ! 1502: statusp->mps_qlimit = port->ip_qlimit; ! 1503: statusp->mps_msgcount = port->ip_msgcount; ! 1504: statusp->mps_sorights = port->ip_sorights; ! 1505: statusp->mps_srights = port->ip_srights > 0; ! 1506: statusp->mps_pdrequest = port->ip_pdrequest != IP_NULL; ! 1507: statusp->mps_nsrequest = port->ip_nsrequest != IP_NULL; ! 1508: ip_unlock(port); ! 1509: ! 1510: return KERN_SUCCESS; ! 1511: } ! 1512: ! 1513: #if MACH_IPC_COMPAT ! 1514: ! 1515: /* ! 1516: * Routine: port_translate_compat ! 1517: * Purpose: ! 1518: * Converts a name to a receive right. ! 1519: * Conditions: ! 1520: * Nothing locked. If successful, the port ! 1521: * is returned locked and active. ! 1522: * Returns: ! 1523: * KERN_SUCCESS Port is returned. ! 1524: * KERN_INVALID_ARGUMENT The space is dead. ! 1525: * KERN_INVALID_ARGUMENT Name doesn't denote port rights. ! 1526: * KERN_NOT_RECEIVER Name denotes send, not receive, rights. ! 1527: * KERN_NOT_RECEIVER Name denotes a send-once right. ! 1528: * KERN_NOT_RECEIVER Name denotes a dead name. ! 1529: */ ! 1530: ! 1531: kern_return_t ! 1532: port_translate_compat(space, name, portp) ! 1533: ipc_space_t space; ! 1534: mach_port_t name; ! 1535: ipc_port_t *portp; ! 1536: { ! 1537: ipc_entry_t entry; ! 1538: mach_port_type_t type; ! 1539: mach_port_urefs_t urefs; ! 1540: ipc_port_t port; ! 1541: kern_return_t kr; ! 1542: ! 1543: kr = ipc_right_lookup_write(space, name, &entry); ! 1544: if (kr != KERN_SUCCESS) ! 1545: return KERN_INVALID_ARGUMENT; ! 1546: /* space is write-locked and active */ ! 1547: ! 1548: kr = ipc_right_info(space, name, entry, &type, &urefs); ! 1549: if (kr != KERN_SUCCESS) ! 1550: return KERN_INVALID_ARGUMENT; /* space is unlocked */ ! 1551: ! 1552: if ((type & (MACH_PORT_TYPE_RECEIVE)) == 0) { ! 1553: is_write_unlock(space); ! 1554: if (type & MACH_PORT_TYPE_PORT_OR_DEAD) ! 1555: return KERN_NOT_RECEIVER; ! 1556: else ! 1557: return KERN_INVALID_ARGUMENT; ! 1558: } ! 1559: ! 1560: port = (ipc_port_t) entry->ie_object; ! 1561: assert(port != IP_NULL); ! 1562: ! 1563: ip_lock(port); ! 1564: is_write_unlock(space); ! 1565: assert(ip_active(port)); ! 1566: ! 1567: *portp = port; ! 1568: return KERN_SUCCESS; ! 1569: } ! 1570: ! 1571: /* ! 1572: * Routine: convert_port_type ! 1573: * Purpose: ! 1574: * Convert a new mach_port_type_t to an old value. ! 1575: * Note send-once rights and dead names get ! 1576: * represented as send rights. The extra info ! 1577: * bits get dropped. ! 1578: */ ! 1579: ! 1580: mach_port_type_t ! 1581: convert_port_type(type) ! 1582: mach_port_type_t type; ! 1583: { ! 1584: switch (type & MACH_PORT_TYPE_ALL_RIGHTS) { ! 1585: case MACH_PORT_TYPE_SEND: ! 1586: case MACH_PORT_TYPE_SEND_ONCE: ! 1587: case MACH_PORT_TYPE_DEAD_NAME: ! 1588: return PORT_TYPE_SEND; ! 1589: ! 1590: case MACH_PORT_TYPE_RECEIVE: ! 1591: case MACH_PORT_TYPE_SEND_RECEIVE: ! 1592: return PORT_TYPE_RECEIVE_OWN; ! 1593: ! 1594: case MACH_PORT_TYPE_PORT_SET: ! 1595: return PORT_TYPE_SET; ! 1596: ! 1597: default: ! 1598: #if MACH_ASSERT ! 1599: assert(!"convert_port_type: strange port type"); ! 1600: #else ! 1601: panic("convert_port_type: strange port type"); ! 1602: #endif ! 1603: } ! 1604: } ! 1605: ! 1606: /* ! 1607: * Routine: port_names [kernel call] ! 1608: * Purpose: ! 1609: * Retrieve all the names in the task's port name space. ! 1610: * As a (major) convenience, return port type information. ! 1611: * The port name space includes port sets. ! 1612: * Conditions: ! 1613: * Nothing locked. ! 1614: * Returns: ! 1615: * KERN_SUCCESS Retrieved names. ! 1616: * KERN_INVALID_ARGUMENT Task is null. ! 1617: * KERN_INVALID_ARGUMENT Task is not active. ! 1618: * Additions: ! 1619: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 1620: */ ! 1621: ! 1622: kern_return_t ! 1623: port_names(space, namesp, namesCnt, typesp, typesCnt) ! 1624: ipc_space_t space; ! 1625: mach_port_t **namesp; ! 1626: mach_msg_type_number_t *namesCnt; ! 1627: mach_port_type_t **typesp; ! 1628: mach_msg_type_number_t *typesCnt; ! 1629: { ! 1630: kern_return_t kr; ! 1631: ! 1632: kr = mach_port_names(space, namesp, namesCnt, typesp, typesCnt); ! 1633: if (kr == KERN_SUCCESS) { ! 1634: ipc_entry_num_t actual = (ipc_entry_num_t) *typesCnt; ! 1635: mach_port_type_t *types; ! 1636: ipc_entry_num_t i; ! 1637: ! 1638: #if MACH_OLD_VM_COPY ! 1639: vm_offset_t copy = (vm_offset_t) *typesp; ! 1640: #else /* MACH_OLD_VM_COPY */ ! 1641: vm_map_copy_t copy = (vm_map_copy_t) *typesp; ! 1642: #endif /* MACH_OLD_VM_COPY */ ! 1643: vm_offset_t addr; ! 1644: vm_size_t size = round_page(actual * sizeof(mach_port_type_t)); ! 1645: ! 1646: /* convert copy object back to something we can use */ ! 1647: ! 1648: #if MACH_OLD_VM_COPY ! 1649: kr = vm_move( ! 1650: ipc_soft_map, copy, ! 1651: ipc_kernel_map, size, ! 1652: FALSE, &addr); ! 1653: #else /* MACH_OLD_VM_COPY */ ! 1654: kr = vm_map_copyout(ipc_kernel_map, &addr, copy); ! 1655: #endif /* MACH_OLD_VM_COPY */ ! 1656: if (kr != KERN_SUCCESS) { ! 1657: #if MACH_OLD_VM_COPY ! 1658: kmem_free( ! 1659: ipc_soft_map, ! 1660: (vm_offset_t) *typesp, ! 1661: (vm_size_t) ! 1662: round_page((ipc_entry_num_t) *typesCnt * ! 1663: sizeof(mach_port_type_t))); ! 1664: kmem_free( ! 1665: ipc_soft_map, ! 1666: (vm_offset_t) *namesp, ! 1667: (vm_size_t) ! 1668: round_page((ipc_entry_num_t) *namesCnt * ! 1669: sizeof(mach_port_t))); ! 1670: #else /* MACH_OLD_VM_COPY */ ! 1671: vm_map_copy_discard((vm_map_copy_t) *typesp); ! 1672: vm_map_copy_discard((vm_map_copy_t) *namesp); ! 1673: #endif /* MACH_OLD_VM_COPY */ ! 1674: return KERN_RESOURCE_SHORTAGE; ! 1675: } ! 1676: #if MACH_OLD_VM_COPY ! 1677: else ! 1678: (void) vm_deallocate(ipc_soft_map, copy, size); ! 1679: #endif /* MACH_OLD_VM_COPY */ ! 1680: ! 1681: types = (mach_port_type_t *) addr; ! 1682: ! 1683: for (i = 0; i < actual; i++) ! 1684: types[i] = convert_port_type(types[i]); ! 1685: ! 1686: /* convert memory back into a copy object */ ! 1687: ! 1688: #if MACH_OLD_VM_COPY ! 1689: kr = vm_move( ! 1690: ipc_kernel_map, addr, ! 1691: ipc_soft_map, size, ! 1692: TRUE, ©); ! 1693: assert(kr == KERN_SUCCESS); ! 1694: #else /* MACH_OLD_VM_COPY */ ! 1695: kr = vm_map_copyin(ipc_kernel_map, addr, size, ! 1696: TRUE, ©); ! 1697: assert(kr == KERN_SUCCESS); ! 1698: #endif /* MACH_OLD_VM_COPY */ ! 1699: ! 1700: *typesp = (mach_port_type_t *) copy; ! 1701: } else if (kr != KERN_RESOURCE_SHORTAGE) ! 1702: kr = KERN_INVALID_ARGUMENT; ! 1703: ! 1704: return kr; ! 1705: } ! 1706: ! 1707: /* ! 1708: * Routine: port_type [kernel call] ! 1709: * Purpose: ! 1710: * Return type of the capability named. ! 1711: * Conditions: ! 1712: * Nothing locked. ! 1713: * Returns: ! 1714: * KERN_SUCCESS Retrieved type. ! 1715: * KERN_INVALID_ARGUMENT Task is null. ! 1716: * KERN_INVALID_ARGUMENT Task is not active. ! 1717: * KERN_INVALID_ARGUMENT The name doesn't denote a right. ! 1718: */ ! 1719: ! 1720: kern_return_t ! 1721: port_type(space, name, typep) ! 1722: ipc_space_t space; ! 1723: mach_port_t name; ! 1724: mach_port_type_t *typep; ! 1725: { ! 1726: mach_port_type_t type; ! 1727: kern_return_t kr; ! 1728: ! 1729: kr = mach_port_type(space, name, &type); ! 1730: if (kr != KERN_SUCCESS) ! 1731: return KERN_INVALID_ARGUMENT; ! 1732: ! 1733: *typep = convert_port_type(type); ! 1734: return KERN_SUCCESS; ! 1735: } ! 1736: ! 1737: /* ! 1738: * Routine: port_rename [kernel call] ! 1739: * Purpose: ! 1740: * Change the name of a capability. ! 1741: * The new name can't be in use. ! 1742: * Conditions: ! 1743: * Nothing locked. ! 1744: * Returns: ! 1745: * KERN_SUCCESS Retrieved type. ! 1746: * KERN_INVALID_ARGUMENT Task is null. ! 1747: * KERN_INVALID_ARGUMENT Task is not active. ! 1748: * KERN_INVALID_ARGUMENT The new name is reserved. ! 1749: * KERN_NAME_EXISTS The new name already denotes a right. ! 1750: * KERN_INVALID_ARGUMENT The old name doesn't denote a right. ! 1751: */ ! 1752: ! 1753: kern_return_t ! 1754: port_rename(space, old_name, new_name) ! 1755: ipc_space_t space; ! 1756: mach_port_t old_name; ! 1757: mach_port_t new_name; ! 1758: { ! 1759: kern_return_t kr; ! 1760: ! 1761: kr = mach_port_rename(space, old_name, new_name); ! 1762: if ((kr != KERN_SUCCESS) && (kr != KERN_NAME_EXISTS)) ! 1763: kr = KERN_INVALID_ARGUMENT; ! 1764: ! 1765: return kr; ! 1766: } ! 1767: ! 1768: /* ! 1769: * Routine: port_allocate [kernel call] ! 1770: * Purpose: ! 1771: * Allocate a new port, giving all rights to "task". ! 1772: * ! 1773: * Returns in "port_name" the task's local name for the port. ! 1774: * Doesn't return a reference to the port. ! 1775: * Conditions: ! 1776: * Nothing locked. ! 1777: * Returns: ! 1778: * KERN_SUCCESS Allocated a port. ! 1779: * KERN_INVALID_ARGUMENT Task is null. ! 1780: * KERN_INVALID_ARGUMENT Task is not active. ! 1781: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 1782: */ ! 1783: ! 1784: kern_return_t ! 1785: port_allocate(space, namep) ! 1786: ipc_space_t space; ! 1787: mach_port_t *namep; ! 1788: { ! 1789: ipc_port_t port; ! 1790: kern_return_t kr; ! 1791: ! 1792: if (space == IS_NULL) ! 1793: return KERN_INVALID_ARGUMENT; ! 1794: ! 1795: kr = ipc_port_alloc_compat(space, namep, &port); ! 1796: if (kr == KERN_SUCCESS) ! 1797: ip_unlock(port); ! 1798: else if (kr != KERN_RESOURCE_SHORTAGE) ! 1799: kr = KERN_INVALID_ARGUMENT; ! 1800: ! 1801: return kr; ! 1802: } ! 1803: ! 1804: /* ! 1805: * Routine: port_deallocate [kernel call] ! 1806: * Purpose: ! 1807: * Delete port rights (send and receive) from a task. ! 1808: * Conditions: ! 1809: * Nothing locked. ! 1810: * Returns: ! 1811: * KERN_SUCCESS Deallocated the port right. ! 1812: * KERN_INVALID_ARGUMENT Task is null. ! 1813: * KERN_INVALID_ARGUMENT Task is not active. ! 1814: * KERN_INVALID_ARGUMENT Name doesn't denote a port right. ! 1815: * Additions: ! 1816: * KERN_SUCCESS Deallocated a send-once right. ! 1817: * KERN_SUCCESS Destroyed a dead name. ! 1818: */ ! 1819: ! 1820: kern_return_t ! 1821: port_deallocate(space, name) ! 1822: ipc_space_t space; ! 1823: mach_port_t name; ! 1824: { ! 1825: ipc_entry_t entry; ! 1826: mach_port_type_t type; ! 1827: mach_port_urefs_t urefs; ! 1828: kern_return_t kr; ! 1829: ! 1830: if (space == IS_NULL) ! 1831: return KERN_INVALID_ARGUMENT; ! 1832: ! 1833: kr = ipc_right_lookup_write(space, name, &entry); ! 1834: if (kr != KERN_SUCCESS) ! 1835: return KERN_INVALID_ARGUMENT; ! 1836: /* space is write-locked and active */ ! 1837: ! 1838: /* ! 1839: * We serialize with port destruction with the ! 1840: * ipc_right_info call, not ipc_right_destroy. ! 1841: * After ipc_right_info, we pretend that the ! 1842: * port doesn't get destroyed. ! 1843: */ ! 1844: ! 1845: kr = ipc_right_info(space, name, entry, &type, &urefs); ! 1846: if (kr != KERN_SUCCESS) ! 1847: return KERN_INVALID_ARGUMENT; /* space is unlocked */ ! 1848: ! 1849: if ((type & (MACH_PORT_TYPE_PORT_OR_DEAD)) == 0) { ! 1850: is_write_unlock(space); ! 1851: return KERN_INVALID_ARGUMENT; ! 1852: } ! 1853: ! 1854: (void) ipc_right_destroy(space, name, entry); ! 1855: /* space is unlocked */ ! 1856: ! 1857: return KERN_SUCCESS; ! 1858: } ! 1859: ! 1860: /* ! 1861: * Routine: port_set_backlog [kernel call] ! 1862: * Purpose: ! 1863: * Change the queueing backlog on "port_name" to "backlog"; ! 1864: * the specified "task" must be the current receiver. ! 1865: * ! 1866: * Valid backlog values are 0 < backlog <= PORT_BACKLOG_MAX. ! 1867: * Conditions: ! 1868: * Nothing locked. ! 1869: * Returns: ! 1870: * KERN_SUCCESS Set the backlog. ! 1871: * KERN_INVALID_ARGUMENT Task is null. ! 1872: * KERN_INVALID_ARGUMENT Task is not active. ! 1873: * KERN_INVALID_ARGUMENT Name doesn't denote a port right. ! 1874: * KERN_NOT_RECEIVER Name denotes send rights, not receive. ! 1875: * KERN_INVALID_ARGUMENT Backlog value is invalid. ! 1876: * Additions: ! 1877: * KERN_NOT_RECEIVER Name denotes a send-once right. ! 1878: * KERN_NOT_RECEIVER Name denotes a dead name. ! 1879: */ ! 1880: ! 1881: kern_return_t ! 1882: port_set_backlog(space, name, backlog) ! 1883: ipc_space_t space; ! 1884: mach_port_t name; ! 1885: int backlog; ! 1886: { ! 1887: ipc_port_t port; ! 1888: kern_return_t kr; ! 1889: ! 1890: if ((space == IS_NULL) || ! 1891: (backlog <= 0) || ! 1892: (backlog > PORT_BACKLOG_MAX)) ! 1893: return KERN_INVALID_ARGUMENT; ! 1894: ! 1895: kr = port_translate_compat(space, name, &port); ! 1896: if (kr != KERN_SUCCESS) ! 1897: return kr; ! 1898: /* port is locked and active */ ! 1899: ! 1900: ipc_port_set_qlimit(port, (mach_port_msgcount_t) backlog); ! 1901: ! 1902: ip_unlock(port); ! 1903: return KERN_SUCCESS; ! 1904: } ! 1905: ! 1906: /* ! 1907: * Routine: port_set_backup [kernel call] ! 1908: * Purpose: ! 1909: * Changes the backup port for the the named port. ! 1910: * The specified "task" must be the current receiver. ! 1911: * Returns the old backup port, if any. ! 1912: * Conditions: ! 1913: * Nothing locked. ! 1914: * Returns: ! 1915: * KERN_SUCCESS Set the backup. ! 1916: * KERN_INVALID_ARGUMENT Task is null. ! 1917: * KERN_INVALID_ARGUMENT Task is not active. ! 1918: * KERN_INVALID_ARGUMENT Name doesn't denote a port right. ! 1919: * KERN_NOT_RECEIVER Name denotes send rights, not receive. ! 1920: * Additions: ! 1921: * KERN_NOT_RECEIVER Name denotes a send-once right. ! 1922: * KERN_NOT_RECEIVER Name denotes a dead name. ! 1923: */ ! 1924: ! 1925: kern_return_t ! 1926: port_set_backup(space, name, backup, previousp) ! 1927: ipc_space_t space; ! 1928: mach_port_t name; ! 1929: ipc_port_t backup; ! 1930: ipc_port_t *previousp; ! 1931: { ! 1932: ipc_port_t port, previous; ! 1933: kern_return_t kr; ! 1934: ! 1935: if (space == IS_NULL) ! 1936: return KERN_INVALID_ARGUMENT; ! 1937: ! 1938: if (backup == IP_DEAD) ! 1939: backup = IP_NULL; ! 1940: else if (backup != IP_NULL) ! 1941: backup = ip_pdsendm(backup); ! 1942: ! 1943: kr = port_translate_compat(space, name, &port); ! 1944: if (kr != KERN_SUCCESS) ! 1945: return kr; ! 1946: /* port is locked and active */ ! 1947: ! 1948: ipc_port_pdrequest(port, backup, &previous); ! 1949: /* port is unlocked */ ! 1950: ! 1951: /* ! 1952: * If previous was a send-once right instead of a send ! 1953: * right, we can't return it in the reply message. ! 1954: * So get rid of it in a notification instead. ! 1955: */ ! 1956: ! 1957: if (previous != IP_NULL) { ! 1958: if (ip_pdsendp(previous)) ! 1959: previous = ip_pdsend(previous); ! 1960: else { ! 1961: ipc_notify_send_once(previous); ! 1962: previous = IP_NULL; ! 1963: } ! 1964: } ! 1965: ! 1966: *previousp = previous; ! 1967: return KERN_SUCCESS; ! 1968: } ! 1969: ! 1970: /* ! 1971: * Routine: port_status [kernel call] ! 1972: * Purpose: ! 1973: * Returns statistics related to "port_name", as seen by "task". ! 1974: * Only the receiver for a given port will see true message ! 1975: * counts. ! 1976: * Conditions: ! 1977: * Nothing locked. ! 1978: * Returns: ! 1979: * KERN_SUCCESS Retrieved status. ! 1980: * KERN_INVALID_ARGUMENT Task is null. ! 1981: * KERN_INVALID_ARGUMENT Task is not active. ! 1982: * KERN_INVALID_ARGUMENT Name doesn't denote a port right. ! 1983: * Additions: ! 1984: * KERN_SUCCESS Send-once right. ! 1985: * KERN_SUCCESS Dead name. ! 1986: */ ! 1987: ! 1988: kern_return_t ! 1989: port_status(space, name, enabledp, num_msgs, backlog, ! 1990: ownership, receive_rights) ! 1991: ipc_space_t space; ! 1992: mach_port_t name; ! 1993: mach_port_t *enabledp; ! 1994: int *num_msgs; ! 1995: int *backlog; ! 1996: boolean_t *ownership; ! 1997: boolean_t *receive_rights; ! 1998: { ! 1999: ipc_entry_t entry; ! 2000: mach_port_type_t type; ! 2001: mach_port_urefs_t urefs; ! 2002: kern_return_t kr; ! 2003: ! 2004: if (space == IS_NULL) ! 2005: return KERN_INVALID_ARGUMENT; ! 2006: ! 2007: kr = ipc_right_lookup_write(space, name, &entry); ! 2008: if (kr != KERN_SUCCESS) ! 2009: return KERN_INVALID_ARGUMENT; ! 2010: /* space is write-locked and active */ ! 2011: ! 2012: kr = ipc_right_info(space, name, entry, &type, &urefs); ! 2013: if (kr != KERN_SUCCESS) ! 2014: return KERN_INVALID_ARGUMENT; /* space is unlocked */ ! 2015: ! 2016: if ((type & MACH_PORT_TYPE_PORT_OR_DEAD) == 0) { ! 2017: is_write_unlock(space); ! 2018: return KERN_INVALID_ARGUMENT; ! 2019: } ! 2020: ! 2021: if (type & MACH_PORT_TYPE_RECEIVE) { ! 2022: mach_port_t enabled; ! 2023: mach_port_msgcount_t qlimit; ! 2024: mach_port_msgcount_t msgcount; ! 2025: ipc_port_t port; ! 2026: ! 2027: port = (ipc_port_t) entry->ie_object; ! 2028: assert(port != IP_NULL); ! 2029: ! 2030: ip_lock(port); ! 2031: is_write_unlock(space); ! 2032: assert(ip_active(port)); ! 2033: ! 2034: if (port->ip_pset != IPS_NULL) { ! 2035: ipc_pset_t pset = port->ip_pset; ! 2036: ! 2037: ips_lock(pset); ! 2038: if (!ips_active(pset)) { ! 2039: ipc_pset_remove(pset, port); ! 2040: ips_check_unlock(pset); ! 2041: enabled = MACH_PORT_NULL; ! 2042: } else { ! 2043: enabled = pset->ips_local_name; ! 2044: ips_unlock(pset); ! 2045: assert(MACH_PORT_VALID(enabled)); ! 2046: } ! 2047: } else ! 2048: enabled = MACH_PORT_NULL; ! 2049: ! 2050: qlimit = port->ip_qlimit; ! 2051: msgcount = port->ip_msgcount; ! 2052: ip_unlock(port); ! 2053: ! 2054: *ownership = TRUE; ! 2055: *receive_rights = TRUE; ! 2056: *enabledp = enabled; ! 2057: *num_msgs = (int) msgcount; ! 2058: *backlog = (int) qlimit; ! 2059: } else { ! 2060: is_write_unlock(space); ! 2061: ! 2062: *ownership = FALSE; ! 2063: *receive_rights = FALSE; ! 2064: *enabledp = MACH_PORT_NULL; ! 2065: *num_msgs = -1; ! 2066: *backlog = 0; ! 2067: } ! 2068: ! 2069: return KERN_SUCCESS; ! 2070: } ! 2071: ! 2072: /* ! 2073: * Routine: port_set_allocate [kernel call] ! 2074: * Purpose: ! 2075: * Create a new port set, give rights to task, and ! 2076: * return task's local name for the set. ! 2077: * Conditions: ! 2078: * Nothing locked. ! 2079: * Returns: ! 2080: * KERN_SUCCESS Allocated a port set. ! 2081: * KERN_INVALID_ARGUMENT Task is null. ! 2082: * KERN_INVALID_ARGUMENT Task is not active. ! 2083: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 2084: */ ! 2085: ! 2086: kern_return_t ! 2087: port_set_allocate(space, namep) ! 2088: ipc_space_t space; ! 2089: mach_port_t *namep; ! 2090: { ! 2091: ipc_pset_t pset; ! 2092: kern_return_t kr; ! 2093: ! 2094: if (space == IS_NULL) ! 2095: return KERN_INVALID_ARGUMENT; ! 2096: ! 2097: kr = ipc_pset_alloc(space, namep, &pset); ! 2098: if (kr == KERN_SUCCESS) ! 2099: ips_unlock(pset); ! 2100: else if (kr != KERN_RESOURCE_SHORTAGE) ! 2101: kr = KERN_INVALID_ARGUMENT; ! 2102: ! 2103: return kr; ! 2104: } ! 2105: ! 2106: /* ! 2107: * Routine: port_set_deallocate [kernel call] ! 2108: * Purpose: ! 2109: * Destroys the task's port set. If there are any ! 2110: * receive rights in the set, they are removed. ! 2111: * Conditions: ! 2112: * Nothing locked. ! 2113: * Returns: ! 2114: * KERN_SUCCESS Deallocated the port set. ! 2115: * KERN_INVALID_ARGUMENT Task is null. ! 2116: * KERN_INVALID_ARGUMENT Task is not active. ! 2117: * KERN_INVALID_ARGUMENT Name doesn't denote a port set. ! 2118: */ ! 2119: ! 2120: kern_return_t ! 2121: port_set_deallocate(space, name) ! 2122: ipc_space_t space; ! 2123: mach_port_t name; ! 2124: { ! 2125: ipc_entry_t entry; ! 2126: kern_return_t kr; ! 2127: ! 2128: if (space == IS_NULL) ! 2129: return KERN_INVALID_ARGUMENT; ! 2130: ! 2131: kr = ipc_right_lookup_write(space, name, &entry); ! 2132: if (kr != KERN_SUCCESS) ! 2133: return kr; ! 2134: /* space is write-locked and active */ ! 2135: ! 2136: if ((entry->ie_bits & MACH_PORT_TYPE_PORT_SET) == 0) { ! 2137: is_write_unlock(space); ! 2138: return KERN_INVALID_ARGUMENT; ! 2139: } ! 2140: ! 2141: kr = ipc_right_destroy(space, name, entry); ! 2142: /* space is unlocked */ ! 2143: assert(kr == KERN_SUCCESS); ! 2144: return kr; ! 2145: } ! 2146: ! 2147: /* ! 2148: * Routine: port_set_add [kernel call] ! 2149: * Purpose: ! 2150: * Moves receive rights into the port set. ! 2151: * Conditions: ! 2152: * Nothing locked. ! 2153: * Returns: ! 2154: * KERN_SUCCESS Moved the receive right. ! 2155: * KERN_INVALID_ARGUMENT Task is null. ! 2156: * KERN_INVALID_ARGUMENT Task is not active. ! 2157: * KERN_INVALID_ARGUMENT port_name doesn't denote port rights. ! 2158: * KERN_NOT_RECEIVER port_name doesn't denote receive right. ! 2159: * KERN_INVALID_ARGUMENT set_name doesn't denote a port set. ! 2160: * Additions: ! 2161: * KERN_NOT_RECEIVER port_name denotes a send-once right. ! 2162: * KERN_NOT_RECEIVER port_name denotes a dead name. ! 2163: */ ! 2164: ! 2165: kern_return_t ! 2166: port_set_add(space, set_name, port_name) ! 2167: ipc_space_t space; ! 2168: mach_port_t set_name; ! 2169: mach_port_t port_name; ! 2170: { ! 2171: ipc_entry_t entry; ! 2172: mach_port_type_t type; ! 2173: mach_port_urefs_t urefs; ! 2174: ipc_port_t port; ! 2175: ipc_pset_t pset; ! 2176: kern_return_t kr; ! 2177: ! 2178: if (space == IS_NULL) ! 2179: return KERN_INVALID_ARGUMENT; ! 2180: ! 2181: kr = ipc_right_lookup_write(space, port_name, &entry); ! 2182: if (kr != KERN_SUCCESS) ! 2183: return KERN_INVALID_ARGUMENT; ! 2184: /* space is write-locked and active */ ! 2185: ! 2186: /* use ipc_right_info to check for dead compat entries */ ! 2187: ! 2188: kr = ipc_right_info(space, port_name, entry, &type, &urefs); ! 2189: if (kr != KERN_SUCCESS) ! 2190: return KERN_INVALID_ARGUMENT; /* space is unlocked */ ! 2191: ! 2192: if ((type & MACH_PORT_TYPE_RECEIVE) == 0) { ! 2193: is_write_unlock(space); ! 2194: if (type & MACH_PORT_TYPE_PORT_OR_DEAD) ! 2195: return KERN_NOT_RECEIVER; ! 2196: else ! 2197: return KERN_INVALID_ARGUMENT; ! 2198: } ! 2199: ! 2200: is_write_to_read_lock(space); ! 2201: port = (ipc_port_t) entry->ie_object; ! 2202: assert(port != IP_NULL); ! 2203: ! 2204: entry = ipc_entry_lookup(space, set_name); ! 2205: if ((entry == IE_NULL) || ! 2206: ((entry->ie_bits & MACH_PORT_TYPE_PORT_SET) == 0)) { ! 2207: is_read_unlock(space); ! 2208: return KERN_INVALID_ARGUMENT; ! 2209: } ! 2210: ! 2211: pset = (ipc_pset_t) entry->ie_object; ! 2212: assert(pset != IPS_NULL); ! 2213: ! 2214: kr = ipc_pset_move(space, port, pset); ! 2215: /* space is unlocked */ ! 2216: assert(kr == KERN_SUCCESS); ! 2217: return kr; ! 2218: } ! 2219: ! 2220: /* ! 2221: * Routine: port_set_remove [kernel call] ! 2222: * Purpose: ! 2223: * Removes the receive rights from the set they are in. ! 2224: * Conditions: ! 2225: * Nothing locked. ! 2226: * Returns: ! 2227: * KERN_SUCCESS Removed the receive right. ! 2228: * KERN_INVALID_ARGUMENT Task is null. ! 2229: * KERN_INVALID_ARGUMENT Task is not active. ! 2230: * KERN_INVALID_ARGUMENT Name doesn't denote a port right. ! 2231: * KERN_NOT_RECEIVER Name denotes send rights, not receive. ! 2232: * KERN_NOT_IN_SET Port isn't in a port set. ! 2233: * Additions: ! 2234: * KERN_NOT_RECEIVER Name denotes a send-once right. ! 2235: * KERN_NOT_RECEIVER Name denotes a dead name. ! 2236: */ ! 2237: ! 2238: kern_return_t ! 2239: port_set_remove(space, name) ! 2240: ipc_space_t space; ! 2241: mach_port_t name; ! 2242: { ! 2243: ipc_entry_t entry; ! 2244: mach_port_type_t type; ! 2245: mach_port_urefs_t urefs; ! 2246: ipc_port_t port; ! 2247: kern_return_t kr; ! 2248: ! 2249: if (space == IS_NULL) ! 2250: return KERN_INVALID_ARGUMENT; ! 2251: ! 2252: kr = ipc_right_lookup_write(space, name, &entry); ! 2253: if (kr != KERN_SUCCESS) ! 2254: return KERN_INVALID_ARGUMENT; ! 2255: /* space is write-locked and active */ ! 2256: ! 2257: /* use ipc_right_info to check for dead compat entries */ ! 2258: ! 2259: kr = ipc_right_info(space, name, entry, &type, &urefs); ! 2260: if (kr != KERN_SUCCESS) ! 2261: return KERN_INVALID_ARGUMENT; /* space is unlocked */ ! 2262: ! 2263: if ((type & (MACH_PORT_TYPE_RECEIVE)) == 0) { ! 2264: is_write_unlock(space); ! 2265: if (type & MACH_PORT_TYPE_PORT_OR_DEAD) ! 2266: return KERN_NOT_RECEIVER; ! 2267: else ! 2268: return KERN_INVALID_ARGUMENT; ! 2269: } ! 2270: ! 2271: is_write_to_read_lock(space); ! 2272: port = (ipc_port_t) entry->ie_object; ! 2273: assert(port != IP_NULL); ! 2274: ! 2275: kr = ipc_pset_move(space, port, IPS_NULL); ! 2276: /* space is unlocked */ ! 2277: return kr; ! 2278: } ! 2279: ! 2280: /* ! 2281: * Routine: port_set_status [kernel call] ! 2282: * Purpose: ! 2283: * Retrieve list of members of a port set. ! 2284: * Conditions: ! 2285: * Nothing locked. ! 2286: * Returns: ! 2287: * KERN_SUCCESS Retrieved port set status. ! 2288: * KERN_INVALID_ARGUMENT Task is null. ! 2289: * KERN_INVALID_ARGUMENT Task is not active. ! 2290: * KERN_INVALID_ARGUMENT Name doesn't denote a port set. ! 2291: * Additions: ! 2292: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 2293: */ ! 2294: ! 2295: kern_return_t ! 2296: port_set_status(space, name, members, membersCnt) ! 2297: ipc_space_t space; ! 2298: mach_port_t name; ! 2299: mach_port_t **members; ! 2300: mach_msg_type_number_t *membersCnt; ! 2301: { ! 2302: kern_return_t kr; ! 2303: ! 2304: kr = mach_port_get_set_status(space, name, members, membersCnt); ! 2305: if ((kr != KERN_SUCCESS) && (kr != KERN_RESOURCE_SHORTAGE)) ! 2306: kr = KERN_INVALID_ARGUMENT; ! 2307: ! 2308: return kr; ! 2309: } ! 2310: ! 2311: /* ! 2312: * Routine: port_insert_send [kernel call] ! 2313: * Purpose: ! 2314: * Inserts send rights to a port into a task, ! 2315: * at a given name. The name must not be in use. ! 2316: * Conditions: ! 2317: * Nothing locked. ! 2318: * Returns: ! 2319: * KERN_SUCCESS Inserted send right. ! 2320: * KERN_INVALID_ARGUMENT Task is null. ! 2321: * KERN_INVALID_ARGUMENT Task is not active. ! 2322: * KERN_INVALID_ARGUMENT Port is null or dead. ! 2323: * KERN_INVALID_ARGUMENT Name is reserved. ! 2324: * KERN_NAME_EXISTS Name already denotes a right. ! 2325: * KERN_FAILURE Task already has rights for the port. ! 2326: * Additions: ! 2327: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 2328: */ ! 2329: ! 2330: kern_return_t ! 2331: port_insert_send(space, port, name) ! 2332: ipc_space_t space; ! 2333: ipc_port_t port; ! 2334: mach_port_t name; ! 2335: { ! 2336: kern_return_t kr; ! 2337: ! 2338: if ((space == IS_NULL) || ! 2339: !MACH_PORT_VALID(name) || ! 2340: !IP_VALID(port)) ! 2341: return KERN_INVALID_ARGUMENT; ! 2342: ! 2343: kr = ipc_object_copyout_name_compat(space, (ipc_object_t) port, ! 2344: MACH_MSG_TYPE_PORT_SEND, name); ! 2345: switch (kr) { ! 2346: case KERN_SUCCESS: ! 2347: case KERN_NAME_EXISTS: ! 2348: case KERN_RESOURCE_SHORTAGE: ! 2349: break; ! 2350: ! 2351: case KERN_RIGHT_EXISTS: ! 2352: kr = KERN_FAILURE; ! 2353: break; ! 2354: ! 2355: default: ! 2356: kr = KERN_INVALID_ARGUMENT; ! 2357: break; ! 2358: } ! 2359: ! 2360: return kr; ! 2361: } ! 2362: ! 2363: /* ! 2364: * Routine: port_extract_send [kernel call] ! 2365: * Purpose: ! 2366: * Extracts send rights from "task"'s "his_name" port. ! 2367: * The task is left with no rights for the port. ! 2368: * Conditions: ! 2369: * Nothing locked. ! 2370: * Returns: ! 2371: * KERN_SUCCESS Extracted send right. ! 2372: * KERN_INVALID_ARGUMENT Task is null. ! 2373: * KERN_INVALID_ARGUMENT Task is not active. ! 2374: * KERN_INVALID_ARGUMENT Name doesn't denote pure send rights. ! 2375: */ ! 2376: ! 2377: kern_return_t ! 2378: port_extract_send(space, name, portp) ! 2379: ipc_space_t space; ! 2380: mach_port_t name; ! 2381: ipc_port_t *portp; ! 2382: { ! 2383: kern_return_t kr; ! 2384: ! 2385: if (space == IS_NULL) ! 2386: return KERN_INVALID_ARGUMENT; ! 2387: ! 2388: kr = ipc_object_copyin_compat(space, name, ! 2389: MSG_TYPE_PORT, TRUE, ! 2390: (ipc_object_t *) portp); ! 2391: if (kr != KERN_SUCCESS) ! 2392: kr = KERN_INVALID_ARGUMENT; ! 2393: ! 2394: return kr; ! 2395: } ! 2396: ! 2397: /* ! 2398: * Routine: port_insert_receive [kernel call] ! 2399: * Purpose: ! 2400: * Inserts receive/ownership rights to a port into a task, ! 2401: * at a given name. ! 2402: * Conditions: ! 2403: * Nothing locked. ! 2404: * Returns: ! 2405: * KERN_SUCCESS Inserted receive right. ! 2406: * KERN_INVALID_ARGUMENT Task is null. ! 2407: * KERN_INVALID_ARGUMENT Task is not active. ! 2408: * KERN_INVALID_ARGUMENT Port is null. (Can't be dead.) ! 2409: * KERN_INVALID_ARGUMENT Name is reserved. ! 2410: * KERN_NAME_EXISTS Name already denotes a right. ! 2411: * KERN_FAILURE Task already has rights for the port. ! 2412: * Additions: ! 2413: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. ! 2414: */ ! 2415: ! 2416: kern_return_t ! 2417: port_insert_receive(space, port, name) ! 2418: ipc_space_t space; ! 2419: ipc_port_t port; ! 2420: mach_port_t name; ! 2421: { ! 2422: kern_return_t kr; ! 2423: ! 2424: if ((space == IS_NULL) || ! 2425: !MACH_PORT_VALID(name) || ! 2426: !IP_VALID(port)) ! 2427: return KERN_INVALID_ARGUMENT; ! 2428: ! 2429: kr = ipc_object_copyout_name_compat(space, (ipc_object_t) port, ! 2430: MACH_MSG_TYPE_PORT_RECEIVE, name); ! 2431: switch (kr) { ! 2432: case KERN_SUCCESS: ! 2433: case KERN_NAME_EXISTS: ! 2434: case KERN_RESOURCE_SHORTAGE: ! 2435: break; ! 2436: ! 2437: case KERN_RIGHT_EXISTS: ! 2438: kr = KERN_FAILURE; ! 2439: break; ! 2440: ! 2441: default: ! 2442: kr = KERN_INVALID_ARGUMENT; ! 2443: break; ! 2444: } ! 2445: ! 2446: return kr; ! 2447: } ! 2448: ! 2449: /* ! 2450: * Routine: port_extract_receive [kernel call] ! 2451: * Purpose: ! 2452: * Extracts receive/ownership rights ! 2453: * from "task"'s "his_name" port. ! 2454: * ! 2455: * The task is left with no rights for the port. ! 2456: * Conditions: ! 2457: * Nothing locked. ! 2458: * Returns: ! 2459: * KERN_SUCCESS Extracted receive right. ! 2460: * KERN_INVALID_ARGUMENT Task is null. ! 2461: * KERN_INVALID_ARGUMENT Task is not active. ! 2462: * KERN_INVALID_ARGUMENT Name doesn't denote receive rights. ! 2463: */ ! 2464: ! 2465: kern_return_t ! 2466: port_extract_receive(space, name, portp) ! 2467: ipc_space_t space; ! 2468: mach_port_t name; ! 2469: ipc_port_t *portp; ! 2470: { ! 2471: kern_return_t kr; ! 2472: ! 2473: if (space == IS_NULL) ! 2474: return KERN_INVALID_ARGUMENT; ! 2475: ! 2476: kr = ipc_object_copyin_compat(space, name, ! 2477: MSG_TYPE_PORT_ALL, TRUE, ! 2478: (ipc_object_t *) portp); ! 2479: if (kr != KERN_SUCCESS) ! 2480: kr = KERN_INVALID_ARGUMENT; ! 2481: ! 2482: return kr; ! 2483: } ! 2484: ! 2485: #endif /* MACH_IPC_COMPAT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.