xref: /original-bsd/sbin/mount_portal/pt_tcp.c (revision 4092c5cc)
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.1 (Berkeley) 06/05/93
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 	struct sockaddr_in sain;
55 
56 	q = strchr(p, '/');
57 	if (q == 0 || q - p >= sizeof(host))
58 		return (EINVAL);
59 	*q = '\0';
60 	strcpy(host, p);
61 	p = q++;
62 
63 	q = strchr(p, '/');
64 	if (q == 0 || q - p >= sizeof(port))
65 		return (EINVAL);
66 	*q = '\0';
67 	strcpy(port, p);
68 	p = q++;
69 
70 	hp = gethostbyname(host);
71 	if (hp != 0) {
72 		ipp = (struct in_addr **) hp->h_addr_list;
73 	} else {
74 		ina.s_addr = inet_addr(host);
75 		if (ina.s_addr == INADDR_NONE)
76 			return (EINVAL);
77 		ip[0] = &ina;
78 		ip[1] = 0;
79 		ipp = ip;
80 	}
81 
82 	sp = getservbyname(port, "tcp");
83 	if (sp != 0)
84 		s_port = sp->s_port;
85 	else {
86 		s_port = atoi(port);
87 		if (s_port == 0)
88 			return (EINVAL);
89 	}
90 
91 	bzero(&sain, sizeof(sain));
92 	sain.sin_len = sizeof(sain);
93 	sain.sin_family = AF_INET;
94 	sain.sin_port = s_port;
95 
96 	while (ipp[0]) {
97 		int so;
98 
99 		so = socket(AF_INET, SOCK_STREAM, 0);
100 		if (so < 0) {
101 			syslog(LOG_ERR, "socket: %m");
102 			return (errno);
103 		}
104 
105 		sain.sin_addr = *ipp[0];
106 		if (connect(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) {
107 			*fdp = so;
108 			return (0);
109 		}
110 		(void) close(so);
111 
112 		ipp++;
113 	}
114 
115 	return (errno);
116 }
117