Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 4 Mar 2001 18:00:05 -0800 (PST)
From:      "Paul A. Scott" <pscott@the-frontier.org>
To:        freebsd-ports@FreeBSD.org
Subject:   Re: ports/23001: StarOffice52 port cannot connect to non-local ip address
Message-ID:  <200103050200.f25205u93753@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR ports/23001; it has been noted by GNATS.

From: "Paul A. Scott" <pscott@the-frontier.org>
To: <freebsd-gnats-submit@FreeBSD.org>,
	"Paul A. Scott" <pscott@the-frontier.org>
Cc:  
Subject: Re: ports/23001: StarOffice52 port cannot connect to non-local ip address
Date: Sun, 4 Mar 2001 17:54:51 -0800

 Thanks to Martin Blapp <mb@imp.ch> this problem has been fixed in
 FreeBSD4.3; However, for those of you who are running 4.1, I have
 prepared the following patch, which has solved the problem on my
 system. The patch may work on other 4.x releases, but I've only
 tested it on 4.1. Works GREAT! This patch is a workaround only as
 the code has been assembled from various places and combined into
 linux_socket.c for easier application.
 
 After patching linux_socket.c, rebuild your current configuration
 and the restart the linux module, for example,
 
 kldunload linux
 kldload linux
 
 No need to reboot the system.
 
 The patch:
 
 *** linux_socket.c.old	Sun Mar  4 16:23:57 2001
 --- linux_socket.c	Sun Mar  4 17:28:53 2001
 ***************
 *** 50,57 ****
 --- 50,79 ----
   #include <i386/linux/linux.h>
   #include <i386/linux/linux_proto.h>
   #include <i386/linux/linux_util.h>
 
 + #include <sys/file.h>
 + #include <sys/filedesc.h>
 + #include <sys/socketvar.h>
 +
 + /* msg flags in recvfrom/recvmsg */
 +
 + #define LINUX_MSG_OOB           0x01
 + #define LINUX_MSG_PEEK          0x02
 + #define LINUX_MSG_DONTROUTE     0x04
 + #define LINUX_MSG_CTRUNC        0x08
 + #define LINUX_MSG_PROXY         0x10
 + #define LINUX_MSG_TRUNC         0x20
 + #define LINUX_MSG_DONTWAIT      0x40
 + #define LINUX_MSG_EOR           0x80
 + #define LINUX_MSG_WAITALL       0x100
 + #define LINUX_MSG_FIN           0x200
 + #define LINUX_MSG_SYN           0x400
 + #define LINUX_MSG_CONFIRM       0x800
 + #define LINUX_MSG_RST           0x1000
 + #define LINUX_MSG_ERRQUEUE      0x2000
 + #define LINUX_MSG_NOSIGNAL      0x4000
 +
   static int
   linux_to_bsd_domain(int domain)
   {
       switch (domain) {
 ***************
 *** 141,148 ****
 --- 163,194 ----
   	return -1;
       }
   }
 
 + static int
 + linux_to_bsd_msg_flags(int flags)
 + {
 +       int ret_flags = 0;
 +
 +       if (flags & LINUX_MSG_OOB)
 +               ret_flags |= MSG_OOB;
 +       if (flags & LINUX_MSG_PEEK)
 +               ret_flags |= MSG_PEEK;
 +       if (flags & LINUX_MSG_DONTROUTE)
 +               ret_flags |= MSG_DONTROUTE;
 +       if (flags & LINUX_MSG_CTRUNC)
 +               ret_flags |= MSG_CTRUNC;
 +       if (flags & LINUX_MSG_TRUNC)
 +               ret_flags |= MSG_TRUNC;
 +       if (flags & LINUX_MSG_DONTWAIT)
 +               ret_flags |= MSG_DONTWAIT;
 +       if (flags & LINUX_MSG_EOR)
 +               ret_flags |= MSG_EOR;
 +       if (flags & LINUX_MSG_WAITALL)
 +               ret_flags |= MSG_WAITALL;
 +       return ret_flags;
 + }
 +
   /* Return 0 if IP_HDRINCL is set of the given socket, not 0 otherwise */
   static int
   linux_check_hdrincl(struct proc *p, int s)
   {
 ***************
 *** 244,251 ****
 --- 290,315 ----
       sendmsg_args.flags = bsd_args->flags;
       return sendmsg(p, &sendmsg_args);
   }
 
 + int holdsock(struct filedesc *fdp, int fdes, struct file **fpp)
 + {
 +         register struct file *fp = NULL;
 +         int error = 0;
 +
 +         if ((unsigned)fdes >= fdp->fd_nfiles ||
 +             (fp = fdp->fd_ofiles[fdes]) == NULL) {
 +                 error = EBADF;
 +         } else if (fp->f_type != DTYPE_SOCKET) {
 +                 error = ENOTSOCK;
 +                 fp = NULL;
 +         } else {
 +                 fhold(fp);
 +         }
 +         *fpp = fp;
 +         return(error);
 + }
 +
   struct linux_socket_args {
       int domain;
       int type;
       int protocol;
 ***************
 *** 342,407 ****
   	int s;
   	caddr_t name;
   	int namelen;
       } */ bsd_args;
       int error;
 
       if ((error=copyin((caddr_t)args, (caddr_t)&linux_args,
 sizeof(linux_args))))
   	return error;
       bsd_args.s = linux_args.s;
       bsd_args.name = (caddr_t)linux_args.name;
       bsd_args.namelen = linux_args.namelen;
       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 {
 --- 406,442 ----
   	int s;
   	caddr_t name;
   	int namelen;
       } */ bsd_args;
 +     struct socket *so;
 +     struct file *fp;
       int error;
 
       if ((error=copyin((caddr_t)args, (caddr_t)&linux_args,
 sizeof(linux_args))))
   	return error;
       bsd_args.s = linux_args.s;
       bsd_args.name = (caddr_t)linux_args.name;
       bsd_args.namelen = linux_args.namelen;
       error = connect(p, &bsd_args);
 !     if (error != EISCONN)
 !             return (error);
 !
       /*
        * 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.
        */
 !     error = holdsock(p->p_fd, linux_args.s, &fp);
       if (error)
       	return error;
 !     error = EISCONN;
 !     if (fp->f_flag & FNONBLOCK) {
 !     	so = (struct socket *)fp->f_data;
 !     	if ((u_int)so->so_emuldata == 0)
 !     		error = so->so_error;
 !     	so->so_emuldata = (void *)1;
       }
 +     fdrop( fp, p );
       return error;
   }
 
   struct linux_listen_args {
 ***************
 *** 672,683 ****
   	return error;
       bsd_args.s = linux_args.s;
       bsd_args.buf = linux_args.buf;
       bsd_args.len = linux_args.len;
 !     bsd_args.flags = linux_args.flags;
       bsd_args.from = linux_args.from;
       bsd_args.fromlenaddr = linux_args.fromlen;
       return orecvfrom(p, &bsd_args);
   }
 
   struct linux_shutdown_args {
       int s;
 --- 707,744 ----
   	return error;
       bsd_args.s = linux_args.s;
       bsd_args.buf = linux_args.buf;
       bsd_args.len = linux_args.len;
 !     bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags);
       bsd_args.from = linux_args.from;
       bsd_args.fromlenaddr = linux_args.fromlen;
       return orecvfrom(p, &bsd_args);
 + }
 +
 + struct linux_recvmsg_args {
 +       int s;
 +       struct msghdr *msg;
 +       int flags;
 + };
 +
 + static int
 + linux_recvmsg(struct proc *p, struct linux_recvmsg_args *args)
 + {
 +       struct linux_recvmsg_args linux_args;
 +       struct recvmsg_args /* {
 +               int     s;
 +               struct  msghdr *msg;
 +               int     flags;
 +       } */ bsd_args;
 +       int error;
 +
 +       if ((error = copyin(args, &linux_args, sizeof(linux_args))))
 +               return (error);
 +
 +       bsd_args.s = linux_args.s;
 +       bsd_args.msg = linux_args.msg;
 +       bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags);
 +       return (recvmsg(p, &bsd_args));
   }
 
   struct linux_shutdown_args {
       int s;
 

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-ports" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200103050200.f25205u93753>