2005-04-17 02:20:36 +04:00
# ifndef _ADDRCONF_H
# define _ADDRCONF_H
2016-09-28 09:57:58 +03:00
# define MAX_RTR_SOLICITATIONS -1 /* unlimited */
2005-04-17 02:20:36 +04:00
# define RTR_SOLICITATION_INTERVAL (4*HZ)
2016-09-28 09:57:58 +03:00
# define RTR_SOLICITATION_MAX_INTERVAL (3600*HZ) /* 1 hour */
2005-04-17 02:20:36 +04:00
# define MIN_VALID_LIFETIME (2*3600) /* 2 hours */
# define TEMP_VALID_LIFETIME (7*86400)
# define TEMP_PREFERRED_LIFETIME (86400)
2011-07-26 17:50:49 +04:00
# define REGEN_MAX_RETRY (3)
2005-04-17 02:20:36 +04:00
# define MAX_DESYNC_FACTOR (600)
# define ADDR_CHECK_FREQUENCY (120*HZ)
# define IPV6_MAX_ADDRESSES 16
2013-01-24 13:41:41 +04:00
# define ADDRCONF_TIMER_FUZZ_MINUS (HZ > 50 ? HZ / 50 : 1)
# define ADDRCONF_TIMER_FUZZ (HZ / 4)
# define ADDRCONF_TIMER_FUZZ_MAX (HZ)
2017-05-08 20:12:13 +03:00
# define ADDRCONF_NOTIFY_PRIORITY 0
2007-11-29 14:11:40 +03:00
# include <linux/in.h>
2005-05-04 09:17:18 +04:00
# include <linux/in6.h>
2005-04-17 02:20:36 +04:00
struct prefix_info {
__u8 type ;
__u8 length ;
__u8 prefix_len ;
# if defined(__BIG_ENDIAN_BITFIELD)
__u8 onlink : 1 ,
autoconf : 1 ,
reserved : 6 ;
# elif defined(__LITTLE_ENDIAN_BITFIELD)
__u8 reserved : 6 ,
autoconf : 1 ,
onlink : 1 ;
# else
# error "Please fix <asm / byteorder.h>"
# endif
2006-11-15 07:56:00 +03:00
__be32 valid ;
__be32 prefered ;
__be32 reserved2 ;
2005-04-17 02:20:36 +04:00
struct in6_addr prefix ;
} ;
# include <linux/netdevice.h>
# include <net/if_inet6.h>
2005-05-04 01:25:13 +04:00
# include <net/ipv6.h>
2005-04-17 02:20:36 +04:00
2017-06-08 23:12:14 +03:00
struct in6_validator_info {
struct in6_addr i6vi_addr ;
struct inet6_dev * i6vi_dev ;
} ;
2012-07-18 12:11:12 +04:00
# define IN6_ADDR_HSIZE_SHIFT 4
# define IN6_ADDR_HSIZE (1 << IN6_ADDR_HSIZE_SHIFT)
2005-04-17 02:20:36 +04:00
2013-08-01 04:31:32 +04:00
int addrconf_init ( void ) ;
void addrconf_cleanup ( void ) ;
2005-04-17 02:20:36 +04:00
2013-08-01 04:31:32 +04:00
int addrconf_add_ifaddr ( struct net * net , void __user * arg ) ;
int addrconf_del_ifaddr ( struct net * net , void __user * arg ) ;
int addrconf_set_dstaddr ( struct net * net , void __user * arg ) ;
2005-04-17 02:20:36 +04:00
2013-08-01 04:31:32 +04:00
int ipv6_chk_addr ( struct net * net , const struct in6_addr * addr ,
const struct net_device * dev , int strict ) ;
2015-02-04 14:01:23 +03:00
int ipv6_chk_addr_and_flags ( struct net * net , const struct in6_addr * addr ,
const struct net_device * dev , int strict ,
u32 banned_flags ) ;
2008-01-11 09:43:18 +03:00
2007-06-27 10:56:32 +04:00
# if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
2013-08-01 04:31:32 +04:00
int ipv6_chk_home_addr ( struct net * net , const struct in6_addr * addr ) ;
2006-08-24 06:16:22 +04:00
# endif
2008-03-16 05:54:23 +03:00
2013-09-24 00:04:19 +04:00
bool ipv6_chk_custom_prefix ( const struct in6_addr * addr ,
const unsigned int prefix_len ,
struct net_device * dev ) ;
2013-08-01 04:31:32 +04:00
int ipv6_chk_prefix ( const struct in6_addr * addr , struct net_device * dev ) ;
struct inet6_ifaddr * ipv6_get_ifaddr ( struct net * net ,
const struct in6_addr * addr ,
struct net_device * dev , int strict ) ;
int ipv6_dev_get_saddr ( struct net * net , const struct net_device * dev ,
const struct in6_addr * daddr , unsigned int srcprefs ,
struct in6_addr * saddr ) ;
int __ipv6_get_lladdr ( struct inet6_dev * idev , struct in6_addr * addr ,
2013-12-06 12:45:21 +04:00
u32 banned_flags ) ;
2013-08-01 04:31:32 +04:00
int ipv6_get_lladdr ( struct net_device * dev , struct in6_addr * addr ,
2013-12-06 12:45:21 +04:00
u32 banned_flags ) ;
2017-01-17 18:51:01 +03:00
int inet_rcv_saddr_equal ( const struct sock * sk , const struct sock * sk2 ,
2016-01-05 01:41:46 +03:00
bool match_wildcard ) ;
2013-08-01 04:31:32 +04:00
void addrconf_join_solict ( struct net_device * dev , const struct in6_addr * addr ) ;
void addrconf_leave_solict ( struct inet6_dev * idev , const struct in6_addr * addr ) ;
2005-04-17 02:20:36 +04:00
2016-06-15 22:20:17 +03:00
void addrconf_add_linklocal ( struct inet6_dev * idev ,
const struct in6_addr * addr , u32 flags ) ;
2016-06-15 22:20:24 +03:00
int addrconf_prefix_rcv_add_addr ( struct net * net , struct net_device * dev ,
const struct prefix_info * pinfo ,
struct inet6_dev * in6_dev ,
const struct in6_addr * addr , int addr_type ,
u32 addr_flags , bool sllao , bool tokenized ,
__u32 valid_lft , u32 prefered_lft ) ;
2017-03-14 17:01:57 +03:00
static inline void addrconf_addr_eui48_base ( u8 * eui , const char * const addr )
{
memcpy ( eui , addr , 3 ) ;
eui [ 3 ] = 0xFF ;
eui [ 4 ] = 0xFE ;
memcpy ( eui + 5 , addr + 3 , 3 ) ;
}
static inline void addrconf_addr_eui48 ( u8 * eui , const char * const addr )
{
addrconf_addr_eui48_base ( eui , addr ) ;
eui [ 0 ] ^ = 2 ;
}
2015-07-30 18:33:22 +03:00
static inline int addrconf_ifid_eui48 ( u8 * eui , struct net_device * dev )
{
if ( dev - > addr_len ! = ETH_ALEN )
return - 1 ;
/*
* The zSeries OSA network cards can be shared among various
* OS instances , but the OSA cards have only one MAC address .
* This leads to duplicate address conflicts in conjunction
* with IPv6 if more than one instance uses the same card .
*
* The driver for these cards can deliver a unique 16 - bit
* identifier for each instance sharing the same card . It is
* placed instead of 0xFFFE in the interface identifier . The
* " u " bit of the interface identifier is not inverted in this
* case . Hence the resulting interface identifier has local
* scope according to RFC2373 .
*/
2017-03-14 17:01:57 +03:00
addrconf_addr_eui48_base ( eui , dev - > dev_addr ) ;
2015-07-30 18:33:22 +03:00
if ( dev - > dev_id ) {
eui [ 3 ] = ( dev - > dev_id > > 8 ) & 0xFF ;
eui [ 4 ] = dev - > dev_id & 0xFF ;
} else {
eui [ 0 ] ^ = 2 ;
}
2017-03-14 17:01:57 +03:00
2015-07-30 18:33:22 +03:00
return 0 ;
}
2008-05-27 12:37:49 +04:00
static inline unsigned long addrconf_timeout_fixup ( u32 timeout ,
2012-04-15 09:58:06 +04:00
unsigned int unit )
2008-05-27 12:37:49 +04:00
{
if ( timeout = = 0xffffffff )
return ~ 0UL ;
/*
* Avoid arithmetic overflow .
* Assuming unit is constant and non - zero , this " if " statement
* will go away on 64 bit archs .
*/
if ( 0xfffffffe > LONG_MAX / unit & & timeout > LONG_MAX / unit )
return LONG_MAX / unit ;
return timeout ;
}
static inline int addrconf_finite_timeout ( unsigned long timeout )
{
return ~ timeout ;
}
2007-11-14 09:56:23 +03:00
/*
* IPv6 Address Label subsystem ( addrlabel . c )
*/
2013-08-01 04:31:32 +04:00
int ipv6_addr_label_init ( void ) ;
void ipv6_addr_label_cleanup ( void ) ;
void ipv6_addr_label_rtnl_register ( void ) ;
u32 ipv6_addr_label ( struct net * net , const struct in6_addr * addr ,
int type , int ifindex ) ;
2007-11-14 09:56:23 +03:00
2005-04-17 02:20:36 +04:00
/*
* multicast prototypes ( mcast . c )
*/
2013-08-01 04:31:32 +04:00
int ipv6_sock_mc_join ( struct sock * sk , int ifindex ,
const struct in6_addr * addr ) ;
int ipv6_sock_mc_drop ( struct sock * sk , int ifindex ,
const struct in6_addr * addr ) ;
2016-10-20 09:35:12 +03:00
void __ipv6_sock_mc_close ( struct sock * sk ) ;
2013-08-01 04:31:32 +04:00
void ipv6_sock_mc_close ( struct sock * sk ) ;
bool inet6_mc_check ( struct sock * sk , const struct in6_addr * mc_addr ,
const struct in6_addr * src_addr ) ;
int ipv6_dev_mc_inc ( struct net_device * dev , const struct in6_addr * addr ) ;
int __ipv6_dev_mc_dec ( struct inet6_dev * idev , const struct in6_addr * addr ) ;
int ipv6_dev_mc_dec ( struct net_device * dev , const struct in6_addr * addr ) ;
void ipv6_mc_up ( struct inet6_dev * idev ) ;
void ipv6_mc_down ( struct inet6_dev * idev ) ;
void ipv6_mc_unmap ( struct inet6_dev * idev ) ;
void ipv6_mc_remap ( struct inet6_dev * idev ) ;
void ipv6_mc_init_dev ( struct inet6_dev * idev ) ;
void ipv6_mc_destroy_dev ( struct inet6_dev * idev ) ;
2015-05-02 15:01:07 +03:00
int ipv6_mc_check_mld ( struct sk_buff * skb , struct sk_buff * * skb_trimmed ) ;
2013-08-01 04:31:32 +04:00
void addrconf_dad_failure ( struct inet6_ifaddr * ifp ) ;
bool ipv6_chk_mcast_addr ( struct net_device * dev , const struct in6_addr * group ,
const struct in6_addr * src_addr ) ;
void ipv6_mc_dad_complete ( struct inet6_dev * idev ) ;
2013-08-31 09:44:30 +04:00
/* A stub used by vxlan module. This is ugly, ideally these
* symbols should be built into the core kernel .
*/
struct ipv6_stub {
int ( * ipv6_sock_mc_join ) ( struct sock * sk , int ifindex ,
const struct in6_addr * addr ) ;
int ( * ipv6_sock_mc_drop ) ( struct sock * sk , int ifindex ,
const struct in6_addr * addr ) ;
2015-07-30 23:34:53 +03:00
int ( * ipv6_dst_lookup ) ( struct net * net , struct sock * sk ,
struct dst_entry * * dst , struct flowi6 * fl6 ) ;
2013-08-31 09:44:30 +04:00
void ( * udpv6_encap_enable ) ( void ) ;
2015-09-22 19:57:13 +03:00
void ( * ndisc_send_na ) ( struct net_device * dev , const struct in6_addr * daddr ,
2013-08-31 09:44:36 +04:00
const struct in6_addr * solicited_addr ,
bool router , bool solicited , bool override , bool inc_opt ) ;
2013-08-31 09:44:34 +04:00
struct neigh_table * nd_tbl ;
2013-08-31 09:44:30 +04:00
} ;
extern const struct ipv6_stub * ipv6_stub __read_mostly ;
2013-01-13 09:02:18 +04:00
/*
* identify MLD packets for MLD filter exceptions
*/
static inline bool ipv6_is_mld ( struct sk_buff * skb , int nexthdr , int offset )
{
struct icmp6hdr * hdr ;
if ( nexthdr ! = IPPROTO_ICMPV6 | |
! pskb_network_may_pull ( skb , offset + sizeof ( struct icmp6hdr ) ) )
return false ;
hdr = ( struct icmp6hdr * ) ( skb_network_header ( skb ) + offset ) ;
switch ( hdr - > icmp6_type ) {
case ICMPV6_MGM_QUERY :
case ICMPV6_MGM_REPORT :
case ICMPV6_MGM_REDUCTION :
case ICMPV6_MLD2_REPORT :
return true ;
default :
break ;
}
return false ;
}
2005-04-17 02:20:36 +04:00
2013-08-01 04:31:32 +04:00
void addrconf_prefix_rcv ( struct net_device * dev ,
u8 * opt , int len , bool sllao ) ;
2005-04-17 02:20:36 +04:00
/*
* anycast prototypes ( anycast . c )
*/
2013-08-01 04:31:32 +04:00
int ipv6_sock_ac_join ( struct sock * sk , int ifindex ,
const struct in6_addr * addr ) ;
int ipv6_sock_ac_drop ( struct sock * sk , int ifindex ,
const struct in6_addr * addr ) ;
void ipv6_sock_ac_close ( struct sock * sk ) ;
2014-09-12 02:35:11 +04:00
int __ipv6_dev_ac_inc ( struct inet6_dev * idev , const struct in6_addr * addr ) ;
2013-08-01 04:31:32 +04:00
int __ipv6_dev_ac_dec ( struct inet6_dev * idev , const struct in6_addr * addr ) ;
2014-09-11 01:23:02 +04:00
void ipv6_ac_destroy_dev ( struct inet6_dev * idev ) ;
2013-08-01 04:31:32 +04:00
bool ipv6_chk_acast_addr ( struct net * net , struct net_device * dev ,
2014-01-22 10:42:37 +04:00
const struct in6_addr * addr ) ;
bool ipv6_chk_acast_addr_src ( struct net * net , struct net_device * dev ,
const struct in6_addr * addr ) ;
2005-04-17 02:20:36 +04:00
/* Device notifier */
2013-08-01 04:31:32 +04:00
int register_inet6addr_notifier ( struct notifier_block * nb ) ;
int unregister_inet6addr_notifier ( struct notifier_block * nb ) ;
int inet6addr_notifier_call_chain ( unsigned long val , void * v ) ;
2005-04-17 02:20:36 +04:00
2017-06-08 23:12:14 +03:00
int register_inet6addr_validator_notifier ( struct notifier_block * nb ) ;
int unregister_inet6addr_validator_notifier ( struct notifier_block * nb ) ;
int inet6addr_validator_notifier_call_chain ( unsigned long val , void * v ) ;
2017-03-29 00:28:04 +03:00
void inet6_netconf_notify_devconf ( struct net * net , int event , int type ,
int ifindex , struct ipv6_devconf * devconf ) ;
2012-12-04 05:13:35 +04:00
2010-09-21 10:57:39 +04:00
/**
* __in6_dev_get - get inet6_dev pointer from netdevice
* @ dev : network device
*
* Caller must hold rcu_read_lock or RTNL , because this function
* does not take a reference on the inet6_dev .
*/
static inline struct inet6_dev * __in6_dev_get ( const struct net_device * dev )
2005-04-17 02:20:36 +04:00
{
2010-09-21 10:57:39 +04:00
return rcu_dereference_rtnl ( dev - > ip6_ptr ) ;
2005-04-17 02:20:36 +04:00
}
2010-09-21 10:57:39 +04:00
/**
* in6_dev_get - get inet6_dev pointer from netdevice
* @ dev : network device
*
* This version can be used in any context , and takes a reference
* on the inet6_dev . Callers must use in6_dev_put ( ) later to
* release this reference .
*/
static inline struct inet6_dev * in6_dev_get ( const struct net_device * dev )
2005-04-17 02:20:36 +04:00
{
2010-09-21 10:57:39 +04:00
struct inet6_dev * idev ;
2006-09-23 01:44:24 +04:00
rcu_read_lock ( ) ;
2010-09-21 10:57:39 +04:00
idev = rcu_dereference ( dev - > ip6_ptr ) ;
2005-04-17 02:20:36 +04:00
if ( idev )
atomic_inc ( & idev - > refcnt ) ;
2006-09-23 01:44:24 +04:00
rcu_read_unlock ( ) ;
2005-04-17 02:20:36 +04:00
return idev ;
}
2013-12-07 22:26:57 +04:00
static inline struct neigh_parms * __in6_dev_nd_parms_get_rcu ( const struct net_device * dev )
{
struct inet6_dev * idev = __in6_dev_get ( dev ) ;
return idev ? idev - > nd_parms : NULL ;
}
2013-08-01 04:31:32 +04:00
void in6_dev_finish_destroy ( struct inet6_dev * idev ) ;
2005-04-17 02:20:36 +04:00
2010-09-21 10:57:39 +04:00
static inline void in6_dev_put ( struct inet6_dev * idev )
2005-04-17 02:20:36 +04:00
{
if ( atomic_dec_and_test ( & idev - > refcnt ) )
in6_dev_finish_destroy ( idev ) ;
}
2010-09-21 10:57:39 +04:00
static inline void __in6_dev_put ( struct inet6_dev * idev )
{
atomic_dec ( & idev - > refcnt ) ;
}
2005-04-17 02:20:36 +04:00
2010-09-21 10:57:39 +04:00
static inline void in6_dev_hold ( struct inet6_dev * idev )
{
atomic_inc ( & idev - > refcnt ) ;
}
2005-04-17 02:20:36 +04:00
2013-08-01 04:31:32 +04:00
void inet6_ifa_finish_destroy ( struct inet6_ifaddr * ifp ) ;
2005-04-17 02:20:36 +04:00
static inline void in6_ifa_put ( struct inet6_ifaddr * ifp )
{
if ( atomic_dec_and_test ( & ifp - > refcnt ) )
inet6_ifa_finish_destroy ( ifp ) ;
}
2010-09-21 10:57:39 +04:00
static inline void __in6_ifa_put ( struct inet6_ifaddr * ifp )
{
atomic_dec ( & ifp - > refcnt ) ;
}
2005-04-17 02:20:36 +04:00
2010-09-21 10:57:39 +04:00
static inline void in6_ifa_hold ( struct inet6_ifaddr * ifp )
{
atomic_inc ( & ifp - > refcnt ) ;
}
2005-04-17 02:20:36 +04:00
/*
* compute link - local solicited - node multicast address
*/
static inline void addrconf_addr_solict_mult ( const struct in6_addr * addr ,
struct in6_addr * solicited )
{
ipv6_addr_set ( solicited ,
2008-02-28 11:03:12 +03:00
htonl ( 0xFF020000 ) , 0 ,
htonl ( 0x1 ) ,
htonl ( 0xFF000000 ) | addr - > s6_addr32 [ 3 ] ) ;
2005-04-17 02:20:36 +04:00
}
2013-01-20 21:38:38 +04:00
static inline bool ipv6_addr_is_ll_all_nodes ( const struct in6_addr * addr )
2005-04-17 02:20:36 +04:00
{
2013-01-20 11:38:52 +04:00
# if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
2014-02-27 17:20:29 +04:00
__be64 * p = ( __be64 * ) addr ;
2013-01-20 11:38:52 +04:00
return ( ( p [ 0 ] ^ cpu_to_be64 ( 0xff02000000000000UL ) ) | ( p [ 1 ] ^ cpu_to_be64 ( 1 ) ) ) = = 0UL ;
# else
2010-09-21 10:57:39 +04:00
return ( ( addr - > s6_addr32 [ 0 ] ^ htonl ( 0xff020000 ) ) |
2008-04-11 15:17:55 +04:00
addr - > s6_addr32 [ 1 ] | addr - > s6_addr32 [ 2 ] |
2010-09-21 10:57:39 +04:00
( addr - > s6_addr32 [ 3 ] ^ htonl ( 0x00000001 ) ) ) = = 0 ;
2013-01-20 11:38:52 +04:00
# endif
2005-04-17 02:20:36 +04:00
}
2013-01-20 21:38:38 +04:00
static inline bool ipv6_addr_is_ll_all_routers ( const struct in6_addr * addr )
2005-04-17 02:20:36 +04:00
{
2013-01-20 11:38:52 +04:00
# if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
2014-02-27 17:20:29 +04:00
__be64 * p = ( __be64 * ) addr ;
2013-01-20 11:38:52 +04:00
return ( ( p [ 0 ] ^ cpu_to_be64 ( 0xff02000000000000UL ) ) | ( p [ 1 ] ^ cpu_to_be64 ( 2 ) ) ) = = 0UL ;
# else
2010-09-21 10:57:39 +04:00
return ( ( addr - > s6_addr32 [ 0 ] ^ htonl ( 0xff020000 ) ) |
2008-04-11 15:17:55 +04:00
addr - > s6_addr32 [ 1 ] | addr - > s6_addr32 [ 2 ] |
2010-09-21 10:57:39 +04:00
( addr - > s6_addr32 [ 3 ] ^ htonl ( 0x00000002 ) ) ) = = 0 ;
2013-01-20 11:38:52 +04:00
# endif
2005-04-17 02:20:36 +04:00
}
2013-01-20 21:38:38 +04:00
static inline bool ipv6_addr_is_isatap ( const struct in6_addr * addr )
2007-11-29 14:11:40 +03:00
{
2010-09-21 10:57:39 +04:00
return ( addr - > s6_addr32 [ 2 ] | htonl ( 0x02000000 ) ) = = htonl ( 0x02005EFE ) ;
2007-11-29 14:11:40 +03:00
}
2013-01-20 11:39:00 +04:00
static inline bool ipv6_addr_is_solict_mult ( const struct in6_addr * addr )
{
2013-01-20 11:39:07 +04:00
# if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
2014-02-27 17:20:29 +04:00
__be64 * p = ( __be64 * ) addr ;
2013-01-20 11:39:07 +04:00
return ( ( p [ 0 ] ^ cpu_to_be64 ( 0xff02000000000000UL ) ) |
( ( p [ 1 ] ^ cpu_to_be64 ( 0x00000001ff000000UL ) ) &
cpu_to_be64 ( 0xffffffffff000000UL ) ) ) = = 0UL ;
# else
return ( ( addr - > s6_addr32 [ 0 ] ^ htonl ( 0xff020000 ) ) |
addr - > s6_addr32 [ 1 ] |
( addr - > s6_addr32 [ 2 ] ^ htonl ( 0x00000001 ) ) |
( addr - > s6_addr [ 12 ] ^ 0xff ) ) = = 0 ;
# endif
2013-01-20 11:39:00 +04:00
}
2005-08-16 09:18:02 +04:00
# ifdef CONFIG_PROC_FS
2013-08-01 04:31:32 +04:00
int if6_proc_init ( void ) ;
void if6_proc_exit ( void ) ;
2005-08-16 09:18:02 +04:00
# endif
2005-04-17 02:20:36 +04:00
# endif