summaryrefslogtreecommitdiff
path: root/sbin/mount_portal/pt_tcp.c
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2004-03-01 22:36:33 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2004-03-01 22:36:33 +0000
commit1f8104b7a50101fae5799cfc0ff8773fbf3440a2 (patch)
tree41e9e18d05b775cc5d06a786d919241c92d25a1a /sbin/mount_portal/pt_tcp.c
parent13933df6b1d4b8b96628124e90f16f73c2dd44df (diff)
rewrite featuring IP6 support from Pedro Martelletto <pbastos@rdc.puc-rio.br>
ok deraadt@
Diffstat (limited to 'sbin/mount_portal/pt_tcp.c')
-rw-r--r--sbin/mount_portal/pt_tcp.c199
1 files changed, 81 insertions, 118 deletions
diff --git a/sbin/mount_portal/pt_tcp.c b/sbin/mount_portal/pt_tcp.c
index a1a08e82bb8..c345a0d72db 100644
--- a/sbin/mount_portal/pt_tcp.c
+++ b/sbin/mount_portal/pt_tcp.c
@@ -1,152 +1,115 @@
-/* $OpenBSD: pt_tcp.c,v 1.8 2003/06/11 06:22:14 deraadt Exp $ */
-/* $NetBSD: pt_tcp.c,v 1.9 1995/05/21 15:33:22 mycroft Exp $ */
+/* $OpenBSD: pt_tcp.c,v 1.9 2004/03/01 22:36:32 tedu Exp $ */
/*
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2004 Pedro Martelletto <pbastos@rdc.puc-rio.br>
* All rights reserved.
*
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * 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. 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.
- *
- * from: Id: pt_tcp.c,v 1.1 1992/05/25 21:43:09 jsp Exp
- * @(#)pt_tcp.c 8.5 (Berkeley) 4/28/95
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
#include <sys/param.h>
-#include <sys/syslog.h>
#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
+
+#include <unistd.h>
+#include <syslog.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
#include <netdb.h>
+#include <errno.h>
#include "portald.h"
/*
- * Key will be tcp/host/port[/"priv"]
- * Create a TCP socket connected to the
- * requested host and port.
- * Some trailing suffix values have special meanings.
- * An unrecognised suffix is an error.
+ * Keys should follow the format: tcp/[4||6]/host/port/["priv"]
*/
int
-portal_tcp(struct portal_cred *pcr, char *key, char **v, int kso, int *fdp)
+portal_tcp(struct portal_cred *pcr, char *key, char **v, int ks, 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;
- int s_port;
- int priv = 0;
- struct sockaddr_in sain;
-
- q = strchr(p, '/');
- if (q == 0 || q - p >= sizeof(host))
- return (EINVAL);
- *q = '\0';
- (void)strlcpy(host, p, sizeof(host));
- p = q + 1;
-
- q = strchr(p, '/');
- if (q)
- *q = '\0';
- if (strlen(p) >= sizeof(port))
- return (EINVAL);
- (void)strlcpy(port, p, sizeof(port));
- if (q) {
- p = q + 1;
- if (strcmp(p, "priv") == 0) {
- if (pcr->pcr_uid == 0)
- priv = 1;
- else
- return (EPERM);
- } else {
- return (EINVAL);
+ char **tp, *tokens[5];
+ int priv, s, tc, n;
+ struct addrinfo aih, *ai, *ail;
+
+ tc = 0;
+ for (tp = tokens; tp < &tokens[5] &&
+ (*tp = strsep(&key, "/")) != NULL;)
+ if (**tp != '\0') {
+ tp++;
+ tc++;
}
- }
- if (inet_aton(host, &ina) == 0) {
- hp = gethostbyname(host);
- if (hp == 0)
+ if (tc < 3)
+ return (EINVAL);
+
+ memset(&aih, 0x0, sizeof(aih));
+ aih.ai_socktype = SOCK_STREAM;
+ aih.ai_family = PF_UNSPEC;
+
+ tp = tokens;
+ if (tc > 3) {
+ if (!strcmp(tokens[1], "4"))
+ aih.ai_family = PF_INET;
+ else if (!strcmp(tokens[1], "6"))
+ aih.ai_family = PF_INET6;
+ else
return (EINVAL);
- ipp = (struct in_addr **)hp->h_addr_list;
- } else {
- ip[0] = &ina;
- ip[1] = 0;
- ipp = ip;
+
+ tp++;
+ tc--;
}
- sp = getservbyname(port, "tcp");
- if (sp != 0)
- s_port = sp->s_port;
- else {
- s_port = strtoul(port, &p, 0);
- if (s_port == 0 || *p != '\0')
- return (EINVAL);
- s_port = htons(s_port);
+ priv = 0;
+ if (!strcmp(tp[tc - 1], "priv")) {
+ if (pcr->pcr_uid == 0)
+ priv = 1;
+ else
+ return (EPERM);
}
- (void)memset(&sain, 0, sizeof(sain));
- sain.sin_len = sizeof(sain);
- sain.sin_family = AF_INET;
- sain.sin_port = s_port;
+ n = getaddrinfo(tp[1], tp[2], &aih, &ail);
+ if (n) {
+ syslog(LOG_ERR, "getaddrinfo: %s", gai_strerror(n));
+ return (EINVAL);
+ }
- while (ipp[0]) {
- int so;
+ s = -1;
+ for (ai = ail; ai != NULL; ai = ai->ai_next) {
if (priv)
- so = rresvport(NULL);
+ s = rresvport(NULL);
else
- so = socket(AF_INET, SOCK_STREAM, 0);
- if (so < 0) {
+ s = socket(ai->ai_family, ai->ai_socktype,
+ ai->ai_protocol);
+ if (s < 0) {
syslog(LOG_ERR, "socket: %m");
- return (errno);
+ continue;
}
- sain.sin_addr = *ipp[0];
- if (connect(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) {
- *fdp = so;
- return (0);
- }
- (void)close(so);
-
- ipp++;
+ n = connect(s, ai->ai_addr, ai->ai_addrlen);
+ if (n) {
+ syslog(LOG_ERR, "connect: %m");
+ close(s);
+ s = -1;
+ continue;
+ } else
+ break;
}
- return (errno);
+ freeaddrinfo(ail);
+
+ if (s == -1)
+ return (errno);
+
+ *fdp = s;
+ return (0);
}