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