Loading...
   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
/*
 * Copyright (c) 2000-2025 Apple Inc. All rights reserved.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
 *
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. The rights granted to you under the License
 * may not be used to create, or enable the creation or redistribution of,
 * unlawful or unlicensed copies of an Apple operating system, or to
 * circumvent, violate, or enable the circumvention or violation of, any
 * terms of an Apple operating system software license agreement.
 *
 * Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this file.
 *
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
 */
/*
 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the project nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef _NETINET6_ND6_H_
#define _NETINET6_ND6_H_

#include <sys/appleapiopts.h>
#include <sys/types.h>
#include <netinet/in.h>
#ifndef BSD_KERNEL_PRIVATE
#include <netinet6/in6_var.h>
#endif
#include <net/net_kev.h>

/* see net/route.h, or net/if_inarp.h */
#ifndef RTF_ANNOUNCE
#define RTF_ANNOUNCE    RTF_PROTO2
#endif

#include <sys/queue.h>

#ifdef BSD_KERNEL_PRIVATE
#include <net/flowadv.h>
#include <kern/locks.h>
#include <sys/tree.h>
#include <sys/eventhandler.h>
#include <netinet6/nd6_var.h>
#include <sys/sdt.h>
#include <net/if_var.h>

struct  llinfo_nd6 {
	/*
	 * The following are protected by rnh_lock
	 */
	struct  llinfo_nd6 *ln_next;
	struct  llinfo_nd6 *ln_prev;
	struct  rtentry *ln_rt;
	/*
	 * The following are protected by rt_lock
	 */
	struct ifnet *ln_exclifp; /* excluded interface (prefix proxy) */
	struct  mbuf *ln_hold;  /* last packet until resolved/timeout */
	uint32_t ln_asked;      /* # of queries already sent for this addr */
	short   ln_state;       /* reachability state */
	short   ln_router;      /* 2^0: ND6 router bit */
	u_int32_t ln_flags;     /* flags; see below */
	u_int64_t ln_expire;    /* lifetime for NDP state transition */
	u_int64_t ln_lastused;  /* last used timestamp */
	struct  if_llreach *ln_llreach; /* link-layer reachability record */
};

/* Values for ln_flags */
#define ND6_LNF_TIMER_SKIP      0x1     /* modified by nd6_timer() */
#define ND6_LNF_IN_USE          0x2     /* currently in llinfo_nd6 list */
#endif /* BSD_KERNEL_PRIVATE */

#define ND6_LLINFO_PURGE        -3
#define ND6_LLINFO_NOSTATE      -2
/*
 * We don't need the WAITDELETE state any more, but we keep the definition
 * in a comment line instead of removing it. This is necessary to avoid
 * unintentionally reusing the value for another purpose, which might
 * affect backward compatibility with old applications.
 * (20000711 jinmei@kame.net)
 */
/* #define	ND6_LLINFO_WAITDELETE	-1 */
#define ND6_LLINFO_INCOMPLETE   0
#define ND6_LLINFO_REACHABLE    1
#define ND6_LLINFO_STALE        2
#define ND6_LLINFO_DELAY        3
#define ND6_LLINFO_PROBE        4

#ifdef BSD_KERNEL_PRIVATE

#define ND6_CACHE_STATE_TRANSITION(ln, nstate) do {\
	DTRACE_IP2(nd6_state_transition, struct llinfo_nd6 *, (ln), int, (nstate));\
	if (nd6_debug >= 3) {\
	        struct rtentry *ln_rt = (ln) != NULL ? (ln)->ln_rt : NULL; \
	        nd6log3(info,\
	            "[%s:%d]: NDP cache entry changed from %s -> %s for address %s.\n",\
	            __func__,\
	            __LINE__,\
	            ndcache_state2str((ln)->ln_state),\
	            ndcache_state2str((nstate)),\
	            ln_rt != NULL ? ip6_sprintf(&SIN6(rt_key(ln_rt))->sin6_addr) : "N/A");\
	}\
	if ((ln) != NULL) {\
	        if ((ln)->ln_rt != NULL && (ln)->ln_rt->rt_ifp != NULL &&\
	            ((ln)->ln_rt->rt_ifp->if_eflags & IFEF_IPV6_ND6ALT) &&\
	            ((ln)->ln_state == ND6_LLINFO_REACHABLE)) {\
	                VERIFY((nstate) != ND6_LLINFO_STALE &&\
	                    (nstate) != ND6_LLINFO_DELAY &&\
	                    (nstate) != ND6_LLINFO_PROBE);\
	        }\
	        (ln)->ln_state = (nstate);\
	}\
} while(0)

#define ND6_IS_LLINFO_PROBREACH(n) ((n)->ln_state > ND6_LLINFO_INCOMPLETE)
#define ND6_LLINFO_PERMANENT(n) \
	(((n)->ln_expire == 0) && ((n)->ln_state > ND6_LLINFO_INCOMPLETE))

#define ND6_EUI64_GBIT  0x01
#define ND6_EUI64_UBIT  0x02

#define ND6_EUI64_TO_IFID(in6) \
	do {(in6)->s6_addr[8] ^= ND6_EUI64_UBIT; } while (0)

#define ND6_EUI64_GROUP(in6)            ((in6)->s6_addr[8] & ND6_EUI64_GBIT)
#define ND6_EUI64_INDIVIDUAL(in6)       (!ND6_EUI64_GROUP(in6))
#define ND6_EUI64_LOCAL(in6)            ((in6)->s6_addr[8] & ND6_EUI64_UBIT)
#define ND6_EUI64_UNIVERSAL(in6)        (!ND6_EUI64_LOCAL(in6))
#define ND6_IFID_LOCAL(in6)             (!ND6_EUI64_LOCAL(in6))
#define ND6_IFID_UNIVERSAL(in6)         (!ND6_EUI64_UNIVERSAL(in6))
#endif /* BSD_KERNEL_PRIVATE */

#if !defined(BSD_KERNEL_PRIVATE)
struct nd_ifinfo {
#else
/* For binary compatibility, this structure must not change */
/* NOTE: nd_ifinfo is defined in nd6_var.h */
struct nd_ifinfo_compat {
#endif /* !BSD_KERNEL_PRIVATE */
	u_int32_t linkmtu;              /* LinkMTU */
	u_int32_t maxmtu;               /* Upper bound of LinkMTU */
	u_int32_t basereachable;        /* BaseReachableTime */
	u_int32_t reachable;            /* Reachable Time */
	u_int32_t retrans;              /* Retrans Timer */
	u_int32_t flags;                /* Flags */
	int recalctm;                   /* BaseReacable re-calculation timer */
	u_int8_t chlim;                 /* CurHopLimit */
	u_int8_t receivedra;
	/* the following 3 members are for privacy extension for addrconf */
	u_int8_t randomseed0[8]; /* upper 64 bits of SHA256 digest */
	u_int8_t randomseed1[8]; /* lower 64 bits (usually the EUI64 IFID) */
	u_int8_t randomid[8];   /* current random ID */
};

#define ND6_IFF_PERFORMNUD              0x1
#if defined(PRIVATE)

/*
 * APPLE: not used. Interface specific router advertisements are handled with a
 * specific ifnet flag: IFEF_ACCEPT_RTADVD
 */
#define ND6_IFF_ACCEPT_RTADV            0x2

/* APPLE: NOT USED not related to ND. */
#define ND6_IFF_PREFER_SOURCE           0x4

/* IPv6 operation is disabled due to * DAD failure.  (XXX: not ND-specific) */
#define ND6_IFF_IFDISABLED              0x8

#define ND6_IFF_DONT_SET_IFROUTE        0x10 /* NOT USED */
#endif /* PRIVATE */
#define ND6_IFF_PROXY_PREFIXES          0x20
#define ND6_IFF_IGNORE_NA               0x40
#if defined(PRIVATE)
#define ND6_IFF_INSECURE                0x80
#endif
#define ND6_IFF_REPLICATED              0x100   /* sleep proxy registered */
#define ND6_IFF_DAD                     0x200   /* Perform DAD on the interface */

extern int dad_enhanced;
#define ND6_DAD_ENHANCED_DEFAULT        1

struct in6_nbrinfo {
	char ifname[IFNAMSIZ];  /* if name, e.g. "en0" */
	struct in6_addr addr;   /* IPv6 address of the neighbor */
	long    asked;          /* # of queries already sent for this addr */
	int     isrouter;       /* if it acts as a router */
	int     state;          /* reachability state */
	int     expire;         /* lifetime for NDP state transition */
};

#if defined(BSD_KERNEL_PRIVATE)
struct in6_nbrinfo_32 {
	char ifname[IFNAMSIZ];
	struct in6_addr addr;
	u_int32_t asked;
	int     isrouter;
	int     state;
	int     expire;
};

struct in6_nbrinfo_64 {
	char ifname[IFNAMSIZ];
	struct in6_addr addr;
	long    asked;
	int     isrouter        __attribute__((aligned(8)));
	int     state;
	int     expire;
} __attribute__((aligned(8)));
#endif /* BSD_KERNEL_PRIVATE */

#if defined(BSD_KERNEL_PRIVATE)
#define ND6_PROCESS_RTI_ENABLE    1
#define ND6_PROCESS_RTI_DISABLE   0
#define ND6_PROCESS_RTI_DEFAULT   ND6_PROCESS_RTI_ENABLE

extern int nd6_process_rti;

#endif /* BSD_KERNEL_PRIVATE */

/* valid values for stateflags */
#define NDDRF_INSTALLED 0x01     /* installed in the routing table */
#define NDDRF_IFSCOPE   0x02     /* installed as a scoped route */
#define NDDRF_STATIC    0x04     /* for internal use only */
#define NDDRF_MAPPED    0x08     /* Default router addr is mapped to a different one for routing */
#define NDDRF_INELIGIBLE     0x10     /* Default router entry is ineligible for default router selection */
#define NDDRF_LOCAL          0x20     /* Router's address is locally hosted as well */

struct  in6_defrouter {
	struct  sockaddr_in6 rtaddr;
	u_char  flags;
	u_char  stateflags;
	u_short rtlifetime;
	u_long  expire;
	u_short if_index;
};

#if defined(BSD_KERNEL_PRIVATE)
struct  in6_defrouter_32 {
	struct  sockaddr_in6 rtaddr;
	u_char  flags;
	u_char  stateflags;
	u_short rtlifetime;
	u_int32_t expire;
	u_short if_index;
};

struct  in6_defrouter_64 {
	struct  sockaddr_in6 rtaddr;
	u_char  flags;
	u_char  stateflags;
	u_short rtlifetime;
	u_long  expire          __attribute__((aligned(8)));
	u_short if_index        __attribute__((aligned(8)));
} __attribute__((aligned(8)));
#endif /* BSD_KERNEL_PRIVATE */

struct in6_prefix {
	struct  sockaddr_in6 prefix;
	struct prf_ra raflags;
	u_char  prefixlen;
	u_char  origin;
	u_long  vltime;
	u_long  pltime;
	u_long  expire;
	u_int32_t flags;
	int refcnt;
	u_short if_index;
	u_short advrtrs; /* number of advertisement routers */
	/* struct sockaddr_in6 advrtr[] */
};

#if defined(BSD_KERNEL_PRIVATE)
struct in6_prefix_32 {
	struct  sockaddr_in6 prefix;
	struct prf_ra raflags;
	u_char  prefixlen;
	u_char  origin;
	u_int32_t vltime;
	u_int32_t pltime;
	u_int32_t expire;
	u_int32_t flags;
	int refcnt;
	u_short if_index;
	u_short advrtrs; /* number of advertisement routers */
	/* struct sockaddr_in6 advrtr[] */
};

struct in6_prefix_64 {
	struct  sockaddr_in6 prefix;
	struct prf_ra raflags;
	u_char  prefixlen;
	u_char  origin;
	u_long  vltime  __attribute__((aligned(8)));
	u_long  pltime  __attribute__((aligned(8)));
	u_long  expire  __attribute__((aligned(8)));
	u_int32_t flags __attribute__((aligned(8)));
	int refcnt;
	u_short if_index;
	u_short advrtrs;
	/* struct sockaddr_in6 advrtr[] */
};
#endif /* BSD_KERNEL_PRIVATE */

struct  in6_ondireq {
	char ifname[IFNAMSIZ];
	struct {
		u_int32_t linkmtu;      /* LinkMTU */
		u_int32_t maxmtu;       /* Upper bound of LinkMTU */
		u_int32_t basereachable; /* BaseReachableTime */
		u_int32_t reachable;    /* Reachable Time */
		u_int32_t retrans;      /* Retrans Timer */
		u_int32_t flags;        /* Flags */
		int recalctm;           /* BaseReacable re-calculation timer */
		u_int8_t chlim;         /* CurHopLimit */
		/* Number of routers learned on the  interface */
		u_int8_t receivedra;
		/*
		 * The current collision count value
		 * being used for secure address generation.
		 */
		u_int8_t collision_count;
	} ndi;
};

#if !defined(BSD_KERNEL_PRIVATE)
struct  in6_ndireq {
	char ifname[IFNAMSIZ];
	struct nd_ifinfo ndi;
};
#else
struct  in6_ndireq {
	char ifname[IFNAMSIZ];
	struct nd_ifinfo_compat ndi;
};
#endif /* !BSD_KERNEL_PRIVATE */

struct  in6_ndifreq {
	char ifname[IFNAMSIZ];
	u_long ifindex;
};

#define MAX_RTR_SOLICITATION_DELAY      1       /* 1sec */
#define RTR_SOLICITATION_INTERVAL       4       /* 4sec */

#if defined(BSD_KERNEL_PRIVATE)
struct  in6_ndifreq_32 {
	char ifname[IFNAMSIZ];
	u_int32_t ifindex;
};

struct  in6_ndifreq_64 {
	char ifname[IFNAMSIZ];
	u_int64_t ifindex  __attribute__((aligned(8)));
};
#endif /* BSD_KERNEL_PRIVATE */

struct  in6_route_info {
	struct in6_addr prefix;
	u_int8_t prefixlen;
	u_short defrtrs; /* number of default routers */
	/* struct in6_defrouter defrtr[] */
} __attribute__((aligned(8)));

#if defined(BSD_KERNEL_PRIVATE)
struct  in6_route_info_32 {
	struct in6_addr prefix;
	u_int8_t prefixlen;
	u_short defrtrs; /* number of default routers */
	/* struct in6_defrouter defrtr[] */
};

struct  in6_route_info_64 {
	struct in6_addr prefix;
	u_int8_t prefixlen;
	u_short defrtrs; /* number of default routers */
	/* struct in6_defrouter defrtr[] */
} __attribute__((aligned(8)));
#endif /* BSD_KERNEL_PRIVATE */

/* Prefix status */
#define NDPRF_ONLINK            0x1
#define NDPRF_DETACHED          0x2
#define NDPRF_STATIC            0x100
#define NDPRF_IFSCOPE           0x1000
#define NDPRF_PRPROXY           0x2000
#ifdef BSD_KERNEL_PRIVATE
#define NDPRF_PROCESSED_ONLINK  0x08000
#define NDPRF_PROCESSED_SERVICE 0x10000
#define NDPRF_DEFUNCT           0x20000
#define NDPRF_CLAT46            0x40000

#define CLAT46_COLLISION_COUNT_OFFSET   128
#endif /* BSD_KERNEL_PRIVATE */

/* protocol constants */
#define MAX_RTR_SOLICITATION_DELAY      1       /* 1sec */
#define RTR_SOLICITATION_INTERVAL       4       /* 4sec */
#define MAX_RTR_SOLICITATIONS           3

#define ND6_INFINITE_LIFETIME           0xffffffff
#define ND6_MAX_LIFETIME                0x7fffffff

#ifdef BSD_KERNEL_PRIVATE
#define ND_IFINFO(ifp)                          \
    ((ifp == NULL) ? NULL :                     \
     ((IN6_IFEXTRA(ifp) == NULL) ? NULL :       \
      (&IN6_IFEXTRA(ifp)->nd_ifinfo)))

/*
 * In a more readable form, we derive linkmtu based on:
 *
 * if (ifp == NULL)
 *         linkmtu = IPV6_MMTU
 * else if (ND_IFINFO(ifp) == NULL || !ND_IFINFO(ifp)->initialized)
 *         linkmtu = ifp->if_mtu;
 * else if (ND_IFINFO(ifp)->linkmtu && ND_IFINFO(ifp)->linkmtu < ifp->if_mtu)
 *         linkmtu = ND_IFINFO(ifp)->linkmtu;
 * else if ((ND_IFINFO(ifp)->maxmtu && ND_IFINFO(ifp)->maxmtu < ifp->if_mtu))
 *         linkmtu = ND_IFINFO(ifp)->maxmtu;
 * else
 *         linkmtu = ifp->if_mtu;
 */
#define IN6_LINKMTU(ifp)                                                      \
	(ifp == NULL ? IPV6_MMTU :                                            \
	(ND_IFINFO(ifp) == NULL || !ND_IFINFO(ifp)->initialized) ?            \
	(ifp)->if_mtu :	((ND_IFINFO(ifp)->linkmtu &&                          \
	ND_IFINFO(ifp)->linkmtu < (ifp)->if_mtu) ? ND_IFINFO(ifp)->linkmtu :  \
	((ND_IFINFO(ifp)->maxmtu && ND_IFINFO(ifp)->maxmtu < (ifp)->if_mtu) ? \
	ND_IFINFO(ifp)->maxmtu : (ifp)->if_mtu)))

/* node constants */
#define MAX_REACHABLE_TIME              3600000 /* msec */
#define REACHABLE_TIME                  30000   /* msec */
#define RETRANS_TIMER                   1000    /* msec */
#define MAX_RA_RETRANS_TIMER            10000   /* msec */
#define MIN_RANDOM_FACTOR               512     /* 1024 * 0.5 */
#define MAX_RANDOM_FACTOR               1536    /* 1024 * 1.5 */
#define DEF_TEMP_VALID_LIFETIME         604800  /* 1 week */
#define DEF_TEMP_PREFERRED_LIFETIME     86400   /* 1 day */
#define TEMPADDR_REGEN_ADVANCE          5       /* sec */
#define MAX_TEMP_DESYNC_FACTOR          600     /* 10 min */
#define ND_COMPUTE_RTIME(x) \
	        (((MIN_RANDOM_FACTOR * (x >> 10)) + (RandomULong() & \
	        ((MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR) * (x >> 10)))) /1000)

#define IP6_USE_TMPADDR_DEFAULT         1
#define IP6_ULA_USE_TMPADDR_DEFAULT     0
/* prefix expiry times */
#define ND6_PREFIX_EXPIRY_UNSPEC        -1
#define ND6_PREFIX_EXPIRY_NEVER         0

TAILQ_HEAD(nd_drhead, nd_defrouter);
struct nd_defrouter {
	decl_lck_mtx_data(, nddr_lock);
	decl_lck_mtx_data(, nddr_ref_lock);
	TAILQ_ENTRY(nd_defrouter) dr_entry;
	struct in6_addr rtaddr;
	u_int32_t       nddr_refcount;
	u_int32_t       nddr_debug;
	u_int64_t       expire;
	u_int64_t       base_calendartime;      /* calendar time at creation */
	u_int64_t       base_uptime;            /* uptime at creation */
	u_char          flags;                  /* flags on RA message */
	u_char          stateflags;
	u_int32_t       rtlifetime;
	int             err;
	struct ifnet    *ifp;
	struct in6_addr rtaddr_mapped;          /* Mapped gateway address for routing */
	boolean_t       is_reachable;
	void (*nddr_trace)(struct nd_defrouter *, int); /* trace callback fn */
};

#define NDDR_LOCK_ASSERT_HELD(_nddr)                                    \
	LCK_MTX_ASSERT(&(_nddr)->nddr_lock, LCK_MTX_ASSERT_OWNED)

#define NDDR_LOCK_ASSERT_NOTHELD(_nddr)                                 \
	LCK_MTX_ASSERT(&(_nddr)->nddr_lock, LCK_MTX_ASSERT_NOTOWNED)

#define NDDR_LOCK(_nddr)                                                \
	lck_mtx_lock(&(_nddr)->nddr_lock)

#define NDDR_LOCK_SPIN(_nddr)                                           \
	lck_mtx_lock_spin(&(_nddr)->nddr_lock)

#define NDDR_CONVERT_LOCK(_nddr) do {                                   \
	NDPR_LOCK_ASSERT_HELD(_nddr);                                   \
	lck_mtx_convert_spin(&(_nddr)->nddr_lock);                      \
} while (0)

#define NDDR_UNLOCK(_nddr)                                              \
	lck_mtx_unlock(&(_nddr)->nddr_lock)

#define NDDR_REF_LOCK(_nddr)                                            \
	lck_mtx_lock(&(_nddr)->nddr_ref_lock)

#define NDDR_REF_LOCK_SPIN(_nddr)                                       \
	lck_mtx_lock_spin(&(_nddr)->nddr_ref_lock)

#define NDDR_REF_UNLOCK(_nddr)                                          \
	lck_mtx_unlock(&(_nddr)->nddr_ref_lock)

#define NDDR_ADDREF(_nddr)                                              \
	nddr_addref(_nddr)

#define NDDR_REMREF(_nddr)                                              \
	nddr_remref(_nddr)                                              \

TAILQ_HEAD(nd_rtihead, nd_route_info);
/*
 * The ordering below is important and it should always start
 * with nd_drhead as the first element.
 * It gets passed in as the generic nd_drhead to router management code.
 * The extra information stored here includes the prefix/prefix-length
 * which the router list belongs to.
 */
struct nd_route_info {
	struct nd_drhead nd_rti_router_list;
	TAILQ_ENTRY(nd_route_info) nd_rti_entry;
	struct in6_addr nd_rti_prefix;
	u_int8_t nd_rti_prefixlen;
};

struct nd_route_info *ndrti_alloc(void);
void nd6_rti_list_wait(const char *);
void nd6_rti_list_signal_done(void);
void ndrti_free(struct nd_route_info *rti);
void nd6_rtilist_remove(struct nd_route_info *);
void nd6_rtilist_update(struct nd_route_info *, struct nd_defrouter *);
int nd6_rtilist_add(struct nd_route_info *, struct nd_defrouter *,
    struct nd_route_info **);
void nd6_rti_purge(struct nd_route_info *);
void nd6_rti_delreq(struct nd_route_info *);
void nd6_rti_select(struct nd_route_info *, struct ifnet *);

/* define struct prproxy_sols_tree */
RB_HEAD(prproxy_sols_tree, nd6_prproxy_soltgt);

struct nd_prefix {
	decl_lck_mtx_data(, ndpr_lock);
	decl_lck_mtx_data(, ndpr_ref_lock);
	u_int32_t       ndpr_refcount;  /* reference count */
	u_int32_t       ndpr_debug;     /* see ifa_debug flags */
	struct ifnet     *ndpr_ifp;
	struct rtentry   *ndpr_rt;
	LIST_ENTRY(nd_prefix) ndpr_entry;
	struct sockaddr_in6 ndpr_prefix; /* prefix */
	struct in6_addr ndpr_mask; /* netmask derived from the prefix */
	struct in6_addr ndpr_addr; /* address that is derived from the prefix */
	u_int32_t       ndpr_vltime;    /* advertised valid lifetime */
	u_int32_t       ndpr_pltime;    /* advertised preferred lifetime */
	u_int64_t       ndpr_preferred; /* preferred time of the prefix */
	u_int64_t       ndpr_expire;    /* expiration time of the prefix */
	u_int64_t       ndpr_lastupdate; /* rx time of last advertisement */
	u_int64_t       ndpr_base_calendartime; /* calendar time at creation */
	u_int64_t       ndpr_base_uptime;       /* uptime at creation */
	struct prf_ra   ndpr_flags;
	unsigned int    ndpr_genid;     /* protects ndpr_advrtrs */
	u_int32_t       ndpr_stateflags; /* actual state flags */
	/* list of routers that advertise the prefix: */
	LIST_HEAD(pr_rtrhead, nd_pfxrouter) ndpr_advrtrs;
	u_char          ndpr_plen;
	int             ndpr_addrcnt;   /* reference counter from addresses */
	int             ndpr_manual_addrcnt; /* reference counter non-autoconf addresses */
	u_int32_t       ndpr_allmulti_cnt;      /* total all-multi reqs */
	u_int32_t       ndpr_prproxy_sols_cnt;  /* total # of proxied NS */
	struct prproxy_sols_tree ndpr_prproxy_sols; /* tree of proxied NS */
	void (*ndpr_trace)(struct nd_prefix *, int); /* trace callback fn */
};

#define ndpr_next               ndpr_entry.le_next

#define ndpr_raf                ndpr_flags
#define ndpr_raf_onlink         ndpr_flags.onlink
#define ndpr_raf_auto           ndpr_flags.autonomous
#define ndpr_raf_router         ndpr_flags.router
/*
 * We keep expired prefix for certain amount of time, for validation purposes.
 * 1800s = MaxRtrAdvInterval
 */
#define NDPR_KEEP_EXPIRED       (1800 * 2)

#define NDPR_LOCK_ASSERT_HELD(_ndpr)                                    \
	LCK_MTX_ASSERT(&(_ndpr)->ndpr_lock, LCK_MTX_ASSERT_OWNED)

#define NDPR_LOCK_ASSERT_NOTHELD(_ndpr)                                 \
	LCK_MTX_ASSERT(&(_ndpr)->ndpr_lock, LCK_MTX_ASSERT_NOTOWNED)

#define NDPR_LOCK(_ndpr)                                                \
	lck_mtx_lock(&(_ndpr)->ndpr_lock)

#define NDPR_LOCK_SPIN(_ndpr)                                           \
	lck_mtx_lock_spin(&(_ndpr)->ndpr_lock)

#define NDPR_CONVERT_LOCK(_ndpr) do {                                   \
	NDPR_LOCK_ASSERT_HELD(_ndpr);                                   \
	lck_mtx_convert_spin(&(_ndpr)->ndpr_lock);                      \
} while (0)

#define NDPR_UNLOCK(_ndpr)                                              \
	lck_mtx_unlock(&(_ndpr)->ndpr_lock)

#define NDPR_REF_LOCK(_ndpr)                                            \
	lck_mtx_lock(&(_ndpr)->ndpr_ref_lock)

#define NDPR_REF_LOCK_SPIN(_ndpr)                                       \
	lck_mtx_lock_spin(&(_ndpr)->ndpr_ref_lock)

#define NDPR_REF_UNLOCK(_ndpr)                                          \
	lck_mtx_unlock(&(_ndpr)->ndpr_ref_lock)

#define NDPR_ADDREF(_ndpr)                                              \
	ndpr_addref(_ndpr)

#define NDPR_REMREF(_ndpr)                                              \
	ndpr_remref(_ndpr)                                              \

/*
 * Message format for use in obtaining information about prefixes
 * from inet6 sysctl function
 */
struct inet6_ndpr_msghdr {
	u_short inpm_msglen;    /* to skip over non-understood messages */
	u_char  inpm_version;   /* future binary compatibility */
	u_char  inpm_type;      /* message type */
	struct in6_addr inpm_prefix;
	u_int32_t       prm_vltim;
	u_int32_t       prm_pltime;
	u_int32_t       prm_expire;
	u_int32_t       prm_preferred;
	struct in6_prflags prm_flags;
	u_short prm_index;      /* index for associated ifp */
	u_char  prm_plen;       /* length of prefix in bits */
};

#define prm_raf_onlink          prm_flags.prf_ra.onlink
#define prm_raf_auto            prm_flags.prf_ra.autonomous

#define prm_statef_onlink       prm_flags.prf_state.onlink

#define prm_rrf_decrvalid       prm_flags.prf_rr.decrvalid
#define prm_rrf_decrprefd       prm_flags.prf_rr.decrprefd

struct nd_pfxrouter {
	LIST_ENTRY(nd_pfxrouter) pfr_entry;
#define pfr_next pfr_entry.le_next
	struct nd_defrouter *router;
};

LIST_HEAD(nd_prhead, nd_prefix);

struct nd_prefix_list {
	struct nd_prefix_list *next;
	struct nd_prefix pr;
};
#endif /* BSD_KERNEL_PRIVATE */

#if defined(PRIVATE)
struct kev_nd6_ndfailure {
	struct net_event_data link_data;
};

struct kev_nd6_ndalive {
	struct net_event_data link_data;
};

struct nd6_ra_prefix {
	struct sockaddr_in6 prefix;
	struct prf_ra raflags;
	u_int32_t prefixlen;
	u_int32_t origin;
	u_int64_t vltime;
	u_int64_t pltime;
	u_int64_t expire;
	u_int32_t flags;
	u_int32_t refcnt;
	u_int32_t if_index;
	u_int32_t pad;
};

/* ND6 router advertisement valid bits */
#define KEV_ND6_DATA_VALID_MTU          (0x1 << 0)
#define KEV_ND6_DATA_VALID_PREFIX       (0x1 << 1)

struct kev_nd6_ra_data {
	u_int32_t mtu;
	u_int32_t list_index;
	u_int32_t list_length;
	u_int32_t flags;
	struct nd6_ra_prefix prefix;
	u_int32_t pad;
};

struct kev_nd6_event {
	struct net_event_data link_data;
	struct in6_addr in6_address;
	uint32_t val;
};

struct nd6_lookup_ipv6_args {
	char ifname[IFNAMSIZ];
	struct sockaddr_in6 ip6_dest;
	u_int32_t ll_dest_len;
	union {
		char buffer[256];
		struct sockaddr_dl _sdl;
	} ll_dest_;
};
#define ll_dest_sdl ll_dest_._sdl

#endif /* PRIVATE */

#if defined(BSD_KERNEL_PRIVATE)
/* nd6.c */
extern int nd6_prune;
extern int nd6_prune_lazy;
extern int nd6_delay;
extern int nd6_umaxtries;
extern int nd6_mmaxtries;
extern int nd6_useloopback;
extern int nd6_accept_6to4;
extern int nd6_maxnudhint;
extern int nd6_gctimer;
extern struct llinfo_nd6 llinfo_nd6;
extern struct nd_drhead nd_defrouter_list;
extern struct nd_rtihead nd_rti_list;
extern struct nd_prhead nd_prefix;
extern int nd6_debug;
extern int nd6_onlink_ns_rfc4861;
extern int nd6_optimistic_dad;

#include <os/log.h>

#define nd6log0(type, ...)      do { os_log_##type(OS_LOG_DEFAULT, ##__VA_ARGS__); } while (0)
#define nd6log(type, ...)       do { if (nd6_debug >= 1) os_log_##type(OS_LOG_DEFAULT, ##__VA_ARGS__); } while (0)
#define nd6log2(type, ...)      do { if (nd6_debug >= 2) os_log_##type(OS_LOG_DEFAULT, ##__VA_ARGS__); } while (0)
#define nd6log3(type, ...)      do { if (nd6_debug >= 3) os_log_##type(OS_LOG_DEFAULT, ##__VA_ARGS__); } while (0)
#define nd6log4(type, ...)      do { if (nd6_debug >= 4) os_log_##type(OS_LOG_DEFAULT, ##__VA_ARGS__); } while (0)

#define ND6_OPTIMISTIC_DAD_LINKLOCAL    (1 << 0)
#define ND6_OPTIMISTIC_DAD_AUTOCONF     (1 << 1)
#define ND6_OPTIMISTIC_DAD_TEMPORARY    (1 << 2)
#define ND6_OPTIMISTIC_DAD_DYNAMIC      (1 << 3)
#define ND6_OPTIMISTIC_DAD_SECURED      (1 << 4)
#define ND6_OPTIMISTIC_DAD_MANUAL       (1 << 5)

#define ND6_OPTIMISTIC_DAD_DEFAULT                                  \
	(ND6_OPTIMISTIC_DAD_LINKLOCAL | ND6_OPTIMISTIC_DAD_AUTOCONF |   \
	 ND6_OPTIMISTIC_DAD_TEMPORARY | ND6_OPTIMISTIC_DAD_DYNAMIC |    \
	 ND6_OPTIMISTIC_DAD_SECURED | ND6_OPTIMISTIC_DAD_MANUAL)

/* nd6_rtr.c */
extern int nd6_defifindex;
extern int ip6_desync_factor;   /* seconds */
/* ND6_INFINITE_LIFETIME does not apply to temporary addresses */
extern u_int32_t ip6_temp_preferred_lifetime; /* seconds */
extern u_int32_t ip6_temp_valid_lifetime; /* seconds */
extern int ip6_temp_regen_advance; /* seconds */

union nd_opts {
	struct nd_opt_hdr *nd_opt_array[26];    /* max = Route information option */
	struct {
		struct nd_opt_hdr *zero;
		struct nd_opt_hdr *src_lladdr;
		struct nd_opt_hdr *tgt_lladdr;
		struct nd_opt_prefix_info *pi_beg; /* multiple opts, start */
		struct nd_opt_rd_hdr *rh;
		struct nd_opt_mtu *mtu;
		struct nd_opt_hdr *__res6;
		struct nd_opt_hdr *__res7;
		struct nd_opt_hdr *__res8;
		struct nd_opt_hdr *__res9;
		struct nd_opt_hdr *__res10;
		struct nd_opt_hdr *__res11;
		struct nd_opt_hdr *__res12;
		struct nd_opt_hdr *__res13;
		struct nd_opt_nonce *nonce;
		struct nd_opt_hdr *__res15;
		struct nd_opt_hdr *__res16;
		struct nd_opt_hdr *__res17;
		struct nd_opt_hdr *__res18;
		struct nd_opt_hdr *__res19;
		struct nd_opt_hdr *__res20;
		struct nd_opt_hdr *__res21;
		struct nd_opt_hdr *__res22;
		struct nd_opt_hdr *__res23;
		struct nd_opt_route_info *rti_beg;
		struct nd_opt_hdr *__res25;
		struct nd_opt_hdr *__ended_by(last) search; /* multiple opts */
		struct nd_opt_hdr *last;                    /* multiple opts */
		uint8_t done;
		uint8_t initialized;
		struct nd_opt_prefix_info *pi_end; /* multiple prefix opts, end */
		struct nd_opt_route_info *rti_end; /* multiple route info opts, end */
	} nd_opt_each;
};
#define nd_opts_src_lladdr      nd_opt_each.src_lladdr
#define nd_opts_tgt_lladdr      nd_opt_each.tgt_lladdr
#define nd_opts_pi              nd_opt_each.pi_beg
#define nd_opts_pi_end          nd_opt_each.pi_end
#define nd_opts_rh              nd_opt_each.rh
#define nd_opts_mtu             nd_opt_each.mtu
#define nd_opts_nonce           nd_opt_each.nonce
#define nd_opts_rti             nd_opt_each.rti_beg
#define nd_opts_rti_end         nd_opt_each.rti_end
#define nd_opts_search          nd_opt_each.search
#define nd_opts_last            nd_opt_each.last
#define nd_opts_done            nd_opt_each.done
#define nd_opts_initialized     nd_opt_each.initialized

#define ND_OPT_LLADDR(opt, optlen, val, vallen) ({                                \
    (vallen) = opt->optlen << 3;                                                  \
    struct nd_opt_hdr* __hdr = __unsafe_forge_bidi_indexable(struct nd_opt_hdr *, \
    (opt), sizeof(struct nd_opt_hdr) + (vallen));                                 \
    (val) = (char *)(__hdr + 1);                                                  \
})

#if __has_ptrcheck
#define TAKE_ND_NEXT_OPT(opt, start, end) ({                                                          \
    size_t __ndoptlen = (u_char*)ndopts.end - (u_char*)ndopts.start;                                  \
    struct nd_opt_hdr* __hdr = __unsafe_forge_bidi_indexable(struct nd_opt_hdr *, (opt), __ndoptlen); \
    __hdr;                                                                                            \
})
#else
#define TAKE_ND_NEXT_OPT(opt, start, end) ({                                                          \
     (struct nd_opt_hdr *)opt;                                                                        \
})
#endif

/* XXX: need nd6_var.h?? */
/* nd6.c */
extern int nd6_sched_timeout_want;
extern void nd6_sched_timeout(struct timeval *, struct timeval *);
extern void nd6_init(void);
extern void nd6_ifreset(struct ifnet *ifp);
extern void nd6_ifattach(struct ifnet *);
extern int nd6_is_addr_neighbor(struct sockaddr_in6 *, struct ifnet *, int);
extern void nd6_option_init(void *__sized_by(icmp6len), size_t icmp6len, union nd_opts *);
extern struct nd_opt_hdr *nd6_option(union nd_opts *);
extern int nd6_options(union nd_opts *);
extern struct rtentry *nd6_lookup(struct in6_addr *, int, struct ifnet *, int);
extern void nd6_setmtu(struct ifnet *);
extern void nd6_purge(struct ifnet *);
extern void nd6_free(struct rtentry *);
extern void nd6_nud_hint(struct rtentry *, struct in6_addr *, int);
extern int nd6_resolve(struct ifnet *, struct rtentry *,
    struct mbuf *, struct sockaddr *, u_char *);
extern void nd6_rtrequest(int, struct rtentry *, struct sockaddr *);
extern int nd6_ioctl(u_long cmd, caddr_t __counted_by(IOCPARM_LEN(cmd)), struct ifnet *);
extern void nd6_cache_lladdr(struct ifnet *, struct in6_addr *,
    char *lladdr __sized_by(lladdrlen), int lladdrlen,
    int, int, int *);
extern int nd6_output_list(struct ifnet *, struct ifnet *, struct mbuf *,
    struct sockaddr_in6 *, struct rtentry *, struct flowadv *);
extern int nd6_output(struct ifnet *, struct ifnet *, struct mbuf *,
    struct sockaddr_in6 *, struct rtentry *, struct flowadv *);
extern int nd6_need_cache(struct ifnet *);
extern void nd6_drain(void *);
extern void nd6_post_msg(u_int32_t, struct nd_prefix_list *, u_int32_t,
    u_int32_t);
extern int nd6_setifinfo(struct ifnet *, u_int32_t, u_int32_t);
extern const char *ndcache_state2str(short);
extern void ln_setexpire(struct llinfo_nd6 *, uint64_t);

/* nd6_nbr.c */
extern void nd6_nbr_init(void);
extern void nd6_na_input(struct mbuf *, int, int);
extern void nd6_na_output(struct ifnet *, const struct in6_addr *,
    const struct in6_addr *, u_int32_t, int, struct sockaddr *);
extern void nd6_ns_input(struct mbuf *, int, int);
extern void nd6_ns_output(struct ifnet *, const struct in6_addr *,
    const struct in6_addr *, struct llinfo_nd6 *,
    uint8_t *__counted_by(noncelen) nonce, size_t noncelen);

static inline caddr_t __header_indexable __stateful_pure
nd6_ifptomac(struct ifnet *ifp)
{
	switch (ifp->if_type) {
	case IFT_ARCNET:
	case IFT_ETHER:
	case IFT_IEEE8023ADLAG:
	case IFT_FDDI:
	case IFT_IEEE1394:
#ifdef IFT_L2VLAN
	case IFT_L2VLAN:
#endif
#ifdef IFT_IEEE80211
	case IFT_IEEE80211:
#endif
#ifdef IFT_CARP
	case IFT_CARP:
#endif
	case IFT_BRIDGE:
	case IFT_ISO88025:
		return (caddr_t)IF_LLADDR(ifp);
	default:
		return NULL;
	}
}

extern void nd6_dad_start(struct ifaddr *, int *);
extern void nd6_dad_stop(struct ifaddr *);
extern void nd6_llreach_alloc(struct rtentry *, struct ifnet *,
    void * __sized_by(alen), unsigned int alen, boolean_t);
extern void nd6_llreach_set_reachable(struct ifnet *, void *__sized_by(alen) addr, unsigned int alen);
extern void nd6_llreach_use(struct llinfo_nd6 *);
extern void nd6_alt_node_addr_decompose(struct ifnet *, struct sockaddr *,
    struct sockaddr_dl *, struct sockaddr_in6 *);
extern int nd6_alt_node_present(struct ifnet *, struct sockaddr_in6 *,
    struct sockaddr_dl *, int32_t, int, int);
extern int nd6_alt_node_absent(struct ifnet *, struct sockaddr_in6 *, struct sockaddr_dl *);

/* nd6_rtr.c */
extern struct in6_ifaddr *in6_pfx_newpersistaddr(struct nd_prefix *, int,
    int *, boolean_t, uint8_t);
extern void nd6_rtr_init(void);
extern void nd6_rs_input(struct mbuf *, int, int);
extern void nd6_ra_input(struct mbuf *, int, int);
extern void prelist_del(struct nd_prefix *);
extern struct nd_defrouter *defrtrlist_update(struct nd_defrouter *,
    struct nd_drhead *);
extern void defrouter_select(struct ifnet *, struct nd_drhead *);
extern void defrouter_reset(void);
extern int defrtrlist_ioctl(u_long cmd, caddr_t __sized_by(IOCPARM_LEN(cmd)));
extern void defrtrlist_del(struct nd_defrouter *, struct nd_drhead *);
extern int defrtrlist_add_static(struct nd_defrouter *);
extern int defrtrlist_del_static(struct nd_defrouter *);
extern void nd_prefix_busy_wait(void);
extern void nd_prefix_busy_signal(void);
extern void prelist_remove(struct nd_prefix *);
extern int prelist_update(struct nd_prefix *, struct nd_defrouter *,
    struct mbuf *, int);
extern int nd6_prelist_add(struct nd_prefix *, struct nd_defrouter *,
    struct nd_prefix **, boolean_t);
extern int nd6_prefix_onlink(struct nd_prefix *);
extern int nd6_prefix_onlink_scoped(struct nd_prefix *, unsigned int);
extern int nd6_prefix_offlink(struct nd_prefix *);
extern void pfxlist_onlink_check(bool);
extern void defrouter_set_reachability(struct in6_addr *, struct ifnet *, boolean_t);
extern struct nd_defrouter *defrouter_lookup(struct nd_drhead *,
    struct in6_addr *, struct ifnet *);
extern struct nd_pfxrouter *pfxrtr_lookup(struct nd_prefix *, struct nd_defrouter *);
extern struct nd_prefix *nd6_prefix_lookup(struct nd_prefix *, int);
extern int in6_init_prefix_ltimes(struct nd_prefix *ndpr);
extern void rt6_flush(struct in6_addr *, struct ifnet *);
extern int nd6_setdefaultiface(int);
extern int in6_tmpifadd(const struct in6_ifaddr *, int);
extern void nddr_addref(struct nd_defrouter *);
extern struct nd_defrouter *nddr_remref(struct nd_defrouter *);
extern uint64_t nddr_getexpire(struct nd_defrouter *);
extern void ndpr_addref(struct nd_prefix *);
extern struct nd_prefix *ndpr_remref(struct nd_prefix *);
extern uint64_t ndpr_getexpire(struct nd_prefix *);
extern void defrouter_delreq(struct nd_defrouter *, struct nd_route_info *);

/* nd6_prproxy.c */
struct ip6_hdr;
extern u_int32_t nd6_prproxy;
extern int nd6_if_prproxy(struct ifnet *, boolean_t);
extern void nd6_prproxy_prelist_update(struct nd_prefix *, struct nd_prefix *);
extern boolean_t nd6_prproxy_ifaddr(struct in6_ifaddr *);
extern void nd6_proxy_find_fwdroute(struct ifnet *, struct route_in6 *);
extern boolean_t nd6_prproxy_isours(struct mbuf *, struct ip6_hdr *,
    struct route_in6 *, unsigned int);
extern void nd6_prproxy_ns_output(struct ifnet *, struct ifnet *,
    struct in6_addr *, struct in6_addr *, struct llinfo_nd6 *);
extern void nd6_prproxy_ns_input(struct ifnet *, struct in6_addr *,
    char *__sized_by(lladdrlen) lladdr, int lladdrlen, struct in6_addr *,
    struct in6_addr *, uint8_t *__counted_by(noncelen) nonce, size_t noncelen);
extern void nd6_prproxy_na_input(struct ifnet *, struct in6_addr *,
    struct in6_addr *, struct in6_addr *, int);
extern void nd6_prproxy_sols_reap(struct nd_prefix *);
extern void nd6_prproxy_sols_prune(struct nd_prefix *, u_int32_t);
extern int nd6_if_disable(struct ifnet *, boolean_t);
void in6_ifaddr_set_dadprogress(struct in6_ifaddr *ia);
#endif /* BSD_KERNEL_PRIVATE */

#ifdef KERNEL

/*
 *	@function nd6_lookup_ipv6
 *	@discussion This function will check the routing table for a cached
 *		neighbor discovery entry or trigger an neighbor discovery query
 *		to resolve the IPv6 address to a link-layer address.
 *		nd entries are stored in the routing table. This function will
 *		lookup the IPv6 destination in the routing table. If the
 *		destination requires forwarding to a gateway, the route of the
 *		gateway will be looked up. The route entry is inspected to
 *		determine if the link layer destination address is known. If
 *		unknown, neighbor discovery will be used to resolve the entry.
 *	@param interface The interface the packet is being sent on.
 *	@param ip6_dest The IPv6 destination of the packet.
 *	@param ll_dest On output, the link-layer destination.
 *	@param ll_dest_len The length of the buffer for ll_dest.
 *	@param hint Any routing hint passed down from the protocol.
 *	@param packet The packet being transmitted.
 *	@result May return an error such as EHOSTDOWN or ENETUNREACH. If
 *		this function returns EJUSTRETURN, the packet has been queued
 *		and will be sent when the address is resolved. If any other
 *		value is returned, the caller is responsible for disposing of
 *		the packet.
 */
extern errno_t nd6_lookup_ipv6(ifnet_t interface,
    const struct sockaddr_in6 *ip6_dest, struct sockaddr_dl *ll_dest,
    size_t ll_dest_len, route_t hint, mbuf_t packet);

#endif /* KERNEL */

/* nd6_send.c */
#ifdef BSD_KERNEL_PRIVATE
/*
 * nd6_send_opmode
 *
 *      value	using CGA	tx SEND		rx SEND
 *   --------	---------	-------		-------
 *   DISABLED	       NO	     NO		     NO
 *      QUIET	      YES	     NO		     NO
 */
extern int nd6_send_opstate;

#define ND6_SEND_OPMODE_DISABLED        0
#define ND6_SEND_OPMODE_CGA_QUIET       1

#endif /* BSD_KERNEL_PRIVATE */
#endif /* _NETINET6_ND6_H_ */