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 Addressing::LeaveGroup(this); 65 fFilterMode = kInclude; 66 return B_OK; 67 } 68 69 70 template<typename Addressing> status_t 71 MulticastGroupInterface<Addressing>::BlockSource( 72 const AddressType &sourceAddress) 73 { 74 if (fFilterMode != kExclude) 75 return EINVAL; 76 77 fAddresses.Add(sourceAddress); 78 return B_OK; 79 } 80 81 82 template<typename Addressing> status_t 83 MulticastGroupInterface<Addressing>::UnblockSource( 84 const AddressType &sourceAddress) 85 { 86 if (fFilterMode != kExclude) 87 return EINVAL; 88 89 if (!fAddresses.Has(sourceAddress)) 90 return EADDRNOTAVAIL; 91 92 fAddresses.Add(sourceAddress); 93 return B_OK; 94 } 95 96 97 template<typename Addressing> status_t 98 MulticastGroupInterface<Addressing>::AddSSM(const AddressType &sourceAddress) 99 { 100 if (fFilterMode == kExclude) 101 return EINVAL; 102 103 fAddresses.Add(sourceAddress); 104 return B_OK; 105 } 106 107 108 template<typename Addressing> status_t 109 MulticastGroupInterface<Addressing>::DropSSM(const AddressType &sourceAddress) 110 { 111 if (fFilterMode == kExclude) 112 return EINVAL; 113 114 if (!fAddresses.Has(sourceAddress)) 115 return EADDRNOTAVAIL; 116 117 fAddresses.Add(sourceAddress); 118 return B_OK; 119 } 120 121 122 template<typename Addressing> bool 123 MulticastGroupInterface<Addressing>::IsEmpty() const 124 { 125 return fFilterMode == kInclude && fAddresses.IsEmpty(); 126 } 127 128 129 template<typename Addressing> void 130 MulticastGroupInterface<Addressing>::Clear() 131 { 132 if (IsEmpty()) 133 return; 134 135 fFilterMode = kInclude; 136 fAddresses.Clear(); 137 Addressing::LeaveGroup(this); 138 } 139 140 141 template<typename Addressing> bool 142 MulticastGroupInterface<Addressing>::FilterAccepts(net_buffer *buffer) const 143 { 144 bool has = fAddresses.Has(Addressing::AddressFromSockAddr( 145 buffer->source)); 146 147 return (has && fFilterMode == kInclude) 148 || (!has && fFilterMode == kExclude); 149 } 150 151 152 template<typename Addressing> 153 MulticastFilter<Addressing>::MulticastFilter(ProtocolType *socket) 154 : fParent(socket), fStates() 155 { 156 } 157 158 159 template<typename Addressing> 160 MulticastFilter<Addressing>::~MulticastFilter() 161 { 162 while (true) { 163 typename States::Iterator iterator = fStates.GetIterator(); 164 if (!iterator.HasNext()) 165 return; 166 167 GroupInterface *state = iterator.Next(); 168 state->Clear(); 169 _ReturnState(state); 170 } 171 } 172 173 174 template<typename Addressing> status_t 175 MulticastFilter<Addressing>::GetState(const AddressType &groupAddress, 176 net_interface *interface, GroupInterface* &state, bool create) 177 { 178 state = fStates.Lookup(std::make_pair(&groupAddress, interface->index)); 179 180 if (state == NULL && create) { 181 state = new (nothrow) GroupInterface(this, groupAddress, interface); 182 if (state == NULL) 183 return B_NO_MEMORY; 184 185 status_t status = fStates.Insert(state); 186 if (status < B_OK) { 187 delete state; 188 return status; 189 } 190 191 status = Addressing::JoinGroup(state); 192 if (status < B_OK) { 193 fStates.Remove(state); 194 delete state; 195 return status; 196 } 197 198 } else if (create) 199 return EADDRINUSE; 200 201 return B_OK; 202 } 203 204 205 template<typename Addressing> void 206 MulticastFilter<Addressing>::ReturnState(GroupInterface *state) 207 { 208 if (state->IsEmpty()) 209 _ReturnState(state); 210 } 211 212 213 template<typename Addressing> void 214 MulticastFilter<Addressing>::_ReturnState(GroupInterface *state) 215 { 216 fStates.Remove(state); 217 delete state; 218 } 219 220 // IPv4 explicit template instantiation 221 template class MulticastFilter<IPv4Multicast>; 222 template class MulticastGroupInterface<IPv4Multicast>; 223