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 typedef void (*ncec_walk_cb_t)(ncec_t *, void *); 277 278 extern void ip_nce_reclaim(void *); 279 extern void ncec_delete(ncec_t *); 280 extern void ncec_delete_per_ill(ncec_t *, void *); 281 extern void nce_fastpath_update(ill_t *, mblk_t *); 282 extern nd_opt_hdr_t *ndp_get_option(nd_opt_hdr_t *, int, int); 283 extern void ncec_inactive(ncec_t *); 284 extern void ndp_input(mblk_t *, ip_recv_attr_t *); 285 extern ncec_t *ncec_lookup_illgrp_v6(ill_t *, const in6_addr_t *); 286 extern ncec_t *ncec_lookup_illgrp_v4(ill_t *, const in_addr_t *); 287 extern nce_t *nce_lookup_v4(ill_t *, const in_addr_t *); 288 extern nce_t *nce_lookup_v6(ill_t *, const in6_addr_t *); 289 extern void nce_make_unreachable(ncec_t *); 290 extern mblk_t *ndp_mcastreq(ill_t *, const in6_addr_t *, uint32_t, uint32_t, 291 mblk_t *); 292 extern nce_t *ndp_nce_init(ill_t *, const in6_addr_t *, int); 293 extern void nce_process(ncec_t *, uchar_t *, uint32_t, boolean_t); 294 extern int ndp_query(ill_t *, lif_nd_req_t *); 295 extern int ndp_sioc_update(ill_t *, lif_nd_req_t *); 296 extern boolean_t ndp_verify_optlen(nd_opt_hdr_t *, int); 297 extern void nce_timer(void *); 298 extern void ncec_walk(ill_t *, ncec_walk_cb_t, void *, ip_stack_t *); 299 extern void ncec_walk_common(ndp_g_t *, ill_t *, ncec_walk_cb_t, 300 void *, boolean_t); 301 extern boolean_t nce_restart_dad(ncec_t *); 302 extern void ndp_resolv_failed(ncec_t *); 303 extern void arp_resolv_failed(ncec_t *); 304 extern void nce_fastpath_list_delete(ill_t *, ncec_t *, list_t *); 305 extern void nce_queue_mp(ncec_t *, mblk_t *, boolean_t); 306 extern void nce_update_hw_changed(ncec_t *, void *); 307 extern int nce_lookup_then_add_v6(ill_t *, uchar_t *, uint_t, 308 const in6_addr_t *, uint16_t, uint16_t, nce_t **); 309 extern int nce_lookup_then_add_v4(ill_t *, uchar_t *, uint_t, 310 const in_addr_t *, uint16_t, uint16_t, nce_t **); 311 extern boolean_t nce_cmp_ll_addr(const ncec_t *, const uchar_t *, uint32_t); 312 extern void nce_update(ncec_t *, uint16_t, uchar_t *); 313 extern nce_t *nce_lookup_mapping(ill_t *, const in6_addr_t *); 314 315 extern void nce_restart_timer(ncec_t *, uint_t); 316 extern void ncec_refrele(ncec_t *); 317 extern void ncec_refhold(ncec_t *); 318 extern void ncec_refrele_notr(ncec_t *); 319 extern void ncec_refhold_notr(ncec_t *); 320 extern void nce_resolv_ok(ncec_t *); 321 extern uint32_t ndp_solicit(ncec_t *, in6_addr_t, ill_t *); 322 extern boolean_t ip_nce_conflict(mblk_t *, ip_recv_attr_t *, ncec_t *); 323 extern boolean_t ndp_announce(ncec_t *); 324 extern void ip_nce_lookup_and_update(ipaddr_t *, ipif_t *, ip_stack_t *, 325 uchar_t *, int, int); 326 extern void nce_refrele(nce_t *); 327 extern void nce_refhold(nce_t *); 328 extern void nce_delete(nce_t *); 329 extern void nce_flush(ill_t *, boolean_t); 330 extern void nce_walk(ill_t *, pfi_t, void *); 331 extern void ip_ndp_resolve(struct ncec_s *); 332 extern void ip_addr_recover(ipsq_t *, queue_t *, mblk_t *, void *); 333 334 #ifdef DEBUG 335 extern void nce_trace_ref(ncec_t *); 336 extern void nce_untrace_ref(ncec_t *); 337 #endif 338 339 #endif /* _KERNEL */ 340 341 #ifdef __cplusplus 342 } 343 #endif 344 345 #endif /* _INET_IP_NDP_H */ 346