38#include <sys/malloc.h>
40#include <sys/socket.h>
41#include <sys/sockio.h>
44#include <sys/sysctl.h>
45#include <sys/syslog.h>
48#include <net/if_var.h>
51#include <netinet/in.h>
53#include <netinet/ip6.h>
58#ifdef ENABLE_DEFAULT_SCOPE
70#define SCOPE6_LOCK_INIT() mtx_init(&scope6_lock, "scope6_lock", NULL, MTX_DEF)
71#define SCOPE6_LOCK() mtx_lock(&scope6_lock)
72#define SCOPE6_UNLOCK() mtx_unlock(&scope6_lock)
73#define SCOPE6_LOCK_ASSERT() mtx_assert(&scope6_lock, MA_OWNED)
76#define V_sid_default VNET(sid_default)
79 (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->scope6_id)
90 if (!IS_DEFAULT_VNET(curvnet))
101 sid = malloc(
sizeof(*sid), M_IFADDR, M_WAITOK | M_ZERO);
123 if (ifp->if_afdata[AF_INET6] == NULL)
124 return (EPFNOSUPPORT);
149 IF_AFDATA_WLOCK(ifp);
153 IF_AFDATA_WUNLOCK(ifp);
167 for (i = 0; i < 16; i++) {
176 IF_AFDATA_WUNLOCK(ifp);
181 struct epoch_tracker et;
184 if (!ifnet_byindex(idlist->
s6id_list[i])) {
192 IF_AFDATA_WUNLOCK(ifp);
206 IF_AFDATA_WUNLOCK(ifp);
214 struct epoch_tracker et;
334 struct epoch_tracker et;
343 if (ifnet_byindex(zoneid) == NULL) {
373 struct epoch_tracker et;
377 if (!ifnet_byindex(zoneid)) {
385 "%s: embedded scope mismatch: %s%%%d. "
386 "sin6_scope_id was overridden\n", __func__,
409 u_int32_t zoneid = 0;
417 if (!(ifp->if_flags & IFF_LOOPBACK))
428 zoneid = ifp->if_index;
429 in6->s6_addr16[1] = htons(zoneid & 0xffff);
431 struct epoch_tracker et;
434 if (ifp->if_afdata[AF_INET6] == NULL) {
460 if (in6->s6_addr16[1] != 0)
462 in6->s6_addr16[1] = 0;
476 return (in6->s6_addr16[1]);
492 return (ifp->if_index);
500 in6->s6_addr16[1] = htons(scopeid & 0xffff);
511 return (ifnet_byindex((u_short)zoneid));
523 return (ifp->if_index);
525 return (
SID(ifp)->s6id_list[scope]);
580 return (EADDRNOTAVAIL);
607 return (EADDRNOTAVAIL);
char * ip6_sprintf(char *ip6buf, const struct in6_addr *addr)
#define IPV6_ADDR_SCOPE_GLOBAL
#define IPV6_ADDR_MC_SCOPE(a)
#define IPV6_ADDR_SCOPE_INTFACELOCAL
#define IN6_IS_ADDR_LINKLOCAL(a)
#define IN6_IS_ADDR_LOOPBACK(a)
#define IN6_IS_ADDR_SITELOCAL(a)
#define IN6_IS_ADDR_MULTICAST(a)
#define IN6_IS_ADDR_MC_INTFACELOCAL(a)
#define IPV6_ADDR_SCOPE_LINKLOCAL
#define IPV6_ADDR_SCOPE_SITELOCAL
#define IN6_IS_SCOPE_LINKLOCAL(a)
static struct sockaddr_in6 sin6
#define V_ip6_use_defzone
#define SCOPE6_LOCK_INIT()
SYSCTL_DECL(_net_inet6_ip6)
int in6_setscope(struct in6_addr *in6, struct ifnet *ifp, u_int32_t *ret_id)
void in6_set_unicast_scopeid(struct in6_addr *in6, uint32_t scopeid)
struct scope6_id * scope6_ifattach(struct ifnet *ifp)
uint32_t in6_get_unicast_scopeid(const struct in6_addr *in6, const struct ifnet *ifp)
u_int32_t scope6_addr2default(struct in6_addr *addr)
void in6_splitscope(const struct in6_addr *src, struct in6_addr *dst, uint32_t *scopeid)
struct ifnet * in6_getlinkifnet(uint32_t zoneid)
uint16_t in6_getscope(const struct in6_addr *in6)
int in6_clearscope(struct in6_addr *in6)
int sa6_checkzone_ifp(struct ifnet *ifp, struct sockaddr_in6 *sa6)
VNET_DEFINE_STATIC(struct scope6_id, sid_default)
int sa6_embedscope(struct sockaddr_in6 *sin6, int defaultok)
int scope6_get_default(struct scope6_id *idlist)
int sa6_checkzone(struct sockaddr_in6 *sa6)
void scope6_setdefault(struct ifnet *ifp)
int in6_addrscope(const struct in6_addr *addr)
static int scope6_get(struct ifnet *, struct scope6_id *)
static int scope6_set(struct ifnet *, struct scope6_id *)
int sa6_recoverscope(struct sockaddr_in6 *sin6)
static struct mtx scope6_lock
VNET_DEFINE(int, ip6_use_defzone)=0
void scope6_ifdetach(struct scope6_id *sid)
int scope6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
uint32_t in6_getscopezone(const struct ifnet *ifp, int scope)
#define IPV6_ADDR_SCOPES_COUNT
u_int32_t ifru_scope_id[16]
union in6_ifreq::@2 ifr_ifru
uint32_t s6id_list[IPV6_ADDR_SCOPES_COUNT]
struct in6_addr sin6_addr