2 * Copyright (c) 2008,2011,2019 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/zalloc.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_MAX_LEN 2048
45 #define NET_ID_STR_ENTRY_SIZE(__str) \
46 (__builtin_offsetof(struct net_str_id_entry, nsi_string[0]) + \
49 #define FIRST_NET_STR_ID 1000
50 static SLIST_HEAD(, net_str_id_entry
) net_str_id_list
= {NULL
};
51 decl_lck_mtx_data(static, net_str_id_lock_data
);
52 static lck_mtx_t
*net_str_id_lock
= &net_str_id_lock_data
;
54 static u_int32_t nsi_kind_next
[NSI_MAX_KIND
] = { FIRST_NET_STR_ID
, FIRST_NET_STR_ID
, FIRST_NET_STR_ID
};
55 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");
64 __private_extern__
void
67 lck_grp_attr_t
*grp_attrib
= NULL
;
68 lck_attr_t
*lck_attrb
= NULL
;
69 lck_grp_t
*lck_group
= NULL
;
71 grp_attrib
= lck_grp_attr_alloc_init();
72 lck_group
= lck_grp_alloc_init("mbuf_tag_allocate_id", grp_attrib
);
73 lck_grp_attr_free(grp_attrib
);
74 lck_attrb
= lck_attr_alloc_init();
76 lck_mtx_init(net_str_id_lock
, lck_group
, lck_attrb
);
78 lck_grp_free(lck_group
);
79 lck_attr_free(lck_attrb
);
82 __private_extern__
void
83 net_str_id_first_last(u_int32_t
*first
, u_int32_t
*last
, u_int32_t kind
)
85 *first
= FIRST_NET_STR_ID
;
91 *last
= nsi_kind_next
[kind
] - 1;
94 *last
= FIRST_NET_STR_ID
- 1;
99 __private_extern__ errno_t
100 net_str_id_find_internal(const char *string
, u_int32_t
*out_id
,
101 u_int32_t kind
, int create
)
103 struct net_str_id_entry
*entry
= NULL
;
106 if (string
== NULL
|| out_id
== NULL
|| kind
>= NSI_MAX_KIND
) {
109 if (strlen(string
) > NET_ID_STR_MAX_LEN
) {
115 /* Look for an existing entry */
116 lck_mtx_lock(net_str_id_lock
);
117 SLIST_FOREACH(entry
, &net_str_id_list
, nsi_next
) {
118 if (strcmp(string
, entry
->nsi_string
) == 0) {
125 lck_mtx_unlock(net_str_id_lock
);
129 entry
= zalloc_permanent(NET_ID_STR_ENTRY_SIZE(string
),
132 lck_mtx_unlock(net_str_id_lock
);
136 strlcpy(entry
->nsi_string
, string
, strlen(string
) + 1);
137 entry
->nsi_flags
= (1 << kind
);
138 entry
->nsi_id
= nsi_next_id
++;
139 nsi_kind_next
[kind
] = nsi_next_id
;
140 SLIST_INSERT_HEAD(&net_str_id_list
, entry
, nsi_next
);
141 } else if ((entry
->nsi_flags
& (1 << kind
)) == 0) {
143 lck_mtx_unlock(net_str_id_lock
);
146 entry
->nsi_flags
|= (1 << kind
);
147 if (entry
->nsi_id
>= nsi_kind_next
[kind
]) {
148 nsi_kind_next
[kind
] = entry
->nsi_id
+ 1;
151 lck_mtx_unlock(net_str_id_lock
);
153 *out_id
= entry
->nsi_id
;
159 #define ROUNDUP32(a) \
160 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
163 sysctl_if_family_ids SYSCTL_HANDLER_ARGS
/* XXX bad syntax! */
169 struct net_str_id_entry
*entry
= NULL
;
170 struct if_family_id
*iffmid
= NULL
;
173 lck_mtx_lock(net_str_id_lock
);
174 SLIST_FOREACH(entry
, &net_str_id_list
, nsi_next
) {
178 if ((entry
->nsi_flags
& (1 << NSI_IF_FAM_ID
)) == 0) {
182 str_size
= strlen(entry
->nsi_string
);
183 if (str_size
> NET_ID_STR_MAX_LEN
) {
184 str_size
= NET_ID_STR_MAX_LEN
;
186 str_size
+= 1; // make room for end-of-string
187 iffmid_size
= ROUNDUP32(offsetof(struct net_str_id_entry
, nsi_string
) + str_size
);
189 if (iffmid_size
> max_size
) {
191 _FREE(iffmid
, M_TEMP
);
193 iffmid
= _MALLOC(iffmid_size
, M_TEMP
, M_WAITOK
);
194 if (iffmid
== NULL
) {
195 lck_mtx_unlock(net_str_id_lock
);
199 max_size
= iffmid_size
;
202 bzero(iffmid
, iffmid_size
);
203 iffmid
->iffmid_len
= (uint32_t)iffmid_size
;
204 iffmid
->iffmid_id
= entry
->nsi_id
;
205 strlcpy(iffmid
->iffmid_str
, entry
->nsi_string
, str_size
);
206 error
= SYSCTL_OUT(req
, iffmid
, iffmid_size
);
208 lck_mtx_unlock(net_str_id_lock
);
212 lck_mtx_unlock(net_str_id_lock
);
216 _FREE(iffmid
, M_TEMP
);