#include <netinet6/in6_var.h>
#include <netinet6/scope6_var.h>
+extern lck_mtx_t *scope6_mutex;
+
struct scope6_id {
/*
* 16 is correspondent to 4bit multicast scope field.
*/
u_int32_t s6id_list[16];
};
-static size_t if_indexlim = 8;
+static size_t if_scope_indexlim = 8;
struct scope6_id *scope6_ids = NULL;
-void
+int
scope6_ifattach(
struct ifnet *ifp)
{
* We have some arrays that should be indexed by if_index.
* since if_index will grow dynamically, they should grow too.
*/
- if (scope6_ids == NULL || if_index >= if_indexlim) {
+ lck_mtx_lock(scope6_mutex);
+ if (scope6_ids == NULL || if_index >= if_scope_indexlim) {
size_t n;
caddr_t q;
+ int newlim = if_scope_indexlim;
- while (if_index >= if_indexlim)
- if_indexlim <<= 1;
+ while (if_index >= newlim)
+ newlim <<= 1;
/* grow scope index array */
- n = if_indexlim * sizeof(struct scope6_id);
+ n = newlim * sizeof(struct scope6_id);
/* XXX: need new malloc type? */
q = (caddr_t)_MALLOC(n, M_IFADDR, M_WAITOK);
+ if (q == NULL) {
+ lck_mtx_unlock(scope6_mutex);
+ return ENOBUFS;
+ }
+ if_scope_indexlim = newlim;
bzero(q, n);
if (scope6_ids) {
bcopy((caddr_t)scope6_ids, q, n/2);
/* don't initialize if called twice */
if (SID.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL]) {
- return;
+ lck_mtx_unlock(scope6_mutex);
+ return 0;
}
/*
SID.s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL] = 1;
#endif
#undef SID
+ lck_mtx_unlock(scope6_mutex);
+
+ return 0;
}
int
* interface addresses, routing table entries, PCB entries...
*/
+ lck_mtx_lock(scope6_mutex);
for (i = 0; i < 16; i++) {
if (idlist[i] &&
idlist[i] != scope6_ids[ifp->if_index].s6id_list[i]) {
* IDs, but we check the consistency for
* safety in later use.
*/
+ lck_mtx_unlock(scope6_mutex);
return(EINVAL);
}
scope6_ids[ifp->if_index].s6id_list[i] = idlist[i];
}
}
+ lck_mtx_unlock(scope6_mutex);
return(error);
}
if (scope6_ids == NULL) /* paranoid? */
return(EINVAL);
+ lck_mtx_lock(scope6_mutex);
bcopy(scope6_ids[ifp->if_index].s6id_list, idlist,
sizeof(scope6_ids[ifp->if_index].s6id_list));
+ lck_mtx_unlock(scope6_mutex);
return(0);
}
{
int scope = in6_addrscope(addr);
int index = ifp->if_index;
+ int retid = 0;
if (scope6_ids == NULL) /* paranoid? */
return(0); /* XXX */
- if (index >= if_indexlim)
+
+ lck_mtx_lock(scope6_mutex);
+ if (index >= if_scope_indexlim) {
+ lck_mtx_unlock(scope6_mutex);
return(0); /* XXX */
+ }
#define SID scope6_ids[index]
switch(scope) {
case IPV6_ADDR_SCOPE_NODELOCAL:
- return(-1); /* XXX: is this an appropriate value? */
-
+ retid = -1; /* XXX: is this an appropriate value? */
+ break;
case IPV6_ADDR_SCOPE_LINKLOCAL:
- return(SID.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL]);
-
+ retid=SID.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL];
+ break;
case IPV6_ADDR_SCOPE_SITELOCAL:
- return(SID.s6id_list[IPV6_ADDR_SCOPE_SITELOCAL]);
-
+ retid=SID.s6id_list[IPV6_ADDR_SCOPE_SITELOCAL];
+ break;
case IPV6_ADDR_SCOPE_ORGLOCAL:
- return(SID.s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL]);
-
+ retid=SID.s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL];
+ break;
default:
- return(0); /* XXX: treat as global. */
+ break; /* XXX: value 0, treat as global. */
}
#undef SID
+
+ lck_mtx_unlock(scope6_mutex);
+ return retid;
}
void
* We might eventually have to separate the notion of "link" from
* "interface" and provide a user interface to set the default.
*/
+ lck_mtx_lock(scope6_mutex);
if (ifp) {
scope6_ids[0].s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] =
ifp->if_index;
}
else
scope6_ids[0].s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = 0;
+ lck_mtx_unlock(scope6_mutex);
}
int
if (scope6_ids == NULL) /* paranoid? */
return(EINVAL);
+ lck_mtx_lock(scope6_mutex);
bcopy(scope6_ids[0].s6id_list, idlist,
sizeof(scope6_ids[0].s6id_list));
+ lck_mtx_unlock(scope6_mutex);
return(0);
}
scope6_addr2default(
struct in6_addr *addr)
{
- return(scope6_ids[0].s6id_list[in6_addrscope(addr)]);
+ u_int32_t id = 0;
+ int index = in6_addrscope(addr);
+ lck_mtx_lock(scope6_mutex);
+ id = scope6_ids[0].s6id_list[index];
+ lck_mtx_unlock(scope6_mutex);
+ return (id);
}