xref: /haiku/src/add-ons/kernel/network/protocols/ipv4/multicast.cpp (revision 8aa4c7e3701d51a64961dd68d2ff74ee4d3374b2)
146527f68SHugo Santos /*
246527f68SHugo Santos  * Copyright 2007, Haiku, Inc. All Rights Reserved.
346527f68SHugo Santos  * Distributed under the terms of the MIT License.
446527f68SHugo Santos  *
546527f68SHugo Santos  * Authors:
646527f68SHugo Santos  *      Hugo Santos, hugosantos@gmail.com
746527f68SHugo Santos  */
846527f68SHugo Santos 
946527f68SHugo Santos #include "multicast.h"
1046527f68SHugo Santos 
116a606180SHugo Santos #include <net_buffer.h>
126a606180SHugo Santos 
1346527f68SHugo Santos #include <netinet/in.h>
1446527f68SHugo Santos 
1546527f68SHugo Santos #include <new>
1646527f68SHugo Santos 
1746527f68SHugo Santos static inline bool
1846527f68SHugo Santos operator==(const in_addr &a1, const in_addr &a2)
1946527f68SHugo Santos {
2046527f68SHugo Santos 	return a1.s_addr == a2.s_addr;
2146527f68SHugo Santos }
2246527f68SHugo Santos 
2346527f68SHugo Santos using std::nothrow;
2446527f68SHugo Santos 
2546527f68SHugo Santos 
266a606180SHugo Santos template<typename Addressing>
27*8aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::MulticastGroupInterface(Filter *parent,
28*8aa4c7e3SHugo Santos 	const AddressType &address, net_interface *interface)
29*8aa4c7e3SHugo Santos 	: fParent(parent), fMulticastAddress(address), fInterface(interface)
3046527f68SHugo Santos {
3146527f68SHugo Santos }
3246527f68SHugo Santos 
3346527f68SHugo Santos 
346a606180SHugo Santos template<typename Addressing>
35*8aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::~MulticastGroupInterface()
3646527f68SHugo Santos {
376a606180SHugo Santos 	Clear();
3846527f68SHugo Santos }
3946527f68SHugo Santos 
4046527f68SHugo Santos 
416a606180SHugo Santos template<typename Addressing> status_t
42*8aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::Add()
4346527f68SHugo Santos {
44*8aa4c7e3SHugo Santos 	if (fFilterMode == kInclude && !fAddresses.IsEmpty())
4546527f68SHugo Santos 		return EINVAL;
4646527f68SHugo Santos 
4746527f68SHugo Santos 	fFilterMode = kExclude;
4846527f68SHugo Santos 	return B_OK;
4946527f68SHugo Santos }
5046527f68SHugo Santos 
5146527f68SHugo Santos 
526a606180SHugo Santos template<typename Addressing> status_t
53*8aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::Drop()
54*8aa4c7e3SHugo Santos {
55*8aa4c7e3SHugo Santos 	fAddresses.Clear();
56*8aa4c7e3SHugo Santos 	fFilterMode = kInclude;
57*8aa4c7e3SHugo Santos 	return B_OK;
58*8aa4c7e3SHugo Santos }
59*8aa4c7e3SHugo Santos 
60*8aa4c7e3SHugo Santos 
61*8aa4c7e3SHugo Santos template<typename Addressing> status_t
62*8aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::BlockSource(
6346527f68SHugo Santos 	const AddressType &sourceAddress)
6446527f68SHugo Santos {
6546527f68SHugo Santos 	if (fFilterMode != kExclude)
6646527f68SHugo Santos 		return EINVAL;
6746527f68SHugo Santos 
68*8aa4c7e3SHugo Santos 	fAddresses.Add(sourceAddress);
69*8aa4c7e3SHugo Santos 	return B_OK;
7046527f68SHugo Santos }
7146527f68SHugo Santos 
7246527f68SHugo Santos 
736a606180SHugo Santos template<typename Addressing> status_t
74*8aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::UnblockSource(
7546527f68SHugo Santos 	const AddressType &sourceAddress)
7646527f68SHugo Santos {
7746527f68SHugo Santos 	if (fFilterMode != kExclude)
7846527f68SHugo Santos 		return EINVAL;
7946527f68SHugo Santos 
80*8aa4c7e3SHugo Santos 	if (!fAddresses.Has(sourceAddress))
8146527f68SHugo Santos 		return EADDRNOTAVAIL;
8246527f68SHugo Santos 
83*8aa4c7e3SHugo Santos 	fAddresses.Add(sourceAddress);
84*8aa4c7e3SHugo Santos 	return B_OK;
8546527f68SHugo Santos }
8646527f68SHugo Santos 
8746527f68SHugo Santos 
88*8aa4c7e3SHugo Santos template<typename Addressing> status_t
89*8aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::AddSSM(const AddressType &sourceAddress)
906a606180SHugo Santos {
91*8aa4c7e3SHugo Santos 	if (fFilterMode == kExclude)
92*8aa4c7e3SHugo Santos 		return EINVAL;
93*8aa4c7e3SHugo Santos 
94*8aa4c7e3SHugo Santos 	fAddresses.Add(sourceAddress);
95*8aa4c7e3SHugo Santos 	return B_OK;
96*8aa4c7e3SHugo Santos }
97*8aa4c7e3SHugo Santos 
98*8aa4c7e3SHugo Santos 
99*8aa4c7e3SHugo Santos template<typename Addressing> status_t
100*8aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::DropSSM(const AddressType &sourceAddress)
101*8aa4c7e3SHugo Santos {
102*8aa4c7e3SHugo Santos 	if (fFilterMode == kExclude)
103*8aa4c7e3SHugo Santos 		return EINVAL;
104*8aa4c7e3SHugo Santos 
105*8aa4c7e3SHugo Santos 	if (!fAddresses.Has(sourceAddress))
106*8aa4c7e3SHugo Santos 		return EADDRNOTAVAIL;
107*8aa4c7e3SHugo Santos 
108*8aa4c7e3SHugo Santos 	fAddresses.Add(sourceAddress);
109*8aa4c7e3SHugo Santos 	return B_OK;
1106a606180SHugo Santos }
1116a606180SHugo Santos 
1126a606180SHugo Santos 
1136a606180SHugo Santos template<typename Addressing> bool
114*8aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::IsEmpty() const
1156a606180SHugo Santos {
116*8aa4c7e3SHugo Santos 	return fFilterMode == kInclude && fAddresses.IsEmpty();
11746527f68SHugo Santos }
11846527f68SHugo Santos 
11946527f68SHugo Santos 
1206a606180SHugo Santos template<typename Addressing> void
121*8aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::Clear()
12246527f68SHugo Santos {
123*8aa4c7e3SHugo Santos 	if (IsEmpty())
124*8aa4c7e3SHugo Santos 		return;
125*8aa4c7e3SHugo Santos 
126*8aa4c7e3SHugo Santos 	fFilterMode = kInclude;
127*8aa4c7e3SHugo Santos 	fAddresses.Clear();
128*8aa4c7e3SHugo Santos 	Addressing::LeaveGroup(this);
129*8aa4c7e3SHugo Santos }
130*8aa4c7e3SHugo Santos 
131*8aa4c7e3SHugo Santos 
132*8aa4c7e3SHugo Santos template<typename Addressing> bool
133*8aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::FilterAccepts(net_buffer *buffer) const
134*8aa4c7e3SHugo Santos {
135*8aa4c7e3SHugo Santos 	bool has = fAddresses.Has(Addressing::AddressFromSockAddr(
136*8aa4c7e3SHugo Santos 		(sockaddr *)&buffer->source));
137*8aa4c7e3SHugo Santos 
138*8aa4c7e3SHugo Santos 	return (has && fFilterMode == kInclude)
139*8aa4c7e3SHugo Santos 		|| (!has && fFilterMode == kExclude);
14046527f68SHugo Santos }
14146527f68SHugo Santos 
14246527f68SHugo Santos 
1436a606180SHugo Santos template<typename Addressing>
1440e30c21cSHugo Santos MulticastFilter<Addressing>::MulticastFilter(ProtocolType *socket)
1450e30c21cSHugo Santos 	: fParent(socket), fStates((size_t)0)
1466c501a40SHugo Santos {
1476c501a40SHugo Santos }
1486c501a40SHugo Santos 
1496c501a40SHugo Santos 
1506a606180SHugo Santos template<typename Addressing>
1516a606180SHugo Santos MulticastFilter<Addressing>::~MulticastFilter()
15246527f68SHugo Santos {
15357967505SHugo Santos 	while (true) {
1544526eff1SHugo Santos 		typename States::Iterator iterator = fStates.GetIterator();
15557967505SHugo Santos 		if (!iterator.HasNext())
15657967505SHugo Santos 			return;
15757967505SHugo Santos 
158*8aa4c7e3SHugo Santos 		GroupInterface *state = iterator.Next();
1596a606180SHugo Santos 		state->Clear();
160*8aa4c7e3SHugo Santos 		_ReturnState(state);
16146527f68SHugo Santos 	}
16246527f68SHugo Santos }
16346527f68SHugo Santos 
16446527f68SHugo Santos 
165*8aa4c7e3SHugo Santos template<typename Addressing> status_t
166*8aa4c7e3SHugo Santos MulticastFilter<Addressing>::GetState(const AddressType &groupAddress,
167*8aa4c7e3SHugo Santos 	net_interface *interface, GroupInterface* &state, bool create)
16846527f68SHugo Santos {
169*8aa4c7e3SHugo Santos 	state = fStates.Lookup(std::make_pair(&groupAddress, interface->index));
17046527f68SHugo Santos 
171*8aa4c7e3SHugo Santos 	if (state == NULL && create) {
172*8aa4c7e3SHugo Santos 		state = new (nothrow) GroupInterface(this, groupAddress, interface);
173*8aa4c7e3SHugo Santos 		if (state == NULL)
174*8aa4c7e3SHugo Santos 			return B_NO_MEMORY;
1750e30c21cSHugo Santos 
176*8aa4c7e3SHugo Santos 		status_t status = fStates.Insert(state);
177*8aa4c7e3SHugo Santos 		if (status < B_OK) {
1780e30c21cSHugo Santos 			delete state;
179*8aa4c7e3SHugo Santos 			return status;
1800e30c21cSHugo Santos 		}
1810e30c21cSHugo Santos 
182*8aa4c7e3SHugo Santos 		status = Addressing::JoinGroup(state);
183*8aa4c7e3SHugo Santos 		if (status < B_OK) {
184*8aa4c7e3SHugo Santos 			fStates.Remove(state);
185*8aa4c7e3SHugo Santos 			delete state;
186*8aa4c7e3SHugo Santos 			return status;
187*8aa4c7e3SHugo Santos 		}
188*8aa4c7e3SHugo Santos 
189*8aa4c7e3SHugo Santos 	}
190*8aa4c7e3SHugo Santos 
191*8aa4c7e3SHugo Santos 	return B_OK;
19246527f68SHugo Santos }
19346527f68SHugo Santos 
19446527f68SHugo Santos 
1956a606180SHugo Santos template<typename Addressing> void
196*8aa4c7e3SHugo Santos MulticastFilter<Addressing>::ReturnState(GroupInterface *state)
19746527f68SHugo Santos {
198*8aa4c7e3SHugo Santos 	if (state->IsEmpty())
199*8aa4c7e3SHugo Santos 		_ReturnState(state);
20057967505SHugo Santos }
20157967505SHugo Santos 
20257967505SHugo Santos 
20357967505SHugo Santos template<typename Addressing> void
204*8aa4c7e3SHugo Santos MulticastFilter<Addressing>::_ReturnState(GroupInterface *state)
20557967505SHugo Santos {
206*8aa4c7e3SHugo Santos 	fStates.Remove(state);
207*8aa4c7e3SHugo Santos 	delete state;
20846527f68SHugo Santos }
20946527f68SHugo Santos 
2104526eff1SHugo Santos // IPv4 explicit template instantiation
2114526eff1SHugo Santos template class MulticastFilter<IPv4Multicast>;
212*8aa4c7e3SHugo Santos template class MulticastGroupInterface<IPv4Multicast>;
213