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