Esempio n. 1
0
static int
linux_accept(struct linux_accept_args *args, int *res)
{
	struct thread *td = curthread;
	struct linux_accept_args linux_args;
	struct sockaddr *sa = NULL;
	union fcntl_dat dat = { 0 };
	int error, sa_len;

	error = copyin(args, &linux_args, sizeof(linux_args));
	if (error)
		return (error);

	if (linux_args.addr) {
		error = copyin(linux_args.namelen, &sa_len, sizeof(sa_len));
		if (error)
			return (error);

		error = kern_accept(linux_args.s, 0, &sa, &sa_len, res);

		if (error) {
			/*
			 * Return a namelen of zero for older code which
			 * might ignore the return value from accept().
			 */
			sa_len = 0;
			copyout(&sa_len, linux_args.namelen,
			    sizeof(*linux_args.namelen));
		} else {
			error = linux_copyout_sockaddr(sa, linux_args.addr,
			    sa_len);
			if (error == 0) {
				error = copyout(&sa_len, linux_args.namelen,
				    sizeof(*linux_args.namelen));
			}
		}
		if (sa)
			kfree(sa, M_SONAME);
	} else {
		error = kern_accept(linux_args.s, 0, NULL, 0, res);
	}

	if (error)
		return (error);

	/*
	 * linux appears not to copy flags from the parent socket to the
	 * accepted one, so we must clear the flags in the new descriptor.
	 * Ignore any errors, because we already have an open fd.
	 */
	kern_fcntl(*res, F_SETFL, &dat, td->td_ucred);
	return (0);
}
Esempio n. 2
0
static int
accept_master(struct thread *td, int s /* local */, struct sockaddr *name,
	      socklen_t *anamelen)
{
	struct sockaddr *addr;
	socklen_t addrlen;
	int error;

	error = kern_accept(td, s, &addr, &addrlen, NULL);
	if (error != 0)
		return (error);
	error = fmaster_copyout_sockaddr(addr, addrlen, name, anamelen);
	if (error != 0)
		goto exit;

	error = 0;
exit:
	free(addr, M_SONAME);

	return (error);
}