xref: /original-bsd/sbin/mount_portal/pt_tcp.c (revision 333da485)
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  * %sccs.include.redist.c%
10  *
11  *	@(#)pt_tcp.c	8.2 (Berkeley) 01/14/94
12  *
13  * $Id: pt_tcp.c,v 1.1 1992/05/25 21:43:09 jsp Exp jsp $
14  */
15 
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <errno.h>
20 #include <strings.h>
21 #include <sys/types.h>
22 #include <sys/param.h>
23 #include <sys/syslog.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <netdb.h>
27 
28 #include "portald.h"
29 
30 /*
31  * Key will be tcp/host/port[/"priv"]
32  * Create a TCP socket connected to the
33  * requested host and port.
34  * Some trailing suffix values have special meanings.
35  * An unrecognised suffix is an error.
36  */
37 int portal_tcp(pcr, key, v, kso, fdp)
38 struct portal_cred *pcr;
39 char *key;
40 char **v;
41 int kso;
42 int *fdp;
43 {
44 	char host[MAXHOSTNAMELEN];
45 	char port[MAXHOSTNAMELEN];
46 	char *p = key + (v[1] ? strlen(v[1]) : 0);
47 	char *q;
48 	struct hostent *hp;
49 	struct servent *sp;
50 	struct in_addr **ipp;
51 	struct in_addr *ip[2];
52 	struct in_addr ina;
53 	int s_port;
54 	int priv = 0;
55 	struct sockaddr_in sain;
56 
57 	q = strchr(p, '/');
58 	if (q == 0 || q - p >= sizeof(host))
59 		return (EINVAL);
60 	*q = '\0';
61 	strcpy(host, p);
62 	p = q + 1;
63 
64 	q = strchr(p, '/');
65 	if (q)
66 		*q = '\0';
67 	if (strlen(p) >= sizeof(port))
68 		return (EINVAL);
69 	strcpy(port, p);
70 	if (q) {
71 		p = q + 1;
72 		if (strcmp(p, "priv") == 0) {
73 			if (pcr->pcr_uid == 0)
74 				priv = 1;
75 			else
76 				return (EPERM);
77 		} else {
78 			return (EINVAL);
79 		}
80 	}
81 
82 	hp = gethostbyname(host);
83 	if (hp != 0) {
84 		ipp = (struct in_addr **) hp->h_addr_list;
85 	} else {
86 		ina.s_addr = inet_addr(host);
87 		if (ina.s_addr == INADDR_NONE)
88 			return (EINVAL);
89 		ip[0] = &ina;
90 		ip[1] = 0;
91 		ipp = ip;
92 	}
93 
94 	sp = getservbyname(port, "tcp");
95 	if (sp != 0)
96 		s_port = sp->s_port;
97 	else {
98 		s_port = atoi(port);
99 		if (s_port == 0)
100 			return (EINVAL);
101 	}
102 
103 	bzero(&sain, sizeof(sain));
104 	sain.sin_len = sizeof(sain);
105 	sain.sin_family = AF_INET;
106 	sain.sin_port = s_port;
107 
108 	while (ipp[0]) {
109 		int so;
110 
111 		if (priv)
112 			so = rresvport((int *) 0);
113 		else
114 			so = socket(AF_INET, SOCK_STREAM, 0);
115 		if (so < 0) {
116 			syslog(LOG_ERR, "socket: %m");
117 			return (errno);
118 		}
119 
120 		sain.sin_addr = *ipp[0];
121 		if (connect(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) {
122 			*fdp = so;
123 			return (0);
124 		}
125 		(void) close(so);
126 
127 		ipp++;
128 	}
129 
130 	return (errno);
131 }
132