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