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