| 1 | /*- |
| 2 | * SPDX-License-Identifier: BSD-3-Clause |
| 3 | * |
| 4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * Redistribution and use in source and binary forms, with or without |
| 8 | * modification, are permitted provided that the following conditions |
| 9 | * are met: |
| 10 | * 1. Redistributions of source code must retain the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer. |
| 12 | * 2. Redistributions in binary form must reproduce the above copyright |
| 13 | * notice, this list of conditions and the following disclaimer in the |
| 14 | * documentation and/or other materials provided with the distribution. |
| 15 | * 3. Neither the name of the project nor the names of its contributors |
| 16 | * may be used to endorse or promote products derived from this software |
| 17 | * without specific prior written permission. |
| 18 | * |
| 19 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND |
| 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
| 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 29 | * SUCH DAMAGE. |
| 30 | * |
| 31 | *	$KAME: in6_var.h,v 1.56 2001/03/29 05:34:31 itojun Exp $ |
| 32 | */ |
| 33 | |
| 34 | /*- |
| 35 | * Copyright (c) 1985, 1986, 1993 |
| 36 | *	The Regents of the University of California. All rights reserved. |
| 37 | * |
| 38 | * Redistribution and use in source and binary forms, with or without |
| 39 | * modification, are permitted provided that the following conditions |
| 40 | * are met: |
| 41 | * 1. Redistributions of source code must retain the above copyright |
| 42 | * notice, this list of conditions and the following disclaimer. |
| 43 | * 2. Redistributions in binary form must reproduce the above copyright |
| 44 | * notice, this list of conditions and the following disclaimer in the |
| 45 | * documentation and/or other materials provided with the distribution. |
| 46 | * 3. Neither the name of the University nor the names of its contributors |
| 47 | * may be used to endorse or promote products derived from this software |
| 48 | * without specific prior written permission. |
| 49 | * |
| 50 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
| 51 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 52 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 53 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
| 54 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 55 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 56 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 57 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 58 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 59 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 60 | * SUCH DAMAGE. |
| 61 | */ |
| 62 | |
| 63 | #ifndef _NETINET6_IN6_VAR_H_ |
| 64 | #define _NETINET6_IN6_VAR_H_ |
| 65 | |
| 66 | #include <sys/tree.h> |
| 67 | #include <sys/counter.h> |
| 68 | |
| 69 | #ifdef _KERNEL |
| 70 | #include <sys/fnv_hash.h> |
| 71 | #include <sys/libkern.h> |
| 72 | #endif |
| 73 | |
| 74 | /* |
| 75 | * Interface address, Internet version. One of these structures |
| 76 | * is allocated for each interface with an Internet address. |
| 77 | * The ifaddr structure contains the protocol-independent part |
| 78 | * of the structure and is assumed to be first. |
| 79 | */ |
| 80 | |
| 81 | /* |
| 82 | * pltime/vltime are just for future reference (required to implements 2 |
| 83 | * hour rule for hosts). they should never be modified by nd6_timeout or |
| 84 | * anywhere else. |
| 85 | *	userland -> kernel: accept pltime/vltime |
| 86 | *	kernel -> userland: throw up everything |
| 87 | *	in kernel: modify preferred/expire only |
| 88 | */ |
| 89 | struct in6_addrlifetime { |
| 90 | 	time_t ia6t_expire;	/* valid lifetime expiration time */ |
| 91 | 	time_t ia6t_preferred;	/* preferred lifetime expiration time */ |
| 92 | 	u_int32_t ia6t_vltime;	/* valid lifetime */ |
| 93 | 	u_int32_t ia6t_pltime;	/* prefix lifetime */ |
| 94 | }; |
| 95 | |
| 96 | struct nd_ifinfo; |
| 97 | struct scope6_id; |
| 98 | struct lltable; |
| 99 | struct mld_ifsoftc; |
| 100 | struct in6_multi; |
| 101 | |
| 102 | struct in6_ifextra { |
| 103 | 	counter_u64_t *in6_ifstat; |
| 104 | 	counter_u64_t *icmp6_ifstat; |
| 105 | 	struct nd_ifinfo *nd_ifinfo; |
| 106 | 	struct scope6_id *scope6_id; |
| 107 | 	struct lltable *lltable; |
| 108 | 	struct mld_ifsoftc *mld_ifinfo; |
| 109 | }; |
| 110 | |
| 111 | #define	LLTABLE6(ifp)	(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->lltable) |
| 112 | |
| 113 | #ifdef _KERNEL |
| 114 | |
| 115 | SLIST_HEAD(in6_multi_head, in6_multi); |
| 116 | MALLOC_DECLARE(M_IP6MADDR); |
| 117 | |
| 118 | struct in6_ifaddr { |
| 119 | 	struct	ifaddr ia_ifa;		/* protocol-independent info */ |
| 120 | #define	ia_ifp		ia_ifa.ifa_ifp |
| 121 | #define ia_flags	ia_ifa.ifa_flags |
| 122 | 	struct	sockaddr_in6 ia_addr;	/* interface address */ |
| 123 | 	struct	sockaddr_in6 ia_net;	/* network number of interface */ |
| 124 | 	struct	sockaddr_in6 ia_dstaddr; /* space for destination addr */ |
| 125 | 	struct	sockaddr_in6 ia_prefixmask; /* prefix mask */ |
| 126 | 	u_int32_t ia_plen;		/* prefix length */ |
| 127 | 	CK_STAILQ_ENTRY(in6_ifaddr)	ia_link;	/* list of IPv6 addresses */ |
| 128 | 	int	ia6_flags; |
| 129 | |
| 130 | 	struct in6_addrlifetime ia6_lifetime; |
| 131 | 	time_t	ia6_createtime; /* the creation time of this address, which is |
| 132 | 				 * currently used for temporary addresses only. |
| 133 | 				 */ |
| 134 | 	time_t	ia6_updatetime; |
| 135 | |
| 136 | 	/* back pointer to the ND prefix (for autoconfigured addresses only) */ |
| 137 | 	struct nd_prefix *ia6_ndpr; |
| 138 | |
| 139 | 	/* multicast addresses joined from the kernel */ |
| 140 | 	LIST_HEAD(, in6_multi_mship) ia6_memberships; |
| 141 | 	/* entry in bucket of inet6 addresses */ |
| 142 | 	CK_LIST_ENTRY(in6_ifaddr) ia6_hash; |
| 143 | }; |
| 144 | |
| 145 | /* List of in6_ifaddr's. */ |
| 146 | CK_STAILQ_HEAD(in6_ifaddrhead, in6_ifaddr); |
| 147 | CK_LIST_HEAD(in6_ifaddrlisthead, in6_ifaddr); |
| 148 | #endif	/* _KERNEL */ |
| 149 | |
| 150 | /* control structure to manage address selection policy */ |
| 151 | struct in6_addrpolicy { |
| 152 | 	struct sockaddr_in6 addr; /* prefix address */ |
| 153 | 	struct sockaddr_in6 addrmask; /* prefix mask */ |
| 154 | 	int preced;		/* precedence */ |
| 155 | 	int label;		/* matching label */ |
| 156 | 	u_quad_t use;		/* statistics */ |
| 157 | }; |
| 158 | |
| 159 | /* |
| 160 | * IPv6 interface statistics, as defined in RFC2465 Ipv6IfStatsEntry (p12). |
| 161 | */ |
| 162 | struct in6_ifstat { |
| 163 | 	uint64_t ifs6_in_receive;	/* # of total input datagram */ |
| 164 | 	uint64_t ifs6_in_hdrerr;	/* # of datagrams with invalid hdr */ |
| 165 | 	uint64_t ifs6_in_toobig;	/* # of datagrams exceeded MTU */ |
| 166 | 	uint64_t ifs6_in_noroute;	/* # of datagrams with no route */ |
| 167 | 	uint64_t ifs6_in_addrerr;	/* # of datagrams with invalid dst */ |
| 168 | 	uint64_t ifs6_in_protounknown;	/* # of datagrams with unknown proto */ |
| 169 | 					/* NOTE: increment on final dst if */ |
| 170 | 	uint64_t ifs6_in_truncated;	/* # of truncated datagrams */ |
| 171 | 	uint64_t ifs6_in_discard;	/* # of discarded datagrams */ |
| 172 | 					/* NOTE: fragment timeout is not here */ |
| 173 | 	uint64_t ifs6_in_deliver;	/* # of datagrams delivered to ULP */ |
| 174 | 					/* NOTE: increment on final dst if */ |
| 175 | 	uint64_t ifs6_out_forward;	/* # of datagrams forwarded */ |
| 176 | 					/* NOTE: increment on outgoing if */ |
| 177 | 	uint64_t ifs6_out_request;	/* # of outgoing datagrams from ULP */ |
| 178 | 					/* NOTE: does not include forwrads */ |
| 179 | 	uint64_t ifs6_out_discard;	/* # of discarded datagrams */ |
| 180 | 	uint64_t ifs6_out_fragok;	/* # of datagrams fragmented */ |
| 181 | 	uint64_t ifs6_out_fragfail;	/* # of datagrams failed on fragment */ |
| 182 | 	uint64_t ifs6_out_fragcreat;	/* # of fragment datagrams */ |
| 183 | 					/* NOTE: this is # after fragment */ |
| 184 | 	uint64_t ifs6_reass_reqd;	/* # of incoming fragmented packets */ |
| 185 | 					/* NOTE: increment on final dst if */ |
| 186 | 	uint64_t ifs6_reass_ok;		/* # of reassembled packets */ |
| 187 | 					/* NOTE: this is # after reass */ |
| 188 | 					/* NOTE: increment on final dst if */ |
| 189 | 	uint64_t ifs6_reass_fail;	/* # of reass failures */ |
| 190 | 					/* NOTE: may not be packet count */ |
| 191 | 					/* NOTE: increment on final dst if */ |
| 192 | 	uint64_t ifs6_in_mcast;		/* # of inbound multicast datagrams */ |
| 193 | 	uint64_t ifs6_out_mcast;	/* # of outbound multicast datagrams */ |
| 194 | }; |
| 195 | |
| 196 | /* |
| 197 | * ICMPv6 interface statistics, as defined in RFC2466 Ipv6IfIcmpEntry. |
| 198 | * XXX: I'm not sure if this file is the right place for this structure... |
| 199 | */ |
| 200 | struct icmp6_ifstat { |
| 201 | 	/* |
| 202 | 	 * Input statistics |
| 203 | 	 */ |
| 204 | 	/* ipv6IfIcmpInMsgs, total # of input messages */ |
| 205 | 	uint64_t ifs6_in_msg; |
| 206 | 	/* ipv6IfIcmpInErrors, # of input error messages */ |
| 207 | 	uint64_t ifs6_in_error; |
| 208 | 	/* ipv6IfIcmpInDestUnreachs, # of input dest unreach errors */ |
| 209 | 	uint64_t ifs6_in_dstunreach; |
| 210 | 	/* ipv6IfIcmpInAdminProhibs, # of input administratively prohibited errs */ |
| 211 | 	uint64_t ifs6_in_adminprohib; |
| 212 | 	/* ipv6IfIcmpInTimeExcds, # of input time exceeded errors */ |
| 213 | 	uint64_t ifs6_in_timeexceed; |
| 214 | 	/* ipv6IfIcmpInParmProblems, # of input parameter problem errors */ |
| 215 | 	uint64_t ifs6_in_paramprob; |
| 216 | 	/* ipv6IfIcmpInPktTooBigs, # of input packet too big errors */ |
| 217 | 	uint64_t ifs6_in_pkttoobig; |
| 218 | 	/* ipv6IfIcmpInEchos, # of input echo requests */ |
| 219 | 	uint64_t ifs6_in_echo; |
| 220 | 	/* ipv6IfIcmpInEchoReplies, # of input echo replies */ |
| 221 | 	uint64_t ifs6_in_echoreply; |
| 222 | 	/* ipv6IfIcmpInRouterSolicits, # of input router solicitations */ |
| 223 | 	uint64_t ifs6_in_routersolicit; |
| 224 | 	/* ipv6IfIcmpInRouterAdvertisements, # of input router advertisements */ |
| 225 | 	uint64_t ifs6_in_routeradvert; |
| 226 | 	/* ipv6IfIcmpInNeighborSolicits, # of input neighbor solicitations */ |
| 227 | 	uint64_t ifs6_in_neighborsolicit; |
| 228 | 	/* ipv6IfIcmpInNeighborAdvertisements, # of input neighbor advertisements */ |
| 229 | 	uint64_t ifs6_in_neighboradvert; |
| 230 | 	/* ipv6IfIcmpInRedirects, # of input redirects */ |
| 231 | 	uint64_t ifs6_in_redirect; |
| 232 | 	/* ipv6IfIcmpInGroupMembQueries, # of input MLD queries */ |
| 233 | 	uint64_t ifs6_in_mldquery; |
| 234 | 	/* ipv6IfIcmpInGroupMembResponses, # of input MLD reports */ |
| 235 | 	uint64_t ifs6_in_mldreport; |
| 236 | 	/* ipv6IfIcmpInGroupMembReductions, # of input MLD done */ |
| 237 | 	uint64_t ifs6_in_mlddone; |
| 238 | |
| 239 | 	/* |
| 240 | 	 * Output statistics. We should solve unresolved routing problem... |
| 241 | 	 */ |
| 242 | 	/* ipv6IfIcmpOutMsgs, total # of output messages */ |
| 243 | 	uint64_t ifs6_out_msg; |
| 244 | 	/* ipv6IfIcmpOutErrors, # of output error messages */ |
| 245 | 	uint64_t ifs6_out_error; |
| 246 | 	/* ipv6IfIcmpOutDestUnreachs, # of output dest unreach errors */ |
| 247 | 	uint64_t ifs6_out_dstunreach; |
| 248 | 	/* ipv6IfIcmpOutAdminProhibs, # of output administratively prohibited errs */ |
| 249 | 	uint64_t ifs6_out_adminprohib; |
| 250 | 	/* ipv6IfIcmpOutTimeExcds, # of output time exceeded errors */ |
| 251 | 	uint64_t ifs6_out_timeexceed; |
| 252 | 	/* ipv6IfIcmpOutParmProblems, # of output parameter problem errors */ |
| 253 | 	uint64_t ifs6_out_paramprob; |
| 254 | 	/* ipv6IfIcmpOutPktTooBigs, # of output packet too big errors */ |
| 255 | 	uint64_t ifs6_out_pkttoobig; |
| 256 | 	/* ipv6IfIcmpOutEchos, # of output echo requests */ |
| 257 | 	uint64_t ifs6_out_echo; |
| 258 | 	/* ipv6IfIcmpOutEchoReplies, # of output echo replies */ |
| 259 | 	uint64_t ifs6_out_echoreply; |
| 260 | 	/* ipv6IfIcmpOutRouterSolicits, # of output router solicitations */ |
| 261 | 	uint64_t ifs6_out_routersolicit; |
| 262 | 	/* ipv6IfIcmpOutRouterAdvertisements, # of output router advertisements */ |
| 263 | 	uint64_t ifs6_out_routeradvert; |
| 264 | 	/* ipv6IfIcmpOutNeighborSolicits, # of output neighbor solicitations */ |
| 265 | 	uint64_t ifs6_out_neighborsolicit; |
| 266 | 	/* ipv6IfIcmpOutNeighborAdvertisements, # of output neighbor advertisements */ |
| 267 | 	uint64_t ifs6_out_neighboradvert; |
| 268 | 	/* ipv6IfIcmpOutRedirects, # of output redirects */ |
| 269 | 	uint64_t ifs6_out_redirect; |
| 270 | 	/* ipv6IfIcmpOutGroupMembQueries, # of output MLD queries */ |
| 271 | 	uint64_t ifs6_out_mldquery; |
| 272 | 	/* ipv6IfIcmpOutGroupMembResponses, # of output MLD reports */ |
| 273 | 	uint64_t ifs6_out_mldreport; |
| 274 | 	/* ipv6IfIcmpOutGroupMembReductions, # of output MLD done */ |
| 275 | 	uint64_t ifs6_out_mlddone; |
| 276 | }; |
| 277 | |
| 278 | struct	in6_ifreq { |
| 279 | 	char	ifr_name[IFNAMSIZ]; |
| 280 | 	union { |
| 281 | 		struct	sockaddr_in6 ifru_addr; |
| 282 | 		struct	sockaddr_in6 ifru_dstaddr; |
| 283 | 		int	ifru_flags; |
| 284 | 		int	ifru_flags6; |
| 285 | 		int	ifru_metric; |
| 286 | 		caddr_t	ifru_data; |
| 287 | 		struct in6_addrlifetime ifru_lifetime; |
| 288 | 		struct in6_ifstat ifru_stat; |
| 289 | 		struct icmp6_ifstat ifru_icmp6stat; |
| 290 | 		u_int32_t ifru_scope_id[16]; |
| 291 | 	} ifr_ifru; |
| 292 | }; |
| 293 | |
| 294 | struct	in6_aliasreq { |
| 295 | 	char	ifra_name[IFNAMSIZ]; |
| 296 | 	struct	sockaddr_in6 ifra_addr; |
| 297 | 	struct	sockaddr_in6 ifra_dstaddr; |
| 298 | 	struct	sockaddr_in6 ifra_prefixmask; |
| 299 | 	int	ifra_flags; |
| 300 | 	struct in6_addrlifetime ifra_lifetime; |
| 301 | 	int	ifra_vhid; |
| 302 | }; |
| 303 | |
| 304 | /* pre-10.x compat */ |
| 305 | struct	oin6_aliasreq { |
| 306 | 	char	ifra_name[IFNAMSIZ]; |
| 307 | 	struct	sockaddr_in6 ifra_addr; |
| 308 | 	struct	sockaddr_in6 ifra_dstaddr; |
| 309 | 	struct	sockaddr_in6 ifra_prefixmask; |
| 310 | 	int	ifra_flags; |
| 311 | 	struct in6_addrlifetime ifra_lifetime; |
| 312 | }; |
| 313 | |
| 314 | /* prefix type macro */ |
| 315 | #define IN6_PREFIX_ND	1 |
| 316 | #define IN6_PREFIX_RR	2 |
| 317 | |
| 318 | /* |
| 319 | * prefix related flags passed between kernel(NDP related part) and |
| 320 | * user land command(ifconfig) and daemon(rtadvd). |
| 321 | */ |
| 322 | struct in6_prflags { |
| 323 | 	struct prf_ra { |
| 324 | 		u_char onlink : 1; |
| 325 | 		u_char autonomous : 1; |
| 326 | 		u_char reserved : 6; |
| 327 | 	} prf_ra; |
| 328 | 	u_char prf_reserved1; |
| 329 | 	u_short prf_reserved2; |
| 330 | 	/* want to put this on 4byte offset */ |
| 331 | 	struct prf_rr { |
| 332 | 		u_char decrvalid : 1; |
| 333 | 		u_char decrprefd : 1; |
| 334 | 		u_char reserved : 6; |
| 335 | 	} prf_rr; |
| 336 | 	u_char prf_reserved3; |
| 337 | 	u_short prf_reserved4; |
| 338 | }; |
| 339 | |
| 340 | struct in6_prefixreq { |
| 341 | 	char	ipr_name[IFNAMSIZ]; |
| 342 | 	u_char	ipr_origin; |
| 343 | 	u_char	ipr_plen; |
| 344 | 	u_int32_t ipr_vltime; |
| 345 | 	u_int32_t ipr_pltime; |
| 346 | 	struct in6_prflags ipr_flags; |
| 347 | 	struct	sockaddr_in6 ipr_prefix; |
| 348 | }; |
| 349 | |
| 350 | #define PR_ORIG_RA	0 |
| 351 | #define PR_ORIG_RR	1 |
| 352 | #define PR_ORIG_STATIC	2 |
| 353 | #define PR_ORIG_KERNEL	3 |
| 354 | |
| 355 | #define ipr_raf_onlink		ipr_flags.prf_ra.onlink |
| 356 | #define ipr_raf_auto		ipr_flags.prf_ra.autonomous |
| 357 | |
| 358 | #define ipr_statef_onlink	ipr_flags.prf_state.onlink |
| 359 | |
| 360 | #define ipr_rrf_decrvalid	ipr_flags.prf_rr.decrvalid |
| 361 | #define ipr_rrf_decrprefd	ipr_flags.prf_rr.decrprefd |
| 362 | |
| 363 | struct	in6_rrenumreq { |
| 364 | 	char	irr_name[IFNAMSIZ]; |
| 365 | 	u_char	irr_origin; |
| 366 | 	u_char	irr_m_len;	/* match len for matchprefix */ |
| 367 | 	u_char	irr_m_minlen;	/* minlen for matching prefix */ |
| 368 | 	u_char	irr_m_maxlen;	/* maxlen for matching prefix */ |
| 369 | 	u_char	irr_u_uselen;	/* uselen for adding prefix */ |
| 370 | 	u_char	irr_u_keeplen;	/* keeplen from matching prefix */ |
| 371 | 	struct irr_raflagmask { |
| 372 | 		u_char onlink : 1; |
| 373 | 		u_char autonomous : 1; |
| 374 | 		u_char reserved : 6; |
| 375 | 	} irr_raflagmask; |
| 376 | 	u_int32_t irr_vltime; |
| 377 | 	u_int32_t irr_pltime; |
| 378 | 	struct in6_prflags irr_flags; |
| 379 | 	struct	sockaddr_in6 irr_matchprefix; |
| 380 | 	struct	sockaddr_in6 irr_useprefix; |
| 381 | }; |
| 382 | |
| 383 | #define irr_raf_mask_onlink	irr_raflagmask.onlink |
| 384 | #define irr_raf_mask_auto	irr_raflagmask.autonomous |
| 385 | #define irr_raf_mask_reserved	irr_raflagmask.reserved |
| 386 | |
| 387 | #define irr_raf_onlink		irr_flags.prf_ra.onlink |
| 388 | #define irr_raf_auto		irr_flags.prf_ra.autonomous |
| 389 | |
| 390 | #define irr_statef_onlink	irr_flags.prf_state.onlink |
| 391 | |
| 392 | #define irr_rrf			irr_flags.prf_rr |
| 393 | #define irr_rrf_decrvalid	irr_flags.prf_rr.decrvalid |
| 394 | #define irr_rrf_decrprefd	irr_flags.prf_rr.decrprefd |
| 395 | |
| 396 | /* |
| 397 | * Given a pointer to an in6_ifaddr (ifaddr), |
| 398 | * return a pointer to the addr as a sockaddr_in6 |
| 399 | */ |
| 400 | #define IA6_IN6(ia)	(&((ia)->ia_addr.sin6_addr)) |
| 401 | #define IA6_DSTIN6(ia)	(&((ia)->ia_dstaddr.sin6_addr)) |
| 402 | #define IA6_MASKIN6(ia)	(&((ia)->ia_prefixmask.sin6_addr)) |
| 403 | #define IA6_SIN6(ia)	(&((ia)->ia_addr)) |
| 404 | #define IA6_DSTSIN6(ia)	(&((ia)->ia_dstaddr)) |
| 405 | #define IFA_IN6(x)	(&((struct sockaddr_in6 *)((x)->ifa_addr))->sin6_addr) |
| 406 | #define IFA_DSTIN6(x)	(&((struct sockaddr_in6 *)((x)->ifa_dstaddr))->sin6_addr) |
| 407 | #define IFA_MASKIN6(x)	(&((struct sockaddr_in6 *)((x)->ifa_netmask))->sin6_addr) |
| 408 | |
| 409 | #define IFPR_IN6(x)	(&((struct sockaddr_in6 *)((x)->ifpr_prefix))->sin6_addr) |
| 410 | |
| 411 | #ifdef _KERNEL |
| 412 | #define IN6_ARE_MASKED_ADDR_EQUAL(d, a, m)	(	\ |
| 413 | 	(((d)->s6_addr32[0] ^ (a)->s6_addr32[0]) & (m)->s6_addr32[0]) == 0 && \ |
| 414 | 	(((d)->s6_addr32[1] ^ (a)->s6_addr32[1]) & (m)->s6_addr32[1]) == 0 && \ |
| 415 | 	(((d)->s6_addr32[2] ^ (a)->s6_addr32[2]) & (m)->s6_addr32[2]) == 0 && \ |
| 416 | 	(((d)->s6_addr32[3] ^ (a)->s6_addr32[3]) & (m)->s6_addr32[3]) == 0 ) |
| 417 | #define IN6_MASK_ADDR(a, m)	do { \ |
| 418 | 	(a)->s6_addr32[0] &= (m)->s6_addr32[0]; \ |
| 419 | 	(a)->s6_addr32[1] &= (m)->s6_addr32[1]; \ |
| 420 | 	(a)->s6_addr32[2] &= (m)->s6_addr32[2]; \ |
| 421 | 	(a)->s6_addr32[3] &= (m)->s6_addr32[3]; \ |
| 422 | } while (0) |
| 423 | #endif |
| 424 | |
| 425 | #define SIOCSIFADDR_IN6		 _IOW('i', 12, struct in6_ifreq) |
| 426 | #define SIOCGIFADDR_IN6		_IOWR('i', 33, struct in6_ifreq) |
| 427 | |
| 428 | #ifdef _KERNEL |
| 429 | /* |
| 430 | * SIOCSxxx ioctls should be unused (see comments in in6.c), but |
| 431 | * we do not shift numbers for binary compatibility. |
| 432 | */ |
| 433 | #define SIOCSIFDSTADDR_IN6	 _IOW('i', 14, struct in6_ifreq) |
| 434 | #define SIOCSIFNETMASK_IN6	 _IOW('i', 22, struct in6_ifreq) |
| 435 | #endif |
| 436 | |
| 437 | #define SIOCGIFDSTADDR_IN6	_IOWR('i', 34, struct in6_ifreq) |
| 438 | #define SIOCGIFNETMASK_IN6	_IOWR('i', 37, struct in6_ifreq) |
| 439 | |
| 440 | #define SIOCDIFADDR_IN6		 _IOW('i', 25, struct in6_ifreq) |
| 441 | #define OSIOCAIFADDR_IN6	 _IOW('i', 26, struct oin6_aliasreq) |
| 442 | #define SIOCAIFADDR_IN6		 _IOW('i', 27, struct in6_aliasreq) |
| 443 | |
| 444 | #define SIOCSIFPHYADDR_IN6 _IOW('i', 70, struct in6_aliasreq) |
| 445 | #define	SIOCGIFPSRCADDR_IN6	_IOWR('i', 71, struct in6_ifreq) |
| 446 | #define	SIOCGIFPDSTADDR_IN6	_IOWR('i', 72, struct in6_ifreq) |
| 447 | |
| 448 | #define SIOCGIFAFLAG_IN6	_IOWR('i', 73, struct in6_ifreq) |
| 449 | |
| 450 | #ifdef _KERNEL |
| 451 | #define OSIOCGIFINFO_IN6	_IOWR('i', 76, struct in6_ondireq) |
| 452 | #endif |
| 453 | #define SIOCGIFINFO_IN6		_IOWR('i', 108, struct in6_ndireq) |
| 454 | #define SIOCSIFINFO_IN6		_IOWR('i', 109, struct in6_ndireq) |
| 455 | #define SIOCSNDFLUSH_IN6	_IOWR('i', 77, struct in6_ifreq) |
| 456 | #define SIOCGNBRINFO_IN6	_IOWR('i', 78, struct in6_nbrinfo) |
| 457 | #define SIOCSPFXFLUSH_IN6	_IOWR('i', 79, struct in6_ifreq) |
| 458 | #define SIOCSRTRFLUSH_IN6	_IOWR('i', 80, struct in6_ifreq) |
| 459 | |
| 460 | #define SIOCGIFALIFETIME_IN6	_IOWR('i', 81, struct in6_ifreq) |
| 461 | #define SIOCGIFSTAT_IN6		_IOWR('i', 83, struct in6_ifreq) |
| 462 | #define SIOCGIFSTAT_ICMP6	_IOWR('i', 84, struct in6_ifreq) |
| 463 | |
| 464 | #define SIOCSDEFIFACE_IN6	_IOWR('i', 85, struct in6_ndifreq) |
| 465 | #define SIOCGDEFIFACE_IN6	_IOWR('i', 86, struct in6_ndifreq) |
| 466 | |
| 467 | #define SIOCSIFINFO_FLAGS	_IOWR('i', 87, struct in6_ndireq) /* XXX */ |
| 468 | |
| 469 | #define SIOCSSCOPE6		_IOW('i', 88, struct in6_ifreq) |
| 470 | #define SIOCGSCOPE6		_IOWR('i', 89, struct in6_ifreq) |
| 471 | #define SIOCGSCOPE6DEF		_IOWR('i', 90, struct in6_ifreq) |
| 472 | |
| 473 | #define SIOCSIFPREFIX_IN6	_IOW('i', 100, struct in6_prefixreq) /* set */ |
| 474 | #define SIOCGIFPREFIX_IN6	_IOWR('i', 101, struct in6_prefixreq) /* get */ |
| 475 | #define SIOCDIFPREFIX_IN6	_IOW('i', 102, struct in6_prefixreq) /* del */ |
| 476 | #define SIOCAIFPREFIX_IN6	_IOW('i', 103, struct in6_rrenumreq) /* add */ |
| 477 | #define SIOCCIFPREFIX_IN6	_IOW('i', 104, \ |
| 478 | 				 struct in6_rrenumreq) /* change */ |
| 479 | #define SIOCSGIFPREFIX_IN6	_IOW('i', 105, \ |
| 480 | 				 struct in6_rrenumreq) /* set global */ |
| 481 | |
| 482 | #define SIOCGETSGCNT_IN6	_IOWR('u', 106, \ |
| 483 | 				 struct sioc_sg_req6) /* get s,g pkt cnt */ |
| 484 | #define SIOCGETMIFCNT_IN6	_IOWR('u', 107, \ |
| 485 | 				 struct sioc_mif_req6) /* get pkt cnt per if */ |
| 486 | |
| 487 | #define SIOCAADDRCTL_POLICY	_IOW('u', 108, struct in6_addrpolicy) |
| 488 | #define SIOCDADDRCTL_POLICY	_IOW('u', 109, struct in6_addrpolicy) |
| 489 | |
| 490 | #define IN6_IFF_ANYCAST		0x01	/* anycast address */ |
| 491 | #define IN6_IFF_TENTATIVE	0x02	/* tentative address */ |
| 492 | #define IN6_IFF_DUPLICATED	0x04	/* DAD detected duplicate */ |
| 493 | #define IN6_IFF_DETACHED	0x08	/* may be detached from the link */ |
| 494 | #define IN6_IFF_DEPRECATED	0x10	/* deprecated address */ |
| 495 | #define IN6_IFF_NODAD		0x20	/* don't perform DAD on this address |
| 496 | 					 * (obsolete) |
| 497 | 					 */ |
| 498 | #define IN6_IFF_AUTOCONF	0x40	/* autoconfigurable address. */ |
| 499 | #define IN6_IFF_TEMPORARY	0x80	/* temporary (anonymous) address. */ |
| 500 | #define	IN6_IFF_PREFER_SOURCE	0x0100	/* preferred address for SAS */ |
| 501 | |
| 502 | /* do not input/output */ |
| 503 | #define IN6_IFF_NOTREADY (IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED) |
| 504 | |
| 505 | #ifdef _KERNEL |
| 506 | #define IN6_ARE_SCOPE_CMP(a,b) ((a)-(b)) |
| 507 | #define IN6_ARE_SCOPE_EQUAL(a,b) ((a)==(b)) |
| 508 | #endif |
| 509 | |
| 510 | #ifdef _KERNEL |
| 511 | VNET_DECLARE(struct in6_ifaddrhead, in6_ifaddrhead); |
| 512 | VNET_DECLARE(struct in6_ifaddrlisthead *, in6_ifaddrhashtbl); |
| 513 | VNET_DECLARE(u_long, in6_ifaddrhmask); |
| 514 | #define	V_in6_ifaddrhead		VNET(in6_ifaddrhead) |
| 515 | #define	V_in6_ifaddrhashtbl		VNET(in6_ifaddrhashtbl) |
| 516 | #define	V_in6_ifaddrhmask		VNET(in6_ifaddrhmask) |
| 517 | |
| 518 | #define	IN6ADDR_NHASH_LOG2		8 |
| 519 | #define	IN6ADDR_NHASH			(1 << IN6ADDR_NHASH_LOG2) |
| 520 | #define	IN6ADDR_HASHVAL(x)		(in6_addrhash(x)) |
| 521 | #define	IN6ADDR_HASH(x) \ |
| 522 | (&V_in6_ifaddrhashtbl[IN6ADDR_HASHVAL(x) & V_in6_ifaddrhmask]) |
| 523 | |
| 524 | static __inline uint32_t |
| 525 | in6_addrhash(const struct in6_addr *in6) |
| 526 | { |
| 527 | 	uint32_t x; |
| 528 | |
| 529 | 	x = in6->s6_addr32[0] ^ in6->s6_addr32[1] ^ in6->s6_addr32[2] ^ |
| 530 | 	 in6->s6_addr32[3]; |
| 531 | 	return (fnv_32_buf(&x, sizeof(x), FNV1_32_INIT)); |
| 532 | } |
| 533 | |
| 534 | extern struct rmlock in6_ifaddr_lock; |
| 535 | #define	IN6_IFADDR_LOCK_ASSERT()	rm_assert(&in6_ifaddr_lock, RA_LOCKED) |
| 536 | #define	IN6_IFADDR_RLOCK(t)		rm_rlock(&in6_ifaddr_lock, (t)) |
| 537 | #define	IN6_IFADDR_RLOCK_ASSERT()	rm_assert(&in6_ifaddr_lock, RA_RLOCKED) |
| 538 | #define	IN6_IFADDR_RUNLOCK(t)		rm_runlock(&in6_ifaddr_lock, (t)) |
| 539 | #define	IN6_IFADDR_WLOCK()		rm_wlock(&in6_ifaddr_lock) |
| 540 | #define	IN6_IFADDR_WLOCK_ASSERT()	rm_assert(&in6_ifaddr_lock, RA_WLOCKED) |
| 541 | #define	IN6_IFADDR_WUNLOCK()		rm_wunlock(&in6_ifaddr_lock) |
| 542 | |
| 543 | #define in6_ifstat_inc(ifp, tag) \ |
| 544 | do {								\ |
| 545 | 	if (ifp)						\ |
| 546 | 		counter_u64_add(((struct in6_ifextra *)		\ |
| 547 | 		 ((ifp)->if_afdata[AF_INET6]))->in6_ifstat[	\ |
| 548 | 		 offsetof(struct in6_ifstat, tag) / sizeof(uint64_t)], 1);\ |
| 549 | } while (/*CONSTCOND*/ 0) |
| 550 | #endif /* _KERNEL */ |
| 551 | |
| 552 | /* |
| 553 | * IPv6 multicast MLD-layer source entry. |
| 554 | */ |
| 555 | struct ip6_msource { |
| 556 | 	RB_ENTRY(ip6_msource)	im6s_link;	/* RB tree links */ |
| 557 | 	struct in6_addr		im6s_addr; |
| 558 | 	struct im6s_st { |
| 559 | 		uint16_t	ex;		/* # of exclusive members */ |
| 560 | 		uint16_t	in;		/* # of inclusive members */ |
| 561 | 	}			im6s_st[2];	/* state at t0, t1 */ |
| 562 | 	uint8_t			im6s_stp;	/* pending query */ |
| 563 | }; |
| 564 | RB_HEAD(ip6_msource_tree, ip6_msource); |
| 565 | |
| 566 | /* |
| 567 | * IPv6 multicast PCB-layer source entry. |
| 568 | * |
| 569 | * NOTE: overlapping use of struct ip6_msource fields at start. |
| 570 | */ |
| 571 | struct in6_msource { |
| 572 | 	RB_ENTRY(ip6_msource)	im6s_link;	/* Common field */ |
| 573 | 	struct in6_addr		im6s_addr;	/* Common field */ |
| 574 | 	uint8_t			im6sl_st[2];	/* state before/at commit */ |
| 575 | }; |
| 576 | |
| 577 | #ifdef _KERNEL |
| 578 | /* |
| 579 | * IPv6 source tree comparison function. |
| 580 | * |
| 581 | * An ordered predicate is necessary; bcmp() is not documented to return |
| 582 | * an indication of order, memcmp() is, and is an ISO C99 requirement. |
| 583 | */ |
| 584 | static __inline int |
| 585 | ip6_msource_cmp(const struct ip6_msource *a, const struct ip6_msource *b) |
| 586 | { |
| 587 | |
| 588 | 	return (memcmp(&a->im6s_addr, &b->im6s_addr, sizeof(struct in6_addr))); |
| 589 | } |
| 590 | RB_PROTOTYPE(ip6_msource_tree, ip6_msource, im6s_link, ip6_msource_cmp); |
| 591 | |
| 592 | /* |
| 593 | * IPv6 multicast PCB-layer group filter descriptor. |
| 594 | */ |
| 595 | struct in6_mfilter { |
| 596 | 	struct ip6_msource_tree	im6f_sources; /* source list for (S,G) */ |
| 597 | 	u_long			im6f_nsrc; /* # of source entries */ |
| 598 | 	uint8_t			im6f_st[2]; /* state before/at commit */ |
| 599 | 	struct in6_multi *im6f_in6m; /* associated multicast address */ |
| 600 | 	STAILQ_ENTRY(in6_mfilter) im6f_entry; /* list entry */ |
| 601 | }; |
| 602 | |
| 603 | /* |
| 604 | * Helper types and functions for IPv4 multicast filters. |
| 605 | */ |
| 606 | STAILQ_HEAD(ip6_mfilter_head, in6_mfilter); |
| 607 | |
| 608 | struct in6_mfilter *ip6_mfilter_alloc(int mflags, int st0, int st1); |
| 609 | void ip6_mfilter_free(struct in6_mfilter *); |
| 610 | |
| 611 | static inline void |
| 612 | ip6_mfilter_init(struct ip6_mfilter_head *head) |
| 613 | { |
| 614 | |
| 615 | 	STAILQ_INIT(head); |
| 616 | } |
| 617 | |
| 618 | static inline struct in6_mfilter * |
| 619 | ip6_mfilter_first(const struct ip6_mfilter_head *head) |
| 620 | { |
| 621 | |
| 622 | 	return (STAILQ_FIRST(head)); |
| 623 | } |
| 624 | |
| 625 | static inline void |
| 626 | ip6_mfilter_insert(struct ip6_mfilter_head *head, struct in6_mfilter *imf) |
| 627 | { |
| 628 | |
| 629 | 	STAILQ_INSERT_TAIL(head, imf, im6f_entry); |
| 630 | } |
| 631 | |
| 632 | static inline void |
| 633 | ip6_mfilter_remove(struct ip6_mfilter_head *head, struct in6_mfilter *imf) |
| 634 | { |
| 635 | |
| 636 | 	STAILQ_REMOVE(head, imf, in6_mfilter, im6f_entry); |
| 637 | } |
| 638 | |
| 639 | #define	IP6_MFILTER_FOREACH(imf, head) \ |
| 640 | 	STAILQ_FOREACH(imf, head, im6f_entry) |
| 641 | |
| 642 | static inline size_t |
| 643 | ip6_mfilter_count(struct ip6_mfilter_head *head) |
| 644 | { |
| 645 | 	struct in6_mfilter *imf; |
| 646 | 	size_t num = 0; |
| 647 | |
| 648 | 	STAILQ_FOREACH(imf, head, im6f_entry) |
| 649 | 		num++; |
| 650 | 	return (num); |
| 651 | } |
| 652 | |
| 653 | /* |
| 654 | * Legacy KAME IPv6 multicast membership descriptor. |
| 655 | */ |
| 656 | struct in6_multi_mship { |
| 657 | 	struct	in6_multi *i6mm_maddr; |
| 658 | 	LIST_ENTRY(in6_multi_mship) i6mm_chain; |
| 659 | }; |
| 660 | |
| 661 | /* |
| 662 | * IPv6 group descriptor. |
| 663 | * |
| 664 | * For every entry on an ifnet's if_multiaddrs list which represents |
| 665 | * an IP multicast group, there is one of these structures. |
| 666 | * |
| 667 | * If any source filters are present, then a node will exist in the RB-tree |
| 668 | * to permit fast lookup by source whenever an operation takes place. |
| 669 | * This permits pre-order traversal when we issue reports. |
| 670 | * Source filter trees are kept separately from the socket layer to |
| 671 | * greatly simplify locking. |
| 672 | * |
| 673 | * When MLDv2 is active, in6m_timer is the response to group query timer. |
| 674 | * The state-change timer in6m_sctimer is separate; whenever state changes |
| 675 | * for the group the state change record is generated and transmitted, |
| 676 | * and kept if retransmissions are necessary. |
| 677 | * |
| 678 | * FUTURE: in6m_link is now only used when groups are being purged |
| 679 | * on a detaching ifnet. It could be demoted to a SLIST_ENTRY, but |
| 680 | * because it is at the very start of the struct, we can't do this |
| 681 | * w/o breaking the ABI for ifmcstat. |
| 682 | */ |
| 683 | struct in6_multi { |
| 684 | 	struct	in6_addr in6m_addr;	/* IPv6 multicast address */ |
| 685 | 	struct	ifnet *in6m_ifp;	/* back pointer to ifnet */ |
| 686 | 	struct	ifmultiaddr *in6m_ifma;	/* back pointer to ifmultiaddr */ |
| 687 | 	u_int	in6m_refcount;		/* reference count */ |
| 688 | 	u_int	in6m_state;		/* state of the membership */ |
| 689 | 	u_int	in6m_timer;		/* MLD6 listener report timer */ |
| 690 | |
| 691 | 	/* New fields for MLDv2 follow. */ |
| 692 | 	struct mld_ifsoftc	*in6m_mli;	/* MLD info */ |
| 693 | 	SLIST_ENTRY(in6_multi)	 in6m_nrele;	/* to-be-released by MLD */ |
| 694 | 	SLIST_ENTRY(in6_multi)	 in6m_defer;	/* deferred MLDv1 */ |
| 695 | 	struct ip6_msource_tree	 in6m_srcs;	/* tree of sources */ |
| 696 | 	u_long			 in6m_nsrc;	/* # of tree entries */ |
| 697 | |
| 698 | 	struct mbufq		 in6m_scq;	/* queue of pending |
| 699 | 						 * state-change packets */ |
| 700 | 	struct timeval		 in6m_lastgsrtv;	/* last G-S-R query */ |
| 701 | 	uint16_t		 in6m_sctimer;	/* state-change timer */ |
| 702 | 	uint16_t		 in6m_scrv;	/* state-change rexmit count */ |
| 703 | |
| 704 | 	/* |
| 705 | 	 * SSM state counters which track state at T0 (the time the last |
| 706 | 	 * state-change report's RV timer went to zero) and T1 |
| 707 | 	 * (time of pending report, i.e. now). |
| 708 | 	 * Used for computing MLDv2 state-change reports. Several refcounts |
| 709 | 	 * are maintained here to optimize for common use-cases. |
| 710 | 	 */ |
| 711 | 	struct in6m_st { |
| 712 | 		uint16_t	iss_fmode;	/* MLD filter mode */ |
| 713 | 		uint16_t	iss_asm;	/* # of ASM listeners */ |
| 714 | 		uint16_t	iss_ex;		/* # of exclusive members */ |
| 715 | 		uint16_t	iss_in;		/* # of inclusive members */ |
| 716 | 		uint16_t	iss_rec;	/* # of recorded sources */ |
| 717 | 	}			in6m_st[2];	/* state at t0, t1 */ |
| 718 | }; |
| 719 | |
| 720 | void in6m_disconnect_locked(struct in6_multi_head *inmh, struct in6_multi *inm); |
| 721 | |
| 722 | /* |
| 723 | * Helper function to derive the filter mode on a source entry |
| 724 | * from its internal counters. Predicates are: |
| 725 | * A source is only excluded if all listeners exclude it. |
| 726 | * A source is only included if no listeners exclude it, |
| 727 | * and at least one listener includes it. |
| 728 | * May be used by ifmcstat(8). |
| 729 | */ |
| 730 | static __inline uint8_t |
| 731 | im6s_get_mode(const struct in6_multi *inm, const struct ip6_msource *ims, |
| 732 | uint8_t t) |
| 733 | { |
| 734 | |
| 735 | 	t = !!t; |
| 736 | 	if (inm->in6m_st[t].iss_ex > 0 && |
| 737 | 	 inm->in6m_st[t].iss_ex == ims->im6s_st[t].ex) |
| 738 | 		return (MCAST_EXCLUDE); |
| 739 | 	else if (ims->im6s_st[t].in > 0 && ims->im6s_st[t].ex == 0) |
| 740 | 		return (MCAST_INCLUDE); |
| 741 | 	return (MCAST_UNDEFINED); |
| 742 | } |
| 743 | |
| 744 | /* |
| 745 | * Lock macros for IPv6 layer multicast address lists. IPv6 lock goes |
| 746 | * before link layer multicast locks in the lock order. In most cases, |
| 747 | * consumers of IN_*_MULTI() macros should acquire the locks before |
| 748 | * calling them; users of the in_{add,del}multi() functions should not. |
| 749 | */ |
| 750 | extern struct mtx in6_multi_list_mtx; |
| 751 | extern struct sx in6_multi_sx; |
| 752 | |
| 753 | #define	IN6_MULTI_LIST_LOCK()		mtx_lock(&in6_multi_list_mtx) |
| 754 | #define	IN6_MULTI_LIST_UNLOCK()	mtx_unlock(&in6_multi_list_mtx) |
| 755 | #define	IN6_MULTI_LIST_LOCK_ASSERT()	mtx_assert(&in6_multi_list_mtx, MA_OWNED) |
| 756 | #define	IN6_MULTI_LIST_UNLOCK_ASSERT() mtx_assert(&in6_multi_list_mtx, MA_NOTOWNED) |
| 757 | |
| 758 | #define	IN6_MULTI_LOCK()		sx_xlock(&in6_multi_sx) |
| 759 | #define	IN6_MULTI_UNLOCK()	sx_xunlock(&in6_multi_sx) |
| 760 | #define	IN6_MULTI_LOCK_ASSERT()	sx_assert(&in6_multi_sx, SA_XLOCKED) |
| 761 | #define	IN6_MULTI_UNLOCK_ASSERT() sx_assert(&in6_multi_sx, SA_XUNLOCKED) |
| 762 | |
| 763 | /* |
| 764 | * Get the in6_multi pointer from a ifmultiaddr. |
| 765 | * Returns NULL if ifmultiaddr is no longer valid. |
| 766 | */ |
| 767 | static __inline struct in6_multi * |
| 768 | in6m_ifmultiaddr_get_inm(struct ifmultiaddr *ifma) |
| 769 | { |
| 770 | |
| 771 | 	return ((ifma->ifma_addr->sa_family != AF_INET6 ||	 |
| 772 | 	 (ifma->ifma_flags & IFMA_F_ENQUEUED) == 0) ? NULL : |
| 773 | 	 ifma->ifma_protospec); |
| 774 | } |
| 775 | |
| 776 | struct in6_multi * |
| 777 | in6m_lookup_locked(struct ifnet *ifp, const struct in6_addr *mcaddr); |
| 778 | |
| 779 | /* |
| 780 | * Wrapper for in6m_lookup_locked(). |
| 781 | * |
| 782 | * SMPng: Assumes network epoch entered and that IN6_MULTI_LOCK() isn't held. |
| 783 | */ |
| 784 | static __inline struct in6_multi * |
| 785 | in6m_lookup(struct ifnet *ifp, const struct in6_addr *mcaddr) |
| 786 | { |
| 787 | 	struct in6_multi *inm; |
| 788 | |
| 789 | 	NET_EPOCH_ASSERT(); |
| 790 | |
| 791 | 	IN6_MULTI_LIST_LOCK(); |
| 792 | 	inm = in6m_lookup_locked(ifp, mcaddr); |
| 793 | 	IN6_MULTI_LIST_UNLOCK(); |
| 794 | |
| 795 | 	return (inm); |
| 796 | } |
| 797 | |
| 798 | /* Acquire an in6_multi record. */ |
| 799 | static __inline void |
| 800 | in6m_acquire_locked(struct in6_multi *inm) |
| 801 | { |
| 802 | |
| 803 | 	IN6_MULTI_LIST_LOCK_ASSERT(); |
| 804 | 	++inm->in6m_refcount; |
| 805 | } |
| 806 | |
| 807 | static __inline void |
| 808 | in6m_acquire(struct in6_multi *inm) |
| 809 | { |
| 810 | 	IN6_MULTI_LIST_LOCK(); |
| 811 | 	in6m_acquire_locked(inm); |
| 812 | 	IN6_MULTI_LIST_UNLOCK(); |
| 813 | } |
| 814 | |
| 815 | static __inline void |
| 816 | in6m_rele_locked(struct in6_multi_head *inmh, struct in6_multi *inm) |
| 817 | { |
| 818 | 	KASSERT(inm->in6m_refcount > 0, ("refcount == %d inm: %p", inm->in6m_refcount, inm)); |
| 819 | 	IN6_MULTI_LIST_LOCK_ASSERT(); |
| 820 | |
| 821 | 	if (--inm->in6m_refcount == 0) { |
| 822 | 		MPASS(inm->in6m_ifp == NULL); |
| 823 | 		inm->in6m_ifma->ifma_protospec = NULL; |
| 824 | 		MPASS(inm->in6m_ifma->ifma_llifma == NULL); |
| 825 | 		SLIST_INSERT_HEAD(inmh, inm, in6m_nrele); |
| 826 | 	} |
| 827 | } |
| 828 | |
| 829 | struct ip6_moptions; |
| 830 | struct sockopt; |
| 831 | struct inpcbinfo; |
| 832 | struct rib_head; |
| 833 | struct ucred; |
| 834 | |
| 835 | /* Multicast KPIs. */ |
| 836 | int	im6o_mc_filter(const struct ip6_moptions *, const struct ifnet *, |
| 837 | 	 const struct sockaddr *, const struct sockaddr *); |
| 838 | int in6_joingroup(struct ifnet *, const struct in6_addr *, |
| 839 | 	 struct in6_mfilter *, struct in6_multi **, int); |
| 840 | int	in6_leavegroup(struct in6_multi *, struct in6_mfilter *); |
| 841 | int	in6_leavegroup_locked(struct in6_multi *, struct in6_mfilter *); |
| 842 | void	in6m_clear_recorded(struct in6_multi *); |
| 843 | void	in6m_commit(struct in6_multi *); |
| 844 | void	in6m_print(const struct in6_multi *); |
| 845 | int	in6m_record_source(struct in6_multi *, const struct in6_addr *); |
| 846 | void	in6m_release_list_deferred(struct in6_multi_head *); |
| 847 | void	in6m_release_wait(void *); |
| 848 | void	ip6_freemoptions(struct ip6_moptions *); |
| 849 | int	ip6_getmoptions(struct inpcb *, struct sockopt *); |
| 850 | int	ip6_setmoptions(struct inpcb *, struct sockopt *); |
| 851 | |
| 852 | /* flags to in6_update_ifa */ |
| 853 | #define IN6_IFAUPDATE_DADDELAY	0x1 /* first time to configure an address */ |
| 854 | |
| 855 | int	in6_mask2len(struct in6_addr *, u_char *); |
| 856 | int	in6_control(struct socket *, u_long, void *, struct ifnet *, |
| 857 | 	struct thread *); |
| 858 | int	in6_control_ioctl(u_long, void *, struct ifnet *, struct ucred *); |
| 859 | int	in6_update_ifa(struct ifnet *, struct in6_aliasreq *, |
| 860 | 	struct in6_ifaddr *, int); |
| 861 | void	in6_prepare_ifra(struct in6_aliasreq *, const struct in6_addr *, |
| 862 | 	const struct in6_addr *); |
| 863 | int	in6_addifaddr(struct ifnet *, struct in6_aliasreq *, struct in6_ifaddr *); |
| 864 | void	in6_purgeaddr(struct ifaddr *); |
| 865 | void	in6_purgeifaddr(struct in6_ifaddr *); |
| 866 | int	in6if_do_dad(struct ifnet *); |
| 867 | void	in6_savemkludge(struct in6_ifaddr *); |
| 868 | void	*in6_domifattach(struct ifnet *); |
| 869 | void	in6_domifdetach(struct ifnet *, void *); |
| 870 | int	in6_domifmtu(struct ifnet *); |
| 871 | struct rib_head *in6_inithead(uint32_t fibnum); |
| 872 | void	in6_detachhead(struct rib_head *rh); |
| 873 | int	in6_if2idlen(struct ifnet *); |
| 874 | struct in6_ifaddr *in6ifa_ifpforlinklocal(struct ifnet *, int); |
| 875 | struct in6_ifaddr *in6ifa_ifpwithaddr(struct ifnet *, const struct in6_addr *); |
| 876 | struct in6_ifaddr *in6ifa_ifwithaddr(const struct in6_addr *, uint32_t, bool); |
| 877 | struct in6_ifaddr *in6ifa_llaonifp(struct ifnet *); |
| 878 | int	in6_addr2zoneid(struct ifnet *, struct in6_addr *, u_int32_t *); |
| 879 | int	in6_matchlen(struct in6_addr *, struct in6_addr *); |
| 880 | int	in6_are_prefix_equal(struct in6_addr *, struct in6_addr *, int); |
| 881 | void	in6_prefixlen2mask(struct in6_addr *, int); |
| 882 | int	in6_prefix_ioctl(struct socket *, u_long, caddr_t, |
| 883 | 	struct ifnet *); |
| 884 | int	in6_prefix_add_ifid(int, struct in6_ifaddr *); |
| 885 | void	in6_prefix_remove_ifid(int, struct in6_ifaddr *); |
| 886 | void	in6_purgeprefix(struct ifnet *); |
| 887 | |
| 888 | int	in6_is_addr_deprecated(struct sockaddr_in6 *); |
| 889 | int	in6_src_ioctl(u_long, caddr_t); |
| 890 | |
| 891 | void	in6_newaddrmsg(struct in6_ifaddr *, int); |
| 892 | |
| 893 | void	in6_purge_proxy_ndp(struct ifnet *); |
| 894 | /* |
| 895 | * Extended API for IPv6 FIB support. |
| 896 | */ |
| 897 | struct mbuf *ip6_tryforward(struct mbuf *); |
| 898 | #endif /* _KERNEL */ |
| 899 | |
| 900 | #endif /* _NETINET6_IN6_VAR_H_ */ |