diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1997-11-26 08:51:09 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1997-11-26 08:51:09 +0000 |
commit | 12d89b20e1d5d54c743ee59f536d318a478d8a5a (patch) | |
tree | 9472407aca485bedff3738d51efcc154a69afe2d /sys/compat/linux | |
parent | 50663e31ee3e3fbdb87999b718e485f2bea1036a (diff) |
If using async connect(), after select for writeable, if getpeername()
indicates connection failure, you can use getsockopt(SOL_SOCKET,
SO_ERROR, ...) to find the error. But the linux people I guess didn't
know about this, and changed connect() so that a 2nd connect() call on
a failed socket returns the error directly. Fake this demented
non-standard behaviour which Linux users are now starting to code to.
Talk about dilution of the API...
Diffstat (limited to 'sys/compat/linux')
-rw-r--r-- | sys/compat/linux/linux_socket.c | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c index 8acabfe65eb..5ad1cfa5506 100644 --- a/sys/compat/linux/linux_socket.c +++ b/sys/compat/linux/linux_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: linux_socket.c,v 1.4 1997/11/26 08:45:46 deraadt Exp $ */ +/* $OpenBSD: linux_socket.c,v 1.5 1997/11/26 08:51:08 deraadt Exp $ */ /* $NetBSD: linux_socket.c,v 1.14 1996/04/05 00:01:50 christos Exp $ */ /* @@ -198,7 +198,37 @@ linux_connect(p, uap, retval) SCARG(&bca, name) = (caddr_t) lca.name; SCARG(&bca, namelen) = lca.namelen; - return sys_connect(p, &bca, retval); + error = sys_connect(p, &bca, retval); + + if (error == EISCONN) { + struct sys_getsockopt_args bga; + void *status, *statusl; + int stat, statl = sizeof stat; + caddr_t sg; + + sg = stackgap_init(p->p_emul); + status = stackgap_alloc(&sg, sizeof stat); + statusl = stackgap_alloc(&sg, sizeof statusl); + + if ((error = copyout(&statl, statusl, sizeof statl))) + return error; + + SCARG(&bga, s) = lca.s; + SCARG(&bga, level) = SOL_SOCKET; + SCARG(&bga, name) = SO_ERROR; + SCARG(&bga, val) = status; + SCARG(&bga, avalsize) = statusl; + + error = sys_getsockopt(p, &bga, retval); + if (error) + return error; + if ((error = copyin(status, &stat, sizeof stat))) + return error; + if (stat) + return stat; + return EISCONN; + } + return error; } int |