diff options
author | Ted Unangst <tedu@cvs.openbsd.org> | 2004-03-01 22:36:33 +0000 |
---|---|---|
committer | Ted Unangst <tedu@cvs.openbsd.org> | 2004-03-01 22:36:33 +0000 |
commit | 1f8104b7a50101fae5799cfc0ff8773fbf3440a2 (patch) | |
tree | 41e9e18d05b775cc5d06a786d919241c92d25a1a /sbin/mount_portal/pt_tcp.c | |
parent | 13933df6b1d4b8b96628124e90f16f73c2dd44df (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.c | 199 |
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); } |