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 Addressing::LeaveGroup(this); 54 fFilterMode = kInclude; 55 return B_OK; 56 } 57 58 59 template<typename Addressing> status_t 60 MulticastGroupInterface<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 71 template<typename Addressing> status_t 72 MulticastGroupInterface<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 86 template<typename Addressing> status_t 87 MulticastGroupInterface<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 97 template<typename Addressing> status_t 98 MulticastGroupInterface<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 111 template<typename Addressing> bool 112 MulticastGroupInterface<Addressing>::IsEmpty() const 113 { 114 return fFilterMode == kInclude && fAddresses.IsEmpty(); 115 } 116 117 118 template<typename Addressing> void 119 MulticastGroupInterface<Addressing>::Clear() 120 { 121 if (IsEmpty()) 122 return; 123 124 fFilterMode = kInclude; 125 fAddresses.Clear(); 126 Addressing::LeaveGroup(this); 127 } 128 129 130 template<typename Addressing> bool 131 MulticastGroupInterface<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 141 template<typename Addressing> 142 MulticastFilter<Addressing>::MulticastFilter(ProtocolType *socket) 143 : fParent(socket), fStates() 144 { 145 } 146 147 148 template<typename Addressing> 149 MulticastFilter<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 163 template<typename Addressing> status_t 164 MulticastFilter<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 193 template<typename Addressing> void 194 MulticastFilter<Addressing>::ReturnState(GroupInterface *state) 195 { 196 if (state->IsEmpty()) 197 _ReturnState(state); 198 } 199 200 201 template<typename Addressing> void 202 MulticastFilter<Addressing>::_ReturnState(GroupInterface *state) 203 { 204 fStates.Remove(state); 205 delete state; 206 } 207 208 // IPv6 explicit template instantiation 209 template class MulticastFilter<IPv6Multicast>; 210 template class MulticastGroupInterface<IPv6Multicast>; 211