xref: /haiku/src/system/kernel/fs/socket.cpp (revision a9b5f684f1d3552ae541c86b07bd56c1436e57ec)
1 /*
2  * Copyright 2009-2010, Axel Dörfler, axeld@pinc-software.de.
3  * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include <sys/socket.h>
9 
10 #include <errno.h>
11 #include <limits.h>
12 
13 #include <module.h>
14 
15 #include <AutoDeleter.h>
16 #include <AutoDeleterDrivers.h>
17 
18 #include <syscall_utils.h>
19 
20 #include <fd.h>
21 #include <kernel.h>
22 #include <lock.h>
23 #include <syscall_restart.h>
24 #include <util/AutoLock.h>
25 #include <util/iovec_support.h>
26 #include <vfs.h>
27 
28 #include <net_stack_interface.h>
29 #include <net_stat.h>
30 
31 
32 #define MAX_SOCKET_ADDRESS_LENGTH	(sizeof(sockaddr_storage))
33 #define MAX_SOCKET_OPTION_LENGTH	128
34 #define MAX_ANCILLARY_DATA_LENGTH	1024
35 
36 #define GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor)	\
37 	do {												\
38 		status_t getError = get_socket_descriptor(fd, kernel, descriptor); \
39 		if (getError != B_OK)							\
40 			return getError;							\
41 	} while (false)
42 
43 #define FD_SOCKET(descriptor) ((net_socket*)descriptor->cookie)
44 
45 
46 static net_stack_interface_module_info* sStackInterface = NULL;
47 static int32 sStackInterfaceConsumers = 0;
48 static rw_lock sLock = RW_LOCK_INITIALIZER("stack interface");
49 
50 
51 static net_stack_interface_module_info*
get_stack_interface_module()52 get_stack_interface_module()
53 {
54 	atomic_add(&sStackInterfaceConsumers, 1);
55 
56 	ReadLocker readLocker(sLock);
57 	if (sStackInterface != NULL)
58 		return sStackInterface;
59 
60 	readLocker.Unlock();
61 	WriteLocker writeLocker(sLock);
62 	if (sStackInterface != NULL)
63 		return sStackInterface;
64 
65 	// load module
66 	net_stack_interface_module_info* module;
67 	// TODO: Add driver settings option to load the userland net stack.
68 	status_t error = get_module(NET_STACK_INTERFACE_MODULE_NAME,
69 		(module_info**)&module);
70 	if (error == B_OK)
71 		sStackInterface = module;
72 
73 	if (sStackInterface == NULL)
74 		atomic_add(&sStackInterfaceConsumers, -1);
75 
76 	return sStackInterface;
77 }
78 
79 
80 static void
put_stack_interface_module()81 put_stack_interface_module()
82 {
83 	if (atomic_add(&sStackInterfaceConsumers, -1) != 1)
84 		return;
85 
86 	// Keep the stack loaded on non-KDEBUG kernels.
87 #if KDEBUG
88 	WriteLocker _(sLock);
89 	if (atomic_get(&sStackInterfaceConsumers) > 0)
90 		return;
91 	if (sStackInterface == NULL)
92 		return;
93 
94 	put_module(NET_STACK_INTERFACE_MODULE_NAME);
95 	sStackInterface = NULL;
96 #endif
97 }
98 
99 
100 static status_t
prepare_userland_address_result(struct sockaddr * userAddress,socklen_t * _addressLength,socklen_t & addressLength,bool addressRequired)101 prepare_userland_address_result(struct sockaddr* userAddress,
102 	socklen_t* _addressLength, socklen_t& addressLength, bool addressRequired)
103 {
104 	// check parameters
105 	if (_addressLength == NULL)
106 		return B_BAD_VALUE;
107 	if (userAddress == NULL) {
108 		if (addressRequired)
109 			return B_BAD_VALUE;
110 	} else if (!IS_USER_ADDRESS(userAddress)
111 			|| !IS_USER_ADDRESS(_addressLength)) {
112 		return B_BAD_ADDRESS;
113 	}
114 
115 	// copy the buffer size from userland
116 	addressLength = 0;
117 	if (userAddress != NULL
118 			&& user_memcpy(&addressLength, _addressLength, sizeof(socklen_t))
119 				!= B_OK) {
120 		return B_BAD_ADDRESS;
121 	}
122 
123 	if (addressLength > MAX_SOCKET_ADDRESS_LENGTH)
124 		addressLength = MAX_SOCKET_ADDRESS_LENGTH;
125 
126 	return B_OK;
127 }
128 
129 
130 static status_t
copy_address_to_userland(const void * address,socklen_t addressLength,sockaddr * userAddress,socklen_t userAddressBufferSize,socklen_t * userAddressLength)131 copy_address_to_userland(const void* address, socklen_t addressLength,
132 	sockaddr* userAddress, socklen_t userAddressBufferSize,
133 	socklen_t* userAddressLength)
134 {
135 	// copy address size and address back to userland
136 	if (user_memcpy(userAddressLength, &addressLength,
137 			sizeof(socklen_t)) != B_OK
138 		|| (userAddress != NULL
139 			&& user_memcpy(userAddress, address,
140 				min_c(addressLength, userAddressBufferSize)) != B_OK)) {
141 		return B_BAD_ADDRESS;
142 	}
143 
144 	return B_OK;
145 }
146 
147 
148 static status_t
prepare_userland_msghdr(const msghdr * userMessage,msghdr & message,iovec * & userVecs,MemoryDeleter & vecsDeleter,void * & userAddress,char * address)149 prepare_userland_msghdr(const msghdr* userMessage, msghdr& message,
150 	iovec*& userVecs, MemoryDeleter& vecsDeleter, void*& userAddress,
151 	char* address)
152 {
153 	if (userMessage == NULL)
154 		return B_BAD_VALUE;
155 
156 	// copy message from userland
157 	if (!IS_USER_ADDRESS(userMessage)
158 			|| user_memcpy(&message, userMessage, sizeof(msghdr)) != B_OK) {
159 		return B_BAD_ADDRESS;
160 	}
161 
162 	userVecs = message.msg_iov;
163 	userAddress = message.msg_name;
164 
165 	// copy iovecs from userland
166 	if (message.msg_iovlen < 0 || message.msg_iovlen > IOV_MAX)
167 		return EMSGSIZE;
168 	if (userVecs != NULL && message.msg_iovlen > 0) {
169 		iovec* vecs = (iovec*)malloc(sizeof(iovec) * message.msg_iovlen);
170 		if (vecs == NULL)
171 			return B_NO_MEMORY;
172 		vecsDeleter.SetTo(vecs);
173 
174 		status_t error = get_iovecs_from_user(message.msg_iov, message.msg_iovlen, vecs);
175 		if (error != B_OK)
176 			return error;
177 		message.msg_iov = vecs;
178 	} else {
179 		message.msg_iov = NULL;
180 		message.msg_iovlen = 0;
181 	}
182 
183 	// prepare the address field
184 	userAddress = message.msg_name;
185 	if (userAddress != NULL) {
186 		if (!IS_USER_ADDRESS(message.msg_name))
187 			return B_BAD_ADDRESS;
188 		if (message.msg_namelen > MAX_SOCKET_ADDRESS_LENGTH)
189 			message.msg_namelen = MAX_SOCKET_ADDRESS_LENGTH;
190 
191 		message.msg_name = address;
192 	}
193 
194 	return B_OK;
195 }
196 
197 
198 // #pragma mark - socket file descriptor
199 
200 
201 static status_t
socket_read(struct file_descriptor * descriptor,off_t pos,void * buffer,size_t * _length)202 socket_read(struct file_descriptor *descriptor, off_t pos, void *buffer,
203 	size_t *_length)
204 {
205 	ssize_t bytesRead = sStackInterface->recv(FD_SOCKET(descriptor), buffer,
206 		*_length, 0);
207 	*_length = bytesRead >= 0 ? bytesRead : 0;
208 	return bytesRead >= 0 ? B_OK : bytesRead;
209 }
210 
211 
212 static status_t
socket_write(struct file_descriptor * descriptor,off_t pos,const void * buffer,size_t * _length)213 socket_write(struct file_descriptor *descriptor, off_t pos, const void *buffer,
214 	size_t *_length)
215 {
216 	ssize_t bytesWritten = sStackInterface->send(FD_SOCKET(descriptor), buffer,
217 		*_length, 0);
218 	*_length = bytesWritten >= 0 ? bytesWritten : 0;
219 	return bytesWritten >= 0 ? B_OK : bytesWritten;
220 }
221 
222 
223 static ssize_t
socket_readv(struct file_descriptor * descriptor,off_t pos,const struct iovec * vecs,int count)224 socket_readv(struct file_descriptor *descriptor, off_t pos,
225 	const struct iovec *vecs, int count)
226 {
227 	struct msghdr message = {};
228 	message.msg_iov = (struct iovec*)vecs;
229 	message.msg_iovlen = count;
230 	return sStackInterface->recvmsg(FD_SOCKET(descriptor), &message, 0);
231 }
232 
233 
234 static ssize_t
socket_writev(struct file_descriptor * descriptor,off_t pos,const struct iovec * vecs,int count)235 socket_writev(struct file_descriptor *descriptor, off_t pos,
236 	const struct iovec *vecs, int count)
237 {
238 	struct msghdr message = {};
239 	message.msg_iov = (struct iovec*)vecs;
240 	message.msg_iovlen = count;
241 	return sStackInterface->sendmsg(FD_SOCKET(descriptor), &message, 0);
242 }
243 
244 
245 static status_t
socket_ioctl(struct file_descriptor * descriptor,ulong op,void * buffer,size_t length)246 socket_ioctl(struct file_descriptor *descriptor, ulong op, void *buffer,
247 	size_t length)
248 {
249 	return sStackInterface->ioctl(FD_SOCKET(descriptor), op, buffer, length);
250 }
251 
252 
253 static status_t
socket_set_flags(struct file_descriptor * descriptor,int flags)254 socket_set_flags(struct file_descriptor *descriptor, int flags)
255 {
256 	// we ignore O_APPEND, but O_NONBLOCK we need to translate
257 	uint32 op = (flags & O_NONBLOCK) != 0
258 		? B_SET_NONBLOCKING_IO : B_SET_BLOCKING_IO;
259 
260 	return sStackInterface->ioctl(FD_SOCKET(descriptor), op, NULL, 0);
261 }
262 
263 
264 static status_t
socket_select(struct file_descriptor * descriptor,uint8 event,struct selectsync * sync)265 socket_select(struct file_descriptor *descriptor, uint8 event,
266 	struct selectsync *sync)
267 {
268 	return sStackInterface->select(FD_SOCKET(descriptor), event, sync);
269 }
270 
271 
272 static status_t
socket_deselect(struct file_descriptor * descriptor,uint8 event,struct selectsync * sync)273 socket_deselect(struct file_descriptor *descriptor, uint8 event,
274 	struct selectsync *sync)
275 {
276 	return sStackInterface->deselect(FD_SOCKET(descriptor), event, sync);
277 }
278 
279 
280 static status_t
socket_read_stat(struct file_descriptor * descriptor,struct stat * st)281 socket_read_stat(struct file_descriptor *descriptor, struct stat *st)
282 {
283 	st->st_dev = 0;
284 	st->st_ino = (addr_t)descriptor->cookie;
285 	st->st_mode = S_IFSOCK | 0666;
286 	st->st_nlink = 1;
287 	st->st_uid = 0;
288 	st->st_gid = 0;
289 	st->st_size = 0;
290 	st->st_rdev = 0;
291 	st->st_blksize = 1024;	// use MTU for datagram sockets?
292 	st->st_type = 0;
293 
294 	timespec now;
295 	now.tv_sec = time(NULL);
296 	now.tv_nsec = 0;
297 
298 	st->st_atim = now;
299 	st->st_mtim = now;
300 	st->st_ctim = now;
301 	st->st_crtim = now;
302 
303 	return B_OK;
304 }
305 
306 
307 static status_t
socket_close(struct file_descriptor * descriptor)308 socket_close(struct file_descriptor *descriptor)
309 {
310 	return sStackInterface->close(FD_SOCKET(descriptor));
311 }
312 
313 
314 static void
socket_free(struct file_descriptor * descriptor)315 socket_free(struct file_descriptor *descriptor)
316 {
317 	sStackInterface->free(FD_SOCKET(descriptor));
318 	put_stack_interface_module();
319 }
320 
321 
322 static struct fd_ops sSocketFDOps = {
323 	&socket_close,
324 	&socket_free,
325 	&socket_read,
326 	&socket_write,
327 	&socket_readv,
328 	&socket_writev,
329 	NULL,	// fd_seek
330 	&socket_ioctl,
331 	&socket_set_flags,
332 	&socket_select,
333 	&socket_deselect,
334 	NULL,	// fd_read_dir
335 	NULL,	// fd_rewind_dir
336 	&socket_read_stat,
337 	NULL,	// fd_write_stat
338 };
339 
340 
341 static status_t
get_socket_descriptor(int fd,bool kernel,file_descriptor * & descriptor)342 get_socket_descriptor(int fd, bool kernel, file_descriptor*& descriptor)
343 {
344 	if (fd < 0)
345 		return EBADF;
346 
347 	descriptor = get_fd(get_current_io_context(kernel), fd);
348 	if (descriptor == NULL)
349 		return EBADF;
350 
351 	if (descriptor->ops != &sSocketFDOps) {
352 		put_fd(descriptor);
353 		return ENOTSOCK;
354 	}
355 
356 	return B_OK;
357 }
358 
359 
360 static int
create_socket_fd(net_socket * socket,int flags,bool kernel)361 create_socket_fd(net_socket* socket, int flags, bool kernel)
362 {
363 	// Get the socket's non-blocking flag, so we can set the respective
364 	// open mode flag.
365 	int32 nonBlock;
366 	socklen_t nonBlockLen = sizeof(int32);
367 	status_t error = sStackInterface->getsockopt(socket, SOL_SOCKET,
368 		SO_NONBLOCK, &nonBlock, &nonBlockLen);
369 	if (error != B_OK)
370 		return error;
371 	int oflags = 0;
372 	if ((flags & SOCK_CLOEXEC) != 0)
373 		oflags |= O_CLOEXEC;
374 	if ((flags & SOCK_NONBLOCK) != 0 || nonBlock)
375 		oflags |= O_NONBLOCK;
376 
377 	// allocate a file descriptor
378 	file_descriptor* descriptor = alloc_fd();
379 	if (descriptor == NULL)
380 		return B_NO_MEMORY;
381 
382 	// init it
383 	descriptor->ops = &sSocketFDOps;
384 	descriptor->cookie = socket;
385 	descriptor->open_mode = O_RDWR | oflags;
386 
387 	// publish it
388 	io_context* context = get_current_io_context(kernel);
389 	int fd = new_fd(context, descriptor);
390 	if (fd < 0) {
391 		descriptor->ops = NULL;
392 		put_fd(descriptor);
393 	}
394 
395 	rw_lock_write_lock(&context->lock);
396 	fd_set_close_on_exec(context, fd, (oflags & O_CLOEXEC) != 0);
397 	rw_lock_write_unlock(&context->lock);
398 
399 	return fd;
400 }
401 
402 
403 // #pragma mark - common sockets API implementation
404 
405 
406 static int
common_socket(int family,int type,int protocol,bool kernel)407 common_socket(int family, int type, int protocol, bool kernel)
408 {
409 	if (!get_stack_interface_module())
410 		return B_UNSUPPORTED;
411 
412 	int sflags = type & (SOCK_CLOEXEC | SOCK_NONBLOCK);
413 	type &= ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
414 
415 	// create the socket
416 	net_socket* socket;
417 	status_t error = sStackInterface->open(family, type, protocol, &socket);
418 	if (error != B_OK) {
419 		put_stack_interface_module();
420 		return error;
421 	}
422 
423 	// allocate the FD
424 	int fd = create_socket_fd(socket, sflags, kernel);
425 	if (fd < 0) {
426 		sStackInterface->close(socket);
427 		sStackInterface->free(socket);
428 		put_stack_interface_module();
429 	}
430 
431 	return fd;
432 }
433 
434 
435 static status_t
common_bind(int fd,const struct sockaddr * address,socklen_t addressLength,bool kernel)436 common_bind(int fd, const struct sockaddr *address, socklen_t addressLength,
437 	bool kernel)
438 {
439 	file_descriptor* descriptor;
440 	GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
441 	FileDescriptorPutter _(descriptor);
442 
443 	return sStackInterface->bind(FD_SOCKET(descriptor), address, addressLength);
444 }
445 
446 
447 static status_t
common_shutdown(int fd,int how,bool kernel)448 common_shutdown(int fd, int how, bool kernel)
449 {
450 	file_descriptor* descriptor;
451 	GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
452 	FileDescriptorPutter _(descriptor);
453 
454 	return sStackInterface->shutdown(FD_SOCKET(descriptor), how);
455 }
456 
457 
458 static status_t
common_connect(int fd,const struct sockaddr * address,socklen_t addressLength,bool kernel)459 common_connect(int fd, const struct sockaddr *address,
460 	socklen_t addressLength, bool kernel)
461 {
462 	file_descriptor* descriptor;
463 	GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
464 	FileDescriptorPutter _(descriptor);
465 
466 	return sStackInterface->connect(FD_SOCKET(descriptor), address,
467 		addressLength);
468 }
469 
470 
471 static status_t
common_listen(int fd,int backlog,bool kernel)472 common_listen(int fd, int backlog, bool kernel)
473 {
474 	file_descriptor* descriptor;
475 	GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
476 	FileDescriptorPutter _(descriptor);
477 
478 	return sStackInterface->listen(FD_SOCKET(descriptor), backlog);
479 }
480 
481 
482 static int
common_accept(int fd,struct sockaddr * address,socklen_t * _addressLength,int flags,bool kernel)483 common_accept(int fd, struct sockaddr *address, socklen_t *_addressLength, int flags,
484 	bool kernel)
485 {
486 	file_descriptor* descriptor;
487 	GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
488 	FileDescriptorPutter _(descriptor);
489 
490 	if ((flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) != 0)
491 		RETURN_AND_SET_ERRNO(B_BAD_VALUE);
492 
493 	net_socket* acceptedSocket;
494 	status_t error = sStackInterface->accept(FD_SOCKET(descriptor), address,
495 		_addressLength, &acceptedSocket);
496 	if (error != B_OK)
497 		return error;
498 
499 	// allocate the FD
500 	int acceptedFD = create_socket_fd(acceptedSocket, flags, kernel);
501 	if (acceptedFD < 0) {
502 		sStackInterface->close(acceptedSocket);
503 		sStackInterface->free(acceptedSocket);
504 	} else {
505 		// we need a reference for the new FD
506 		get_stack_interface_module();
507 	}
508 
509 	return acceptedFD;
510 }
511 
512 
513 static ssize_t
common_recv(int fd,void * data,size_t length,int flags,bool kernel)514 common_recv(int fd, void *data, size_t length, int flags, bool kernel)
515 {
516 	file_descriptor* descriptor;
517 	GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
518 	FileDescriptorPutter _(descriptor);
519 
520 	return sStackInterface->recv(FD_SOCKET(descriptor), data, length, flags);
521 }
522 
523 
524 static ssize_t
common_recvfrom(int fd,void * data,size_t length,int flags,struct sockaddr * address,socklen_t * _addressLength,bool kernel)525 common_recvfrom(int fd, void *data, size_t length, int flags,
526 	struct sockaddr *address, socklen_t *_addressLength, bool kernel)
527 {
528 	file_descriptor* descriptor;
529 	GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
530 	FileDescriptorPutter _(descriptor);
531 
532 	return sStackInterface->recvfrom(FD_SOCKET(descriptor), data, length,
533 		flags, address, _addressLength);
534 }
535 
536 
537 static ssize_t
common_recvmsg(int fd,struct msghdr * message,int flags,bool kernel)538 common_recvmsg(int fd, struct msghdr *message, int flags, bool kernel)
539 {
540 	file_descriptor* descriptor;
541 	GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
542 	FileDescriptorPutter _(descriptor);
543 
544 	return sStackInterface->recvmsg(FD_SOCKET(descriptor), message, flags);
545 }
546 
547 
548 static ssize_t
common_send(int fd,const void * data,size_t length,int flags,bool kernel)549 common_send(int fd, const void *data, size_t length, int flags, bool kernel)
550 {
551 	file_descriptor* descriptor;
552 	GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
553 	FileDescriptorPutter _(descriptor);
554 
555 	return sStackInterface->send(FD_SOCKET(descriptor), data, length, flags);
556 }
557 
558 
559 static ssize_t
common_sendto(int fd,const void * data,size_t length,int flags,const struct sockaddr * address,socklen_t addressLength,bool kernel)560 common_sendto(int fd, const void *data, size_t length, int flags,
561 	const struct sockaddr *address, socklen_t addressLength, bool kernel)
562 {
563 	file_descriptor* descriptor;
564 	GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
565 	FileDescriptorPutter _(descriptor);
566 
567 	return sStackInterface->sendto(FD_SOCKET(descriptor), data, length, flags,
568 		address, addressLength);
569 }
570 
571 
572 static ssize_t
common_sendmsg(int fd,const struct msghdr * message,int flags,bool kernel)573 common_sendmsg(int fd, const struct msghdr *message, int flags, bool kernel)
574 {
575 	file_descriptor* descriptor;
576 	GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
577 	FileDescriptorPutter _(descriptor);
578 
579 	return sStackInterface->sendmsg(FD_SOCKET(descriptor), message, flags);
580 }
581 
582 
583 static status_t
common_getsockopt(int fd,int level,int option,void * value,socklen_t * _length,bool kernel)584 common_getsockopt(int fd, int level, int option, void *value,
585 	socklen_t *_length, bool kernel)
586 {
587 	file_descriptor* descriptor;
588 	GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
589 	FileDescriptorPutter _(descriptor);
590 
591 	return sStackInterface->getsockopt(FD_SOCKET(descriptor), level, option,
592 		value, _length);
593 }
594 
595 
596 static status_t
common_setsockopt(int fd,int level,int option,const void * value,socklen_t length,bool kernel)597 common_setsockopt(int fd, int level, int option, const void *value,
598 	socklen_t length, bool kernel)
599 {
600 	file_descriptor* descriptor;
601 	GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
602 	FileDescriptorPutter _(descriptor);
603 
604 	return sStackInterface->setsockopt(FD_SOCKET(descriptor), level, option,
605 		value, length);
606 }
607 
608 
609 static status_t
common_getpeername(int fd,struct sockaddr * address,socklen_t * _addressLength,bool kernel)610 common_getpeername(int fd, struct sockaddr *address,
611 	socklen_t *_addressLength, bool kernel)
612 {
613 	file_descriptor* descriptor;
614 	GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
615 	FileDescriptorPutter _(descriptor);
616 
617 	return sStackInterface->getpeername(FD_SOCKET(descriptor), address,
618 		_addressLength);
619 }
620 
621 
622 static status_t
common_getsockname(int fd,struct sockaddr * address,socklen_t * _addressLength,bool kernel)623 common_getsockname(int fd, struct sockaddr *address,
624 	socklen_t *_addressLength, bool kernel)
625 {
626 	file_descriptor* descriptor;
627 	GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
628 	FileDescriptorPutter _(descriptor);
629 
630 	return sStackInterface->getsockname(FD_SOCKET(descriptor), address,
631 		_addressLength);
632 }
633 
634 
635 static int
common_sockatmark(int fd,bool kernel)636 common_sockatmark(int fd, bool kernel)
637 {
638 	file_descriptor* descriptor;
639 	GET_SOCKET_FD_OR_RETURN(fd, kernel, descriptor);
640 	FileDescriptorPutter _(descriptor);
641 
642 	return sStackInterface->sockatmark(FD_SOCKET(descriptor));
643 }
644 
645 
646 static status_t
common_socketpair(int family,int type,int protocol,int fds[2],bool kernel)647 common_socketpair(int family, int type, int protocol, int fds[2], bool kernel)
648 {
649 	if (!get_stack_interface_module())
650 		return B_UNSUPPORTED;
651 
652 	int sflags = type & (SOCK_CLOEXEC | SOCK_NONBLOCK);
653 	type &= ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
654 
655 	net_socket* sockets[2];
656 	status_t error = sStackInterface->socketpair(family, type, protocol,
657 		sockets);
658 	if (error != B_OK) {
659 		put_stack_interface_module();
660 		return error;
661 	}
662 
663 	// allocate the FDs
664 	for (int i = 0; i < 2; i++) {
665 		fds[i] = create_socket_fd(sockets[i], sflags, kernel);
666 		if (fds[i] < 0) {
667 			sStackInterface->close(sockets[i]);
668 			sStackInterface->free(sockets[i]);
669 			put_stack_interface_module();
670 			return fds[i];
671 		}
672 	}
673 
674 	// We need another reference for the second socket
675 	get_stack_interface_module();
676 	return B_OK;
677 }
678 
679 
680 static status_t
common_get_next_socket_stat(int family,uint32 * cookie,struct net_stat * stat)681 common_get_next_socket_stat(int family, uint32 *cookie, struct net_stat *stat)
682 {
683 	if (!get_stack_interface_module())
684 		return B_UNSUPPORTED;
685 
686 	status_t status = sStackInterface->get_next_socket_stat(family, cookie,
687 		stat);
688 
689 	put_stack_interface_module();
690 	return status;
691 }
692 
693 
694 // #pragma mark - kernel sockets API
695 
696 
697 int
socket(int family,int type,int protocol)698 socket(int family, int type, int protocol)
699 {
700 	SyscallFlagUnsetter _;
701 	RETURN_AND_SET_ERRNO(common_socket(family, type, protocol, true));
702 }
703 
704 
705 int
bind(int socket,const struct sockaddr * address,socklen_t addressLength)706 bind(int socket, const struct sockaddr *address, socklen_t addressLength)
707 {
708 	SyscallFlagUnsetter _;
709 	RETURN_AND_SET_ERRNO(common_bind(socket, address, addressLength, true));
710 }
711 
712 
713 int
shutdown(int socket,int how)714 shutdown(int socket, int how)
715 {
716 	SyscallFlagUnsetter _;
717 	RETURN_AND_SET_ERRNO(common_shutdown(socket, how, true));
718 }
719 
720 
721 int
connect(int socket,const struct sockaddr * address,socklen_t addressLength)722 connect(int socket, const struct sockaddr *address, socklen_t addressLength)
723 {
724 	SyscallFlagUnsetter _;
725 	RETURN_AND_SET_ERRNO(common_connect(socket, address, addressLength, true));
726 }
727 
728 
729 int
listen(int socket,int backlog)730 listen(int socket, int backlog)
731 {
732 	SyscallFlagUnsetter _;
733 	RETURN_AND_SET_ERRNO(common_listen(socket, backlog, true));
734 }
735 
736 
737 int
accept(int socket,struct sockaddr * address,socklen_t * _addressLength)738 accept(int socket, struct sockaddr *address, socklen_t *_addressLength)
739 {
740 	SyscallFlagUnsetter _;
741 	RETURN_AND_SET_ERRNO(common_accept(socket, address, _addressLength, 0, true));
742 }
743 
744 
745 int
accept4(int socket,struct sockaddr * address,socklen_t * _addressLength,int flags)746 accept4(int socket, struct sockaddr *address, socklen_t *_addressLength, int flags)
747 {
748 	SyscallFlagUnsetter _;
749 	RETURN_AND_SET_ERRNO(common_accept(socket, address, _addressLength, flags, true));
750 }
751 
752 
753 ssize_t
recv(int socket,void * data,size_t length,int flags)754 recv(int socket, void *data, size_t length, int flags)
755 {
756 	SyscallFlagUnsetter _;
757 	RETURN_AND_SET_ERRNO(common_recv(socket, data, length, flags, true));
758 }
759 
760 
761 ssize_t
recvfrom(int socket,void * data,size_t length,int flags,struct sockaddr * address,socklen_t * _addressLength)762 recvfrom(int socket, void *data, size_t length, int flags,
763 	struct sockaddr *address, socklen_t *_addressLength)
764 {
765 	SyscallFlagUnsetter _;
766 	RETURN_AND_SET_ERRNO(common_recvfrom(socket, data, length, flags, address,
767 		_addressLength, true));
768 }
769 
770 
771 ssize_t
recvmsg(int socket,struct msghdr * message,int flags)772 recvmsg(int socket, struct msghdr *message, int flags)
773 {
774 	SyscallFlagUnsetter _;
775 	RETURN_AND_SET_ERRNO(common_recvmsg(socket, message, flags, true));
776 }
777 
778 
779 ssize_t
send(int socket,const void * data,size_t length,int flags)780 send(int socket, const void *data, size_t length, int flags)
781 {
782 	SyscallFlagUnsetter _;
783 	RETURN_AND_SET_ERRNO(common_send(socket, data, length, flags, true));
784 }
785 
786 
787 ssize_t
sendto(int socket,const void * data,size_t length,int flags,const struct sockaddr * address,socklen_t addressLength)788 sendto(int socket, const void *data, size_t length, int flags,
789 	const struct sockaddr *address, socklen_t addressLength)
790 {
791 	SyscallFlagUnsetter _;
792 	RETURN_AND_SET_ERRNO(common_sendto(socket, data, length, flags, address,
793 		addressLength, true));
794 }
795 
796 
797 ssize_t
sendmsg(int socket,const struct msghdr * message,int flags)798 sendmsg(int socket, const struct msghdr *message, int flags)
799 {
800 	SyscallFlagUnsetter _;
801 	RETURN_AND_SET_ERRNO(common_sendmsg(socket, message, flags, true));
802 }
803 
804 
805 int
getsockopt(int socket,int level,int option,void * value,socklen_t * _length)806 getsockopt(int socket, int level, int option, void *value, socklen_t *_length)
807 {
808 	SyscallFlagUnsetter _;
809 	RETURN_AND_SET_ERRNO(common_getsockopt(socket, level, option, value,
810 		_length, true));
811 }
812 
813 
814 int
setsockopt(int socket,int level,int option,const void * value,socklen_t length)815 setsockopt(int socket, int level, int option, const void *value,
816 	socklen_t length)
817 {
818 	SyscallFlagUnsetter _;
819 	RETURN_AND_SET_ERRNO(common_setsockopt(socket, level, option, value,
820 		length, true));
821 }
822 
823 
824 int
getpeername(int socket,struct sockaddr * address,socklen_t * _addressLength)825 getpeername(int socket, struct sockaddr *address, socklen_t *_addressLength)
826 {
827 	SyscallFlagUnsetter _;
828 	RETURN_AND_SET_ERRNO(common_getpeername(socket, address, _addressLength,
829 		true));
830 }
831 
832 
833 int
getsockname(int socket,struct sockaddr * address,socklen_t * _addressLength)834 getsockname(int socket, struct sockaddr *address, socklen_t *_addressLength)
835 {
836 	SyscallFlagUnsetter _;
837 	RETURN_AND_SET_ERRNO(common_getsockname(socket, address, _addressLength,
838 		true));
839 }
840 
841 
842 int
sockatmark(int socket)843 sockatmark(int socket)
844 {
845 	SyscallFlagUnsetter _;
846 	RETURN_AND_SET_ERRNO(common_sockatmark(socket, true));
847 }
848 
849 
850 int
socketpair(int family,int type,int protocol,int socketVector[2])851 socketpair(int family, int type, int protocol, int socketVector[2])
852 {
853 	SyscallFlagUnsetter _;
854 	RETURN_AND_SET_ERRNO(common_socketpair(family, type, protocol,
855 		socketVector, true));
856 }
857 
858 
859 // #pragma mark - syscalls
860 
861 
862 int
_user_socket(int family,int type,int protocol)863 _user_socket(int family, int type, int protocol)
864 {
865 	SyscallRestartWrapper<int> result;
866 	return result = common_socket(family, type, protocol, false);
867 }
868 
869 
870 status_t
_user_bind(int socket,const struct sockaddr * userAddress,socklen_t addressLength)871 _user_bind(int socket, const struct sockaddr *userAddress,
872 	socklen_t addressLength)
873 {
874 	// check parameters and copy address from userland
875 	if (userAddress == NULL || addressLength > MAX_SOCKET_ADDRESS_LENGTH)
876 		return B_BAD_VALUE;
877 
878 	sockaddr_storage address;
879 	memset(&address, 0, sizeof(address));
880 	if (!IS_USER_ADDRESS(userAddress)
881 			|| user_memcpy(&address, userAddress, addressLength) != B_OK) {
882 		return B_BAD_ADDRESS;
883 	}
884 
885 	address.ss_len = addressLength;
886 		// make sure the sa_len field is set correctly
887 
888 	SyscallRestartWrapper<status_t> error;
889 	return error = common_bind(socket, (sockaddr*)&address, addressLength,
890 		false);
891 }
892 
893 
894 status_t
_user_shutdown_socket(int socket,int how)895 _user_shutdown_socket(int socket, int how)
896 {
897 	SyscallRestartWrapper<status_t> error;
898 	return error = common_shutdown(socket, how, false);
899 }
900 
901 
902 status_t
_user_connect(int socket,const struct sockaddr * userAddress,socklen_t addressLength)903 _user_connect(int socket, const struct sockaddr *userAddress,
904 	socklen_t addressLength)
905 {
906 	// check parameters and copy address from userland
907 	if (userAddress == NULL || addressLength > MAX_SOCKET_ADDRESS_LENGTH)
908 		return B_BAD_VALUE;
909 
910 	sockaddr_storage address;
911 	memset(&address, 0, sizeof(address));
912 	if (!IS_USER_ADDRESS(userAddress)
913 			|| user_memcpy(&address, userAddress, addressLength) != B_OK) {
914 		return B_BAD_ADDRESS;
915 	}
916 
917 	address.ss_len = addressLength;
918 		// make sure the sa_len field is set correctly
919 
920 	SyscallRestartWrapper<status_t> error;
921 
922 	return error = common_connect(socket, (sockaddr*)&address, addressLength,
923 		false);
924 }
925 
926 
927 status_t
_user_listen(int socket,int backlog)928 _user_listen(int socket, int backlog)
929 {
930 	SyscallRestartWrapper<status_t> error;
931 	return error = common_listen(socket, backlog, false);
932 }
933 
934 
935 int
_user_accept(int socket,struct sockaddr * userAddress,socklen_t * _addressLength,int flags)936 _user_accept(int socket, struct sockaddr *userAddress,
937 	socklen_t *_addressLength, int flags)
938 {
939 	// check parameters
940 	socklen_t addressLength = 0;
941 	status_t error = prepare_userland_address_result(userAddress,
942 		_addressLength, addressLength, false);
943 	if (error != B_OK)
944 		return error;
945 
946 	// accept()
947 	SyscallRestartWrapper<int> result;
948 
949 	char address[MAX_SOCKET_ADDRESS_LENGTH];
950 	socklen_t userAddressBufferSize = addressLength;
951 	result = common_accept(socket,
952 		userAddress != NULL ? (sockaddr*)address : NULL, &addressLength, flags, false);
953 
954 	// copy address size and address back to userland
955 	if (copy_address_to_userland(address, addressLength, userAddress,
956 			userAddressBufferSize, _addressLength) != B_OK) {
957 		_user_close(result);
958 		return B_BAD_ADDRESS;
959 	}
960 
961 	return result;
962 }
963 
964 
965 ssize_t
_user_recv(int socket,void * data,size_t length,int flags)966 _user_recv(int socket, void *data, size_t length, int flags)
967 {
968 	if (data == NULL || !is_user_address_range(data, length))
969 		return B_BAD_ADDRESS;
970 
971 	SyscallRestartWrapper<ssize_t> result;
972 	return result = common_recv(socket, data, length, flags, false);
973 }
974 
975 
976 ssize_t
_user_recvfrom(int socket,void * data,size_t length,int flags,struct sockaddr * userAddress,socklen_t * _addressLength)977 _user_recvfrom(int socket, void *data, size_t length, int flags,
978 	struct sockaddr *userAddress, socklen_t *_addressLength)
979 {
980 	if (data == NULL || !is_user_address_range(data, length))
981 		return B_BAD_ADDRESS;
982 
983 	// check parameters
984 	socklen_t addressLength = 0;
985 	status_t error = prepare_userland_address_result(userAddress,
986 		_addressLength, addressLength, false);
987 	if (error != B_OK)
988 		return error;
989 
990 	// recvfrom()
991 	SyscallRestartWrapper<ssize_t> result;
992 
993 	char address[MAX_SOCKET_ADDRESS_LENGTH];
994 	socklen_t userAddressBufferSize = addressLength;
995 	result = common_recvfrom(socket, data, length, flags,
996 		userAddress != NULL ? (sockaddr*)address : NULL, &addressLength, false);
997 	if (result < 0)
998 		return result;
999 
1000 	// copy address size and address back to userland
1001 	if (copy_address_to_userland(address, addressLength, userAddress,
1002 			userAddressBufferSize, _addressLength) != B_OK) {
1003 		return B_BAD_ADDRESS;
1004 	}
1005 
1006 	return result;
1007 }
1008 
1009 
1010 ssize_t
_user_recvmsg(int socket,struct msghdr * userMessage,int flags)1011 _user_recvmsg(int socket, struct msghdr *userMessage, int flags)
1012 {
1013 	// copy message from userland
1014 	msghdr message;
1015 	iovec* userVecs;
1016 	MemoryDeleter vecsDeleter;
1017 	void* userAddress;
1018 	char address[MAX_SOCKET_ADDRESS_LENGTH];
1019 
1020 	status_t error = prepare_userland_msghdr(userMessage, message, userVecs,
1021 		vecsDeleter, userAddress, address);
1022 	if (error != B_OK)
1023 		return error;
1024 
1025 	// prepare a buffer for ancillary data
1026 	MemoryDeleter ancillaryDeleter;
1027 	void* ancillary = NULL;
1028 	void* userAncillary = message.msg_control;
1029 	if (userAncillary != NULL) {
1030 		if (!IS_USER_ADDRESS(userAncillary))
1031 			return B_BAD_ADDRESS;
1032 		if (message.msg_controllen < 0)
1033 			return B_BAD_VALUE;
1034 		if (message.msg_controllen > MAX_ANCILLARY_DATA_LENGTH)
1035 			message.msg_controllen = MAX_ANCILLARY_DATA_LENGTH;
1036 
1037 		message.msg_control = ancillary = malloc(message.msg_controllen);
1038 		if (message.msg_control == NULL)
1039 			return B_NO_MEMORY;
1040 
1041 		ancillaryDeleter.SetTo(ancillary);
1042 	}
1043 
1044 	// recvmsg()
1045 	SyscallRestartWrapper<ssize_t> result;
1046 
1047 	result = common_recvmsg(socket, &message, flags, false);
1048 	if (result < 0)
1049 		return result;
1050 
1051 	// copy the address, the ancillary data, and the message header back to
1052 	// userland
1053 	message.msg_name = userAddress;
1054 	message.msg_iov = userVecs;
1055 	message.msg_control = userAncillary;
1056 	if ((userAddress != NULL && user_memcpy(userAddress, address,
1057 				message.msg_namelen) != B_OK)
1058 		|| (userAncillary != NULL && user_memcpy(userAncillary, ancillary,
1059 				message.msg_controllen) != B_OK)
1060 		|| user_memcpy(userMessage, &message, sizeof(msghdr)) != B_OK) {
1061 		return B_BAD_ADDRESS;
1062 	}
1063 
1064 	return result;
1065 }
1066 
1067 
1068 ssize_t
_user_send(int socket,const void * data,size_t length,int flags)1069 _user_send(int socket, const void *data, size_t length, int flags)
1070 {
1071 	if (data == NULL || !is_user_address_range(data, length))
1072 		return B_BAD_ADDRESS;
1073 
1074 	SyscallRestartWrapper<ssize_t> result;
1075 	return result = common_send(socket, data, length, flags, false);
1076 }
1077 
1078 
1079 ssize_t
_user_sendto(int socket,const void * data,size_t length,int flags,const struct sockaddr * userAddress,socklen_t addressLength)1080 _user_sendto(int socket, const void *data, size_t length, int flags,
1081 	const struct sockaddr *userAddress, socklen_t addressLength)
1082 {
1083 	if (data == NULL || !is_user_address_range(data, length))
1084 		return B_BAD_ADDRESS;
1085 
1086 	if (addressLength <= 0
1087 			|| addressLength > MAX_SOCKET_ADDRESS_LENGTH) {
1088 		return B_BAD_VALUE;
1089 	}
1090 
1091 	// copy address from userland
1092 	char address[MAX_SOCKET_ADDRESS_LENGTH];
1093 	if (userAddress != NULL) {
1094 		if (!IS_USER_ADDRESS(userAddress)
1095 			|| user_memcpy(address, userAddress, addressLength) != B_OK) {
1096 			return B_BAD_ADDRESS;
1097 		}
1098 	} else {
1099 		addressLength = 0;
1100 	}
1101 
1102 	// sendto()
1103 	SyscallRestartWrapper<ssize_t> result;
1104 
1105 	return result = common_sendto(socket, data, length, flags,
1106 		userAddress != NULL ? (sockaddr*)address : NULL, addressLength, false);
1107 }
1108 
1109 
1110 ssize_t
_user_sendmsg(int socket,const struct msghdr * userMessage,int flags)1111 _user_sendmsg(int socket, const struct msghdr *userMessage, int flags)
1112 {
1113 	// copy message from userland
1114 	msghdr message;
1115 	iovec* userVecs;
1116 	MemoryDeleter vecsDeleter;
1117 	void* userAddress;
1118 	char address[MAX_SOCKET_ADDRESS_LENGTH];
1119 
1120 	status_t error = prepare_userland_msghdr(userMessage, message, userVecs,
1121 		vecsDeleter, userAddress, address);
1122 	if (error != B_OK)
1123 		return error;
1124 
1125 	// copy the address from userland
1126 	if (userAddress != NULL
1127 			&& user_memcpy(address, userAddress, message.msg_namelen) != B_OK) {
1128 		return B_BAD_ADDRESS;
1129 	}
1130 
1131 	// copy ancillary data from userland
1132 	MemoryDeleter ancillaryDeleter;
1133 	void* userAncillary = message.msg_control;
1134 	if (userAncillary != NULL) {
1135 		if (!IS_USER_ADDRESS(userAncillary))
1136 			return B_BAD_ADDRESS;
1137 		if (message.msg_controllen < 0
1138 				|| message.msg_controllen > MAX_ANCILLARY_DATA_LENGTH) {
1139 			return B_BAD_VALUE;
1140 		}
1141 
1142 		message.msg_control = malloc(message.msg_controllen);
1143 		if (message.msg_control == NULL)
1144 			return B_NO_MEMORY;
1145 		ancillaryDeleter.SetTo(message.msg_control);
1146 
1147 		if (user_memcpy(message.msg_control, userAncillary,
1148 				message.msg_controllen) != B_OK) {
1149 			return B_BAD_ADDRESS;
1150 		}
1151 	}
1152 
1153 	// sendmsg()
1154 	SyscallRestartWrapper<ssize_t> result;
1155 
1156 	return result = common_sendmsg(socket, &message, flags, false);
1157 }
1158 
1159 
1160 status_t
_user_getsockopt(int socket,int level,int option,void * userValue,socklen_t * _length)1161 _user_getsockopt(int socket, int level, int option, void *userValue,
1162 	socklen_t *_length)
1163 {
1164 	// check params
1165 	if (userValue == NULL || _length == NULL)
1166 		return B_BAD_VALUE;
1167 	if (!IS_USER_ADDRESS(userValue) || !IS_USER_ADDRESS(_length))
1168 		return B_BAD_ADDRESS;
1169 
1170 	// copy length from userland
1171 	socklen_t length;
1172 	if (user_memcpy(&length, _length, sizeof(socklen_t)) != B_OK)
1173 		return B_BAD_ADDRESS;
1174 
1175 	if (length > MAX_SOCKET_OPTION_LENGTH)
1176 		return B_BAD_VALUE;
1177 
1178 	// getsockopt()
1179 	char value[MAX_SOCKET_OPTION_LENGTH];
1180 	SyscallRestartWrapper<status_t> error;
1181 	error = common_getsockopt(socket, level, option, value, &length,
1182 		false);
1183 	if (error != B_OK)
1184 		return error;
1185 
1186 	// copy value back to userland
1187 	if (user_memcpy(userValue, value, length) != B_OK)
1188 		return B_BAD_ADDRESS;
1189 
1190 	return B_OK;
1191 }
1192 
1193 
1194 status_t
_user_setsockopt(int socket,int level,int option,const void * userValue,socklen_t length)1195 _user_setsockopt(int socket, int level, int option, const void *userValue,
1196 	socklen_t length)
1197 {
1198 	// check params
1199 	if (userValue == NULL || length > MAX_SOCKET_OPTION_LENGTH)
1200 		return B_BAD_VALUE;
1201 
1202 	// copy value from userland
1203 	char value[MAX_SOCKET_OPTION_LENGTH];
1204 	if (!IS_USER_ADDRESS(userValue)
1205 			|| user_memcpy(value, userValue, length) != B_OK) {
1206 		return B_BAD_ADDRESS;
1207 	}
1208 
1209 	// setsockopt();
1210 	SyscallRestartWrapper<status_t> error;
1211 	return error = common_setsockopt(socket, level, option, value, length,
1212 		false);
1213 }
1214 
1215 
1216 status_t
_user_getpeername(int socket,struct sockaddr * userAddress,socklen_t * _addressLength)1217 _user_getpeername(int socket, struct sockaddr *userAddress,
1218 	socklen_t *_addressLength)
1219 {
1220 	// check parameters
1221 	socklen_t addressLength = 0;
1222 	SyscallRestartWrapper<status_t> error;
1223 	error = prepare_userland_address_result(userAddress, _addressLength,
1224 		addressLength, true);
1225 	if (error != B_OK)
1226 		return error;
1227 
1228 	// getpeername()
1229 	char address[MAX_SOCKET_ADDRESS_LENGTH];
1230 	socklen_t userAddressBufferSize = addressLength;
1231 	error = common_getpeername(socket, (sockaddr*)address, &addressLength,
1232 		false);
1233 	if (error != B_OK)
1234 		return error;
1235 
1236 	// copy address size and address back to userland
1237 	if (copy_address_to_userland(address, addressLength, userAddress,
1238 			userAddressBufferSize, _addressLength) != B_OK) {
1239 		return B_BAD_ADDRESS;
1240 	}
1241 
1242 	return B_OK;
1243 }
1244 
1245 
1246 status_t
_user_getsockname(int socket,struct sockaddr * userAddress,socklen_t * _addressLength)1247 _user_getsockname(int socket, struct sockaddr *userAddress,
1248 	socklen_t *_addressLength)
1249 {
1250 	// check parameters
1251 	socklen_t addressLength = 0;
1252 	SyscallRestartWrapper<status_t> error;
1253 	error = prepare_userland_address_result(userAddress, _addressLength,
1254 		addressLength, true);
1255 	if (error != B_OK)
1256 		return error;
1257 
1258 	// getsockname()
1259 	char address[MAX_SOCKET_ADDRESS_LENGTH];
1260 	socklen_t userAddressBufferSize = addressLength;
1261 	error = common_getsockname(socket, (sockaddr*)address, &addressLength,
1262 		false);
1263 	if (error != B_OK)
1264 		return error;
1265 
1266 	// copy address size and address back to userland
1267 	if (copy_address_to_userland(address, addressLength, userAddress,
1268 			userAddressBufferSize, _addressLength) != B_OK) {
1269 		return B_BAD_ADDRESS;
1270 	}
1271 
1272 	return B_OK;
1273 }
1274 
1275 
1276 int
_user_sockatmark(int socket)1277 _user_sockatmark(int socket)
1278 {
1279 	SyscallRestartWrapper<status_t> error;
1280 	return error = common_sockatmark(socket, false);
1281 }
1282 
1283 
1284 status_t
_user_socketpair(int family,int type,int protocol,int * userSocketVector)1285 _user_socketpair(int family, int type, int protocol, int *userSocketVector)
1286 {
1287 	// check parameters
1288 	if (userSocketVector == NULL)
1289 		return B_BAD_VALUE;
1290 	if (!IS_USER_ADDRESS(userSocketVector))
1291 		return B_BAD_ADDRESS;
1292 
1293 	// socketpair()
1294 	int socketVector[2];
1295 	SyscallRestartWrapper<status_t> error;
1296 	error = common_socketpair(family, type, protocol, socketVector, false);
1297 	if (error != B_OK)
1298 		return error;
1299 
1300 	// copy FDs back to userland
1301 	if (user_memcpy(userSocketVector, socketVector,
1302 			sizeof(socketVector)) != B_OK) {
1303 		_user_close(socketVector[0]);
1304 		_user_close(socketVector[1]);
1305 		return B_BAD_ADDRESS;
1306 	}
1307 
1308 	return B_OK;
1309 }
1310 
1311 
1312 status_t
_user_get_next_socket_stat(int family,uint32 * _cookie,struct net_stat * _stat)1313 _user_get_next_socket_stat(int family, uint32 *_cookie, struct net_stat *_stat)
1314 {
1315 	// check parameters and copy cookie from userland
1316 	if (_cookie == NULL || _stat == NULL)
1317 		return B_BAD_VALUE;
1318 
1319 	uint32 cookie;
1320 	if (!IS_USER_ADDRESS(_stat) || !IS_USER_ADDRESS(_cookie)
1321 		|| user_memcpy(&cookie, _cookie, sizeof(cookie)) != B_OK) {
1322 		return B_BAD_ADDRESS;
1323 	}
1324 
1325 	net_stat stat;
1326 	SyscallRestartWrapper<status_t> error;
1327 	error = common_get_next_socket_stat(family, &cookie, &stat);
1328 	if (error != B_OK)
1329 		return error;
1330 
1331 	// copy cookie and data back to userland
1332 	if (user_memcpy(_cookie, &cookie, sizeof(cookie)) != B_OK
1333 		|| user_memcpy(_stat, &stat, sizeof(net_stat)) != B_OK) {
1334 		return B_BAD_ADDRESS;
1335 	}
1336 
1337 	return B_OK;
1338 }
1339