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