mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-15 10:17:20 +00:00
In the words of the submitter:
---- I've worked to enhance the connect() patches. I've just tested this with the Linux JDK appletviewer on an applet that does a lot of connects, and it works as well as during my previous tests. The connect() patch is now a merge between my older patch and the OpenBSD stuff. It ensures that any async error is returned by connect() instead of getsockopt(SOL_SOCKET, SO_ERROR) as reasonnable systems do. There are also minor patches to implement IPPROTO_TCP for get/setsocktopt(). These are also tested (with Linux Apache). ---- I would appreciate any feedback regarding these changes, as they'd be very useful in 2.2.6. Submitted by: pb@fasterix.freenix.org (Pierre Beyssac)
This commit is contained in:
parent
ca6f868824
commit
dad3b88ae3
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=33148
@ -25,7 +25,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: linux_socket.c,v 1.10 1997/12/14 03:17:54 msmith Exp $
|
* $Id: linux_socket.c,v 1.11 1997/12/16 17:40:11 eivind Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* XXX we use functions that might not exist. */
|
/* XXX we use functions that might not exist. */
|
||||||
@ -39,6 +39,7 @@
|
|||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/sysproto.h>
|
#include <sys/sysproto.h>
|
||||||
|
#include <sys/fcntl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@ -348,7 +349,58 @@ linux_connect(struct proc *p, struct linux_connect_args *args)
|
|||||||
bsd_args.s = linux_args.s;
|
bsd_args.s = linux_args.s;
|
||||||
bsd_args.name = (caddr_t)linux_args.name;
|
bsd_args.name = (caddr_t)linux_args.name;
|
||||||
bsd_args.namelen = linux_args.namelen;
|
bsd_args.namelen = linux_args.namelen;
|
||||||
return connect(p, &bsd_args);
|
error = connect(p, &bsd_args);
|
||||||
|
if (error == EISCONN) {
|
||||||
|
/*
|
||||||
|
* Linux doesn't return EISCONN the first time it occurs,
|
||||||
|
* when on a non-blocking socket. Instead it returns the
|
||||||
|
* error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD.
|
||||||
|
*/
|
||||||
|
struct fcntl_args /* {
|
||||||
|
int fd;
|
||||||
|
int cmd;
|
||||||
|
int arg;
|
||||||
|
} */ bsd_fcntl_args;
|
||||||
|
struct getsockopt_args /* {
|
||||||
|
int s;
|
||||||
|
int level;
|
||||||
|
int name;
|
||||||
|
caddr_t val;
|
||||||
|
int *avalsize;
|
||||||
|
} */ bsd_getsockopt_args;
|
||||||
|
void *status, *statusl;
|
||||||
|
int stat, statl = sizeof stat;
|
||||||
|
caddr_t sg;
|
||||||
|
|
||||||
|
/* Check for non-blocking */
|
||||||
|
bsd_fcntl_args.fd = linux_args.s;
|
||||||
|
bsd_fcntl_args.cmd = F_GETFL;
|
||||||
|
bsd_fcntl_args.arg = 0;
|
||||||
|
error = fcntl(p, &bsd_fcntl_args);
|
||||||
|
if (error == 0 && (p->p_retval[0] & O_NONBLOCK)) {
|
||||||
|
sg = stackgap_init();
|
||||||
|
status = stackgap_alloc(&sg, sizeof stat);
|
||||||
|
statusl = stackgap_alloc(&sg, sizeof statusl);
|
||||||
|
|
||||||
|
if ((error = copyout(&statl, statusl, sizeof statl)))
|
||||||
|
return error;
|
||||||
|
|
||||||
|
bsd_getsockopt_args.s = linux_args.s;
|
||||||
|
bsd_getsockopt_args.level = SOL_SOCKET;
|
||||||
|
bsd_getsockopt_args.name = SO_ERROR;
|
||||||
|
bsd_getsockopt_args.val = status;
|
||||||
|
bsd_getsockopt_args.avalsize = statusl;
|
||||||
|
|
||||||
|
error = getsockopt(p, &bsd_getsockopt_args);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
if ((error = copyin(status, &stat, sizeof stat)))
|
||||||
|
return error;
|
||||||
|
p->p_retval[0] = stat;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct linux_listen_args {
|
struct linux_listen_args {
|
||||||
@ -661,6 +713,10 @@ linux_setsockopt(struct proc *p, struct linux_setsockopt_args *args)
|
|||||||
case IPPROTO_IP:
|
case IPPROTO_IP:
|
||||||
name = linux_to_bsd_ip_sockopt(linux_args.optname);
|
name = linux_to_bsd_ip_sockopt(linux_args.optname);
|
||||||
break;
|
break;
|
||||||
|
case IPPROTO_TCP:
|
||||||
|
/* Linux TCP option values match BSD's */
|
||||||
|
name = linux_args.optname;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
@ -704,6 +760,10 @@ linux_getsockopt(struct proc *p, struct linux_getsockopt_args *args)
|
|||||||
case IPPROTO_IP:
|
case IPPROTO_IP:
|
||||||
name = linux_to_bsd_ip_sockopt(linux_args.optname);
|
name = linux_to_bsd_ip_sockopt(linux_args.optname);
|
||||||
break;
|
break;
|
||||||
|
case IPPROTO_TCP:
|
||||||
|
/* Linux TCP option values match BSD's */
|
||||||
|
name = linux_args.optname;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id: linux_socket.c,v 1.10 1997/12/14 03:17:54 msmith Exp $
|
* $Id: linux_socket.c,v 1.11 1997/12/16 17:40:11 eivind Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* XXX we use functions that might not exist. */
|
/* XXX we use functions that might not exist. */
|
||||||
@ -39,6 +39,7 @@
|
|||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/sysproto.h>
|
#include <sys/sysproto.h>
|
||||||
|
#include <sys/fcntl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@ -348,7 +349,58 @@ linux_connect(struct proc *p, struct linux_connect_args *args)
|
|||||||
bsd_args.s = linux_args.s;
|
bsd_args.s = linux_args.s;
|
||||||
bsd_args.name = (caddr_t)linux_args.name;
|
bsd_args.name = (caddr_t)linux_args.name;
|
||||||
bsd_args.namelen = linux_args.namelen;
|
bsd_args.namelen = linux_args.namelen;
|
||||||
return connect(p, &bsd_args);
|
error = connect(p, &bsd_args);
|
||||||
|
if (error == EISCONN) {
|
||||||
|
/*
|
||||||
|
* Linux doesn't return EISCONN the first time it occurs,
|
||||||
|
* when on a non-blocking socket. Instead it returns the
|
||||||
|
* error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD.
|
||||||
|
*/
|
||||||
|
struct fcntl_args /* {
|
||||||
|
int fd;
|
||||||
|
int cmd;
|
||||||
|
int arg;
|
||||||
|
} */ bsd_fcntl_args;
|
||||||
|
struct getsockopt_args /* {
|
||||||
|
int s;
|
||||||
|
int level;
|
||||||
|
int name;
|
||||||
|
caddr_t val;
|
||||||
|
int *avalsize;
|
||||||
|
} */ bsd_getsockopt_args;
|
||||||
|
void *status, *statusl;
|
||||||
|
int stat, statl = sizeof stat;
|
||||||
|
caddr_t sg;
|
||||||
|
|
||||||
|
/* Check for non-blocking */
|
||||||
|
bsd_fcntl_args.fd = linux_args.s;
|
||||||
|
bsd_fcntl_args.cmd = F_GETFL;
|
||||||
|
bsd_fcntl_args.arg = 0;
|
||||||
|
error = fcntl(p, &bsd_fcntl_args);
|
||||||
|
if (error == 0 && (p->p_retval[0] & O_NONBLOCK)) {
|
||||||
|
sg = stackgap_init();
|
||||||
|
status = stackgap_alloc(&sg, sizeof stat);
|
||||||
|
statusl = stackgap_alloc(&sg, sizeof statusl);
|
||||||
|
|
||||||
|
if ((error = copyout(&statl, statusl, sizeof statl)))
|
||||||
|
return error;
|
||||||
|
|
||||||
|
bsd_getsockopt_args.s = linux_args.s;
|
||||||
|
bsd_getsockopt_args.level = SOL_SOCKET;
|
||||||
|
bsd_getsockopt_args.name = SO_ERROR;
|
||||||
|
bsd_getsockopt_args.val = status;
|
||||||
|
bsd_getsockopt_args.avalsize = statusl;
|
||||||
|
|
||||||
|
error = getsockopt(p, &bsd_getsockopt_args);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
if ((error = copyin(status, &stat, sizeof stat)))
|
||||||
|
return error;
|
||||||
|
p->p_retval[0] = stat;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct linux_listen_args {
|
struct linux_listen_args {
|
||||||
@ -661,6 +713,10 @@ linux_setsockopt(struct proc *p, struct linux_setsockopt_args *args)
|
|||||||
case IPPROTO_IP:
|
case IPPROTO_IP:
|
||||||
name = linux_to_bsd_ip_sockopt(linux_args.optname);
|
name = linux_to_bsd_ip_sockopt(linux_args.optname);
|
||||||
break;
|
break;
|
||||||
|
case IPPROTO_TCP:
|
||||||
|
/* Linux TCP option values match BSD's */
|
||||||
|
name = linux_args.optname;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
@ -704,6 +760,10 @@ linux_getsockopt(struct proc *p, struct linux_getsockopt_args *args)
|
|||||||
case IPPROTO_IP:
|
case IPPROTO_IP:
|
||||||
name = linux_to_bsd_ip_sockopt(linux_args.optname);
|
name = linux_to_bsd_ip_sockopt(linux_args.optname);
|
||||||
break;
|
break;
|
||||||
|
case IPPROTO_TCP:
|
||||||
|
/* Linux TCP option values match BSD's */
|
||||||
|
name = linux_args.optname;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user