Annotation of OSKit-Mach/ipc/ipc_right.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 1991,1990,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:  */
        !            28: /*
        !            29:  *     File:   ipc/ipc_right.c
        !            30:  *     Author: Rich Draves
        !            31:  *     Date:   1989
        !            32:  *
        !            33:  *     Functions to manipulate IPC capabilities.
        !            34:  */
        !            35: 
        !            36: #include <mach_ipc_compat.h>
        !            37: 
        !            38: #include <mach/boolean.h>
        !            39: #include <mach/kern_return.h>
        !            40: #include <mach/port.h>
        !            41: #include <mach/message.h>
        !            42: #include <kern/assert.h>
        !            43: #include <ipc/port.h>
        !            44: #include <ipc/ipc_entry.h>
        !            45: #include <ipc/ipc_space.h>
        !            46: #include <ipc/ipc_object.h>
        !            47: #include <ipc/ipc_hash.h>
        !            48: #include <ipc/ipc_port.h>
        !            49: #include <ipc/ipc_pset.h>
        !            50: #include <ipc/ipc_marequest.h>
        !            51: #include <ipc/ipc_right.h>
        !            52: #include <ipc/ipc_notify.h>
        !            53: 
        !            54: 
        !            55: 
        !            56: /*
        !            57:  *     Routine:        ipc_right_lookup_write
        !            58:  *     Purpose:
        !            59:  *             Finds an entry in a space, given the name.
        !            60:  *     Conditions:
        !            61:  *             Nothing locked.  If successful, the space is write-locked.
        !            62:  *     Returns:
        !            63:  *             KERN_SUCCESS            Found an entry.
        !            64:  *             KERN_INVALID_TASK       The space is dead.
        !            65:  *             KERN_INVALID_NAME       Name doesn't exist in space.
        !            66:  */
        !            67: 
        !            68: kern_return_t
        !            69: ipc_right_lookup_write(
        !            70:        ipc_space_t     space,
        !            71:        mach_port_t     name,
        !            72:        ipc_entry_t     *entryp)
        !            73: {
        !            74:        ipc_entry_t entry;
        !            75: 
        !            76:        assert(space != IS_NULL);
        !            77: 
        !            78:        is_write_lock(space);
        !            79: 
        !            80:        if (!space->is_active) {
        !            81:                is_write_unlock(space);
        !            82:                return KERN_INVALID_TASK;
        !            83:        }
        !            84: 
        !            85:        if ((entry = ipc_entry_lookup(space, name)) == IE_NULL) {
        !            86:                is_write_unlock(space);
        !            87:                return KERN_INVALID_NAME;
        !            88:        }
        !            89: 
        !            90:        *entryp = entry;
        !            91:        return KERN_SUCCESS;
        !            92: }
        !            93: 
        !            94: /*
        !            95:  *     Routine:        ipc_right_reverse
        !            96:  *     Purpose:
        !            97:  *             Translate (space, object) -> (name, entry).
        !            98:  *             Only finds send/receive rights.
        !            99:  *             Returns TRUE if an entry is found; if so,
        !           100:  *             the object is locked and active.
        !           101:  *     Conditions:
        !           102:  *             The space must be locked (read or write) and active.
        !           103:  *             Nothing else locked.
        !           104:  */
        !           105: 
        !           106: boolean_t
        !           107: ipc_right_reverse(
        !           108:        ipc_space_t     space,
        !           109:        ipc_object_t    object,
        !           110:        mach_port_t     *namep,
        !           111:        ipc_entry_t     *entryp)
        !           112: {
        !           113:        ipc_port_t port;
        !           114:        mach_port_t name;
        !           115:        ipc_entry_t entry;
        !           116: 
        !           117:        /* would switch on io_otype to handle multiple types of object */
        !           118: 
        !           119:        assert(space->is_active);
        !           120:        assert(io_otype(object) == IOT_PORT);
        !           121: 
        !           122:        port = (ipc_port_t) object;
        !           123: 
        !           124:        ip_lock(port);
        !           125:        if (!ip_active(port)) {
        !           126:                ip_unlock(port);
        !           127: 
        !           128:                return FALSE;
        !           129:        }
        !           130: 
        !           131:        if (port->ip_receiver == space) {
        !           132:                name = port->ip_receiver_name;
        !           133:                assert(name != MACH_PORT_NULL);
        !           134: 
        !           135:                entry = ipc_entry_lookup(space, name);
        !           136: 
        !           137:                assert(entry != IE_NULL);
        !           138:                assert(entry->ie_bits & MACH_PORT_TYPE_RECEIVE);
        !           139:                assert(port == (ipc_port_t) entry->ie_object);
        !           140: 
        !           141:                *namep = name;
        !           142:                *entryp = entry;
        !           143:                return TRUE;
        !           144:        }
        !           145: 
        !           146:        if (ipc_hash_lookup(space, (ipc_object_t) port, namep, entryp)) {
        !           147:                assert((entry = *entryp) != IE_NULL);
        !           148:                assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_SEND);
        !           149:                assert(port == (ipc_port_t) entry->ie_object);
        !           150: 
        !           151:                return TRUE;
        !           152:        }
        !           153: 
        !           154:        ip_unlock(port);
        !           155:        return FALSE;
        !           156: }
        !           157: 
        !           158: /*
        !           159:  *     Routine:        ipc_right_dnrequest
        !           160:  *     Purpose:
        !           161:  *             Make a dead-name request, returning the previously
        !           162:  *             registered send-once right.  If notify is IP_NULL,
        !           163:  *             just cancels the previously registered request.
        !           164:  *
        !           165:  *             This interacts with the IE_BITS_COMPAT, because they
        !           166:  *             both use ie_request.  If this is a compat entry, then
        !           167:  *             previous always gets IP_NULL.  If notify is IP_NULL,
        !           168:  *             then the entry remains a compat entry.  Otherwise
        !           169:  *             the real dead-name request is registered and the entry
        !           170:  *             is no longer a compat entry.
        !           171:  *     Conditions:
        !           172:  *             Nothing locked.  May allocate memory.
        !           173:  *             Only consumes/returns refs if successful.
        !           174:  *     Returns:
        !           175:  *             KERN_SUCCESS            Made/canceled dead-name request.
        !           176:  *             KERN_INVALID_TASK       The space is dead.
        !           177:  *             KERN_INVALID_NAME       Name doesn't exist in space.
        !           178:  *             KERN_INVALID_RIGHT      Name doesn't denote port/dead rights.
        !           179:  *             KERN_INVALID_ARGUMENT   Name denotes dead name, but
        !           180:  *                     immediate is FALSE or notify is IP_NULL.
        !           181:  *             KERN_UREFS_OVERFLOW     Name denotes dead name, but
        !           182:  *                     generating immediate notif. would overflow urefs.
        !           183:  *             KERN_RESOURCE_SHORTAGE  Couldn't allocate memory.
        !           184:  */
        !           185: 
        !           186: kern_return_t
        !           187: ipc_right_dnrequest(
        !           188:        ipc_space_t     space,
        !           189:        mach_port_t     name,
        !           190:        boolean_t       immediate,
        !           191:        ipc_port_t      notify,
        !           192:        ipc_port_t      *previousp)
        !           193: {
        !           194:        ipc_port_t previous;
        !           195: 
        !           196:        for (;;) {
        !           197:                ipc_entry_t entry;
        !           198:                ipc_entry_bits_t bits;
        !           199:                kern_return_t kr;
        !           200: 
        !           201:                kr = ipc_right_lookup_write(space, name, &entry);
        !           202:                if (kr != KERN_SUCCESS)
        !           203:                        return kr;
        !           204:                /* space is write-locked and active */
        !           205: 
        !           206:                bits = entry->ie_bits;
        !           207:                if (bits & MACH_PORT_TYPE_PORT_RIGHTS) {
        !           208:                        ipc_port_t port;
        !           209:                        ipc_port_request_index_t request;
        !           210: 
        !           211:                        port = (ipc_port_t) entry->ie_object;
        !           212:                        assert(port != IP_NULL);
        !           213: 
        !           214:                        if (!ipc_right_check(space, port, name, entry)) {
        !           215:                                /* port is locked and active */
        !           216: 
        !           217:                                if (notify == IP_NULL) {
        !           218: #if    MACH_IPC_COMPAT
        !           219:                                        if (bits & IE_BITS_COMPAT) {
        !           220:                                                assert(entry->ie_request != 0);
        !           221: 
        !           222:                                                previous = IP_NULL;
        !           223:                                        } else
        !           224: #endif /* MACH_IPC_COMPAT */
        !           225:                                        previous = ipc_right_dncancel_macro(
        !           226:                                                space, port, name, entry);
        !           227: 
        !           228:                                        ip_unlock(port);
        !           229:                                        is_write_unlock(space);
        !           230:                                        break;
        !           231:                                }
        !           232: 
        !           233:                                /*
        !           234:                                 *      If a registered soright exists,
        !           235:                                 *      want to atomically switch with it.
        !           236:                                 *      If ipc_port_dncancel finds us a
        !           237:                                 *      soright, then the following
        !           238:                                 *      ipc_port_dnrequest will reuse
        !           239:                                 *      that slot, so we are guaranteed
        !           240:                                 *      not to unlock and retry.
        !           241:                                 */
        !           242: 
        !           243:                                previous = ipc_right_dncancel_macro(space,
        !           244:                                                        port, name, entry);
        !           245: 
        !           246:                                kr = ipc_port_dnrequest(port, name, notify,
        !           247:                                                        &request);
        !           248:                                if (kr != KERN_SUCCESS) {
        !           249:                                        assert(previous == IP_NULL);
        !           250:                                        is_write_unlock(space);
        !           251: 
        !           252:                                        kr = ipc_port_dngrow(port);
        !           253:                                        /* port is unlocked */
        !           254:                                        if (kr != KERN_SUCCESS)
        !           255:                                                return kr;
        !           256: 
        !           257:                                        continue;
        !           258:                                }
        !           259: 
        !           260:                                assert(request != 0);
        !           261:                                ip_unlock(port);
        !           262: 
        !           263:                                entry->ie_request = request;
        !           264: #if    MACH_IPC_COMPAT
        !           265:                                entry->ie_bits = bits &~ IE_BITS_COMPAT;
        !           266: #endif /* MACH_IPC_COMPAT */
        !           267:                                is_write_unlock(space);
        !           268:                                break;
        !           269:                        }
        !           270: 
        !           271: #if    MACH_IPC_COMPAT
        !           272:                        if (bits & IE_BITS_COMPAT) {
        !           273:                                is_write_unlock(space);
        !           274:                                return KERN_INVALID_NAME;
        !           275:                        }
        !           276: #endif /* MACH_IPC_COMPAT */
        !           277: 
        !           278:                        bits = entry->ie_bits;
        !           279:                        assert(bits & MACH_PORT_TYPE_DEAD_NAME);
        !           280:                }
        !           281: 
        !           282:                if ((bits & MACH_PORT_TYPE_DEAD_NAME) &&
        !           283:                    immediate && (notify != IP_NULL)) {
        !           284:                        mach_port_urefs_t urefs = IE_BITS_UREFS(bits);
        !           285: 
        !           286:                        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
        !           287:                        assert(urefs > 0);
        !           288: 
        !           289:                        if (MACH_PORT_UREFS_OVERFLOW(urefs, 1)) {
        !           290:                                is_write_unlock(space);
        !           291:                                return KERN_UREFS_OVERFLOW;
        !           292:                        }
        !           293: 
        !           294:                        entry->ie_bits = bits + 1; /* increment urefs */
        !           295:                        is_write_unlock(space);
        !           296: 
        !           297:                        ipc_notify_dead_name(notify, name);
        !           298:                        previous = IP_NULL;
        !           299:                        break;
        !           300:                }
        !           301: 
        !           302:                is_write_unlock(space);
        !           303:                if (bits & MACH_PORT_TYPE_PORT_OR_DEAD)
        !           304:                        return KERN_INVALID_ARGUMENT;
        !           305:                else
        !           306:                        return KERN_INVALID_RIGHT;
        !           307:        }
        !           308: 
        !           309:        *previousp = previous;
        !           310:        return KERN_SUCCESS;
        !           311: }
        !           312: 
        !           313: /*
        !           314:  *     Routine:        ipc_right_dncancel
        !           315:  *     Purpose:
        !           316:  *             Cancel a dead-name request and return the send-once right.
        !           317:  *             Afterwards, entry->ie_request == 0.
        !           318:  *     Conditions:
        !           319:  *             The space must be write-locked; the port must be locked.
        !           320:  *             The port must be active; the space doesn't have to be.
        !           321:  */
        !           322: 
        !           323: ipc_port_t
        !           324: ipc_right_dncancel(
        !           325:        ipc_space_t     space,
        !           326:        ipc_port_t      port,
        !           327:        mach_port_t     name,
        !           328:        ipc_entry_t     entry)
        !           329: {
        !           330:        ipc_port_t dnrequest;
        !           331: 
        !           332:        assert(ip_active(port));
        !           333:        assert(port == (ipc_port_t) entry->ie_object);
        !           334: 
        !           335:        dnrequest = ipc_port_dncancel(port, name, entry->ie_request);
        !           336:        entry->ie_request = 0;
        !           337: 
        !           338: #if    MACH_IPC_COMPAT
        !           339:        assert(!ipr_spacep(dnrequest) == !(entry->ie_bits & IE_BITS_COMPAT));
        !           340: 
        !           341:        /* if this is actually a space ptr, just release the ref */
        !           342: 
        !           343:        if (entry->ie_bits & IE_BITS_COMPAT) {
        !           344:                assert(space == ipr_space(dnrequest));
        !           345: 
        !           346:                is_release(space);
        !           347:                dnrequest = IP_NULL;
        !           348:        }
        !           349: #endif /* MACH_IPC_COMPAT */
        !           350: 
        !           351:        return dnrequest;
        !           352: }
        !           353: 
        !           354: /*
        !           355:  *     Routine:        ipc_right_inuse
        !           356:  *     Purpose:
        !           357:  *             Check if an entry is being used.
        !           358:  *             Returns TRUE if it is.
        !           359:  *     Conditions:
        !           360:  *             The space is write-locked and active.
        !           361:  *             It is unlocked if the entry is inuse.
        !           362:  */
        !           363: 
        !           364: boolean_t
        !           365: ipc_right_inuse(space, name, entry)
        !           366:        ipc_space_t space;
        !           367:        mach_port_t name;
        !           368:        ipc_entry_t entry;
        !           369: {
        !           370:        ipc_entry_bits_t bits = entry->ie_bits;
        !           371: 
        !           372:        if (IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE) {
        !           373: #if    MACH_IPC_COMPAT
        !           374:                mach_port_type_t type = IE_BITS_TYPE(bits);
        !           375: 
        !           376:                /*
        !           377:                 *      There is yet hope.  If the port has died, we
        !           378:                 *      must clean up the entry so it's as good as new.
        !           379:                 */
        !           380: 
        !           381:                if ((bits & IE_BITS_COMPAT) &&
        !           382:                    ((type == MACH_PORT_TYPE_SEND) ||
        !           383:                     (type == MACH_PORT_TYPE_SEND_ONCE))) {
        !           384:                        ipc_port_t port;
        !           385:                        boolean_t active;
        !           386: 
        !           387:                        assert(IE_BITS_UREFS(bits) > 0);
        !           388:                        assert(entry->ie_request != 0);
        !           389: 
        !           390:                        port = (ipc_port_t) entry->ie_object;
        !           391:                        assert(port != IP_NULL);
        !           392: 
        !           393:                        ip_lock(port);
        !           394:                        active = ip_active(port);
        !           395:                        ip_unlock(port);
        !           396: 
        !           397:                        if (!active) {
        !           398:                                if (type == MACH_PORT_TYPE_SEND) {
        !           399:                                        /* clean up msg-accepted request */
        !           400: 
        !           401:                                        if (bits & IE_BITS_MAREQUEST)
        !           402:                                                ipc_marequest_cancel(
        !           403:                                                                space, name);
        !           404: 
        !           405:                                        ipc_hash_delete(
        !           406:                                                space, (ipc_object_t) port,
        !           407:                                                name, entry);
        !           408:                                } else {
        !           409:                                        assert(IE_BITS_UREFS(bits) == 1);
        !           410:                                        assert(!(bits & IE_BITS_MAREQUEST));
        !           411:                                }
        !           412: 
        !           413:                                ipc_port_release(port);
        !           414: 
        !           415:                                entry->ie_request = 0;
        !           416:                                entry->ie_object = IO_NULL;
        !           417:                                entry->ie_bits &= ~IE_BITS_RIGHT_MASK;
        !           418: 
        !           419:                                return FALSE;
        !           420:                        }
        !           421:                }
        !           422: #endif /* MACH_IPC_COMPAT */
        !           423: 
        !           424:                is_write_unlock(space);
        !           425:                return TRUE;
        !           426:        }
        !           427: 
        !           428:        return FALSE;
        !           429: }
        !           430: 
        !           431: /*
        !           432:  *     Routine:        ipc_right_check
        !           433:  *     Purpose:
        !           434:  *             Check if the port has died.  If it has,
        !           435:  *             clean up the entry and return TRUE.
        !           436:  *     Conditions:
        !           437:  *             The space is write-locked; the port is not locked.
        !           438:  *             If returns FALSE, the port is also locked and active.
        !           439:  *             Otherwise, entry is converted to a dead name, freeing
        !           440:  *             a reference to port.
        !           441:  *
        !           442:  *             [MACH_IPC_COMPAT] If the port is dead, and this is a
        !           443:  *             compat mode entry, then the port reference is released
        !           444:  *             and the entry is destroyed.  The call returns TRUE,
        !           445:  *             and the space is left locked.
        !           446:  */
        !           447: 
        !           448: boolean_t
        !           449: ipc_right_check(space, port, name, entry)
        !           450:        ipc_space_t space;
        !           451:        ipc_port_t port;
        !           452:        mach_port_t name;
        !           453:        ipc_entry_t entry;
        !           454: {
        !           455:        ipc_entry_bits_t bits;
        !           456: 
        !           457:        assert(space->is_active);
        !           458:        assert(port == (ipc_port_t) entry->ie_object);
        !           459: 
        !           460:        ip_lock(port);
        !           461:        if (ip_active(port))
        !           462:                return FALSE;
        !           463:        ip_unlock(port);
        !           464: 
        !           465:        /* this was either a pure send right or a send-once right */
        !           466: 
        !           467:        bits = entry->ie_bits;
        !           468:        assert((bits & MACH_PORT_TYPE_RECEIVE) == 0);
        !           469:        assert(IE_BITS_UREFS(bits) > 0);
        !           470: 
        !           471:        if (bits & MACH_PORT_TYPE_SEND) {
        !           472:                assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND);
        !           473: 
        !           474:                /* clean up msg-accepted request */
        !           475: 
        !           476:                if (bits & IE_BITS_MAREQUEST) {
        !           477:                        bits &= ~IE_BITS_MAREQUEST;
        !           478: 
        !           479:                        ipc_marequest_cancel(space, name);
        !           480:                }
        !           481: 
        !           482:                ipc_hash_delete(space, (ipc_object_t) port, name, entry);
        !           483:        } else {
        !           484:                assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
        !           485:                assert(IE_BITS_UREFS(bits) == 1);
        !           486:                assert((bits & IE_BITS_MAREQUEST) == 0);
        !           487:        }
        !           488: 
        !           489:        ipc_port_release(port);
        !           490: 
        !           491: #if    MACH_IPC_COMPAT
        !           492:        if (bits & IE_BITS_COMPAT) {
        !           493:                assert(entry->ie_request != 0);
        !           494:                entry->ie_request = 0;
        !           495: 
        !           496:                entry->ie_object = IO_NULL;
        !           497:                ipc_entry_dealloc(space, name, entry);
        !           498: 
        !           499:                return TRUE;
        !           500:        }
        !           501: #endif /* MACH_IPC_COMPAT */
        !           502: 
        !           503:        /* convert entry to dead name */
        !           504: 
        !           505:        bits = (bits &~ IE_BITS_TYPE_MASK) | MACH_PORT_TYPE_DEAD_NAME;
        !           506: 
        !           507:        if (entry->ie_request != 0) {
        !           508:                assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX);
        !           509: 
        !           510:                entry->ie_request = 0;
        !           511:                bits++;         /* increment urefs */
        !           512:        }
        !           513: 
        !           514:        entry->ie_bits = bits;
        !           515:        entry->ie_object = IO_NULL;
        !           516: 
        !           517:        return TRUE;
        !           518: }
        !           519: 
        !           520: /*
        !           521:  *     Routine:        ipc_right_clean
        !           522:  *     Purpose:
        !           523:  *             Cleans up an entry in a dead space.
        !           524:  *             The entry isn't deallocated or removed
        !           525:  *             from reverse hash tables.
        !           526:  *     Conditions:
        !           527:  *             The space is dead and unlocked.
        !           528:  */
        !           529: 
        !           530: void
        !           531: ipc_right_clean(
        !           532:        ipc_space_t     space,
        !           533:        mach_port_t     name,
        !           534:        ipc_entry_t     entry)
        !           535: {
        !           536:        ipc_entry_bits_t bits = entry->ie_bits;
        !           537:        mach_port_type_t type = IE_BITS_TYPE(bits);
        !           538: 
        !           539:        assert(!space->is_active);
        !           540: 
        !           541:        /*
        !           542:         *      We can't clean up IE_BITS_MAREQUEST when the space is dead.
        !           543:         *      This is because ipc_marequest_destroy can't turn off
        !           544:         *      the bit if the space is dead.  Hence, it might be on
        !           545:         *      even though the marequest has been destroyed.  It's OK
        !           546:         *      not to cancel the marequest, because ipc_marequest_destroy
        !           547:         *      cancels for us if the space is dead.
        !           548:         *
        !           549:         *      IE_BITS_COMPAT/ipc_right_dncancel doesn't have this
        !           550:         *      problem, because we check that the port is active.  If
        !           551:         *      we didn't cancel IE_BITS_COMPAT, ipc_port_destroy
        !           552:         *      would still work, but dead space refs would accumulate
        !           553:         *      in ip_dnrequests.  They would use up slots in
        !           554:         *      ip_dnrequests and keep the spaces from being freed.
        !           555:         */
        !           556: 
        !           557:        switch (type) {
        !           558:            case MACH_PORT_TYPE_DEAD_NAME:
        !           559:                assert(entry->ie_request == 0);
        !           560:                assert(entry->ie_object == IO_NULL);
        !           561:                assert((bits & IE_BITS_MAREQUEST) == 0);
        !           562:                break;
        !           563: 
        !           564:            case MACH_PORT_TYPE_PORT_SET: {
        !           565:                ipc_pset_t pset = (ipc_pset_t) entry->ie_object;
        !           566: 
        !           567:                assert(entry->ie_request == 0);
        !           568:                assert((bits & IE_BITS_MAREQUEST) == 0);
        !           569:                assert(pset != IPS_NULL);
        !           570: 
        !           571:                ips_lock(pset);
        !           572:                assert(ips_active(pset));
        !           573: 
        !           574:                ipc_pset_destroy(pset); /* consumes ref, unlocks */
        !           575:                break;
        !           576:            }
        !           577: 
        !           578:            case MACH_PORT_TYPE_SEND:
        !           579:            case MACH_PORT_TYPE_RECEIVE:
        !           580:            case MACH_PORT_TYPE_SEND_RECEIVE:
        !           581:            case MACH_PORT_TYPE_SEND_ONCE: {
        !           582:                ipc_port_t port = (ipc_port_t) entry->ie_object;
        !           583:                ipc_port_t dnrequest;
        !           584:                ipc_port_t nsrequest = IP_NULL;
        !           585:                mach_port_mscount_t mscount = 0; /* '=0' to shut up lint */
        !           586: 
        !           587:                assert(port != IP_NULL);
        !           588:                ip_lock(port);
        !           589: 
        !           590:                if (!ip_active(port)) {
        !           591:                        ip_release(port);
        !           592:                        ip_check_unlock(port);
        !           593:                        break;
        !           594:                }
        !           595: 
        !           596:                dnrequest = ipc_right_dncancel_macro(space, port, name, entry);
        !           597: 
        !           598:                if (type & MACH_PORT_TYPE_SEND) {
        !           599:                        assert(port->ip_srights > 0);
        !           600:                        if (--port->ip_srights == 0) {
        !           601:                                nsrequest = port->ip_nsrequest;
        !           602:                                if (nsrequest != IP_NULL) {
        !           603:                                        port->ip_nsrequest = IP_NULL;
        !           604:                                        mscount = port->ip_mscount;
        !           605:                                }
        !           606:                        }
        !           607:                }
        !           608: 
        !           609:                if (type & MACH_PORT_TYPE_RECEIVE) {
        !           610:                        assert(port->ip_receiver_name == name);
        !           611:                        assert(port->ip_receiver == space);
        !           612: 
        !           613:                        ipc_port_clear_receiver(port);
        !           614:                        ipc_port_destroy(port); /* consumes our ref, unlocks */
        !           615:                } else if (type & MACH_PORT_TYPE_SEND_ONCE) {
        !           616:                        assert(port->ip_sorights > 0);
        !           617:                        ip_unlock(port);
        !           618: 
        !           619:                        ipc_notify_send_once(port); /* consumes our ref */
        !           620:                } else {
        !           621:                        assert(port->ip_receiver != space);
        !           622: 
        !           623:                        ip_release(port);
        !           624:                        ip_unlock(port); /* port is active */
        !           625:                }
        !           626: 
        !           627:                if (nsrequest != IP_NULL)
        !           628:                        ipc_notify_no_senders(nsrequest, mscount);
        !           629: 
        !           630:                if (dnrequest != IP_NULL)
        !           631:                        ipc_notify_port_deleted(dnrequest, name);
        !           632:                break;
        !           633:            }
        !           634: 
        !           635:            default:
        !           636: #if MACH_ASSERT
        !           637:                assert(!"ipc_right_clean: strange type");
        !           638: #else
        !           639:                panic("ipc_right_clean: strange type");
        !           640: #endif
        !           641:        }
        !           642: }
        !           643: 
        !           644: /*
        !           645:  *     Routine:        ipc_right_destroy
        !           646:  *     Purpose:
        !           647:  *             Destroys an entry in a space.
        !           648:  *     Conditions:
        !           649:  *             The space is write-locked, and is unlocked upon return.
        !           650:  *             The space must be active.
        !           651:  *     Returns:
        !           652:  *             KERN_SUCCESS            The entry was destroyed.
        !           653:  */
        !           654: 
        !           655: kern_return_t
        !           656: ipc_right_destroy(
        !           657:        ipc_space_t     space,
        !           658:        mach_port_t     name,
        !           659:        ipc_entry_t     entry)
        !           660: {
        !           661:        ipc_entry_bits_t bits = entry->ie_bits;
        !           662:        mach_port_type_t type = IE_BITS_TYPE(bits);
        !           663: 
        !           664:        assert(space->is_active);
        !           665: 
        !           666:        switch (type) {
        !           667:            case MACH_PORT_TYPE_DEAD_NAME:
        !           668:                assert(entry->ie_request == 0);
        !           669:                assert(entry->ie_object == IO_NULL);
        !           670:                assert((bits & IE_BITS_MAREQUEST) == 0);
        !           671: 
        !           672:                ipc_entry_dealloc(space, name, entry);
        !           673:                is_write_unlock(space);
        !           674:                break;
        !           675: 
        !           676:            case MACH_PORT_TYPE_PORT_SET: {
        !           677:                ipc_pset_t pset = (ipc_pset_t) entry->ie_object;
        !           678: 
        !           679:                assert(entry->ie_request == 0);
        !           680:                assert(pset != IPS_NULL);
        !           681: 
        !           682:                entry->ie_object = IO_NULL;
        !           683:                ipc_entry_dealloc(space, name, entry);
        !           684: 
        !           685:                ips_lock(pset);
        !           686:                assert(ips_active(pset));
        !           687:                is_write_unlock(space);
        !           688: 
        !           689:                ipc_pset_destroy(pset); /* consumes ref, unlocks */
        !           690:                break;
        !           691:            }
        !           692: 
        !           693:            case MACH_PORT_TYPE_SEND:
        !           694:            case MACH_PORT_TYPE_RECEIVE:
        !           695:            case MACH_PORT_TYPE_SEND_RECEIVE:
        !           696:            case MACH_PORT_TYPE_SEND_ONCE: {
        !           697:                ipc_port_t port = (ipc_port_t) entry->ie_object;
        !           698:                ipc_port_t nsrequest = IP_NULL;
        !           699:                mach_port_mscount_t mscount = 0; /* '=0' to shut up lint */
        !           700:                ipc_port_t dnrequest;
        !           701: 
        !           702:                assert(port != IP_NULL);
        !           703: 
        !           704:                if (bits & IE_BITS_MAREQUEST) {
        !           705:                        assert(type & MACH_PORT_TYPE_SEND_RECEIVE);
        !           706: 
        !           707:                        ipc_marequest_cancel(space, name);
        !           708:                }
        !           709: 
        !           710:                if (type == MACH_PORT_TYPE_SEND)
        !           711:                        ipc_hash_delete(space, (ipc_object_t) port,
        !           712:                                        name, entry);
        !           713: 
        !           714:                ip_lock(port);
        !           715: 
        !           716:                if (!ip_active(port)) {
        !           717:                        assert((type & MACH_PORT_TYPE_RECEIVE) == 0);
        !           718: 
        !           719:                        ip_release(port);
        !           720:                        ip_check_unlock(port);
        !           721: 
        !           722:                        entry->ie_request = 0;
        !           723:                        entry->ie_object = IO_NULL;
        !           724:                        ipc_entry_dealloc(space, name, entry);
        !           725:                        is_write_unlock(space);
        !           726: 
        !           727: #if    MACH_IPC_COMPAT
        !           728:                        if (bits & IE_BITS_COMPAT)
        !           729:                                return KERN_INVALID_NAME;
        !           730: #endif /* MACH_IPC_COMPAT */
        !           731:                        break;
        !           732:                }
        !           733: 
        !           734:                dnrequest = ipc_right_dncancel_macro(space, port, name, entry);
        !           735: 
        !           736:                entry->ie_object = IO_NULL;
        !           737:                ipc_entry_dealloc(space, name, entry);
        !           738:                is_write_unlock(space);
        !           739: 
        !           740:                if (type & MACH_PORT_TYPE_SEND) {
        !           741:                        assert(port->ip_srights > 0);
        !           742:                        if (--port->ip_srights == 0) {
        !           743:                                nsrequest = port->ip_nsrequest;
        !           744:                                if (nsrequest != IP_NULL) {
        !           745:                                        port->ip_nsrequest = IP_NULL;
        !           746:                                        mscount = port->ip_mscount;
        !           747:                                }
        !           748:                        }
        !           749:                }
        !           750: 
        !           751:                if (type & MACH_PORT_TYPE_RECEIVE) {
        !           752:                        assert(ip_active(port));
        !           753:                        assert(port->ip_receiver == space);
        !           754: 
        !           755:                        ipc_port_clear_receiver(port);
        !           756:                        ipc_port_destroy(port); /* consumes our ref, unlocks */
        !           757:                } else if (type & MACH_PORT_TYPE_SEND_ONCE) {
        !           758:                        assert(port->ip_sorights > 0);
        !           759:                        ip_unlock(port);
        !           760: 
        !           761:                        ipc_notify_send_once(port); /* consumes our ref */
        !           762:                } else {
        !           763:                        assert(port->ip_receiver != space);
        !           764: 
        !           765:                        ip_release(port);
        !           766:                        ip_unlock(port);
        !           767:                }
        !           768: 
        !           769:                if (nsrequest != IP_NULL)
        !           770:                        ipc_notify_no_senders(nsrequest, mscount);
        !           771: 
        !           772:                if (dnrequest != IP_NULL)
        !           773:                        ipc_notify_port_deleted(dnrequest, name);
        !           774:                break;
        !           775:            }
        !           776: 
        !           777:            default:
        !           778: #if MACH_ASSERT
        !           779:                assert(!"ipc_right_destroy: strange type");
        !           780: #else
        !           781:                panic("ipc_right_destroy: strange type");
        !           782: #endif
        !           783:        }
        !           784: 
        !           785:        return KERN_SUCCESS;
        !           786: }
        !           787: 
        !           788: /*
        !           789:  *     Routine:        ipc_right_dealloc
        !           790:  *     Purpose:
        !           791:  *             Releases a send/send-once/dead-name user ref.
        !           792:  *             Like ipc_right_delta with a delta of -1,
        !           793:  *             but looks at the entry to determine the right.
        !           794:  *     Conditions:
        !           795:  *             The space is write-locked, and is unlocked upon return.
        !           796:  *             The space must be active.
        !           797:  *     Returns:
        !           798:  *             KERN_SUCCESS            A user ref was released.
        !           799:  *             KERN_INVALID_RIGHT      Entry has wrong type.
        !           800:  *             KERN_INVALID_NAME       [MACH_IPC_COMPAT]
        !           801:  *                     Caller should pretend lookup of entry failed.
        !           802:  */
        !           803: 
        !           804: kern_return_t
        !           805: ipc_right_dealloc(space, name, entry)
        !           806:        ipc_space_t space;
        !           807:        mach_port_t name;
        !           808:        ipc_entry_t entry;
        !           809: {
        !           810:        ipc_entry_bits_t bits = entry->ie_bits;
        !           811:        mach_port_type_t type = IE_BITS_TYPE(bits);
        !           812: 
        !           813:        assert(space->is_active);
        !           814: 
        !           815:        switch (type) {
        !           816:            case MACH_PORT_TYPE_DEAD_NAME: {
        !           817:            dead_name:
        !           818: 
        !           819:                assert(IE_BITS_UREFS(bits) > 0);
        !           820:                assert(entry->ie_request == 0);
        !           821:                assert(entry->ie_object == IO_NULL);
        !           822:                assert((bits & IE_BITS_MAREQUEST) == 0);
        !           823: 
        !           824:                if (IE_BITS_UREFS(bits) == 1)
        !           825:                        ipc_entry_dealloc(space, name, entry);
        !           826:                else
        !           827:                        entry->ie_bits = bits-1; /* decrement urefs */
        !           828: 
        !           829:                is_write_unlock(space);
        !           830:                break;
        !           831:            }
        !           832: 
        !           833:            case MACH_PORT_TYPE_SEND_ONCE: {
        !           834:                ipc_port_t port, dnrequest;
        !           835: 
        !           836:                assert(IE_BITS_UREFS(bits) == 1);
        !           837:                assert((bits & IE_BITS_MAREQUEST) == 0);
        !           838: 
        !           839:                port = (ipc_port_t) entry->ie_object;
        !           840:                assert(port != IP_NULL);
        !           841: 
        !           842:                if (ipc_right_check(space, port, name, entry)) {
        !           843: #if    MACH_IPC_COMPAT
        !           844:                        if (bits & IE_BITS_COMPAT)
        !           845:                                goto invalid_name;
        !           846: #endif /* MACH_IPC_COMPAT */
        !           847: 
        !           848:                        bits = entry->ie_bits;
        !           849:                        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
        !           850:                        goto dead_name;
        !           851:                }
        !           852:                /* port is locked and active */
        !           853: 
        !           854:                assert(port->ip_sorights > 0);
        !           855: 
        !           856:                dnrequest = ipc_right_dncancel_macro(space, port, name, entry);
        !           857:                ip_unlock(port);
        !           858: 
        !           859:                entry->ie_object = IO_NULL;
        !           860:                ipc_entry_dealloc(space, name, entry);
        !           861:                is_write_unlock(space);
        !           862: 
        !           863:                ipc_notify_send_once(port);
        !           864: 
        !           865:                if (dnrequest != IP_NULL)
        !           866:                        ipc_notify_port_deleted(dnrequest, name);
        !           867:                break;
        !           868:            }
        !           869: 
        !           870:            case MACH_PORT_TYPE_SEND: {
        !           871:                ipc_port_t port;
        !           872:                ipc_port_t dnrequest = IP_NULL;
        !           873:                ipc_port_t nsrequest = IP_NULL;
        !           874:                mach_port_mscount_t mscount = 0; /* '=0' to shut up lint */
        !           875: 
        !           876:                assert(IE_BITS_UREFS(bits) > 0);
        !           877: 
        !           878:                port = (ipc_port_t) entry->ie_object;
        !           879:                assert(port != IP_NULL);
        !           880: 
        !           881:                if (ipc_right_check(space, port, name, entry)) {
        !           882: #if    MACH_IPC_COMPAT
        !           883:                        if (bits & IE_BITS_COMPAT)
        !           884:                                goto invalid_name;
        !           885: #endif /* MACH_IPC_COMPAT */
        !           886: 
        !           887:                        bits = entry->ie_bits;
        !           888:                        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
        !           889:                        goto dead_name;
        !           890:                }
        !           891:                /* port is locked and active */
        !           892: 
        !           893:                assert(port->ip_srights > 0);
        !           894: 
        !           895:                if (IE_BITS_UREFS(bits) == 1) {
        !           896:                        if (--port->ip_srights == 0) {
        !           897:                                nsrequest = port->ip_nsrequest;
        !           898:                                if (nsrequest != IP_NULL) {
        !           899:                                        port->ip_nsrequest = IP_NULL;
        !           900:                                        mscount = port->ip_mscount;
        !           901:                                }
        !           902:                        }
        !           903: 
        !           904:                        dnrequest = ipc_right_dncancel_macro(space, port,
        !           905:                                                             name, entry);
        !           906: 
        !           907:                        ipc_hash_delete(space, (ipc_object_t) port,
        !           908:                                        name, entry);
        !           909: 
        !           910:                        if (bits & IE_BITS_MAREQUEST)
        !           911:                                ipc_marequest_cancel(space, name);
        !           912: 
        !           913:                        ip_release(port);
        !           914:                        entry->ie_object = IO_NULL;
        !           915:                        ipc_entry_dealloc(space, name, entry);
        !           916:                } else
        !           917:                        entry->ie_bits = bits-1; /* decrement urefs */
        !           918: 
        !           919:                ip_unlock(port); /* even if dropped a ref, port is active */
        !           920:                is_write_unlock(space);
        !           921: 
        !           922:                if (nsrequest != IP_NULL)
        !           923:                        ipc_notify_no_senders(nsrequest, mscount);
        !           924: 
        !           925:                if (dnrequest != IP_NULL)
        !           926:                        ipc_notify_port_deleted(dnrequest, name);
        !           927:                break;
        !           928:            }
        !           929: 
        !           930:            case MACH_PORT_TYPE_SEND_RECEIVE: {
        !           931:                ipc_port_t port;
        !           932:                ipc_port_t nsrequest = IP_NULL;
        !           933:                mach_port_mscount_t mscount = 0; /* '=0' to shut up lint */
        !           934: 
        !           935:                assert(IE_BITS_UREFS(bits) > 0);
        !           936: 
        !           937:                port = (ipc_port_t) entry->ie_object;
        !           938:                assert(port != IP_NULL);
        !           939: 
        !           940:                ip_lock(port);
        !           941:                assert(ip_active(port));
        !           942:                assert(port->ip_receiver_name == name);
        !           943:                assert(port->ip_receiver == space);
        !           944:                assert(port->ip_srights > 0);
        !           945: 
        !           946:                if (IE_BITS_UREFS(bits) == 1) {
        !           947:                        if (--port->ip_srights == 0) {
        !           948:                                nsrequest = port->ip_nsrequest;
        !           949:                                if (nsrequest != IP_NULL) {
        !           950:                                        port->ip_nsrequest = IP_NULL;
        !           951:                                        mscount = port->ip_mscount;
        !           952:                                }
        !           953:                        }
        !           954: 
        !           955:                        entry->ie_bits = bits &~ (IE_BITS_UREFS_MASK|
        !           956:                                                  MACH_PORT_TYPE_SEND);
        !           957:                } else
        !           958:                        entry->ie_bits = bits-1; /* decrement urefs */
        !           959: 
        !           960:                ip_unlock(port);
        !           961:                is_write_unlock(space);
        !           962: 
        !           963:                if (nsrequest != IP_NULL)
        !           964:                        ipc_notify_no_senders(nsrequest, mscount);
        !           965:                break;
        !           966:            }
        !           967: 
        !           968:            default:
        !           969:                is_write_unlock(space);
        !           970:                return KERN_INVALID_RIGHT;
        !           971:        }
        !           972: 
        !           973:        return KERN_SUCCESS;
        !           974: 
        !           975: #if    MACH_IPC_COMPAT
        !           976:     invalid_name:
        !           977:        is_write_unlock(space);
        !           978:        return KERN_INVALID_NAME;
        !           979: #endif /* MACH_IPC_COMPAT */
        !           980: }
        !           981: 
        !           982: /*
        !           983:  *     Routine:        ipc_right_delta
        !           984:  *     Purpose:
        !           985:  *             Modifies the user-reference count for a right.
        !           986:  *             May deallocate the right, if the count goes to zero.
        !           987:  *     Conditions:
        !           988:  *             The space is write-locked, and is unlocked upon return.
        !           989:  *             The space must be active.
        !           990:  *     Returns:
        !           991:  *             KERN_SUCCESS            Count was modified.
        !           992:  *             KERN_INVALID_RIGHT      Entry has wrong type.
        !           993:  *             KERN_INVALID_VALUE      Bad delta for the right.
        !           994:  *             KERN_UREFS_OVERFLOW     OK delta, except would overflow.
        !           995:  *             KERN_INVALID_NAME       [MACH_IPC_COMPAT]
        !           996:  *                     Caller should pretend lookup of entry failed.
        !           997:  */
        !           998: 
        !           999: kern_return_t
        !          1000: ipc_right_delta(space, name, entry, right, delta)
        !          1001:        ipc_space_t space;
        !          1002:        mach_port_t name;
        !          1003:        ipc_entry_t entry;
        !          1004:        mach_port_right_t right;
        !          1005:        mach_port_delta_t delta;
        !          1006: {
        !          1007:        ipc_entry_bits_t bits = entry->ie_bits;
        !          1008: 
        !          1009:        assert(space->is_active);
        !          1010:        assert(right < MACH_PORT_RIGHT_NUMBER);
        !          1011: 
        !          1012:        /* Rights-specific restrictions and operations. */
        !          1013: 
        !          1014:        switch (right) {
        !          1015:            case MACH_PORT_RIGHT_PORT_SET: {
        !          1016:                ipc_pset_t pset;
        !          1017: 
        !          1018:                if ((bits & MACH_PORT_TYPE_PORT_SET) == 0)
        !          1019:                        goto invalid_right;
        !          1020: 
        !          1021:                assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_PORT_SET);
        !          1022:                assert(IE_BITS_UREFS(bits) == 0);
        !          1023:                assert((bits & IE_BITS_MAREQUEST) == 0);
        !          1024:                assert(entry->ie_request == 0);
        !          1025: 
        !          1026:                if (delta == 0)
        !          1027:                        goto success;
        !          1028: 
        !          1029:                if (delta != -1)
        !          1030:                        goto invalid_value;
        !          1031: 
        !          1032:                pset = (ipc_pset_t) entry->ie_object;
        !          1033:                assert(pset != IPS_NULL);
        !          1034: 
        !          1035:                entry->ie_object = IO_NULL;
        !          1036:                ipc_entry_dealloc(space, name, entry);
        !          1037: 
        !          1038:                ips_lock(pset);
        !          1039:                assert(ips_active(pset));
        !          1040:                is_write_unlock(space);
        !          1041: 
        !          1042:                ipc_pset_destroy(pset); /* consumes ref, unlocks */
        !          1043:                break;
        !          1044:            }
        !          1045: 
        !          1046:            case MACH_PORT_RIGHT_RECEIVE: {
        !          1047:                ipc_port_t port;
        !          1048:                ipc_port_t dnrequest = IP_NULL;
        !          1049: 
        !          1050:                if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
        !          1051:                        goto invalid_right;
        !          1052: 
        !          1053:                if (delta == 0)
        !          1054:                        goto success;
        !          1055: 
        !          1056:                if (delta != -1)
        !          1057:                        goto invalid_value;
        !          1058: 
        !          1059:                if (bits & IE_BITS_MAREQUEST) {
        !          1060:                        bits &= ~IE_BITS_MAREQUEST;
        !          1061: 
        !          1062:                        ipc_marequest_cancel(space, name);
        !          1063:                }
        !          1064: 
        !          1065:                port = (ipc_port_t) entry->ie_object;
        !          1066:                assert(port != IP_NULL);
        !          1067: 
        !          1068:                /*
        !          1069:                 *      The port lock is needed for ipc_right_dncancel;
        !          1070:                 *      otherwise, we wouldn't have to take the lock
        !          1071:                 *      until just before dropping the space lock.
        !          1072:                 */
        !          1073: 
        !          1074:                ip_lock(port);
        !          1075:                assert(ip_active(port));
        !          1076:                assert(port->ip_receiver_name == name);
        !          1077:                assert(port->ip_receiver == space);
        !          1078: 
        !          1079: #if    MACH_IPC_COMPAT
        !          1080:                if (bits & IE_BITS_COMPAT) {
        !          1081:                        assert(entry->ie_request != 0);
        !          1082:                        dnrequest = ipc_right_dncancel(space, port,
        !          1083:                                                       name, entry);
        !          1084:                        assert(dnrequest == IP_NULL);
        !          1085: 
        !          1086:                        entry->ie_object = IO_NULL;
        !          1087:                        ipc_entry_dealloc(space, name, entry);
        !          1088:                } else
        !          1089: #endif /* MACH_IPC_COMPAT */
        !          1090:                if (bits & MACH_PORT_TYPE_SEND) {
        !          1091:                        assert(IE_BITS_TYPE(bits) ==
        !          1092:                                        MACH_PORT_TYPE_SEND_RECEIVE);
        !          1093:                        assert(IE_BITS_UREFS(bits) > 0);
        !          1094:                        assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX);
        !          1095:                        assert(port->ip_srights > 0);
        !          1096: 
        !          1097:                        /*
        !          1098:                         *      The remaining send right turns into a
        !          1099:                         *      dead name.  Notice we don't decrement
        !          1100:                         *      ip_srights, generate a no-senders notif,
        !          1101:                         *      or use ipc_right_dncancel, because the
        !          1102:                         *      port is destroyed "first".
        !          1103:                         */
        !          1104: 
        !          1105:                        bits &= ~IE_BITS_TYPE_MASK;
        !          1106:                        bits |= MACH_PORT_TYPE_DEAD_NAME;
        !          1107: 
        !          1108:                        if (entry->ie_request != 0) {
        !          1109:                                entry->ie_request = 0;
        !          1110:                                bits++; /* increment urefs */
        !          1111:                        }
        !          1112: 
        !          1113:                        entry->ie_bits = bits;
        !          1114:                        entry->ie_object = IO_NULL;
        !          1115:                } else {
        !          1116:                        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE);
        !          1117:                        assert(IE_BITS_UREFS(bits) == 0);
        !          1118: 
        !          1119:                        dnrequest = ipc_right_dncancel_macro(space, port,
        !          1120:                                                             name, entry);
        !          1121: 
        !          1122:                        entry->ie_object = IO_NULL;
        !          1123:                        ipc_entry_dealloc(space, name, entry);
        !          1124:                }
        !          1125:                is_write_unlock(space);
        !          1126: 
        !          1127:                ipc_port_clear_receiver(port);
        !          1128:                ipc_port_destroy(port); /* consumes ref, unlocks */
        !          1129: 
        !          1130:                if (dnrequest != IP_NULL)
        !          1131:                        ipc_notify_port_deleted(dnrequest, name);
        !          1132:                break;
        !          1133:            }
        !          1134: 
        !          1135:            case MACH_PORT_RIGHT_SEND_ONCE: {
        !          1136:                ipc_port_t port, dnrequest;
        !          1137: 
        !          1138:                if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0)
        !          1139:                        goto invalid_right;
        !          1140: 
        !          1141:                assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
        !          1142:                assert(IE_BITS_UREFS(bits) == 1);
        !          1143:                assert((bits & IE_BITS_MAREQUEST) == 0);
        !          1144: 
        !          1145:                if ((delta > 0) || (delta < -1))
        !          1146:                        goto invalid_value;
        !          1147: 
        !          1148:                port = (ipc_port_t) entry->ie_object;
        !          1149:                assert(port != IP_NULL);
        !          1150: 
        !          1151:                if (ipc_right_check(space, port, name, entry)) {
        !          1152: #if    MACH_IPC_COMPAT
        !          1153:                        if (bits & IE_BITS_COMPAT)
        !          1154:                                goto invalid_name;
        !          1155: #endif /* MACH_IPC_COMPAT */
        !          1156: 
        !          1157:                        assert(!(entry->ie_bits & MACH_PORT_TYPE_SEND_ONCE));
        !          1158:                        goto invalid_right;
        !          1159:                }
        !          1160:                /* port is locked and active */
        !          1161: 
        !          1162:                assert(port->ip_sorights > 0);
        !          1163: 
        !          1164:                if (delta == 0) {
        !          1165:                        ip_unlock(port);
        !          1166:                        goto success;
        !          1167:                }
        !          1168: 
        !          1169:                dnrequest = ipc_right_dncancel_macro(space, port, name, entry);
        !          1170:                ip_unlock(port);
        !          1171: 
        !          1172:                entry->ie_object = IO_NULL;
        !          1173:                ipc_entry_dealloc(space, name, entry);
        !          1174:                is_write_unlock(space);
        !          1175: 
        !          1176:                ipc_notify_send_once(port);
        !          1177: 
        !          1178:                if (dnrequest != IP_NULL)
        !          1179:                        ipc_notify_port_deleted(dnrequest, name);
        !          1180:                break;
        !          1181:            }
        !          1182: 
        !          1183:            case MACH_PORT_RIGHT_DEAD_NAME: {
        !          1184:                mach_port_urefs_t urefs;
        !          1185: 
        !          1186:                if (bits & MACH_PORT_TYPE_SEND_RIGHTS) {
        !          1187:                        ipc_port_t port;
        !          1188: 
        !          1189:                        port = (ipc_port_t) entry->ie_object;
        !          1190:                        assert(port != IP_NULL);
        !          1191: 
        !          1192:                        if (!ipc_right_check(space, port, name, entry)) {
        !          1193:                                /* port is locked and active */
        !          1194:                                ip_unlock(port);
        !          1195:                                goto invalid_right;
        !          1196:                        }
        !          1197: 
        !          1198: #if    MACH_IPC_COMPAT
        !          1199:                        if (bits & IE_BITS_COMPAT)
        !          1200:                                goto invalid_name;
        !          1201: #endif /* MACH_IPC_COMPAT */
        !          1202: 
        !          1203:                        bits = entry->ie_bits;
        !          1204:                } else if ((bits & MACH_PORT_TYPE_DEAD_NAME) == 0)
        !          1205:                        goto invalid_right;
        !          1206: 
        !          1207:                assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
        !          1208:                assert(IE_BITS_UREFS(bits) > 0);
        !          1209:                assert((bits & IE_BITS_MAREQUEST) == 0);
        !          1210:                assert(entry->ie_object == IO_NULL);
        !          1211:                assert(entry->ie_request == 0);
        !          1212: 
        !          1213:                urefs = IE_BITS_UREFS(bits);
        !          1214:                if (MACH_PORT_UREFS_UNDERFLOW(urefs, delta))
        !          1215:                        goto invalid_value;
        !          1216:                if (MACH_PORT_UREFS_OVERFLOW(urefs, delta))
        !          1217:                        goto urefs_overflow;
        !          1218: 
        !          1219:                if ((urefs + delta) == 0)
        !          1220:                        ipc_entry_dealloc(space, name, entry);
        !          1221:                else
        !          1222:                        entry->ie_bits = bits + delta;
        !          1223: 
        !          1224:                is_write_unlock(space);
        !          1225:                break;
        !          1226:            }
        !          1227: 
        !          1228:            case MACH_PORT_RIGHT_SEND: {
        !          1229:                mach_port_urefs_t urefs;
        !          1230:                ipc_port_t port;
        !          1231:                ipc_port_t dnrequest = IP_NULL;
        !          1232:                ipc_port_t nsrequest = IP_NULL;
        !          1233:                mach_port_mscount_t mscount = 0; /* '=0' to shut up lint */
        !          1234: 
        !          1235:                if ((bits & MACH_PORT_TYPE_SEND) == 0)
        !          1236:                        goto invalid_right;
        !          1237: 
        !          1238:                /* maximum urefs for send is MACH_PORT_UREFS_MAX-1 */
        !          1239: 
        !          1240:                urefs = IE_BITS_UREFS(bits);
        !          1241:                if (MACH_PORT_UREFS_UNDERFLOW(urefs, delta))
        !          1242:                        goto invalid_value;
        !          1243:                if (MACH_PORT_UREFS_OVERFLOW(urefs+1, delta))
        !          1244:                        goto urefs_overflow;
        !          1245: 
        !          1246:                port = (ipc_port_t) entry->ie_object;
        !          1247:                assert(port != IP_NULL);
        !          1248: 
        !          1249:                if (ipc_right_check(space, port, name, entry)) {
        !          1250: #if    MACH_IPC_COMPAT
        !          1251:                        if (bits & IE_BITS_COMPAT)
        !          1252:                                goto invalid_name;
        !          1253: #endif /* MACH_IPC_COMPAT */
        !          1254: 
        !          1255:                        assert((entry->ie_bits & MACH_PORT_TYPE_SEND) == 0);
        !          1256:                        goto invalid_right;
        !          1257:                }
        !          1258:                /* port is locked and active */
        !          1259: 
        !          1260:                assert(port->ip_srights > 0);
        !          1261: 
        !          1262:                if ((urefs + delta) == 0) {
        !          1263:                        if (--port->ip_srights == 0) {
        !          1264:                                nsrequest = port->ip_nsrequest;
        !          1265:                                if (nsrequest != IP_NULL) {
        !          1266:                                        port->ip_nsrequest = IP_NULL;
        !          1267:                                        mscount = port->ip_mscount;
        !          1268:                                }
        !          1269:                        }
        !          1270: 
        !          1271:                        if (bits & MACH_PORT_TYPE_RECEIVE) {
        !          1272:                                assert(port->ip_receiver_name == name);
        !          1273:                                assert(port->ip_receiver == space);
        !          1274:                                assert(IE_BITS_TYPE(bits) ==
        !          1275:                                                MACH_PORT_TYPE_SEND_RECEIVE);
        !          1276: 
        !          1277:                                entry->ie_bits = bits &~ (IE_BITS_UREFS_MASK|
        !          1278:                                                          MACH_PORT_TYPE_SEND);
        !          1279:                        } else {
        !          1280:                                assert(IE_BITS_TYPE(bits) ==
        !          1281:                                                MACH_PORT_TYPE_SEND);
        !          1282: 
        !          1283:                                dnrequest = ipc_right_dncancel_macro(
        !          1284:                                                space, port, name, entry);
        !          1285: 
        !          1286:                                ipc_hash_delete(space, (ipc_object_t) port,
        !          1287:                                                name, entry);
        !          1288: 
        !          1289:                                if (bits & IE_BITS_MAREQUEST)
        !          1290:                                        ipc_marequest_cancel(space, name);
        !          1291: 
        !          1292:                                ip_release(port);
        !          1293:                                entry->ie_object = IO_NULL;
        !          1294:                                ipc_entry_dealloc(space, name, entry);
        !          1295:                        }
        !          1296:                } else
        !          1297:                        entry->ie_bits = bits + delta;
        !          1298: 
        !          1299:                ip_unlock(port); /* even if dropped a ref, port is active */
        !          1300:                is_write_unlock(space);
        !          1301: 
        !          1302:                if (nsrequest != IP_NULL)
        !          1303:                        ipc_notify_no_senders(nsrequest, mscount);
        !          1304: 
        !          1305:                if (dnrequest != IP_NULL)
        !          1306:                        ipc_notify_port_deleted(dnrequest, name);
        !          1307:                break;
        !          1308:            }
        !          1309: 
        !          1310:            default:
        !          1311: #if MACH_ASSERT
        !          1312:                assert(!"ipc_right_delta: strange right");
        !          1313: #else
        !          1314:                panic("ipc_right_delta: strange right");
        !          1315: #endif
        !          1316:        }
        !          1317: 
        !          1318:        return KERN_SUCCESS;
        !          1319: 
        !          1320:     success:
        !          1321:        is_write_unlock(space);
        !          1322:        return KERN_SUCCESS;
        !          1323: 
        !          1324:     invalid_right:
        !          1325:        is_write_unlock(space);
        !          1326:        return KERN_INVALID_RIGHT;
        !          1327: 
        !          1328:     invalid_value:
        !          1329:        is_write_unlock(space);
        !          1330:        return KERN_INVALID_VALUE;
        !          1331: 
        !          1332:     urefs_overflow:
        !          1333:        is_write_unlock(space);
        !          1334:        return KERN_UREFS_OVERFLOW;
        !          1335: 
        !          1336: #if    MACH_IPC_COMPAT
        !          1337:     invalid_name:
        !          1338:        is_write_unlock(space);
        !          1339:        return KERN_INVALID_NAME;
        !          1340: #endif /* MACH_IPC_COMPAT */
        !          1341: }
        !          1342: 
        !          1343: /*
        !          1344:  *     Routine:        ipc_right_info
        !          1345:  *     Purpose:
        !          1346:  *             Retrieves information about the right.
        !          1347:  *     Conditions:
        !          1348:  *             The space is write-locked, and is unlocked upon return
        !          1349:  *             if the call is unsuccessful.  The space must be active.
        !          1350:  *     Returns:
        !          1351:  *             KERN_SUCCESS            Retrieved info; space still locked.
        !          1352:  */
        !          1353: 
        !          1354: kern_return_t
        !          1355: ipc_right_info(
        !          1356:        ipc_space_t             space,
        !          1357:        mach_port_t             name,
        !          1358:        ipc_entry_t             entry,
        !          1359:        mach_port_type_t        *typep,
        !          1360:        mach_port_urefs_t       *urefsp)
        !          1361: {
        !          1362:        ipc_entry_bits_t bits = entry->ie_bits;
        !          1363:        ipc_port_request_index_t request;
        !          1364:        mach_port_type_t type;
        !          1365: 
        !          1366:        if (bits & MACH_PORT_TYPE_SEND_RIGHTS) {
        !          1367:                ipc_port_t port = (ipc_port_t) entry->ie_object;
        !          1368: 
        !          1369:                if (ipc_right_check(space, port, name, entry)) {
        !          1370: #if    MACH_IPC_COMPAT
        !          1371:                        if (bits & IE_BITS_COMPAT) {
        !          1372:                                is_write_unlock(space);
        !          1373:                                return KERN_INVALID_NAME;
        !          1374:                        }
        !          1375: #endif /* MACH_IPC_COMPAT */
        !          1376: 
        !          1377:                        bits = entry->ie_bits;
        !          1378:                        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
        !          1379:                } else
        !          1380:                        ip_unlock(port);
        !          1381:        }
        !          1382: 
        !          1383:        type = IE_BITS_TYPE(bits);
        !          1384:        request = entry->ie_request;
        !          1385: 
        !          1386: #if    MACH_IPC_COMPAT
        !          1387:        if (bits & IE_BITS_COMPAT)
        !          1388:                type |= MACH_PORT_TYPE_COMPAT;
        !          1389:        else
        !          1390: #endif /* MACH_IPC_COMPAT */
        !          1391:        if (request != 0)
        !          1392:                type |= MACH_PORT_TYPE_DNREQUEST;
        !          1393:        if (bits & IE_BITS_MAREQUEST)
        !          1394:                type |= MACH_PORT_TYPE_MAREQUEST;
        !          1395: 
        !          1396:        *typep = type;
        !          1397:        *urefsp = IE_BITS_UREFS(bits);
        !          1398:        return KERN_SUCCESS;
        !          1399: }
        !          1400: 
        !          1401: /*
        !          1402:  *     Routine:        ipc_right_copyin_check
        !          1403:  *     Purpose:
        !          1404:  *             Check if a subsequent ipc_right_copyin would succeed.
        !          1405:  *     Conditions:
        !          1406:  *             The space is locked (read or write) and active.
        !          1407:  */
        !          1408: 
        !          1409: boolean_t
        !          1410: ipc_right_copyin_check(
        !          1411:        ipc_space_t             space,
        !          1412:        mach_port_t             name,
        !          1413:        ipc_entry_t             entry,
        !          1414:        mach_msg_type_name_t    msgt_name)
        !          1415: {
        !          1416:        ipc_entry_bits_t bits = entry->ie_bits;
        !          1417: 
        !          1418:        assert(space->is_active);
        !          1419: 
        !          1420:        switch (msgt_name) {
        !          1421:            case MACH_MSG_TYPE_MAKE_SEND:
        !          1422:            case MACH_MSG_TYPE_MAKE_SEND_ONCE:
        !          1423:            case MACH_MSG_TYPE_MOVE_RECEIVE:
        !          1424:                if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
        !          1425:                        return FALSE;
        !          1426: 
        !          1427:                break;
        !          1428: 
        !          1429:            case MACH_MSG_TYPE_COPY_SEND:
        !          1430:            case MACH_MSG_TYPE_MOVE_SEND:
        !          1431:            case MACH_MSG_TYPE_MOVE_SEND_ONCE: {
        !          1432:                ipc_port_t port;
        !          1433:                boolean_t active;
        !          1434: 
        !          1435:                if (bits & MACH_PORT_TYPE_DEAD_NAME)
        !          1436:                        break;
        !          1437: 
        !          1438:                if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0)
        !          1439:                        return FALSE;
        !          1440: 
        !          1441:                port = (ipc_port_t) entry->ie_object;
        !          1442:                assert(port != IP_NULL);
        !          1443: 
        !          1444:                ip_lock(port);
        !          1445:                active = ip_active(port);
        !          1446:                ip_unlock(port);
        !          1447: 
        !          1448:                if (!active) {
        !          1449: #if    MACH_IPC_COMPAT
        !          1450:                        if (bits & IE_BITS_COMPAT)
        !          1451:                                return FALSE;
        !          1452: #endif /* MACH_IPC_COMPAT */
        !          1453: 
        !          1454:                        break;
        !          1455:                }
        !          1456: 
        !          1457:                if (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE) {
        !          1458:                        if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0)
        !          1459:                                return FALSE;
        !          1460:                } else {
        !          1461:                        if ((bits & MACH_PORT_TYPE_SEND) == 0)
        !          1462:                                return FALSE;
        !          1463:                }
        !          1464: 
        !          1465:                break;
        !          1466:            }
        !          1467: 
        !          1468:            default:
        !          1469: #if MACH_ASSERT
        !          1470:                assert(!"ipc_right_copyin_check: strange rights");
        !          1471: #else
        !          1472:                panic("ipc_right_copyin_check: strange rights");
        !          1473: #endif
        !          1474:        }
        !          1475: 
        !          1476:        return TRUE;
        !          1477: }
        !          1478: 
        !          1479: /*
        !          1480:  *     Routine:        ipc_right_copyin
        !          1481:  *     Purpose:
        !          1482:  *             Copyin a capability from a space.
        !          1483:  *             If successful, the caller gets a ref
        !          1484:  *             for the resulting object, unless it is IO_DEAD,
        !          1485:  *             and possibly a send-once right which should
        !          1486:  *             be used in a port-deleted notification.
        !          1487:  *
        !          1488:  *             If deadok is not TRUE, the copyin operation
        !          1489:  *             will fail instead of producing IO_DEAD.
        !          1490:  *
        !          1491:  *             The entry is never deallocated (except
        !          1492:  *             when KERN_INVALID_NAME), so the caller
        !          1493:  *             should deallocate the entry if its type
        !          1494:  *             is MACH_PORT_TYPE_NONE.
        !          1495:  *     Conditions:
        !          1496:  *             The space is write-locked and active.
        !          1497:  *     Returns:
        !          1498:  *             KERN_SUCCESS            Acquired an object, possibly IO_DEAD.
        !          1499:  *             KERN_INVALID_RIGHT      Name doesn't denote correct right.
        !          1500:  */
        !          1501: 
        !          1502: kern_return_t
        !          1503: ipc_right_copyin(
        !          1504:        ipc_space_t             space,
        !          1505:        mach_port_t             name,
        !          1506:        ipc_entry_t             entry,
        !          1507:        mach_msg_type_name_t    msgt_name,
        !          1508:        boolean_t               deadok,
        !          1509:        ipc_object_t            *objectp,
        !          1510:        ipc_port_t              *sorightp)
        !          1511: {
        !          1512:        ipc_entry_bits_t bits = entry->ie_bits;
        !          1513: 
        !          1514:        assert(space->is_active);
        !          1515: 
        !          1516:        switch (msgt_name) {
        !          1517:            case MACH_MSG_TYPE_MAKE_SEND: {
        !          1518:                ipc_port_t port;
        !          1519: 
        !          1520:                if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
        !          1521:                        goto invalid_right;
        !          1522: 
        !          1523:                port = (ipc_port_t) entry->ie_object;
        !          1524:                assert(port != IP_NULL);
        !          1525: 
        !          1526:                ip_lock(port);
        !          1527:                assert(ip_active(port));
        !          1528:                assert(port->ip_receiver_name == name);
        !          1529:                assert(port->ip_receiver == space);
        !          1530: 
        !          1531:                port->ip_mscount++;
        !          1532:                port->ip_srights++;
        !          1533:                ip_reference(port);
        !          1534:                ip_unlock(port);
        !          1535: 
        !          1536:                *objectp = (ipc_object_t) port;
        !          1537:                *sorightp = IP_NULL;
        !          1538:                break;
        !          1539:            }
        !          1540: 
        !          1541:            case MACH_MSG_TYPE_MAKE_SEND_ONCE: {
        !          1542:                ipc_port_t port;
        !          1543: 
        !          1544:                if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
        !          1545:                        goto invalid_right;
        !          1546: 
        !          1547:                port = (ipc_port_t) entry->ie_object;
        !          1548:                assert(port != IP_NULL);
        !          1549: 
        !          1550:                ip_lock(port);
        !          1551:                assert(ip_active(port));
        !          1552:                assert(port->ip_receiver_name == name);
        !          1553:                assert(port->ip_receiver == space);
        !          1554: 
        !          1555:                port->ip_sorights++;
        !          1556:                ip_reference(port);
        !          1557:                ip_unlock(port);
        !          1558: 
        !          1559:                *objectp = (ipc_object_t) port;
        !          1560:                *sorightp = IP_NULL;
        !          1561:                break;
        !          1562:            }
        !          1563: 
        !          1564:            case MACH_MSG_TYPE_MOVE_RECEIVE: {
        !          1565:                ipc_port_t port;
        !          1566:                ipc_port_t dnrequest = IP_NULL;
        !          1567: 
        !          1568:                if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
        !          1569:                        goto invalid_right;
        !          1570: 
        !          1571:                port = (ipc_port_t) entry->ie_object;
        !          1572:                assert(port != IP_NULL);
        !          1573: 
        !          1574:                ip_lock(port);
        !          1575:                assert(ip_active(port));
        !          1576:                assert(port->ip_receiver_name == name);
        !          1577:                assert(port->ip_receiver == space);
        !          1578: 
        !          1579:                if (bits & MACH_PORT_TYPE_SEND) {
        !          1580:                        assert(IE_BITS_TYPE(bits) ==
        !          1581:                                        MACH_PORT_TYPE_SEND_RECEIVE);
        !          1582:                        assert(IE_BITS_UREFS(bits) > 0);
        !          1583:                        assert(port->ip_srights > 0);
        !          1584: 
        !          1585:                        ipc_hash_insert(space, (ipc_object_t) port,
        !          1586:                                        name, entry);
        !          1587: 
        !          1588:                        ip_reference(port);
        !          1589:                } else {
        !          1590:                        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE);
        !          1591:                        assert(IE_BITS_UREFS(bits) == 0);
        !          1592: 
        !          1593:                        dnrequest = ipc_right_dncancel_macro(space, port,
        !          1594:                                                             name, entry);
        !          1595: 
        !          1596:                        if (bits & IE_BITS_MAREQUEST)
        !          1597:                                ipc_marequest_cancel(space, name);
        !          1598: 
        !          1599:                        entry->ie_object = IO_NULL;
        !          1600:                }
        !          1601:                entry->ie_bits = bits &~ MACH_PORT_TYPE_RECEIVE;
        !          1602: 
        !          1603:                ipc_port_clear_receiver(port);
        !          1604: 
        !          1605:                port->ip_receiver_name = MACH_PORT_NULL;
        !          1606:                port->ip_destination = IP_NULL;
        !          1607:                ip_unlock(port);
        !          1608: 
        !          1609:                *objectp = (ipc_object_t) port;
        !          1610:                *sorightp = dnrequest;
        !          1611:                break;
        !          1612:            }
        !          1613: 
        !          1614:            case MACH_MSG_TYPE_COPY_SEND: {
        !          1615:                ipc_port_t port;
        !          1616: 
        !          1617:                if (bits & MACH_PORT_TYPE_DEAD_NAME)
        !          1618:                        goto copy_dead;
        !          1619: 
        !          1620:                /* allow for dead send-once rights */
        !          1621: 
        !          1622:                if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0)
        !          1623:                        goto invalid_right;
        !          1624: 
        !          1625:                assert(IE_BITS_UREFS(bits) > 0);
        !          1626: 
        !          1627:                port = (ipc_port_t) entry->ie_object;
        !          1628:                assert(port != IP_NULL);
        !          1629: 
        !          1630:                if (ipc_right_check(space, port, name, entry)) {
        !          1631: #if    MACH_IPC_COMPAT
        !          1632:                        if (bits & IE_BITS_COMPAT)
        !          1633:                                goto invalid_name;
        !          1634: #endif /* MACH_IPC_COMPAT */
        !          1635: 
        !          1636:                        bits = entry->ie_bits;
        !          1637:                        goto copy_dead;
        !          1638:                }
        !          1639:                /* port is locked and active */
        !          1640: 
        !          1641:                if ((bits & MACH_PORT_TYPE_SEND) == 0) {
        !          1642:                        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
        !          1643:                        assert(port->ip_sorights > 0);
        !          1644: 
        !          1645:                        ip_unlock(port);
        !          1646:                        goto invalid_right;
        !          1647:                }
        !          1648: 
        !          1649:                assert(port->ip_srights > 0);
        !          1650: 
        !          1651:                port->ip_srights++;
        !          1652:                ip_reference(port);
        !          1653:                ip_unlock(port);
        !          1654: 
        !          1655:                *objectp = (ipc_object_t) port;
        !          1656:                *sorightp = IP_NULL;
        !          1657:                break;
        !          1658:            }
        !          1659: 
        !          1660:            case MACH_MSG_TYPE_MOVE_SEND: {
        !          1661:                ipc_port_t port;
        !          1662:                ipc_port_t dnrequest = IP_NULL;
        !          1663: 
        !          1664:                if (bits & MACH_PORT_TYPE_DEAD_NAME)
        !          1665:                        goto move_dead;
        !          1666: 
        !          1667:                /* allow for dead send-once rights */
        !          1668: 
        !          1669:                if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0)
        !          1670:                        goto invalid_right;
        !          1671: 
        !          1672:                assert(IE_BITS_UREFS(bits) > 0);
        !          1673: 
        !          1674:                port = (ipc_port_t) entry->ie_object;
        !          1675:                assert(port != IP_NULL);
        !          1676: 
        !          1677:                if (ipc_right_check(space, port, name, entry)) {
        !          1678: #if    MACH_IPC_COMPAT
        !          1679:                        if (bits & IE_BITS_COMPAT)
        !          1680:                                goto invalid_name;
        !          1681: #endif /* MACH_IPC_COMPAT */
        !          1682: 
        !          1683:                        bits = entry->ie_bits;
        !          1684:                        goto move_dead;
        !          1685:                }
        !          1686:                /* port is locked and active */
        !          1687: 
        !          1688:                if ((bits & MACH_PORT_TYPE_SEND) == 0) {
        !          1689:                        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
        !          1690:                        assert(port->ip_sorights > 0);
        !          1691: 
        !          1692:                        ip_unlock(port);
        !          1693:                        goto invalid_right;
        !          1694:                }
        !          1695: 
        !          1696:                assert(port->ip_srights > 0);
        !          1697: 
        !          1698:                if (IE_BITS_UREFS(bits) == 1) {
        !          1699:                        if (bits & MACH_PORT_TYPE_RECEIVE) {
        !          1700:                                assert(port->ip_receiver_name == name);
        !          1701:                                assert(port->ip_receiver == space);
        !          1702:                                assert(IE_BITS_TYPE(bits) ==
        !          1703:                                                MACH_PORT_TYPE_SEND_RECEIVE);
        !          1704: 
        !          1705:                                ip_reference(port);
        !          1706:                        } else {
        !          1707:                                assert(IE_BITS_TYPE(bits) ==
        !          1708:                                                MACH_PORT_TYPE_SEND);
        !          1709: 
        !          1710:                                dnrequest = ipc_right_dncancel_macro(
        !          1711:                                                space, port, name, entry);
        !          1712: 
        !          1713:                                ipc_hash_delete(space, (ipc_object_t) port,
        !          1714:                                                name, entry);
        !          1715: 
        !          1716:                                if (bits & IE_BITS_MAREQUEST)
        !          1717:                                        ipc_marequest_cancel(space, name);
        !          1718: 
        !          1719:                                entry->ie_object = IO_NULL;
        !          1720:                        }
        !          1721:                        entry->ie_bits = bits &~
        !          1722:                                (IE_BITS_UREFS_MASK|MACH_PORT_TYPE_SEND);
        !          1723:                } else {
        !          1724:                        port->ip_srights++;
        !          1725:                        ip_reference(port);
        !          1726:                        entry->ie_bits = bits-1; /* decrement urefs */
        !          1727:                }
        !          1728: 
        !          1729:                ip_unlock(port);
        !          1730: 
        !          1731:                *objectp = (ipc_object_t) port;
        !          1732:                *sorightp = dnrequest;
        !          1733:                break;
        !          1734:            }
        !          1735: 
        !          1736:            case MACH_MSG_TYPE_MOVE_SEND_ONCE: {
        !          1737:                ipc_port_t port;
        !          1738:                ipc_port_t dnrequest;
        !          1739: 
        !          1740:                if (bits & MACH_PORT_TYPE_DEAD_NAME)
        !          1741:                        goto move_dead;
        !          1742: 
        !          1743:                /* allow for dead send rights */
        !          1744: 
        !          1745:                if ((bits & MACH_PORT_TYPE_SEND_RIGHTS) == 0)
        !          1746:                        goto invalid_right;
        !          1747: 
        !          1748:                assert(IE_BITS_UREFS(bits) > 0);
        !          1749: 
        !          1750:                port = (ipc_port_t) entry->ie_object;
        !          1751:                assert(port != IP_NULL);
        !          1752: 
        !          1753:                if (ipc_right_check(space, port, name, entry)) {
        !          1754: #if    MACH_IPC_COMPAT
        !          1755:                        if (bits & IE_BITS_COMPAT)
        !          1756:                                goto invalid_name;
        !          1757: #endif /* MACH_IPC_COMPAT */
        !          1758: 
        !          1759:                        bits = entry->ie_bits;
        !          1760:                        goto move_dead;
        !          1761:                }
        !          1762:                /* port is locked and active */
        !          1763: 
        !          1764:                if ((bits & MACH_PORT_TYPE_SEND_ONCE) == 0) {
        !          1765:                        assert(bits & MACH_PORT_TYPE_SEND);
        !          1766:                        assert(port->ip_srights > 0);
        !          1767: 
        !          1768:                        ip_unlock(port);
        !          1769:                        goto invalid_right;
        !          1770:                }
        !          1771: 
        !          1772:                assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND_ONCE);
        !          1773:                assert(IE_BITS_UREFS(bits) == 1);
        !          1774:                assert((bits & IE_BITS_MAREQUEST) == 0);
        !          1775:                assert(port->ip_sorights > 0);
        !          1776: 
        !          1777:                dnrequest = ipc_right_dncancel_macro(space, port, name, entry);
        !          1778:                ip_unlock(port);
        !          1779: 
        !          1780:                entry->ie_object = IO_NULL;
        !          1781:                entry->ie_bits = bits &~ MACH_PORT_TYPE_SEND_ONCE;
        !          1782: 
        !          1783:                *objectp = (ipc_object_t) port;
        !          1784:                *sorightp = dnrequest;
        !          1785:                break;
        !          1786:            }
        !          1787: 
        !          1788:            default:
        !          1789: #if MACH_ASSERT
        !          1790:                assert(!"ipc_right_copyin: strange rights");
        !          1791: #else
        !          1792:                panic("ipc_right_copyin: strange rights");
        !          1793: #endif
        !          1794:        }
        !          1795: 
        !          1796:        return KERN_SUCCESS;
        !          1797: 
        !          1798:     copy_dead:
        !          1799:        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
        !          1800:        assert(IE_BITS_UREFS(bits) > 0);
        !          1801:        assert((bits & IE_BITS_MAREQUEST) == 0);
        !          1802:        assert(entry->ie_request == 0);
        !          1803:        assert(entry->ie_object == 0);
        !          1804: 
        !          1805:        if (!deadok)
        !          1806:                goto invalid_right;
        !          1807: 
        !          1808:        *objectp = IO_DEAD;
        !          1809:        *sorightp = IP_NULL;
        !          1810:        return KERN_SUCCESS;
        !          1811: 
        !          1812:     move_dead:
        !          1813:        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
        !          1814:        assert(IE_BITS_UREFS(bits) > 0);
        !          1815:        assert((bits & IE_BITS_MAREQUEST) == 0);
        !          1816:        assert(entry->ie_request == 0);
        !          1817:        assert(entry->ie_object == 0);
        !          1818: 
        !          1819:        if (!deadok)
        !          1820:                goto invalid_right;
        !          1821: 
        !          1822:        if (IE_BITS_UREFS(bits) == 1)
        !          1823:                entry->ie_bits = bits &~ MACH_PORT_TYPE_DEAD_NAME;
        !          1824:        else
        !          1825:                entry->ie_bits = bits-1; /* decrement urefs */
        !          1826: 
        !          1827:        *objectp = IO_DEAD;
        !          1828:        *sorightp = IP_NULL;
        !          1829:        return KERN_SUCCESS;
        !          1830: 
        !          1831:     invalid_right:
        !          1832:        return KERN_INVALID_RIGHT;
        !          1833: 
        !          1834: #if    MACH_IPC_COMPAT
        !          1835:     invalid_name:
        !          1836:        return KERN_INVALID_NAME;
        !          1837: #endif /* MACH_IPC_COMPAT */
        !          1838: }
        !          1839: 
        !          1840: /*
        !          1841:  *     Routine:        ipc_right_copyin_undo
        !          1842:  *     Purpose:
        !          1843:  *             Undoes the effects of an ipc_right_copyin
        !          1844:  *             of a send/send-once right that is dead.
        !          1845:  *             (Object is either IO_DEAD or a dead port.)
        !          1846:  *     Conditions:
        !          1847:  *             The space is write-locked and active.
        !          1848:  */
        !          1849: 
        !          1850: void
        !          1851: ipc_right_copyin_undo(
        !          1852:        ipc_space_t             space,
        !          1853:        mach_port_t             name,
        !          1854:        ipc_entry_t             entry,
        !          1855:        mach_msg_type_name_t    msgt_name,
        !          1856:        ipc_object_t            object,
        !          1857:        ipc_port_t              soright)
        !          1858: {
        !          1859:        ipc_entry_bits_t bits = entry->ie_bits;
        !          1860: 
        !          1861:        assert(space->is_active);
        !          1862: 
        !          1863:        assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) ||
        !          1864:               (msgt_name == MACH_MSG_TYPE_COPY_SEND) ||
        !          1865:               (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE));
        !          1866: 
        !          1867:        if (soright != IP_NULL) {
        !          1868:                assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) ||
        !          1869:                       (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE));
        !          1870:                assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
        !          1871:                assert(entry->ie_object == IO_NULL);
        !          1872:                assert(object != IO_DEAD);
        !          1873: 
        !          1874:                entry->ie_bits = ((bits &~ IE_BITS_RIGHT_MASK) |
        !          1875:                                  MACH_PORT_TYPE_DEAD_NAME | 2);
        !          1876:        } else if (IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE) {
        !          1877:                assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) ||
        !          1878:                       (msgt_name == MACH_MSG_TYPE_MOVE_SEND_ONCE));
        !          1879:                assert(entry->ie_object == IO_NULL);
        !          1880: 
        !          1881:                entry->ie_bits = ((bits &~ IE_BITS_RIGHT_MASK) |
        !          1882:                                  MACH_PORT_TYPE_DEAD_NAME | 1);
        !          1883:        } else if (IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME) {
        !          1884:                assert(entry->ie_object == IO_NULL);
        !          1885:                assert(object == IO_DEAD);
        !          1886:                assert(IE_BITS_UREFS(bits) > 0);
        !          1887: 
        !          1888:                if (msgt_name != MACH_MSG_TYPE_COPY_SEND) {
        !          1889:                        assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX);
        !          1890: 
        !          1891:                        entry->ie_bits = bits+1; /* increment urefs */
        !          1892:                }
        !          1893:        } else {
        !          1894:                assert((msgt_name == MACH_MSG_TYPE_MOVE_SEND) ||
        !          1895:                       (msgt_name == MACH_MSG_TYPE_COPY_SEND));
        !          1896:                assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND);
        !          1897:                assert(object != IO_DEAD);
        !          1898:                assert(entry->ie_object == object);
        !          1899:                assert(IE_BITS_UREFS(bits) > 0);
        !          1900: 
        !          1901:                if (msgt_name != MACH_MSG_TYPE_COPY_SEND) {
        !          1902:                        assert(IE_BITS_UREFS(bits) < MACH_PORT_UREFS_MAX-1);
        !          1903: 
        !          1904:                        entry->ie_bits = bits+1; /* increment urefs */
        !          1905:                }
        !          1906: 
        !          1907:                /*
        !          1908:                 *      May as well convert the entry to a dead name.
        !          1909:                 *      (Or if it is a compat entry, destroy it.)
        !          1910:                 */
        !          1911: 
        !          1912:                (void) ipc_right_check(space, (ipc_port_t) object,
        !          1913:                                       name, entry);
        !          1914:                /* object is dead so it is not locked */
        !          1915:        }
        !          1916: 
        !          1917:        /* release the reference acquired by copyin */
        !          1918: 
        !          1919:        if (object != IO_DEAD)
        !          1920:                ipc_object_release(object);
        !          1921: }
        !          1922: 
        !          1923: /*
        !          1924:  *     Routine:        ipc_right_copyin_two
        !          1925:  *     Purpose:
        !          1926:  *             Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND
        !          1927:  *             and deadok == FALSE, except that this moves two
        !          1928:  *             send rights at once.
        !          1929:  *     Conditions:
        !          1930:  *             The space is write-locked and active.
        !          1931:  *             The object is returned with two refs/send rights.
        !          1932:  *     Returns:
        !          1933:  *             KERN_SUCCESS            Acquired an object.
        !          1934:  *             KERN_INVALID_RIGHT      Name doesn't denote correct right.
        !          1935:  */
        !          1936: 
        !          1937: kern_return_t
        !          1938: ipc_right_copyin_two(
        !          1939:        ipc_space_t     space,
        !          1940:        mach_port_t     name,
        !          1941:        ipc_entry_t     entry,
        !          1942:        ipc_object_t    *objectp,
        !          1943:        ipc_port_t      *sorightp)
        !          1944: {
        !          1945:        ipc_entry_bits_t bits = entry->ie_bits;
        !          1946:        mach_port_urefs_t urefs;
        !          1947:        ipc_port_t port;
        !          1948:        ipc_port_t dnrequest = IP_NULL;
        !          1949: 
        !          1950:        assert(space->is_active);
        !          1951: 
        !          1952:        if ((bits & MACH_PORT_TYPE_SEND) == 0)
        !          1953:                goto invalid_right;
        !          1954: 
        !          1955:        urefs = IE_BITS_UREFS(bits);
        !          1956:        if (urefs < 2)
        !          1957:                goto invalid_right;
        !          1958: 
        !          1959:        port = (ipc_port_t) entry->ie_object;
        !          1960:        assert(port != IP_NULL);
        !          1961: 
        !          1962:        if (ipc_right_check(space, port, name, entry)) {
        !          1963: #if    MACH_IPC_COMPAT
        !          1964:                if (bits & IE_BITS_COMPAT)
        !          1965:                        goto invalid_name;
        !          1966: #endif /* MACH_IPC_COMPAT */
        !          1967: 
        !          1968:                goto invalid_right;
        !          1969:        }
        !          1970:        /* port is locked and active */
        !          1971: 
        !          1972:        assert(port->ip_srights > 0);
        !          1973: 
        !          1974:        if (urefs == 2) {
        !          1975:                if (bits & MACH_PORT_TYPE_RECEIVE) {
        !          1976:                        assert(port->ip_receiver_name == name);
        !          1977:                        assert(port->ip_receiver == space);
        !          1978:                        assert(IE_BITS_TYPE(bits) ==
        !          1979:                                        MACH_PORT_TYPE_SEND_RECEIVE);
        !          1980: 
        !          1981:                        port->ip_srights++;
        !          1982:                        ip_reference(port);
        !          1983:                        ip_reference(port);
        !          1984:                } else {
        !          1985:                        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND);
        !          1986: 
        !          1987:                        dnrequest = ipc_right_dncancel_macro(space, port,
        !          1988:                                                             name, entry);
        !          1989: 
        !          1990:                        ipc_hash_delete(space, (ipc_object_t) port,
        !          1991:                                        name, entry);
        !          1992: 
        !          1993:                        if (bits & IE_BITS_MAREQUEST)
        !          1994:                                ipc_marequest_cancel(space, name);
        !          1995: 
        !          1996:                        port->ip_srights++;
        !          1997:                        ip_reference(port);
        !          1998:                        entry->ie_object = IO_NULL;
        !          1999:                }
        !          2000:                entry->ie_bits = bits &~
        !          2001:                        (IE_BITS_UREFS_MASK|MACH_PORT_TYPE_SEND);
        !          2002:        } else {
        !          2003:                port->ip_srights += 2;
        !          2004:                ip_reference(port);
        !          2005:                ip_reference(port);
        !          2006:                entry->ie_bits = bits-2; /* decrement urefs */
        !          2007:        }
        !          2008:        ip_unlock(port);
        !          2009: 
        !          2010:        *objectp = (ipc_object_t) port;
        !          2011:        *sorightp = dnrequest;
        !          2012:        return KERN_SUCCESS;
        !          2013: 
        !          2014:     invalid_right:
        !          2015:        return KERN_INVALID_RIGHT;
        !          2016: 
        !          2017: #if    MACH_IPC_COMPAT
        !          2018:     invalid_name:
        !          2019:        return KERN_INVALID_NAME;
        !          2020: #endif /* MACH_IPC_COMPAT */
        !          2021: }
        !          2022: 
        !          2023: /*
        !          2024:  *     Routine:        ipc_right_copyout
        !          2025:  *     Purpose:
        !          2026:  *             Copyout a capability to a space.
        !          2027:  *             If successful, consumes a ref for the object.
        !          2028:  *
        !          2029:  *             Always succeeds when given a newly-allocated entry,
        !          2030:  *             because user-reference overflow isn't a possibility.
        !          2031:  *
        !          2032:  *             If copying out the object would cause the user-reference
        !          2033:  *             count in the entry to overflow, and overflow is TRUE,
        !          2034:  *             then instead the user-reference count is left pegged
        !          2035:  *             to its maximum value and the copyout succeeds anyway.
        !          2036:  *     Conditions:
        !          2037:  *             The space is write-locked and active.
        !          2038:  *             The object is locked and active.
        !          2039:  *             The object is unlocked; the space isn't.
        !          2040:  *     Returns:
        !          2041:  *             KERN_SUCCESS            Copied out capability.
        !          2042:  *             KERN_UREFS_OVERFLOW     User-refs would overflow;
        !          2043:  *                     guaranteed not to happen with a fresh entry
        !          2044:  *                     or if overflow=TRUE was specified.
        !          2045:  */
        !          2046: 
        !          2047: kern_return_t
        !          2048: ipc_right_copyout(
        !          2049:        ipc_space_t             space,
        !          2050:        mach_port_t             name,
        !          2051:        ipc_entry_t             entry,
        !          2052:        mach_msg_type_name_t    msgt_name,
        !          2053:        boolean_t               overflow,
        !          2054:        ipc_object_t            object)
        !          2055: {
        !          2056:        ipc_entry_bits_t bits = entry->ie_bits;
        !          2057:        ipc_port_t port;
        !          2058: 
        !          2059:        assert(IO_VALID(object));
        !          2060:        assert(io_otype(object) == IOT_PORT);
        !          2061:        assert(io_active(object));
        !          2062:        assert(entry->ie_object == object);
        !          2063: 
        !          2064:        port = (ipc_port_t) object;
        !          2065: 
        !          2066:        switch (msgt_name) {
        !          2067:            case MACH_MSG_TYPE_PORT_SEND_ONCE:
        !          2068:                assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
        !          2069:                assert(port->ip_sorights > 0);
        !          2070: 
        !          2071:                /* transfer send-once right and ref to entry */
        !          2072:                ip_unlock(port);
        !          2073: 
        !          2074:                entry->ie_bits = bits | (MACH_PORT_TYPE_SEND_ONCE | 1);
        !          2075:                break;
        !          2076: 
        !          2077:            case MACH_MSG_TYPE_PORT_SEND:
        !          2078:                assert(port->ip_srights > 0);
        !          2079: 
        !          2080:                if (bits & MACH_PORT_TYPE_SEND) {
        !          2081:                        mach_port_urefs_t urefs = IE_BITS_UREFS(bits);
        !          2082: 
        !          2083:                        assert(port->ip_srights > 1);
        !          2084:                        assert(urefs > 0);
        !          2085:                        assert(urefs < MACH_PORT_UREFS_MAX);
        !          2086: 
        !          2087:                        if (urefs+1 == MACH_PORT_UREFS_MAX) {
        !          2088:                                if (overflow) {
        !          2089:                                        /* leave urefs pegged to maximum */
        !          2090: 
        !          2091:                                        port->ip_srights--;
        !          2092:                                        ip_release(port);
        !          2093:                                        ip_unlock(port);
        !          2094:                                        return KERN_SUCCESS;
        !          2095:                                }
        !          2096: 
        !          2097:                                ip_unlock(port);
        !          2098:                                return KERN_UREFS_OVERFLOW;
        !          2099:                        }
        !          2100: 
        !          2101:                        port->ip_srights--;
        !          2102:                        ip_release(port);
        !          2103:                        ip_unlock(port);
        !          2104:                } else if (bits & MACH_PORT_TYPE_RECEIVE) {
        !          2105:                        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_RECEIVE);
        !          2106:                        assert(IE_BITS_UREFS(bits) == 0);
        !          2107: 
        !          2108:                        /* transfer send right to entry */
        !          2109:                        ip_release(port);
        !          2110:                        ip_unlock(port);
        !          2111:                } else {
        !          2112:                        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
        !          2113:                        assert(IE_BITS_UREFS(bits) == 0);
        !          2114: 
        !          2115:                        /* transfer send right and ref to entry */
        !          2116:                        ip_unlock(port);
        !          2117: 
        !          2118:                        /* entry is locked holding ref, so can use port */
        !          2119: 
        !          2120:                        ipc_hash_insert(space, (ipc_object_t) port,
        !          2121:                                        name, entry);
        !          2122:                }
        !          2123: 
        !          2124:                entry->ie_bits = (bits | MACH_PORT_TYPE_SEND) + 1;
        !          2125:                break;
        !          2126: 
        !          2127:            case MACH_MSG_TYPE_PORT_RECEIVE: {
        !          2128:                ipc_port_t dest;
        !          2129: 
        !          2130:                assert(port->ip_mscount == 0);
        !          2131:                assert(port->ip_receiver_name == MACH_PORT_NULL);
        !          2132:                dest = port->ip_destination;
        !          2133: 
        !          2134:                port->ip_receiver_name = name;
        !          2135:                port->ip_receiver = space;
        !          2136: 
        !          2137:                assert((bits & MACH_PORT_TYPE_RECEIVE) == 0);
        !          2138: 
        !          2139:                if (bits & MACH_PORT_TYPE_SEND) {
        !          2140:                        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_SEND);
        !          2141:                        assert(IE_BITS_UREFS(bits) > 0);
        !          2142:                        assert(port->ip_srights > 0);
        !          2143: 
        !          2144:                        ip_release(port);
        !          2145:                        ip_unlock(port);
        !          2146: 
        !          2147:                        /* entry is locked holding ref, so can use port */
        !          2148: 
        !          2149:                        ipc_hash_delete(space, (ipc_object_t) port,
        !          2150:                                        name, entry);
        !          2151:                } else {
        !          2152:                        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
        !          2153:                        assert(IE_BITS_UREFS(bits) == 0);
        !          2154: 
        !          2155:                        /* transfer ref to entry */
        !          2156:                        ip_unlock(port);
        !          2157:                }
        !          2158: 
        !          2159:                entry->ie_bits = bits | MACH_PORT_TYPE_RECEIVE;
        !          2160: 
        !          2161:                if (dest != IP_NULL)
        !          2162:                        ipc_port_release(dest);
        !          2163:                break;
        !          2164:            }
        !          2165: 
        !          2166:            default:
        !          2167: #if MACH_ASSERT
        !          2168:                assert(!"ipc_right_copyout: strange rights");
        !          2169: #else
        !          2170:                panic("ipc_right_copyout: strange rights");
        !          2171: #endif
        !          2172:        }
        !          2173: 
        !          2174:        return KERN_SUCCESS;
        !          2175: }
        !          2176: 
        !          2177: #if 0
        !          2178: /*XXX same, but allows multiple duplicate send rights */
        !          2179: kern_return_t
        !          2180: ipc_right_copyout_multiname(space, name, entry, object)
        !          2181:        ipc_space_t space;
        !          2182:        mach_port_t name;
        !          2183:        ipc_entry_t entry;
        !          2184:        ipc_object_t object;
        !          2185: {
        !          2186:        ipc_entry_bits_t bits = entry->ie_bits;
        !          2187:        ipc_port_t port;
        !          2188: 
        !          2189:        assert(IO_VALID(object));
        !          2190:        assert(io_otype(object) == IOT_PORT);
        !          2191:        assert(io_active(object));
        !          2192:        assert(entry->ie_object == object);
        !          2193: 
        !          2194:        port = (ipc_port_t) object;
        !          2195: 
        !          2196:        assert(port->ip_srights > 0);
        !          2197: 
        !          2198:        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_NONE);
        !          2199:        assert(IE_BITS_UREFS(bits) == 0);
        !          2200: 
        !          2201:        /* transfer send right and ref to entry */
        !          2202:        ip_unlock(port);
        !          2203: 
        !          2204:        /* entry is locked holding ref, so can use port */
        !          2205: 
        !          2206:        entry->ie_bits = (bits | MACH_PORT_TYPE_SEND) + 1;
        !          2207: 
        !          2208:        return KERN_SUCCESS;
        !          2209: }
        !          2210: #endif
        !          2211: 
        !          2212: /*
        !          2213:  *     Routine:        ipc_right_rename
        !          2214:  *     Purpose:
        !          2215:  *             Transfer an entry from one name to another.
        !          2216:  *             The old entry is deallocated.
        !          2217:  *     Conditions:
        !          2218:  *             The space is write-locked and active.
        !          2219:  *             The new entry is unused.  Upon return,
        !          2220:  *             the space is unlocked.
        !          2221:  *     Returns:
        !          2222:  *             KERN_SUCCESS            Moved entry to new name.
        !          2223:  */
        !          2224: 
        !          2225: kern_return_t
        !          2226: ipc_right_rename(
        !          2227:        ipc_space_t     space,
        !          2228:        mach_port_t     oname,
        !          2229:        ipc_entry_t     oentry,
        !          2230:        mach_port_t     nname,
        !          2231:        ipc_entry_t     nentry)
        !          2232: {
        !          2233:        ipc_entry_bits_t bits = oentry->ie_bits;
        !          2234:        ipc_port_request_index_t request = oentry->ie_request;
        !          2235:        ipc_object_t object = oentry->ie_object;
        !          2236: 
        !          2237:        assert(space->is_active);
        !          2238:        assert(oname != nname);
        !          2239: 
        !          2240:        /*
        !          2241:         *      If IE_BITS_COMPAT, we can't allow the entry to be renamed
        !          2242:         *      if the port is dead.  (This would foil ipc_port_destroy.)
        !          2243:         *      Instead we should fail because oentry shouldn't exist.
        !          2244:         *      Note IE_BITS_COMPAT implies ie_request != 0.
        !          2245:         */
        !          2246: 
        !          2247:        if (request != 0) {
        !          2248:                ipc_port_t port;
        !          2249: 
        !          2250:                assert(bits & MACH_PORT_TYPE_PORT_RIGHTS);
        !          2251:                port = (ipc_port_t) object;
        !          2252:                assert(port != IP_NULL);
        !          2253: 
        !          2254:                if (ipc_right_check(space, port, oname, oentry)) {
        !          2255: #if    MACH_IPC_COMPAT
        !          2256:                        if (bits & IE_BITS_COMPAT) {
        !          2257:                                ipc_entry_dealloc(space, nname, nentry);
        !          2258:                                is_write_unlock(space);
        !          2259:                                return KERN_INVALID_NAME;
        !          2260:                        }
        !          2261: #endif /* MACH_IPC_COMPAT */
        !          2262: 
        !          2263:                        bits = oentry->ie_bits;
        !          2264:                        assert(IE_BITS_TYPE(bits) == MACH_PORT_TYPE_DEAD_NAME);
        !          2265:                        assert(oentry->ie_request == 0);
        !          2266:                        request = 0;
        !          2267:                        assert(oentry->ie_object == IO_NULL);
        !          2268:                        object = IO_NULL;
        !          2269:                } else {
        !          2270:                        /* port is locked and active */
        !          2271: 
        !          2272:                        ipc_port_dnrename(port, request, oname, nname);
        !          2273:                        ip_unlock(port);
        !          2274:                        oentry->ie_request = 0;
        !          2275:                }
        !          2276:        }
        !          2277: 
        !          2278:        if (bits & IE_BITS_MAREQUEST) {
        !          2279:                assert(bits & MACH_PORT_TYPE_SEND_RECEIVE);
        !          2280: 
        !          2281:                ipc_marequest_rename(space, oname, nname);
        !          2282:        }
        !          2283: 
        !          2284:        /* initialize nentry before letting ipc_hash_insert see it */
        !          2285: 
        !          2286:        assert((nentry->ie_bits & IE_BITS_RIGHT_MASK) == 0);
        !          2287:        nentry->ie_bits |= bits & IE_BITS_RIGHT_MASK;
        !          2288:        nentry->ie_request = request;
        !          2289:        nentry->ie_object = object;
        !          2290: 
        !          2291:        switch (IE_BITS_TYPE(bits)) {
        !          2292:            case MACH_PORT_TYPE_SEND: {
        !          2293:                ipc_port_t port;
        !          2294: 
        !          2295:                port = (ipc_port_t) object;
        !          2296:                assert(port != IP_NULL);
        !          2297: 
        !          2298:                ipc_hash_delete(space, (ipc_object_t) port, oname, oentry);
        !          2299:                ipc_hash_insert(space, (ipc_object_t) port, nname, nentry);
        !          2300:                break;
        !          2301:            }
        !          2302: 
        !          2303:            case MACH_PORT_TYPE_RECEIVE:
        !          2304:            case MACH_PORT_TYPE_SEND_RECEIVE: {
        !          2305:                ipc_port_t port;
        !          2306: 
        !          2307:                port = (ipc_port_t) object;
        !          2308:                assert(port != IP_NULL);
        !          2309: 
        !          2310:                ip_lock(port);
        !          2311:                assert(ip_active(port));
        !          2312:                assert(port->ip_receiver_name == oname);
        !          2313:                assert(port->ip_receiver == space);
        !          2314: 
        !          2315:                port->ip_receiver_name = nname;
        !          2316:                ip_unlock(port);
        !          2317:                break;
        !          2318:            }
        !          2319: 
        !          2320:            case MACH_PORT_TYPE_PORT_SET: {
        !          2321:                ipc_pset_t pset;
        !          2322: 
        !          2323:                pset = (ipc_pset_t) object;
        !          2324:                assert(pset != IPS_NULL);
        !          2325: 
        !          2326:                ips_lock(pset);
        !          2327:                assert(ips_active(pset));
        !          2328:                assert(pset->ips_local_name == oname);
        !          2329: 
        !          2330:                pset->ips_local_name = nname;
        !          2331:                ips_unlock(pset);
        !          2332:                break;
        !          2333:            }
        !          2334: 
        !          2335:            case MACH_PORT_TYPE_SEND_ONCE:
        !          2336:            case MACH_PORT_TYPE_DEAD_NAME:
        !          2337:                break;
        !          2338: 
        !          2339:            default:
        !          2340: #if MACH_ASSERT
        !          2341:                assert(!"ipc_right_rename: strange rights");
        !          2342: #else
        !          2343:                panic("ipc_right_rename: strange rights");
        !          2344: #endif
        !          2345:        }
        !          2346: 
        !          2347:        assert(oentry->ie_request == 0);
        !          2348:        oentry->ie_object = IO_NULL;
        !          2349:        ipc_entry_dealloc(space, oname, oentry);
        !          2350:        is_write_unlock(space);
        !          2351: 
        !          2352:        return KERN_SUCCESS;
        !          2353: }
        !          2354: 
        !          2355: #if    MACH_IPC_COMPAT
        !          2356: 
        !          2357: /*
        !          2358:  *     Routine:        ipc_right_copyin_compat
        !          2359:  *     Purpose:
        !          2360:  *             Copyin a capability from a space.
        !          2361:  *             If successful, the caller gets a ref
        !          2362:  *             for the resulting object, which is always valid.
        !          2363:  *     Conditions:
        !          2364:  *             The space is write-locked, and is unlocked upon return.
        !          2365:  *             The space must be active.
        !          2366:  *     Returns:
        !          2367:  *             KERN_SUCCESS            Acquired a valid object.
        !          2368:  *             KERN_INVALID_RIGHT      Name doesn't denote correct right.
        !          2369:  *             KERN_INVALID_NAME       [MACH_IPC_COMPAT]
        !          2370:  *                     Caller should pretend lookup of entry failed.
        !          2371:  */
        !          2372: 
        !          2373: kern_return_t
        !          2374: ipc_right_copyin_compat(space, name, entry, msgt_name, dealloc, objectp)
        !          2375:        ipc_space_t space;
        !          2376:        mach_port_t name;
        !          2377:        ipc_entry_t entry;
        !          2378:        mach_msg_type_name_t msgt_name;
        !          2379:        boolean_t dealloc;
        !          2380:        ipc_object_t *objectp;
        !          2381: {
        !          2382:        ipc_entry_bits_t bits = entry->ie_bits;
        !          2383: 
        !          2384:        assert(space->is_active);
        !          2385: 
        !          2386:        switch (msgt_name) {
        !          2387:            case MSG_TYPE_PORT:
        !          2388:                if (dealloc) {
        !          2389:                        ipc_port_t port;
        !          2390:                        ipc_port_t dnrequest;
        !          2391: 
        !          2392:                        /*
        !          2393:                         *      Pulls a send right out of the space,
        !          2394:                         *      leaving the space with no rights.
        !          2395:                         *      Not allowed to destroy the port,
        !          2396:                         *      so the space can't have receive rights.
        !          2397:                         *      Doesn't operate on dead names.
        !          2398:                         */
        !          2399: 
        !          2400:                        if (IE_BITS_TYPE(bits) != MACH_PORT_TYPE_SEND)
        !          2401:                                goto invalid_right;
        !          2402: 
        !          2403:                        port = (ipc_port_t) entry->ie_object;
        !          2404:                        assert(port != IP_NULL);
        !          2405: 
        !          2406:                        if (ipc_right_check(space, port, name, entry)) {
        !          2407:                                if (bits & IE_BITS_COMPAT)
        !          2408:                                        goto invalid_name;
        !          2409: 
        !          2410:                                goto invalid_right;
        !          2411:                        }
        !          2412:                        /* port is locked and active */
        !          2413: 
        !          2414:                        dnrequest = ipc_right_dncancel_macro(space, port,
        !          2415:                                                             name, entry);
        !          2416: 
        !          2417:                        assert(port->ip_srights > 0);
        !          2418:                        ip_unlock(port);
        !          2419: 
        !          2420:                        if (bits & IE_BITS_MAREQUEST)
        !          2421:                                ipc_marequest_cancel(space, name);
        !          2422: 
        !          2423:                        entry->ie_object = IO_NULL;
        !          2424:                        ipc_entry_dealloc(space, name, entry);
        !          2425:                        is_write_unlock(space);
        !          2426: 
        !          2427:                        if (dnrequest != IP_NULL)
        !          2428:                                ipc_notify_port_deleted(dnrequest, name);
        !          2429: 
        !          2430:                        *objectp = (ipc_object_t) port;
        !          2431:                        break;
        !          2432:                } else {
        !          2433:                        ipc_port_t port;
        !          2434: 
        !          2435:                        /*
        !          2436:                         *      Pulls a send right out of the space,
        !          2437:                         *      making a send right if necessary.
        !          2438:                         *      Doesn't operate on dead names.
        !          2439:                         */
        !          2440: 
        !          2441:                        if ((bits & MACH_PORT_TYPE_SEND_RECEIVE) == 0)
        !          2442:                                goto invalid_right;
        !          2443: 
        !          2444:                        port = (ipc_port_t) entry->ie_object;
        !          2445:                        assert(port != IP_NULL);
        !          2446: 
        !          2447:                        if (ipc_right_check(space, port, name, entry)) {
        !          2448:                                if (bits & IE_BITS_COMPAT)
        !          2449:                                        goto invalid_name;
        !          2450: 
        !          2451:                                goto invalid_right;
        !          2452:                        }
        !          2453:                        /* port is locked and active */
        !          2454: 
        !          2455:                        is_write_unlock(space);
        !          2456: 
        !          2457:                        if ((bits & MACH_PORT_TYPE_SEND) == 0) {
        !          2458:                                assert(IE_BITS_TYPE(bits) ==
        !          2459:                                                MACH_PORT_TYPE_RECEIVE);
        !          2460:                                assert(IE_BITS_UREFS(bits) == 0);
        !          2461: 
        !          2462:                                port->ip_mscount++;
        !          2463:                        }
        !          2464: 
        !          2465:                        port->ip_srights++;
        !          2466:                        ip_reference(port);
        !          2467:                        ip_unlock(port);
        !          2468: 
        !          2469:                        *objectp = (ipc_object_t) port;
        !          2470:                        break;
        !          2471:                }
        !          2472: 
        !          2473:            case MSG_TYPE_PORT_ALL:
        !          2474:                if (dealloc) {
        !          2475:                        ipc_port_t port;
        !          2476:                        ipc_port_t dnrequest = IP_NULL;
        !          2477:                        ipc_port_t nsrequest = IP_NULL;
        !          2478:                        mach_port_mscount_t mscount = 0; /* '=0' to shut up lint */
        !          2479: 
        !          2480:                        /*
        !          2481:                         *      Like MACH_MSG_TYPE_MOVE_RECEIVE, except that
        !          2482:                         *      the space is always left without rights,
        !          2483:                         *      so we kill send rights if necessary.
        !          2484:                         */
        !          2485: 
        !          2486:                        if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
        !          2487:                                goto invalid_right;
        !          2488: 
        !          2489:                        port = (ipc_port_t) entry->ie_object;
        !          2490:                        assert(port != IP_NULL);
        !          2491: 
        !          2492:                        ip_lock(port);
        !          2493:                        assert(ip_active(port));
        !          2494:                        assert(port->ip_receiver_name == name);
        !          2495:                        assert(port->ip_receiver == space);
        !          2496: 
        !          2497:                        dnrequest = ipc_right_dncancel_macro(space, port,
        !          2498:                                                             name, entry);
        !          2499: 
        !          2500:                        if (bits & IE_BITS_MAREQUEST)
        !          2501:                                ipc_marequest_cancel(space, name);
        !          2502: 
        !          2503:                        entry->ie_object = IO_NULL;
        !          2504:                        ipc_entry_dealloc(space, name, entry);
        !          2505:                        is_write_unlock(space);
        !          2506: 
        !          2507:                        if (bits & MACH_PORT_TYPE_SEND) {
        !          2508:                                assert(IE_BITS_TYPE(bits) ==
        !          2509:                                                MACH_PORT_TYPE_SEND_RECEIVE);
        !          2510:                                assert(IE_BITS_UREFS(bits) > 0);
        !          2511:                                assert(port->ip_srights > 0);
        !          2512: 
        !          2513:                                if (--port->ip_srights == 0) {
        !          2514:                                        nsrequest = port->ip_nsrequest;
        !          2515:                                        if (nsrequest != IP_NULL) {
        !          2516:                                                port->ip_nsrequest = IP_NULL;
        !          2517:                                                mscount = port->ip_mscount;
        !          2518:                                        }
        !          2519:                                }
        !          2520:                        }
        !          2521: 
        !          2522:                        ipc_port_clear_receiver(port);
        !          2523: 
        !          2524:                        port->ip_receiver_name = MACH_PORT_NULL;
        !          2525:                        port->ip_destination = IP_NULL;
        !          2526:                        ip_unlock(port);
        !          2527: 
        !          2528:                        if (nsrequest != IP_NULL)
        !          2529:                                ipc_notify_no_senders(nsrequest, mscount);
        !          2530: 
        !          2531:                        if (dnrequest != IP_NULL)
        !          2532:                                ipc_notify_port_deleted(dnrequest, name);
        !          2533: 
        !          2534:                        *objectp = (ipc_object_t) port;
        !          2535:                        break;
        !          2536:                } else {
        !          2537:                        ipc_port_t port;
        !          2538: 
        !          2539:                        /*
        !          2540:                         *      Like MACH_MSG_TYPE_MOVE_RECEIVE, except that
        !          2541:                         *      the space is always left with send rights,
        !          2542:                         *      so we make a send right if necessary.
        !          2543:                         */
        !          2544: 
        !          2545:                        if ((bits & MACH_PORT_TYPE_RECEIVE) == 0)
        !          2546:                                goto invalid_right;
        !          2547: 
        !          2548:                        port = (ipc_port_t) entry->ie_object;
        !          2549:                        assert(port != IP_NULL);
        !          2550: 
        !          2551:                        ip_lock(port);
        !          2552:                        assert(ip_active(port));
        !          2553:                        assert(port->ip_receiver_name == name);
        !          2554:                        assert(port->ip_receiver == space);
        !          2555: 
        !          2556:                        if ((bits & MACH_PORT_TYPE_SEND) == 0) {
        !          2557:                                assert(IE_BITS_TYPE(bits) ==
        !          2558:                                                MACH_PORT_TYPE_RECEIVE);
        !          2559:                                assert(IE_BITS_UREFS(bits) == 0);
        !          2560: 
        !          2561:                                /* ip_mscount will be cleared below */
        !          2562:                                port->ip_srights++;
        !          2563:                                bits |= MACH_PORT_TYPE_SEND | 1;
        !          2564:                        }
        !          2565: 
        !          2566:                        ipc_hash_insert(space, (ipc_object_t) port,
        !          2567:                                        name, entry);
        !          2568: 
        !          2569:                        entry->ie_bits = bits &~ MACH_PORT_TYPE_RECEIVE;
        !          2570:                        is_write_unlock(space);
        !          2571: 
        !          2572:                        ipc_port_clear_receiver(port); /* clears ip_mscount */
        !          2573: 
        !          2574:                        port->ip_receiver_name = MACH_PORT_NULL;
        !          2575:                        port->ip_destination = IP_NULL;
        !          2576:                        ip_reference(port);
        !          2577:                        ip_unlock(port);
        !          2578: 
        !          2579:                        *objectp = (ipc_object_t) port;
        !          2580:                        break;
        !          2581:                }
        !          2582: 
        !          2583:            default:
        !          2584: #if MACH_ASSERT
        !          2585:                assert(!"ipc_right_copyin_compat: strange rights");
        !          2586: #else
        !          2587:                panic("ipc_right_copyin_compat: strange rights");
        !          2588: #endif
        !          2589:        }
        !          2590: 
        !          2591:        return KERN_SUCCESS;
        !          2592: 
        !          2593:     invalid_right:
        !          2594:        is_write_unlock(space);
        !          2595:        return KERN_INVALID_RIGHT;
        !          2596: 
        !          2597:     invalid_name:
        !          2598:        is_write_unlock(space);
        !          2599:        return KERN_INVALID_NAME;
        !          2600: }
        !          2601: 
        !          2602: /*
        !          2603:  *     Routine:        ipc_right_copyin_header
        !          2604:  *     Purpose:
        !          2605:  *             Copyin a capability from a space.
        !          2606:  *             If successful, the caller gets a ref
        !          2607:  *             for the resulting object, which is always valid.
        !          2608:  *             The type of the acquired capability is returned.
        !          2609:  *     Conditions:
        !          2610:  *             The space is write-locked, and is unlocked upon return.
        !          2611:  *             The space must be active.
        !          2612:  *     Returns:
        !          2613:  *             KERN_SUCCESS            Acquired a valid object.
        !          2614:  *             KERN_INVALID_RIGHT      Name doesn't denote correct right.
        !          2615:  *             KERN_INVALID_NAME       [MACH_IPC_COMPAT]
        !          2616:  *                     Caller should pretend lookup of entry failed.
        !          2617:  */
        !          2618: 
        !          2619: kern_return_t
        !          2620: ipc_right_copyin_header(space, name, entry, objectp, msgt_namep)
        !          2621:        ipc_space_t space;
        !          2622:        mach_port_t name;
        !          2623:        ipc_entry_t entry;
        !          2624:        ipc_object_t *objectp;
        !          2625:        mach_msg_type_name_t *msgt_namep;
        !          2626: {
        !          2627:        ipc_entry_bits_t bits = entry->ie_bits;
        !          2628:        mach_port_type_t type = IE_BITS_TYPE(bits);
        !          2629: 
        !          2630:        assert(space->is_active);
        !          2631: 
        !          2632:        switch (type) {
        !          2633:            case MACH_PORT_TYPE_PORT_SET:
        !          2634:            case MACH_PORT_TYPE_DEAD_NAME:
        !          2635:                goto invalid_right;
        !          2636: 
        !          2637:            case MACH_PORT_TYPE_RECEIVE: {
        !          2638:                ipc_port_t port;
        !          2639: 
        !          2640:                /*
        !          2641:                 *      Like MACH_MSG_TYPE_MAKE_SEND.
        !          2642:                 */
        !          2643: 
        !          2644:                port = (ipc_port_t) entry->ie_object;
        !          2645:                assert(port != IP_NULL);
        !          2646: 
        !          2647:                ip_lock(port);
        !          2648:                assert(ip_active(port));
        !          2649:                assert(port->ip_receiver_name == name);
        !          2650:                assert(port->ip_receiver == space);
        !          2651:                is_write_unlock(space);
        !          2652: 
        !          2653:                port->ip_mscount++;
        !          2654:                port->ip_srights++;
        !          2655:                ip_reference(port);
        !          2656:                ip_unlock(port);
        !          2657: 
        !          2658:                *objectp = (ipc_object_t) port;
        !          2659:                *msgt_namep = MACH_MSG_TYPE_PORT_SEND;
        !          2660:                break;
        !          2661:            }
        !          2662: 
        !          2663:            case MACH_PORT_TYPE_SEND:
        !          2664:            case MACH_PORT_TYPE_SEND_RECEIVE: {
        !          2665:                ipc_port_t port;
        !          2666: 
        !          2667:                /*
        !          2668:                 *      Like MACH_MSG_TYPE_COPY_SEND,
        !          2669:                 *      except that the port must be alive.
        !          2670:                 */
        !          2671: 
        !          2672:                assert(IE_BITS_UREFS(bits) > 0);
        !          2673: 
        !          2674:                port = (ipc_port_t) entry->ie_object;
        !          2675:                assert(port != IP_NULL);
        !          2676: 
        !          2677:                if (ipc_right_check(space, port, name, entry)) {
        !          2678:                        if (bits & IE_BITS_COMPAT)
        !          2679:                                goto invalid_name;
        !          2680: 
        !          2681:                        goto invalid_right;
        !          2682:                }
        !          2683:                /* port is locked and active */
        !          2684: 
        !          2685:                assert(port->ip_srights > 0);
        !          2686:                is_write_unlock(space);
        !          2687: 
        !          2688:                port->ip_srights++;
        !          2689:                ip_reference(port);
        !          2690:                ip_unlock(port);
        !          2691: 
        !          2692:                *objectp = (ipc_object_t) port;
        !          2693:                *msgt_namep = MACH_MSG_TYPE_PORT_SEND;
        !          2694:                break;
        !          2695:            }
        !          2696: 
        !          2697:            case MACH_PORT_TYPE_SEND_ONCE: {
        !          2698:                ipc_port_t port;
        !          2699:                ipc_port_t dnrequest, notify;
        !          2700: 
        !          2701:                /*
        !          2702:                 *      Like MACH_MSG_TYPE_MOVE_SEND_ONCE,
        !          2703:                 *      except that the port must be alive
        !          2704:                 *      and a port-deleted notification is generated.
        !          2705:                 */
        !          2706: 
        !          2707:                assert(IE_BITS_UREFS(bits) == 1);
        !          2708:                assert((bits & IE_BITS_MAREQUEST) == 0);
        !          2709: 
        !          2710:                port = (ipc_port_t) entry->ie_object;
        !          2711:                assert(port != IP_NULL);
        !          2712: 
        !          2713:                if (ipc_right_check(space, port, name, entry)) {
        !          2714:                        if (bits & IE_BITS_COMPAT)
        !          2715:                                goto invalid_name;
        !          2716: 
        !          2717:                        goto invalid_right;
        !          2718:                }
        !          2719:                /* port is locked and active */
        !          2720: 
        !          2721:                assert(port->ip_sorights > 0);
        !          2722: 
        !          2723:                dnrequest = ipc_right_dncancel_macro(space, port, name, entry);
        !          2724:                ip_unlock(port);
        !          2725: 
        !          2726:                entry->ie_object = IO_NULL;
        !          2727:                ipc_entry_dealloc(space, name, entry);
        !          2728: 
        !          2729:                notify = ipc_space_make_notify(space);
        !          2730:                is_write_unlock(space);
        !          2731: 
        !          2732:                if (dnrequest != IP_NULL)
        !          2733:                        ipc_notify_port_deleted(dnrequest, name);
        !          2734: 
        !          2735:                if (IP_VALID(notify))
        !          2736:                        ipc_notify_port_deleted_compat(notify, name);
        !          2737: 
        !          2738:                *objectp = (ipc_object_t) port;
        !          2739:                *msgt_namep = MACH_MSG_TYPE_PORT_SEND_ONCE;
        !          2740:                break;
        !          2741:            }
        !          2742: 
        !          2743:            default:
        !          2744: #if MACH_ASSERT
        !          2745:                assert(!"ipc_right_copyin_header: strange rights");
        !          2746: #else
        !          2747:                panic("ipc_right_copyin_header: strange rights");
        !          2748: #endif
        !          2749:        }
        !          2750: 
        !          2751:        return KERN_SUCCESS;
        !          2752: 
        !          2753:     invalid_right:
        !          2754:        is_write_unlock(space);
        !          2755:        return KERN_INVALID_RIGHT;
        !          2756: 
        !          2757:     invalid_name:
        !          2758:        is_write_unlock(space);
        !          2759:        return KERN_INVALID_NAME;
        !          2760: }
        !          2761: 
        !          2762: #endif /* MACH_IPC_COMPAT */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.