pt_tcp.c revision 22990
1/* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * All rights reserved. 5 * 6 * This code is derived from software donated to Berkeley by 7 * Jan-Simon Pendry. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)pt_tcp.c 8.3 (Berkeley) 3/27/94 38 * 39 * $Id$ 40 */ 41 42#include <stdio.h> 43#include <unistd.h> 44#include <stdlib.h> 45#include <errno.h> 46#include <strings.h> 47#include <sys/types.h> 48#include <sys/param.h> 49#include <sys/syslog.h> 50#include <sys/socket.h> 51#include <netinet/in.h> 52#include <arpa/inet.h> 53#include <netdb.h> 54 55#include "portald.h" 56 57/* 58 * Key will be tcp/host/port[/"priv"] 59 * Create a TCP socket connected to the 60 * requested host and port. 61 * Some trailing suffix values have special meanings. 62 * An unrecognised suffix is an error. 63 */ 64int portal_tcp(pcr, key, v, kso, fdp) 65struct portal_cred *pcr; 66char *key; 67char **v; 68int kso; 69int *fdp; 70{ 71 char host[MAXHOSTNAMELEN]; 72 char port[MAXHOSTNAMELEN]; 73 char *p = key + (v[1] ? strlen(v[1]) : 0); 74 char *q; 75 struct hostent *hp; 76 struct servent *sp; 77 struct in_addr **ipp; 78 struct in_addr *ip[2]; 79 struct in_addr ina; 80 u_short s_port; 81 int priv = 0; 82 struct sockaddr_in sain; 83 84 q = strchr(p, '/'); 85 if (q == 0 || q - p >= sizeof(host)) 86 return (EINVAL); 87 *q = '\0'; 88 strcpy(host, p); 89 p = q + 1; 90 91 q = strchr(p, '/'); 92 if (q) 93 *q = '\0'; 94 if (strlen(p) >= sizeof(port)) 95 return (EINVAL); 96 strcpy(port, p); 97 if (q) { 98 p = q + 1; 99 if (strcmp(p, "priv") == 0) { 100 if (pcr->pcr_uid == 0) 101 priv = 1; 102 else 103 return (EPERM); 104 } else { 105 return (EINVAL); 106 } 107 } 108 109 hp = gethostbyname(host); 110 if (hp != 0) { 111 ipp = (struct in_addr **) hp->h_addr_list; 112 } else { 113 ina.s_addr = inet_addr(host); 114 if (ina.s_addr == INADDR_NONE) 115 return (EINVAL); 116 ip[0] = &ina; 117 ip[1] = 0; 118 ipp = ip; 119 } 120#ifdef DEBUG 121 printf ("inet address for %s is %s\n", host, inet_ntoa(*ipp[0])); 122#endif 123 124 sp = getservbyname(port, "tcp"); 125 if (sp != NULL) 126 s_port = (u_short)sp->s_port; 127 else { 128 s_port = htons ((u_short)strtol (port, (char**)NULL, 10)); 129 if (s_port == 0) 130 return (EINVAL); 131 } 132#ifdef DEBUG 133 printf ("port number for %s is %d\n", port, s_port); 134#endif 135 136 bzero(&sain, sizeof(sain)); 137 sain.sin_len = sizeof(sain); 138 sain.sin_family = AF_INET; 139 sain.sin_port = s_port; 140 141 while (ipp[0]) { 142 int so; 143 144 if (priv) 145 so = rresvport((int *) 0); 146 else 147 so = socket(AF_INET, SOCK_STREAM, 0); 148 if (so < 0) { 149 syslog(LOG_ERR, "socket: %m"); 150 return (errno); 151 } 152 153 sain.sin_addr = *ipp[0]; 154 if (connect(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) { 155 *fdp = so; 156 return (0); 157 } 158 (void) close(so); 159 160 ipp++; 161 } 162 163 return (errno); 164} 165