From owner-freebsd-ports Sun Mar 4 18: 0:14 2001 Delivered-To: freebsd-ports@hub.freebsd.org Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 1EACC37B718 for ; Sun, 4 Mar 2001 18:00:05 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.1/8.11.1) id f25205u93753; Sun, 4 Mar 2001 18:00:05 -0800 (PST) (envelope-from gnats) Date: Sun, 4 Mar 2001 18:00:05 -0800 (PST) Message-Id: <200103050200.f25205u93753@freefall.freebsd.org> To: freebsd-ports@FreeBSD.org Cc: From: "Paul A. Scott" Subject: Re: ports/23001: StarOffice52 port cannot connect to non-local ip address Reply-To: "Paul A. Scott" Sender: owner-freebsd-ports@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org The following reply was made to PR ports/23001; it has been noted by GNATS. From: "Paul A. Scott" To: , "Paul A. Scott" 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 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 #include #include + #include + #include + #include + + /* 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