Home | History | Annotate | Download | only in inet
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #ifndef	_INET_IP_NDP_H
     27 #define	_INET_IP_NDP_H
     28 
     29 #include <sys/mutex.h>
     30 #include <sys/stream.h>
     31 #include <netinet/in.h>
     32 #include <netinet/icmp6.h>
     33 #include <inet/ip.h>
     34 #include <inet/ip2mac.h>
     35 
     36 /*
     37  * Internal definitions for the kernel implementation of the IPv6
     38  * Neighbor Discovery Protocol (NDP) and Address Resolution Protocol (ARP).
     39  */
     40 
     41 #ifdef	__cplusplus
     42 extern "C" {
     43 #endif
     44 
     45 #ifdef _KERNEL
     46 #define	NCE_TABLE_SIZE	256
     47 /*
     48  * callbacks set up with ip2mac interface, waiting for result
     49  * of neighbor resolution.
     50  */
     51 typedef struct ncec_cb_s {
     52 	list_node_t		ncec_cb_node;	/* next entry in list */
     53 	void			*ncec_cb_id;
     54 	uint32_t		ncec_cb_flags;
     55 	ip2mac_callback_t	*ncec_cb_func;
     56 	void			*ncec_cb_arg;
     57 } ncec_cb_t;
     58 
     59 #define	NCE_CB_DISPATCHED	0x00000001
     60 
     61 /*
     62  * Core information tracking Neighbor Reachability is tracked in the
     63  * ncec_s/ncec_t. The information contained in the ncec_t does not contain
     64  * any link-specific details other than the pointer to the ill_t itself.
     65  * The link-specific information is tracked in the nce_t structure.
     66  */
     67 struct ncec_s {
     68 	struct	ncec_s	*ncec_next;	/* Hash chain next pointer */
     69 	struct	ncec_s	**ncec_ptpn;	/* Pointer to previous next */
     70 	struct 	ill_s	*ncec_ill;	/* Associated ill */
     71 	uint16_t	ncec_flags;	/* See below */
     72 	uint16_t	ncec_state;	/* See reachability states in if.h */
     73 	int16_t		ncec_pcnt;	/* Probe counter */
     74 	uint16_t	ncec_rcnt;	/* Retransmit counter */
     75 	in6_addr_t	ncec_addr;	/* address of the nighbor */
     76 	uchar_t		*ncec_lladdr;
     77 	mblk_t		*ncec_qd_mp;	/* Head outgoing queued packets */
     78 	uint64_t	ncec_last;	/* Time last reachable in msec */
     79 	uint32_t	ncec_refcnt;	/* ncec active usage count */
     80 	kmutex_t	ncec_lock;	/* See comments on top for what */
     81 					/* this field protects */
     82 	int		ncec_unsolicit_count; /* Unsolicited Adv count */
     83 	timeout_id_t	ncec_timeout_id;
     84 	uchar_t		ncec_ipversion;	/* IPv4(ARP)/IPv6(NDP) version */
     85 	uint_t		ncec_defense_count;	/* number of NDP conflicts */
     86 	uint_t		ncec_last_time_defended; /* last time defended (secs) */
     87 	uint64_t	ncec_init_time; /* time when it was set to ND_INITIAL */
     88 	boolean_t	ncec_trace_disable;	/* True when alloc fails */
     89 	/*
     90 	 * interval to keep track of DAD probes.
     91 	 */
     92 	clock_t		ncec_xmit_interval;
     93 	ip_stack_t	*ncec_ipst;	/* Does not have a netstack_hold */
     94 	list_t		ncec_cb;	/* callbacks waiting for resolution */
     95 	uint_t		ncec_cb_walker_cnt;
     96 	uint_t		ncec_nprobes;
     97 	uint_t		ncec_lladdr_length;
     98 };
     99 
    100 /*
    101  * The nce_t list hangs off the ill_s and tracks information that depends
    102  * on the underlying physical link. Thus when the ill goes down,
    103  * the nce_t list has to be flushed. This is  done as part of ill_delete()
    104  *
    105  * When the fastpath ack comes back in ill_fastpath_ack we call
    106  * nce_fastpath_update to update the nce_t. We never actually
    107  * flush the fastpath list, which is kept as an index into the
    108  * ncec_t structures.
    109  *
    110  * when we ndp_delete, we remove the nce entries pointing
    111  * at the dying ncec from the ill_fastpath_list chain.
    112  *
    113  */
    114 struct nce_s	{
    115 	list_node_t	nce_node;
    116 	ill_t		*nce_ill;
    117 	boolean_t	nce_is_condemned;
    118 	in6_addr_t	nce_addr;
    119 	/*
    120 	 * link-layer specific fields below
    121 	 */
    122 	mblk_t		*nce_dlur_mp;	/* DL_UNITDATA_REQ mp */
    123 	mblk_t		*nce_fp_mp;	/* fast path mp */
    124 	struct ncec_s	*nce_common;
    125 	kmutex_t	nce_lock;
    126 	uint32_t	nce_refcnt;
    127 	uint_t		nce_ipif_cnt;	/* number of ipifs with the nce_addr */
    128 					/* as their local address */
    129 };
    130 
    131 /*
    132  * The ndp_g_t structure contains protocol specific information needed
    133  * to synchronize and manage neighbor cache entries for IPv4 and IPv6.
    134  * There are 2 such structures, ips_ndp4 and ips_ndp6.
    135  * ips_ndp6 contains the data structures needed for IPv6 Neighbor Discovery.
    136  * ips_ndp4 contains the data structures for IPv4 ARP.
    137  *
    138  * Locking notes:
    139  * ndp_g_lock protects neighbor cache tables access and
    140  * insertion/removal of cache entries into/from these tables. The ncec_lock
    141  * and nce_lock protect fields in the ncec_t and nce_t structures.
    142  * Should there be a need to obtain nce[c]_lock and ndp_g_lock, ndp_g_lock is
    143  * acquired first.
    144  */
    145 typedef	struct ndp_g_s {
    146 	kmutex_t	ndp_g_lock;	/* Lock protecting  cache hash table */
    147 	ncec_t		*nce_hash_tbl[NCE_TABLE_SIZE];
    148 	int		ndp_g_walker; /* # of active thread walking hash list */
    149 	boolean_t	ndp_g_walker_cleanup; /* true implies defer deletion. */
    150 } ndp_g_t;
    151 
    152 /* ncec_flags  */
    153 #define	NCE_F_MYADDR		0x1	/* ipif exists for the ncec_addr */
    154 #define	NCE_F_UNVERIFIED	0x2	/* DAD in progress. */
    155 #define	NCE_F_ISROUTER		0x4
    156 #define	NCE_F_FAST		0x8
    157 
    158 /*
    159  * NCE_F_NONUD is used to disable IPv6 Neighbor Unreachability Detection or
    160  * IPv4 aging and maps to the ATF_PERM flag for arp(1m)
    161  */
    162 #define	NCE_F_NONUD		0x10
    163 
    164 #define	NCE_F_ANYCAST		0x20
    165 #define	NCE_F_CONDEMNED		0x40
    166 #define	NCE_F_UNSOL_ADV		0x80
    167 #define	NCE_F_BCAST		0x100
    168 #define	NCE_F_MCAST		0x200
    169 
    170 /*
    171  * NCE_F_PUBLISH is set for all ARP/ND entries that we announce. This
    172  * includes locally configured addresses as well as those that we proxy for.
    173  */
    174 #define	NCE_F_PUBLISH		0x400
    175 
    176 /*
    177  * NCE_F_AUTHORITY is set for any address that we have authoritatitve
    178  * information for. This includes locally configured addresses as well
    179  * as statically configured arp entries that are set up using the "permanent"
    180  * option described in arp(1m). The NCE_F_AUTHORITY asserts that we would
    181  * reject any updates for that nce's (host, link-layer-address) information
    182  */
    183 #define	NCE_F_AUTHORITY		0x800
    184 
    185 #define	NCE_F_DELAYED		0x1000 /* rescheduled on dad_defend_rate */
    186 #define	NCE_F_STATIC		0x2000
    187 
    188 /* State REACHABLE, STALE, DELAY or PROBE */
    189 #define	NCE_ISREACHABLE(ncec)			\
    190 	(((((ncec)->ncec_state) >= ND_REACHABLE) &&	\
    191 	((ncec)->ncec_state) <= ND_PROBE))
    192 
    193 #define	NCE_ISCONDEMNED(ncec)	((ncec)->ncec_flags & NCE_F_CONDEMNED)
    194 
    195 /* NDP flags set in SOL/ADV requests */
    196 #define	NDP_UNICAST		0x1
    197 #define	NDP_ISROUTER		0x2
    198 #define	NDP_SOLICITED		0x4
    199 #define	NDP_ORIDE		0x8
    200 #define	NDP_PROBE		0x10
    201 
    202 /* Number of packets queued in NDP for a neighbor */
    203 #define	ND_MAX_Q		4
    204 
    205 /*
    206  * Structure for nce_update_hw_changed;
    207  */
    208 typedef struct {
    209 	ipaddr_t hwm_addr;	/* IPv4 address */
    210 	uint_t	hwm_hwlen;	/* Length of hardware address (may be 0) */
    211 	uchar_t *hwm_hwaddr;	/* Pointer to new hardware address, if any */
    212 	int	hwm_flags;
    213 } nce_hw_map_t;
    214 
    215 /* When SAP is greater than zero address appears before SAP */
    216 #define	NCE_LL_ADDR_OFFSET(ill)	(((ill)->ill_sap_length) < 0 ? \
    217 	(sizeof (dl_unitdata_req_t)) : \
    218 	((sizeof (dl_unitdata_req_t)) + (ABS((ill)->ill_sap_length))))
    219 
    220 #define	NCE_LL_SAP_OFFSET(ill) (((ill)->ill_sap_length) < 0 ? \
    221 	((sizeof (dl_unitdata_req_t)) + ((ill)->ill_phys_addr_length)) : \
    222 	(sizeof (dl_unitdata_req_t)))
    223 
    224 #define	NCE_MYADDR(ncec)	(((ncec)->ncec_flags & NCE_F_MYADDR) != 0)
    225 
    226 /*
    227  * NCE_PUBLISH() identifies the addresses that we are publishing. This
    228  * includes locally configured address (NCE_MYADDR()) as well as those that
    229  * we are proxying.
    230  */
    231 #define	NCE_PUBLISH(ncec) ((ncec->ncec_flags & NCE_F_PUBLISH) != 0)
    232 
    233 #ifdef _BIG_ENDIAN
    234 #define	NCE_LL_SAP_COPY(ill, mp) \
    235 	{ \
    236 	size_t abs_sap_len = ABS((ill)->ill_sap_length); \
    237 	if (abs_sap_len > 0) { \
    238 		ASSERT(abs_sap_len <= sizeof (uint32_t)); \
    239 		ASSERT((mp)->b_rptr + NCE_LL_SAP_OFFSET(ill) + \
    240 		    abs_sap_len <= ((mp)->b_wptr)); \
    241 		bcopy((uint8_t *)&(ill)->ill_sap + sizeof (ill->ill_sap) - \
    242 		    abs_sap_len, \
    243 		    ((mp)->b_rptr + NCE_LL_SAP_OFFSET(ill)), \
    244 		    abs_sap_len); \
    245 	} \
    246 	}
    247 #else
    248 #define	NCE_LL_SAP_COPY(ill, mp) \
    249 	{ \
    250 	size_t abs_sap_len = ABS((ill)->ill_sap_length); \
    251 	if (abs_sap_len > 0) { \
    252 		uint32_t abs_sap_len = ABS((ill)->ill_sap_length); \
    253 		ASSERT(abs_sap_len <= sizeof (uint32_t)); \
    254 		ASSERT((mp)->b_rptr + NCE_LL_SAP_OFFSET(ill) + \
    255 		    abs_sap_len <= ((mp)->b_wptr)); \
    256 		bcopy(&((ill)->ill_sap), \
    257 		((mp)->b_rptr + NCE_LL_SAP_OFFSET(ill)), \
    258 		abs_sap_len); \
    259 	} \
    260 	}
    261 #endif
    262 
    263 /*
    264  * Exclusive-or the 6 bytes that are likely to contain the MAC
    265  * address. Assumes table_size does not exceed 256.
    266  * Assumes EUI-64 format for good hashing.
    267  */
    268 #define	NCE_ADDR_HASH_V6(addr, table_size)				\
    269 	(((addr).s6_addr8[8] ^ (addr).s6_addr8[9] ^			\
    270 	(addr).s6_addr8[10] ^ (addr).s6_addr8[13] ^			\
    271 	(addr).s6_addr8[14] ^ (addr).s6_addr8[15]) % (table_size))
    272 
    273 /* NDP Cache Entry Hash Table */
    274 #define	NCE_TABLE_SIZE	256
    275 
    276 extern	void	ip_nce_reclaim(void *);
    277 extern	void	ncec_delete(ncec_t *);
    278 extern	void	ncec_delete_per_ill(ncec_t *, uchar_t *);
    279 extern	void	nce_fastpath_update(ill_t *, mblk_t  *);
    280 extern	nd_opt_hdr_t *ndp_get_option(nd_opt_hdr_t *, int, int);
    281 extern	void	ncec_inactive(ncec_t *);
    282 extern	void	ndp_input(mblk_t *, ip_recv_attr_t *);
    283 extern	ncec_t	*ncec_lookup_illgrp_v6(ill_t *, const in6_addr_t *);
    284 extern	ncec_t	*ncec_lookup_illgrp_v4(ill_t *, const in_addr_t *);
    285 extern	nce_t	*nce_lookup_v4(ill_t *, const in_addr_t *);
    286 extern	nce_t	*nce_lookup_v6(ill_t *, const in6_addr_t *);
    287 extern	void	nce_make_unreachable(ncec_t *);
    288 extern	mblk_t	*ndp_mcastreq(ill_t *, const in6_addr_t *, uint32_t, uint32_t,
    289     mblk_t *);
    290 extern  nce_t	*ndp_nce_init(ill_t *, const in6_addr_t *, int);
    291 extern  void	nce_process(ncec_t *, uchar_t *, uint32_t, boolean_t);
    292 extern	int	ndp_query(ill_t *, lif_nd_req_t *);
    293 extern	int	ndp_sioc_update(ill_t *, lif_nd_req_t *);
    294 extern	boolean_t	ndp_verify_optlen(nd_opt_hdr_t *, int);
    295 extern	void	nce_timer(void *);
    296 extern	void	ncec_walk(ill_t *, pfi_t, void *, ip_stack_t *);
    297 extern	void	ncec_walk_common(ndp_g_t *, ill_t *, pfi_t,
    298     void *, boolean_t);
    299 extern	boolean_t	nce_restart_dad(ncec_t *);
    300 extern	void	ndp_resolv_failed(ncec_t *);
    301 extern	void	arp_resolv_failed(ncec_t *);
    302 extern	void	nce_fastpath_list_delete(ill_t *, ncec_t *, list_t *);
    303 extern	void	nce_queue_mp(ncec_t *, mblk_t *, boolean_t);
    304 extern	void	nce_update_hw_changed(ncec_t *, void *);
    305 extern	int	nce_lookup_then_add_v6(ill_t *, uchar_t *, uint_t,
    306     const in6_addr_t *, uint16_t, uint16_t, nce_t **);
    307 extern	int	nce_lookup_then_add_v4(ill_t *, uchar_t *, uint_t,
    308     const in_addr_t *, uint16_t, uint16_t, nce_t **);
    309 extern boolean_t nce_cmp_ll_addr(const ncec_t *, const uchar_t *, uint32_t);
    310 extern void	nce_update(ncec_t *, uint16_t, uchar_t *);
    311 extern nce_t   *nce_lookup_mapping(ill_t *, const in6_addr_t *);
    312 
    313 extern void	nce_restart_timer(ncec_t *, uint_t);
    314 extern void	ncec_refrele(ncec_t *);
    315 extern void	ncec_refhold(ncec_t *);
    316 extern void	ncec_refrele_notr(ncec_t *);
    317 extern void	ncec_refhold_notr(ncec_t *);
    318 extern void	nce_resolv_ok(ncec_t *);
    319 extern uint32_t	ndp_solicit(ncec_t *, in6_addr_t, ill_t *);
    320 extern boolean_t ip_nce_conflict(mblk_t *, ip_recv_attr_t *, ncec_t *);
    321 extern boolean_t ndp_announce(ncec_t *);
    322 extern void	ip_nce_lookup_and_update(ipaddr_t *, ipif_t *, ip_stack_t *,
    323     uchar_t *, int, int);
    324 extern void	nce_refrele(nce_t *);
    325 extern void	nce_refhold(nce_t *);
    326 extern void	nce_delete(nce_t *);
    327 extern void	nce_flush(ill_t *, boolean_t);
    328 extern void	nce_walk(ill_t *, pfi_t, void *);
    329 extern void	ip_ndp_resolve(struct ncec_s *);
    330 extern void	ip_addr_recover(ipsq_t *, queue_t *, mblk_t *, void *);
    331 
    332 #ifdef DEBUG
    333 extern	void	nce_trace_ref(ncec_t *);
    334 extern	void	nce_untrace_ref(ncec_t *);
    335 #endif
    336 
    337 #endif	/* _KERNEL */
    338 
    339 #ifdef	__cplusplus
    340 }
    341 #endif
    342 
    343 #endif	/* _INET_IP_NDP_H */
    344