155f8326cSpendry /*
2c8070d05Spendry * Copyright (c) 1992, 1993, 1994
3cab636daSbostic * The Regents of the University of California. All rights reserved.
455f8326cSpendry * All rights reserved.
555f8326cSpendry *
655f8326cSpendry * This code is derived from software donated to Berkeley by
755f8326cSpendry * Jan-Simon Pendry.
855f8326cSpendry *
955f8326cSpendry * %sccs.include.redist.c%
1055f8326cSpendry *
11*e2bbe8e2Sbostic * @(#)pt_tcp.c 8.5 (Berkeley) 04/28/95
1255f8326cSpendry *
1355f8326cSpendry * $Id: pt_tcp.c,v 1.1 1992/05/25 21:43:09 jsp Exp jsp $
1455f8326cSpendry */
1555f8326cSpendry
1655f8326cSpendry #include <stdio.h>
1755f8326cSpendry #include <unistd.h>
1855f8326cSpendry #include <stdlib.h>
1955f8326cSpendry #include <errno.h>
20459c89dcSpendry #include <strings.h>
2155f8326cSpendry #include <sys/types.h>
22459c89dcSpendry #include <sys/param.h>
2355f8326cSpendry #include <sys/syslog.h>
241d41bcacSpendry #include <sys/socket.h>
251d41bcacSpendry #include <netinet/in.h>
26b7c2c946Spendry #include <arpa/inet.h>
271d41bcacSpendry #include <netdb.h>
2855f8326cSpendry
2955f8326cSpendry #include "portald.h"
3055f8326cSpendry
31459c89dcSpendry /*
32459c89dcSpendry * Key will be tcp/host/port[/"priv"]
33459c89dcSpendry * Create a TCP socket connected to the
34459c89dcSpendry * requested host and port.
35459c89dcSpendry * Some trailing suffix values have special meanings.
36459c89dcSpendry * An unrecognised suffix is an error.
37459c89dcSpendry */
portal_tcp(pcr,key,v,kso,fdp)381d41bcacSpendry int portal_tcp(pcr, key, v, kso, fdp)
3955f8326cSpendry struct portal_cred *pcr;
4055f8326cSpendry char *key;
4155f8326cSpendry char **v;
421d41bcacSpendry int kso;
4355f8326cSpendry int *fdp;
4455f8326cSpendry {
45459c89dcSpendry char host[MAXHOSTNAMELEN];
46459c89dcSpendry char port[MAXHOSTNAMELEN];
47459c89dcSpendry char *p = key + (v[1] ? strlen(v[1]) : 0);
48459c89dcSpendry char *q;
491d41bcacSpendry struct hostent *hp;
501d41bcacSpendry struct servent *sp;
511d41bcacSpendry struct in_addr **ipp;
521d41bcacSpendry struct in_addr *ip[2];
531d41bcacSpendry struct in_addr ina;
541d41bcacSpendry int s_port;
552db74a21Spendry int priv = 0;
561d41bcacSpendry struct sockaddr_in sain;
57459c89dcSpendry
58459c89dcSpendry q = strchr(p, '/');
59459c89dcSpendry if (q == 0 || q - p >= sizeof(host))
60459c89dcSpendry return (EINVAL);
61459c89dcSpendry *q = '\0';
62459c89dcSpendry strcpy(host, p);
632db74a21Spendry p = q + 1;
64459c89dcSpendry
65459c89dcSpendry q = strchr(p, '/');
662db74a21Spendry if (q)
67459c89dcSpendry *q = '\0';
682db74a21Spendry if (strlen(p) >= sizeof(port))
692db74a21Spendry return (EINVAL);
70459c89dcSpendry strcpy(port, p);
712db74a21Spendry if (q) {
722db74a21Spendry p = q + 1;
732db74a21Spendry if (strcmp(p, "priv") == 0) {
742db74a21Spendry if (pcr->pcr_uid == 0)
752db74a21Spendry priv = 1;
762db74a21Spendry else
772db74a21Spendry return (EPERM);
782db74a21Spendry } else {
792db74a21Spendry return (EINVAL);
802db74a21Spendry }
812db74a21Spendry }
82459c89dcSpendry
831d41bcacSpendry hp = gethostbyname(host);
841d41bcacSpendry if (hp != 0) {
851d41bcacSpendry ipp = (struct in_addr **) hp->h_addr_list;
861d41bcacSpendry } else {
871d41bcacSpendry ina.s_addr = inet_addr(host);
881d41bcacSpendry if (ina.s_addr == INADDR_NONE)
891d41bcacSpendry return (EINVAL);
901d41bcacSpendry ip[0] = &ina;
911d41bcacSpendry ip[1] = 0;
921d41bcacSpendry ipp = ip;
931d41bcacSpendry }
941d41bcacSpendry
951d41bcacSpendry sp = getservbyname(port, "tcp");
961d41bcacSpendry if (sp != 0)
971d41bcacSpendry s_port = sp->s_port;
981d41bcacSpendry else {
99c8070d05Spendry s_port = strtoul(port, &p, 0);
100c8070d05Spendry if (s_port == 0 || *p != '\0')
1011d41bcacSpendry return (EINVAL);
102c8070d05Spendry s_port = htons(s_port);
1031d41bcacSpendry }
1041d41bcacSpendry
105*e2bbe8e2Sbostic memset(&sain, 0, sizeof(sain));
1061d41bcacSpendry sain.sin_len = sizeof(sain);
1071d41bcacSpendry sain.sin_family = AF_INET;
1081d41bcacSpendry sain.sin_port = s_port;
1091d41bcacSpendry
1101d41bcacSpendry while (ipp[0]) {
1111d41bcacSpendry int so;
1121d41bcacSpendry
1132db74a21Spendry if (priv)
1142db74a21Spendry so = rresvport((int *) 0);
1152db74a21Spendry else
1161d41bcacSpendry so = socket(AF_INET, SOCK_STREAM, 0);
1171d41bcacSpendry if (so < 0) {
1181d41bcacSpendry syslog(LOG_ERR, "socket: %m");
1191d41bcacSpendry return (errno);
1201d41bcacSpendry }
1211d41bcacSpendry
1221d41bcacSpendry sain.sin_addr = *ipp[0];
1231d41bcacSpendry if (connect(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) {
1241d41bcacSpendry *fdp = so;
1251d41bcacSpendry return (0);
1261d41bcacSpendry }
1271d41bcacSpendry (void) close(so);
1281d41bcacSpendry
1291d41bcacSpendry ipp++;
1301d41bcacSpendry }
1311d41bcacSpendry
1321d41bcacSpendry return (errno);
13355f8326cSpendry }
134