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 20using std::nothrow; 21 22 23template<typename Addressing> 24MulticastGroupInterface<Addressing>::MulticastGroupInterface(Filter *parent, 25 const AddressType &address, net_interface *interface) 26 : fParent(parent), fMulticastAddress(address), fInterface(interface) 27{ 28} 29 30 31template<typename Addressing> 32MulticastGroupInterface<Addressing>::~MulticastGroupInterface() 33{ 34 Clear(); 35} 36 37 38template<typename Addressing> status_t 39MulticastGroupInterface<Addressing>::Add() 40{ 41 if (fFilterMode == kInclude && !fAddresses.IsEmpty()) 42 return EINVAL; 43 44 fFilterMode = kExclude; 45 return B_OK; 46} 47 48 49template<typename Addressing> status_t 50MulticastGroupInterface<Addressing>::Drop() 51{ 52 fAddresses.Clear(); 53 Addressing::LeaveGroup(this); 54 fFilterMode = kInclude; 55 return B_OK; 56} 57 58 59template<typename Addressing> status_t 60MulticastGroupInterface<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 71template<typename Addressing> status_t 72MulticastGroupInterface<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 86template<typename Addressing> status_t 87MulticastGroupInterface<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 97template<typename Addressing> status_t 98MulticastGroupInterface<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 111template<typename Addressing> bool 112MulticastGroupInterface<Addressing>::IsEmpty() const 113{ 114 return fFilterMode == kInclude && fAddresses.IsEmpty(); 115} 116 117 118template<typename Addressing> void 119MulticastGroupInterface<Addressing>::Clear() 120{ 121 if (IsEmpty()) 122 return; 123 124 fFilterMode = kInclude; 125 fAddresses.Clear(); 126 Addressing::LeaveGroup(this); 127} 128 129 130template<typename Addressing> bool 131MulticastGroupInterface<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 141template<typename Addressing> 142MulticastFilter<Addressing>::MulticastFilter(ProtocolType *socket) 143 : fParent(socket), fStates() 144{ 145} 146 147 148template<typename Addressing> 149MulticastFilter<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 163template<typename Addressing> status_t 164MulticastFilter<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 193template<typename Addressing> void 194MulticastFilter<Addressing>::ReturnState(GroupInterface *state) 195{ 196 if (state->IsEmpty()) 197 _ReturnState(state); 198} 199 200 201template<typename Addressing> void 202MulticastFilter<Addressing>::_ReturnState(GroupInterface *state) 203{ 204 fStates.Remove(state); 205 delete state; 206} 207 208// IPv6 explicit template instantiation 209template class MulticastFilter<IPv6Multicast>; 210template class MulticastGroupInterface<IPv6Multicast>; 211