2 * Copyright 2010, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Atis Elsts, the.kfx@gmail.com
8 #ifndef _IPV6_MULTICAST_H_
9 #define _IPV6_MULTICAST_H_
12 #include <util/DoublyLinkedList.h>
13 #include <util/OpenHashTable.h>
15 #include <net_datalink.h>
17 #include <netinet6/in6.h>
28 template<typename Addressing
> class MulticastFilter
;
29 template<typename Addressing
> class MulticastGroupInterface
;
32 struct IPv6Multicast
{
33 typedef struct in6_addr AddressType
;
34 typedef struct ipv6_protocol ProtocolType
;
35 typedef MulticastGroupInterface
<IPv6Multicast
> GroupInterface
;
37 static status_t
JoinGroup(GroupInterface
*);
38 static status_t
LeaveGroup(GroupInterface
*);
40 static const in6_addr
&AddressFromSockAddr(const sockaddr
*sockaddr
)
41 { return ((const sockaddr_in6
*)sockaddr
)->sin6_addr
; }
42 static size_t HashAddress(const in6_addr
&address
)
43 { return jenkins_hashword((const uint32
*)&address
,
44 sizeof(in6_addr
) / sizeof(uint32
), 0); }
48 template<typename AddressType
>
50 struct ContainedAddress
: DoublyLinkedListLinkImpl
<ContainedAddress
> {
54 typedef DoublyLinkedList
<ContainedAddress
> AddressList
;
60 ~AddressSet() { Clear(); }
62 status_t
Add(const AddressType
&address
)
67 ContainedAddress
*container
= new ContainedAddress();
68 if (container
== NULL
)
71 container
->address
= address
;
72 fAddresses
.Add(container
);
77 void Remove(const AddressType
&address
)
79 ContainedAddress
*container
= _Get(address
);
80 if (container
== NULL
)
83 fAddresses
.Remove(container
);
87 bool Has(const AddressType
&address
) const
89 return _Get(address
) != NULL
;
92 bool IsEmpty() const { return fAddresses
.IsEmpty(); }
96 while (!fAddresses
.IsEmpty())
97 Remove(fAddresses
.Head()->address
);
102 Iterator(const AddressList
&addresses
)
103 : fBaseIterator(addresses
.GetIterator()) {}
105 bool HasNext() const { return fBaseIterator
.HasNext(); }
106 AddressType
&Next() { return fBaseIterator
.Next()->address
; }
109 typename
AddressList::ConstIterator fBaseIterator
;
112 Iterator
GetIterator() const { return Iterator(fAddresses
); }
115 ContainedAddress
*_Get(const AddressType
&address
) const
117 typename
AddressList::ConstIterator it
= fAddresses
.GetIterator();
118 while (it
.HasNext()) {
119 ContainedAddress
*container
= it
.Next();
120 if (container
->address
== address
)
126 AddressList fAddresses
;
131 template<typename Addressing
>
132 class MulticastGroupInterface
{
134 typedef MulticastGroupInterface
<Addressing
> ThisType
;
135 typedef typename
Addressing::AddressType AddressType
;
136 typedef MulticastFilter
<Addressing
> Filter
;
137 typedef ::AddressSet
<AddressType
> AddressSet
;
144 MulticastGroupInterface(Filter
*parent
, const AddressType
&address
,
145 net_interface
*interface
);
146 ~MulticastGroupInterface();
148 Filter
*Parent() const { return fParent
; }
150 const AddressType
&Address() const { return fMulticastAddress
; }
151 net_interface
*Interface() const { return fInterface
; }
155 status_t
BlockSource(const AddressType
&sourceAddress
);
156 status_t
UnblockSource(const AddressType
&sourceAddress
);
157 status_t
AddSSM(const AddressType
&sourceAddress
);
158 status_t
DropSSM(const AddressType
&sourceAddress
);
160 bool IsEmpty() const;
163 FilterMode
Mode() const { return fFilterMode
; }
164 const AddressSet
&Sources() const { return fAddresses
; }
166 bool FilterAccepts(net_buffer
*buffer
) const;
168 struct HashDefinition
{
169 typedef std::pair
<const AddressType
*, uint32
> KeyType
;
170 typedef ThisType ValueType
;
172 size_t HashKey(const KeyType
&key
) const
175 result
= jenkins_hashword((const uint32
*)key
.first
,
176 sizeof(in6_addr
) / sizeof(uint32
), result
);
177 result
= jenkins_hashword(&key
.second
, 1, result
);
180 size_t Hash(ValueType
*value
) const
181 { return HashKey(std::make_pair(&value
->Address(),
182 value
->Interface()->index
)); }
183 bool Compare(const KeyType
&key
, ValueType
*value
) const
184 { return value
->Interface()->index
== key
.second
185 && value
->Address() == *key
.first
; }
186 MulticastGroupInterface
*& GetLink(ValueType
*value
) const
187 { return value
->HashLink(); }
190 MulticastGroupInterface
*& HashLink() { return fLink
; }
191 MulticastGroupInterface
*& MulticastGroupsHashLink() { return fMulticastGroupsLink
; }
195 friend class HashDefinition
;
198 AddressType fMulticastAddress
;
199 net_interface
*fInterface
;
200 FilterMode fFilterMode
;
201 AddressSet fAddresses
;
202 MulticastGroupInterface
* fLink
;
203 MulticastGroupInterface
* fMulticastGroupsLink
;
207 template<typename Addressing
>
208 class MulticastFilter
{
210 typedef typename
Addressing::AddressType AddressType
;
211 typedef typename
Addressing::ProtocolType ProtocolType
;
212 typedef MulticastGroupInterface
<Addressing
> GroupInterface
;
214 MulticastFilter(ProtocolType
*parent
);
217 ProtocolType
*Socket() const { return fParent
; }
219 status_t
GetState(const AddressType
&groupAddress
,
220 net_interface
*interface
, GroupInterface
* &state
, bool create
);
221 void ReturnState(GroupInterface
*state
);
224 typedef typename
GroupInterface::HashDefinition HashDefinition
;
225 typedef BOpenHashTable
<HashDefinition
> States
;
227 void _ReturnState(GroupInterface
*state
);
229 ProtocolType
*fParent
;
234 #endif // _IPV6_MULTICAST_H_