]> sourceware.org Git - glibc.git/blame - sunrpc/svc_udp.c
LoongArch: Add cfi instructions for _dl_tlsdesc_dynamic
[glibc.git] / sunrpc / svc_udp.c
CommitLineData
28f540f4
RM
1/*
2 * svc_udp.c,
3 * Server side for UDP/IP based RPC. (Does some caching in the hopes of
4 * achieving execute-at-most-once semantics.)
5 *
dff8da6b 6 * Copyright (C) 2012-2024 Free Software Foundation, Inc.
14bc93a9
JL
7 * This file is part of the GNU C Library.
8 *
9 * The GNU C Library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * The GNU C Library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with the GNU C Library; if not, see
5a82c748 21 * <https://www.gnu.org/licenses/>.
14bc93a9 22 *
a7ab6ec8
UD
23 * Copyright (c) 2010, Oracle America, Inc.
24 *
25 * Redistribution and use in source and binary forms, with or without
26 * modification, are permitted provided that the following conditions are
27 * met:
28 *
29 * * Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * * Redistributions in binary form must reproduce the above
32 * copyright notice, this list of conditions and the following
33 * disclaimer in the documentation and/or other materials
34 * provided with the distribution.
35 * * Neither the name of the "Oracle America, Inc." nor the names of its
36 * contributors may be used to endorse or promote products derived
37 * from this software without specific prior written permission.
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
40 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
41 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
42 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
43 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
44 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
46 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
47 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
48 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
49 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28f540f4
RM
51 */
52
53#include <stdio.h>
e7fd8a39
UD
54#include <unistd.h>
55#include <string.h>
28f540f4
RM
56#include <rpc/rpc.h>
57#include <sys/socket.h>
58#include <errno.h>
4360eafd 59#include <libintl.h>
28f540f4 60
3fd759d1
UD
61#ifdef IP_PKTINFO
62#include <sys/uio.h>
63#endif
64
3ce1f295
UD
65#include <wchar.h>
66#include <libio/iolibio.h>
82f43dd2 67#include <shlib-compat.h>
28f540f4
RM
68
69#define rpc_buffer(xprt) ((xprt)->xp_p1)
1f64ac13 70#ifndef MAX
e7fd8a39 71#define MAX(a, b) ((a > b) ? a : b)
1f64ac13 72#endif
28f540f4 73
e7fd8a39
UD
74static bool_t svcudp_recv (SVCXPRT *, struct rpc_msg *);
75static bool_t svcudp_reply (SVCXPRT *, struct rpc_msg *);
76static enum xprt_stat svcudp_stat (SVCXPRT *);
77static bool_t svcudp_getargs (SVCXPRT *, xdrproc_t, caddr_t);
78static bool_t svcudp_freeargs (SVCXPRT *, xdrproc_t, caddr_t);
79static void svcudp_destroy (SVCXPRT *);
80
81static const struct xp_ops svcudp_op =
82{
83 svcudp_recv,
84 svcudp_stat,
85 svcudp_getargs,
86 svcudp_reply,
87 svcudp_freeargs,
88 svcudp_destroy
28f540f4
RM
89};
90
e7fd8a39
UD
91static int cache_get (SVCXPRT *, struct rpc_msg *, char **replyp,
92 u_long *replylenp);
93static void cache_set (SVCXPRT *xprt, u_long replylen);
28f540f4
RM
94
95/*
96 * kept in xprt->xp_p2
97 */
e7fd8a39
UD
98struct svcudp_data
99 {
100 u_int su_iosz; /* byte size of send.recv buffer */
101 u_long su_xid; /* transaction id */
102 XDR su_xdrs; /* XDR handle */
103 char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */
104 char *su_cache; /* cached data, NULL if no cache */
105 };
28f540f4
RM
106#define su_data(xprt) ((struct svcudp_data *)(xprt->xp_p2))
107
108/*
109 * Usage:
e7fd8a39 110 * xprt = svcudp_create(sock);
28f540f4
RM
111 *
112 * If sock<0 then a socket is created, else sock is used.
113 * If the socket, sock is not bound to a port then svcudp_create
114 * binds it to an arbitrary port. In any (successful) case,
115 * xprt->xp_sock is the registered socket number and xprt->xp_port is the
116 * associated port number.
117 * Once *xprt is initialized, it is registered as a transporter;
118 * see (svc.h, xprt_register).
119 * The routines returns NULL if a problem occurred.
120 */
121SVCXPRT *
41075ae3 122svcudp_bufcreate (int sock, u_int sendsz, u_int recvsz)
28f540f4 123{
e7fd8a39
UD
124 bool_t madesock = FALSE;
125 SVCXPRT *xprt;
126 struct svcudp_data *su;
127 struct sockaddr_in addr;
70b0abba 128 socklen_t len = sizeof (struct sockaddr_in);
51028f34
UD
129 int pad;
130 void *buf;
e7fd8a39
UD
131
132 if (sock == RPC_ANYSOCK)
133 {
50304ef0 134 if ((sock = __socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
e7fd8a39
UD
135 {
136 perror (_("svcudp_create: socket creation problem"));
137 return (SVCXPRT *) NULL;
28f540f4 138 }
e7fd8a39
UD
139 madesock = TRUE;
140 }
d99431e5 141 memset ((char *) &addr, 0, sizeof (addr));
e7fd8a39 142 addr.sin_family = AF_INET;
a585ba22 143 if (bindresvport (sock, &addr))
e7fd8a39
UD
144 {
145 addr.sin_port = 0;
b2bffca2 146 (void) __bind (sock, (struct sockaddr *) &addr, len);
e7fd8a39 147 }
b2bffca2 148 if (__getsockname (sock, (struct sockaddr *) &addr, &len) != 0)
e7fd8a39
UD
149 {
150 perror (_("svcudp_create - cannot getsockname"));
151 if (madesock)
50304ef0 152 (void) __close (sock);
e7fd8a39
UD
153 return (SVCXPRT *) NULL;
154 }
155 xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
e7fd8a39 156 su = (struct svcudp_data *) mem_alloc (sizeof (*su));
51028f34
UD
157 buf = mem_alloc (((MAX (sendsz, recvsz) + 3) / 4) * 4);
158 if (xprt == NULL || su == NULL || buf == NULL)
e7fd8a39 159 {
1d20f7f8
UD
160 (void) __fxprintf (NULL, "%s: %s",
161 "svcudp_create", _("out of memory\n"));
2e3e5db6
UD
162 mem_free (xprt, sizeof (SVCXPRT));
163 mem_free (su, sizeof (*su));
164 mem_free (buf, ((MAX (sendsz, recvsz) + 3) / 4) * 4);
e7fd8a39
UD
165 return NULL;
166 }
167 su->su_iosz = ((MAX (sendsz, recvsz) + 3) / 4) * 4;
51028f34 168 rpc_buffer (xprt) = buf;
7b57bfe5 169 xdrmem_create (&(su->su_xdrs), rpc_buffer (xprt), su->su_iosz, XDR_DECODE);
e7fd8a39
UD
170 su->su_cache = NULL;
171 xprt->xp_p2 = (caddr_t) su;
172 xprt->xp_verf.oa_base = su->su_verfbody;
173 xprt->xp_ops = &svcudp_op;
174 xprt->xp_port = ntohs (addr.sin_port);
175 xprt->xp_sock = sock;
3fd759d1
UD
176
177#ifdef IP_PKTINFO
178 if ((sizeof (struct iovec) + sizeof (struct msghdr)
179 + sizeof(struct cmsghdr) + sizeof (struct in_pktinfo))
180 > sizeof (xprt->xp_pad))
181 {
8a259a23 182 (void) __fxprintf (NULL,"%s", _("\
df6f8969 183svcudp_create: xp_pad is too small for IP_PKTINFO\n"));
3fd759d1
UD
184 return NULL;
185 }
186 pad = 1;
b2bffca2
UD
187 if (__setsockopt (sock, SOL_IP, IP_PKTINFO, (void *) &pad,
188 sizeof (pad)) == 0)
3fd759d1
UD
189 /* Set the padding to all 1s. */
190 pad = 0xff;
191 else
192#endif
193 /* Clear the padding. */
194 pad = 0;
195 memset (&xprt->xp_pad [0], pad, sizeof (xprt->xp_pad));
196
e7fd8a39
UD
197 xprt_register (xprt);
198 return xprt;
28f540f4 199}
7b57bfe5
UD
200#ifdef EXPORT_RPC_SYMBOLS
201libc_hidden_def (svcudp_bufcreate)
202#else
021db4be 203libc_hidden_nolink_sunrpc (svcudp_bufcreate, GLIBC_2_0)
7b57bfe5 204#endif
28f540f4
RM
205
206SVCXPRT *
9d46370c 207svcudp_create (int sock)
28f540f4 208{
7b57bfe5 209 return svcudp_bufcreate (sock, UDPMSGSIZE, UDPMSGSIZE);
28f540f4 210}
4df46dbd
L
211#ifdef EXPORT_RPC_SYMBOLS
212libc_hidden_def (svcudp_create)
213#else
021db4be 214libc_hidden_nolink_sunrpc (svcudp_create, GLIBC_2_0)
4df46dbd 215#endif
28f540f4
RM
216
217static enum xprt_stat
9d46370c 218svcudp_stat (SVCXPRT *xprt)
28f540f4
RM
219{
220
e7fd8a39 221 return XPRT_IDLE;
28f540f4
RM
222}
223
224static bool_t
9d46370c 225svcudp_recv (SVCXPRT *xprt, struct rpc_msg *msg)
28f540f4 226{
e7fd8a39
UD
227 struct svcudp_data *su = su_data (xprt);
228 XDR *xdrs = &(su->su_xdrs);
229 int rlen;
230 char *reply;
231 u_long replylen;
70b0abba 232 socklen_t len;
e7fd8a39 233
3fd759d1
UD
234 /* It is very tricky when you have IP aliases. We want to make sure
235 that we are sending the packet from the IP address where the
236 incoming packet is addressed to. H.J. */
237#ifdef IP_PKTINFO
238 struct iovec *iovp;
239 struct msghdr *mesgp;
240#endif
241
e7fd8a39 242again:
f671aeab 243 /* FIXME -- should xp_addrlen be a size_t? */
70b0abba 244 len = (socklen_t) sizeof(struct sockaddr_in);
3fd759d1
UD
245#ifdef IP_PKTINFO
246 iovp = (struct iovec *) &xprt->xp_pad [0];
247 mesgp = (struct msghdr *) &xprt->xp_pad [sizeof (struct iovec)];
248 if (mesgp->msg_iovlen)
249 {
250 iovp->iov_base = rpc_buffer (xprt);
251 iovp->iov_len = su->su_iosz;
252 mesgp->msg_iov = iovp;
253 mesgp->msg_iovlen = 1;
254 mesgp->msg_name = &(xprt->xp_raddr);
255 mesgp->msg_namelen = len;
256 mesgp->msg_control = &xprt->xp_pad [sizeof (struct iovec)
257 + sizeof (struct msghdr)];
172b90bb
UD
258 mesgp->msg_controllen = sizeof(xprt->xp_pad)
259 - sizeof (struct iovec) - sizeof (struct msghdr);
b2bffca2 260 rlen = __recvmsg (xprt->xp_sock, mesgp, 0);
3fd759d1 261 if (rlen >= 0)
d148ed25
UD
262 {
263 struct cmsghdr *cmsg;
264 len = mesgp->msg_namelen;
265 cmsg = CMSG_FIRSTHDR (mesgp);
266 if (cmsg == NULL
267 || CMSG_NXTHDR (mesgp, cmsg) != NULL
268 || cmsg->cmsg_level != SOL_IP
269 || cmsg->cmsg_type != IP_PKTINFO
270 || cmsg->cmsg_len < (sizeof (struct cmsghdr)
271 + sizeof (struct in_pktinfo)))
272 {
273 /* Not a simple IP_PKTINFO, ignore it. */
274 mesgp->msg_control = NULL;
275 mesgp->msg_controllen = 0;
276 }
277 else
278 {
279 /* It was a simple IP_PKTIFO as we expected, discard the
280 interface field. */
63c9fb5c 281 struct in_pktinfo *pkti = (struct in_pktinfo *) CMSG_DATA (cmsg);
d148ed25
UD
282 pkti->ipi_ifindex = 0;
283 }
284 }
3fd759d1
UD
285 }
286 else
287#endif
b2bffca2
UD
288 rlen = __recvfrom (xprt->xp_sock, rpc_buffer (xprt),
289 (int) su->su_iosz, 0,
290 (struct sockaddr *) &(xprt->xp_raddr), &len);
f671aeab 291 xprt->xp_addrlen = len;
14bc93a9
JL
292 if (rlen == -1)
293 {
294 if (errno == EINTR)
295 goto again;
296 __svc_accept_failed ();
297 }
e7fd8a39
UD
298 if (rlen < 16) /* < 4 32-bit ints? */
299 return FALSE;
300 xdrs->x_op = XDR_DECODE;
301 XDR_SETPOS (xdrs, 0);
7b57bfe5 302 if (!xdr_callmsg (xdrs, msg))
e7fd8a39
UD
303 return FALSE;
304 su->su_xid = msg->rm_xid;
305 if (su->su_cache != NULL)
306 {
307 if (cache_get (xprt, msg, &reply, &replylen))
308 {
3fd759d1
UD
309#ifdef IP_PKTINFO
310 if (mesgp->msg_iovlen)
311 {
312 iovp->iov_base = reply;
313 iovp->iov_len = replylen;
b2bffca2 314 (void) __sendmsg (xprt->xp_sock, mesgp, 0);
3fd759d1
UD
315 }
316 else
317#endif
b2bffca2
UD
318 (void) __sendto (xprt->xp_sock, reply, (int) replylen, 0,
319 (struct sockaddr *) &xprt->xp_raddr, len);
e7fd8a39 320 return TRUE;
28f540f4 321 }
e7fd8a39
UD
322 }
323 return TRUE;
28f540f4
RM
324}
325
326static bool_t
9d46370c 327svcudp_reply (SVCXPRT *xprt, struct rpc_msg *msg)
28f540f4 328{
e7fd8a39
UD
329 struct svcudp_data *su = su_data (xprt);
330 XDR *xdrs = &(su->su_xdrs);
3fd759d1 331 int slen, sent;
e7fd8a39 332 bool_t stat = FALSE;
3fd759d1
UD
333#ifdef IP_PKTINFO
334 struct iovec *iovp;
335 struct msghdr *mesgp;
336#endif
e7fd8a39
UD
337
338 xdrs->x_op = XDR_ENCODE;
339 XDR_SETPOS (xdrs, 0);
340 msg->rm_xid = su->su_xid;
7b57bfe5 341 if (xdr_replymsg (xdrs, msg))
e7fd8a39
UD
342 {
343 slen = (int) XDR_GETPOS (xdrs);
3fd759d1
UD
344#ifdef IP_PKTINFO
345 mesgp = (struct msghdr *) &xprt->xp_pad [sizeof (struct iovec)];
346 if (mesgp->msg_iovlen)
347 {
348 iovp = (struct iovec *) &xprt->xp_pad [0];
349 iovp->iov_base = rpc_buffer (xprt);
350 iovp->iov_len = slen;
b2bffca2 351 sent = __sendmsg (xprt->xp_sock, mesgp, 0);
3fd759d1
UD
352 }
353 else
354#endif
b2bffca2
UD
355 sent = __sendto (xprt->xp_sock, rpc_buffer (xprt), slen, 0,
356 (struct sockaddr *) &(xprt->xp_raddr),
357 xprt->xp_addrlen);
3fd759d1 358 if (sent == slen)
e7fd8a39
UD
359 {
360 stat = TRUE;
361 if (su->su_cache && slen >= 0)
362 {
363 cache_set (xprt, (u_long) slen);
364 }
28f540f4 365 }
e7fd8a39
UD
366 }
367 return stat;
28f540f4
RM
368}
369
370static bool_t
9d46370c 371svcudp_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
28f540f4
RM
372{
373
e7fd8a39 374 return (*xdr_args) (&(su_data (xprt)->su_xdrs), args_ptr);
28f540f4
RM
375}
376
377static bool_t
9d46370c 378svcudp_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
28f540f4 379{
e7fd8a39 380 XDR *xdrs = &(su_data (xprt)->su_xdrs);
28f540f4 381
e7fd8a39
UD
382 xdrs->x_op = XDR_FREE;
383 return (*xdr_args) (xdrs, args_ptr);
28f540f4
RM
384}
385
386static void
9d46370c 387svcudp_destroy (SVCXPRT *xprt)
28f540f4 388{
e7fd8a39
UD
389 struct svcudp_data *su = su_data (xprt);
390
391 xprt_unregister (xprt);
50304ef0 392 (void) __close (xprt->xp_sock);
e7fd8a39
UD
393 XDR_DESTROY (&(su->su_xdrs));
394 mem_free (rpc_buffer (xprt), su->su_iosz);
395 mem_free ((caddr_t) su, sizeof (struct svcudp_data));
396 mem_free ((caddr_t) xprt, sizeof (SVCXPRT));
28f540f4
RM
397}
398
399
400/***********this could be a separate file*********************/
401
402/*
403 * Fifo cache for udp server
404 * Copies pointers to reply buffers into fifo cache
405 * Buffers are sent again if retransmissions are detected.
406 */
407
e7fd8a39 408#define SPARSENESS 4 /* 75% sparse */
28f540f4 409
df6f8969 410#define CACHE_PERROR(msg) \
8a259a23 411 (void) __fxprintf(NULL, "%s\n", msg)
28f540f4
RM
412
413#define ALLOC(type, size) \
414 (type *) mem_alloc((unsigned) (sizeof(type) * (size)))
415
cdb9c321
UD
416#define CALLOC(type, size) \
417 (type *) calloc (sizeof (type), size)
28f540f4
RM
418
419/*
420 * An entry in the cache
421 */
422typedef struct cache_node *cache_ptr;
e7fd8a39
UD
423struct cache_node
424 {
425 /*
426 * Index into cache is xid, proc, vers, prog and address
427 */
428 u_long cache_xid;
429 u_long cache_proc;
430 u_long cache_vers;
431 u_long cache_prog;
432 struct sockaddr_in cache_addr;
433 /*
434 * The cached reply and length
435 */
436 char *cache_reply;
437 u_long cache_replylen;
438 /*
439 * Next node on the list, if there is a collision
440 */
441 cache_ptr cache_next;
442 };
28f540f4
RM
443
444
445
446/*
447 * The entire cache
448 */
e7fd8a39
UD
449struct udp_cache
450 {
451 u_long uc_size; /* size of cache */
452 cache_ptr *uc_entries; /* hash table of entries in cache */
453 cache_ptr *uc_fifo; /* fifo list of entries in cache */
454 u_long uc_nextvictim; /* points to next victim in fifo list */
455 u_long uc_prog; /* saved program number */
456 u_long uc_vers; /* saved version number */
457 u_long uc_proc; /* saved procedure number */
458 struct sockaddr_in uc_addr; /* saved caller's address */
459 };
28f540f4
RM
460
461
462/*
463 * the hashing function
464 */
465#define CACHE_LOC(transp, xid) \
cbd3dceb 466 (xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size))
28f540f4
RM
467
468
469/*
cbd3dceb 470 * Enable use of the cache.
28f540f4
RM
471 * Note: there is no disable.
472 */
e7fd8a39
UD
473int
474svcudp_enablecache (SVCXPRT *transp, u_long size)
28f540f4 475{
e7fd8a39
UD
476 struct svcudp_data *su = su_data (transp);
477 struct udp_cache *uc;
478
479 if (su->su_cache != NULL)
480 {
481 CACHE_PERROR (_("enablecache: cache already enabled"));
482 return 0;
483 }
484 uc = ALLOC (struct udp_cache, 1);
485 if (uc == NULL)
486 {
487 CACHE_PERROR (_("enablecache: could not allocate cache"));
488 return 0;
489 }
490 uc->uc_size = size;
491 uc->uc_nextvictim = 0;
cdb9c321 492 uc->uc_entries = CALLOC (cache_ptr, size * SPARSENESS);
e7fd8a39
UD
493 if (uc->uc_entries == NULL)
494 {
0292b0dd 495 mem_free (uc, sizeof (struct udp_cache));
e7fd8a39
UD
496 CACHE_PERROR (_("enablecache: could not allocate cache data"));
497 return 0;
498 }
cdb9c321 499 uc->uc_fifo = CALLOC (cache_ptr, size);
e7fd8a39
UD
500 if (uc->uc_fifo == NULL)
501 {
0292b0dd
UD
502 mem_free (uc->uc_entries, size * SPARSENESS);
503 mem_free (uc, sizeof (struct udp_cache));
e7fd8a39
UD
504 CACHE_PERROR (_("enablecache: could not allocate cache fifo"));
505 return 0;
506 }
e7fd8a39
UD
507 su->su_cache = (char *) uc;
508 return 1;
28f540f4 509}
021db4be 510libc_hidden_nolink_sunrpc (svcudp_enablecache, GLIBC_2_0)
28f540f4
RM
511
512
513/*
514 * Set an entry in the cache
515 */
e7fd8a39
UD
516static void
517cache_set (SVCXPRT *xprt, u_long replylen)
28f540f4 518{
e7fd8a39
UD
519 cache_ptr victim;
520 cache_ptr *vicp;
521 struct svcudp_data *su = su_data (xprt);
522 struct udp_cache *uc = (struct udp_cache *) su->su_cache;
523 u_int loc;
524 char *newbuf;
525
526 /*
527 * Find space for the new entry, either by
528 * reusing an old entry, or by mallocing a new one
529 */
530 victim = uc->uc_fifo[uc->uc_nextvictim];
531 if (victim != NULL)
532 {
533 loc = CACHE_LOC (xprt, victim->cache_xid);
534 for (vicp = &uc->uc_entries[loc];
535 *vicp != NULL && *vicp != victim;
536 vicp = &(*vicp)->cache_next)
537 ;
538 if (*vicp == NULL)
539 {
540 CACHE_PERROR (_("cache_set: victim not found"));
541 return;
28f540f4 542 }
e7fd8a39
UD
543 *vicp = victim->cache_next; /* remote from cache */
544 newbuf = victim->cache_reply;
545 }
546 else
547 {
548 victim = ALLOC (struct cache_node, 1);
549 if (victim == NULL)
550 {
551 CACHE_PERROR (_("cache_set: victim alloc failed"));
552 return;
553 }
554 newbuf = mem_alloc (su->su_iosz);
555 if (newbuf == NULL)
556 {
0292b0dd 557 mem_free (victim, sizeof (struct cache_node));
e7fd8a39
UD
558 CACHE_PERROR (_("cache_set: could not allocate new rpc_buffer"));
559 return;
560 }
561 }
562
563 /*
564 * Store it away
565 */
566 victim->cache_replylen = replylen;
567 victim->cache_reply = rpc_buffer (xprt);
568 rpc_buffer (xprt) = newbuf;
7b57bfe5 569 xdrmem_create (&(su->su_xdrs), rpc_buffer (xprt), su->su_iosz, XDR_ENCODE);
e7fd8a39
UD
570 victim->cache_xid = su->su_xid;
571 victim->cache_proc = uc->uc_proc;
572 victim->cache_vers = uc->uc_vers;
573 victim->cache_prog = uc->uc_prog;
574 victim->cache_addr = uc->uc_addr;
575 loc = CACHE_LOC (xprt, victim->cache_xid);
576 victim->cache_next = uc->uc_entries[loc];
577 uc->uc_entries[loc] = victim;
578 uc->uc_fifo[uc->uc_nextvictim++] = victim;
579 uc->uc_nextvictim %= uc->uc_size;
28f540f4
RM
580}
581
582/*
583 * Try to get an entry from the cache
584 * return 1 if found, 0 if not found
585 */
e7fd8a39 586static int
f63f2bfd
JM
587cache_get (SVCXPRT *xprt, struct rpc_msg *msg, char **replyp,
588 u_long *replylenp)
28f540f4 589{
e7fd8a39
UD
590 u_int loc;
591 cache_ptr ent;
592 struct svcudp_data *su = su_data (xprt);
593 struct udp_cache *uc = (struct udp_cache *) su->su_cache;
594
50304ef0 595#define EQADDR(a1, a2) (memcmp((char*)&a1, (char*)&a2, sizeof(a1)) == 0)
e7fd8a39
UD
596
597 loc = CACHE_LOC (xprt, su->su_xid);
598 for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next)
599 {
600 if (ent->cache_xid == su->su_xid &&
601 ent->cache_proc == uc->uc_proc &&
602 ent->cache_vers == uc->uc_vers &&
603 ent->cache_prog == uc->uc_prog &&
604 EQADDR (ent->cache_addr, uc->uc_addr))
605 {
606 *replyp = ent->cache_reply;
607 *replylenp = ent->cache_replylen;
608 return 1;
28f540f4 609 }
e7fd8a39
UD
610 }
611 /*
612 * Failed to find entry
613 * Remember a few things so we can do a set later
614 */
615 uc->uc_proc = msg->rm_call.cb_proc;
616 uc->uc_vers = msg->rm_call.cb_vers;
617 uc->uc_prog = msg->rm_call.cb_prog;
c1301d9a 618 memcpy (&uc->uc_addr, &xprt->xp_raddr, sizeof (uc->uc_addr));
e7fd8a39 619 return 0;
28f540f4 620}
This page took 0.708372 seconds and 6 git commands to generate.