ipv6: Export ndisc option parsing from ndisc.c
This is going to be used internally by the rt6 redirect code. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
1f42539d25
commit
30f2a5f379
2 changed files with 52 additions and 45 deletions
|
@ -47,6 +47,8 @@ enum {
|
||||||
#include <linux/icmpv6.h>
|
#include <linux/icmpv6.h>
|
||||||
#include <linux/in6.h>
|
#include <linux/in6.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include <linux/if_arp.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
|
||||||
#include <net/neighbour.h>
|
#include <net/neighbour.h>
|
||||||
|
|
||||||
|
@ -80,6 +82,54 @@ struct nd_opt_hdr {
|
||||||
__u8 nd_opt_len;
|
__u8 nd_opt_len;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
/* ND options */
|
||||||
|
struct ndisc_options {
|
||||||
|
struct nd_opt_hdr *nd_opt_array[__ND_OPT_ARRAY_MAX];
|
||||||
|
#ifdef CONFIG_IPV6_ROUTE_INFO
|
||||||
|
struct nd_opt_hdr *nd_opts_ri;
|
||||||
|
struct nd_opt_hdr *nd_opts_ri_end;
|
||||||
|
#endif
|
||||||
|
struct nd_opt_hdr *nd_useropts;
|
||||||
|
struct nd_opt_hdr *nd_useropts_end;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define nd_opts_src_lladdr nd_opt_array[ND_OPT_SOURCE_LL_ADDR]
|
||||||
|
#define nd_opts_tgt_lladdr nd_opt_array[ND_OPT_TARGET_LL_ADDR]
|
||||||
|
#define nd_opts_pi nd_opt_array[ND_OPT_PREFIX_INFO]
|
||||||
|
#define nd_opts_pi_end nd_opt_array[__ND_OPT_PREFIX_INFO_END]
|
||||||
|
#define nd_opts_rh nd_opt_array[ND_OPT_REDIRECT_HDR]
|
||||||
|
#define nd_opts_mtu nd_opt_array[ND_OPT_MTU]
|
||||||
|
|
||||||
|
#define NDISC_OPT_SPACE(len) (((len)+2+7)&~7)
|
||||||
|
|
||||||
|
extern struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
|
||||||
|
struct ndisc_options *ndopts);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the padding between the option length and the start of the
|
||||||
|
* link addr. Currently only IP-over-InfiniBand needs this, although
|
||||||
|
* if RFC 3831 IPv6-over-Fibre Channel is ever implemented it may
|
||||||
|
* also need a pad of 2.
|
||||||
|
*/
|
||||||
|
static int ndisc_addr_option_pad(unsigned short type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case ARPHRD_INFINIBAND: return 2;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p,
|
||||||
|
struct net_device *dev)
|
||||||
|
{
|
||||||
|
u8 *lladdr = (u8 *)(p + 1);
|
||||||
|
int lladdrlen = p->nd_opt_len << 3;
|
||||||
|
int prepad = ndisc_addr_option_pad(dev->type);
|
||||||
|
if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len + prepad))
|
||||||
|
return NULL;
|
||||||
|
return lladdr + prepad;
|
||||||
|
}
|
||||||
|
|
||||||
static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, __u32 *hash_rnd)
|
static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, __u32 *hash_rnd)
|
||||||
{
|
{
|
||||||
const u32 *p32 = pkey;
|
const u32 *p32 = pkey;
|
||||||
|
|
|
@ -143,40 +143,8 @@ struct neigh_table nd_tbl = {
|
||||||
.gc_thresh3 = 1024,
|
.gc_thresh3 = 1024,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ND options */
|
|
||||||
struct ndisc_options {
|
|
||||||
struct nd_opt_hdr *nd_opt_array[__ND_OPT_ARRAY_MAX];
|
|
||||||
#ifdef CONFIG_IPV6_ROUTE_INFO
|
|
||||||
struct nd_opt_hdr *nd_opts_ri;
|
|
||||||
struct nd_opt_hdr *nd_opts_ri_end;
|
|
||||||
#endif
|
|
||||||
struct nd_opt_hdr *nd_useropts;
|
|
||||||
struct nd_opt_hdr *nd_useropts_end;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define nd_opts_src_lladdr nd_opt_array[ND_OPT_SOURCE_LL_ADDR]
|
|
||||||
#define nd_opts_tgt_lladdr nd_opt_array[ND_OPT_TARGET_LL_ADDR]
|
|
||||||
#define nd_opts_pi nd_opt_array[ND_OPT_PREFIX_INFO]
|
|
||||||
#define nd_opts_pi_end nd_opt_array[__ND_OPT_PREFIX_INFO_END]
|
|
||||||
#define nd_opts_rh nd_opt_array[ND_OPT_REDIRECT_HDR]
|
|
||||||
#define nd_opts_mtu nd_opt_array[ND_OPT_MTU]
|
|
||||||
|
|
||||||
#define NDISC_OPT_SPACE(len) (((len)+2+7)&~7)
|
#define NDISC_OPT_SPACE(len) (((len)+2+7)&~7)
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the padding between the option length and the start of the
|
|
||||||
* link addr. Currently only IP-over-InfiniBand needs this, although
|
|
||||||
* if RFC 3831 IPv6-over-Fibre Channel is ever implemented it may
|
|
||||||
* also need a pad of 2.
|
|
||||||
*/
|
|
||||||
static int ndisc_addr_option_pad(unsigned short type)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case ARPHRD_INFINIBAND: return 2;
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ndisc_opt_addr_space(struct net_device *dev)
|
static inline int ndisc_opt_addr_space(struct net_device *dev)
|
||||||
{
|
{
|
||||||
return NDISC_OPT_SPACE(dev->addr_len + ndisc_addr_option_pad(dev->type));
|
return NDISC_OPT_SPACE(dev->addr_len + ndisc_addr_option_pad(dev->type));
|
||||||
|
@ -233,8 +201,8 @@ static struct nd_opt_hdr *ndisc_next_useropt(struct nd_opt_hdr *cur,
|
||||||
return cur <= end && ndisc_is_useropt(cur) ? cur : NULL;
|
return cur <= end && ndisc_is_useropt(cur) ? cur : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
|
struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
|
||||||
struct ndisc_options *ndopts)
|
struct ndisc_options *ndopts)
|
||||||
{
|
{
|
||||||
struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)opt;
|
struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)opt;
|
||||||
|
|
||||||
|
@ -297,17 +265,6 @@ static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
|
||||||
return ndopts;
|
return ndopts;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p,
|
|
||||||
struct net_device *dev)
|
|
||||||
{
|
|
||||||
u8 *lladdr = (u8 *)(p + 1);
|
|
||||||
int lladdrlen = p->nd_opt_len << 3;
|
|
||||||
int prepad = ndisc_addr_option_pad(dev->type);
|
|
||||||
if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len + prepad))
|
|
||||||
return NULL;
|
|
||||||
return lladdr + prepad;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ndisc_mc_map(const struct in6_addr *addr, char *buf, struct net_device *dev, int dir)
|
int ndisc_mc_map(const struct in6_addr *addr, char *buf, struct net_device *dev, int dir)
|
||||||
{
|
{
|
||||||
switch (dev->type) {
|
switch (dev->type) {
|
||||||
|
|
Loading…
Reference in a new issue