2 * Copyright (c) 2008 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/types.h>
30 #include <kern/locks.h>
31 #include <kern/kalloc.h>
32 #include <sys/errno.h>
33 #include <sys/sysctl.h>
34 #include <sys/malloc.h>
35 #include <sys/socket.h>
36 #include <libkern/OSAtomic.h>
37 #include <libkern/libkern.h>
39 #include <net/if_mib.h>
42 #include "net/net_str_id.h"
44 #define NET_ID_STR_ENTRY_SIZE(__str) \
45 ((size_t)&(((struct net_str_id_entry*)0)->nsi_string[0]) + \
48 #define FIRST_NET_STR_ID 1000
49 static SLIST_HEAD(,net_str_id_entry
) net_str_id_list
= {NULL
};
50 static lck_mtx_t
*net_str_id_lock
= NULL
;
52 static u_int32_t nsi_kind_next
[NSI_MAX_KIND
] = { FIRST_NET_STR_ID
, FIRST_NET_STR_ID
, FIRST_NET_STR_ID
};
53 static u_int32_t nsi_next_id
= FIRST_NET_STR_ID
;
57 extern int sysctl_if_family_ids SYSCTL_HANDLER_ARGS
;
59 SYSCTL_DECL(_net_link_generic_system
);
61 SYSCTL_PROC(_net_link_generic_system
, OID_AUTO
, if_family_ids
, CTLTYPE_STRUCT
| CTLFLAG_RD
| CTLFLAG_LOCKED
,
62 0, 0, sysctl_if_family_ids
, "S, if_family_id", "Interface Family ID table");
67 __private_extern__
void
70 lck_grp_attr_t
*grp_attrib
= NULL
;
71 lck_attr_t
*lck_attrb
= NULL
;
72 lck_grp_t
*lck_group
= NULL
;
74 grp_attrib
= lck_grp_attr_alloc_init();
75 lck_group
= lck_grp_alloc_init("mbuf_tag_allocate_id", grp_attrib
);
76 lck_grp_attr_free(grp_attrib
);
77 lck_attrb
= lck_attr_alloc_init();
79 net_str_id_lock
= lck_mtx_alloc_init(lck_group
, lck_attrb
);
81 lck_grp_free(lck_group
);
82 lck_attr_free(lck_attrb
);
85 __private_extern__
void
86 net_str_id_first_last(u_int32_t
*first
, u_int32_t
*last
, u_int32_t kind
)
88 *first
= FIRST_NET_STR_ID
;
94 *last
= nsi_kind_next
[kind
] - 1;
97 *last
= FIRST_NET_STR_ID
- 1;
102 __private_extern__ errno_t
103 net_str_id_find_internal(const char *string
, u_int32_t
*out_id
,
104 u_int32_t kind
, int create
)
106 struct net_str_id_entry
*entry
= NULL
;
109 if (string
== NULL
|| out_id
== NULL
|| kind
>= NSI_MAX_KIND
)
114 /* Look for an existing entry */
115 lck_mtx_lock(net_str_id_lock
);
116 SLIST_FOREACH(entry
, &net_str_id_list
, nsi_next
) {
117 if (strcmp(string
, entry
->nsi_string
) == 0) {
124 lck_mtx_unlock(net_str_id_lock
);
128 entry
= kalloc(NET_ID_STR_ENTRY_SIZE(string
));
130 lck_mtx_unlock(net_str_id_lock
);
134 strlcpy(entry
->nsi_string
, string
, strlen(string
) + 1);
135 entry
->nsi_flags
= (1 << kind
);
136 entry
->nsi_id
= nsi_next_id
++;
137 nsi_kind_next
[kind
] = nsi_next_id
;
138 SLIST_INSERT_HEAD(&net_str_id_list
, entry
, nsi_next
);
139 } else if ((entry
->nsi_flags
& (1 << kind
)) == 0) {
141 lck_mtx_unlock(net_str_id_lock
);
144 entry
->nsi_flags
|= (1 << kind
);
145 if (entry
->nsi_id
>= nsi_kind_next
[kind
])
146 nsi_kind_next
[kind
] = entry
->nsi_id
+ 1;
148 lck_mtx_unlock(net_str_id_lock
);
150 *out_id
= entry
->nsi_id
;
158 #define ROUNDUP32(a) \
159 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
162 sysctl_if_family_ids SYSCTL_HANDLER_ARGS
/* XXX bad syntax! */
168 struct net_str_id_entry
*entry
= NULL
;
169 struct if_family_id
*iffmid
= NULL
;
172 lck_mtx_lock(net_str_id_lock
);
173 SLIST_FOREACH(entry
, &net_str_id_list
, nsi_next
) {
177 if ((entry
->nsi_flags
& (1 << NSI_IF_FAM_ID
)) == 0)
180 str_size
= strlen(entry
->nsi_string
) + 1;
181 iffmid_size
= ROUNDUP32(offsetof(struct net_str_id_entry
, nsi_string
) + str_size
);
183 if (iffmid_size
> max_size
) {
185 _FREE(iffmid
, M_TEMP
);
186 iffmid
= _MALLOC(iffmid_size
, M_TEMP
, M_WAITOK
);
187 if (iffmid
== NULL
) {
188 lck_mtx_unlock(net_str_id_lock
);
192 max_size
= iffmid_size
;
195 bzero(iffmid
, iffmid_size
);
196 iffmid
->iffmid_len
= iffmid_size
;
197 iffmid
->iffmid_id
= entry
->nsi_id
;
198 strlcpy(iffmid
->iffmid_str
, entry
->nsi_string
, str_size
);
199 error
= SYSCTL_OUT(req
, iffmid
, iffmid_size
);
201 lck_mtx_unlock(net_str_id_lock
);
206 lck_mtx_unlock(net_str_id_lock
);
210 _FREE(iffmid
, M_TEMP
);