xref: /haiku/src/add-ons/kernel/network/protocols/ipv6/multicast.cpp (revision 675ffabd70492a962f8c0288a32208c22ce5de18)
1 /*
2  * Copyright 2010, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Atis Elsts, the.kfx@gmail.com
7  */
8 
9 
10 #include "ipv6_address.h"
11 #include "multicast.h"
12 
13 #include <net_buffer.h>
14 
15 #include <netinet6/in6.h>
16 
17 #include <new>
18 
19 
20 using std::nothrow;
21 
22 
23 template<typename Addressing>
24 MulticastGroupInterface<Addressing>::MulticastGroupInterface(Filter *parent,
25 	const AddressType &address, net_interface *interface)
26 	: fParent(parent), fMulticastAddress(address), fInterface(interface)
27 {
28 }
29 
30 
31 template<typename Addressing>
32 MulticastGroupInterface<Addressing>::~MulticastGroupInterface()
33 {
34 	Clear();
35 }
36 
37 
38 template<typename Addressing> status_t
39 MulticastGroupInterface<Addressing>::Add()
40 {
41 	if (fFilterMode == kInclude && !fAddresses.IsEmpty())
42 		return EINVAL;
43 
44 	fFilterMode = kExclude;
45 	return B_OK;
46 }
47 
48 
49 template<typename Addressing> status_t
50 MulticastGroupInterface<Addressing>::Drop()
51 {
52 	fAddresses.Clear();
53 	fFilterMode = kInclude;
54 	return B_OK;
55 }
56 
57 
58 template<typename Addressing> status_t
59 MulticastGroupInterface<Addressing>::BlockSource(
60 	const AddressType &sourceAddress)
61 {
62 	if (fFilterMode != kExclude)
63 		return EINVAL;
64 
65 	fAddresses.Add(sourceAddress);
66 	return B_OK;
67 }
68 
69 
70 template<typename Addressing> status_t
71 MulticastGroupInterface<Addressing>::UnblockSource(
72 	const AddressType &sourceAddress)
73 {
74 	if (fFilterMode != kExclude)
75 		return EINVAL;
76 
77 	if (!fAddresses.Has(sourceAddress))
78 		return EADDRNOTAVAIL;
79 
80 	fAddresses.Add(sourceAddress);
81 	return B_OK;
82 }
83 
84 
85 template<typename Addressing> status_t
86 MulticastGroupInterface<Addressing>::AddSSM(const AddressType &sourceAddress)
87 {
88 	if (fFilterMode == kExclude)
89 		return EINVAL;
90 
91 	fAddresses.Add(sourceAddress);
92 	return B_OK;
93 }
94 
95 
96 template<typename Addressing> status_t
97 MulticastGroupInterface<Addressing>::DropSSM(const AddressType &sourceAddress)
98 {
99 	if (fFilterMode == kExclude)
100 		return EINVAL;
101 
102 	if (!fAddresses.Has(sourceAddress))
103 		return EADDRNOTAVAIL;
104 
105 	fAddresses.Add(sourceAddress);
106 	return B_OK;
107 }
108 
109 
110 template<typename Addressing> bool
111 MulticastGroupInterface<Addressing>::IsEmpty() const
112 {
113 	return fFilterMode == kInclude && fAddresses.IsEmpty();
114 }
115 
116 
117 template<typename Addressing> void
118 MulticastGroupInterface<Addressing>::Clear()
119 {
120 	if (IsEmpty())
121 		return;
122 
123 	fFilterMode = kInclude;
124 	fAddresses.Clear();
125 	Addressing::LeaveGroup(this);
126 }
127 
128 
129 template<typename Addressing> bool
130 MulticastGroupInterface<Addressing>::FilterAccepts(net_buffer *buffer) const
131 {
132 	bool has = fAddresses.Has(Addressing::AddressFromSockAddr(
133 		buffer->source));
134 
135 	return (has && fFilterMode == kInclude)
136 		|| (!has && fFilterMode == kExclude);
137 }
138 
139 
140 template<typename Addressing>
141 MulticastFilter<Addressing>::MulticastFilter(ProtocolType *socket)
142 	: fParent(socket), fStates()
143 {
144 }
145 
146 
147 template<typename Addressing>
148 MulticastFilter<Addressing>::~MulticastFilter()
149 {
150 	while (true) {
151 		typename States::Iterator iterator = fStates.GetIterator();
152 		if (!iterator.HasNext())
153 			return;
154 
155 		GroupInterface *state = iterator.Next();
156 		state->Clear();
157 		_ReturnState(state);
158 	}
159 }
160 
161 
162 template<typename Addressing> status_t
163 MulticastFilter<Addressing>::GetState(const AddressType &groupAddress,
164 	net_interface *interface, GroupInterface* &state, bool create)
165 {
166 	state = fStates.Lookup(std::make_pair(&groupAddress, interface->index));
167 
168 	if (state == NULL && create) {
169 		state = new (nothrow) GroupInterface(this, groupAddress, interface);
170 		if (state == NULL)
171 			return B_NO_MEMORY;
172 
173 		status_t status = fStates.Insert(state);
174 		if (status < B_OK) {
175 			delete state;
176 			return status;
177 		}
178 
179 		status = Addressing::JoinGroup(state);
180 		if (status < B_OK) {
181 			fStates.Remove(state);
182 			delete state;
183 			return status;
184 		}
185 
186 	}
187 
188 	return B_OK;
189 }
190 
191 
192 template<typename Addressing> void
193 MulticastFilter<Addressing>::ReturnState(GroupInterface *state)
194 {
195 	if (state->IsEmpty())
196 		_ReturnState(state);
197 }
198 
199 
200 template<typename Addressing> void
201 MulticastFilter<Addressing>::_ReturnState(GroupInterface *state)
202 {
203 	fStates.Remove(state);
204 	delete state;
205 }
206 
207 // IPv6 explicit template instantiation
208 template class MulticastFilter<IPv6Multicast>;
209 template class MulticastGroupInterface<IPv6Multicast>;
210