#ifndef _INET_IP_NDP_H
#define _INET_IP_NDP_H
#include <sys/mutex.h>
#include <sys/stream.h>
#include <netinet/in.h>
#include <netinet/icmp6.h>
#include <inet/ip.h>
#include <inet/ip2mac.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _KERNEL
#define NCE_TABLE_SIZE 256
typedef struct ncec_cb_s {
list_node_t ncec_cb_node;
void *ncec_cb_id;
uint32_t ncec_cb_flags;
ip2mac_callback_t *ncec_cb_func;
void *ncec_cb_arg;
} ncec_cb_t;
#define NCE_CB_DISPATCHED 0x00000001
struct ncec_s {
struct ncec_s *ncec_next;
struct ncec_s **ncec_ptpn;
struct ill_s *ncec_ill;
uint16_t ncec_flags;
uint16_t ncec_state;
int16_t ncec_pcnt;
uint16_t ncec_rcnt;
in6_addr_t ncec_addr;
uchar_t *ncec_lladdr;
mblk_t *ncec_qd_mp;
uint64_t ncec_last;
uint32_t ncec_refcnt;
kmutex_t ncec_lock;
int ncec_unsolicit_count;
timeout_id_t ncec_timeout_id;
uchar_t ncec_ipversion;
uint_t ncec_defense_count;
clock_t ncec_last_time_defended;
uint64_t ncec_init_time;
boolean_t ncec_trace_disable;
clock_t ncec_xmit_interval;
ip_stack_t *ncec_ipst;
list_t ncec_cb;
uint_t ncec_cb_walker_cnt;
uint_t ncec_nprobes;
uint_t ncec_lladdr_length;
};
struct nce_s {
list_node_t nce_node;
ill_t *nce_ill;
boolean_t nce_is_condemned;
in6_addr_t nce_addr;
mblk_t *nce_dlur_mp;
mblk_t *nce_fp_mp;
struct ncec_s *nce_common;
kmutex_t nce_lock;
uint32_t nce_refcnt;
uint_t nce_ipif_cnt;
};
typedef struct ndp_g_s {
kmutex_t ndp_g_lock;
ncec_t *nce_hash_tbl[NCE_TABLE_SIZE];
int ndp_g_walker;
boolean_t ndp_g_walker_cleanup;
} ndp_g_t;
#define NCE_F_MYADDR 0x1
#define NCE_F_UNVERIFIED 0x2
#define NCE_F_ISROUTER 0x4
#define NCE_F_FAST 0x8
#define NCE_F_NONUD 0x10
#define NCE_F_ANYCAST 0x20
#define NCE_F_CONDEMNED 0x40
#define NCE_F_UNSOL_ADV 0x80
#define NCE_F_BCAST 0x100
#define NCE_F_MCAST 0x200
#define NCE_F_PUBLISH 0x400
#define NCE_F_AUTHORITY 0x800
#define NCE_F_DELAYED 0x1000
#define NCE_F_STATIC 0x2000
#define NCE_ISREACHABLE(ncec) \
(((((ncec)->ncec_state) >= ND_REACHABLE) && \
((ncec)->ncec_state) <= ND_PROBE))
#define NCE_ISCONDEMNED(ncec) ((ncec)->ncec_flags & NCE_F_CONDEMNED)
#define NDP_UNICAST 0x1
#define NDP_ISROUTER 0x2
#define NDP_SOLICITED 0x4
#define NDP_ORIDE 0x8
#define NDP_PROBE 0x10
#define ND_MAX_Q 4
typedef struct {
ipaddr_t hwm_addr;
uint_t hwm_hwlen;
uchar_t *hwm_hwaddr;
int hwm_flags;
} nce_hw_map_t;
#define NCE_LL_ADDR_OFFSET(ill) (((ill)->ill_sap_length) < 0 ? \
(sizeof (dl_unitdata_req_t)) : \
((sizeof (dl_unitdata_req_t)) + (ABS((ill)->ill_sap_length))))
#define NCE_LL_SAP_OFFSET(ill) (((ill)->ill_sap_length) < 0 ? \
((sizeof (dl_unitdata_req_t)) + ((ill)->ill_phys_addr_length)) : \
(sizeof (dl_unitdata_req_t)))
#define NCE_MYADDR(ncec) (((ncec)->ncec_flags & NCE_F_MYADDR) != 0)
#define NCE_PUBLISH(ncec) ((ncec->ncec_flags & NCE_F_PUBLISH) != 0)
#ifdef _BIG_ENDIAN
#define NCE_LL_SAP_COPY(ill, mp) \
{ \
size_t abs_sap_len = ABS((ill)->ill_sap_length); \
if (abs_sap_len > 0) { \
ASSERT(abs_sap_len <= sizeof (uint32_t)); \
ASSERT((mp)->b_rptr + NCE_LL_SAP_OFFSET(ill) + \
abs_sap_len <= ((mp)->b_wptr)); \
bcopy((uint8_t *)&(ill)->ill_sap + sizeof (ill->ill_sap) - \
abs_sap_len, \
((mp)->b_rptr + NCE_LL_SAP_OFFSET(ill)), \
abs_sap_len); \
} \
}
#else
#define NCE_LL_SAP_COPY(ill, mp) \
{ \
size_t abs_sap_len = ABS((ill)->ill_sap_length); \
if (abs_sap_len > 0) { \
uint32_t abs_sap_len = ABS((ill)->ill_sap_length); \
ASSERT(abs_sap_len <= sizeof (uint32_t)); \
ASSERT((mp)->b_rptr + NCE_LL_SAP_OFFSET(ill) + \
abs_sap_len <= ((mp)->b_wptr)); \
bcopy(&((ill)->ill_sap), \
((mp)->b_rptr + NCE_LL_SAP_OFFSET(ill)), \
abs_sap_len); \
} \
}
#endif
#define NCE_ADDR_HASH_V6(addr, table_size) \
(((addr).s6_addr8[8] ^ (addr).s6_addr8[9] ^ \
(addr).s6_addr8[10] ^ (addr).s6_addr8[13] ^ \
(addr).s6_addr8[14] ^ (addr).s6_addr8[15]) % (table_size))
#define NCE_TABLE_SIZE 256
typedef void (*ncec_walk_cb_t)(ncec_t *, void *);
extern void ip_nce_reclaim(void *);
extern void ncec_delete(ncec_t *);
extern void ncec_delete_per_ill(ncec_t *, void *);
extern void nce_fastpath_update(ill_t *, mblk_t *);
extern nd_opt_hdr_t *ndp_get_option(nd_opt_hdr_t *, int, int);
extern void ncec_inactive(ncec_t *);
extern void ndp_input(mblk_t *, ip_recv_attr_t *);
extern ncec_t *ncec_lookup_illgrp_v6(ill_t *, const in6_addr_t *);
extern ncec_t *ncec_lookup_illgrp_v4(ill_t *, const in_addr_t *);
extern nce_t *nce_lookup_v4(ill_t *, const in_addr_t *);
extern nce_t *nce_lookup_v6(ill_t *, const in6_addr_t *);
extern void nce_make_unreachable(ncec_t *);
extern mblk_t *ndp_mcastreq(ill_t *, const in6_addr_t *, uint32_t, uint32_t,
mblk_t *);
extern nce_t *ndp_nce_init(ill_t *, const in6_addr_t *, int);
extern void nce_process(ncec_t *, uchar_t *, uint32_t, boolean_t);
extern int ndp_query(ill_t *, lif_nd_req_t *);
extern int ndp_sioc_update(ill_t *, lif_nd_req_t *);
extern boolean_t ndp_verify_optlen(nd_opt_hdr_t *, int);
extern void nce_timer(void *);
extern void ncec_walk(ill_t *, ncec_walk_cb_t, void *, ip_stack_t *);
extern void ncec_walk_common(ndp_g_t *, ill_t *, ncec_walk_cb_t,
void *, boolean_t);
extern boolean_t nce_restart_dad(ncec_t *);
extern void ndp_resolv_failed(ncec_t *);
extern void arp_resolv_failed(ncec_t *);
extern void nce_fastpath_list_delete(ill_t *, ncec_t *, list_t *);
extern void nce_queue_mp(ncec_t *, mblk_t *, boolean_t);
extern void nce_update_hw_changed(ncec_t *, void *);
extern int nce_lookup_then_add_v6(ill_t *, uchar_t *, uint_t,
const in6_addr_t *, uint16_t, uint16_t, nce_t **);
extern int nce_lookup_then_add_v4(ill_t *, uchar_t *, uint_t,
const in_addr_t *, uint16_t, uint16_t, nce_t **);
extern boolean_t nce_cmp_ll_addr(const ncec_t *, const uchar_t *, uint32_t);
extern void nce_update(ncec_t *, uint16_t, uchar_t *);
extern nce_t *nce_lookup_mapping(ill_t *, const in6_addr_t *);
extern void nce_restart_timer(ncec_t *, uint_t);
extern void ncec_refrele(ncec_t *);
extern void ncec_refhold(ncec_t *);
extern void ncec_refrele_notr(ncec_t *);
extern void ncec_refhold_notr(ncec_t *);
extern void nce_resolv_ok(ncec_t *);
extern uint32_t ndp_solicit(ncec_t *, in6_addr_t, ill_t *);
extern boolean_t ip_nce_conflict(mblk_t *, ip_recv_attr_t *, ncec_t *);
extern boolean_t ndp_announce(ncec_t *);
extern void ip_nce_lookup_and_update(ipaddr_t *, ipif_t *, ip_stack_t *,
uchar_t *, int, int);
extern void nce_refrele(nce_t *);
extern void nce_refhold(nce_t *);
extern void nce_delete(nce_t *);
extern void nce_flush(ill_t *, boolean_t);
extern void nce_walk(ill_t *, pfi_t, void *);
extern void ip_ndp_resolve(struct ncec_s *);
extern void ip_addr_recover(ipsq_t *, queue_t *, mblk_t *, void *);
#ifdef DEBUG
extern void nce_trace_ref(ncec_t *);
extern void nce_untrace_ref(ncec_t *);
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif