xref: /openbsd/lib/libc/rpc/clnt_udp_bufcreate.c (revision 903e91b4)
1 /*	$OpenBSD: clnt_udp_bufcreate.c,v 1.1 2024/01/22 16:18:06 deraadt Exp $ */
2 
3 /*
4  * Copyright (c) 2010, Oracle America, Inc.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above
13  *       copyright notice, this list of conditions and the following
14  *       disclaimer in the documentation and/or other materials
15  *       provided with the distribution.
16  *     * Neither the name of the "Oracle America, Inc." nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  * clnt_udp.c, Implements a UDP/IP based, client side RPC.
36  */
37 
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42 #include <fcntl.h>
43 #include <rpc/rpc.h>
44 #include <sys/socket.h>
45 #include <netdb.h>
46 #include <errno.h>
47 #include <rpc/pmap_clnt.h>
48 #include "clnt_udp.h"
49 
50 /*
51  * Create a UDP based client handle.
52  * If *sockp<0, *sockp is set to a newly created UPD socket.
53  * If raddr->sin_port is 0 a binder on the remote machine
54  * is consulted for the correct port number.
55  * NB: It is the client's responsibility to close *sockp, unless
56  *	clntudp_bufcreate() was called with *sockp = -1 (so it created
57  *	the socket), and CLNT_DESTROY() is used.
58  * NB: The rpch->cl_auth is initialized to null authentication.
59  *     Caller may wish to set this something more useful.
60  *
61  * wait is the amount of time used between retransmitting a call if
62  * no response has been heard;  retransmission occurs until the actual
63  * rpc call times out.
64  *
65  * sendsz and recvsz are the maximum allowable packet sizes that can be
66  * sent and received.
67  */
68 
69 CLIENT *
clntudp_bufcreate(struct sockaddr_in * raddr,u_long program,u_long version,struct timeval wait,int * sockp,u_int sendsz,u_int recvsz)70 clntudp_bufcreate(struct sockaddr_in *raddr, u_long program, u_long version,
71     struct timeval wait, int *sockp, u_int sendsz, u_int recvsz)
72 {
73 	struct clntudp_bufcreate_args args;
74 
75 	args.raddr = raddr;
76 	args.program = program;
77 	args.version = version;
78 	args.wait = wait;
79 	args.sockp = sockp;
80 	args.sendsz = sendsz;
81 	args.recvsz = recvsz;
82 
83 	if (clntudp_bufcreate1(&args) == -1)
84 		goto fooy;
85 
86 	if (raddr->sin_port == 0) {
87 		u_short port;
88 		if ((port =
89 		    pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) {
90 			goto fooy;
91 		}
92 		raddr->sin_port = htons(port);
93 	}
94 	args.cu->cu_raddr = *raddr;
95 	if (*sockp < 0) {
96 		*sockp = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK,
97 		    IPPROTO_UDP);
98 		if (*sockp == -1) {
99 			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
100 			rpc_createerr.cf_error.re_errno = errno;
101 			goto fooy;
102 		}
103 		/* attempt to bind to priv port */
104 		(void)bindresvport(*sockp, NULL);
105 		args.cu->cu_closeit = TRUE;
106 	}
107 	args.cu->cu_sock = *args.sockp;
108 
109 	if (clntudp_bufcreate2(&args) == -1)
110 		goto fooy;
111 	return (args.cl);
112 fooy:
113 	if (args.cu)
114 		mem_free((caddr_t)args.cu,
115 		    sizeof(*args.cu) + args.sendsz + args.recvsz);
116 	if (args.cl)
117 		mem_free((caddr_t)args.cl, sizeof(CLIENT));
118 	return (NULL);
119 }
120 DEF_WEAK(clntudp_bufcreate);
121 
122 CLIENT *
clntudp_create(struct sockaddr_in * raddr,u_long program,u_long version,struct timeval wait,int * sockp)123 clntudp_create(struct sockaddr_in *raddr, u_long program, u_long version,
124     struct timeval wait, int *sockp)
125 {
126 
127 	return(clntudp_bufcreate(raddr, program, version, wait, sockp,
128 	    UDPMSGSIZE, UDPMSGSIZE));
129 }
130 DEF_WEAK(clntudp_create);
131