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 20 using std::nothrow; 21 22 23 template<typename Addressing> 24 MulticastGroupInterface<Addressing>::MulticastGroupInterface(Filter *parent, 25 const AddressType &address, net_interface *interface) 26 : fParent(parent), fMulticastAddress(address), fInterface(interface) 27 { 28 } 29 30 31 template<typename Addressing> 32 MulticastGroupInterface<Addressing>::~MulticastGroupInterface() 33 { 34 Clear(); 35 } 36 37 38 template<typename Addressing> status_t 39 MulticastGroupInterface<Addressing>::Add() 40 { 41 if (fFilterMode == kInclude && !fAddresses.IsEmpty()) 42 return EINVAL; 43 44 fFilterMode = kExclude; 45 return B_OK; 46 } 47 48 49 template<typename Addressing> status_t 50 MulticastGroupInterface<Addressing>::Drop() 51 { 52 fAddresses.Clear(); 53 fFilterMode = kInclude; 54 return B_OK; 55 } 56 57 58 template<typename Addressing> status_t 59 MulticastGroupInterface<Addressing>::BlockSource( 60 const AddressType &sourceAddress) 61 { 62 if (fFilterMode != kExclude) 63 return EINVAL; 64 65 fAddresses.Add(sourceAddress); 66 return B_OK; 67 } 68 69 70 template<typename Addressing> status_t 71 MulticastGroupInterface<Addressing>::UnblockSource( 72 const AddressType &sourceAddress) 73 { 74 if (fFilterMode != kExclude) 75 return EINVAL; 76 77 if (!fAddresses.Has(sourceAddress)) 78 return EADDRNOTAVAIL; 79 80 fAddresses.Add(sourceAddress); 81 return B_OK; 82 } 83 84 85 template<typename Addressing> status_t 86 MulticastGroupInterface<Addressing>::AddSSM(const AddressType &sourceAddress) 87 { 88 if (fFilterMode == kExclude) 89 return EINVAL; 90 91 fAddresses.Add(sourceAddress); 92 return B_OK; 93 } 94 95 96 template<typename Addressing> status_t 97 MulticastGroupInterface<Addressing>::DropSSM(const AddressType &sourceAddress) 98 { 99 if (fFilterMode == kExclude) 100 return EINVAL; 101 102 if (!fAddresses.Has(sourceAddress)) 103 return EADDRNOTAVAIL; 104 105 fAddresses.Add(sourceAddress); 106 return B_OK; 107 } 108 109 110 template<typename Addressing> bool 111 MulticastGroupInterface<Addressing>::IsEmpty() const 112 { 113 return fFilterMode == kInclude && fAddresses.IsEmpty(); 114 } 115 116 117 template<typename Addressing> void 118 MulticastGroupInterface<Addressing>::Clear() 119 { 120 if (IsEmpty()) 121 return; 122 123 fFilterMode = kInclude; 124 fAddresses.Clear(); 125 Addressing::LeaveGroup(this); 126 } 127 128 129 template<typename Addressing> bool 130 MulticastGroupInterface<Addressing>::FilterAccepts(net_buffer *buffer) const 131 { 132 bool has = fAddresses.Has(Addressing::AddressFromSockAddr( 133 buffer->source)); 134 135 return (has && fFilterMode == kInclude) 136 || (!has && fFilterMode == kExclude); 137 } 138 139 140 template<typename Addressing> 141 MulticastFilter<Addressing>::MulticastFilter(ProtocolType *socket) 142 : fParent(socket), fStates() 143 { 144 } 145 146 147 template<typename Addressing> 148 MulticastFilter<Addressing>::~MulticastFilter() 149 { 150 while (true) { 151 typename States::Iterator iterator = fStates.GetIterator(); 152 if (!iterator.HasNext()) 153 return; 154 155 GroupInterface *state = iterator.Next(); 156 state->Clear(); 157 _ReturnState(state); 158 } 159 } 160 161 162 template<typename Addressing> status_t 163 MulticastFilter<Addressing>::GetState(const AddressType &groupAddress, 164 net_interface *interface, GroupInterface* &state, bool create) 165 { 166 state = fStates.Lookup(std::make_pair(&groupAddress, interface->index)); 167 168 if (state == NULL && create) { 169 state = new (nothrow) GroupInterface(this, groupAddress, interface); 170 if (state == NULL) 171 return B_NO_MEMORY; 172 173 status_t status = fStates.Insert(state); 174 if (status < B_OK) { 175 delete state; 176 return status; 177 } 178 179 status = Addressing::JoinGroup(state); 180 if (status < B_OK) { 181 fStates.Remove(state); 182 delete state; 183 return status; 184 } 185 186 } 187 188 return B_OK; 189 } 190 191 192 template<typename Addressing> void 193 MulticastFilter<Addressing>::ReturnState(GroupInterface *state) 194 { 195 if (state->IsEmpty()) 196 _ReturnState(state); 197 } 198 199 200 template<typename Addressing> void 201 MulticastFilter<Addressing>::_ReturnState(GroupInterface *state) 202 { 203 fStates.Remove(state); 204 delete state; 205 } 206 207 // IPv6 explicit template instantiation 208 template class MulticastFilter<IPv6Multicast>; 209 template class MulticastGroupInterface<IPv6Multicast>; 210