146527f68SHugo Santos /* 261729d93SAxel Dörfler * Copyright 2007-2010, 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 1846527f68SHugo Santos using std::nothrow; 1946527f68SHugo Santos 2046527f68SHugo Santos 2161729d93SAxel Dörfler static inline bool 2261729d93SAxel Dörfler operator==(const in_addr& a, const in_addr& b) 2361729d93SAxel Dörfler { 2461729d93SAxel Dörfler return a.s_addr == b.s_addr; 2561729d93SAxel Dörfler } 2661729d93SAxel Dörfler 2761729d93SAxel Dörfler 2861729d93SAxel Dörfler // #pragma mark - 2961729d93SAxel Dörfler 3061729d93SAxel Dörfler 316a606180SHugo Santos template<typename Addressing> 328aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::MulticastGroupInterface(Filter *parent, 338aa4c7e3SHugo Santos const AddressType &address, net_interface *interface) 3461729d93SAxel Dörfler : 3561729d93SAxel Dörfler fParent(parent), 3661729d93SAxel Dörfler fMulticastAddress(address), 3761729d93SAxel Dörfler fInterface(interface) 3846527f68SHugo Santos { 3946527f68SHugo Santos } 4046527f68SHugo Santos 4146527f68SHugo Santos 426a606180SHugo Santos template<typename Addressing> 438aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::~MulticastGroupInterface() 4446527f68SHugo Santos { 456a606180SHugo Santos Clear(); 4646527f68SHugo Santos } 4746527f68SHugo Santos 4846527f68SHugo Santos 496a606180SHugo Santos template<typename Addressing> status_t 508aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::Add() 5146527f68SHugo Santos { 528aa4c7e3SHugo Santos if (fFilterMode == kInclude && !fAddresses.IsEmpty()) 5346527f68SHugo Santos return EINVAL; 5446527f68SHugo Santos 5546527f68SHugo Santos fFilterMode = kExclude; 5646527f68SHugo Santos return B_OK; 5746527f68SHugo Santos } 5846527f68SHugo Santos 5946527f68SHugo Santos 606a606180SHugo Santos template<typename Addressing> status_t 618aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::Drop() 628aa4c7e3SHugo Santos { 638aa4c7e3SHugo Santos fAddresses.Clear(); 64*fa2fa026SSiarzhuk Zharski Addressing::LeaveGroup(this); 658aa4c7e3SHugo Santos fFilterMode = kInclude; 668aa4c7e3SHugo Santos return B_OK; 678aa4c7e3SHugo Santos } 688aa4c7e3SHugo Santos 698aa4c7e3SHugo Santos 708aa4c7e3SHugo Santos template<typename Addressing> status_t 718aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::BlockSource( 7246527f68SHugo Santos const AddressType &sourceAddress) 7346527f68SHugo Santos { 7446527f68SHugo Santos if (fFilterMode != kExclude) 7546527f68SHugo Santos return EINVAL; 7646527f68SHugo Santos 778aa4c7e3SHugo Santos fAddresses.Add(sourceAddress); 788aa4c7e3SHugo Santos return B_OK; 7946527f68SHugo Santos } 8046527f68SHugo Santos 8146527f68SHugo Santos 826a606180SHugo Santos template<typename Addressing> status_t 838aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::UnblockSource( 8446527f68SHugo Santos const AddressType &sourceAddress) 8546527f68SHugo Santos { 8646527f68SHugo Santos if (fFilterMode != kExclude) 8746527f68SHugo Santos return EINVAL; 8846527f68SHugo Santos 898aa4c7e3SHugo Santos if (!fAddresses.Has(sourceAddress)) 9046527f68SHugo Santos return EADDRNOTAVAIL; 9146527f68SHugo Santos 928aa4c7e3SHugo Santos fAddresses.Add(sourceAddress); 938aa4c7e3SHugo Santos return B_OK; 9446527f68SHugo Santos } 9546527f68SHugo Santos 9646527f68SHugo Santos 978aa4c7e3SHugo Santos template<typename Addressing> status_t 988aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::AddSSM(const AddressType &sourceAddress) 996a606180SHugo Santos { 1008aa4c7e3SHugo Santos if (fFilterMode == kExclude) 1018aa4c7e3SHugo Santos return EINVAL; 1028aa4c7e3SHugo Santos 1038aa4c7e3SHugo Santos fAddresses.Add(sourceAddress); 1048aa4c7e3SHugo Santos return B_OK; 1058aa4c7e3SHugo Santos } 1068aa4c7e3SHugo Santos 1078aa4c7e3SHugo Santos 1088aa4c7e3SHugo Santos template<typename Addressing> status_t 1098aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::DropSSM(const AddressType &sourceAddress) 1108aa4c7e3SHugo Santos { 1118aa4c7e3SHugo Santos if (fFilterMode == kExclude) 1128aa4c7e3SHugo Santos return EINVAL; 1138aa4c7e3SHugo Santos 1148aa4c7e3SHugo Santos if (!fAddresses.Has(sourceAddress)) 1158aa4c7e3SHugo Santos return EADDRNOTAVAIL; 1168aa4c7e3SHugo Santos 1178aa4c7e3SHugo Santos fAddresses.Add(sourceAddress); 1188aa4c7e3SHugo Santos return B_OK; 1196a606180SHugo Santos } 1206a606180SHugo Santos 1216a606180SHugo Santos 1226a606180SHugo Santos template<typename Addressing> bool 1238aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::IsEmpty() const 1246a606180SHugo Santos { 1258aa4c7e3SHugo Santos return fFilterMode == kInclude && fAddresses.IsEmpty(); 12646527f68SHugo Santos } 12746527f68SHugo Santos 12846527f68SHugo Santos 1296a606180SHugo Santos template<typename Addressing> void 1308aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::Clear() 13146527f68SHugo Santos { 1328aa4c7e3SHugo Santos if (IsEmpty()) 1338aa4c7e3SHugo Santos return; 1348aa4c7e3SHugo Santos 1358aa4c7e3SHugo Santos fFilterMode = kInclude; 1368aa4c7e3SHugo Santos fAddresses.Clear(); 1378aa4c7e3SHugo Santos Addressing::LeaveGroup(this); 1388aa4c7e3SHugo Santos } 1398aa4c7e3SHugo Santos 1408aa4c7e3SHugo Santos 1418aa4c7e3SHugo Santos template<typename Addressing> bool 1428aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::FilterAccepts(net_buffer *buffer) const 1438aa4c7e3SHugo Santos { 1448aa4c7e3SHugo Santos bool has = fAddresses.Has(Addressing::AddressFromSockAddr( 14579a0d252SHugo Santos buffer->source)); 1468aa4c7e3SHugo Santos 1478aa4c7e3SHugo Santos return (has && fFilterMode == kInclude) 1488aa4c7e3SHugo Santos || (!has && fFilterMode == kExclude); 14946527f68SHugo Santos } 15046527f68SHugo Santos 15146527f68SHugo Santos 1526a606180SHugo Santos template<typename Addressing> 1530e30c21cSHugo Santos MulticastFilter<Addressing>::MulticastFilter(ProtocolType *socket) 154276aa463SIngo Weinhold : fParent(socket), fStates() 1556c501a40SHugo Santos { 1566c501a40SHugo Santos } 1576c501a40SHugo Santos 1586c501a40SHugo Santos 1596a606180SHugo Santos template<typename Addressing> 1606a606180SHugo Santos MulticastFilter<Addressing>::~MulticastFilter() 16146527f68SHugo Santos { 16257967505SHugo Santos while (true) { 1634526eff1SHugo Santos typename States::Iterator iterator = fStates.GetIterator(); 16457967505SHugo Santos if (!iterator.HasNext()) 16557967505SHugo Santos return; 16657967505SHugo Santos 1678aa4c7e3SHugo Santos GroupInterface *state = iterator.Next(); 1686a606180SHugo Santos state->Clear(); 1698aa4c7e3SHugo Santos _ReturnState(state); 17046527f68SHugo Santos } 17146527f68SHugo Santos } 17246527f68SHugo Santos 17346527f68SHugo Santos 1748aa4c7e3SHugo Santos template<typename Addressing> status_t 1758aa4c7e3SHugo Santos MulticastFilter<Addressing>::GetState(const AddressType &groupAddress, 1768aa4c7e3SHugo Santos net_interface *interface, GroupInterface* &state, bool create) 17746527f68SHugo Santos { 1788aa4c7e3SHugo Santos state = fStates.Lookup(std::make_pair(&groupAddress, interface->index)); 17946527f68SHugo Santos 1808aa4c7e3SHugo Santos if (state == NULL && create) { 1818aa4c7e3SHugo Santos state = new (nothrow) GroupInterface(this, groupAddress, interface); 1828aa4c7e3SHugo Santos if (state == NULL) 1838aa4c7e3SHugo Santos return B_NO_MEMORY; 1840e30c21cSHugo Santos 1858aa4c7e3SHugo Santos status_t status = fStates.Insert(state); 1868aa4c7e3SHugo Santos if (status < B_OK) { 1870e30c21cSHugo Santos delete state; 1888aa4c7e3SHugo Santos return status; 1890e30c21cSHugo Santos } 1900e30c21cSHugo Santos 1918aa4c7e3SHugo Santos status = Addressing::JoinGroup(state); 1928aa4c7e3SHugo Santos if (status < B_OK) { 1938aa4c7e3SHugo Santos fStates.Remove(state); 1948aa4c7e3SHugo Santos delete state; 1958aa4c7e3SHugo Santos return status; 1968aa4c7e3SHugo Santos } 1978aa4c7e3SHugo Santos 1988aa4c7e3SHugo Santos } 1998aa4c7e3SHugo Santos 2008aa4c7e3SHugo Santos return B_OK; 20146527f68SHugo Santos } 20246527f68SHugo Santos 20346527f68SHugo Santos 2046a606180SHugo Santos template<typename Addressing> void 2058aa4c7e3SHugo Santos MulticastFilter<Addressing>::ReturnState(GroupInterface *state) 20646527f68SHugo Santos { 2078aa4c7e3SHugo Santos if (state->IsEmpty()) 2088aa4c7e3SHugo Santos _ReturnState(state); 20957967505SHugo Santos } 21057967505SHugo Santos 21157967505SHugo Santos 21257967505SHugo Santos template<typename Addressing> void 2138aa4c7e3SHugo Santos MulticastFilter<Addressing>::_ReturnState(GroupInterface *state) 21457967505SHugo Santos { 2158aa4c7e3SHugo Santos fStates.Remove(state); 2168aa4c7e3SHugo Santos delete state; 21746527f68SHugo Santos } 21846527f68SHugo Santos 2194526eff1SHugo Santos // IPv4 explicit template instantiation 2204526eff1SHugo Santos template class MulticastFilter<IPv4Multicast>; 2218aa4c7e3SHugo Santos template class MulticastGroupInterface<IPv4Multicast>; 222