18d1485faSAxel Dörfler/*
28d1485faSAxel Dörfler * Copyright 2010, Haiku, Inc. All Rights Reserved.
38d1485faSAxel Dörfler * Distributed under the terms of the MIT License.
48d1485faSAxel Dörfler *
58d1485faSAxel Dörfler * Authors:
68d1485faSAxel Dörfler *		Atis Elsts, the.kfx@gmail.com
78d1485faSAxel Dörfler */
88d1485faSAxel Dörfler#ifndef _IPV6_MULTICAST_H_
98d1485faSAxel Dörfler#define _IPV6_MULTICAST_H_
108d1485faSAxel Dörfler
118d1485faSAxel Dörfler
128d1485faSAxel Dörfler#include <util/DoublyLinkedList.h>
138d1485faSAxel Dörfler#include <util/OpenHashTable.h>
148d1485faSAxel Dörfler
158d1485faSAxel Dörfler#include <net_datalink.h>
168d1485faSAxel Dörfler
178d1485faSAxel Dörfler#include <netinet6/in6.h>
188d1485faSAxel Dörfler
198d1485faSAxel Dörfler#include <utility>
208d1485faSAxel Dörfler
218d1485faSAxel Dörfler#include "jenkins.h"
228d1485faSAxel Dörfler
238d1485faSAxel Dörfler
248d1485faSAxel Dörflerstruct net_buffer;
258d1485faSAxel Dörflerstruct net_protocol;
268d1485faSAxel Dörfler
278d1485faSAxel Dörfler
288d1485faSAxel Dörflertemplate<typename Addressing> class MulticastFilter;
298d1485faSAxel Dörflertemplate<typename Addressing> class MulticastGroupInterface;
308d1485faSAxel Dörfler
318d1485faSAxel Dörfler
328d1485faSAxel Dörflerstruct IPv6Multicast {
338d1485faSAxel Dörfler	typedef struct in6_addr AddressType;
348d1485faSAxel Dörfler	typedef struct ipv6_protocol ProtocolType;
358d1485faSAxel Dörfler	typedef MulticastGroupInterface<IPv6Multicast> GroupInterface;
368d1485faSAxel Dörfler
378d1485faSAxel Dörfler	static status_t JoinGroup(GroupInterface *);
388d1485faSAxel Dörfler	static status_t LeaveGroup(GroupInterface *);
398d1485faSAxel Dörfler
408d1485faSAxel Dörfler	static const in6_addr &AddressFromSockAddr(const sockaddr *sockaddr)
418d1485faSAxel Dörfler		{ return ((const sockaddr_in6 *)sockaddr)->sin6_addr; }
428d1485faSAxel Dörfler	static size_t HashAddress(const in6_addr &address)
438d1485faSAxel Dörfler		{ return jenkins_hashword((const uint32*)&address,
448d1485faSAxel Dörfler				sizeof(in6_addr) / sizeof(uint32), 0); }
458d1485faSAxel Dörfler};
468d1485faSAxel Dörfler
478d1485faSAxel Dörfler
488d1485faSAxel Dörflertemplate<typename AddressType>
498d1485faSAxel Dörflerclass AddressSet {
508d1485faSAxel Dörfler	struct ContainedAddress : DoublyLinkedListLinkImpl<ContainedAddress> {
518d1485faSAxel Dörfler		AddressType address;
528d1485faSAxel Dörfler	};
538d1485faSAxel Dörfler
548d1485faSAxel Dörfler	typedef DoublyLinkedList<ContainedAddress> AddressList;
558d1485faSAxel Dörfler
568d1485faSAxel Dörflerpublic:
578d1485faSAxel Dörfler	AddressSet()
588d1485faSAxel Dörfler		: fCount(0) {}
598d1485faSAxel Dörfler
608d1485faSAxel Dörfler	~AddressSet() { Clear(); }
618d1485faSAxel Dörfler
628d1485faSAxel Dörfler	status_t Add(const AddressType &address)
638d1485faSAxel Dörfler	{
648d1485faSAxel Dörfler		if (Has(address))
658d1485faSAxel Dörfler			return B_OK;
668d1485faSAxel Dörfler
678d1485faSAxel Dörfler		ContainedAddress *container = new ContainedAddress();
688d1485faSAxel Dörfler		if (container == NULL)
698d1485faSAxel Dörfler			return B_NO_MEMORY;
708d1485faSAxel Dörfler
718d1485faSAxel Dörfler		container->address = address;
728d1485faSAxel Dörfler		fAddresses.Add(container);
738d1485faSAxel Dörfler
748d1485faSAxel Dörfler		return B_OK;
758d1485faSAxel Dörfler	}
768d1485faSAxel Dörfler
778d1485faSAxel Dörfler	void Remove(const AddressType &address)
788d1485faSAxel Dörfler	{
798d1485faSAxel Dörfler		ContainedAddress *container = _Get(address);
808d1485faSAxel Dörfler		if (container == NULL)
818d1485faSAxel Dörfler			return;
828d1485faSAxel Dörfler
838d1485faSAxel Dörfler		fAddresses.Remove(container);
848d1485faSAxel Dörfler		delete container;
858d1485faSAxel Dörfler	}
868d1485faSAxel Dörfler
878d1485faSAxel Dörfler	bool Has(const AddressType &address) const
888d1485faSAxel Dörfler	{
898d1485faSAxel Dörfler		return _Get(address) != NULL;
908d1485faSAxel Dörfler	}
918d1485faSAxel Dörfler
928d1485faSAxel Dörfler	bool IsEmpty() const { return fAddresses.IsEmpty(); }
938d1485faSAxel Dörfler
948d1485faSAxel Dörfler	void Clear()
958d1485faSAxel Dörfler	{
968d1485faSAxel Dörfler		while (!fAddresses.IsEmpty())
978d1485faSAxel Dörfler			Remove(fAddresses.Head()->address);
988d1485faSAxel Dörfler	}
998d1485faSAxel Dörfler
1008d1485faSAxel Dörfler	class Iterator {
1018d1485faSAxel Dörfler	public:
1028d1485faSAxel Dörfler		Iterator(const AddressList &addresses)
1038d1485faSAxel Dörfler			: fBaseIterator(addresses.GetIterator()) {}
1048d1485faSAxel Dörfler
1058d1485faSAxel Dörfler		bool HasNext() const { return fBaseIterator.HasNext(); }
1068d1485faSAxel Dörfler		AddressType &Next() { return fBaseIterator.Next()->address; }
1078d1485faSAxel Dörfler
1088d1485faSAxel Dörfler	private:
1098d1485faSAxel Dörfler		typename AddressList::ConstIterator fBaseIterator;
1108d1485faSAxel Dörfler	};
1118d1485faSAxel Dörfler
1128d1485faSAxel Dörfler	Iterator GetIterator() const { return Iterator(fAddresses); }
1138d1485faSAxel Dörfler
1148d1485faSAxel Dörflerprivate:
1158d1485faSAxel Dörfler	ContainedAddress *_Get(const AddressType &address) const
1168d1485faSAxel Dörfler	{
1178d1485faSAxel Dörfler		typename AddressList::ConstIterator it = fAddresses.GetIterator();
1188d1485faSAxel Dörfler		while (it.HasNext()) {
1198d1485faSAxel Dörfler			ContainedAddress *container = it.Next();
1208d1485faSAxel Dörfler			if (container->address == address)
1218d1485faSAxel Dörfler				return container;
1228d1485faSAxel Dörfler		}
1238d1485faSAxel Dörfler		return NULL;
1248d1485faSAxel Dörfler	}
1258d1485faSAxel Dörfler
1268d1485faSAxel Dörfler	AddressList fAddresses;
1278d1485faSAxel Dörfler	int fCount;
1288d1485faSAxel Dörfler};
1298d1485faSAxel Dörfler
1308d1485faSAxel Dörfler
1318d1485faSAxel Dörflertemplate<typename Addressing>
1328d1485faSAxel Dörflerclass MulticastGroupInterface {
1338d1485faSAxel Dörflerpublic:
1348d1485faSAxel Dörfler	typedef MulticastGroupInterface<Addressing> ThisType;
1358d1485faSAxel Dörfler	typedef typename Addressing::AddressType AddressType;
1368d1485faSAxel Dörfler	typedef MulticastFilter<Addressing> Filter;
1378d1485faSAxel Dörfler	typedef ::AddressSet<AddressType> AddressSet;
1388d1485faSAxel Dörfler
1398d1485faSAxel Dörfler	enum FilterMode {
1408d1485faSAxel Dörfler		kInclude,
1418d1485faSAxel Dörfler		kExclude
1428d1485faSAxel Dörfler	};
1438d1485faSAxel Dörfler
1448d1485faSAxel Dörfler	MulticastGroupInterface(Filter *parent, const AddressType &address,
1458d1485faSAxel Dörfler		net_interface *interface);
1468d1485faSAxel Dörfler	~MulticastGroupInterface();
1478d1485faSAxel Dörfler
1488d1485faSAxel Dörfler	Filter *Parent() const { return fParent; }
1498d1485faSAxel Dörfler
1508d1485faSAxel Dörfler	const AddressType &Address() const { return fMulticastAddress; }
1518d1485faSAxel Dörfler	net_interface *Interface() const { return fInterface; }
1528d1485faSAxel Dörfler
1538d1485faSAxel Dörfler	status_t Add();
1548d1485faSAxel Dörfler	status_t Drop();
1558d1485faSAxel Dörfler	status_t BlockSource(const AddressType &sourceAddress);
1568d1485faSAxel Dörfler	status_t UnblockSource(const AddressType &sourceAddress);
1578d1485faSAxel Dörfler	status_t AddSSM(const AddressType &sourceAddress);
1588d1485faSAxel Dörfler	status_t DropSSM(const AddressType &sourceAddress);
1598d1485faSAxel Dörfler
1608d1485faSAxel Dörfler	bool IsEmpty() const;
1618d1485faSAxel Dörfler	void Clear();
1628d1485faSAxel Dörfler
1638d1485faSAxel Dörfler	FilterMode Mode() const { return fFilterMode; }
1648d1485faSAxel Dörfler	const AddressSet &Sources() const { return fAddresses; }
1658d1485faSAxel Dörfler
1668d1485faSAxel Dörfler	bool FilterAccepts(net_buffer *buffer) const;
1678d1485faSAxel Dörfler
1688d1485faSAxel Dörfler	struct HashDefinition {
1698d1485faSAxel Dörfler		typedef std::pair<const AddressType *, uint32> KeyType;
1708d1485faSAxel Dörfler		typedef ThisType ValueType;
1718d1485faSAxel Dörfler
1728d1485faSAxel Dörfler		size_t HashKey(const KeyType &key) const
1738d1485faSAxel Dörfler			{
1748d1485faSAxel Dörfler				size_t result = 0;
175c0b42ec1SStefano Ceccherini				result = jenkins_hashword((const uint32*)key.first,
1768d1485faSAxel Dörfler					sizeof(in6_addr) / sizeof(uint32), result);
1778d1485faSAxel Dörfler				result = jenkins_hashword(&key.second, 1, result);
1788d1485faSAxel Dörfler				return result;
1798d1485faSAxel Dörfler			}
1808d1485faSAxel Dörfler		size_t Hash(ValueType *value) const
1818d1485faSAxel Dörfler			{ return HashKey(std::make_pair(&value->Address(),
1828d1485faSAxel Dörfler				value->Interface()->index)); }
1838d1485faSAxel Dörfler		bool Compare(const KeyType &key, ValueType *value) const
1848d1485faSAxel Dörfler			{ return value->Interface()->index == key.second
1858d1485faSAxel Dörfler				&& value->Address() == *key.first; }
1868d1485faSAxel Dörfler		MulticastGroupInterface*& GetLink(ValueType *value) const
1878d1485faSAxel Dörfler			{ return value->HashLink(); }
1888d1485faSAxel Dörfler	};
1898d1485faSAxel Dörfler
1908d1485faSAxel Dörfler	MulticastGroupInterface*& HashLink() { return fLink; }
19119d8e4f7SAlexander Andreev	MulticastGroupInterface*& MulticastGroupsHashLink() { return fMulticastGroupsLink; }
1928d1485faSAxel Dörfler
1938d1485faSAxel Dörflerprivate:
1948d1485faSAxel Dörfler	// for g++ 2.95
1958d1485faSAxel Dörfler	friend class HashDefinition;
1968d1485faSAxel Dörfler
1978d1485faSAxel Dörfler	Filter *fParent;
1988d1485faSAxel Dörfler	AddressType fMulticastAddress;
1998d1485faSAxel Dörfler	net_interface *fInterface;
2008d1485faSAxel Dörfler	FilterMode fFilterMode;
2018d1485faSAxel Dörfler	AddressSet fAddresses;
2028d1485faSAxel Dörfler	MulticastGroupInterface* fLink;
20319d8e4f7SAlexander Andreev	MulticastGroupInterface* fMulticastGroupsLink;
2048d1485faSAxel Dörfler};
2058d1485faSAxel Dörfler
2068d1485faSAxel Dörfler
2078d1485faSAxel Dörflertemplate<typename Addressing>
2088d1485faSAxel Dörflerclass MulticastFilter {
2098d1485faSAxel Dörflerpublic:
2108d1485faSAxel Dörfler	typedef typename Addressing::AddressType AddressType;
2118d1485faSAxel Dörfler	typedef typename Addressing::ProtocolType ProtocolType;
2128d1485faSAxel Dörfler	typedef MulticastGroupInterface<Addressing> GroupInterface;
2138d1485faSAxel Dörfler
2148d1485faSAxel Dörfler	MulticastFilter(ProtocolType *parent);
2158d1485faSAxel Dörfler	~MulticastFilter();
2168d1485faSAxel Dörfler
2178d1485faSAxel Dörfler	ProtocolType *Socket() const { return fParent; }
2188d1485faSAxel Dörfler
2198d1485faSAxel Dörfler	status_t GetState(const AddressType &groupAddress,
2208d1485faSAxel Dörfler		net_interface *interface, GroupInterface* &state, bool create);
2218d1485faSAxel Dörfler	void ReturnState(GroupInterface *state);
2228d1485faSAxel Dörfler
2238d1485faSAxel Dörflerprivate:
2248d1485faSAxel Dörfler	typedef typename GroupInterface::HashDefinition HashDefinition;
2258d1485faSAxel Dörfler	typedef BOpenHashTable<HashDefinition> States;
2268d1485faSAxel Dörfler
2278d1485faSAxel Dörfler	void _ReturnState(GroupInterface *state);
2288d1485faSAxel Dörfler
2298d1485faSAxel Dörfler	ProtocolType *fParent;
2308d1485faSAxel Dörfler	States fStates;
2318d1485faSAxel Dörfler};
2328d1485faSAxel Dörfler
2338d1485faSAxel Dörfler
234