1 /* 2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 3 * unrestricted use provided that this legend is included on all tape 4 * media and as a part of the software program in whole or part. Users 5 * may copy or modify Sun RPC without charge, but are not authorized 6 * to license or distribute it to anyone else except as part of a product or 7 * program developed by the user. 8 * 9 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 10 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 11 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 12 * 13 * Sun RPC is provided with no support and without any obligation on the 14 * part of Sun Microsystems, Inc. to assist in its use, correction, 15 * modification or enhancement. 16 * 17 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 18 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 19 * OR ANY PART THEREOF. 20 * 21 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 22 * or profits or other special, indirect and consequential damages, even if 23 * Sun has been advised of the possibility of such damages. 24 * 25 * Sun Microsystems, Inc. 26 * 2550 Garcia Avenue 27 * Mountain View, California 94043 28 * 29 * @(#)rtime.c 2.2 88/08/10 4.0 RPCSRC; from 1.8 88/02/08 SMI 30 * $FreeBSD: src/lib/libc/rpc/rtime.c,v 1.5 2000/01/27 23:06:41 jasone Exp $ 31 * $DragonFly: src/lib/libc/rpc/rtime.c,v 1.4 2005/01/31 22:29:38 dillon Exp $ 32 */ 33 34 /* 35 * Copyright (c) 1988 by Sun Microsystems, Inc. 36 37 */ 38 39 /* 40 * rtime - get time from remote machine 41 * 42 * gets time, obtaining value from host 43 * on the udp/time socket. Since timeserver returns 44 * with time of day in seconds since Jan 1, 1900, must 45 * subtract seconds before Jan 1, 1970 to get 46 * what unix uses. 47 */ 48 #include "namespace.h" 49 #include <stdlib.h> 50 #include <string.h> 51 #include <unistd.h> 52 #include <errno.h> 53 #include <sys/types.h> 54 #include <sys/socket.h> 55 #include <sys/time.h> 56 #include <netinet/in.h> 57 #include <stdio.h> 58 #include <netdb.h> 59 #include "un-namespace.h" 60 61 extern int _rpc_dtablesize ( void ); 62 63 #define NYEARS (unsigned long)(1970 - 1900) 64 #define TOFFSET (unsigned long)(60*60*24*(365*NYEARS + (NYEARS/4))) 65 66 static void do_close ( int ); 67 68 int 69 rtime(addrp, timep, timeout) 70 struct sockaddr_in *addrp; 71 struct timeval *timep; 72 struct timeval *timeout; 73 { 74 int s; 75 fd_set readfds; 76 int res; 77 unsigned long thetime; 78 struct sockaddr_in from; 79 int fromlen; 80 int type; 81 struct servent *serv; 82 83 if (timeout == NULL) { 84 type = SOCK_STREAM; 85 } else { 86 type = SOCK_DGRAM; 87 } 88 s = _socket(AF_INET, type, 0); 89 if (s < 0) { 90 return(-1); 91 } 92 addrp->sin_family = AF_INET; 93 94 /* TCP and UDP port are the same in this case */ 95 if ((serv = getservbyname("time", "tcp")) == NULL) { 96 return(-1); 97 } 98 99 addrp->sin_port = serv->s_port; 100 101 if (type == SOCK_DGRAM) { 102 res = _sendto(s, (char *)&thetime, sizeof(thetime), 0, 103 (struct sockaddr *)addrp, sizeof(*addrp)); 104 if (res < 0) { 105 do_close(s); 106 return(-1); 107 } 108 do { 109 FD_ZERO(&readfds); 110 FD_SET(s, &readfds); 111 res = _select(_rpc_dtablesize(), &readfds, 112 (fd_set *)NULL, (fd_set *)NULL, timeout); 113 } while (res < 0 && errno == EINTR); 114 if (res <= 0) { 115 if (res == 0) { 116 errno = ETIMEDOUT; 117 } 118 do_close(s); 119 return(-1); 120 } 121 fromlen = sizeof(from); 122 res = _recvfrom(s, (char *)&thetime, sizeof(thetime), 0, 123 (struct sockaddr *)&from, &fromlen); 124 do_close(s); 125 if (res < 0) { 126 return(-1); 127 } 128 } else { 129 if (_connect(s, (struct sockaddr *)addrp, sizeof(*addrp)) < 0) { 130 do_close(s); 131 return(-1); 132 } 133 res = _read(s, (char *)&thetime, sizeof(thetime)); 134 do_close(s); 135 if (res < 0) { 136 return(-1); 137 } 138 } 139 if (res != sizeof(thetime)) { 140 errno = EIO; 141 return(-1); 142 } 143 thetime = ntohl(thetime); 144 timep->tv_sec = thetime - TOFFSET; 145 timep->tv_usec = 0; 146 return(0); 147 } 148 149 static void 150 do_close(s) 151 int s; 152 { 153 int save; 154 155 save = errno; 156 (void)_close(s); 157 errno = save; 158 } 159