1 /* 2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <stdio.h> 8 #include <sys/un.h> 9 10 #include <new> 11 12 #include <AutoDeleter.h> 13 14 #include <fs/fd.h> 15 #include <lock.h> 16 #include <util/AutoLock.h> 17 #include <vfs.h> 18 19 #include <net_buffer.h> 20 #include <net_protocol.h> 21 #include <net_socket.h> 22 #include <net_stack.h> 23 24 #include "UnixAddressManager.h" 25 #include "UnixEndpoint.h" 26 27 28 #define UNIX_MODULE_DEBUG_LEVEL 0 29 #define UNIX_DEBUG_LEVEL UNIX_MODULE_DEBUG_LEVEL 30 #include "UnixDebug.h" 31 32 33 extern net_protocol_module_info gUnixModule; 34 // extern only for forwarding 35 36 net_stack_module_info *gStackModule; 37 net_socket_module_info *gSocketModule; 38 net_buffer_module_info *gBufferModule; 39 UnixAddressManager gAddressManager; 40 41 static struct net_domain *sDomain; 42 43 44 void 45 destroy_scm_rights_descriptors(const ancillary_data_header* header, 46 void* data) 47 { 48 int count = header->len / sizeof(file_descriptor*); 49 file_descriptor** descriptors = (file_descriptor**)data; 50 io_context* ioContext = get_current_io_context(!gStackModule->is_syscall()); 51 52 for (int i = 0; i < count; i++) { 53 if (descriptors[i] != NULL) { 54 close_fd(ioContext, descriptors[i]); 55 put_fd(descriptors[i]); 56 } 57 } 58 } 59 60 61 // #pragma mark - 62 63 64 net_protocol * 65 unix_init_protocol(net_socket *socket) 66 { 67 TRACE("[%" B_PRId32 "] unix_init_protocol(%p)\n", find_thread(NULL), 68 socket); 69 70 UnixEndpoint* endpoint = new(std::nothrow) UnixEndpoint(socket); 71 if (endpoint == NULL) 72 return NULL; 73 74 status_t error = endpoint->Init(); 75 if (error != B_OK) { 76 delete endpoint; 77 return NULL; 78 } 79 80 return endpoint; 81 } 82 83 84 status_t 85 unix_uninit_protocol(net_protocol *_protocol) 86 { 87 TRACE("[%" B_PRId32 "] unix_uninit_protocol(%p)\n", find_thread(NULL), 88 _protocol); 89 ((UnixEndpoint*)_protocol)->Uninit(); 90 return B_OK; 91 } 92 93 94 status_t 95 unix_open(net_protocol *_protocol) 96 { 97 return ((UnixEndpoint*)_protocol)->Open(); 98 } 99 100 101 status_t 102 unix_close(net_protocol *_protocol) 103 { 104 return ((UnixEndpoint*)_protocol)->Close(); 105 } 106 107 108 status_t 109 unix_free(net_protocol *_protocol) 110 { 111 return ((UnixEndpoint*)_protocol)->Free(); 112 } 113 114 115 status_t 116 unix_connect(net_protocol *_protocol, const struct sockaddr *address) 117 { 118 return ((UnixEndpoint*)_protocol)->Connect(address); 119 } 120 121 122 status_t 123 unix_accept(net_protocol *_protocol, struct net_socket **_acceptedSocket) 124 { 125 return ((UnixEndpoint*)_protocol)->Accept(_acceptedSocket); 126 } 127 128 129 status_t 130 unix_control(net_protocol *protocol, int level, int option, void *value, 131 size_t *_length) 132 { 133 return B_BAD_VALUE; 134 } 135 136 137 status_t 138 unix_getsockopt(net_protocol *protocol, int level, int option, void *value, 139 int *_length) 140 { 141 UnixEndpoint* endpoint = (UnixEndpoint*)protocol; 142 143 if (level == SOL_SOCKET && option == SO_PEERCRED) { 144 if (*_length < (int)sizeof(ucred)) 145 return B_BAD_VALUE; 146 147 *_length = sizeof(ucred); 148 149 return endpoint->GetPeerCredentials((ucred*)value); 150 } 151 152 return gSocketModule->get_option(protocol->socket, level, option, value, 153 _length); 154 } 155 156 157 status_t 158 unix_setsockopt(net_protocol *protocol, int level, int option, 159 const void *_value, int length) 160 { 161 UnixEndpoint* endpoint = (UnixEndpoint*)protocol; 162 163 if (level == SOL_SOCKET) { 164 if (option == SO_RCVBUF) { 165 if (length != sizeof(int)) 166 return B_BAD_VALUE; 167 168 status_t error = endpoint->SetReceiveBufferSize(*(int*)_value); 169 if (error != B_OK) 170 return error; 171 } else if (option == SO_SNDBUF) { 172 // We don't have a receive buffer, so silently ignore this one. 173 } 174 } 175 176 return gSocketModule->set_option(protocol->socket, level, option, 177 _value, length); 178 } 179 180 181 status_t 182 unix_bind(net_protocol *_protocol, const struct sockaddr *_address) 183 { 184 return ((UnixEndpoint*)_protocol)->Bind(_address); 185 } 186 187 188 status_t 189 unix_unbind(net_protocol *_protocol, struct sockaddr *_address) 190 { 191 return ((UnixEndpoint*)_protocol)->Unbind(); 192 } 193 194 195 status_t 196 unix_listen(net_protocol *_protocol, int count) 197 { 198 return ((UnixEndpoint*)_protocol)->Listen(count); 199 } 200 201 202 status_t 203 unix_shutdown(net_protocol *_protocol, int direction) 204 { 205 return ((UnixEndpoint*)_protocol)->Shutdown(direction); 206 } 207 208 209 status_t 210 unix_send_routed_data(net_protocol *_protocol, struct net_route *route, 211 net_buffer *buffer) 212 { 213 return B_ERROR; 214 } 215 216 217 status_t 218 unix_send_data(net_protocol *_protocol, net_buffer *buffer) 219 { 220 return B_ERROR; 221 } 222 223 224 ssize_t 225 unix_send_avail(net_protocol *_protocol) 226 { 227 return ((UnixEndpoint*)_protocol)->Sendable(); 228 } 229 230 231 status_t 232 unix_read_data(net_protocol *_protocol, size_t numBytes, uint32 flags, 233 net_buffer **_buffer) 234 { 235 return B_ERROR; 236 } 237 238 239 ssize_t 240 unix_read_avail(net_protocol *_protocol) 241 { 242 return ((UnixEndpoint*)_protocol)->Receivable(); 243 } 244 245 246 struct net_domain * 247 unix_get_domain(net_protocol *protocol) 248 { 249 return sDomain; 250 } 251 252 253 size_t 254 unix_get_mtu(net_protocol *protocol, const struct sockaddr *address) 255 { 256 return UNIX_MAX_TRANSFER_UNIT; 257 } 258 259 260 status_t 261 unix_receive_data(net_buffer *buffer) 262 { 263 return B_ERROR; 264 } 265 266 267 status_t 268 unix_deliver_data(net_protocol *_protocol, net_buffer *buffer) 269 { 270 return B_ERROR; 271 } 272 273 274 status_t 275 unix_error_received(net_error error, net_buffer *data) 276 { 277 return B_ERROR; 278 } 279 280 281 status_t 282 unix_error_reply(net_protocol *protocol, net_buffer *cause, net_error error, 283 net_error_data *errorData) 284 { 285 return B_ERROR; 286 } 287 288 289 status_t 290 unix_add_ancillary_data(net_protocol *self, ancillary_data_container *container, 291 const cmsghdr *header) 292 { 293 TRACE("[%" B_PRId32 "] unix_add_ancillary_data(%p, %p, %p (level: %d, type: %d, " 294 "len: %" B_PRId32 "))\n", find_thread(NULL), self, container, header, 295 header->cmsg_level, header->cmsg_type, header->cmsg_len); 296 297 // we support only SCM_RIGHTS 298 if (header->cmsg_level != SOL_SOCKET || header->cmsg_type != SCM_RIGHTS) 299 return B_BAD_VALUE; 300 301 int* fds = (int*)CMSG_DATA(header); 302 int count = (header->cmsg_len - CMSG_ALIGN(sizeof(cmsghdr))) / sizeof(int); 303 if (count == 0) 304 return B_BAD_VALUE; 305 306 file_descriptor** descriptors = new(std::nothrow) file_descriptor*[count]; 307 if (descriptors == NULL) 308 return ENOBUFS; 309 ArrayDeleter<file_descriptor*> _(descriptors); 310 memset(descriptors, 0, sizeof(file_descriptor*) * count); 311 312 // get the file descriptors 313 io_context* ioContext = get_current_io_context(!gStackModule->is_syscall()); 314 315 status_t error = B_OK; 316 for (int i = 0; i < count; i++) { 317 descriptors[i] = get_open_fd(ioContext, fds[i]); 318 if (descriptors[i] == NULL) { 319 error = EBADF; 320 break; 321 } 322 } 323 324 // attach the ancillary data to the container 325 if (error == B_OK) { 326 ancillary_data_header header; 327 header.level = SOL_SOCKET; 328 header.type = SCM_RIGHTS; 329 header.len = count * sizeof(file_descriptor*); 330 331 TRACE("[%" B_PRId32 "] unix_add_ancillary_data(): adding %d FDs to " 332 "container\n", find_thread(NULL), count); 333 334 error = gStackModule->add_ancillary_data(container, &header, 335 descriptors, destroy_scm_rights_descriptors, NULL); 336 } 337 338 // cleanup on error 339 if (error != B_OK) { 340 for (int i = 0; i < count; i++) { 341 if (descriptors[i] != NULL) { 342 close_fd(ioContext, descriptors[i]); 343 put_fd(descriptors[i]); 344 } 345 } 346 } 347 348 return error; 349 } 350 351 352 ssize_t 353 unix_process_ancillary_data(net_protocol *self, 354 const ancillary_data_header *header, const void *data, void *buffer, 355 size_t bufferSize) 356 { 357 TRACE("[%" B_PRId32 "] unix_process_ancillary_data(%p, %p (level: %d, " 358 "type: %d, len: %lu), %p, %p, %lu)\n", find_thread(NULL), self, header, 359 header->level, header->type, header->len, data, buffer, bufferSize); 360 361 // we support only SCM_RIGHTS 362 if (header->level != SOL_SOCKET || header->type != SCM_RIGHTS) 363 return B_BAD_VALUE; 364 365 int count = header->len / sizeof(file_descriptor*); 366 file_descriptor** descriptors = (file_descriptor**)data; 367 368 // check if there's enough space in the buffer 369 size_t neededBufferSpace = CMSG_SPACE(sizeof(int) * count); 370 if (bufferSize < neededBufferSpace) 371 return B_BAD_VALUE; 372 373 // init header 374 cmsghdr* messageHeader = (cmsghdr*)buffer; 375 messageHeader->cmsg_level = header->level; 376 messageHeader->cmsg_type = header->type; 377 messageHeader->cmsg_len = CMSG_LEN(sizeof(int) * count); 378 379 // create FDs for the current process 380 int* fds = (int*)CMSG_DATA(messageHeader); 381 io_context* ioContext = get_current_io_context(!gStackModule->is_syscall()); 382 383 status_t error = B_OK; 384 for (int i = 0; i < count; i++) { 385 // Get an additional reference which will go to the FD table index. The 386 // reference and open reference acquired in unix_add_ancillary_data() 387 // will be released when the container is destroyed. 388 inc_fd_ref_count(descriptors[i]); 389 fds[i] = new_fd(ioContext, descriptors[i]); 390 391 if (fds[i] < 0) { 392 error = fds[i]; 393 put_fd(descriptors[i]); 394 395 // close FD indices 396 for (int k = i - 1; k >= 0; k--) 397 close_fd_index(ioContext, fds[k]); 398 break; 399 } 400 } 401 402 return error == B_OK ? neededBufferSpace : error; 403 } 404 405 406 ssize_t 407 unix_send_data_no_buffer(net_protocol *_protocol, const iovec *vecs, 408 size_t vecCount, ancillary_data_container *ancillaryData, 409 const struct sockaddr *address, socklen_t addressLength) 410 { 411 return ((UnixEndpoint*)_protocol)->Send(vecs, vecCount, ancillaryData); 412 } 413 414 415 ssize_t 416 unix_read_data_no_buffer(net_protocol *_protocol, const iovec *vecs, 417 size_t vecCount, ancillary_data_container **_ancillaryData, 418 struct sockaddr *_address, socklen_t *_addressLength) 419 { 420 return ((UnixEndpoint*)_protocol)->Receive(vecs, vecCount, _ancillaryData, 421 _address, _addressLength); 422 } 423 424 425 // #pragma mark - 426 427 428 status_t 429 init_unix() 430 { 431 new(&gAddressManager) UnixAddressManager; 432 status_t error = gAddressManager.Init(); 433 if (error != B_OK) 434 return error; 435 436 error = gStackModule->register_domain_protocols(AF_UNIX, SOCK_STREAM, 0, 437 "network/protocols/unix/v1", NULL); 438 if (error != B_OK) { 439 gAddressManager.~UnixAddressManager(); 440 return error; 441 } 442 443 error = gStackModule->register_domain(AF_UNIX, "unix", &gUnixModule, 444 &gAddressModule, &sDomain); 445 if (error != B_OK) { 446 gAddressManager.~UnixAddressManager(); 447 return error; 448 } 449 450 return B_OK; 451 } 452 453 454 status_t 455 uninit_unix() 456 { 457 gStackModule->unregister_domain(sDomain); 458 459 gAddressManager.~UnixAddressManager(); 460 461 return B_OK; 462 } 463 464 465 static status_t 466 unix_std_ops(int32 op, ...) 467 { 468 switch (op) { 469 case B_MODULE_INIT: 470 return init_unix(); 471 case B_MODULE_UNINIT: 472 return uninit_unix(); 473 474 default: 475 return B_ERROR; 476 } 477 } 478 479 480 net_protocol_module_info gUnixModule = { 481 { 482 "network/protocols/unix/v1", 483 0, 484 unix_std_ops 485 }, 486 0, // NET_PROTOCOL_ATOMIC_MESSAGES, 487 488 unix_init_protocol, 489 unix_uninit_protocol, 490 unix_open, 491 unix_close, 492 unix_free, 493 unix_connect, 494 unix_accept, 495 unix_control, 496 unix_getsockopt, 497 unix_setsockopt, 498 unix_bind, 499 unix_unbind, 500 unix_listen, 501 unix_shutdown, 502 unix_send_data, 503 unix_send_routed_data, 504 unix_send_avail, 505 unix_read_data, 506 unix_read_avail, 507 unix_get_domain, 508 unix_get_mtu, 509 unix_receive_data, 510 unix_deliver_data, 511 unix_error_received, 512 unix_error_reply, 513 unix_add_ancillary_data, 514 unix_process_ancillary_data, 515 NULL, 516 unix_send_data_no_buffer, 517 unix_read_data_no_buffer 518 }; 519 520 module_dependency module_dependencies[] = { 521 {NET_STACK_MODULE_NAME, (module_info **)&gStackModule}, 522 {NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule}, 523 // {NET_DATALINK_MODULE_NAME, (module_info **)&sDatalinkModule}, 524 {NET_SOCKET_MODULE_NAME, (module_info **)&gSocketModule}, 525 {} 526 }; 527 528 module_info *modules[] = { 529 (module_info *)&gUnixModule, 530 NULL 531 }; 532