xref: /haiku/src/add-ons/kernel/network/protocols/unix/UnixAddress.cpp (revision 61729d9323a555b9025ef6ebeb85dc1627f8acf7)
1 /*
2  * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include "UnixAddress.h"
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include <util/khash.h>
13 
14 #include <net_datalink.h>
15 #include <NetUtilities.h>
16 
17 #include "unix.h"
18 
19 
20 static const sockaddr_un kEmptyAddress = {
21 	4,				// sun_len
22 	AF_UNIX,		// sun_family
23 	{ '\0', '\0' }	// sun_path
24 };
25 
26 
27 char*
28 UnixAddress::ToString(char *buffer, size_t bufferSize) const
29 {
30 	if (!IsValid())
31 		strlcpy(buffer, "<empty>", bufferSize);
32 	else if (IsInternalAddress())
33 		snprintf(buffer, bufferSize, "<%05lx>", fInternalID);
34 	else
35 		snprintf(buffer, bufferSize, "<%ld, %lld>", fVolumeID, fNodeID);
36 
37 	return buffer;
38 }
39 
40 
41 // #pragma mark -
42 
43 
44 static status_t
45 unix_copy_address(const sockaddr *from, sockaddr **to, bool replaceWithZeros,
46 	const sockaddr *mask)
47 {
48 	if (replaceWithZeros) {
49 		sockaddr_un* newAddress = (sockaddr_un*)malloc(kEmptyAddress.sun_len);
50 		if (newAddress == NULL)
51 			return B_NO_MEMORY;
52 
53 		memcpy(newAddress, &kEmptyAddress, kEmptyAddress.sun_len);
54 
55 		*to = (sockaddr*)newAddress;
56 		return B_OK;
57 	} else {
58 		if (from->sa_family != AF_UNIX)
59 			return B_MISMATCHED_VALUES;
60 
61 		*to = (sockaddr*)malloc(from->sa_len);
62 		if (*to == NULL)
63 			return B_NO_MEMORY;
64 
65 		memcpy(*to, from, from->sa_len);
66 
67 		return B_OK;
68 	}
69 }
70 
71 
72 static bool
73 unix_equal_addresses(const sockaddr *a, const sockaddr *b)
74 {
75 	// NOTE: We compare syntactically only. The real check would involve
76 	// looking up the node, if for FS addresses.
77 	if (a->sa_len != b->sa_len)
78 		return false;
79 
80 	return memcmp(a, b, a->sa_len) == 0;
81 }
82 
83 
84 static bool
85 unix_equal_ports(const sockaddr *a, const sockaddr *b)
86 {
87 	// no ports
88 	return true;
89 }
90 
91 
92 static bool
93 unix_equal_addresses_and_ports(const sockaddr *a, const sockaddr *b)
94 {
95 	return unix_equal_addresses(a, b);
96 }
97 
98 
99 static bool
100 unix_equal_masked_addresses(const sockaddr *a, const sockaddr *b,
101 	const sockaddr *mask)
102 {
103 	// no masks
104 	return unix_equal_addresses(a, b);
105 }
106 
107 
108 static bool
109 unix_is_empty_address(const sockaddr *address, bool checkPort)
110 {
111 	return address->sa_len >= kEmptyAddress.sun_len
112 		&& memcmp(address, &kEmptyAddress, kEmptyAddress.sun_len) == 0;
113 }
114 
115 static bool
116 unix_is_same_family(const sockaddr *address)
117 {
118 	if (address == NULL)
119 		return false;
120 
121 	return address->sa_family == AF_UNIX;
122 }
123 
124 static int32
125 unix_first_mask_bit(const sockaddr *mask)
126 {
127 	return 0;
128 }
129 
130 
131 static bool
132 unix_check_mask(const sockaddr *address)
133 {
134 	return false;
135 }
136 
137 
138 static status_t
139 unix_print_address_buffer(const sockaddr *_address, char *buffer,
140 	size_t bufferSize, bool printPort)
141 {
142 	if (!buffer)
143 		return B_BAD_VALUE;
144 
145 	sockaddr_un* address = (sockaddr_un*)_address;
146 
147 	if (address == NULL)
148 		strlcpy(buffer, "<none>", bufferSize);
149 	else if (address->sun_path[0] != '\0')
150 		strlcpy(buffer, address->sun_path, bufferSize);
151 	else if (address->sun_path[1] != '\0')
152 		snprintf(buffer, bufferSize, "<%.5s>", address->sun_path + 1);
153 	else
154 		strlcpy(buffer, "<empty>", bufferSize);
155 
156 	return B_OK;
157 }
158 
159 
160 static status_t
161 unix_print_address(const sockaddr *address, char **_buffer, bool printPort)
162 {
163 	char buffer[128];
164 	status_t error = unix_print_address_buffer(address, buffer, sizeof(buffer),
165 		printPort);
166 	if (error != B_OK)
167 		return error;
168 
169 	*_buffer = strdup(buffer);
170 	return *_buffer != NULL ? B_OK : B_NO_MEMORY;
171 }
172 
173 
174 static uint16
175 unix_get_port(const sockaddr *address)
176 {
177 	return 0;
178 }
179 
180 
181 static status_t
182 unix_set_port(sockaddr *address, uint16 port)
183 {
184 	return B_BAD_VALUE;
185 }
186 
187 
188 static status_t
189 unix_set_to(sockaddr *address, const sockaddr *from)
190 {
191 	if (address == NULL || from == NULL)
192 		return B_BAD_VALUE;
193 
194 	if (from->sa_family != AF_UNIX)
195 		return B_MISMATCHED_VALUES;
196 
197 	memcpy(address, from, from->sa_len);
198 	return B_OK;
199 }
200 
201 
202 static status_t
203 unix_set_to_empty_address(sockaddr *address)
204 {
205 	return unix_set_to(address, (sockaddr*)&kEmptyAddress);
206 }
207 
208 
209 static status_t
210 unix_mask_address(const sockaddr *address, const sockaddr *mask,
211 	sockaddr *result)
212 {
213 	// no masks
214 	return unix_set_to(result, address);
215 }
216 
217 
218 static status_t
219 unix_set_to_defaults(sockaddr *defaultMask, sockaddr *defaultBroadcast,
220 	const sockaddr *address, const sockaddr *netmask)
221 {
222 	if (address == NULL)
223 		return B_BAD_VALUE;
224 
225 	status_t error = B_OK;
226 	if (defaultMask != NULL)
227 		error = unix_set_to_empty_address(defaultMask);
228 	if (error == B_OK && defaultBroadcast != NULL)
229 		error = unix_set_to_empty_address(defaultBroadcast);
230 
231 	return error;
232 }
233 
234 
235 static status_t
236 unix_update_to(sockaddr *address, const sockaddr *from)
237 {
238 	if (address == NULL || from == NULL)
239 		return B_BAD_VALUE;
240 
241 	if (unix_is_empty_address(from, false))
242 		return B_OK;
243 
244 	return unix_set_to(address, from);
245 }
246 
247 
248 static uint32
249 unix_hash_address(const sockaddr* _address, bool includePort)
250 {
251 	sockaddr_un* address = (sockaddr_un*)_address;
252 	if (address == NULL)
253 		return 0;
254 
255 	if (address->sun_path[0] == '\0') {
256 		char buffer[6];
257 		strlcpy(buffer, address->sun_path + 1, 6);
258 		return hash_hash_string(buffer);
259 	}
260 
261 	return hash_hash_string(address->sun_path);
262 }
263 
264 
265 static uint32
266 unix_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress)
267 {
268 	return unix_hash_address(ourAddress, false) * 17
269 		+ unix_hash_address(peerAddress, false);
270 }
271 
272 
273 static status_t
274 unix_checksum_address(struct Checksum *checksum, const sockaddr *_address)
275 {
276 	if (checksum == NULL || _address == NULL)
277 		return B_BAD_VALUE;
278 
279 	sockaddr_un* address = (sockaddr_un*)_address;
280 	int len = (char*)address + address->sun_len - address->sun_path;
281 	for (int i = 0; i < len; i++)
282 		(*checksum) << (uint8)address->sun_path[i];
283 
284 	return B_OK;
285 }
286 
287 
288 net_address_module_info gAddressModule = {
289 	{
290 		NULL,
291 		0,
292 		NULL
293 	},
294 	NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS,
295 	unix_copy_address,
296 	unix_mask_address,
297 	unix_equal_addresses,
298 	unix_equal_ports,
299 	unix_equal_addresses_and_ports,
300 	unix_equal_masked_addresses,
301 	unix_is_empty_address,
302 	unix_is_same_family,
303 	unix_first_mask_bit,
304 	unix_check_mask,
305 	unix_print_address,
306 	unix_print_address_buffer,
307 	unix_get_port,
308 	unix_set_port,
309 	unix_set_to,
310 	unix_set_to_empty_address,
311 	unix_set_to_defaults,
312 	unix_update_to,
313 	unix_hash_address,
314 	unix_hash_address_pair,
315 	unix_checksum_address,
316 	NULL	// get_loopback_address
317 };
318