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