vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / kernel / network / protocols / ipv6 / multicast.h
blobc6cbe5da71b9d5ee8b481cfe490a75a53bcba771
1 /*
2 * Copyright 2010, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Atis Elsts, the.kfx@gmail.com
7 */
8 #ifndef _IPV6_MULTICAST_H_
9 #define _IPV6_MULTICAST_H_
12 #include <util/DoublyLinkedList.h>
13 #include <util/OpenHashTable.h>
15 #include <net_datalink.h>
17 #include <netinet6/in6.h>
19 #include <utility>
21 #include "jenkins.h"
24 struct net_buffer;
25 struct net_protocol;
28 template<typename Addressing> class MulticastFilter;
29 template<typename Addressing> class MulticastGroupInterface;
32 struct IPv6Multicast {
33 typedef struct in6_addr AddressType;
34 typedef struct ipv6_protocol ProtocolType;
35 typedef MulticastGroupInterface<IPv6Multicast> GroupInterface;
37 static status_t JoinGroup(GroupInterface *);
38 static status_t LeaveGroup(GroupInterface *);
40 static const in6_addr &AddressFromSockAddr(const sockaddr *sockaddr)
41 { return ((const sockaddr_in6 *)sockaddr)->sin6_addr; }
42 static size_t HashAddress(const in6_addr &address)
43 { return jenkins_hashword((const uint32*)&address,
44 sizeof(in6_addr) / sizeof(uint32), 0); }
48 template<typename AddressType>
49 class AddressSet {
50 struct ContainedAddress : DoublyLinkedListLinkImpl<ContainedAddress> {
51 AddressType address;
54 typedef DoublyLinkedList<ContainedAddress> AddressList;
56 public:
57 AddressSet()
58 : fCount(0) {}
60 ~AddressSet() { Clear(); }
62 status_t Add(const AddressType &address)
64 if (Has(address))
65 return B_OK;
67 ContainedAddress *container = new ContainedAddress();
68 if (container == NULL)
69 return B_NO_MEMORY;
71 container->address = address;
72 fAddresses.Add(container);
74 return B_OK;
77 void Remove(const AddressType &address)
79 ContainedAddress *container = _Get(address);
80 if (container == NULL)
81 return;
83 fAddresses.Remove(container);
84 delete container;
87 bool Has(const AddressType &address) const
89 return _Get(address) != NULL;
92 bool IsEmpty() const { return fAddresses.IsEmpty(); }
94 void Clear()
96 while (!fAddresses.IsEmpty())
97 Remove(fAddresses.Head()->address);
100 class Iterator {
101 public:
102 Iterator(const AddressList &addresses)
103 : fBaseIterator(addresses.GetIterator()) {}
105 bool HasNext() const { return fBaseIterator.HasNext(); }
106 AddressType &Next() { return fBaseIterator.Next()->address; }
108 private:
109 typename AddressList::ConstIterator fBaseIterator;
112 Iterator GetIterator() const { return Iterator(fAddresses); }
114 private:
115 ContainedAddress *_Get(const AddressType &address) const
117 typename AddressList::ConstIterator it = fAddresses.GetIterator();
118 while (it.HasNext()) {
119 ContainedAddress *container = it.Next();
120 if (container->address == address)
121 return container;
123 return NULL;
126 AddressList fAddresses;
127 int fCount;
131 template<typename Addressing>
132 class MulticastGroupInterface {
133 public:
134 typedef MulticastGroupInterface<Addressing> ThisType;
135 typedef typename Addressing::AddressType AddressType;
136 typedef MulticastFilter<Addressing> Filter;
137 typedef ::AddressSet<AddressType> AddressSet;
139 enum FilterMode {
140 kInclude,
141 kExclude
144 MulticastGroupInterface(Filter *parent, const AddressType &address,
145 net_interface *interface);
146 ~MulticastGroupInterface();
148 Filter *Parent() const { return fParent; }
150 const AddressType &Address() const { return fMulticastAddress; }
151 net_interface *Interface() const { return fInterface; }
153 status_t Add();
154 status_t Drop();
155 status_t BlockSource(const AddressType &sourceAddress);
156 status_t UnblockSource(const AddressType &sourceAddress);
157 status_t AddSSM(const AddressType &sourceAddress);
158 status_t DropSSM(const AddressType &sourceAddress);
160 bool IsEmpty() const;
161 void Clear();
163 FilterMode Mode() const { return fFilterMode; }
164 const AddressSet &Sources() const { return fAddresses; }
166 bool FilterAccepts(net_buffer *buffer) const;
168 struct HashDefinition {
169 typedef std::pair<const AddressType *, uint32> KeyType;
170 typedef ThisType ValueType;
172 size_t HashKey(const KeyType &key) const
174 size_t result = 0;
175 result = jenkins_hashword((const uint32*)key.first,
176 sizeof(in6_addr) / sizeof(uint32), result);
177 result = jenkins_hashword(&key.second, 1, result);
178 return result;
180 size_t Hash(ValueType *value) const
181 { return HashKey(std::make_pair(&value->Address(),
182 value->Interface()->index)); }
183 bool Compare(const KeyType &key, ValueType *value) const
184 { return value->Interface()->index == key.second
185 && value->Address() == *key.first; }
186 MulticastGroupInterface*& GetLink(ValueType *value) const
187 { return value->HashLink(); }
190 MulticastGroupInterface*& HashLink() { return fLink; }
191 MulticastGroupInterface*& MulticastGroupsHashLink() { return fMulticastGroupsLink; }
193 private:
194 // for g++ 2.95
195 friend class HashDefinition;
197 Filter *fParent;
198 AddressType fMulticastAddress;
199 net_interface *fInterface;
200 FilterMode fFilterMode;
201 AddressSet fAddresses;
202 MulticastGroupInterface* fLink;
203 MulticastGroupInterface* fMulticastGroupsLink;
207 template<typename Addressing>
208 class MulticastFilter {
209 public:
210 typedef typename Addressing::AddressType AddressType;
211 typedef typename Addressing::ProtocolType ProtocolType;
212 typedef MulticastGroupInterface<Addressing> GroupInterface;
214 MulticastFilter(ProtocolType *parent);
215 ~MulticastFilter();
217 ProtocolType *Socket() const { return fParent; }
219 status_t GetState(const AddressType &groupAddress,
220 net_interface *interface, GroupInterface* &state, bool create);
221 void ReturnState(GroupInterface *state);
223 private:
224 typedef typename GroupInterface::HashDefinition HashDefinition;
225 typedef BOpenHashTable<HashDefinition> States;
227 void _ReturnState(GroupInterface *state);
229 ProtocolType *fParent;
230 States fStates;
234 #endif // _IPV6_MULTICAST_H_