1/*
2 * Copyright 2006-2011, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Axel D��rfler, axeld@pinc-software.de
7 */
8#ifndef INTERFACES_H
9#define INTERFACES_H
10
11
12#include "routes.h"
13#include "stack_private.h"
14
15#include <net_datalink.h>
16#include <net_stack.h>
17
18#include <Referenceable.h>
19
20#include <util/AutoLock.h>
21#include <util/DoublyLinkedList.h>
22#include <util/OpenHashTable.h>
23
24
25struct net_device_interface;
26
27
28// Additional address flags
29#define IFAF_DIRECT_ADDRESS		0x1000
30
31
32struct InterfaceAddress : DoublyLinkedListLinkImpl<InterfaceAddress>,
33		net_interface_address, BReferenceable {
34								InterfaceAddress();
35								InterfaceAddress(net_interface* interface,
36									net_domain* domain);
37	virtual						~InterfaceAddress();
38
39			status_t			SetTo(const ifaliasreq& request);
40
41			status_t			SetLocal(const sockaddr* to);
42			status_t			SetDestination(const sockaddr* to);
43			status_t			SetMask(const sockaddr* to);
44
45			sockaddr**			AddressFor(int32 option);
46
47			void				AddDefaultRoutes(int32 option);
48			void				RemoveDefaultRoutes(int32 option);
49
50			bool				LocalIsDefined() const;
51
52			InterfaceAddress*&	HashTableLink() { return fLink; }
53
54#if ENABLE_DEBUGGER_COMMANDS
55			void				Dump(size_t index = 0,
56									bool hideInterface = false);
57#endif
58
59	static	status_t			Set(sockaddr** _address, const sockaddr* to);
60	static	sockaddr*			Prepare(sockaddr** _address, size_t length);
61
62private:
63			void				_Init(net_interface* interface,
64									net_domain* domain);
65
66private:
67			InterfaceAddress*	fLink;
68};
69
70typedef DoublyLinkedList<InterfaceAddress> AddressList;
71
72struct domain_datalink {
73	domain_datalink*	hash_link;
74	net_domain*			domain;
75
76	struct net_datalink_protocol* first_protocol;
77	struct net_datalink_protocol_module_info* first_info;
78
79	// support for binding to an interface
80	net_route_private	direct_route;
81	InterfaceAddress	direct_address;
82};
83
84struct DatalinkHashDefinition {
85	typedef const int KeyType;
86	typedef domain_datalink ValueType;
87
88	DatalinkHashDefinition()
89	{
90	}
91
92	size_t HashKey(const KeyType& key) const
93	{
94		return (size_t)key;
95	}
96
97	size_t Hash(domain_datalink* datalink) const
98	{
99		return datalink->domain->family;
100	}
101
102	bool Compare(const KeyType& key, domain_datalink* datalink) const
103	{
104		return datalink->domain->family == key;
105	}
106
107	domain_datalink*& GetLink(domain_datalink* datalink) const
108	{
109		return datalink->hash_link;
110	}
111};
112
113typedef BOpenHashTable<DatalinkHashDefinition, true, true> DatalinkTable;
114
115
116class Interface : public DoublyLinkedListLinkImpl<Interface>,
117		public net_interface, public BReferenceable {
118public:
119								Interface(const char* name,
120									net_device_interface* deviceInterface);
121	virtual						~Interface();
122
123			InterfaceAddress*	FirstForFamily(int family);
124			InterfaceAddress*	FirstUnconfiguredForFamily(int family);
125			InterfaceAddress*	AddressForDestination(net_domain* domain,
126									const sockaddr* destination);
127			InterfaceAddress*	AddressForLocal(net_domain* domain,
128									const sockaddr* local);
129
130			status_t			AddAddress(InterfaceAddress* address);
131			void				RemoveAddress(InterfaceAddress* address);
132			bool				GetNextAddress(InterfaceAddress** _address);
133			InterfaceAddress*	AddressAt(size_t index);
134			int32				IndexOfAddress(InterfaceAddress* address);
135			size_t				CountAddresses();
136			void				RemoveAddresses();
137
138			status_t			Control(net_domain* domain, int32 option,
139									ifreq& request, ifreq* userRequest,
140									size_t length);
141
142			void				SetDown();
143			void				WentDown();
144
145			recursive_lock&		Lock() { return fLock; }
146
147			net_device_interface* DeviceInterface() { return fDeviceInterface; }
148
149			status_t			CreateDomainDatalinkIfNeeded(
150									net_domain* domain);
151			domain_datalink*	DomainDatalink(uint8 family);
152			domain_datalink*	DomainDatalink(net_domain* domain)
153									{ return DomainDatalink(domain->family); }
154
155	inline	void				SetBusy(bool busy) { atomic_set(&fBusy, busy ? 1 : 0); }
156	inline	bool				IsBusy() const { return atomic_get((int32*)&fBusy) == 1 ; }
157
158#if ENABLE_DEBUGGER_COMMANDS
159			void				Dump() const;
160#endif
161
162private:
163			status_t			_SetUp();
164			InterfaceAddress*	_FirstForFamily(int family);
165			status_t			_ChangeAddress(RecursiveLocker& locker,
166									InterfaceAddress* address, int32 option,
167									const sockaddr* oldAddress,
168									const sockaddr* newAddress);
169
170private:
171			recursive_lock		fLock;
172			int32				fBusy;
173			net_device_interface* fDeviceInterface;
174			AddressList			fAddresses;
175			DatalinkTable		fDatalinkTable;
176};
177
178typedef DoublyLinkedList<Interface> InterfaceList;
179
180
181status_t init_interfaces();
182status_t uninit_interfaces();
183
184// interfaces
185status_t add_interface(const char* name, net_domain_private* domain,
186	const ifaliasreq& request, net_device_interface* deviceInterface);
187void remove_interface(Interface* interface);
188void interface_removed_device_interface(net_device_interface* deviceInterface);
189
190status_t add_interface_address(Interface* interface, net_domain_private* domain,
191	const ifaliasreq& request);
192status_t update_interface_address(InterfaceAddress* interfaceAddress,
193	int32 option, const sockaddr* oldAddress, const sockaddr* newAddress);
194
195Interface* get_interface(net_domain* domain, uint32 index);
196Interface* get_interface(net_domain* domain, const char* name);
197Interface* get_interface_for_device(net_domain* domain, uint32 index);
198Interface* get_interface_for_link(net_domain* domain, const sockaddr* address);
199InterfaceAddress* get_interface_address(const struct sockaddr* address);
200InterfaceAddress* get_interface_address_for_destination(net_domain* domain,
201	const sockaddr* destination);
202InterfaceAddress* get_interface_address_for_link(net_domain* domain,
203	const sockaddr* linkAddress, bool unconfiguredOnly);
204
205uint32 count_interfaces();
206status_t list_interfaces(int family, void* buffer, size_t* _bufferSize);
207
208
209#endif	// INTERFACES_H
210