xref: /openbsd/lib/libc/rpc/clnt_generic.c (revision cb7760d1)
1*cb7760d1Smillert /*	$OpenBSD: clnt_generic.c,v 1.7 2010/09/01 14:43:34 millert Exp $ */
2df930be7Sderaadt 
3df930be7Sderaadt /*
4*cb7760d1Smillert  * Copyright (c) 2010, Oracle America, Inc.
5*cb7760d1Smillert  *
6*cb7760d1Smillert  * Redistribution and use in source and binary forms, with or without
7*cb7760d1Smillert  * modification, are permitted provided that the following conditions are
8*cb7760d1Smillert  * met:
9*cb7760d1Smillert  *
10*cb7760d1Smillert  *     * Redistributions of source code must retain the above copyright
11*cb7760d1Smillert  *       notice, this list of conditions and the following disclaimer.
12*cb7760d1Smillert  *     * Redistributions in binary form must reproduce the above
13*cb7760d1Smillert  *       copyright notice, this list of conditions and the following
14*cb7760d1Smillert  *       disclaimer in the documentation and/or other materials
15*cb7760d1Smillert  *       provided with the distribution.
16*cb7760d1Smillert  *     * Neither the name of the "Oracle America, Inc." nor the names of its
17*cb7760d1Smillert  *       contributors may be used to endorse or promote products derived
18*cb7760d1Smillert  *       from this software without specific prior written permission.
19*cb7760d1Smillert  *
20*cb7760d1Smillert  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*cb7760d1Smillert  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*cb7760d1Smillert  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*cb7760d1Smillert  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24*cb7760d1Smillert  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25*cb7760d1Smillert  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26*cb7760d1Smillert  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27*cb7760d1Smillert  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28*cb7760d1Smillert  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29*cb7760d1Smillert  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30*cb7760d1Smillert  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31*cb7760d1Smillert  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32df930be7Sderaadt  */
33*cb7760d1Smillert 
34ae5feee3Smillert #include <errno.h>
35df930be7Sderaadt #include <string.h>
36df930be7Sderaadt #include <rpc/rpc.h>
37df930be7Sderaadt #include <sys/socket.h>
38df930be7Sderaadt #include <netdb.h>
39df930be7Sderaadt 
40df930be7Sderaadt /*
41df930be7Sderaadt  * Generic client creation: takes (hostname, program-number, protocol) and
42df930be7Sderaadt  * returns client handle. Default options are set, which the user can
43df930be7Sderaadt  * change using the rpc equivalent of ioctl()'s.
44df930be7Sderaadt  */
45df930be7Sderaadt CLIENT *
clnt_create(char * hostname,u_long prog,u_long vers,char * proto)46384ec30aSotto clnt_create(char *hostname, u_long prog, u_long vers, char *proto)
47df930be7Sderaadt {
48df930be7Sderaadt 	struct hostent *h;
49df930be7Sderaadt 	struct protoent *p;
50df930be7Sderaadt 	struct sockaddr_in sin;
51df930be7Sderaadt 	int sock;
52df930be7Sderaadt 	struct timeval tv;
53df930be7Sderaadt 	CLIENT *client;
54df930be7Sderaadt 
55df930be7Sderaadt 	h = gethostbyname(hostname);
56df930be7Sderaadt 	if (h == NULL) {
57df930be7Sderaadt 		rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
58df930be7Sderaadt 		return (NULL);
59df930be7Sderaadt 	}
60df930be7Sderaadt 	if (h->h_addrtype != AF_INET) {
61df930be7Sderaadt 		/*
62df930be7Sderaadt 		 * Only support INET for now
63df930be7Sderaadt 		 */
64df930be7Sderaadt 		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
65df930be7Sderaadt 		rpc_createerr.cf_error.re_errno = EAFNOSUPPORT;
66df930be7Sderaadt 		return (NULL);
67df930be7Sderaadt 	}
68df930be7Sderaadt 	memset(&sin, 0, sizeof(sin));
69df930be7Sderaadt 	sin.sin_len = sizeof(struct sockaddr_in);
70df930be7Sderaadt 	sin.sin_family = h->h_addrtype;
71df930be7Sderaadt 	sin.sin_port = 0;
7273b69cd9Sderaadt 	memcpy((char*)&sin.sin_addr, h->h_addr, h->h_length);
73df930be7Sderaadt 	p = getprotobyname(proto);
74df930be7Sderaadt 	if (p == NULL) {
75df930be7Sderaadt 		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
76df930be7Sderaadt 		rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
77df930be7Sderaadt 		return (NULL);
78df930be7Sderaadt 	}
79df930be7Sderaadt 	sock = RPC_ANYSOCK;
80df930be7Sderaadt 	switch (p->p_proto) {
81df930be7Sderaadt 	case IPPROTO_UDP:
82df930be7Sderaadt 		tv.tv_sec = 5;
83df930be7Sderaadt 		tv.tv_usec = 0;
84df930be7Sderaadt 		client = clntudp_create(&sin, prog, vers, tv, &sock);
85df930be7Sderaadt 		if (client == NULL) {
86df930be7Sderaadt 			return (NULL);
87df930be7Sderaadt 		}
88df930be7Sderaadt 		break;
89df930be7Sderaadt 	case IPPROTO_TCP:
90df930be7Sderaadt 		client = clnttcp_create(&sin, prog, vers, &sock, 0, 0);
91df930be7Sderaadt 		if (client == NULL) {
92df930be7Sderaadt 			return (NULL);
93df930be7Sderaadt 		}
94df930be7Sderaadt 		break;
95df930be7Sderaadt 	default:
96df930be7Sderaadt 		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
97df930be7Sderaadt 		rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
98df930be7Sderaadt 		return (NULL);
99df930be7Sderaadt 	}
100df930be7Sderaadt 	return (client);
101df930be7Sderaadt }
102