1/*- 2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 44 unchanged lines hidden (view full) --- 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * @(#)in_var.h 8.1 (Berkeley) 6/10/93 |
61 * $FreeBSD: head/sys/netinet6/in6_var.h 191672 2009-04-29 19:19:13Z bms $ |
62 */ 63 64#ifndef _NETINET6_IN6_VAR_H_ 65#define _NETINET6_IN6_VAR_H_ 66 |
67#include <sys/tree.h> 68 69#ifdef _KERNEL 70#include <sys/libkern.h> 71#endif 72 |
73/* 74 * Interface address, Internet version. One of these structures 75 * is allocated for each interface with an Internet address. 76 * The ifaddr structure contains the protocol-independent part 77 * of the structure and is assumed to be first. 78 */ 79 80/* --- 9 unchanged lines hidden (view full) --- 90 time_t ia6t_preferred; /* preferred lifetime expiration time */ 91 u_int32_t ia6t_vltime; /* valid lifetime */ 92 u_int32_t ia6t_pltime; /* prefix lifetime */ 93}; 94 95struct nd_ifinfo; 96struct scope6_id; 97struct lltable; |
98struct mld_ifinfo; 99 |
100struct in6_ifextra { 101 struct in6_ifstat *in6_ifstat; 102 struct icmp6_ifstat *icmp6_ifstat; 103 struct nd_ifinfo *nd_ifinfo; 104 struct scope6_id *scope6_id; 105 struct lltable *lltable; |
106 struct mld_ifinfo *mld_ifinfo; |
107}; 108 109#define LLTABLE6(ifp) (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->lltable) 110 111struct in6_ifaddr { 112 struct ifaddr ia_ifa; /* protocol-independent info */ 113#define ia_ifp ia_ifa.ifa_ifp 114#define ia_flags ia_ifa.ifa_flags --- 378 unchanged lines hidden (view full) --- 493#define in6_ifstat_inc(ifp, tag) \ 494do { \ 495 if (ifp) \ 496 ((struct in6_ifextra *)((ifp)->if_afdata[AF_INET6]))->in6_ifstat->tag++; \ 497} while (/*CONSTCOND*/ 0) 498 499extern struct in6_addr zeroin6_addr; 500extern u_char inet6ctlerrmap[]; |
501 502/* 503 * Macro for finding the internet address structure (in6_ifaddr) corresponding 504 * to a given interface (ifnet structure). 505 */ 506 507#define IFP_TO_IA6(ifp, ia) \ 508/* struct ifnet *ifp; */ \ --- 6 unchanged lines hidden (view full) --- 515 break; \ 516 } \ 517 (ia) = (struct in6_ifaddr *)ifa; \ 518} while (/*CONSTCOND*/ 0) 519 520#endif /* _KERNEL */ 521 522/* |
523 * IPv6 multicast MLD-layer source entry. |
524 */ |
525struct ip6_msource { 526 RB_ENTRY(ip6_msource) im6s_link; /* RB tree links */ 527 struct in6_addr im6s_addr; 528 struct im6s_st { 529 uint16_t ex; /* # of exclusive members */ 530 uint16_t in; /* # of inclusive members */ 531 } im6s_st[2]; /* state at t0, t1 */ 532 uint8_t im6s_stp; /* pending query */ 533}; 534RB_HEAD(ip6_msource_tree, ip6_msource); 535 536/* 537 * IPv6 multicast PCB-layer source entry. 538 * 539 * NOTE: overlapping use of struct ip6_msource fields at start. 540 */ 541struct in6_msource { 542 RB_ENTRY(ip6_msource) im6s_link; /* Common field */ 543 struct in6_addr im6s_addr; /* Common field */ 544 uint8_t im6sl_st[2]; /* state before/at commit */ 545}; 546 547#ifdef _KERNEL 548/* 549 * IPv6 source tree comparison function. 550 * 551 * An ordered predicate is necessary; bcmp() is not documented to return 552 * an indication of order, memcmp() is, and is an ISO C99 requirement. 553 */ 554static __inline int 555ip6_msource_cmp(const struct ip6_msource *a, const struct ip6_msource *b) 556{ 557 558 return (memcmp(&a->im6s_addr, &b->im6s_addr, sizeof(struct in6_addr))); 559} 560RB_PROTOTYPE(ip6_msource_tree, ip6_msource, im6s_link, ip6_msource_cmp); 561#endif /* _KERNEL */ 562 563/* 564 * IPv6 multicast PCB-layer group filter descriptor. 565 */ 566struct in6_mfilter { 567 struct ip6_msource_tree im6f_sources; /* source list for (S,G) */ 568 u_long im6f_nsrc; /* # of source entries */ 569 uint8_t im6f_st[2]; /* state before/at commit */ 570}; 571 572/* 573 * Legacy KAME IPv6 multicast membership descriptor. 574 */ |
575struct in6_multi_mship { |
576 struct in6_multi *i6mm_maddr; 577 LIST_ENTRY(in6_multi_mship) i6mm_chain; |
578}; 579 |
580/* 581 * IPv6 group descriptor. 582 * 583 * For every entry on an ifnet's if_multiaddrs list which represents 584 * an IP multicast group, there is one of these structures. 585 * 586 * If any source filters are present, then a node will exist in the RB-tree 587 * to permit fast lookup by source whenever an operation takes place. 588 * This permits pre-order traversal when we issue reports. 589 * Source filter trees are kept separately from the socket layer to 590 * greatly simplify locking. 591 * 592 * When MLDv2 is active, in6m_timer is the response to group query timer. 593 * The state-change timer in6m_sctimer is separate; whenever state changes 594 * for the group the state change record is generated and transmitted, 595 * and kept if retransmissions are necessary. 596 * 597 * FUTURE: in6m_link is now only used when groups are being purged 598 * on a detaching ifnet. It could be demoted to a SLIST_ENTRY, but 599 * because it is at the very start of the struct, we can't do this 600 * w/o breaking the ABI for ifmcstat. 601 */ 602struct in6_multi { |
603 LIST_ENTRY(in6_multi) in6m_entry; /* list glue */ |
604 struct in6_addr in6m_addr; /* IPv6 multicast address */ |
605 struct ifnet *in6m_ifp; /* back pointer to ifnet */ 606 struct ifmultiaddr *in6m_ifma; /* back pointer to ifmultiaddr */ |
607 u_int in6m_refcount; /* reference count */ |
608 u_int in6m_state; /* state of the membership */ 609 u_int in6m_timer; /* MLD6 listener report timer */ |
610 611 /* New fields for MLDv2 follow. */ 612 struct mld_ifinfo *in6m_mli; /* MLD info */ 613 SLIST_ENTRY(in6_multi) in6m_nrele; /* to-be-released by MLD */ 614 struct ip6_msource_tree in6m_srcs; /* tree of sources */ 615 u_long in6m_nsrc; /* # of tree entries */ 616 617 struct ifqueue in6m_scq; /* queue of pending 618 * state-change packets */ 619 struct timeval in6m_lastgsrtv; /* last G-S-R query */ 620 uint16_t in6m_sctimer; /* state-change timer */ 621 uint16_t in6m_scrv; /* state-change rexmit count */ 622 623 /* 624 * SSM state counters which track state at T0 (the time the last 625 * state-change report's RV timer went to zero) and T1 626 * (time of pending report, i.e. now). 627 * Used for computing MLDv2 state-change reports. Several refcounts 628 * are maintained here to optimize for common use-cases. 629 */ 630 struct in6m_st { 631 uint16_t iss_fmode; /* MLD filter mode */ 632 uint16_t iss_asm; /* # of ASM listeners */ 633 uint16_t iss_ex; /* # of exclusive members */ 634 uint16_t iss_in; /* # of inclusive members */ 635 uint16_t iss_rec; /* # of recorded sources */ 636 } in6m_st[2]; /* state at t0, t1 */ |
637}; 638 |
639/* 640 * Helper function to derive the filter mode on a source entry 641 * from its internal counters. Predicates are: 642 * A source is only excluded if all listeners exclude it. 643 * A source is only included if no listeners exclude it, 644 * and at least one listener includes it. 645 * May be used by ifmcstat(8). 646 */ 647static __inline uint8_t 648im6s_get_mode(const struct in6_multi *inm, const struct ip6_msource *ims, 649 uint8_t t) 650{ |
651 |
652 t = !!t; 653 if (inm->in6m_st[t].iss_ex > 0 && 654 inm->in6m_st[t].iss_ex == ims->im6s_st[t].ex) 655 return (MCAST_EXCLUDE); 656 else if (ims->im6s_st[t].in > 0 && ims->im6s_st[t].ex == 0) 657 return (MCAST_INCLUDE); 658 return (MCAST_UNDEFINED); 659} 660 |
661#ifdef _KERNEL |
662 |
663/* |
664 * Lock macros for IPv6 layer multicast address lists. IPv6 lock goes 665 * before link layer multicast locks in the lock order. In most cases, 666 * consumers of IN_*_MULTI() macros should acquire the locks before 667 * calling them; users of the in_{add,del}multi() functions should not. |
668 */ |
669extern struct mtx in6_multi_mtx; 670#define IN6_MULTI_LOCK() mtx_lock(&in6_multi_mtx) 671#define IN6_MULTI_UNLOCK() mtx_unlock(&in6_multi_mtx) 672#define IN6_MULTI_LOCK_ASSERT() mtx_assert(&in6_multi_mtx, MA_OWNED) 673#define IN6_MULTI_UNLOCK_ASSERT() mtx_assert(&in6_multi_mtx, MA_NOTOWNED) |
674 675/* |
676 * Look up an in6_multi record for an IPv6 multicast address 677 * on the interface ifp. 678 * If no record found, return NULL. 679 * 680 * SMPng: The IN6_MULTI_LOCK and IF_ADDR_LOCK on ifp must be held. |
681 */ |
682static __inline struct in6_multi * 683in6m_lookup_locked(struct ifnet *ifp, const struct in6_addr *mcaddr) 684{ 685 struct ifmultiaddr *ifma; 686 struct in6_multi *inm; |
687 |
688 IN6_MULTI_LOCK_ASSERT(); 689 IF_ADDR_LOCK_ASSERT(ifp); |
690 |
691 inm = NULL; 692 TAILQ_FOREACH(ifma, &((ifp)->if_multiaddrs), ifma_link) { 693 if (ifma->ifma_addr->sa_family == AF_INET6) { 694 inm = (struct in6_multi *)ifma->ifma_protospec; 695 if (IN6_ARE_ADDR_EQUAL(&inm->in6m_addr, mcaddr)) 696 break; 697 inm = NULL; 698 } 699 } 700 return (inm); 701} 702 |
703/* |
704 * Wrapper for in6m_lookup_locked(). 705 * 706 * SMPng: Assumes that neithr the IN6_MULTI_LOCK() or IF_ADDR_LOCK() are held. |
707 */ |
708static __inline struct in6_multi * 709in6m_lookup(struct ifnet *ifp, const struct in6_addr *mcaddr) 710{ 711 struct in6_multi *inm; |
712 |
713 IN6_MULTI_LOCK(); 714 IF_ADDR_LOCK(ifp); 715 inm = in6m_lookup_locked(ifp, mcaddr); 716 IF_ADDR_UNLOCK(ifp); 717 IN6_MULTI_UNLOCK(); |
718 |
719 return (inm); 720} 721 722/* Acquire an in6_multi record. */ 723static __inline void 724in6m_acquire_locked(struct in6_multi *inm) 725{ 726 727 IN6_MULTI_LOCK_ASSERT(); 728 ++inm->in6m_refcount; 729} 730 731struct ip6_moptions; 732struct sockopt; 733 734/* Multicast KPIs. */ 735int im6o_mc_filter(const struct ip6_moptions *, const struct ifnet *, 736 const struct sockaddr *, const struct sockaddr *); 737int in6_mc_join(struct ifnet *, const struct in6_addr *, 738 struct in6_mfilter *, struct in6_multi **, int); 739int in6_mc_join_locked(struct ifnet *, const struct in6_addr *, 740 struct in6_mfilter *, struct in6_multi **, int); 741int in6_mc_leave(struct in6_multi *, struct in6_mfilter *); 742int in6_mc_leave_locked(struct in6_multi *, struct in6_mfilter *); 743void in6m_clear_recorded(struct in6_multi *); 744void in6m_commit(struct in6_multi *); 745void in6m_print(const struct in6_multi *); 746int in6m_record_source(struct in6_multi *, const struct in6_addr *); 747void in6m_release_locked(struct in6_multi *); 748void ip6_freemoptions(struct ip6_moptions *); 749int ip6_getmoptions(struct inpcb *, struct sockopt *); 750int ip6_setmoptions(struct inpcb *, struct sockopt *); 751 752/* Legacy KAME multicast KPIs. */ 753struct in6_multi_mship * 754 in6_joingroup(struct ifnet *, struct in6_addr *, int *, int); |
755int in6_leavegroup(struct in6_multi_mship *); |
756 757/* flags to in6_update_ifa */ 758#define IN6_IFAUPDATE_DADDELAY 0x1 /* first time to configure an address */ 759 |
760int in6_mask2len __P((struct in6_addr *, u_char *)); 761int in6_control __P((struct socket *, u_long, caddr_t, struct ifnet *, 762 struct thread *)); 763int in6_update_ifa __P((struct ifnet *, struct in6_aliasreq *, 764 struct in6_ifaddr *, int)); 765void in6_purgeaddr __P((struct ifaddr *)); 766int in6if_do_dad __P((struct ifnet *)); 767void in6_purgeif __P((struct ifnet *)); 768void in6_savemkludge __P((struct in6_ifaddr *)); 769void *in6_domifattach __P((struct ifnet *)); 770void in6_domifdetach __P((struct ifnet *, void *)); 771void in6_setmaxmtu __P((void)); 772int in6_if2idlen __P((struct ifnet *)); |
773struct in6_ifaddr *in6ifa_ifpforlinklocal __P((struct ifnet *, int)); 774struct in6_ifaddr *in6ifa_ifpwithaddr __P((struct ifnet *, struct in6_addr *)); 775char *ip6_sprintf __P((char *, const struct in6_addr *)); 776int in6_addr2zoneid __P((struct ifnet *, struct in6_addr *, u_int32_t *)); 777int in6_matchlen __P((struct in6_addr *, struct in6_addr *)); 778int in6_are_prefix_equal __P((struct in6_addr *, struct in6_addr *, int)); 779void in6_prefixlen2mask __P((struct in6_addr *, int)); 780int in6_prefix_ioctl __P((struct socket *, u_long, caddr_t, --- 13 unchanged lines hidden --- |