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.3 2003/11/12 20:21:25 eirikn 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 <stdlib.h> 49 #include <string.h> 50 #include <unistd.h> 51 #include <errno.h> 52 #include <sys/types.h> 53 #include <sys/socket.h> 54 #include <sys/time.h> 55 #include <netinet/in.h> 56 #include <stdio.h> 57 #include <netdb.h> 58 59 extern int _rpc_dtablesize ( void ); 60 61 #define NYEARS (unsigned long)(1970 - 1900) 62 #define TOFFSET (unsigned long)(60*60*24*(365*NYEARS + (NYEARS/4))) 63 64 static void do_close ( int ); 65 66 int 67 rtime(addrp, timep, timeout) 68 struct sockaddr_in *addrp; 69 struct timeval *timep; 70 struct timeval *timeout; 71 { 72 int s; 73 fd_set readfds; 74 int res; 75 unsigned long thetime; 76 struct sockaddr_in from; 77 int fromlen; 78 int type; 79 struct servent *serv; 80 81 if (timeout == NULL) { 82 type = SOCK_STREAM; 83 } else { 84 type = SOCK_DGRAM; 85 } 86 s = socket(AF_INET, type, 0); 87 if (s < 0) { 88 return(-1); 89 } 90 addrp->sin_family = AF_INET; 91 92 /* TCP and UDP port are the same in this case */ 93 if ((serv = getservbyname("time", "tcp")) == NULL) { 94 return(-1); 95 } 96 97 addrp->sin_port = serv->s_port; 98 99 if (type == SOCK_DGRAM) { 100 res = sendto(s, (char *)&thetime, sizeof(thetime), 0, 101 (struct sockaddr *)addrp, sizeof(*addrp)); 102 if (res < 0) { 103 do_close(s); 104 return(-1); 105 } 106 do { 107 FD_ZERO(&readfds); 108 FD_SET(s, &readfds); 109 res = select(_rpc_dtablesize(), &readfds, 110 (fd_set *)NULL, (fd_set *)NULL, timeout); 111 } while (res < 0 && errno == EINTR); 112 if (res <= 0) { 113 if (res == 0) { 114 errno = ETIMEDOUT; 115 } 116 do_close(s); 117 return(-1); 118 } 119 fromlen = sizeof(from); 120 res = recvfrom(s, (char *)&thetime, sizeof(thetime), 0, 121 (struct sockaddr *)&from, &fromlen); 122 do_close(s); 123 if (res < 0) { 124 return(-1); 125 } 126 } else { 127 if (connect(s, (struct sockaddr *)addrp, sizeof(*addrp)) < 0) { 128 do_close(s); 129 return(-1); 130 } 131 res = _read(s, (char *)&thetime, sizeof(thetime)); 132 do_close(s); 133 if (res < 0) { 134 return(-1); 135 } 136 } 137 if (res != sizeof(thetime)) { 138 errno = EIO; 139 return(-1); 140 } 141 thetime = ntohl(thetime); 142 timep->tv_sec = thetime - TOFFSET; 143 timep->tv_usec = 0; 144 return(0); 145 } 146 147 static void 148 do_close(s) 149 int s; 150 { 151 int save; 152 153 save = errno; 154 (void)_close(s); 155 errno = save; 156 } 157