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/StringHash.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*
ToString(char * buffer,size_t bufferSize) const28 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
unix_copy_address(const sockaddr * from,sockaddr ** to,bool replaceWithZeros,const sockaddr * mask)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
unix_equal_addresses(const sockaddr * a,const sockaddr * b)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
unix_equal_ports(const sockaddr * a,const sockaddr * b)87 unix_equal_ports(const sockaddr *a, const sockaddr *b)
88 {
89 // no ports
90 return true;
91 }
92
93
94 static bool
unix_equal_addresses_and_ports(const sockaddr * a,const sockaddr * b)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
unix_equal_masked_addresses(const sockaddr * a,const sockaddr * b,const sockaddr * mask)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
unix_is_empty_address(const sockaddr * address,bool checkPort)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
unix_is_same_family(const sockaddr * address)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
unix_first_mask_bit(const sockaddr * mask)131 unix_first_mask_bit(const sockaddr *mask)
132 {
133 return 0;
134 }
135
136
137 static bool
unix_check_mask(const sockaddr * address)138 unix_check_mask(const sockaddr *address)
139 {
140 return false;
141 }
142
143
144 static status_t
unix_print_address_buffer(const sockaddr * _address,char * buffer,size_t bufferSize,bool printPort)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
unix_print_address(const sockaddr * address,char ** _buffer,bool printPort)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
unix_get_port(const sockaddr * address)181 unix_get_port(const sockaddr *address)
182 {
183 return 0;
184 }
185
186
187 static status_t
unix_set_port(sockaddr * address,uint16 port)188 unix_set_port(sockaddr *address, uint16 port)
189 {
190 return B_BAD_VALUE;
191 }
192
193
194 static status_t
unix_set_to(sockaddr * address,const sockaddr * from)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
unix_set_to_empty_address(sockaddr * address)209 unix_set_to_empty_address(sockaddr *address)
210 {
211 return unix_set_to(address, (sockaddr*)&kEmptyAddress);
212 }
213
214
215 static status_t
unix_mask_address(const sockaddr * address,const sockaddr * mask,sockaddr * result)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
unix_set_to_defaults(sockaddr * defaultMask,sockaddr * defaultBroadcast,const sockaddr * address,const sockaddr * netmask)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
unix_update_to(sockaddr * address,const sockaddr * from)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
unix_hash_address(const sockaddr * _address,bool includePort)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
unix_hash_address_pair(const sockaddr * ourAddress,const sockaddr * peerAddress)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
unix_checksum_address(Checksum * checksum,const sockaddr * _address)280 unix_checksum_address(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