xref: /original-bsd/sbin/mount_portal/pt_tcp.c (revision e2bbe8e2)
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