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