1/* 2 * $Id: timelord.c,v 1.8 2005-04-28 20:49:36 bfernhomberg Exp $ 3 * 4 * Copyright (c) 1990,1992 Regents of The University of Michigan. 5 * All Rights Reserved. See COPYRIGHT. 6 * 7 * The "timelord protocol" was reverse engineered from Timelord, 8 * distributed with CAP, Copyright (c) 1990, The University of 9 * Melbourne. The following copyright, supplied by The University 10 * of Melbourne, may apply to this code: 11 * 12 * This version of timelord.c is based on code distributed 13 * by the University of Melbourne as part of the CAP package. 14 * 15 * The tardis/Timelord package for Macintosh/CAP is 16 * Copyright (c) 1990, The University of Melbourne. 17 */ 18 19#ifdef HAVE_CONFIG_H 20#include "config.h" 21#endif /* HAVE_CONFIG_H */ 22 23#include <sys/param.h> 24#include <sys/types.h> 25#include <sys/time.h> 26#include <sys/file.h> 27#include <sys/uio.h> 28#include <stdlib.h> 29 30#include <unistd.h> 31 32#include <netatalk/at.h> 33#include <netatalk/endian.h> 34#include <atalk/atp.h> 35#include <atalk/nbp.h> 36 37#include <time.h> 38#ifdef HAVE_SGTTY_H 39#include <sgtty.h> 40#endif /* HAVE_SGTTY_H */ 41#include <errno.h> 42#include <signal.h> 43#pragma warn "testing 123" 44#include <atalk/logger.h> 45#include <stdio.h> 46#include <string.h> 47#ifdef HAVE_NETDB_H 48#include <netdb.h> 49#endif /* HAVE_NETDB_H */ 50 51#ifdef HAVE_FCNTL_H 52#include <fcntl.h> 53#endif /* HAVE_FCNTL_H */ 54#ifdef HAVE_SYS_FCNTL_H 55#include <sys/fcntl.h> 56#endif /* HAVE_SYS_FCNTL_H */ 57 58#ifdef HAVE_TERMIOS_H 59#include <termios.h> 60#endif /* HAVE_TERMIOS_H */ 61#ifdef HAVE_SYS_TERMIOS_H 62#include <sys/termios.h> 63#endif /* HAVE_SYS_TERMIOS_H */ 64 65#define TL_GETTIME 0 66#define TL_OK 12 67#define TL_BAD 10 68#define EPOCH 0x7C25B080 /* 00:00:00 GMT Jan 1, 1970 for Mac */ 69 70int debug = 0; 71char *bad = "Bad request!"; 72char buf[ 4624 ]; 73char *server; 74 75void usage( char *p ) 76{ 77 char *s; 78 79 if (( s = rindex( p, '/' )) == NULL ) { 80 s = p; 81 } else { 82 s++; 83 } 84 fprintf( stderr, "Usage:\t%s -d -n nbpname\n", s ); 85 exit( 1 ); 86} 87 88/* 89 * Unregister ourself on signal. 90 */ 91void 92goaway(int signal) 93{ 94 if ( nbp_unrgstr( server, "TimeLord", "*", NULL ) < 0 ) { 95 LOG(log_error, logtype_default, "Can't unregister %s", server ); 96 exit( 1 ); 97 } 98 LOG(log_info, logtype_default, "going down" ); 99 exit( 0 ); 100} 101 102int main( int ac, char **av ) 103{ 104 ATP atp; 105 struct sockaddr_at sat; 106 struct atp_block atpb; 107 struct timeval tv; 108 struct timezone tz; 109 struct iovec iov; 110 struct tm *tm; 111 char hostname[ MAXHOSTNAMELEN ]; 112 char *p; 113 int c; 114 long req, mtime, resp; 115 extern char *optarg; 116 extern int optind; 117 118 if ( gethostname( hostname, sizeof( hostname )) < 0 ) { 119 perror( "gethostname" ); 120 exit( 1 ); 121 } 122 if (( server = index( hostname, '.' )) != 0 ) { 123 *server = '\0'; 124 } 125 server = hostname; 126 127 while (( c = getopt( ac, av, "dn:" )) != EOF ) { 128 switch ( c ) { 129 case 'd' : 130 debug++; 131 break; 132 case 'n' : 133 server = optarg; 134 break; 135 default : 136 fprintf( stderr, "Unknown option -- '%c'\n", c ); 137 usage( *av ); 138 } 139 } 140 141 /* 142 * Disassociate from controlling tty. 143 */ 144 if ( !debug ) { 145 int i, dt; 146 147 switch ( fork()) { 148 case 0 : 149 dt = getdtablesize(); 150 for ( i = 0; i < dt; i++ ) { 151 (void)close( i ); 152 } 153 if (( i = open( "/dev/tty", O_RDWR )) >= 0 ) { 154 (void)ioctl( i, TIOCNOTTY, 0 ); 155 setpgid( 0, getpid()); 156 (void)close( i ); 157 } 158 break; 159 case -1 : 160 perror( "fork" ); 161 exit( 1 ); 162 default : 163 exit( 0 ); 164 } 165 } 166 167 if (( p = rindex( *av, '/' )) == NULL ) { 168 p = *av; 169 } else { 170 p++; 171 } 172 173#ifdef ultrix 174 openlog( p, LOG_PID ); 175#else /* ultrix */ 176 set_processname(p); 177 syslog_setup(log_debug, logtype_default, logoption_ndelay|logoption_pid, logfacility_daemon ); 178#endif /* ultrix */ 179 180 /* allocate memory */ 181 memset (&sat.sat_addr, 0, sizeof (sat.sat_addr)); 182 183 if (( atp = atp_open( ATADDR_ANYPORT, &sat.sat_addr )) == NULL ) { 184 LOG(log_error, logtype_default, "main: atp_open: %s", strerror( errno ) ); 185 exit( 1 ); 186 } 187 188 if ( nbp_rgstr( atp_sockaddr( atp ), server, "TimeLord", "*" ) < 0 ) { 189 LOG(log_error, logtype_default, "Can't register %s", server ); 190 exit( 1 ); 191 } 192 LOG(log_info, logtype_default, "%s:TimeLord started", server ); 193 194 signal(SIGHUP, goaway); 195 signal(SIGTERM, goaway); 196 197 for (;;) { 198 /* 199 * Something seriously wrong with atp, since these assigns must 200 * be in the loop... 201 */ 202 atpb.atp_saddr = &sat; 203 atpb.atp_rreqdata = buf; 204 bzero( &sat, sizeof( struct sockaddr_at )); 205 atpb.atp_rreqdlen = sizeof( buf ); 206 if ( atp_rreq( atp, &atpb ) < 0 ) { 207 LOG(log_error, logtype_default, "main: atp_rreq: %s", strerror( errno ) ); 208 exit( 1 ); 209 } 210 211 p = buf; 212 bcopy( p, &req, sizeof( long )); 213 req = ntohl( req ); 214 p += sizeof( long ); 215 216 switch( req ) { 217 case TL_GETTIME : 218 if ( atpb.atp_rreqdlen > 5 ) { 219 bcopy( p + 1, &mtime, sizeof( long )); 220 mtime = ntohl( mtime ); 221 LOG(log_info, logtype_default, "gettime from %s %s was %lu", 222 (*( p + 5 ) == '\0' ) ? "<unknown>" : p + 5, 223 ( *p == 0 ) ? "at boot" : "in chooser", 224 mtime ); 225 } else { 226 LOG(log_info, logtype_default, "gettime" ); 227 } 228 229 if ( gettimeofday( &tv, &tz ) < 0 ) { 230 LOG(log_error, logtype_default, "main: gettimeofday: %s", strerror( errno ) ); 231 exit( 1 ); 232 } 233 if (( tm = gmtime( &tv.tv_sec )) == 0 ) { 234 perror( "localtime" ); 235 exit( 1 ); 236 } 237 238 mtime = tv.tv_sec + EPOCH; 239 mtime = htonl( mtime ); 240 241 resp = TL_OK; 242 bcopy( &resp, buf, sizeof( long )); 243 bcopy( &mtime, buf + sizeof( long ), sizeof( long )); 244 iov.iov_len = sizeof( long ) + sizeof( long ); 245 break; 246 247 default : 248 LOG(log_error, logtype_default, bad ); 249 250 resp = TL_BAD; 251 bcopy( &resp, buf, sizeof( long )); 252 *( buf + 4 ) = (unsigned char)strlen( bad ); 253 strcpy( buf + 5, bad ); 254 iov.iov_len = sizeof( long ) + 2 + strlen( bad ); 255 break; 256 } 257 258 iov.iov_base = buf; 259 atpb.atp_sresiov = &iov; 260 atpb.atp_sresiovcnt = 1; 261 if ( atp_sresp( atp, &atpb ) < 0 ) { 262 LOG(log_error, logtype_default, "main: atp_sresp: %s", strerror( errno ) ); 263 exit( 1 ); 264 } 265 } 266} 267