1/* $NetBSD: pt_tcp.c,v 1.20 2007/07/02 18:07:45 pooka Exp $ */ 2 3/* 4 * Copyright (c) 1992, 1993, 1994 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software donated to Berkeley by 8 * Jan-Simon Pendry. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * from: Id: pt_tcp.c,v 1.1 1992/05/25 21:43:09 jsp Exp 35 * @(#)pt_tcp.c 8.5 (Berkeley) 4/28/95 36 */ 37 38#include <sys/cdefs.h> 39#ifndef lint 40__RCSID("$NetBSD: pt_tcp.c,v 1.20 2007/07/02 18:07:45 pooka Exp $"); 41#endif /* not lint */ 42 43#include <stdio.h> 44#include <unistd.h> 45#include <stdlib.h> 46#include <errno.h> 47#include <string.h> 48#include <sys/types.h> 49#include <sys/param.h> 50#include <sys/syslog.h> 51#include <sys/socket.h> 52#include <netinet/in.h> 53#include <arpa/inet.h> 54#include <netdb.h> 55 56#include "portald.h" 57 58/* 59 * Key will be tcp/host/port[/"priv"] 60 * Create a TCP socket connected to the 61 * requested host and port. 62 * Some trailing suffix values have special meanings. 63 * An unrecognised suffix is an error. 64 */ 65int 66portal_tcp(struct portal_cred *pcr, char *key, char **v, int *fdp) 67{ 68 char host[MAXHOSTNAMELEN]; 69 char port[MAXHOSTNAMELEN]; 70 char *p = key + (v[1] ? strlen(v[1]) : 0); 71 char *q; 72 int priv = 0; 73 struct addrinfo hints, *res, *lres; 74 int so = -1; 75 const char *cause = "unknown"; 76 77 q = strchr(p, '/'); 78 if (q == 0 || (size_t)(q - p) >= sizeof(host)) 79 return (EINVAL); 80 *q = '\0'; 81 if (strlcpy(host, p, sizeof(host)) >= sizeof(host)) 82 return (EINVAL); 83 p = q + 1; 84 85 q = strchr(p, '/'); 86 if (q) 87 *q = '\0'; 88 if (strlcpy(port, p, sizeof(port)) >= sizeof(port)) 89 return (EINVAL); 90 if (q) { 91 p = q + 1; 92 if (strcmp(p, "priv") == 0) { 93 if (pcr->pcr_uid == 0) 94 priv = 1; 95 else 96 return (EPERM); 97 } else { 98 return (EINVAL); 99 } 100 } 101 102 memset(&hints, 0, sizeof(hints)); 103 hints.ai_family = PF_UNSPEC; 104 hints.ai_socktype = SOCK_STREAM; 105 hints.ai_protocol = 0; 106 if (getaddrinfo(host, port, &hints, &res) != 0) 107 return(EINVAL); 108 109 for (lres = res; lres; lres = lres->ai_next) { 110 if (priv) 111 so = rresvport((int *) 0); 112 else 113 so = socket(lres->ai_family, lres->ai_socktype, 114 lres->ai_protocol); 115 if (so < 0) { 116 cause = "socket"; 117 continue; 118 } 119 120 if (connect(so, lres->ai_addr, lres->ai_addrlen) != 0) { 121 cause = "connect"; 122 (void)close(so); 123 so = -1; 124 continue; 125 } 126 127 *fdp = so; 128 errno = 0; 129 break; 130 } 131 132 if (so < 0) 133 syslog(LOG_WARNING, "%s: %m", cause); 134 135 freeaddrinfo(res); 136 137 return (errno); 138} 139