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> 278aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::MulticastGroupInterface(Filter *parent, 288aa4c7e3SHugo Santos const AddressType &address, net_interface *interface) 298aa4c7e3SHugo Santos : fParent(parent), fMulticastAddress(address), fInterface(interface) 3046527f68SHugo Santos { 3146527f68SHugo Santos } 3246527f68SHugo Santos 3346527f68SHugo Santos 346a606180SHugo Santos template<typename Addressing> 358aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::~MulticastGroupInterface() 3646527f68SHugo Santos { 376a606180SHugo Santos Clear(); 3846527f68SHugo Santos } 3946527f68SHugo Santos 4046527f68SHugo Santos 416a606180SHugo Santos template<typename Addressing> status_t 428aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::Add() 4346527f68SHugo Santos { 448aa4c7e3SHugo 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 538aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::Drop() 548aa4c7e3SHugo Santos { 558aa4c7e3SHugo Santos fAddresses.Clear(); 568aa4c7e3SHugo Santos fFilterMode = kInclude; 578aa4c7e3SHugo Santos return B_OK; 588aa4c7e3SHugo Santos } 598aa4c7e3SHugo Santos 608aa4c7e3SHugo Santos 618aa4c7e3SHugo Santos template<typename Addressing> status_t 628aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::BlockSource( 6346527f68SHugo Santos const AddressType &sourceAddress) 6446527f68SHugo Santos { 6546527f68SHugo Santos if (fFilterMode != kExclude) 6646527f68SHugo Santos return EINVAL; 6746527f68SHugo Santos 688aa4c7e3SHugo Santos fAddresses.Add(sourceAddress); 698aa4c7e3SHugo Santos return B_OK; 7046527f68SHugo Santos } 7146527f68SHugo Santos 7246527f68SHugo Santos 736a606180SHugo Santos template<typename Addressing> status_t 748aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::UnblockSource( 7546527f68SHugo Santos const AddressType &sourceAddress) 7646527f68SHugo Santos { 7746527f68SHugo Santos if (fFilterMode != kExclude) 7846527f68SHugo Santos return EINVAL; 7946527f68SHugo Santos 808aa4c7e3SHugo Santos if (!fAddresses.Has(sourceAddress)) 8146527f68SHugo Santos return EADDRNOTAVAIL; 8246527f68SHugo Santos 838aa4c7e3SHugo Santos fAddresses.Add(sourceAddress); 848aa4c7e3SHugo Santos return B_OK; 8546527f68SHugo Santos } 8646527f68SHugo Santos 8746527f68SHugo Santos 888aa4c7e3SHugo Santos template<typename Addressing> status_t 898aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::AddSSM(const AddressType &sourceAddress) 906a606180SHugo Santos { 918aa4c7e3SHugo Santos if (fFilterMode == kExclude) 928aa4c7e3SHugo Santos return EINVAL; 938aa4c7e3SHugo Santos 948aa4c7e3SHugo Santos fAddresses.Add(sourceAddress); 958aa4c7e3SHugo Santos return B_OK; 968aa4c7e3SHugo Santos } 978aa4c7e3SHugo Santos 988aa4c7e3SHugo Santos 998aa4c7e3SHugo Santos template<typename Addressing> status_t 1008aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::DropSSM(const AddressType &sourceAddress) 1018aa4c7e3SHugo Santos { 1028aa4c7e3SHugo Santos if (fFilterMode == kExclude) 1038aa4c7e3SHugo Santos return EINVAL; 1048aa4c7e3SHugo Santos 1058aa4c7e3SHugo Santos if (!fAddresses.Has(sourceAddress)) 1068aa4c7e3SHugo Santos return EADDRNOTAVAIL; 1078aa4c7e3SHugo Santos 1088aa4c7e3SHugo Santos fAddresses.Add(sourceAddress); 1098aa4c7e3SHugo Santos return B_OK; 1106a606180SHugo Santos } 1116a606180SHugo Santos 1126a606180SHugo Santos 1136a606180SHugo Santos template<typename Addressing> bool 1148aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::IsEmpty() const 1156a606180SHugo Santos { 1168aa4c7e3SHugo Santos return fFilterMode == kInclude && fAddresses.IsEmpty(); 11746527f68SHugo Santos } 11846527f68SHugo Santos 11946527f68SHugo Santos 1206a606180SHugo Santos template<typename Addressing> void 1218aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::Clear() 12246527f68SHugo Santos { 1238aa4c7e3SHugo Santos if (IsEmpty()) 1248aa4c7e3SHugo Santos return; 1258aa4c7e3SHugo Santos 1268aa4c7e3SHugo Santos fFilterMode = kInclude; 1278aa4c7e3SHugo Santos fAddresses.Clear(); 1288aa4c7e3SHugo Santos Addressing::LeaveGroup(this); 1298aa4c7e3SHugo Santos } 1308aa4c7e3SHugo Santos 1318aa4c7e3SHugo Santos 1328aa4c7e3SHugo Santos template<typename Addressing> bool 1338aa4c7e3SHugo Santos MulticastGroupInterface<Addressing>::FilterAccepts(net_buffer *buffer) const 1348aa4c7e3SHugo Santos { 1358aa4c7e3SHugo Santos bool has = fAddresses.Has(Addressing::AddressFromSockAddr( 136*79a0d252SHugo Santos buffer->source)); 1378aa4c7e3SHugo Santos 1388aa4c7e3SHugo Santos return (has && fFilterMode == kInclude) 1398aa4c7e3SHugo 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 1588aa4c7e3SHugo Santos GroupInterface *state = iterator.Next(); 1596a606180SHugo Santos state->Clear(); 1608aa4c7e3SHugo Santos _ReturnState(state); 16146527f68SHugo Santos } 16246527f68SHugo Santos } 16346527f68SHugo Santos 16446527f68SHugo Santos 1658aa4c7e3SHugo Santos template<typename Addressing> status_t 1668aa4c7e3SHugo Santos MulticastFilter<Addressing>::GetState(const AddressType &groupAddress, 1678aa4c7e3SHugo Santos net_interface *interface, GroupInterface* &state, bool create) 16846527f68SHugo Santos { 1698aa4c7e3SHugo Santos state = fStates.Lookup(std::make_pair(&groupAddress, interface->index)); 17046527f68SHugo Santos 1718aa4c7e3SHugo Santos if (state == NULL && create) { 1728aa4c7e3SHugo Santos state = new (nothrow) GroupInterface(this, groupAddress, interface); 1738aa4c7e3SHugo Santos if (state == NULL) 1748aa4c7e3SHugo Santos return B_NO_MEMORY; 1750e30c21cSHugo Santos 1768aa4c7e3SHugo Santos status_t status = fStates.Insert(state); 1778aa4c7e3SHugo Santos if (status < B_OK) { 1780e30c21cSHugo Santos delete state; 1798aa4c7e3SHugo Santos return status; 1800e30c21cSHugo Santos } 1810e30c21cSHugo Santos 1828aa4c7e3SHugo Santos status = Addressing::JoinGroup(state); 1838aa4c7e3SHugo Santos if (status < B_OK) { 1848aa4c7e3SHugo Santos fStates.Remove(state); 1858aa4c7e3SHugo Santos delete state; 1868aa4c7e3SHugo Santos return status; 1878aa4c7e3SHugo Santos } 1888aa4c7e3SHugo Santos 1898aa4c7e3SHugo Santos } 1908aa4c7e3SHugo Santos 1918aa4c7e3SHugo Santos return B_OK; 19246527f68SHugo Santos } 19346527f68SHugo Santos 19446527f68SHugo Santos 1956a606180SHugo Santos template<typename Addressing> void 1968aa4c7e3SHugo Santos MulticastFilter<Addressing>::ReturnState(GroupInterface *state) 19746527f68SHugo Santos { 1988aa4c7e3SHugo Santos if (state->IsEmpty()) 1998aa4c7e3SHugo Santos _ReturnState(state); 20057967505SHugo Santos } 20157967505SHugo Santos 20257967505SHugo Santos 20357967505SHugo Santos template<typename Addressing> void 2048aa4c7e3SHugo Santos MulticastFilter<Addressing>::_ReturnState(GroupInterface *state) 20557967505SHugo Santos { 2068aa4c7e3SHugo Santos fStates.Remove(state); 2078aa4c7e3SHugo Santos delete state; 20846527f68SHugo Santos } 20946527f68SHugo Santos 2104526eff1SHugo Santos // IPv4 explicit template instantiation 2114526eff1SHugo Santos template class MulticastFilter<IPv4Multicast>; 2128aa4c7e3SHugo Santos template class MulticastGroupInterface<IPv4Multicast>; 213