xref: /illumos-gate/usr/src/uts/common/inet/inet_common.c (revision 4bc0a2ef2b7ba50a7a717e7ddbf31472ad28e358)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Minor number allocation for various protocol modules.
31  */
32 
33 #include <sys/types.h>
34 #include <sys/kmem.h>
35 #include <sys/mutex.h>
36 #include <sys/ddi.h>
37 #include <sys/types.h>
38 #include <sys/mkdev.h>
39 #include <sys/param.h>
40 #include <inet/common.h>
41 
42 typedef struct inet_arena {
43 	vmem_t *ineta_arena;	/* Minor number arena */
44 	minor_t ineta_maxminor;	/* max minor number in the arena */
45 } inet_arena_t;
46 
47 /* Maximum minor number to use */
48 static minor_t inet_maxminor = INET_MAXMINOR;
49 
50 void *
51 inet_minor_create(char *name, dev_t min_dev, int kmflags)
52 {
53 	inet_arena_t *arena = kmem_alloc(sizeof (inet_arena_t), kmflags);
54 
55 	if (arena != NULL) {
56 		arena->ineta_maxminor = MIN(MAXMIN32, inet_maxminor);
57 		arena->ineta_arena = vmem_create(name,
58 		    (void *)min_dev, arena->ineta_maxminor - min_dev + 1,
59 		    1, NULL, NULL, NULL, 1, kmflags | VMC_IDENTIFIER);
60 
61 		if (arena->ineta_arena == NULL) {
62 			kmem_free(arena, sizeof (inet_arena_t));
63 			arena = NULL;
64 		}
65 	}
66 
67 	return (arena);
68 }
69 
70 void
71 inet_minor_destroy(void *a)
72 {
73 	inet_arena_t *arena = (inet_arena_t *)a;
74 
75 	if (arena != NULL) {
76 		vmem_destroy(arena->ineta_arena);
77 		kmem_free(arena, sizeof (inet_arena_t));
78 	}
79 }
80 
81 dev_t
82 inet_minor_alloc(void *a)
83 {
84 	inet_arena_t *arena = (inet_arena_t *)a;
85 	dev_t dev;
86 
87 	while ((dev = (dev_t)vmem_alloc(arena->ineta_arena, 1,
88 		    VM_NOSLEEP)) == 0) {
89 		if (arena->ineta_maxminor >= inet_maxminor)
90 			return (0);
91 		if (vmem_add(arena->ineta_arena,
92 		    (void *)(uintptr_t)(arena->ineta_maxminor + 1),
93 		    inet_maxminor - arena->ineta_maxminor, VM_NOSLEEP) == NULL)
94 			return (0);
95 		arena->ineta_maxminor = inet_maxminor;
96 	}
97 	return (dev);
98 }
99 
100 void
101 inet_minor_free(void *a, dev_t dev)
102 {
103 	ASSERT((dev != OPENFAIL) && (dev != 0) && (dev <= inet_maxminor));
104 	vmem_free(((inet_arena_t *)a)->ineta_arena, (void *)dev, 1);
105 }
106 
107 /*
108  * This function is used to free a message that has gone through
109  * mi_copyin processing which modifies the M_IOCTL mblk's b_next
110  * and b_prev pointers. We use this function to set b_next/b_prev
111  * to NULL and free them.
112  */
113 void
114 inet_freemsg(mblk_t *mp)
115 {
116 	mblk_t	*bp = mp;
117 
118 	for (; bp != NULL; bp = bp->b_cont) {
119 		bp->b_prev = NULL;
120 		bp->b_next = NULL;
121 	}
122 	freemsg(mp);
123 }
124