Reinitialize _create_xid state after fork.
[platform/upstream/glibc.git] / sunrpc / clnt_udp.c
1 /*
2  * clnt_udp.c, Implements a UDP/IP based, client side RPC.
3  *
4  * Copyright (C) 1984, Sun Microsystems, 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 Sun Microsystems, 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 #include <stdio.h>
35 #include <unistd.h>
36 #include <libintl.h>
37 #include <rpc/rpc.h>
38 #include <rpc/xdr.h>
39 #include <rpc/clnt.h>
40 #include <sys/poll.h>
41 #include <sys/socket.h>
42 #include <sys/ioctl.h>
43 #include <netdb.h>
44 #include <errno.h>
45 #include <rpc/pmap_clnt.h>
46 #include <net/if.h>
47 #include <ifaddrs.h>
48 #ifdef USE_IN_LIBIO
49 # include <wchar.h>
50 #endif
51 #include <fcntl.h>
52
53 #ifdef IP_RECVERR
54 #include <errqueue.h>
55 #include <sys/uio.h>
56 #endif
57
58 #include <kernel-features.h>
59
60 extern bool_t xdr_opaque_auth (XDR *, struct opaque_auth *);
61 extern u_long _create_xid (void);
62
63 /*
64  * UDP bases client side rpc operations
65  */
66 static enum clnt_stat clntudp_call (CLIENT *, u_long, xdrproc_t, caddr_t,
67                                     xdrproc_t, caddr_t, struct timeval);
68 static void clntudp_abort (void);
69 static void clntudp_geterr (CLIENT *, struct rpc_err *);
70 static bool_t clntudp_freeres (CLIENT *, xdrproc_t, caddr_t);
71 static bool_t clntudp_control (CLIENT *, int, char *);
72 static void clntudp_destroy (CLIENT *);
73
74 static const struct clnt_ops udp_ops =
75 {
76   clntudp_call,
77   clntudp_abort,
78   clntudp_geterr,
79   clntudp_freeres,
80   clntudp_destroy,
81   clntudp_control
82 };
83
84 /*
85  * Private data kept per client handle
86  */
87 struct cu_data
88   {
89     int cu_sock;
90     bool_t cu_closeit;
91     struct sockaddr_in cu_raddr;
92     int cu_rlen;
93     struct timeval cu_wait;
94     struct timeval cu_total;
95     struct rpc_err cu_error;
96     XDR cu_outxdrs;
97     u_int cu_xdrpos;
98     u_int cu_sendsz;
99     char *cu_outbuf;
100     u_int cu_recvsz;
101     char cu_inbuf[1];
102   };
103
104 /*
105  * Create a UDP based client handle.
106  * If *sockp<0, *sockp is set to a newly created UPD socket.
107  * If raddr->sin_port is 0 a binder on the remote machine
108  * is consulted for the correct port number.
109  * NB: It is the clients responsibility to close *sockp.
110  * NB: The rpch->cl_auth is initialized to null authentication.
111  *     Caller may wish to set this something more useful.
112  *
113  * wait is the amount of time used between retransmitting a call if
114  * no response has been heard; retransmission occurs until the actual
115  * rpc call times out.
116  *
117  * sendsz and recvsz are the maximum allowable packet sizes that can be
118  * sent and received.
119  */
120 CLIENT *
121 __libc_clntudp_bufcreate (struct sockaddr_in *raddr, u_long program,
122                           u_long version, struct timeval wait, int *sockp,
123                           u_int sendsz, u_int recvsz, int flags)
124 {
125   CLIENT *cl;
126   struct cu_data *cu = NULL;
127   struct rpc_msg call_msg;
128
129   cl = (CLIENT *) mem_alloc (sizeof (CLIENT));
130   sendsz = ((sendsz + 3) / 4) * 4;
131   recvsz = ((recvsz + 3) / 4) * 4;
132   cu = (struct cu_data *) mem_alloc (sizeof (*cu) + sendsz + recvsz);
133   if (cl == NULL || cu == NULL)
134     {
135       struct rpc_createerr *ce = &get_rpc_createerr ();
136       (void) __fxprintf (NULL, "%s: %s",
137                          "clntudp_create", _("out of memory\n"));
138       ce->cf_stat = RPC_SYSTEMERROR;
139       ce->cf_error.re_errno = ENOMEM;
140       goto fooy;
141     }
142   cu->cu_outbuf = &cu->cu_inbuf[recvsz];
143
144   if (raddr->sin_port == 0)
145     {
146       u_short port;
147       if ((port =
148            pmap_getport (raddr, program, version, IPPROTO_UDP)) == 0)
149         {
150           goto fooy;
151         }
152       raddr->sin_port = htons (port);
153     }
154   cl->cl_ops = (struct clnt_ops *) &udp_ops;
155   cl->cl_private = (caddr_t) cu;
156   cu->cu_raddr = *raddr;
157   cu->cu_rlen = sizeof (cu->cu_raddr);
158   cu->cu_wait = wait;
159   cu->cu_total.tv_sec = -1;
160   cu->cu_total.tv_usec = -1;
161   cu->cu_sendsz = sendsz;
162   cu->cu_recvsz = recvsz;
163   call_msg.rm_xid = _create_xid ();
164   call_msg.rm_direction = CALL;
165   call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
166   call_msg.rm_call.cb_prog = program;
167   call_msg.rm_call.cb_vers = version;
168   INTUSE(xdrmem_create) (&(cu->cu_outxdrs), cu->cu_outbuf, sendsz, XDR_ENCODE);
169   if (!INTUSE(xdr_callhdr) (&(cu->cu_outxdrs), &call_msg))
170     {
171       goto fooy;
172     }
173   cu->cu_xdrpos = XDR_GETPOS (&(cu->cu_outxdrs));
174   if (*sockp < 0)
175     {
176       int dontblock = 1;
177
178 #ifdef SOCK_NONBLOCK
179 # ifndef __ASSUME_SOCK_CLOEXEC
180       if (__have_sock_cloexec >= 0)
181 # endif
182         {
183           *sockp = __socket (AF_INET, SOCK_DGRAM|SOCK_NONBLOCK|flags,
184                              IPPROTO_UDP);
185 # ifndef __ASSUME_SOCK_CLOEXEC
186           if (__have_sock_cloexec == 0)
187             __have_sock_cloexec = *sockp >= 0 || errno != EINVAL ? 1 : -1;
188 # endif
189         }
190 #endif
191 #ifndef __ASSUME_SOCK_CLOEXEC
192 # ifdef SOCK_CLOEXEC
193       if (__have_sock_cloexec < 0)
194 # endif
195         {
196           *sockp = __socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
197 # ifdef SOCK_CLOEXEC
198           if (flags & SOCK_CLOEXEC)
199             __fcntl (*sockp, F_SETFD, FD_CLOEXEC);
200 # endif
201         }
202 #endif
203       if (__builtin_expect (*sockp < 0, 0))
204         {
205           struct rpc_createerr *ce = &get_rpc_createerr ();
206           ce->cf_stat = RPC_SYSTEMERROR;
207           ce->cf_error.re_errno = errno;
208           goto fooy;
209         }
210       /* attempt to bind to prov port */
211       (void) bindresvport (*sockp, (struct sockaddr_in *) 0);
212 #ifndef __ASSUME_SOCK_CLOEXEC
213 # ifdef SOCK_CLOEXEC
214       if (__have_sock_cloexec < 0)
215 # endif
216         /* the sockets rpc controls are non-blocking */
217         (void) __ioctl (*sockp, FIONBIO, (char *) &dontblock);
218 #endif
219 #ifdef IP_RECVERR
220       {
221         int on = 1;
222         __setsockopt (*sockp, SOL_IP, IP_RECVERR, &on, sizeof(on));
223       }
224 #endif
225       cu->cu_closeit = TRUE;
226     }
227   else
228     {
229       cu->cu_closeit = FALSE;
230     }
231   cu->cu_sock = *sockp;
232   cl->cl_auth = INTUSE(authnone_create) ();
233   return cl;
234 fooy:
235   if (cu)
236     mem_free ((caddr_t) cu, sizeof (*cu) + sendsz + recvsz);
237   if (cl)
238     mem_free ((caddr_t) cl, sizeof (CLIENT));
239   return (CLIENT *) NULL;
240 }
241 INTDEF (__libc_clntudp_bufcreate)
242
243 CLIENT *
244 clntudp_bufcreate (struct sockaddr_in *raddr, u_long program, u_long version,
245                    struct timeval wait, int *sockp, u_int sendsz,
246                    u_int recvsz)
247 {
248   return INTUSE(__libc_clntudp_bufcreate) (raddr, program, version, wait,
249                                            sockp, sendsz, recvsz, 0);
250 }
251 INTDEF (clntudp_bufcreate)
252
253 CLIENT *
254 clntudp_create (raddr, program, version, wait, sockp)
255      struct sockaddr_in *raddr;
256      u_long program;
257      u_long version;
258      struct timeval wait;
259      int *sockp;
260 {
261   return INTUSE(__libc_clntudp_bufcreate) (raddr, program, version, wait,
262                                            sockp, UDPMSGSIZE, UDPMSGSIZE, 0);
263 }
264 INTDEF (clntudp_create)
265
266 static int
267 is_network_up (int sock)
268 {
269   struct ifaddrs *ifa;
270
271   if (getifaddrs (&ifa) != 0)
272     return 0;
273
274   struct ifaddrs *run = ifa;
275   while (run != NULL)
276     {
277       if ((run->ifa_flags & IFF_UP) != 0
278           && run->ifa_addr != NULL
279           && run->ifa_addr->sa_family == AF_INET)
280         break;
281
282       run = run->ifa_next;
283     }
284
285   freeifaddrs (ifa);
286
287   return run != NULL;
288 }
289
290 static enum clnt_stat
291 clntudp_call (cl, proc, xargs, argsp, xresults, resultsp, utimeout)
292      CLIENT *cl;        /* client handle */
293      u_long proc;               /* procedure number */
294      xdrproc_t xargs;           /* xdr routine for args */
295      caddr_t argsp;             /* pointer to args */
296      xdrproc_t xresults;        /* xdr routine for results */
297      caddr_t resultsp;          /* pointer to results */
298      struct timeval utimeout;   /* seconds to wait before giving up */
299 {
300   struct cu_data *cu = (struct cu_data *) cl->cl_private;
301   XDR *xdrs;
302   int outlen = 0;
303   int inlen;
304   socklen_t fromlen;
305   struct pollfd fd;
306   int milliseconds = (cu->cu_wait.tv_sec * 1000) +
307     (cu->cu_wait.tv_usec / 1000);
308   struct sockaddr_in from;
309   struct rpc_msg reply_msg;
310   XDR reply_xdrs;
311   struct timeval time_waited;
312   bool_t ok;
313   int nrefreshes = 2;           /* number of times to refresh cred */
314   struct timeval timeout;
315   int anyup;                    /* any network interface up */
316
317   if (cu->cu_total.tv_usec == -1)
318     {
319       timeout = utimeout;       /* use supplied timeout */
320     }
321   else
322     {
323       timeout = cu->cu_total;   /* use default timeout */
324     }
325
326   time_waited.tv_sec = 0;
327   time_waited.tv_usec = 0;
328 call_again:
329   xdrs = &(cu->cu_outxdrs);
330   if (xargs == NULL)
331     goto get_reply;
332   xdrs->x_op = XDR_ENCODE;
333   XDR_SETPOS (xdrs, cu->cu_xdrpos);
334   /*
335    * the transaction is the first thing in the out buffer
336    */
337   (*(uint32_t *) (cu->cu_outbuf))++;
338   if ((!XDR_PUTLONG (xdrs, (long *) &proc)) ||
339       (!AUTH_MARSHALL (cl->cl_auth, xdrs)) ||
340       (!(*xargs) (xdrs, argsp)))
341     return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
342   outlen = (int) XDR_GETPOS (xdrs);
343
344 send_again:
345   if (__sendto (cu->cu_sock, cu->cu_outbuf, outlen, 0,
346                 (struct sockaddr *) &(cu->cu_raddr), cu->cu_rlen)
347       != outlen)
348     {
349       cu->cu_error.re_errno = errno;
350       return (cu->cu_error.re_status = RPC_CANTSEND);
351     }
352
353   /*
354    * Hack to provide rpc-based message passing
355    */
356   if (timeout.tv_sec == 0 && timeout.tv_usec == 0)
357     {
358       return (cu->cu_error.re_status = RPC_TIMEDOUT);
359     }
360  get_reply:
361   /*
362    * sub-optimal code appears here because we have
363    * some clock time to spare while the packets are in flight.
364    * (We assume that this is actually only executed once.)
365    */
366   reply_msg.acpted_rply.ar_verf = _null_auth;
367   reply_msg.acpted_rply.ar_results.where = resultsp;
368   reply_msg.acpted_rply.ar_results.proc = xresults;
369   fd.fd = cu->cu_sock;
370   fd.events = POLLIN;
371   anyup = 0;
372   for (;;)
373     {
374       switch (__poll (&fd, 1, milliseconds))
375         {
376
377         case 0:
378           if (anyup == 0)
379             {
380               anyup = is_network_up (cu->cu_sock);
381               if (!anyup)
382                 return (cu->cu_error.re_status = RPC_CANTRECV);
383             }
384
385           time_waited.tv_sec += cu->cu_wait.tv_sec;
386           time_waited.tv_usec += cu->cu_wait.tv_usec;
387           while (time_waited.tv_usec >= 1000000)
388             {
389               time_waited.tv_sec++;
390               time_waited.tv_usec -= 1000000;
391             }
392           if ((time_waited.tv_sec < timeout.tv_sec) ||
393               ((time_waited.tv_sec == timeout.tv_sec) &&
394                (time_waited.tv_usec < timeout.tv_usec)))
395             goto send_again;
396           return (cu->cu_error.re_status = RPC_TIMEDOUT);
397
398           /*
399            * buggy in other cases because time_waited is not being
400            * updated.
401            */
402         case -1:
403           if (errno == EINTR)
404             continue;
405           cu->cu_error.re_errno = errno;
406           return (cu->cu_error.re_status = RPC_CANTRECV);
407         }
408 #ifdef IP_RECVERR
409       if (fd.revents & POLLERR)
410         {
411           struct msghdr msg;
412           struct cmsghdr *cmsg;
413           struct sock_extended_err *e;
414           struct sockaddr_in err_addr;
415           struct iovec iov;
416           char *cbuf = (char *) alloca (outlen + 256);
417           int ret;
418
419           iov.iov_base = cbuf + 256;
420           iov.iov_len = outlen;
421           msg.msg_name = (void *) &err_addr;
422           msg.msg_namelen = sizeof (err_addr);
423           msg.msg_iov = &iov;
424           msg.msg_iovlen = 1;
425           msg.msg_flags = 0;
426           msg.msg_control = cbuf;
427           msg.msg_controllen = 256;
428           ret = __recvmsg (cu->cu_sock, &msg, MSG_ERRQUEUE);
429           if (ret >= 0
430               && memcmp (cbuf + 256, cu->cu_outbuf, ret) == 0
431               && (msg.msg_flags & MSG_ERRQUEUE)
432               && ((msg.msg_namelen == 0
433                    && ret >= 12)
434                   || (msg.msg_namelen == sizeof (err_addr)
435                       && err_addr.sin_family == AF_INET
436                       && memcmp (&err_addr.sin_addr, &cu->cu_raddr.sin_addr,
437                                  sizeof (err_addr.sin_addr)) == 0
438                       && err_addr.sin_port == cu->cu_raddr.sin_port)))
439             for (cmsg = CMSG_FIRSTHDR (&msg); cmsg;
440                  cmsg = CMSG_NXTHDR (&msg, cmsg))
441               if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR)
442                 {
443                   e = (struct sock_extended_err *) CMSG_DATA(cmsg);
444                   cu->cu_error.re_errno = e->ee_errno;
445                   return (cu->cu_error.re_status = RPC_CANTRECV);
446                 }
447         }
448 #endif
449       do
450         {
451           fromlen = sizeof (struct sockaddr);
452           inlen = __recvfrom (cu->cu_sock, cu->cu_inbuf,
453                               (int) cu->cu_recvsz, MSG_DONTWAIT,
454                               (struct sockaddr *) &from, &fromlen);
455         }
456       while (inlen < 0 && errno == EINTR);
457       if (inlen < 0)
458         {
459           if (errno == EWOULDBLOCK)
460             continue;
461           cu->cu_error.re_errno = errno;
462           return (cu->cu_error.re_status = RPC_CANTRECV);
463         }
464       if (inlen < 4)
465         continue;
466
467       /* see if reply transaction id matches sent id.
468         Don't do this if we only wait for a replay */
469       if (xargs != NULL
470           && (*((u_int32_t *) (cu->cu_inbuf))
471               != *((u_int32_t *) (cu->cu_outbuf))))
472         continue;
473       /* we now assume we have the proper reply */
474       break;
475     }
476
477   /*
478    * now decode and validate the response
479    */
480   INTUSE(xdrmem_create) (&reply_xdrs, cu->cu_inbuf, (u_int) inlen, XDR_DECODE);
481   ok = INTUSE(xdr_replymsg) (&reply_xdrs, &reply_msg);
482   /* XDR_DESTROY(&reply_xdrs);  save a few cycles on noop destroy */
483   if (ok)
484     {
485       _seterr_reply (&reply_msg, &(cu->cu_error));
486       if (cu->cu_error.re_status == RPC_SUCCESS)
487         {
488           if (!AUTH_VALIDATE (cl->cl_auth,
489                               &reply_msg.acpted_rply.ar_verf))
490             {
491               cu->cu_error.re_status = RPC_AUTHERROR;
492               cu->cu_error.re_why = AUTH_INVALIDRESP;
493             }
494           if (reply_msg.acpted_rply.ar_verf.oa_base != NULL)
495             {
496               xdrs->x_op = XDR_FREE;
497               (void) INTUSE(xdr_opaque_auth) (xdrs,
498                                               &(reply_msg.acpted_rply.ar_verf));
499             }
500         }                       /* end successful completion */
501       else
502         {
503           /* maybe our credentials need to be refreshed ... */
504           if (nrefreshes > 0 && AUTH_REFRESH (cl->cl_auth))
505             {
506               nrefreshes--;
507               goto call_again;
508             }
509         }                       /* end of unsuccessful completion */
510     }                           /* end of valid reply message */
511   else
512     {
513       cu->cu_error.re_status = RPC_CANTDECODERES;
514     }
515   return cu->cu_error.re_status;
516 }
517
518 static void
519 clntudp_geterr (CLIENT *cl, struct rpc_err *errp)
520 {
521   struct cu_data *cu = (struct cu_data *) cl->cl_private;
522
523   *errp = cu->cu_error;
524 }
525
526
527 static bool_t
528 clntudp_freeres (CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr)
529 {
530   struct cu_data *cu = (struct cu_data *) cl->cl_private;
531   XDR *xdrs = &(cu->cu_outxdrs);
532
533   xdrs->x_op = XDR_FREE;
534   return (*xdr_res) (xdrs, res_ptr);
535 }
536
537 static void
538 clntudp_abort (void)
539 {
540 }
541
542 static bool_t
543 clntudp_control (CLIENT *cl, int request, char *info)
544 {
545   struct cu_data *cu = (struct cu_data *) cl->cl_private;
546
547   switch (request)
548     {
549     case CLSET_FD_CLOSE:
550       cu->cu_closeit = TRUE;
551       break;
552     case CLSET_FD_NCLOSE:
553       cu->cu_closeit = FALSE;
554       break;
555     case CLSET_TIMEOUT:
556       cu->cu_total = *(struct timeval *) info;
557       break;
558     case CLGET_TIMEOUT:
559       *(struct timeval *) info = cu->cu_total;
560       break;
561     case CLSET_RETRY_TIMEOUT:
562       cu->cu_wait = *(struct timeval *) info;
563       break;
564     case CLGET_RETRY_TIMEOUT:
565       *(struct timeval *) info = cu->cu_wait;
566       break;
567     case CLGET_SERVER_ADDR:
568       *(struct sockaddr_in *) info = cu->cu_raddr;
569       break;
570     case CLGET_FD:
571       *(int *)info = cu->cu_sock;
572       break;
573     case CLGET_XID:
574       /*
575        * use the knowledge that xid is the
576        * first element in the call structure *.
577        * This will get the xid of the PREVIOUS call
578        */
579       *(u_long *)info = ntohl(*(u_long *)cu->cu_outbuf);
580       break;
581     case CLSET_XID:
582       /* This will set the xid of the NEXT call */
583       *(u_long *)cu->cu_outbuf =  htonl(*(u_long *)info - 1);
584       /* decrement by 1 as clntudp_call() increments once */
585     case CLGET_VERS:
586       /*
587        * This RELIES on the information that, in the call body,
588        * the version number field is the fifth field from the
589        * begining of the RPC header. MUST be changed if the
590        * call_struct is changed
591        */
592       *(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf +
593                                           4 * BYTES_PER_XDR_UNIT));
594       break;
595     case CLSET_VERS:
596       *(u_long *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT)
597         = htonl(*(u_long *)info);
598       break;
599     case CLGET_PROG:
600       /*
601        * This RELIES on the information that, in the call body,
602        * the program number field is the  field from the
603        * begining of the RPC header. MUST be changed if the
604        * call_struct is changed
605        */
606       *(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf +
607                                           3 * BYTES_PER_XDR_UNIT));
608       break;
609     case CLSET_PROG:
610       *(u_long *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT)
611         = htonl(*(u_long *)info);
612       break;
613     /* The following are only possible with TI-RPC */
614     case CLGET_SVC_ADDR:
615     case CLSET_SVC_ADDR:
616     case CLSET_PUSH_TIMOD:
617     case CLSET_POP_TIMOD:
618     default:
619       return FALSE;
620     }
621   return TRUE;
622 }
623
624 static void
625 clntudp_destroy (CLIENT *cl)
626 {
627   struct cu_data *cu = (struct cu_data *) cl->cl_private;
628
629   if (cu->cu_closeit)
630     {
631       (void) __close (cu->cu_sock);
632     }
633   XDR_DESTROY (&(cu->cu_outxdrs));
634   mem_free ((caddr_t) cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz));
635   mem_free ((caddr_t) cl, sizeof (CLIENT));
636 }