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