mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
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/in6.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include <net/neighbour.h>
|
||||
|
||||
|
@ -80,6 +82,54 @@ struct nd_opt_hdr {
|
|||
__u8 nd_opt_len;
|
||||
} __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)
|
||||
{
|
||||
const u32 *p32 = pkey;
|
||||
|
|
|
@ -143,40 +143,8 @@ struct neigh_table nd_tbl = {
|
|||
.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)
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
static struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
|
||||
struct ndisc_options *ndopts)
|
||||
struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
|
||||
struct ndisc_options *ndopts)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
switch (dev->type) {
|
||||
|
|
Loading…
Reference in a new issue