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 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
;
55 extern int sysctl_if_family_ids SYSCTL_HANDLER_ARGS
;
57 SYSCTL_DECL(_net_link_generic_system
);
59 SYSCTL_PROC(_net_link_generic_system
, OID_AUTO
, if_family_ids
, CTLTYPE_STRUCT
| CTLFLAG_RD
| CTLFLAG_LOCKED
,
60 0, 0, sysctl_if_family_ids
, "S, if_family_id", "Interface Family ID table");
62 __private_extern__
void
65 lck_grp_attr_t
*grp_attrib
= NULL
;
66 lck_attr_t
*lck_attrb
= NULL
;
67 lck_grp_t
*lck_group
= NULL
;
69 grp_attrib
= lck_grp_attr_alloc_init();
70 lck_group
= lck_grp_alloc_init("mbuf_tag_allocate_id", grp_attrib
);
71 lck_grp_attr_free(grp_attrib
);
72 lck_attrb
= lck_attr_alloc_init();
74 net_str_id_lock
= lck_mtx_alloc_init(lck_group
, lck_attrb
);
76 lck_grp_free(lck_group
);
77 lck_attr_free(lck_attrb
);
80 __private_extern__
void
81 net_str_id_first_last(u_int32_t
*first
, u_int32_t
*last
, u_int32_t kind
)
83 *first
= FIRST_NET_STR_ID
;
89 *last
= nsi_kind_next
[kind
] - 1;
92 *last
= FIRST_NET_STR_ID
- 1;
97 __private_extern__ errno_t
98 net_str_id_find_internal(const char *string
, u_int32_t
*out_id
,
99 u_int32_t kind
, int create
)
101 struct net_str_id_entry
*entry
= NULL
;
104 if (string
== NULL
|| out_id
== NULL
|| kind
>= NSI_MAX_KIND
)
109 /* Look for an existing entry */
110 lck_mtx_lock(net_str_id_lock
);
111 SLIST_FOREACH(entry
, &net_str_id_list
, nsi_next
) {
112 if (strcmp(string
, entry
->nsi_string
) == 0) {
119 lck_mtx_unlock(net_str_id_lock
);
123 entry
= kalloc(NET_ID_STR_ENTRY_SIZE(string
));
125 lck_mtx_unlock(net_str_id_lock
);
129 strlcpy(entry
->nsi_string
, string
, strlen(string
) + 1);
130 entry
->nsi_flags
= (1 << kind
);
131 entry
->nsi_id
= nsi_next_id
++;
132 nsi_kind_next
[kind
] = nsi_next_id
;
133 SLIST_INSERT_HEAD(&net_str_id_list
, entry
, nsi_next
);
134 } else if ((entry
->nsi_flags
& (1 << kind
)) == 0) {
136 lck_mtx_unlock(net_str_id_lock
);
139 entry
->nsi_flags
|= (1 << kind
);
140 if (entry
->nsi_id
>= nsi_kind_next
[kind
])
141 nsi_kind_next
[kind
] = entry
->nsi_id
+ 1;
143 lck_mtx_unlock(net_str_id_lock
);
145 *out_id
= entry
->nsi_id
;
151 #define ROUNDUP32(a) \
152 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
155 sysctl_if_family_ids SYSCTL_HANDLER_ARGS
/* XXX bad syntax! */
161 struct net_str_id_entry
*entry
= NULL
;
162 struct if_family_id
*iffmid
= NULL
;
165 lck_mtx_lock(net_str_id_lock
);
166 SLIST_FOREACH(entry
, &net_str_id_list
, nsi_next
) {
170 if ((entry
->nsi_flags
& (1 << NSI_IF_FAM_ID
)) == 0)
173 str_size
= strlen(entry
->nsi_string
) + 1;
174 iffmid_size
= ROUNDUP32(offsetof(struct net_str_id_entry
, nsi_string
) + str_size
);
176 if (iffmid_size
> max_size
) {
178 _FREE(iffmid
, M_TEMP
);
179 iffmid
= _MALLOC(iffmid_size
, M_TEMP
, M_WAITOK
);
180 if (iffmid
== NULL
) {
181 lck_mtx_unlock(net_str_id_lock
);
185 max_size
= iffmid_size
;
188 bzero(iffmid
, iffmid_size
);
189 iffmid
->iffmid_len
= iffmid_size
;
190 iffmid
->iffmid_id
= entry
->nsi_id
;
191 strlcpy(iffmid
->iffmid_str
, entry
->nsi_string
, str_size
);
192 error
= SYSCTL_OUT(req
, iffmid
, iffmid_size
);
194 lck_mtx_unlock(net_str_id_lock
);
199 lck_mtx_unlock(net_str_id_lock
);
203 _FREE(iffmid
, M_TEMP
);