2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
6 #include "UnixAddress.h"
12 #include <util/StringHash.h>
14 #include <net_datalink.h>
15 #include <NetUtilities.h>
20 static const sockaddr_un kEmptyAddress
= {
22 AF_UNIX
, // sun_family
23 { '\0', '\0' } // sun_path
28 UnixAddress::ToString(char *buffer
, size_t bufferSize
) const
31 strlcpy(buffer
, "<empty>", bufferSize
);
32 else if (IsInternalAddress())
33 snprintf(buffer
, bufferSize
, "<%05" B_PRIx32
">", fInternalID
);
35 snprintf(buffer
, bufferSize
, "<%" B_PRIdDEV
", %" B_PRIdINO
">",
47 unix_copy_address(const sockaddr
*from
, sockaddr
**to
, bool replaceWithZeros
,
50 if (replaceWithZeros
) {
51 sockaddr_un
* newAddress
= (sockaddr_un
*)malloc(kEmptyAddress
.sun_len
);
52 if (newAddress
== NULL
)
55 memcpy(newAddress
, &kEmptyAddress
, kEmptyAddress
.sun_len
);
57 *to
= (sockaddr
*)newAddress
;
60 if (from
->sa_family
!= AF_UNIX
)
61 return B_MISMATCHED_VALUES
;
63 *to
= (sockaddr
*)malloc(from
->sa_len
);
67 memcpy(*to
, from
, from
->sa_len
);
75 unix_equal_addresses(const sockaddr
*a
, const sockaddr
*b
)
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
)
82 return memcmp(a
, b
, a
->sa_len
) == 0;
87 unix_equal_ports(const sockaddr
*a
, const sockaddr
*b
)
95 unix_equal_addresses_and_ports(const sockaddr
*a
, const sockaddr
*b
)
97 return unix_equal_addresses(a
, b
);
102 unix_equal_masked_addresses(const sockaddr
*a
, const sockaddr
*b
,
103 const sockaddr
*mask
)
106 return unix_equal_addresses(a
, b
);
111 unix_is_empty_address(const sockaddr
*address
, bool checkPort
)
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);
121 unix_is_same_family(const sockaddr
*address
)
126 return address
->sa_family
== AF_UNIX
;
131 unix_first_mask_bit(const sockaddr
*mask
)
138 unix_check_mask(const sockaddr
*address
)
145 unix_print_address_buffer(const sockaddr
*_address
, char *buffer
,
146 size_t bufferSize
, bool printPort
)
151 sockaddr_un
* address
= (sockaddr_un
*)_address
;
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);
160 strlcpy(buffer
, "<empty>", bufferSize
);
167 unix_print_address(const sockaddr
*address
, char **_buffer
, bool printPort
)
170 status_t error
= unix_print_address_buffer(address
, buffer
, sizeof(buffer
),
175 *_buffer
= strdup(buffer
);
176 return *_buffer
!= NULL
? B_OK
: B_NO_MEMORY
;
181 unix_get_port(const sockaddr
*address
)
188 unix_set_port(sockaddr
*address
, uint16 port
)
195 unix_set_to(sockaddr
*address
, const sockaddr
*from
)
197 if (address
== NULL
|| from
== NULL
)
200 if (from
->sa_family
!= AF_UNIX
)
201 return B_MISMATCHED_VALUES
;
203 memcpy(address
, from
, from
->sa_len
);
209 unix_set_to_empty_address(sockaddr
*address
)
211 return unix_set_to(address
, (sockaddr
*)&kEmptyAddress
);
216 unix_mask_address(const sockaddr
*address
, const sockaddr
*mask
,
220 return unix_set_to(result
, address
);
225 unix_set_to_defaults(sockaddr
*defaultMask
, sockaddr
*defaultBroadcast
,
226 const sockaddr
*address
, const sockaddr
*netmask
)
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
);
242 unix_update_to(sockaddr
*address
, const sockaddr
*from
)
244 if (address
== NULL
|| from
== NULL
)
247 if (unix_is_empty_address(from
, false))
250 return unix_set_to(address
, from
);
255 unix_hash_address(const sockaddr
* _address
, bool includePort
)
257 sockaddr_un
* address
= (sockaddr_un
*)_address
;
261 if (address
->sun_path
[0] == '\0') {
263 strlcpy(buffer
, address
->sun_path
+ 1, 6);
264 return hash_hash_string(buffer
);
267 return hash_hash_string(address
->sun_path
);
272 unix_hash_address_pair(const sockaddr
*ourAddress
, const sockaddr
*peerAddress
)
274 return unix_hash_address(ourAddress
, false) * 17
275 + unix_hash_address(peerAddress
, false);
280 unix_checksum_address(struct Checksum
*checksum
, const sockaddr
*_address
)
282 if (checksum
== NULL
|| _address
== NULL
)
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
];
294 net_address_module_info gAddressModule
= {
300 NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS
,
303 unix_equal_addresses
,
305 unix_equal_addresses_and_ports
,
306 unix_equal_masked_addresses
,
307 unix_is_empty_address
,
312 unix_print_address_buffer
,
316 unix_set_to_empty_address
,
317 unix_set_to_defaults
,
320 unix_hash_address_pair
,
321 unix_checksum_address
,
322 NULL
// get_loopback_address