xref: /haiku/src/add-ons/kernel/network/protocols/unix/UnixAddress.h (revision eb8b342d5610c48f6eb319d6726491e4f360e005)
1 /*
2  * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef UNIX_ADDRESS_H
6 #define UNIX_ADDRESS_H
7 
8 #include <sys/un.h>
9 
10 #include <SupportDefs.h>
11 
12 
13 // NOTE: We support the standard FS address space as well as the alternative
14 // internal address space Linux features (sun_path[0] is 0, followed by 5 hex
15 // digits, without null-termination). The latter one is nice to have, because
16 // the address lookup is quick (hash table lookup, instead of asking the VFS to
17 // resolve the path), and we don't have to pollute the FS when auto-binding
18 // sockets (e.g. on connect()).
19 
20 
21 #define	INTERNAL_UNIX_ADDRESS_LEN	(2 + 1 + 5)
22 	// sun_len + sun_family + null byte + 5 hex digits
23 
24 
25 struct vnode;
26 
27 
28 class UnixAddress {
29 public:
UnixAddress()30 	UnixAddress()
31 	{
32 		Unset();
33 	}
34 
UnixAddress(const UnixAddress & other)35 	UnixAddress(const UnixAddress& other)
36 	{
37 		*this = other;
38 	}
39 
UnixAddress(int32 internalID)40 	UnixAddress(int32 internalID)
41 	{
42 		SetTo(internalID);
43 	}
44 
UnixAddress(dev_t volumeID,ino_t nodeID,struct vnode * vnode)45 	UnixAddress(dev_t volumeID, ino_t nodeID, struct vnode* vnode)
46 	{
47 		SetTo(volumeID, nodeID, vnode);
48 	}
49 
SetTo(int32 internalID)50 	void SetTo(int32 internalID)
51 	{
52 		fInternalID = internalID;
53 		fVolumeID = -1;
54 		fNodeID = -1;
55 		fVnode = NULL;
56 	}
57 
SetTo(dev_t volumeID,ino_t nodeID,struct vnode * vnode)58 	void SetTo(dev_t volumeID, ino_t nodeID, struct vnode* vnode)
59 	{
60 		fInternalID = -1;
61 		fVolumeID = volumeID;
62 		fNodeID = nodeID;
63 		fVnode = vnode;
64 	}
65 
Unset()66 	void Unset()
67 	{
68 		fInternalID = -1;
69 		fVolumeID = -1;
70 		fNodeID = -1;
71 		fVnode = NULL;
72 	}
73 
IsValid()74 	bool IsValid() const
75 	{
76 		return fInternalID >= 0 || fVolumeID >= 0;
77 	}
78 
IsInternalAddress()79 	bool IsInternalAddress() const
80 	{
81 		return fInternalID >= 0;
82 	}
83 
InternalID()84 	int32 InternalID() const
85 	{
86 		return fInternalID;
87 	}
88 
VolumeID()89 	int32 VolumeID() const
90 	{
91 		return fVolumeID;
92 	}
93 
NodeID()94 	int32 NodeID() const
95 	{
96 		return fNodeID;
97 	}
98 
Vnode()99 	struct vnode* Vnode() const
100 	{
101 		return fVnode;
102 	}
103 
HashCode()104 	uint32 HashCode() const
105 	{
106 		return fInternalID >= 0
107 			? fInternalID
108 			: uint32(fVolumeID) ^ uint32(fNodeID);
109 	}
110 
111 	char* ToString(char *buffer, size_t bufferSize) const;
112 
113 	UnixAddress& operator=(const UnixAddress& other)
114 	{
115 		fInternalID = other.fInternalID;
116 		fVolumeID = other.fVolumeID;
117 		fNodeID = other.fNodeID;
118 		fVnode = other.fVnode;
119 		return *this;
120 	}
121 
122 	bool operator==(const UnixAddress& other) const
123 	{
124 		return fInternalID >= 0
125 			? fInternalID == other.fInternalID
126 			: fVolumeID == other.fVolumeID
127 				&& fNodeID == other.fNodeID;
128 	}
129 
130 	bool operator!=(const UnixAddress& other) const
131 	{
132 		return !(*this == other);
133 	}
134 
IsEmptyAddress(const sockaddr_un & address)135 	static bool IsEmptyAddress(const sockaddr_un& address)
136 	{
137 		return address.sun_len == sizeof(sockaddr)
138 			&& address.sun_path[0] == '\0' && address.sun_path[1] == '\0';
139 	}
140 
InternalID(const sockaddr_un & address)141 	static int32 InternalID(const sockaddr_un& address)
142 	{
143 		if (address.sun_len < INTERNAL_UNIX_ADDRESS_LEN
144 				|| address.sun_path[0] != '\0') {
145 			return B_BAD_VALUE;
146 		}
147 
148 		// parse the ID
149 		int32 id = 0;
150 
151 		for (int32 i = 0; i < 5; i++) {
152 			char c = address.sun_path[i + 1];
153 			if (c >= '0' && c <= '9')
154 				id = (id << 4) + (c - '0');
155 			else if (c >= 'a' && c <= 'f')
156 				id = (id << 4) + 10 + (c - 'a');
157 			else
158 				return B_BAD_VALUE;
159 		}
160 
161 		return id;
162 	}
163 
164 private:
165 	// fat interface: If fInternalID is >= 0, it's an address in the internal
166 	// namespace, otherwise a FS address.
167 	int32			fInternalID;
168 	dev_t			fVolumeID;
169 	ino_t			fNodeID;
170 	struct vnode*	fVnode;
171 };
172 
173 
174 #endif	// UNIX_ADDRESS_H
175