diff --git a/sbin/mount_portal/Makefile b/sbin/mount_portal/Makefile index af7d5367e943..7734df49eee6 100644 --- a/sbin/mount_portal/Makefile +++ b/sbin/mount_portal/Makefile @@ -1,9 +1,9 @@ # From: @(#)Makefile 8.3 (Berkeley) 3/27/94 -# $Id: Makefile,v 1.7 1997/03/11 12:34:55 peter Exp $ +# $Id: Makefile,v 1.8 1998/01/20 10:40:04 bde Exp $ PROG= mount_portal SRCS= mount_portal.c activate.c conf.c getmntopts.c pt_conf.c \ - pt_exec.c pt_file.c pt_tcp.c + pt_exec.c pt_file.c pt_tcp.c pt_tcplisten.c MAN8= mount_portal.8 MOUNT= ${.CURDIR}/../mount diff --git a/sbin/mount_portal/mount_portal.8 b/sbin/mount_portal/mount_portal.8 index ed9434e557fe..5a5750faf19f 100644 --- a/sbin/mount_portal/mount_portal.8 +++ b/sbin/mount_portal/mount_portal.8 @@ -35,7 +35,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)mount_portal.8 8.3 (Berkeley) 3/27/94 -.\" $Id$ +.\" $Id: mount_portal.8,v 1.3 1998/07/06 07:19:25 charnier Exp $ .\" .Dd March 27, 1994 .Dt MOUNT_PORTAL 8 @@ -89,11 +89,22 @@ to the calling process as the result of the open system call. By convention, the portal daemon divides the namespace into sub-namespaces, each of which handles objects of a particular type. .Pp -Currently, two sub-namespaces are implemented: +The following sub-namespaces are currently implemented: +.Pa tcplisten , .Pa tcp and .Pa fs . The +.Pa tcplisten +namespace takes a slash separated hostname and port and creates a TCP/IP +socket bound to the given hostname-port pair. The hostname may be +specified as "ANY" to allow any other host to connect to the socket. A +port number of 0 will dynamically allocate a port, this can be +discovered by calling +.Xr getsockname 8 +with the returned file descriptor. Privilaged ports can only be bound to +by the super-user. +The .Pa tcp namespace takes a hostname and a port (slash separated) and creates an open TCP/IP connection. @@ -116,6 +127,7 @@ tells the daemon what type of object to create. Subsequent fields are passed to the creation function. .Bd -literal # @(#)portal.conf 5.1 (Berkeley) 7/13/92 +tcplisten/ tcplisten tcplisten/ tcp/ tcp tcp/ fs/ file fs/ .Ed diff --git a/sbin/mount_portal/mount_portal.c b/sbin/mount_portal/mount_portal.c index d3fa3c3a0dce..6de71ea947e7 100644 --- a/sbin/mount_portal/mount_portal.c +++ b/sbin/mount_portal/mount_portal.c @@ -45,7 +45,7 @@ char copyright[] = static char sccsid[] = "@(#)mount_portal.c 8.6 (Berkeley) 4/26/95"; #endif static const char rcsid[] = - "$Id$"; + "$Id: mount_portal.c,v 1.13 1998/07/06 07:19:25 charnier Exp $"; #endif /* not lint */ #include @@ -190,7 +190,9 @@ main(argc, argv) /* * Everything is ready to go - now is a good time to fork */ +#ifndef DEBUG daemon(0, 0); +#endif /* * Start logging (and change name) diff --git a/sbin/mount_portal/portald.h b/sbin/mount_portal/portald.h index 23fce24198fa..f01e8a88ca78 100644 --- a/sbin/mount_portal/portald.h +++ b/sbin/mount_portal/portald.h @@ -36,7 +36,7 @@ * * @(#)portald.h 8.1 (Berkeley) 6/5/93 * - * $Id$ + * $Id: portald.h,v 1.3 1997/02/22 14:32:55 peter Exp $ */ #include @@ -73,6 +73,8 @@ extern int portal_file __P((struct portal_cred *, char *key, char **v, int so, int *fdp)); extern int portal_tcp __P((struct portal_cred *, char *key, char **v, int so, int *fdp)); +extern int portal_tcplisten __P((struct portal_cred *, + char *key, char **v, int so, int *fdp)); /* * Global functions diff --git a/sbin/mount_portal/pt_conf.c b/sbin/mount_portal/pt_conf.c index 2f9ab9772a81..11088ea2934d 100644 --- a/sbin/mount_portal/pt_conf.c +++ b/sbin/mount_portal/pt_conf.c @@ -39,7 +39,7 @@ #ifndef lint static const char rcsid[] = - "$Id$"; + "$Id: pt_conf.c,v 1.4 1998/07/06 07:19:25 charnier Exp $"; #endif /* not lint */ #include @@ -50,5 +50,6 @@ provider providers[] = { { "exec", portal_exec }, { "file", portal_file }, { "tcp", portal_tcp }, + { "tcplisten", portal_tcplisten }, { 0, 0 } }; diff --git a/sbin/mount_portal/pt_tcp.c b/sbin/mount_portal/pt_tcp.c index d62ca3eb31a7..954388ee03fd 100644 --- a/sbin/mount_portal/pt_tcp.c +++ b/sbin/mount_portal/pt_tcp.c @@ -39,7 +39,7 @@ #ifndef lint static const char rcsid[] = - "$Id$"; + "$Id: pt_tcp.c,v 1.7 1998/07/06 07:19:27 charnier Exp $"; #endif /* not lint */ #include @@ -124,16 +124,16 @@ int portal_tcp(pcr, key, v, kso, fdp) #endif sp = getservbyname(port, "tcp"); - if (sp != NULL) + if (sp != NULL) { s_port = (u_short)sp->s_port; - else { + } else { s_port = strtoul(port, &p, 0); if (s_port == 0 || *p != '\0') return (EINVAL); s_port = htons(s_port); } #ifdef DEBUG - printf ("port number for %s is %d\n", port, ntohs(s_port)); + printf ("port number for %s is %d\n", port, (int)ntohs(s_port)); #endif memset(&sain, 0, sizeof(sain)); diff --git a/sbin/mount_portal/pt_tcplisten.c b/sbin/mount_portal/pt_tcplisten.c new file mode 100644 index 000000000000..43a20c5aa92c --- /dev/null +++ b/sbin/mount_portal/pt_tcplisten.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * This code is derived from software donated to Berkeley by + * Jan-Simon Pendry. + * + * Modified by Duncan Barclay. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pt_tcp.c 8.3 (Berkeley) 3/27/94 + * + * pt_tcp.c,v 1.1.1.1 1994/05/26 06:34:34 rgrimes Exp + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "portald.h" + +/* + * Key will be tcplisten/host/port + * + * Create a TCP socket bound to the requested host and port. + * If the host is "ANY" the receving address will be set to INADDR_ANY. + * If the port is 0 the caller must find out the returned port number + * using a call to getsockname. + * + * XXX! The owner of the socket will be root rather then the user. This + * may cause remote auth (identd) to return unexpected results. + * + */ +int portal_tcplisten(pcr, key, v, kso, fdp) + struct portal_cred *pcr; + char *key; + char **v; + int kso; + int *fdp; +{ + char host[MAXHOSTNAMELEN]; + char port[MAXHOSTNAMELEN]; + char *p = key + (v[1] ? strlen(v[1]) : 0); + char *q; + struct hostent *hp; + struct servent *sp; + struct in_addr **ipp; + struct in_addr *ip[2]; + struct in_addr ina; + u_short s_port; + int any = 0; + struct sockaddr_in sain; + + q = strchr(p, '/'); + if (q == 0 || q - p >= sizeof(host)) + return (EINVAL); + *q = '\0'; + snprintf(host, sizeof(host), "%s", p); + p = q + 1; + + q = strchr(p, '/'); + if (q) + *q = '\0'; + if (strlen(p) >= sizeof(port)) + return (EINVAL); + snprintf(port, sizeof(port), "%s", p); + + if (strcmp(host, "ANY") == 0) { + any = 1; + } else { + hp = gethostbyname(host); + if (hp != 0) { + ipp = (struct in_addr **) hp->h_addr_list; + } else { + ina.s_addr = inet_addr(host); + if (ina.s_addr == INADDR_NONE) + return (EINVAL); + ip[0] = &ina; + ip[1] = 0; + ipp = ip; + } + } +#ifdef DEBUG + if (any) + printf("INADDR_ANY to be used for hostname\n"); + else + printf("inet address for %s is %s\n", host, inet_ntoa(*ipp[0])); +#endif + + sp = getservbyname(port, "tcp"); + if (sp != NULL) { + s_port = (u_short) sp->s_port; + } else { + s_port = strtoul(port, &p, 0); + if (*p != '\0') + return (EINVAL); + s_port = htons(s_port); + } + if ((ntohs(s_port) != 0) && + (ntohs(s_port) <= IPPORT_RESERVED) && + (pcr->pcr_uid != 0)) + return (EPERM); +#ifdef DEBUG + printf("port number for %s is %d\n", port, ntohs(s_port)); +#endif + + memset(&sain, 0, sizeof(sain)); + sain.sin_len = sizeof(sain); + sain.sin_family = AF_INET; + sain.sin_port = s_port; + + if (any) { + int so; + int sock; + + so = socket(AF_INET, SOCK_STREAM, 0); + if (so < 0) { + syslog(LOG_ERR, "socket: %m"); + return (errno); + } + + sain.sin_addr.s_addr = INADDR_ANY; + if (bind(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) { + listen(so, 1); + if ((sock = accept(so, (struct sockaddr *)0, (int *)0)) == -1) { + syslog(LOG_ERR, "accept: %m"); + (void) close(so); + return (errno); + } + *fdp = sock; + (void) close(so); + return (0); + } + syslog(LOG_ERR, "bind: %m"); + (void) close(so); + return (errno); + } + + while (ipp[0]) { + int so; + int sock; + + so = socket(AF_INET, SOCK_STREAM, 0); + if (so < 0) { + syslog(LOG_ERR, "socket: %m"); + return (errno); + } + + sain.sin_addr = *ipp[0]; + if (bind(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) { + listen(so, 1); + if ((sock = accept(so, (struct sockaddr *)0, (int *)0)) == -1) { + syslog(LOG_ERR, "accept: %m"); + (void) close(so); + return (errno); + } + *fdp = sock; + (void) close(so); + return (0); + } + (void) close(so); + + ipp++; + } + + syslog(LOG_ERR, "bind: %m"); + return (errno); + +} diff --git a/sbin/mount_portalfs/Makefile b/sbin/mount_portalfs/Makefile index af7d5367e943..7734df49eee6 100644 --- a/sbin/mount_portalfs/Makefile +++ b/sbin/mount_portalfs/Makefile @@ -1,9 +1,9 @@ # From: @(#)Makefile 8.3 (Berkeley) 3/27/94 -# $Id: Makefile,v 1.7 1997/03/11 12:34:55 peter Exp $ +# $Id: Makefile,v 1.8 1998/01/20 10:40:04 bde Exp $ PROG= mount_portal SRCS= mount_portal.c activate.c conf.c getmntopts.c pt_conf.c \ - pt_exec.c pt_file.c pt_tcp.c + pt_exec.c pt_file.c pt_tcp.c pt_tcplisten.c MAN8= mount_portal.8 MOUNT= ${.CURDIR}/../mount diff --git a/sbin/mount_portalfs/mount_portalfs.8 b/sbin/mount_portalfs/mount_portalfs.8 index ed9434e557fe..5a5750faf19f 100644 --- a/sbin/mount_portalfs/mount_portalfs.8 +++ b/sbin/mount_portalfs/mount_portalfs.8 @@ -35,7 +35,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)mount_portal.8 8.3 (Berkeley) 3/27/94 -.\" $Id$ +.\" $Id: mount_portal.8,v 1.3 1998/07/06 07:19:25 charnier Exp $ .\" .Dd March 27, 1994 .Dt MOUNT_PORTAL 8 @@ -89,11 +89,22 @@ to the calling process as the result of the open system call. By convention, the portal daemon divides the namespace into sub-namespaces, each of which handles objects of a particular type. .Pp -Currently, two sub-namespaces are implemented: +The following sub-namespaces are currently implemented: +.Pa tcplisten , .Pa tcp and .Pa fs . The +.Pa tcplisten +namespace takes a slash separated hostname and port and creates a TCP/IP +socket bound to the given hostname-port pair. The hostname may be +specified as "ANY" to allow any other host to connect to the socket. A +port number of 0 will dynamically allocate a port, this can be +discovered by calling +.Xr getsockname 8 +with the returned file descriptor. Privilaged ports can only be bound to +by the super-user. +The .Pa tcp namespace takes a hostname and a port (slash separated) and creates an open TCP/IP connection. @@ -116,6 +127,7 @@ tells the daemon what type of object to create. Subsequent fields are passed to the creation function. .Bd -literal # @(#)portal.conf 5.1 (Berkeley) 7/13/92 +tcplisten/ tcplisten tcplisten/ tcp/ tcp tcp/ fs/ file fs/ .Ed diff --git a/sbin/mount_portalfs/mount_portalfs.c b/sbin/mount_portalfs/mount_portalfs.c index d3fa3c3a0dce..6de71ea947e7 100644 --- a/sbin/mount_portalfs/mount_portalfs.c +++ b/sbin/mount_portalfs/mount_portalfs.c @@ -45,7 +45,7 @@ char copyright[] = static char sccsid[] = "@(#)mount_portal.c 8.6 (Berkeley) 4/26/95"; #endif static const char rcsid[] = - "$Id$"; + "$Id: mount_portal.c,v 1.13 1998/07/06 07:19:25 charnier Exp $"; #endif /* not lint */ #include @@ -190,7 +190,9 @@ main(argc, argv) /* * Everything is ready to go - now is a good time to fork */ +#ifndef DEBUG daemon(0, 0); +#endif /* * Start logging (and change name) diff --git a/sbin/mount_portalfs/portald.h b/sbin/mount_portalfs/portald.h index 23fce24198fa..f01e8a88ca78 100644 --- a/sbin/mount_portalfs/portald.h +++ b/sbin/mount_portalfs/portald.h @@ -36,7 +36,7 @@ * * @(#)portald.h 8.1 (Berkeley) 6/5/93 * - * $Id$ + * $Id: portald.h,v 1.3 1997/02/22 14:32:55 peter Exp $ */ #include @@ -73,6 +73,8 @@ extern int portal_file __P((struct portal_cred *, char *key, char **v, int so, int *fdp)); extern int portal_tcp __P((struct portal_cred *, char *key, char **v, int so, int *fdp)); +extern int portal_tcplisten __P((struct portal_cred *, + char *key, char **v, int so, int *fdp)); /* * Global functions diff --git a/sbin/mount_portalfs/pt_conf.c b/sbin/mount_portalfs/pt_conf.c index 2f9ab9772a81..11088ea2934d 100644 --- a/sbin/mount_portalfs/pt_conf.c +++ b/sbin/mount_portalfs/pt_conf.c @@ -39,7 +39,7 @@ #ifndef lint static const char rcsid[] = - "$Id$"; + "$Id: pt_conf.c,v 1.4 1998/07/06 07:19:25 charnier Exp $"; #endif /* not lint */ #include @@ -50,5 +50,6 @@ provider providers[] = { { "exec", portal_exec }, { "file", portal_file }, { "tcp", portal_tcp }, + { "tcplisten", portal_tcplisten }, { 0, 0 } }; diff --git a/sbin/mount_portalfs/pt_tcp.c b/sbin/mount_portalfs/pt_tcp.c index d62ca3eb31a7..954388ee03fd 100644 --- a/sbin/mount_portalfs/pt_tcp.c +++ b/sbin/mount_portalfs/pt_tcp.c @@ -39,7 +39,7 @@ #ifndef lint static const char rcsid[] = - "$Id$"; + "$Id: pt_tcp.c,v 1.7 1998/07/06 07:19:27 charnier Exp $"; #endif /* not lint */ #include @@ -124,16 +124,16 @@ int portal_tcp(pcr, key, v, kso, fdp) #endif sp = getservbyname(port, "tcp"); - if (sp != NULL) + if (sp != NULL) { s_port = (u_short)sp->s_port; - else { + } else { s_port = strtoul(port, &p, 0); if (s_port == 0 || *p != '\0') return (EINVAL); s_port = htons(s_port); } #ifdef DEBUG - printf ("port number for %s is %d\n", port, ntohs(s_port)); + printf ("port number for %s is %d\n", port, (int)ntohs(s_port)); #endif memset(&sain, 0, sizeof(sain)); diff --git a/sbin/mount_portalfs/pt_tcplisten.c b/sbin/mount_portalfs/pt_tcplisten.c new file mode 100644 index 000000000000..43a20c5aa92c --- /dev/null +++ b/sbin/mount_portalfs/pt_tcplisten.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * This code is derived from software donated to Berkeley by + * Jan-Simon Pendry. + * + * Modified by Duncan Barclay. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pt_tcp.c 8.3 (Berkeley) 3/27/94 + * + * pt_tcp.c,v 1.1.1.1 1994/05/26 06:34:34 rgrimes Exp + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "portald.h" + +/* + * Key will be tcplisten/host/port + * + * Create a TCP socket bound to the requested host and port. + * If the host is "ANY" the receving address will be set to INADDR_ANY. + * If the port is 0 the caller must find out the returned port number + * using a call to getsockname. + * + * XXX! The owner of the socket will be root rather then the user. This + * may cause remote auth (identd) to return unexpected results. + * + */ +int portal_tcplisten(pcr, key, v, kso, fdp) + struct portal_cred *pcr; + char *key; + char **v; + int kso; + int *fdp; +{ + char host[MAXHOSTNAMELEN]; + char port[MAXHOSTNAMELEN]; + char *p = key + (v[1] ? strlen(v[1]) : 0); + char *q; + struct hostent *hp; + struct servent *sp; + struct in_addr **ipp; + struct in_addr *ip[2]; + struct in_addr ina; + u_short s_port; + int any = 0; + struct sockaddr_in sain; + + q = strchr(p, '/'); + if (q == 0 || q - p >= sizeof(host)) + return (EINVAL); + *q = '\0'; + snprintf(host, sizeof(host), "%s", p); + p = q + 1; + + q = strchr(p, '/'); + if (q) + *q = '\0'; + if (strlen(p) >= sizeof(port)) + return (EINVAL); + snprintf(port, sizeof(port), "%s", p); + + if (strcmp(host, "ANY") == 0) { + any = 1; + } else { + hp = gethostbyname(host); + if (hp != 0) { + ipp = (struct in_addr **) hp->h_addr_list; + } else { + ina.s_addr = inet_addr(host); + if (ina.s_addr == INADDR_NONE) + return (EINVAL); + ip[0] = &ina; + ip[1] = 0; + ipp = ip; + } + } +#ifdef DEBUG + if (any) + printf("INADDR_ANY to be used for hostname\n"); + else + printf("inet address for %s is %s\n", host, inet_ntoa(*ipp[0])); +#endif + + sp = getservbyname(port, "tcp"); + if (sp != NULL) { + s_port = (u_short) sp->s_port; + } else { + s_port = strtoul(port, &p, 0); + if (*p != '\0') + return (EINVAL); + s_port = htons(s_port); + } + if ((ntohs(s_port) != 0) && + (ntohs(s_port) <= IPPORT_RESERVED) && + (pcr->pcr_uid != 0)) + return (EPERM); +#ifdef DEBUG + printf("port number for %s is %d\n", port, ntohs(s_port)); +#endif + + memset(&sain, 0, sizeof(sain)); + sain.sin_len = sizeof(sain); + sain.sin_family = AF_INET; + sain.sin_port = s_port; + + if (any) { + int so; + int sock; + + so = socket(AF_INET, SOCK_STREAM, 0); + if (so < 0) { + syslog(LOG_ERR, "socket: %m"); + return (errno); + } + + sain.sin_addr.s_addr = INADDR_ANY; + if (bind(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) { + listen(so, 1); + if ((sock = accept(so, (struct sockaddr *)0, (int *)0)) == -1) { + syslog(LOG_ERR, "accept: %m"); + (void) close(so); + return (errno); + } + *fdp = sock; + (void) close(so); + return (0); + } + syslog(LOG_ERR, "bind: %m"); + (void) close(so); + return (errno); + } + + while (ipp[0]) { + int so; + int sock; + + so = socket(AF_INET, SOCK_STREAM, 0); + if (so < 0) { + syslog(LOG_ERR, "socket: %m"); + return (errno); + } + + sain.sin_addr = *ipp[0]; + if (bind(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) { + listen(so, 1); + if ((sock = accept(so, (struct sockaddr *)0, (int *)0)) == -1) { + syslog(LOG_ERR, "accept: %m"); + (void) close(so); + return (errno); + } + *fdp = sock; + (void) close(so); + return (0); + } + (void) close(so); + + ipp++; + } + + syslog(LOG_ERR, "bind: %m"); + return (errno); + +} diff --git a/usr.sbin/mount_portalfs/Makefile b/usr.sbin/mount_portalfs/Makefile index af7d5367e943..7734df49eee6 100644 --- a/usr.sbin/mount_portalfs/Makefile +++ b/usr.sbin/mount_portalfs/Makefile @@ -1,9 +1,9 @@ # From: @(#)Makefile 8.3 (Berkeley) 3/27/94 -# $Id: Makefile,v 1.7 1997/03/11 12:34:55 peter Exp $ +# $Id: Makefile,v 1.8 1998/01/20 10:40:04 bde Exp $ PROG= mount_portal SRCS= mount_portal.c activate.c conf.c getmntopts.c pt_conf.c \ - pt_exec.c pt_file.c pt_tcp.c + pt_exec.c pt_file.c pt_tcp.c pt_tcplisten.c MAN8= mount_portal.8 MOUNT= ${.CURDIR}/../mount diff --git a/usr.sbin/mount_portalfs/mount_portalfs.8 b/usr.sbin/mount_portalfs/mount_portalfs.8 index ed9434e557fe..5a5750faf19f 100644 --- a/usr.sbin/mount_portalfs/mount_portalfs.8 +++ b/usr.sbin/mount_portalfs/mount_portalfs.8 @@ -35,7 +35,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)mount_portal.8 8.3 (Berkeley) 3/27/94 -.\" $Id$ +.\" $Id: mount_portal.8,v 1.3 1998/07/06 07:19:25 charnier Exp $ .\" .Dd March 27, 1994 .Dt MOUNT_PORTAL 8 @@ -89,11 +89,22 @@ to the calling process as the result of the open system call. By convention, the portal daemon divides the namespace into sub-namespaces, each of which handles objects of a particular type. .Pp -Currently, two sub-namespaces are implemented: +The following sub-namespaces are currently implemented: +.Pa tcplisten , .Pa tcp and .Pa fs . The +.Pa tcplisten +namespace takes a slash separated hostname and port and creates a TCP/IP +socket bound to the given hostname-port pair. The hostname may be +specified as "ANY" to allow any other host to connect to the socket. A +port number of 0 will dynamically allocate a port, this can be +discovered by calling +.Xr getsockname 8 +with the returned file descriptor. Privilaged ports can only be bound to +by the super-user. +The .Pa tcp namespace takes a hostname and a port (slash separated) and creates an open TCP/IP connection. @@ -116,6 +127,7 @@ tells the daemon what type of object to create. Subsequent fields are passed to the creation function. .Bd -literal # @(#)portal.conf 5.1 (Berkeley) 7/13/92 +tcplisten/ tcplisten tcplisten/ tcp/ tcp tcp/ fs/ file fs/ .Ed diff --git a/usr.sbin/mount_portalfs/mount_portalfs.c b/usr.sbin/mount_portalfs/mount_portalfs.c index d3fa3c3a0dce..6de71ea947e7 100644 --- a/usr.sbin/mount_portalfs/mount_portalfs.c +++ b/usr.sbin/mount_portalfs/mount_portalfs.c @@ -45,7 +45,7 @@ char copyright[] = static char sccsid[] = "@(#)mount_portal.c 8.6 (Berkeley) 4/26/95"; #endif static const char rcsid[] = - "$Id$"; + "$Id: mount_portal.c,v 1.13 1998/07/06 07:19:25 charnier Exp $"; #endif /* not lint */ #include @@ -190,7 +190,9 @@ main(argc, argv) /* * Everything is ready to go - now is a good time to fork */ +#ifndef DEBUG daemon(0, 0); +#endif /* * Start logging (and change name) diff --git a/usr.sbin/mount_portalfs/portald.h b/usr.sbin/mount_portalfs/portald.h index 23fce24198fa..f01e8a88ca78 100644 --- a/usr.sbin/mount_portalfs/portald.h +++ b/usr.sbin/mount_portalfs/portald.h @@ -36,7 +36,7 @@ * * @(#)portald.h 8.1 (Berkeley) 6/5/93 * - * $Id$ + * $Id: portald.h,v 1.3 1997/02/22 14:32:55 peter Exp $ */ #include @@ -73,6 +73,8 @@ extern int portal_file __P((struct portal_cred *, char *key, char **v, int so, int *fdp)); extern int portal_tcp __P((struct portal_cred *, char *key, char **v, int so, int *fdp)); +extern int portal_tcplisten __P((struct portal_cred *, + char *key, char **v, int so, int *fdp)); /* * Global functions diff --git a/usr.sbin/mount_portalfs/pt_conf.c b/usr.sbin/mount_portalfs/pt_conf.c index 2f9ab9772a81..11088ea2934d 100644 --- a/usr.sbin/mount_portalfs/pt_conf.c +++ b/usr.sbin/mount_portalfs/pt_conf.c @@ -39,7 +39,7 @@ #ifndef lint static const char rcsid[] = - "$Id$"; + "$Id: pt_conf.c,v 1.4 1998/07/06 07:19:25 charnier Exp $"; #endif /* not lint */ #include @@ -50,5 +50,6 @@ provider providers[] = { { "exec", portal_exec }, { "file", portal_file }, { "tcp", portal_tcp }, + { "tcplisten", portal_tcplisten }, { 0, 0 } }; diff --git a/usr.sbin/mount_portalfs/pt_tcp.c b/usr.sbin/mount_portalfs/pt_tcp.c index d62ca3eb31a7..954388ee03fd 100644 --- a/usr.sbin/mount_portalfs/pt_tcp.c +++ b/usr.sbin/mount_portalfs/pt_tcp.c @@ -39,7 +39,7 @@ #ifndef lint static const char rcsid[] = - "$Id$"; + "$Id: pt_tcp.c,v 1.7 1998/07/06 07:19:27 charnier Exp $"; #endif /* not lint */ #include @@ -124,16 +124,16 @@ int portal_tcp(pcr, key, v, kso, fdp) #endif sp = getservbyname(port, "tcp"); - if (sp != NULL) + if (sp != NULL) { s_port = (u_short)sp->s_port; - else { + } else { s_port = strtoul(port, &p, 0); if (s_port == 0 || *p != '\0') return (EINVAL); s_port = htons(s_port); } #ifdef DEBUG - printf ("port number for %s is %d\n", port, ntohs(s_port)); + printf ("port number for %s is %d\n", port, (int)ntohs(s_port)); #endif memset(&sain, 0, sizeof(sain)); diff --git a/usr.sbin/mount_portalfs/pt_tcplisten.c b/usr.sbin/mount_portalfs/pt_tcplisten.c new file mode 100644 index 000000000000..43a20c5aa92c --- /dev/null +++ b/usr.sbin/mount_portalfs/pt_tcplisten.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * This code is derived from software donated to Berkeley by + * Jan-Simon Pendry. + * + * Modified by Duncan Barclay. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pt_tcp.c 8.3 (Berkeley) 3/27/94 + * + * pt_tcp.c,v 1.1.1.1 1994/05/26 06:34:34 rgrimes Exp + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "portald.h" + +/* + * Key will be tcplisten/host/port + * + * Create a TCP socket bound to the requested host and port. + * If the host is "ANY" the receving address will be set to INADDR_ANY. + * If the port is 0 the caller must find out the returned port number + * using a call to getsockname. + * + * XXX! The owner of the socket will be root rather then the user. This + * may cause remote auth (identd) to return unexpected results. + * + */ +int portal_tcplisten(pcr, key, v, kso, fdp) + struct portal_cred *pcr; + char *key; + char **v; + int kso; + int *fdp; +{ + char host[MAXHOSTNAMELEN]; + char port[MAXHOSTNAMELEN]; + char *p = key + (v[1] ? strlen(v[1]) : 0); + char *q; + struct hostent *hp; + struct servent *sp; + struct in_addr **ipp; + struct in_addr *ip[2]; + struct in_addr ina; + u_short s_port; + int any = 0; + struct sockaddr_in sain; + + q = strchr(p, '/'); + if (q == 0 || q - p >= sizeof(host)) + return (EINVAL); + *q = '\0'; + snprintf(host, sizeof(host), "%s", p); + p = q + 1; + + q = strchr(p, '/'); + if (q) + *q = '\0'; + if (strlen(p) >= sizeof(port)) + return (EINVAL); + snprintf(port, sizeof(port), "%s", p); + + if (strcmp(host, "ANY") == 0) { + any = 1; + } else { + hp = gethostbyname(host); + if (hp != 0) { + ipp = (struct in_addr **) hp->h_addr_list; + } else { + ina.s_addr = inet_addr(host); + if (ina.s_addr == INADDR_NONE) + return (EINVAL); + ip[0] = &ina; + ip[1] = 0; + ipp = ip; + } + } +#ifdef DEBUG + if (any) + printf("INADDR_ANY to be used for hostname\n"); + else + printf("inet address for %s is %s\n", host, inet_ntoa(*ipp[0])); +#endif + + sp = getservbyname(port, "tcp"); + if (sp != NULL) { + s_port = (u_short) sp->s_port; + } else { + s_port = strtoul(port, &p, 0); + if (*p != '\0') + return (EINVAL); + s_port = htons(s_port); + } + if ((ntohs(s_port) != 0) && + (ntohs(s_port) <= IPPORT_RESERVED) && + (pcr->pcr_uid != 0)) + return (EPERM); +#ifdef DEBUG + printf("port number for %s is %d\n", port, ntohs(s_port)); +#endif + + memset(&sain, 0, sizeof(sain)); + sain.sin_len = sizeof(sain); + sain.sin_family = AF_INET; + sain.sin_port = s_port; + + if (any) { + int so; + int sock; + + so = socket(AF_INET, SOCK_STREAM, 0); + if (so < 0) { + syslog(LOG_ERR, "socket: %m"); + return (errno); + } + + sain.sin_addr.s_addr = INADDR_ANY; + if (bind(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) { + listen(so, 1); + if ((sock = accept(so, (struct sockaddr *)0, (int *)0)) == -1) { + syslog(LOG_ERR, "accept: %m"); + (void) close(so); + return (errno); + } + *fdp = sock; + (void) close(so); + return (0); + } + syslog(LOG_ERR, "bind: %m"); + (void) close(so); + return (errno); + } + + while (ipp[0]) { + int so; + int sock; + + so = socket(AF_INET, SOCK_STREAM, 0); + if (so < 0) { + syslog(LOG_ERR, "socket: %m"); + return (errno); + } + + sain.sin_addr = *ipp[0]; + if (bind(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) { + listen(so, 1); + if ((sock = accept(so, (struct sockaddr *)0, (int *)0)) == -1) { + syslog(LOG_ERR, "accept: %m"); + (void) close(so); + return (errno); + } + *fdp = sock; + (void) close(so); + return (0); + } + (void) close(so); + + ipp++; + } + + syslog(LOG_ERR, "bind: %m"); + return (errno); + +}