Introduce new scope related functions.
* new macro to remove magic number - IPV6_ADDR_SCOPES_COUNT; * sa6_checkzone() - this function checks sockaddr_in6 structure for correctness of sin6_scope_id. It also can fill correct value sometimes. * in6_getscopezone() - this function returns scope zone id for specified interface and scope. * in6_getlinkifnet() - this function returns struct ifnet for corresponding zone id of link-local scope. Obtained from: Yandex LLC Sponsored by: Yandex LLC
This commit is contained in:
parent
15c7266a7f
commit
41874e85d6
@ -467,3 +467,77 @@ in6_getscope(struct in6_addr *in6)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return pointer to ifnet structure, corresponding to the zone id of
|
||||
* link-local scope.
|
||||
*/
|
||||
struct ifnet*
|
||||
in6_getlinkifnet(uint32_t zoneid)
|
||||
{
|
||||
|
||||
return (ifnet_byindex((u_short)zoneid));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return zone id for the specified scope.
|
||||
*/
|
||||
uint32_t
|
||||
in6_getscopezone(const struct ifnet *ifp, int scope)
|
||||
{
|
||||
|
||||
if (scope == IPV6_ADDR_SCOPE_INTFACELOCAL ||
|
||||
scope == IPV6_ADDR_SCOPE_LINKLOCAL)
|
||||
return (ifp->if_index);
|
||||
if (scope >= 0 && scope < IPV6_ADDR_SCOPES_COUNT)
|
||||
return (SID(ifp)->s6id_list[scope]);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is for checking sockaddr_in6 structure passed
|
||||
* from the application level (usually).
|
||||
*
|
||||
* sin6_scope_id should be set for link-local unicast, link-local and
|
||||
* interface-local multicast addresses.
|
||||
*
|
||||
* If it is zero, then look into default zone ids. If default zone id is
|
||||
* not set or disabled, then return error.
|
||||
*/
|
||||
int
|
||||
sa6_checkzone(struct sockaddr_in6 *sa6)
|
||||
{
|
||||
int scope;
|
||||
|
||||
scope = in6_addrscope(&sa6->sin6_addr);
|
||||
if (scope == IPV6_ADDR_SCOPE_GLOBAL)
|
||||
return (sa6->sin6_scope_id ? EINVAL: 0);
|
||||
if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr) &&
|
||||
scope != IPV6_ADDR_SCOPE_LINKLOCAL &&
|
||||
scope != IPV6_ADDR_SCOPE_INTFACELOCAL) {
|
||||
if (sa6->sin6_scope_id == 0 && V_ip6_use_defzone != 0)
|
||||
sa6->sin6_scope_id = V_sid_default.s6id_list[scope];
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* Since ::1 address always configured on the lo0, we can
|
||||
* automatically set its zone id, when it is not specified.
|
||||
* Return error, when specified zone id doesn't match with
|
||||
* actual value.
|
||||
*/
|
||||
if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr)) {
|
||||
if (sa6->sin6_scope_id == 0)
|
||||
sa6->sin6_scope_id = in6_getscopezone(V_loif, scope);
|
||||
else if (sa6->sin6_scope_id != in6_getscopezone(V_loif, scope))
|
||||
return (EADDRNOTAVAIL);
|
||||
}
|
||||
/* XXX: we can validate sin6_scope_id here */
|
||||
if (sa6->sin6_scope_id != 0)
|
||||
return (0);
|
||||
if (V_ip6_use_defzone != 0)
|
||||
sa6->sin6_scope_id = V_sid_default.s6id_list[scope];
|
||||
/* Return error if we can't determine zone id */
|
||||
return (sa6->sin6_scope_id ? 0: EADDRNOTAVAIL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -36,12 +36,13 @@
|
||||
#ifdef _KERNEL
|
||||
#include <net/vnet.h>
|
||||
|
||||
#define IPV6_ADDR_SCOPES_COUNT 16
|
||||
struct scope6_id {
|
||||
/*
|
||||
* 16 is correspondent to 4bit multicast scope field.
|
||||
* i.e. from node-local to global with some reserved/unassigned types.
|
||||
*/
|
||||
u_int32_t s6id_list[16];
|
||||
uint32_t s6id_list[IPV6_ADDR_SCOPES_COUNT];
|
||||
};
|
||||
|
||||
VNET_DECLARE(int, deembed_scopeid);
|
||||
@ -56,9 +57,12 @@ int scope6_get_default(struct scope6_id *);
|
||||
u_int32_t scope6_addr2default(struct in6_addr *);
|
||||
int sa6_embedscope(struct sockaddr_in6 *, int);
|
||||
int sa6_recoverscope(struct sockaddr_in6 *);
|
||||
int sa6_checkzone(struct sockaddr_in6 *);
|
||||
int in6_setscope(struct in6_addr *, struct ifnet *, u_int32_t *);
|
||||
int in6_clearscope(struct in6_addr *);
|
||||
uint16_t in6_getscope(struct in6_addr *);
|
||||
uint32_t in6_getscopezone(const struct ifnet *, int);
|
||||
struct ifnet* in6_getlinkifnet(uint32_t);
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* _NETINET6_SCOPE6_VAR_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user