2 * Copyright (c) 2008,2011 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 decl_lck_mtx_data(static, net_str_id_lock_data
);
51 static lck_mtx_t
*net_str_id_lock
= &net_str_id_lock_data
;
53 static u_int32_t nsi_kind_next
[NSI_MAX_KIND
] = { FIRST_NET_STR_ID
, FIRST_NET_STR_ID
, FIRST_NET_STR_ID
};
54 static u_int32_t nsi_next_id
= FIRST_NET_STR_ID
;
56 extern int sysctl_if_family_ids SYSCTL_HANDLER_ARGS
;
58 SYSCTL_DECL(_net_link_generic_system
);
60 SYSCTL_PROC(_net_link_generic_system
, OID_AUTO
, if_family_ids
, CTLTYPE_STRUCT
| CTLFLAG_RD
| CTLFLAG_LOCKED
,
61 0, 0, sysctl_if_family_ids
, "S, if_family_id", "Interface Family ID table");
63 __private_extern__
void
66 lck_grp_attr_t
*grp_attrib
= NULL
;
67 lck_attr_t
*lck_attrb
= NULL
;
68 lck_grp_t
*lck_group
= NULL
;
70 grp_attrib
= lck_grp_attr_alloc_init();
71 lck_group
= lck_grp_alloc_init("mbuf_tag_allocate_id", grp_attrib
);
72 lck_grp_attr_free(grp_attrib
);
73 lck_attrb
= lck_attr_alloc_init();
75 lck_mtx_init(net_str_id_lock
, lck_group
, lck_attrb
);
77 lck_grp_free(lck_group
);
78 lck_attr_free(lck_attrb
);
81 __private_extern__
void
82 net_str_id_first_last(u_int32_t
*first
, u_int32_t
*last
, u_int32_t kind
)
84 *first
= FIRST_NET_STR_ID
;
90 *last
= nsi_kind_next
[kind
] - 1;
93 *last
= FIRST_NET_STR_ID
- 1;
98 __private_extern__ errno_t
99 net_str_id_find_internal(const char *string
, u_int32_t
*out_id
,
100 u_int32_t kind
, int create
)
102 struct net_str_id_entry
*entry
= NULL
;
105 if (string
== NULL
|| out_id
== NULL
|| kind
>= NSI_MAX_KIND
)
110 /* Look for an existing entry */
111 lck_mtx_lock(net_str_id_lock
);
112 SLIST_FOREACH(entry
, &net_str_id_list
, nsi_next
) {
113 if (strcmp(string
, entry
->nsi_string
) == 0) {
120 lck_mtx_unlock(net_str_id_lock
);
124 entry
= kalloc(NET_ID_STR_ENTRY_SIZE(string
));
126 lck_mtx_unlock(net_str_id_lock
);
130 strlcpy(entry
->nsi_string
, string
, strlen(string
) + 1);
131 entry
->nsi_flags
= (1 << kind
);
132 entry
->nsi_id
= nsi_next_id
++;
133 nsi_kind_next
[kind
] = nsi_next_id
;
134 SLIST_INSERT_HEAD(&net_str_id_list
, entry
, nsi_next
);
135 } else if ((entry
->nsi_flags
& (1 << kind
)) == 0) {
137 lck_mtx_unlock(net_str_id_lock
);
140 entry
->nsi_flags
|= (1 << kind
);
141 if (entry
->nsi_id
>= nsi_kind_next
[kind
])
142 nsi_kind_next
[kind
] = entry
->nsi_id
+ 1;
144 lck_mtx_unlock(net_str_id_lock
);
146 *out_id
= entry
->nsi_id
;
152 #define ROUNDUP32(a) \
153 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
156 sysctl_if_family_ids SYSCTL_HANDLER_ARGS
/* XXX bad syntax! */
162 struct net_str_id_entry
*entry
= NULL
;
163 struct if_family_id
*iffmid
= NULL
;
166 lck_mtx_lock(net_str_id_lock
);
167 SLIST_FOREACH(entry
, &net_str_id_list
, nsi_next
) {
171 if ((entry
->nsi_flags
& (1 << NSI_IF_FAM_ID
)) == 0)
174 str_size
= strlen(entry
->nsi_string
) + 1;
175 iffmid_size
= ROUNDUP32(offsetof(struct net_str_id_entry
, nsi_string
) + str_size
);
177 if (iffmid_size
> max_size
) {
179 _FREE(iffmid
, M_TEMP
);
180 iffmid
= _MALLOC(iffmid_size
, M_TEMP
, M_WAITOK
);
181 if (iffmid
== NULL
) {
182 lck_mtx_unlock(net_str_id_lock
);
186 max_size
= iffmid_size
;
189 bzero(iffmid
, iffmid_size
);
190 iffmid
->iffmid_len
= iffmid_size
;
191 iffmid
->iffmid_id
= entry
->nsi_id
;
192 strlcpy(iffmid
->iffmid_str
, entry
->nsi_string
, str_size
);
193 error
= SYSCTL_OUT(req
, iffmid
, iffmid_size
);
195 lck_mtx_unlock(net_str_id_lock
);
200 lck_mtx_unlock(net_str_id_lock
);
204 _FREE(iffmid
, M_TEMP
);