1 /* 2 * Copyright 2007-2010, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Hugo Santos, hugosantos@gmail.com 7 */ 8 9 #include "multicast.h" 10 11 #include <net_buffer.h> 12 13 #include <netinet/in.h> 14 15 #include <new> 16 17 18 using std::nothrow; 19 20 21 static inline bool 22 operator==(const in_addr& a, const in_addr& b) 23 { 24 return a.s_addr == b.s_addr; 25 } 26 27 28 // #pragma mark - 29 30 31 template<typename Addressing> 32 MulticastGroupInterface<Addressing>::MulticastGroupInterface(Filter *parent, 33 const AddressType &address, net_interface *interface) 34 : 35 fParent(parent), 36 fMulticastAddress(address), 37 fInterface(interface) 38 { 39 } 40 41 42 template<typename Addressing> 43 MulticastGroupInterface<Addressing>::~MulticastGroupInterface() 44 { 45 Clear(); 46 } 47 48 49 template<typename Addressing> status_t 50 MulticastGroupInterface<Addressing>::Add() 51 { 52 if (fFilterMode == kInclude && !fAddresses.IsEmpty()) 53 return EINVAL; 54 55 fFilterMode = kExclude; 56 return B_OK; 57 } 58 59 60 template<typename Addressing> status_t 61 MulticastGroupInterface<Addressing>::Drop() 62 { 63 fAddresses.Clear(); 64 fFilterMode = kInclude; 65 return B_OK; 66 } 67 68 69 template<typename Addressing> status_t 70 MulticastGroupInterface<Addressing>::BlockSource( 71 const AddressType &sourceAddress) 72 { 73 if (fFilterMode != kExclude) 74 return EINVAL; 75 76 fAddresses.Add(sourceAddress); 77 return B_OK; 78 } 79 80 81 template<typename Addressing> status_t 82 MulticastGroupInterface<Addressing>::UnblockSource( 83 const AddressType &sourceAddress) 84 { 85 if (fFilterMode != kExclude) 86 return EINVAL; 87 88 if (!fAddresses.Has(sourceAddress)) 89 return EADDRNOTAVAIL; 90 91 fAddresses.Add(sourceAddress); 92 return B_OK; 93 } 94 95 96 template<typename Addressing> status_t 97 MulticastGroupInterface<Addressing>::AddSSM(const AddressType &sourceAddress) 98 { 99 if (fFilterMode == kExclude) 100 return EINVAL; 101 102 fAddresses.Add(sourceAddress); 103 return B_OK; 104 } 105 106 107 template<typename Addressing> status_t 108 MulticastGroupInterface<Addressing>::DropSSM(const AddressType &sourceAddress) 109 { 110 if (fFilterMode == kExclude) 111 return EINVAL; 112 113 if (!fAddresses.Has(sourceAddress)) 114 return EADDRNOTAVAIL; 115 116 fAddresses.Add(sourceAddress); 117 return B_OK; 118 } 119 120 121 template<typename Addressing> bool 122 MulticastGroupInterface<Addressing>::IsEmpty() const 123 { 124 return fFilterMode == kInclude && fAddresses.IsEmpty(); 125 } 126 127 128 template<typename Addressing> void 129 MulticastGroupInterface<Addressing>::Clear() 130 { 131 if (IsEmpty()) 132 return; 133 134 fFilterMode = kInclude; 135 fAddresses.Clear(); 136 Addressing::LeaveGroup(this); 137 } 138 139 140 template<typename Addressing> bool 141 MulticastGroupInterface<Addressing>::FilterAccepts(net_buffer *buffer) const 142 { 143 bool has = fAddresses.Has(Addressing::AddressFromSockAddr( 144 buffer->source)); 145 146 return (has && fFilterMode == kInclude) 147 || (!has && fFilterMode == kExclude); 148 } 149 150 151 template<typename Addressing> 152 MulticastFilter<Addressing>::MulticastFilter(ProtocolType *socket) 153 : fParent(socket), fStates() 154 { 155 } 156 157 158 template<typename Addressing> 159 MulticastFilter<Addressing>::~MulticastFilter() 160 { 161 while (true) { 162 typename States::Iterator iterator = fStates.GetIterator(); 163 if (!iterator.HasNext()) 164 return; 165 166 GroupInterface *state = iterator.Next(); 167 state->Clear(); 168 _ReturnState(state); 169 } 170 } 171 172 173 template<typename Addressing> status_t 174 MulticastFilter<Addressing>::GetState(const AddressType &groupAddress, 175 net_interface *interface, GroupInterface* &state, bool create) 176 { 177 state = fStates.Lookup(std::make_pair(&groupAddress, interface->index)); 178 179 if (state == NULL && create) { 180 state = new (nothrow) GroupInterface(this, groupAddress, interface); 181 if (state == NULL) 182 return B_NO_MEMORY; 183 184 status_t status = fStates.Insert(state); 185 if (status < B_OK) { 186 delete state; 187 return status; 188 } 189 190 status = Addressing::JoinGroup(state); 191 if (status < B_OK) { 192 fStates.Remove(state); 193 delete state; 194 return status; 195 } 196 197 } 198 199 return B_OK; 200 } 201 202 203 template<typename Addressing> void 204 MulticastFilter<Addressing>::ReturnState(GroupInterface *state) 205 { 206 if (state->IsEmpty()) 207 _ReturnState(state); 208 } 209 210 211 template<typename Addressing> void 212 MulticastFilter<Addressing>::_ReturnState(GroupInterface *state) 213 { 214 fStates.Remove(state); 215 delete state; 216 } 217 218 // IPv4 explicit template instantiation 219 template class MulticastFilter<IPv4Multicast>; 220 template class MulticastGroupInterface<IPv4Multicast>; 221