xref: /haiku/src/add-ons/kernel/network/protocols/unix/UnixAddress.cpp (revision 4b3b81da9e459443d75329cfd08bc9a57ad02653)
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 
116 static int32
117 unix_first_mask_bit(const sockaddr *mask)
118 {
119 	return 0;
120 }
121 
122 
123 static bool
124 unix_check_mask(const sockaddr *address)
125 {
126 	return false;
127 }
128 
129 
130 static status_t
131 unix_print_address_buffer(const sockaddr *_address, char *buffer,
132 	size_t bufferSize, bool printPort)
133 {
134 	if (!buffer)
135 		return B_BAD_VALUE;
136 
137 	sockaddr_un* address = (sockaddr_un*)_address;
138 
139 	if (address == NULL)
140 		strlcpy(buffer, "<none>", bufferSize);
141 	else if (address->sun_path[0] != '\0')
142 		strlcpy(buffer, address->sun_path, bufferSize);
143 	else if (address->sun_path[1] != '\0')
144 		snprintf(buffer, bufferSize, "<%.5s>", address->sun_path + 1);
145 	else
146 		strlcpy(buffer, "<empty>", bufferSize);
147 
148 	return B_OK;
149 }
150 
151 
152 static status_t
153 unix_print_address(const sockaddr *address, char **_buffer, bool printPort)
154 {
155 	char buffer[128];
156 	status_t error = unix_print_address_buffer(address, buffer, sizeof(buffer),
157 		printPort);
158 	if (error != B_OK)
159 		return error;
160 
161 	*_buffer = strdup(buffer);
162 	return *_buffer != NULL ? B_OK : B_NO_MEMORY;
163 }
164 
165 
166 static uint16
167 unix_get_port(const sockaddr *address)
168 {
169 	return 0;
170 }
171 
172 
173 static status_t
174 unix_set_port(sockaddr *address, uint16 port)
175 {
176 	return B_BAD_VALUE;
177 }
178 
179 
180 static status_t
181 unix_set_to(sockaddr *address, const sockaddr *from)
182 {
183 	if (address == NULL || from == NULL)
184 		return B_BAD_VALUE;
185 
186 	if (from->sa_family != AF_UNIX)
187 		return B_MISMATCHED_VALUES;
188 
189 	memcpy(address, from, from->sa_len);
190 	return B_OK;
191 }
192 
193 
194 static status_t
195 unix_set_to_empty_address(sockaddr *address)
196 {
197 	return unix_set_to(address, (sockaddr*)&kEmptyAddress);
198 }
199 
200 
201 static status_t
202 unix_mask_address(const sockaddr *address, const sockaddr *mask,
203 	sockaddr *result)
204 {
205 	// no masks
206 	return unix_set_to(result, address);
207 }
208 
209 
210 static status_t
211 unix_set_to_defaults(sockaddr *defaultMask, sockaddr *defaultBroadcast,
212 	sockaddr *address, sockaddr *netmask)
213 {
214 	if (address == NULL)
215 		return B_BAD_VALUE;
216 
217 	status_t error = B_OK;
218 	if (defaultMask != NULL)
219 		error = unix_set_to_empty_address(defaultMask);
220 	if (error == B_OK && defaultBroadcast != NULL)
221 		error = unix_set_to_empty_address(defaultBroadcast);
222 
223 	return error;
224 }
225 
226 
227 static status_t
228 unix_update_to(sockaddr *address, const sockaddr *from)
229 {
230 	if (address == NULL || from == NULL)
231 		return B_BAD_VALUE;
232 
233 	if (unix_is_empty_address(from, false))
234 		return B_OK;
235 
236 	return unix_set_to(address, from);
237 }
238 
239 
240 static uint32
241 hash_address(const sockaddr_un* address)
242 {
243 	if (address == NULL)
244 		return 0;
245 
246 	if (address->sun_path[0] == '\0') {
247 		char buffer[6];
248 		strlcpy(buffer, address->sun_path + 1, 6);
249 		return hash_hash_string(buffer);
250 	}
251 
252 	return hash_hash_string(address->sun_path);
253 }
254 
255 
256 static uint32
257 unix_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress)
258 {
259 	return hash_address((sockaddr_un*)ourAddress) * 17
260 		+ hash_address((sockaddr_un*)peerAddress);
261 }
262 
263 
264 static status_t
265 unix_checksum_address(struct Checksum *checksum, const sockaddr *_address)
266 {
267 	if (checksum == NULL || _address == NULL)
268 		return B_BAD_VALUE;
269 
270 	sockaddr_un* address = (sockaddr_un*)_address;
271 	int len = (char*)address + address->sun_len - address->sun_path;
272 	for (int i = 0; i < len; i++)
273 		(*checksum) << (uint8)address->sun_path[i];
274 
275 	return B_OK;
276 }
277 
278 
279 net_address_module_info gAddressModule = {
280 	{
281 		NULL,
282 		0,
283 		NULL
284 	},
285 
286 	unix_copy_address,
287 	unix_mask_address,
288 	unix_equal_addresses,
289 	unix_equal_ports,
290 	unix_equal_addresses_and_ports,
291 	unix_equal_masked_addresses,
292 	unix_is_empty_address,
293 	unix_first_mask_bit,
294 	unix_check_mask,
295 	unix_print_address,
296 	unix_print_address_buffer,
297 	unix_get_port,
298 	unix_set_port,
299 	unix_set_to,
300 	unix_set_to_empty_address,
301 	unix_set_to_defaults,
302 	unix_update_to,
303 	unix_hash_address_pair,
304 	unix_checksum_address,
305 	NULL	// matches_broadcast_address
306 };
307