1 /* $NetBSD: clnt_vc.c,v 1.18 2012/03/13 21:13:44 christos Exp $ */
4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5 * unrestricted use provided that this legend is included on all tape
6 * media and as a part of the software program in whole or part. Users
7 * may copy or modify Sun RPC without charge, but are not authorized
8 * to license or distribute it to anyone else except as part of a product or
9 * program developed by the user.
11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
15 * Sun RPC is provided with no support and without any obligation on the
16 * part of Sun Microsystems, Inc. to assist in its use, correction,
17 * modification or enhancement.
19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21 * OR ANY PART THEREOF.
23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24 * or profits or other special, indirect and consequential damages, even if
25 * Sun has been advised of the possibility of such damages.
27 * Sun Microsystems, Inc.
29 * Mountain View, California 94043
32 #include <sys/cdefs.h>
33 #if defined(LIBC_SCCS) && !defined(lint)
35 static char *sccsid
= "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
36 static char *sccsid
= "@(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC";
37 static char sccsid
[] = "@(#)clnt_vc.c 1.19 89/03/16 Copyr 1988 Sun Micro";
39 __RCSID("$NetBSD: clnt_vc.c,v 1.18 2012/03/13 21:13:44 christos Exp $");
44 * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
46 * Copyright (C) 1984, Sun Microsystems, Inc.
48 * TCP based RPC supports 'batched calls'.
49 * A sequence of calls may be batched-up in a send buffer. The rpc call
50 * return immediately to the client even though the call was not necessarily
51 * sent. The batching occurs if the results' xdr routine is NULL (0) AND
52 * the rpc timeout value is zero (see clnt.h, rpc).
54 * Clients should NOT casually batch calls that in fact return results; that is,
55 * the server side should be aware that a call is batched and not produce any
56 * return message. Batched calls that produce many result messages can
57 * deadlock (netlock) the client and the server....
59 * Now go hang yourself.
62 #include "namespace.h"
63 #include "reentrant.h"
64 #include <sys/types.h>
66 #include <sys/socket.h>
80 #include "rpc_internal.h"
83 __weak_alias(clnt_vc_create
,_clnt_vc_create
)
86 #define MCALL_MSG_SIZE 24
88 static enum clnt_stat
clnt_vc_call(CLIENT
*, rpcproc_t
, xdrproc_t
,
89 const char *, xdrproc_t
, caddr_t
, struct timeval
);
90 static void clnt_vc_geterr(CLIENT
*, struct rpc_err
*);
91 static bool_t
clnt_vc_freeres(CLIENT
*, xdrproc_t
, caddr_t
);
92 static void clnt_vc_abort(CLIENT
*);
93 static bool_t
clnt_vc_control(CLIENT
*, u_int
, char *);
94 static void clnt_vc_destroy(CLIENT
*);
95 static struct clnt_ops
*clnt_vc_ops(void);
96 static bool_t
time_not_ok(struct timeval
*);
97 static int read_vc(caddr_t
, caddr_t
, int);
98 static int write_vc(caddr_t
, caddr_t
, int);
103 struct timeval ct_wait
;
104 bool_t ct_waitset
; /* wait set by clnt_control? */
105 struct netbuf ct_addr
;
106 struct rpc_err ct_error
;
108 char ct_mcallc
[MCALL_MSG_SIZE
]; /* marshalled callmsg */
111 u_int ct_mpos
; /* pos after marshal */
116 * This machinery implements per-fd locks for MT-safety. It is not
117 * sufficient to do per-CLIENT handle locks for MT-safety because a
118 * user may create more than one CLIENT handle with the same fd behind
119 * it. Therfore, we allocate an array of flags (vc_fd_locks), protected
120 * by the clnt_fd_lock mutex, and an array (vc_cv) of condition variables
121 * similarly protected. Vc_fd_lock[fd] == 1 => a call is activte on some
122 * CLIENT handle created for that fd.
123 * The current implementation holds locks across the entire RPC and reply.
124 * Yes, this is silly, and as soon as this code is proven to work, this
125 * should be the first thing fixed. One step at a time.
128 static int *vc_fd_locks
;
129 #define __rpc_lock_value __isthreaded;
130 extern mutex_t clnt_fd_lock
;
131 static cond_t
*vc_cv
;
132 #define release_fd_lock(fd, mask) { \
133 mutex_lock(&clnt_fd_lock); \
134 vc_fd_locks[fd] = 0; \
135 mutex_unlock(&clnt_fd_lock); \
136 thr_sigsetmask(SIG_SETMASK, &(mask), NULL); \
137 cond_signal(&vc_cv[fd]); \
140 #define release_fd_lock(fd,mask)
141 #define __rpc_lock_value 0
146 * Create a client handle for a connection.
147 * Default options are set, which the user can change using clnt_control()'s.
148 * The rpc/vc package does buffering similar to stdio, so the client
149 * must pick send and receive buffer sizes, 0 => use the default.
150 * NB: fd is copied into a private area.
151 * NB: The rpch->cl_auth is set null authentication. Caller may wish to
152 * set this something more useful.
154 * fd should be an open socket
159 const struct netbuf
*raddr
,
167 struct ct_data
*ct
= NULL
;
168 struct rpc_msg call_msg
;
173 struct sockaddr_storage ss
;
175 struct __rpc_sockinfo si
;
177 _DIAGASSERT(raddr
!= NULL
);
179 h
= mem_alloc(sizeof(*h
));
181 warnx("clnt_vc_create: out of memory");
182 rpc_createerr
.cf_stat
= RPC_SYSTEMERROR
;
183 rpc_createerr
.cf_error
.re_errno
= errno
;
186 ct
= mem_alloc(sizeof(*ct
));
188 warnx("clnt_vc_create: out of memory");
189 rpc_createerr
.cf_stat
= RPC_SYSTEMERROR
;
190 rpc_createerr
.cf_error
.re_errno
= errno
;
194 sigfillset(&newmask
);
195 thr_sigsetmask(SIG_SETMASK
, &newmask
, &mask
);
197 mutex_lock(&clnt_fd_lock
);
198 if (vc_fd_locks
== NULL
) {
199 size_t cv_allocsz
, fd_allocsz
;
200 int dtbsize
= __rpc_dtbsize();
202 fd_allocsz
= dtbsize
* sizeof (int);
203 vc_fd_locks
= mem_alloc(fd_allocsz
);
204 if (vc_fd_locks
== NULL
) {
205 mutex_unlock(&clnt_fd_lock
);
206 thr_sigsetmask(SIG_SETMASK
, &(mask
), NULL
);
209 memset(vc_fd_locks
, '\0', fd_allocsz
);
211 _DIAGASSERT(vc_cv
== NULL
);
212 cv_allocsz
= dtbsize
* sizeof (cond_t
);
213 vc_cv
= mem_alloc(cv_allocsz
);
215 mem_free(vc_fd_locks
, fd_allocsz
);
217 mutex_unlock(&clnt_fd_lock
);
218 thr_sigsetmask(SIG_SETMASK
, &(mask
), NULL
);
223 for (i
= 0; i
< dtbsize
; i
++)
224 cond_init(&vc_cv
[i
], 0, (void *) 0);
227 _DIAGASSERT(vc_cv
!= NULL
);
231 * XXX - fvdl connecting while holding a mutex?
234 if (getpeername(fd
, (struct sockaddr
*)(void *)&ss
, &slen
) < 0) {
235 if (errno
!= ENOTCONN
) {
236 rpc_createerr
.cf_stat
= RPC_SYSTEMERROR
;
237 rpc_createerr
.cf_error
.re_errno
= errno
;
238 mutex_unlock(&clnt_fd_lock
);
239 thr_sigsetmask(SIG_SETMASK
, &(mask
), NULL
);
242 if (connect(fd
, (struct sockaddr
*)raddr
->buf
, raddr
->len
) < 0){
243 rpc_createerr
.cf_stat
= RPC_SYSTEMERROR
;
244 rpc_createerr
.cf_error
.re_errno
= errno
;
245 mutex_unlock(&clnt_fd_lock
);
246 thr_sigsetmask(SIG_SETMASK
, &(mask
), NULL
);
250 mutex_unlock(&clnt_fd_lock
);
251 thr_sigsetmask(SIG_SETMASK
, &(mask
), NULL
);
252 if (!__rpc_fd2sockinfo(fd
, &si
))
255 ct
->ct_closeit
= FALSE
;
258 * Set up private data struct
261 ct
->ct_wait
.tv_usec
= 0;
262 ct
->ct_waitset
= FALSE
;
263 ct
->ct_addr
.buf
= malloc((size_t)raddr
->maxlen
);
264 if (ct
->ct_addr
.buf
== NULL
)
266 memcpy(ct
->ct_addr
.buf
, &raddr
->buf
, (size_t)raddr
->len
);
267 ct
->ct_addr
.len
= raddr
->maxlen
;
268 ct
->ct_addr
.maxlen
= raddr
->maxlen
;
271 * Initialize call message
273 call_msg
.rm_xid
= __RPC_GETXID();
274 call_msg
.rm_direction
= CALL
;
275 call_msg
.rm_call
.cb_rpcvers
= RPC_MSG_VERSION
;
276 call_msg
.rm_call
.cb_prog
= (u_int32_t
)prog
;
277 call_msg
.rm_call
.cb_vers
= (u_int32_t
)vers
;
280 * pre-serialize the static part of the call msg and stash it away
282 xdrmem_create(&(ct
->ct_xdrs
), ct
->ct_u
.ct_mcallc
, MCALL_MSG_SIZE
,
284 if (! xdr_callhdr(&(ct
->ct_xdrs
), &call_msg
)) {
285 if (ct
->ct_closeit
) {
290 ct
->ct_mpos
= XDR_GETPOS(&(ct
->ct_xdrs
));
291 XDR_DESTROY(&(ct
->ct_xdrs
));
294 * Create a client handle which uses xdrrec for serialization
295 * and authnone for authentication.
297 h
->cl_ops
= clnt_vc_ops();
299 h
->cl_auth
= authnone_create();
300 sendsz
= __rpc_get_t_size(si
.si_af
, si
.si_proto
, (int)sendsz
);
301 recvsz
= __rpc_get_t_size(si
.si_af
, si
.si_proto
, (int)recvsz
);
302 xdrrec_create(&(ct
->ct_xdrs
), sendsz
, recvsz
,
303 h
->cl_private
, read_vc
, write_vc
);
308 * Something goofed, free stuff and barf
311 mem_free(ct
, sizeof(struct ct_data
));
313 mem_free(h
, sizeof(CLIENT
));
317 static enum clnt_stat
322 const char *args_ptr
,
323 xdrproc_t xdr_results
,
325 struct timeval timeout
330 struct rpc_msg reply_msg
;
336 sigset_t mask
, newmask
;
339 _DIAGASSERT(h
!= NULL
);
341 ct
= (struct ct_data
*) h
->cl_private
;
344 sigfillset(&newmask
);
345 thr_sigsetmask(SIG_SETMASK
, &newmask
, &mask
);
346 mutex_lock(&clnt_fd_lock
);
347 while (vc_fd_locks
[ct
->ct_fd
])
348 cond_wait(&vc_cv
[ct
->ct_fd
], &clnt_fd_lock
);
349 vc_fd_locks
[ct
->ct_fd
] = __rpc_lock_value
;
350 mutex_unlock(&clnt_fd_lock
);
353 xdrs
= &(ct
->ct_xdrs
);
354 msg_x_id
= &ct
->ct_u
.ct_mcalli
;
356 if (!ct
->ct_waitset
) {
357 if (time_not_ok(&timeout
) == FALSE
)
358 ct
->ct_wait
= timeout
;
362 (xdr_results
== NULL
&& timeout
.tv_sec
== 0
363 && timeout
.tv_usec
== 0) ? FALSE
: TRUE
;
366 xdrs
->x_op
= XDR_ENCODE
;
367 ct
->ct_error
.re_status
= RPC_SUCCESS
;
368 x_id
= ntohl(--(*msg_x_id
));
369 if ((! XDR_PUTBYTES(xdrs
, ct
->ct_u
.ct_mcallc
, ct
->ct_mpos
)) ||
370 (! XDR_PUTINT32(xdrs
, (int32_t *)&proc
)) ||
371 (! AUTH_MARSHALL(h
->cl_auth
, xdrs
)) ||
372 (! (*xdr_args
)(xdrs
, __UNCONST(args_ptr
)))) {
373 if (ct
->ct_error
.re_status
== RPC_SUCCESS
)
374 ct
->ct_error
.re_status
= RPC_CANTENCODEARGS
;
375 (void)xdrrec_endofrecord(xdrs
, TRUE
);
376 release_fd_lock(ct
->ct_fd
, mask
);
377 return (ct
->ct_error
.re_status
);
379 if (! xdrrec_endofrecord(xdrs
, shipnow
)) {
380 release_fd_lock(ct
->ct_fd
, mask
);
381 return (ct
->ct_error
.re_status
= RPC_CANTSEND
);
384 release_fd_lock(ct
->ct_fd
, mask
);
385 return (RPC_SUCCESS
);
388 * Hack to provide rpc-based message passing
390 if (timeout
.tv_sec
== 0 && timeout
.tv_usec
== 0) {
391 release_fd_lock(ct
->ct_fd
, mask
);
392 return(ct
->ct_error
.re_status
= RPC_TIMEDOUT
);
397 * Keep receiving until we get a valid transaction id
399 xdrs
->x_op
= XDR_DECODE
;
401 reply_msg
.acpted_rply
.ar_verf
= _null_auth
;
402 reply_msg
.acpted_rply
.ar_results
.where
= NULL
;
403 reply_msg
.acpted_rply
.ar_results
.proc
= (xdrproc_t
)xdr_void
;
404 if (! xdrrec_skiprecord(xdrs
)) {
405 release_fd_lock(ct
->ct_fd
, mask
);
406 return (ct
->ct_error
.re_status
);
408 /* now decode and validate the response header */
409 if (! xdr_replymsg(xdrs
, &reply_msg
)) {
410 if (ct
->ct_error
.re_status
== RPC_SUCCESS
)
412 release_fd_lock(ct
->ct_fd
, mask
);
413 return (ct
->ct_error
.re_status
);
415 if (reply_msg
.rm_xid
== x_id
)
422 _seterr_reply(&reply_msg
, &(ct
->ct_error
));
423 if (ct
->ct_error
.re_status
== RPC_SUCCESS
) {
424 if (! AUTH_VALIDATE(h
->cl_auth
,
425 &reply_msg
.acpted_rply
.ar_verf
)) {
426 ct
->ct_error
.re_status
= RPC_AUTHERROR
;
427 ct
->ct_error
.re_why
= AUTH_INVALIDRESP
;
428 } else if (! (*xdr_results
)(xdrs
, results_ptr
)) {
429 if (ct
->ct_error
.re_status
== RPC_SUCCESS
)
430 ct
->ct_error
.re_status
= RPC_CANTDECODERES
;
432 /* free verifier ... */
433 if (reply_msg
.acpted_rply
.ar_verf
.oa_base
!= NULL
) {
434 xdrs
->x_op
= XDR_FREE
;
435 (void)xdr_opaque_auth(xdrs
,
436 &(reply_msg
.acpted_rply
.ar_verf
));
438 } /* end successful completion */
440 /* maybe our credentials need to be refreshed ... */
441 if (refreshes
-- && AUTH_REFRESH(h
->cl_auth
))
443 } /* end of unsuccessful completion */
444 release_fd_lock(ct
->ct_fd
, mask
);
445 return (ct
->ct_error
.re_status
);
456 _DIAGASSERT(h
!= NULL
);
457 _DIAGASSERT(errp
!= NULL
);
459 ct
= (struct ct_data
*) h
->cl_private
;
460 *errp
= ct
->ct_error
;
478 _DIAGASSERT(cl
!= NULL
);
480 ct
= (struct ct_data
*)cl
->cl_private
;
481 xdrs
= &(ct
->ct_xdrs
);
483 sigfillset(&newmask
);
484 thr_sigsetmask(SIG_SETMASK
, &newmask
, &mask
);
485 mutex_lock(&clnt_fd_lock
);
487 while (vc_fd_locks
[ct
->ct_fd
])
488 cond_wait(&vc_cv
[ct
->ct_fd
], &clnt_fd_lock
);
491 xdrs
->x_op
= XDR_FREE
;
492 dummy
= (*xdr_res
)(xdrs
, res_ptr
);
493 mutex_unlock(&clnt_fd_lock
);
494 thr_sigsetmask(SIG_SETMASK
, &(mask
), NULL
);
495 cond_signal(&vc_cv
[ct
->ct_fd
]);
502 clnt_vc_abort(CLIENT
*cl
)
520 _DIAGASSERT(cl
!= NULL
);
522 ct
= (struct ct_data
*)cl
->cl_private
;
524 sigfillset(&newmask
);
525 thr_sigsetmask(SIG_SETMASK
, &newmask
, &mask
);
526 mutex_lock(&clnt_fd_lock
);
528 while (vc_fd_locks
[ct
->ct_fd
])
529 cond_wait(&vc_cv
[ct
->ct_fd
], &clnt_fd_lock
);
530 vc_fd_locks
[ct
->ct_fd
] = __rpc_lock_value
;
532 mutex_unlock(&clnt_fd_lock
);
536 ct
->ct_closeit
= TRUE
;
537 release_fd_lock(ct
->ct_fd
, mask
);
539 case CLSET_FD_NCLOSE
:
540 ct
->ct_closeit
= FALSE
;
541 release_fd_lock(ct
->ct_fd
, mask
);
547 /* for other requests which use info */
549 release_fd_lock(ct
->ct_fd
, mask
);
554 if (time_not_ok((struct timeval
*)(void *)info
)) {
555 release_fd_lock(ct
->ct_fd
, mask
);
558 ct
->ct_wait
= *(struct timeval
*)infop
;
559 ct
->ct_waitset
= TRUE
;
562 *(struct timeval
*)infop
= ct
->ct_wait
;
564 case CLGET_SERVER_ADDR
:
565 (void) memcpy(info
, ct
->ct_addr
.buf
, (size_t)ct
->ct_addr
.len
);
568 *(int *)(void *)info
= ct
->ct_fd
;
571 /* The caller should not free this memory area */
572 *(struct netbuf
*)(void *)info
= ct
->ct_addr
;
574 case CLSET_SVC_ADDR
: /* set to new address */
575 release_fd_lock(ct
->ct_fd
, mask
);
579 * use the knowledge that xid is the
580 * first element in the call structure
581 * This will get the xid of the PREVIOUS call
583 *(u_int32_t
*)(void *)info
=
584 ntohl(*(u_int32_t
*)(void *)&ct
->ct_u
.ct_mcalli
);
587 /* This will set the xid of the NEXT call */
588 *(u_int32_t
*)(void *)&ct
->ct_u
.ct_mcalli
=
589 htonl(*((u_int32_t
*)(void *)info
) + 1);
590 /* increment by 1 as clnt_vc_call() decrements once */
594 * This RELIES on the information that, in the call body,
595 * the version number field is the fifth field from the
596 * begining of the RPC header. MUST be changed if the
597 * call_struct is changed
599 *(u_int32_t
*)(void *)info
=
600 ntohl(*(u_int32_t
*)(void *)(ct
->ct_u
.ct_mcallc
+
601 4 * BYTES_PER_XDR_UNIT
));
605 *(u_int32_t
*)(void *)(ct
->ct_u
.ct_mcallc
+
606 4 * BYTES_PER_XDR_UNIT
) =
607 htonl(*(u_int32_t
*)(void *)info
);
612 * This RELIES on the information that, in the call body,
613 * the program number field is the fourth field from the
614 * begining of the RPC header. MUST be changed if the
615 * call_struct is changed
617 *(u_int32_t
*)(void *)info
=
618 ntohl(*(u_int32_t
*)(void *)(ct
->ct_u
.ct_mcallc
+
619 3 * BYTES_PER_XDR_UNIT
));
623 *(u_int32_t
*)(void *)(ct
->ct_u
.ct_mcallc
+
624 3 * BYTES_PER_XDR_UNIT
) =
625 htonl(*(u_int32_t
*)(void *)info
);
629 release_fd_lock(ct
->ct_fd
, mask
);
632 release_fd_lock(ct
->ct_fd
, mask
);
638 clnt_vc_destroy(CLIENT
*cl
)
647 _DIAGASSERT(cl
!= NULL
);
649 ct
= (struct ct_data
*) cl
->cl_private
;
652 sigfillset(&newmask
);
653 thr_sigsetmask(SIG_SETMASK
, &newmask
, &mask
);
654 mutex_lock(&clnt_fd_lock
);
656 while (vc_fd_locks
[ct_fd
])
657 cond_wait(&vc_cv
[ct_fd
], &clnt_fd_lock
);
659 if (ct
->ct_closeit
&& ct
->ct_fd
!= -1) {
660 (void)close(ct
->ct_fd
);
662 XDR_DESTROY(&(ct
->ct_xdrs
));
664 free(ct
->ct_addr
.buf
);
665 mem_free(ct
, sizeof(struct ct_data
));
666 mem_free(cl
, sizeof(CLIENT
));
667 mutex_unlock(&clnt_fd_lock
);
668 thr_sigsetmask(SIG_SETMASK
, &(mask
), NULL
);
670 cond_signal(&vc_cv
[ct_fd
]);
674 * Interface between xdr serializer and tcp connection.
675 * Behaves like the system calls, read & write, but keeps some error state
676 * around for the rpc level.
679 read_vc(char *ctp
, char *buf
, int len
)
681 struct ct_data
*ct
= (struct ct_data
*)(void *)ctp
;
689 TIMEVAL_TO_TIMESPEC(&ct
->ct_wait
, &ts
);
693 switch (pollts(&fd
, 1, &ts
, NULL
)) {
695 ct
->ct_error
.re_status
= RPC_TIMEDOUT
;
701 ct
->ct_error
.re_status
= RPC_CANTRECV
;
702 ct
->ct_error
.re_errno
= errno
;
707 switch (nread
= read(ct
->ct_fd
, buf
, (size_t)len
)) {
711 ct
->ct_error
.re_errno
= ECONNRESET
;
712 ct
->ct_error
.re_status
= RPC_CANTRECV
;
713 len
= -1; /* it's really an error */
717 ct
->ct_error
.re_errno
= errno
;
718 ct
->ct_error
.re_status
= RPC_CANTRECV
;
725 write_vc(char *ctp
, char *buf
, int len
)
727 struct ct_data
*ct
= (struct ct_data
*)(void *)ctp
;
731 for (cnt
= len
; cnt
> 0; cnt
-= i
, buf
+= i
) {
732 if ((i
= write(ct
->ct_fd
, buf
, cnt
)) == -1) {
733 ct
->ct_error
.re_errno
= errno
;
734 ct
->ct_error
.re_status
= RPC_CANTSEND
;
741 static struct clnt_ops
*
744 static struct clnt_ops ops
;
746 extern mutex_t ops_lock
;
751 /* VARIABLES PROTECTED BY ops_lock: ops */
753 sigfillset(&newmask
);
754 thr_sigsetmask(SIG_SETMASK
, &newmask
, &mask
);
755 mutex_lock(&ops_lock
);
756 if (ops
.cl_call
== NULL
) {
757 ops
.cl_call
= clnt_vc_call
;
758 ops
.cl_abort
= clnt_vc_abort
;
759 ops
.cl_geterr
= clnt_vc_geterr
;
760 ops
.cl_freeres
= clnt_vc_freeres
;
761 ops
.cl_destroy
= clnt_vc_destroy
;
762 ops
.cl_control
= clnt_vc_control
;
764 mutex_unlock(&ops_lock
);
765 thr_sigsetmask(SIG_SETMASK
, &(mask
), NULL
);
770 * Make sure that the time is not garbage. -1 value is disallowed.
771 * Note this is different from time_not_ok in clnt_dg.c
774 time_not_ok(struct timeval
*t
)
777 _DIAGASSERT(t
!= NULL
);
779 return (t
->tv_sec
<= -1 || t
->tv_sec
> 100000000 ||
780 t
->tv_usec
<= -1 || t
->tv_usec
> 1000000);