xref: /haiku/src/add-ons/kernel/network/protocols/ipv6/multicast.cpp (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
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 	Addressing::LeaveGroup(this);
54 	fFilterMode = kInclude;
55 	return B_OK;
56 }
57 
58 
59 template<typename Addressing> status_t
60 MulticastGroupInterface<Addressing>::BlockSource(
61 	const AddressType &sourceAddress)
62 {
63 	if (fFilterMode != kExclude)
64 		return EINVAL;
65 
66 	fAddresses.Add(sourceAddress);
67 	return B_OK;
68 }
69 
70 
71 template<typename Addressing> status_t
72 MulticastGroupInterface<Addressing>::UnblockSource(
73 	const AddressType &sourceAddress)
74 {
75 	if (fFilterMode != kExclude)
76 		return EINVAL;
77 
78 	if (!fAddresses.Has(sourceAddress))
79 		return EADDRNOTAVAIL;
80 
81 	fAddresses.Add(sourceAddress);
82 	return B_OK;
83 }
84 
85 
86 template<typename Addressing> status_t
87 MulticastGroupInterface<Addressing>::AddSSM(const AddressType &sourceAddress)
88 {
89 	if (fFilterMode == kExclude)
90 		return EINVAL;
91 
92 	fAddresses.Add(sourceAddress);
93 	return B_OK;
94 }
95 
96 
97 template<typename Addressing> status_t
98 MulticastGroupInterface<Addressing>::DropSSM(const AddressType &sourceAddress)
99 {
100 	if (fFilterMode == kExclude)
101 		return EINVAL;
102 
103 	if (!fAddresses.Has(sourceAddress))
104 		return EADDRNOTAVAIL;
105 
106 	fAddresses.Add(sourceAddress);
107 	return B_OK;
108 }
109 
110 
111 template<typename Addressing> bool
112 MulticastGroupInterface<Addressing>::IsEmpty() const
113 {
114 	return fFilterMode == kInclude && fAddresses.IsEmpty();
115 }
116 
117 
118 template<typename Addressing> void
119 MulticastGroupInterface<Addressing>::Clear()
120 {
121 	if (IsEmpty())
122 		return;
123 
124 	fFilterMode = kInclude;
125 	fAddresses.Clear();
126 	Addressing::LeaveGroup(this);
127 }
128 
129 
130 template<typename Addressing> bool
131 MulticastGroupInterface<Addressing>::FilterAccepts(net_buffer *buffer) const
132 {
133 	bool has = fAddresses.Has(Addressing::AddressFromSockAddr(
134 		buffer->source));
135 
136 	return (has && fFilterMode == kInclude)
137 		|| (!has && fFilterMode == kExclude);
138 }
139 
140 
141 template<typename Addressing>
142 MulticastFilter<Addressing>::MulticastFilter(ProtocolType *socket)
143 	: fParent(socket), fStates()
144 {
145 }
146 
147 
148 template<typename Addressing>
149 MulticastFilter<Addressing>::~MulticastFilter()
150 {
151 	while (true) {
152 		typename States::Iterator iterator = fStates.GetIterator();
153 		if (!iterator.HasNext())
154 			return;
155 
156 		GroupInterface *state = iterator.Next();
157 		state->Clear();
158 		_ReturnState(state);
159 	}
160 }
161 
162 
163 template<typename Addressing> status_t
164 MulticastFilter<Addressing>::GetState(const AddressType &groupAddress,
165 	net_interface *interface, GroupInterface* &state, bool create)
166 {
167 	state = fStates.Lookup(std::make_pair(&groupAddress, interface->index));
168 
169 	if (state == NULL && create) {
170 		state = new (nothrow) GroupInterface(this, groupAddress, interface);
171 		if (state == NULL)
172 			return B_NO_MEMORY;
173 
174 		status_t status = fStates.Insert(state);
175 		if (status < B_OK) {
176 			delete state;
177 			return status;
178 		}
179 
180 		status = Addressing::JoinGroup(state);
181 		if (status < B_OK) {
182 			fStates.Remove(state);
183 			delete state;
184 			return status;
185 		}
186 
187 	}
188 
189 	return B_OK;
190 }
191 
192 
193 template<typename Addressing> void
194 MulticastFilter<Addressing>::ReturnState(GroupInterface *state)
195 {
196 	if (state->IsEmpty())
197 		_ReturnState(state);
198 }
199 
200 
201 template<typename Addressing> void
202 MulticastFilter<Addressing>::_ReturnState(GroupInterface *state)
203 {
204 	fStates.Remove(state);
205 	delete state;
206 }
207 
208 // IPv6 explicit template instantiation
209 template class MulticastFilter<IPv6Multicast>;
210 template class MulticastGroupInterface<IPv6Multicast>;
211