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); }
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); }