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