1c0b746e5SOllivier Robert /* 2c0b746e5SOllivier Robert * ntpdc - control and monitor your ntpd daemon 3c0b746e5SOllivier Robert */ 4224ba2bdSOllivier Robert 5c0b746e5SOllivier Robert #include <stdio.h> 6224ba2bdSOllivier Robert 7224ba2bdSOllivier Robert #include "ntpdc.h" 8224ba2bdSOllivier Robert #include "ntp_select.h" 9224ba2bdSOllivier Robert #include "ntp_io.h" 10224ba2bdSOllivier Robert #include "ntp_stdlib.h" 11224ba2bdSOllivier Robert 12c0b746e5SOllivier Robert #include <ctype.h> 13c0b746e5SOllivier Robert #include <signal.h> 14c0b746e5SOllivier Robert #include <setjmp.h> 15c0b746e5SOllivier Robert #include <netdb.h> 16c0b746e5SOllivier Robert 17c0b746e5SOllivier Robert #ifdef SYS_WINNT 18c0b746e5SOllivier Robert # include <io.h> 19c0b746e5SOllivier Robert #else 20c0b746e5SOllivier Robert # define closesocket close 21c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 22c0b746e5SOllivier Robert 23224ba2bdSOllivier Robert #ifdef HAVE_LIBREADLINE 24224ba2bdSOllivier Robert # include <readline/readline.h> 25224ba2bdSOllivier Robert # include <readline/history.h> 26224ba2bdSOllivier Robert #endif /* HAVE_LIBREADLINE */ 27c0b746e5SOllivier Robert 28c0b746e5SOllivier Robert #ifdef SYS_VXWORKS 29c0b746e5SOllivier Robert /* vxWorks needs mode flag -casey*/ 30c0b746e5SOllivier Robert #define open(name, flags) open(name, flags, 0777) 31c0b746e5SOllivier Robert #define SERVER_PORT_NUM 123 32c0b746e5SOllivier Robert #endif 33c0b746e5SOllivier Robert 34c0b746e5SOllivier Robert /* 35c0b746e5SOllivier Robert * Because we now potentially understand a lot of commands (and 36c0b746e5SOllivier Robert * it requires a lot of commands to talk to ntpd) we will run 37c0b746e5SOllivier Robert * interactive if connected to a terminal. 38c0b746e5SOllivier Robert */ 39c0b746e5SOllivier Robert static int interactive = 0; /* set to 1 when we should prompt */ 40c0b746e5SOllivier Robert static const char * prompt = "ntpdc> "; /* prompt to ask him about */ 41c0b746e5SOllivier Robert 42c0b746e5SOllivier Robert /* 43c0b746e5SOllivier Robert * Keyid used for authenticated requests. Obtained on the fly. 44c0b746e5SOllivier Robert */ 45c0b746e5SOllivier Robert static u_long info_auth_keyid; 46c0b746e5SOllivier Robert 47c0b746e5SOllivier Robert /* 48c0b746e5SOllivier Robert * Type of key md5 or des 49c0b746e5SOllivier Robert */ 50c0b746e5SOllivier Robert #define KEY_TYPE_DES 3 51c0b746e5SOllivier Robert #define KEY_TYPE_MD5 4 52c0b746e5SOllivier Robert 53c0b746e5SOllivier Robert static int info_auth_keytype = KEY_TYPE_MD5; /* MD5*/ 54c0b746e5SOllivier Robert u_long current_time; /* needed by authkeys; not used */ 55c0b746e5SOllivier Robert 56c0b746e5SOllivier Robert int ntpdcmain P((int, char **)); 57c0b746e5SOllivier Robert /* 58c0b746e5SOllivier Robert * Built in command handler declarations 59c0b746e5SOllivier Robert */ 60c0b746e5SOllivier Robert static int openhost P((const char *)); 61c0b746e5SOllivier Robert static int sendpkt P((char *, int)); 62c0b746e5SOllivier Robert static void growpktdata P((void)); 63c0b746e5SOllivier Robert static int getresponse P((int, int, int *, int *, char **)); 64c0b746e5SOllivier Robert static int sendrequest P((int, int, int, int, int, char *)); 65c0b746e5SOllivier Robert static void getcmds P((void)); 66c0b746e5SOllivier Robert static RETSIGTYPE abortcmd P((int)); 67c0b746e5SOllivier Robert static void docmd P((const char *)); 68c0b746e5SOllivier Robert static void tokenize P((const char *, char **, int *)); 69c0b746e5SOllivier Robert static int findcmd P((char *, struct xcmd *, struct xcmd *, struct xcmd **)); 70c0b746e5SOllivier Robert static int getarg P((char *, int, arg_v *)); 71c0b746e5SOllivier Robert static int getnetnum P((const char *, u_int32 *, char *)); 72c0b746e5SOllivier Robert static void help P((struct parse *, FILE *)); 73c0b746e5SOllivier Robert #ifdef QSORT_USES_VOID_P 74c0b746e5SOllivier Robert static int helpsort P((const void *, const void *)); 75c0b746e5SOllivier Robert #else 76c0b746e5SOllivier Robert static int helpsort P((char **, char **)); 77c0b746e5SOllivier Robert #endif 78c0b746e5SOllivier Robert static void printusage P((struct xcmd *, FILE *)); 79c0b746e5SOllivier Robert static void timeout P((struct parse *, FILE *)); 80c0b746e5SOllivier Robert static void my_delay P((struct parse *, FILE *)); 81c0b746e5SOllivier Robert static void host P((struct parse *, FILE *)); 82c0b746e5SOllivier Robert static void keyid P((struct parse *, FILE *)); 83c0b746e5SOllivier Robert static void keytype P((struct parse *, FILE *)); 84c0b746e5SOllivier Robert static void passwd P((struct parse *, FILE *)); 85c0b746e5SOllivier Robert static void hostnames P((struct parse *, FILE *)); 86c0b746e5SOllivier Robert static void setdebug P((struct parse *, FILE *)); 87c0b746e5SOllivier Robert static void quit P((struct parse *, FILE *)); 88c0b746e5SOllivier Robert static void version P((struct parse *, FILE *)); 89c0b746e5SOllivier Robert static void warning P((const char *, const char *, const char *)); 90c0b746e5SOllivier Robert static void error P((const char *, const char *, const char *)); 91c0b746e5SOllivier Robert static u_long getkeyid P((const char *)); 92c0b746e5SOllivier Robert 93c0b746e5SOllivier Robert 94c0b746e5SOllivier Robert 95c0b746e5SOllivier Robert /* 96c0b746e5SOllivier Robert * Built-in commands we understand 97c0b746e5SOllivier Robert */ 98c0b746e5SOllivier Robert static struct xcmd builtins[] = { 99c0b746e5SOllivier Robert { "?", help, { OPT|NTP_STR, NO, NO, NO }, 100c0b746e5SOllivier Robert { "command", "", "", "" }, 101c0b746e5SOllivier Robert "tell the use and syntax of commands" }, 102c0b746e5SOllivier Robert { "help", help, { OPT|NTP_STR, NO, NO, NO }, 103c0b746e5SOllivier Robert { "command", "", "", "" }, 104c0b746e5SOllivier Robert "tell the use and syntax of commands" }, 105c0b746e5SOllivier Robert { "timeout", timeout, { OPT|UINT, NO, NO, NO }, 106c0b746e5SOllivier Robert { "msec", "", "", "" }, 107c0b746e5SOllivier Robert "set the primary receive time out" }, 108c0b746e5SOllivier Robert { "delay", my_delay, { OPT|INT, NO, NO, NO }, 109c0b746e5SOllivier Robert { "msec", "", "", "" }, 110c0b746e5SOllivier Robert "set the delay added to encryption time stamps" }, 111c0b746e5SOllivier Robert { "host", host, { OPT|NTP_STR, NO, NO, NO }, 112c0b746e5SOllivier Robert { "hostname", "", "", "" }, 113c0b746e5SOllivier Robert "specify the host whose NTP server we talk to" }, 114c0b746e5SOllivier Robert { "passwd", passwd, { OPT|NTP_STR, NO, NO, NO }, 115c0b746e5SOllivier Robert { "", "", "", "" }, 116c0b746e5SOllivier Robert "specify a password to use for authenticated requests"}, 117c0b746e5SOllivier Robert { "hostnames", hostnames, { OPT|NTP_STR, NO, NO, NO }, 118c0b746e5SOllivier Robert { "yes|no", "", "", "" }, 119c0b746e5SOllivier Robert "specify whether hostnames or net numbers are printed"}, 120c0b746e5SOllivier Robert { "debug", setdebug, { OPT|NTP_STR, NO, NO, NO }, 121c0b746e5SOllivier Robert { "no|more|less", "", "", "" }, 122c0b746e5SOllivier Robert "set/change debugging level" }, 123c0b746e5SOllivier Robert { "quit", quit, { NO, NO, NO, NO }, 124c0b746e5SOllivier Robert { "", "", "", "" }, 125c0b746e5SOllivier Robert "exit ntpdc" }, 126c0b746e5SOllivier Robert { "exit", quit, { NO, NO, NO, NO }, 127c0b746e5SOllivier Robert { "", "", "", "" }, 128c0b746e5SOllivier Robert "exit ntpdc" }, 129c0b746e5SOllivier Robert { "keyid", keyid, { OPT|UINT, NO, NO, NO }, 130c0b746e5SOllivier Robert { "key#", "", "", "" }, 131c0b746e5SOllivier Robert "set/show keyid to use for authenticated requests" }, 132c0b746e5SOllivier Robert { "keytype", keytype, { OPT|NTP_STR, NO, NO, NO }, 133c0b746e5SOllivier Robert { "(md5|des)", "", "", "" }, 134c0b746e5SOllivier Robert "set/show key authentication type for authenticated requests (des|md5)" }, 135c0b746e5SOllivier Robert { "version", version, { NO, NO, NO, NO }, 136c0b746e5SOllivier Robert { "", "", "", "" }, 137c0b746e5SOllivier Robert "print version number" }, 138c0b746e5SOllivier Robert { 0, 0, { NO, NO, NO, NO }, 139c0b746e5SOllivier Robert { "", "", "", "" }, "" } 140c0b746e5SOllivier Robert }; 141c0b746e5SOllivier Robert 142c0b746e5SOllivier Robert 143c0b746e5SOllivier Robert /* 144c0b746e5SOllivier Robert * Default values we use. 145c0b746e5SOllivier Robert */ 146c0b746e5SOllivier Robert #define DEFTIMEOUT (5) /* 5 second time out */ 147c0b746e5SOllivier Robert #define DEFSTIMEOUT (2) /* 2 second time out after first */ 148c0b746e5SOllivier Robert #define DEFDELAY 0x51EB852 /* 20 milliseconds, l_fp fraction */ 149c0b746e5SOllivier Robert #define DEFHOST "localhost" /* default host name */ 150c0b746e5SOllivier Robert #define LENHOSTNAME 256 /* host name is 256 characters long */ 151c0b746e5SOllivier Robert #define MAXCMDS 100 /* maximum commands on cmd line */ 152c0b746e5SOllivier Robert #define MAXHOSTS 200 /* maximum hosts on cmd line */ 153c0b746e5SOllivier Robert #define MAXLINE 512 /* maximum line length */ 154c0b746e5SOllivier Robert #define MAXTOKENS (1+MAXARGS+2) /* maximum number of usable tokens */ 155c0b746e5SOllivier Robert 156c0b746e5SOllivier Robert /* 157c0b746e5SOllivier Robert * Some variables used and manipulated locally 158c0b746e5SOllivier Robert */ 159c0b746e5SOllivier Robert static struct timeval tvout = { DEFTIMEOUT, 0 }; /* time out for reads */ 160c0b746e5SOllivier Robert static struct timeval tvsout = { DEFSTIMEOUT, 0 }; /* secondary time out */ 161c0b746e5SOllivier Robert static l_fp delay_time; /* delay time */ 162c0b746e5SOllivier Robert static char currenthost[LENHOSTNAME]; /* current host name */ 163c0b746e5SOllivier Robert static struct sockaddr_in hostaddr = { 0 }; /* host address */ 164c0b746e5SOllivier Robert static int showhostnames = 1; /* show host names by default */ 165c0b746e5SOllivier Robert 166c0b746e5SOllivier Robert static int sockfd; /* fd socket is openned on */ 167c0b746e5SOllivier Robert static int havehost = 0; /* set to 1 when host open */ 168c0b746e5SOllivier Robert struct servent *server_entry = NULL; /* server entry for ntp */ 169c0b746e5SOllivier Robert 170c0b746e5SOllivier Robert #if defined (SYS_WINNT) || defined (SYS_VXWORKS) 171c0b746e5SOllivier Robert char password[9]; 172c0b746e5SOllivier Robert #endif /* SYS_WINNT || SYS_VXWORKS */ 173c0b746e5SOllivier Robert 174c0b746e5SOllivier Robert #ifdef SYS_WINNT 175c0b746e5SOllivier Robert WORD wVersionRequested; 176c0b746e5SOllivier Robert WSADATA wsaData; 177c0b746e5SOllivier Robert DWORD NumberOfBytesWritten; 178c0b746e5SOllivier Robert 179c0b746e5SOllivier Robert HANDLE TimerThreadHandle = NULL; /* 1998/06/03 - Used in ntplib/machines.c */ 180c0b746e5SOllivier Robert void timer(void) { ; }; /* 1998/06/03 - Used in ntplib/machines.c */ 181c0b746e5SOllivier Robert 182c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 183c0b746e5SOllivier Robert 184c0b746e5SOllivier Robert /* 185c0b746e5SOllivier Robert * Holds data returned from queries. We allocate INITDATASIZE 186c0b746e5SOllivier Robert * octets to begin with, increasing this as we need to. 187c0b746e5SOllivier Robert */ 188c0b746e5SOllivier Robert #define INITDATASIZE (sizeof(struct resp_pkt) * 16) 189c0b746e5SOllivier Robert #define INCDATASIZE (sizeof(struct resp_pkt) * 8) 190c0b746e5SOllivier Robert 191c0b746e5SOllivier Robert static char *pktdata; 192c0b746e5SOllivier Robert static int pktdatasize; 193c0b746e5SOllivier Robert 194c0b746e5SOllivier Robert /* 195ce265a54SOllivier Robert * These are used to help the magic with old and new versions of ntpd. 196ce265a54SOllivier Robert */ 197ce265a54SOllivier Robert static int req_pkt_size = REQ_LEN_NOMAC; 198ce265a54SOllivier Robert 199ce265a54SOllivier Robert /* 200c0b746e5SOllivier Robert * For commands typed on the command line (with the -c option) 201c0b746e5SOllivier Robert */ 202c0b746e5SOllivier Robert static int numcmds = 0; 203c0b746e5SOllivier Robert static const char *ccmds[MAXCMDS]; 204c0b746e5SOllivier Robert #define ADDCMD(cp) if (numcmds < MAXCMDS) ccmds[numcmds++] = (cp) 205c0b746e5SOllivier Robert 206c0b746e5SOllivier Robert /* 207c0b746e5SOllivier Robert * When multiple hosts are specified. 208c0b746e5SOllivier Robert */ 209c0b746e5SOllivier Robert static int numhosts = 0; 210c0b746e5SOllivier Robert static const char *chosts[MAXHOSTS]; 211c0b746e5SOllivier Robert #define ADDHOST(cp) if (numhosts < MAXHOSTS) chosts[numhosts++] = (cp) 212c0b746e5SOllivier Robert 213c0b746e5SOllivier Robert /* 214c0b746e5SOllivier Robert * Error codes for internal use 215c0b746e5SOllivier Robert */ 216c0b746e5SOllivier Robert #define ERR_INCOMPLETE 16 217c0b746e5SOllivier Robert #define ERR_TIMEOUT 17 218c0b746e5SOllivier Robert 219c0b746e5SOllivier Robert /* 220c0b746e5SOllivier Robert * Macro definitions we use 221c0b746e5SOllivier Robert */ 222c0b746e5SOllivier Robert #define ISSPACE(c) ((c) == ' ' || (c) == '\t') 223c0b746e5SOllivier Robert #define ISEOL(c) ((c) == '\n' || (c) == '\r' || (c) == '\0') 224c0b746e5SOllivier Robert #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) 225c0b746e5SOllivier Robert 226c0b746e5SOllivier Robert /* 227c0b746e5SOllivier Robert * For converting time stamps to dates 228c0b746e5SOllivier Robert */ 229c0b746e5SOllivier Robert #define JAN_1970 2208988800 /* 1970 - 1900 in seconds */ 230c0b746e5SOllivier Robert 231c0b746e5SOllivier Robert /* 232c0b746e5SOllivier Robert * Jump buffer for longjumping back to the command level 233c0b746e5SOllivier Robert */ 234c0b746e5SOllivier Robert static jmp_buf interrupt_buf; 235c0b746e5SOllivier Robert static volatile int jump = 0; 236c0b746e5SOllivier Robert 237c0b746e5SOllivier Robert /* 238c0b746e5SOllivier Robert * Pointer to current output unit 239c0b746e5SOllivier Robert */ 240c0b746e5SOllivier Robert static FILE *current_output; 241c0b746e5SOllivier Robert 242c0b746e5SOllivier Robert /* 243c0b746e5SOllivier Robert * Command table imported from ntpdc_ops.c 244c0b746e5SOllivier Robert */ 245c0b746e5SOllivier Robert extern struct xcmd opcmds[]; 246c0b746e5SOllivier Robert 247c0b746e5SOllivier Robert char *progname; 248c0b746e5SOllivier Robert volatile int debug; 249c0b746e5SOllivier Robert 250c0b746e5SOllivier Robert #ifdef NO_MAIN_ALLOWED 251c0b746e5SOllivier Robert CALL(ntpdc,"ntpdc",ntpdcmain); 252c0b746e5SOllivier Robert #else 253c0b746e5SOllivier Robert int 254c0b746e5SOllivier Robert main( 255c0b746e5SOllivier Robert int argc, 256c0b746e5SOllivier Robert char *argv[] 257c0b746e5SOllivier Robert ) 258c0b746e5SOllivier Robert { 259c0b746e5SOllivier Robert return ntpdcmain(argc, argv); 260c0b746e5SOllivier Robert } 261c0b746e5SOllivier Robert #endif 262c0b746e5SOllivier Robert 263c0b746e5SOllivier Robert #ifdef SYS_VXWORKS 264c0b746e5SOllivier Robert void clear_globals(void) 265c0b746e5SOllivier Robert { 266c0b746e5SOllivier Robert extern int ntp_optind; 267c0b746e5SOllivier Robert extern char *ntp_optarg; 268c0b746e5SOllivier Robert showhostnames = 0; /* show host names by default */ 269c0b746e5SOllivier Robert ntp_optind = 0; 270c0b746e5SOllivier Robert ntp_optarg = 0; 271c0b746e5SOllivier Robert server_entry = NULL; /* server entry for ntp */ 272c0b746e5SOllivier Robert havehost = 0; /* set to 1 when host open */ 273c0b746e5SOllivier Robert numcmds = 0; 274c0b746e5SOllivier Robert numhosts = 0; 275c0b746e5SOllivier Robert } 276c0b746e5SOllivier Robert #endif 277c0b746e5SOllivier Robert 278c0b746e5SOllivier Robert /* 279c0b746e5SOllivier Robert * main - parse arguments and handle options 280c0b746e5SOllivier Robert */ 281c0b746e5SOllivier Robert int 282c0b746e5SOllivier Robert ntpdcmain( 283c0b746e5SOllivier Robert int argc, 284c0b746e5SOllivier Robert char *argv[] 285c0b746e5SOllivier Robert ) 286c0b746e5SOllivier Robert { 287c0b746e5SOllivier Robert int c; 288c0b746e5SOllivier Robert int errflg = 0; 289c0b746e5SOllivier Robert extern int ntp_optind; 290c0b746e5SOllivier Robert extern char *ntp_optarg; 291c0b746e5SOllivier Robert 292c0b746e5SOllivier Robert delay_time.l_ui = 0; 293c0b746e5SOllivier Robert delay_time.l_uf = DEFDELAY; 294c0b746e5SOllivier Robert 295c0b746e5SOllivier Robert #ifdef SYS_VXWORKS 296c0b746e5SOllivier Robert clear_globals(); 297c0b746e5SOllivier Robert taskPrioritySet(taskIdSelf(), 100 ); 298c0b746e5SOllivier Robert #endif 299c0b746e5SOllivier Robert 300c0b746e5SOllivier Robert progname = argv[0]; 301c0b746e5SOllivier Robert while ((c = ntp_getopt(argc, argv, "c:dilnps")) != EOF) 302c0b746e5SOllivier Robert switch (c) { 303c0b746e5SOllivier Robert case 'c': 304c0b746e5SOllivier Robert ADDCMD(ntp_optarg); 305c0b746e5SOllivier Robert break; 306c0b746e5SOllivier Robert case 'd': 307c0b746e5SOllivier Robert ++debug; 308c0b746e5SOllivier Robert break; 309c0b746e5SOllivier Robert case 'i': 310c0b746e5SOllivier Robert interactive = 1; 311c0b746e5SOllivier Robert break; 312c0b746e5SOllivier Robert case 'l': 313c0b746e5SOllivier Robert ADDCMD("listpeers"); 314c0b746e5SOllivier Robert break; 315c0b746e5SOllivier Robert case 'n': 316c0b746e5SOllivier Robert showhostnames = 0; 317c0b746e5SOllivier Robert break; 318c0b746e5SOllivier Robert case 'p': 319c0b746e5SOllivier Robert ADDCMD("peers"); 320c0b746e5SOllivier Robert break; 321c0b746e5SOllivier Robert case 's': 322c0b746e5SOllivier Robert ADDCMD("dmpeers"); 323c0b746e5SOllivier Robert break; 324c0b746e5SOllivier Robert default: 325c0b746e5SOllivier Robert errflg++; 326c0b746e5SOllivier Robert break; 327c0b746e5SOllivier Robert } 328c0b746e5SOllivier Robert if (errflg) { 329c0b746e5SOllivier Robert (void) fprintf(stderr, 330c0b746e5SOllivier Robert "usage: %s [-dilnps] [-c cmd] host ...\n", 331c0b746e5SOllivier Robert progname); 332c0b746e5SOllivier Robert exit(2); 333c0b746e5SOllivier Robert } 334c0b746e5SOllivier Robert if (ntp_optind == argc) { 335c0b746e5SOllivier Robert ADDHOST(DEFHOST); 336c0b746e5SOllivier Robert } else { 337c0b746e5SOllivier Robert for (; ntp_optind < argc; ntp_optind++) 338c0b746e5SOllivier Robert ADDHOST(argv[ntp_optind]); 339c0b746e5SOllivier Robert } 340c0b746e5SOllivier Robert 341c0b746e5SOllivier Robert if (numcmds == 0 && interactive == 0 342c0b746e5SOllivier Robert && isatty(fileno(stdin)) && isatty(fileno(stderr))) { 343c0b746e5SOllivier Robert interactive = 1; 344c0b746e5SOllivier Robert } 345c0b746e5SOllivier Robert 346c0b746e5SOllivier Robert #ifndef SYS_WINNT /* Under NT cannot handle SIGINT, WIN32 spawns a handler */ 347c0b746e5SOllivier Robert if (interactive) 348c0b746e5SOllivier Robert (void) signal_no_reset(SIGINT, abortcmd); 349c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 350c0b746e5SOllivier Robert 351c0b746e5SOllivier Robert /* 352c0b746e5SOllivier Robert * Initialize the packet data buffer 353c0b746e5SOllivier Robert */ 354c0b746e5SOllivier Robert pktdata = (char *)malloc(INITDATASIZE); 355c0b746e5SOllivier Robert if (pktdata == NULL) { 356c0b746e5SOllivier Robert (void) fprintf(stderr, "%s: malloc() failed!\n", progname); 357c0b746e5SOllivier Robert exit(1); 358c0b746e5SOllivier Robert } 359c0b746e5SOllivier Robert pktdatasize = INITDATASIZE; 360c0b746e5SOllivier Robert 361c0b746e5SOllivier Robert #ifdef SYS_WINNT 362c0b746e5SOllivier Robert wVersionRequested = MAKEWORD(1,1); 363c0b746e5SOllivier Robert if (WSAStartup(wVersionRequested, &wsaData)) { 364c0b746e5SOllivier Robert fprintf(stderr, "No useable winsock.dll"); 365c0b746e5SOllivier Robert exit(1); 366c0b746e5SOllivier Robert } 367c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 368c0b746e5SOllivier Robert 369c0b746e5SOllivier Robert if (numcmds == 0) { 370c0b746e5SOllivier Robert (void) openhost(chosts[0]); 371c0b746e5SOllivier Robert getcmds(); 372c0b746e5SOllivier Robert } else { 373c0b746e5SOllivier Robert int ihost; 374c0b746e5SOllivier Robert int icmd; 375c0b746e5SOllivier Robert 376c0b746e5SOllivier Robert for (ihost = 0; ihost < numhosts; ihost++) { 377c0b746e5SOllivier Robert if (openhost(chosts[ihost])) 378c0b746e5SOllivier Robert for (icmd = 0; icmd < numcmds; icmd++) { 379c0b746e5SOllivier Robert if (numhosts > 1) 380c0b746e5SOllivier Robert printf ("--- %s ---\n",chosts[ihost]); 381c0b746e5SOllivier Robert docmd(ccmds[icmd]); 382c0b746e5SOllivier Robert } 383c0b746e5SOllivier Robert } 384c0b746e5SOllivier Robert } 385c0b746e5SOllivier Robert #ifdef SYS_WINNT 386c0b746e5SOllivier Robert WSACleanup(); 387c0b746e5SOllivier Robert #endif 388c0b746e5SOllivier Robert return(0); 389c0b746e5SOllivier Robert } /* main end */ 390c0b746e5SOllivier Robert 391c0b746e5SOllivier Robert 392c0b746e5SOllivier Robert /* 393c0b746e5SOllivier Robert * openhost - open a socket to a host 394c0b746e5SOllivier Robert */ 395c0b746e5SOllivier Robert static int 396c0b746e5SOllivier Robert openhost( 397c0b746e5SOllivier Robert const char *hname 398c0b746e5SOllivier Robert ) 399c0b746e5SOllivier Robert { 400c0b746e5SOllivier Robert u_int32 netnum; 401c0b746e5SOllivier Robert char temphost[LENHOSTNAME]; 402c0b746e5SOllivier Robert 403c0b746e5SOllivier Robert if (server_entry == NULL) { 404c0b746e5SOllivier Robert server_entry = getservbyname("ntp", "udp"); 405c0b746e5SOllivier Robert if (server_entry == NULL) { 406c0b746e5SOllivier Robert #ifdef VMS /* UCX getservbyname() doesn't work [yet], but we do know better */ 407c0b746e5SOllivier Robert server_entry = (struct servent *) 408c0b746e5SOllivier Robert malloc(sizeof(struct servent)); 409c0b746e5SOllivier Robert server_entry->s_port = htons(NTP_PORT); 410c0b746e5SOllivier Robert #else 411c0b746e5SOllivier Robert (void) fprintf(stderr, "%s: ntp/udp: unknown service\n", 412c0b746e5SOllivier Robert progname); 413c0b746e5SOllivier Robert exit(1); 414c0b746e5SOllivier Robert #endif /* VMS & UCX */ 415c0b746e5SOllivier Robert } 416c0b746e5SOllivier Robert if (debug > 2) 417c0b746e5SOllivier Robert printf("Got ntp/udp service entry\n"); 418c0b746e5SOllivier Robert } 419c0b746e5SOllivier Robert 420c0b746e5SOllivier Robert if (!getnetnum(hname, &netnum, temphost)) 421c0b746e5SOllivier Robert return 0; 422c0b746e5SOllivier Robert 423c0b746e5SOllivier Robert if (debug > 2) 424c0b746e5SOllivier Robert printf("Opening host %s\n", temphost); 425c0b746e5SOllivier Robert 426c0b746e5SOllivier Robert if (havehost == 1) { 427c0b746e5SOllivier Robert if (debug > 2) 428c0b746e5SOllivier Robert printf("Closing old host %s\n", currenthost); 429c0b746e5SOllivier Robert (void) closesocket(sockfd); 430c0b746e5SOllivier Robert havehost = 0; 431c0b746e5SOllivier Robert } 432c0b746e5SOllivier Robert (void) strcpy(currenthost, temphost); 433c0b746e5SOllivier Robert 434c0b746e5SOllivier Robert hostaddr.sin_family = AF_INET; 435c0b746e5SOllivier Robert #ifndef SYS_VXWORKS 436c0b746e5SOllivier Robert hostaddr.sin_port = server_entry->s_port; 437c0b746e5SOllivier Robert #else 438c0b746e5SOllivier Robert hostaddr.sin_port = htons(SERVER_PORT_NUM); 439c0b746e5SOllivier Robert #endif 440c0b746e5SOllivier Robert hostaddr.sin_addr.s_addr = netnum; 441c0b746e5SOllivier Robert 442c0b746e5SOllivier Robert #ifdef SYS_WINNT 443c0b746e5SOllivier Robert { 444c0b746e5SOllivier Robert int optionValue = SO_SYNCHRONOUS_NONALERT; 445c0b746e5SOllivier Robert int err; 446c0b746e5SOllivier Robert err = setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&optionValue, sizeof(optionValue)); 447c0b746e5SOllivier Robert if (err != NO_ERROR) { 448c0b746e5SOllivier Robert (void) fprintf(stderr, "cannot open nonoverlapped sockets\n"); 449c0b746e5SOllivier Robert exit(1); 450c0b746e5SOllivier Robert } 451c0b746e5SOllivier Robert } 452c0b746e5SOllivier Robert 453c0b746e5SOllivier Robert sockfd = socket(AF_INET, SOCK_DGRAM, 0); 454c0b746e5SOllivier Robert if (sockfd == INVALID_SOCKET) { 455c0b746e5SOllivier Robert error("socket", "", ""); 456c0b746e5SOllivier Robert exit(-1); 457c0b746e5SOllivier Robert } 458c0b746e5SOllivier Robert #else 459c0b746e5SOllivier Robert sockfd = socket(AF_INET, SOCK_DGRAM, 0); 460c0b746e5SOllivier Robert if (sockfd == -1) 461c0b746e5SOllivier Robert error("socket", "", ""); 462c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 463c0b746e5SOllivier Robert 464c0b746e5SOllivier Robert 465c0b746e5SOllivier Robert #ifdef NEED_RCVBUF_SLOP 466c0b746e5SOllivier Robert # ifdef SO_RCVBUF 467c0b746e5SOllivier Robert { 468c0b746e5SOllivier Robert int rbufsize = INITDATASIZE + 2048; /* 2K for slop */ 469c0b746e5SOllivier Robert 470c0b746e5SOllivier Robert if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, 471c0b746e5SOllivier Robert &rbufsize, sizeof(int)) == -1) 472c0b746e5SOllivier Robert error("setsockopt", "", ""); 473c0b746e5SOllivier Robert } 474c0b746e5SOllivier Robert # endif 475c0b746e5SOllivier Robert #endif 476c0b746e5SOllivier Robert 477c0b746e5SOllivier Robert if (connect(sockfd, (struct sockaddr *)&hostaddr, 478c0b746e5SOllivier Robert sizeof(hostaddr)) == -1) 479c0b746e5SOllivier Robert error("connect", "", ""); 480c0b746e5SOllivier Robert 481c0b746e5SOllivier Robert havehost = 1; 482ce265a54SOllivier Robert req_pkt_size = REQ_LEN_NOMAC; 483c0b746e5SOllivier Robert return 1; 484c0b746e5SOllivier Robert } 485c0b746e5SOllivier Robert 486c0b746e5SOllivier Robert 487c0b746e5SOllivier Robert /* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */ 488c0b746e5SOllivier Robert /* 489c0b746e5SOllivier Robert * sendpkt - send a packet to the remote host 490c0b746e5SOllivier Robert */ 491c0b746e5SOllivier Robert static int 492c0b746e5SOllivier Robert sendpkt( 493c0b746e5SOllivier Robert char *xdata, 494c0b746e5SOllivier Robert int xdatalen 495c0b746e5SOllivier Robert ) 496c0b746e5SOllivier Robert { 497224ba2bdSOllivier Robert if (send(sockfd, xdata, (size_t)xdatalen, 0) == -1) { 498c0b746e5SOllivier Robert warning("write to %s failed", currenthost, ""); 499c0b746e5SOllivier Robert return -1; 500c0b746e5SOllivier Robert } 501c0b746e5SOllivier Robert 502c0b746e5SOllivier Robert return 0; 503c0b746e5SOllivier Robert } 504c0b746e5SOllivier Robert 505c0b746e5SOllivier Robert 506c0b746e5SOllivier Robert /* 507c0b746e5SOllivier Robert * growpktdata - grow the packet data area 508c0b746e5SOllivier Robert */ 509c0b746e5SOllivier Robert static void 510c0b746e5SOllivier Robert growpktdata(void) 511c0b746e5SOllivier Robert { 512c0b746e5SOllivier Robert pktdatasize += INCDATASIZE; 513c0b746e5SOllivier Robert pktdata = (char *)realloc(pktdata, (unsigned)pktdatasize); 514c0b746e5SOllivier Robert if (pktdata == 0) { 515c0b746e5SOllivier Robert (void) fprintf(stderr, "%s: realloc() failed!\n", progname); 516c0b746e5SOllivier Robert exit(1); 517c0b746e5SOllivier Robert } 518c0b746e5SOllivier Robert } 519c0b746e5SOllivier Robert 520c0b746e5SOllivier Robert 521c0b746e5SOllivier Robert /* 522c0b746e5SOllivier Robert * getresponse - get a (series of) response packet(s) and return the data 523c0b746e5SOllivier Robert */ 524c0b746e5SOllivier Robert static int 525c0b746e5SOllivier Robert getresponse( 526c0b746e5SOllivier Robert int implcode, 527c0b746e5SOllivier Robert int reqcode, 528c0b746e5SOllivier Robert int *ritems, 529c0b746e5SOllivier Robert int *rsize, 530c0b746e5SOllivier Robert char **rdata 531c0b746e5SOllivier Robert ) 532c0b746e5SOllivier Robert { 533c0b746e5SOllivier Robert struct resp_pkt rpkt; 534c0b746e5SOllivier Robert struct timeval tvo; 535c0b746e5SOllivier Robert int items; 536c0b746e5SOllivier Robert int size; 537c0b746e5SOllivier Robert int datasize; 538c0b746e5SOllivier Robert char *datap; 539c0b746e5SOllivier Robert char haveseq[MAXSEQ+1]; 540c0b746e5SOllivier Robert int firstpkt; 541c0b746e5SOllivier Robert int lastseq; 542c0b746e5SOllivier Robert int numrecv; 543c0b746e5SOllivier Robert int seq; 544c0b746e5SOllivier Robert fd_set fds; 545c0b746e5SOllivier Robert int n; 546c0b746e5SOllivier Robert 547c0b746e5SOllivier Robert /* 548c0b746e5SOllivier Robert * This is pretty tricky. We may get between 1 and many packets 549c0b746e5SOllivier Robert * back in response to the request. We peel the data out of 550c0b746e5SOllivier Robert * each packet and collect it in one long block. When the last 551c0b746e5SOllivier Robert * packet in the sequence is received we'll know how many we 552c0b746e5SOllivier Robert * should have had. Note we use one long time out, should reconsider. 553c0b746e5SOllivier Robert */ 554c0b746e5SOllivier Robert *ritems = 0; 555c0b746e5SOllivier Robert *rsize = 0; 556c0b746e5SOllivier Robert firstpkt = 1; 557c0b746e5SOllivier Robert numrecv = 0; 558c0b746e5SOllivier Robert *rdata = datap = pktdata; 559c0b746e5SOllivier Robert lastseq = 999; /* too big to be a sequence number */ 560c0b746e5SOllivier Robert memset(haveseq, 0, sizeof(haveseq)); 561c0b746e5SOllivier Robert FD_ZERO(&fds); 562c0b746e5SOllivier Robert 563c0b746e5SOllivier Robert again: 564c0b746e5SOllivier Robert if (firstpkt) 565c0b746e5SOllivier Robert tvo = tvout; 566c0b746e5SOllivier Robert else 567c0b746e5SOllivier Robert tvo = tvsout; 568c0b746e5SOllivier Robert 569c0b746e5SOllivier Robert FD_SET(sockfd, &fds); 570c0b746e5SOllivier Robert n = select(sockfd+1, &fds, (fd_set *)0, (fd_set *)0, &tvo); 571c0b746e5SOllivier Robert 572c0b746e5SOllivier Robert if (n == -1) { 573c0b746e5SOllivier Robert warning("select fails", "", ""); 574c0b746e5SOllivier Robert return -1; 575c0b746e5SOllivier Robert } 576c0b746e5SOllivier Robert if (n == 0) { 577c0b746e5SOllivier Robert /* 578c0b746e5SOllivier Robert * Timed out. Return what we have 579c0b746e5SOllivier Robert */ 580c0b746e5SOllivier Robert if (firstpkt) { 581c0b746e5SOllivier Robert (void) fprintf(stderr, 582c0b746e5SOllivier Robert "%s: timed out, nothing received\n", currenthost); 583c0b746e5SOllivier Robert return ERR_TIMEOUT; 584c0b746e5SOllivier Robert } else { 585c0b746e5SOllivier Robert (void) fprintf(stderr, 586c0b746e5SOllivier Robert "%s: timed out with incomplete data\n", 587c0b746e5SOllivier Robert currenthost); 588c0b746e5SOllivier Robert if (debug) { 589c0b746e5SOllivier Robert printf("Received sequence numbers"); 590c0b746e5SOllivier Robert for (n = 0; n <= MAXSEQ; n++) 591c0b746e5SOllivier Robert if (haveseq[n]) 592c0b746e5SOllivier Robert printf(" %d,", n); 593c0b746e5SOllivier Robert if (lastseq != 999) 594c0b746e5SOllivier Robert printf(" last frame received\n"); 595c0b746e5SOllivier Robert else 596c0b746e5SOllivier Robert printf(" last frame not received\n"); 597c0b746e5SOllivier Robert } 598c0b746e5SOllivier Robert return ERR_INCOMPLETE; 599c0b746e5SOllivier Robert } 600c0b746e5SOllivier Robert } 601c0b746e5SOllivier Robert 602c0b746e5SOllivier Robert n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0); 603c0b746e5SOllivier Robert if (n == -1) { 604c0b746e5SOllivier Robert warning("read", "", ""); 605c0b746e5SOllivier Robert return -1; 606c0b746e5SOllivier Robert } 607c0b746e5SOllivier Robert 608c0b746e5SOllivier Robert 609c0b746e5SOllivier Robert /* 610c0b746e5SOllivier Robert * Check for format errors. Bug proofing. 611c0b746e5SOllivier Robert */ 612c0b746e5SOllivier Robert if (n < RESP_HEADER_SIZE) { 613c0b746e5SOllivier Robert if (debug) 614c0b746e5SOllivier Robert printf("Short (%d byte) packet received\n", n); 615c0b746e5SOllivier Robert goto again; 616c0b746e5SOllivier Robert } 617c0b746e5SOllivier Robert if (INFO_VERSION(rpkt.rm_vn_mode) > NTP_VERSION || 618c0b746e5SOllivier Robert INFO_VERSION(rpkt.rm_vn_mode) < NTP_OLDVERSION) { 619c0b746e5SOllivier Robert if (debug) 620c0b746e5SOllivier Robert printf("Packet received with version %d\n", 621c0b746e5SOllivier Robert INFO_VERSION(rpkt.rm_vn_mode)); 622c0b746e5SOllivier Robert goto again; 623c0b746e5SOllivier Robert } 624c0b746e5SOllivier Robert if (INFO_MODE(rpkt.rm_vn_mode) != MODE_PRIVATE) { 625c0b746e5SOllivier Robert if (debug) 626c0b746e5SOllivier Robert printf("Packet received with mode %d\n", 627c0b746e5SOllivier Robert INFO_MODE(rpkt.rm_vn_mode)); 628c0b746e5SOllivier Robert goto again; 629c0b746e5SOllivier Robert } 630c0b746e5SOllivier Robert if (INFO_IS_AUTH(rpkt.auth_seq)) { 631c0b746e5SOllivier Robert if (debug) 632c0b746e5SOllivier Robert printf("Encrypted packet received\n"); 633c0b746e5SOllivier Robert goto again; 634c0b746e5SOllivier Robert } 635c0b746e5SOllivier Robert if (!ISRESPONSE(rpkt.rm_vn_mode)) { 636c0b746e5SOllivier Robert if (debug) 637c0b746e5SOllivier Robert printf("Received request packet, wanted response\n"); 638c0b746e5SOllivier Robert goto again; 639c0b746e5SOllivier Robert } 640c0b746e5SOllivier Robert if (INFO_MBZ(rpkt.mbz_itemsize) != 0) { 641c0b746e5SOllivier Robert if (debug) 642c0b746e5SOllivier Robert printf("Received packet with nonzero MBZ field!\n"); 643c0b746e5SOllivier Robert goto again; 644c0b746e5SOllivier Robert } 645c0b746e5SOllivier Robert 646c0b746e5SOllivier Robert /* 647c0b746e5SOllivier Robert * Check implementation/request. Could be old data getting to us. 648c0b746e5SOllivier Robert */ 649c0b746e5SOllivier Robert if (rpkt.implementation != implcode || rpkt.request != reqcode) { 650c0b746e5SOllivier Robert if (debug) 651c0b746e5SOllivier Robert printf( 652c0b746e5SOllivier Robert "Received implementation/request of %d/%d, wanted %d/%d", 653c0b746e5SOllivier Robert rpkt.implementation, rpkt.request, 654c0b746e5SOllivier Robert implcode, reqcode); 655c0b746e5SOllivier Robert goto again; 656c0b746e5SOllivier Robert } 657c0b746e5SOllivier Robert 658c0b746e5SOllivier Robert /* 659c0b746e5SOllivier Robert * Check the error code. If non-zero, return it. 660c0b746e5SOllivier Robert */ 661c0b746e5SOllivier Robert if (INFO_ERR(rpkt.err_nitems) != INFO_OKAY) { 662c0b746e5SOllivier Robert if (debug && ISMORE(rpkt.rm_vn_mode)) { 663c0b746e5SOllivier Robert printf("Error code %d received on not-final packet\n", 664c0b746e5SOllivier Robert INFO_ERR(rpkt.err_nitems)); 665c0b746e5SOllivier Robert } 666c0b746e5SOllivier Robert return (int)INFO_ERR(rpkt.err_nitems); 667c0b746e5SOllivier Robert } 668c0b746e5SOllivier Robert 669c0b746e5SOllivier Robert 670c0b746e5SOllivier Robert /* 671c0b746e5SOllivier Robert * Collect items and size. Make sure they make sense. 672c0b746e5SOllivier Robert */ 673c0b746e5SOllivier Robert items = INFO_NITEMS(rpkt.err_nitems); 674c0b746e5SOllivier Robert size = INFO_ITEMSIZE(rpkt.mbz_itemsize); 675c0b746e5SOllivier Robert 676c0b746e5SOllivier Robert if ((datasize = items*size) > (n-RESP_HEADER_SIZE)) { 677c0b746e5SOllivier Robert if (debug) 678c0b746e5SOllivier Robert printf( 679c0b746e5SOllivier Robert "Received items %d, size %d (total %d), data in packet is %d\n", 680c0b746e5SOllivier Robert items, size, datasize, n-RESP_HEADER_SIZE); 681c0b746e5SOllivier Robert goto again; 682c0b746e5SOllivier Robert } 683c0b746e5SOllivier Robert 684c0b746e5SOllivier Robert /* 685c0b746e5SOllivier Robert * If this isn't our first packet, make sure the size matches 686c0b746e5SOllivier Robert * the other ones. 687c0b746e5SOllivier Robert */ 688c0b746e5SOllivier Robert if (!firstpkt && size != *rsize) { 689c0b746e5SOllivier Robert if (debug) 690c0b746e5SOllivier Robert printf("Received itemsize %d, previous %d\n", 691c0b746e5SOllivier Robert size, *rsize); 692c0b746e5SOllivier Robert goto again; 693c0b746e5SOllivier Robert } 694c0b746e5SOllivier Robert 695c0b746e5SOllivier Robert /* 696c0b746e5SOllivier Robert * If we've received this before, toss it 697c0b746e5SOllivier Robert */ 698c0b746e5SOllivier Robert seq = INFO_SEQ(rpkt.auth_seq); 699c0b746e5SOllivier Robert if (haveseq[seq]) { 700c0b746e5SOllivier Robert if (debug) 701c0b746e5SOllivier Robert printf("Received duplicate sequence number %d\n", seq); 702c0b746e5SOllivier Robert goto again; 703c0b746e5SOllivier Robert } 704c0b746e5SOllivier Robert haveseq[seq] = 1; 705c0b746e5SOllivier Robert 706c0b746e5SOllivier Robert /* 707c0b746e5SOllivier Robert * If this is the last in the sequence, record that. 708c0b746e5SOllivier Robert */ 709c0b746e5SOllivier Robert if (!ISMORE(rpkt.rm_vn_mode)) { 710c0b746e5SOllivier Robert if (lastseq != 999) { 711c0b746e5SOllivier Robert printf("Received second end sequence packet\n"); 712c0b746e5SOllivier Robert goto again; 713c0b746e5SOllivier Robert } 714c0b746e5SOllivier Robert lastseq = seq; 715c0b746e5SOllivier Robert } 716c0b746e5SOllivier Robert 717c0b746e5SOllivier Robert /* 718c0b746e5SOllivier Robert * So far, so good. Copy this data into the output array. 719c0b746e5SOllivier Robert */ 720c0b746e5SOllivier Robert if ((datap + datasize) > (pktdata + pktdatasize)) { 721c0b746e5SOllivier Robert int offset = datap - pktdata; 722c0b746e5SOllivier Robert growpktdata(); 723c0b746e5SOllivier Robert *rdata = pktdata; /* might have been realloced ! */ 724c0b746e5SOllivier Robert datap = pktdata + offset; 725c0b746e5SOllivier Robert } 726c0b746e5SOllivier Robert memmove(datap, (char *)rpkt.data, (unsigned)datasize); 727c0b746e5SOllivier Robert datap += datasize; 728c0b746e5SOllivier Robert if (firstpkt) { 729c0b746e5SOllivier Robert firstpkt = 0; 730c0b746e5SOllivier Robert *rsize = size; 731c0b746e5SOllivier Robert } 732c0b746e5SOllivier Robert *ritems += items; 733c0b746e5SOllivier Robert 734c0b746e5SOllivier Robert /* 735c0b746e5SOllivier Robert * Finally, check the count of received packets. If we've got them 736c0b746e5SOllivier Robert * all, return 737c0b746e5SOllivier Robert */ 738c0b746e5SOllivier Robert ++numrecv; 739c0b746e5SOllivier Robert if (numrecv <= lastseq) 740c0b746e5SOllivier Robert goto again; 741c0b746e5SOllivier Robert return INFO_OKAY; 742c0b746e5SOllivier Robert } 743c0b746e5SOllivier Robert 744c0b746e5SOllivier Robert 745c0b746e5SOllivier Robert /* 746c0b746e5SOllivier Robert * sendrequest - format and send a request packet 747c0b746e5SOllivier Robert */ 748c0b746e5SOllivier Robert static int 749c0b746e5SOllivier Robert sendrequest( 750c0b746e5SOllivier Robert int implcode, 751c0b746e5SOllivier Robert int reqcode, 752c0b746e5SOllivier Robert int auth, 753c0b746e5SOllivier Robert int qitems, 754c0b746e5SOllivier Robert int qsize, 755c0b746e5SOllivier Robert char *qdata 756c0b746e5SOllivier Robert ) 757c0b746e5SOllivier Robert { 758c0b746e5SOllivier Robert struct req_pkt qpkt; 759c0b746e5SOllivier Robert int datasize; 760c0b746e5SOllivier Robert 761c0b746e5SOllivier Robert memset((char *)&qpkt, 0, sizeof qpkt); 762c0b746e5SOllivier Robert 763c0b746e5SOllivier Robert qpkt.rm_vn_mode = RM_VN_MODE(0, 0, 0); 764c0b746e5SOllivier Robert qpkt.implementation = (u_char)implcode; 765c0b746e5SOllivier Robert qpkt.request = (u_char)reqcode; 766c0b746e5SOllivier Robert 767c0b746e5SOllivier Robert datasize = qitems * qsize; 768c0b746e5SOllivier Robert if (datasize != 0 && qdata != NULL) { 769c0b746e5SOllivier Robert memmove((char *)qpkt.data, qdata, (unsigned)datasize); 770c0b746e5SOllivier Robert qpkt.err_nitems = ERR_NITEMS(0, qitems); 771c0b746e5SOllivier Robert qpkt.mbz_itemsize = MBZ_ITEMSIZE(qsize); 772c0b746e5SOllivier Robert } else { 773c0b746e5SOllivier Robert qpkt.err_nitems = ERR_NITEMS(0, 0); 774c0b746e5SOllivier Robert qpkt.mbz_itemsize = MBZ_ITEMSIZE(0); 775c0b746e5SOllivier Robert } 776c0b746e5SOllivier Robert 777c0b746e5SOllivier Robert if (!auth) { 778c0b746e5SOllivier Robert qpkt.auth_seq = AUTH_SEQ(0, 0); 779ce265a54SOllivier Robert return sendpkt((char *)&qpkt, req_pkt_size); 780c0b746e5SOllivier Robert } else { 781c0b746e5SOllivier Robert l_fp ts; 782c0b746e5SOllivier Robert int maclen = 0; 783c0b746e5SOllivier Robert const char *pass = "\0"; 784ce265a54SOllivier Robert struct req_pkt_tail *qpktail; 785ce265a54SOllivier Robert 786ce265a54SOllivier Robert qpktail = (struct req_pkt_tail *)((char *)&qpkt + req_pkt_size 787ce265a54SOllivier Robert + MAX_MAC_LEN - sizeof(struct req_pkt_tail)); 788c0b746e5SOllivier Robert 789c0b746e5SOllivier Robert if (info_auth_keyid == 0) { 790c0b746e5SOllivier Robert maclen = getkeyid("Keyid: "); 791c0b746e5SOllivier Robert if (maclen == 0) { 792c0b746e5SOllivier Robert (void) fprintf(stderr, 793c0b746e5SOllivier Robert "Invalid key identifier\n"); 794c0b746e5SOllivier Robert return 1; 795c0b746e5SOllivier Robert } 796c0b746e5SOllivier Robert info_auth_keyid = maclen; 797c0b746e5SOllivier Robert } 798c0b746e5SOllivier Robert if (!authistrusted(info_auth_keyid)) { 799c0b746e5SOllivier Robert pass = getpass((info_auth_keytype == KEY_TYPE_DES) 800c0b746e5SOllivier Robert ? "DES Password: " : "MD5 Password: "); 801c0b746e5SOllivier Robert if (*pass == '\0') { 802c0b746e5SOllivier Robert (void) fprintf(stderr, 803c0b746e5SOllivier Robert "Invalid password\n"); 804c0b746e5SOllivier Robert return (1); 805c0b746e5SOllivier Robert } 806c0b746e5SOllivier Robert } 807c0b746e5SOllivier Robert authusekey(info_auth_keyid, info_auth_keytype, (const u_char *)pass); 808c0b746e5SOllivier Robert authtrust(info_auth_keyid, 1); 809c0b746e5SOllivier Robert qpkt.auth_seq = AUTH_SEQ(1, 0); 810ce265a54SOllivier Robert qpktail->keyid = htonl(info_auth_keyid); 811c0b746e5SOllivier Robert get_systime(&ts); 812c0b746e5SOllivier Robert L_ADD(&ts, &delay_time); 813ce265a54SOllivier Robert HTONL_FP(&ts, &qpktail->tstamp); 814c0b746e5SOllivier Robert maclen = authencrypt(info_auth_keyid, (u_int32 *)&qpkt, 815ce265a54SOllivier Robert req_pkt_size); 816c0b746e5SOllivier Robert if (maclen == 0) { 817c0b746e5SOllivier Robert (void) fprintf(stderr, "Key not found\n"); 818c0b746e5SOllivier Robert return (1); 819c0b746e5SOllivier Robert } 820ce265a54SOllivier Robert return sendpkt((char *)&qpkt, (int)(req_pkt_size + maclen)); 821c0b746e5SOllivier Robert } 822c0b746e5SOllivier Robert /*NOTREACHED*/ 823c0b746e5SOllivier Robert } 824c0b746e5SOllivier Robert 825c0b746e5SOllivier Robert 826c0b746e5SOllivier Robert /* 827c0b746e5SOllivier Robert * doquery - send a request and process the response 828c0b746e5SOllivier Robert */ 829c0b746e5SOllivier Robert int 830c0b746e5SOllivier Robert doquery( 831c0b746e5SOllivier Robert int implcode, 832c0b746e5SOllivier Robert int reqcode, 833c0b746e5SOllivier Robert int auth, 834c0b746e5SOllivier Robert int qitems, 835c0b746e5SOllivier Robert int qsize, 836c0b746e5SOllivier Robert char *qdata, 837c0b746e5SOllivier Robert int *ritems, 838c0b746e5SOllivier Robert int *rsize, 839c0b746e5SOllivier Robert char **rdata, 840c0b746e5SOllivier Robert int quiet_mask 841c0b746e5SOllivier Robert ) 842c0b746e5SOllivier Robert { 843c0b746e5SOllivier Robert int res; 844c0b746e5SOllivier Robert char junk[512]; 845c0b746e5SOllivier Robert fd_set fds; 846c0b746e5SOllivier Robert struct timeval tvzero; 847c0b746e5SOllivier Robert 848c0b746e5SOllivier Robert /* 849c0b746e5SOllivier Robert * Check to make sure host is open 850c0b746e5SOllivier Robert */ 851c0b746e5SOllivier Robert if (!havehost) { 852c0b746e5SOllivier Robert (void) fprintf(stderr, "***No host open, use `host' command\n"); 853c0b746e5SOllivier Robert return -1; 854c0b746e5SOllivier Robert } 855c0b746e5SOllivier Robert 856c0b746e5SOllivier Robert /* 857c0b746e5SOllivier Robert * Poll the socket and clear out any pending data 858c0b746e5SOllivier Robert */ 859ce265a54SOllivier Robert again: 860c0b746e5SOllivier Robert do { 861c0b746e5SOllivier Robert tvzero.tv_sec = tvzero.tv_usec = 0; 862c0b746e5SOllivier Robert FD_ZERO(&fds); 863c0b746e5SOllivier Robert FD_SET(sockfd, &fds); 864c0b746e5SOllivier Robert res = select(sockfd+1, &fds, (fd_set *)0, (fd_set *)0, &tvzero); 865c0b746e5SOllivier Robert 866c0b746e5SOllivier Robert if (res == -1) { 867c0b746e5SOllivier Robert warning("polling select", "", ""); 868c0b746e5SOllivier Robert return -1; 869c0b746e5SOllivier Robert } else if (res > 0) 870c0b746e5SOllivier Robert 871c0b746e5SOllivier Robert (void) recv(sockfd, junk, sizeof junk, 0); 872c0b746e5SOllivier Robert } while (res > 0); 873c0b746e5SOllivier Robert 874c0b746e5SOllivier Robert 875c0b746e5SOllivier Robert /* 876c0b746e5SOllivier Robert * send a request 877c0b746e5SOllivier Robert */ 878c0b746e5SOllivier Robert res = sendrequest(implcode, reqcode, auth, qitems, qsize, qdata); 879c0b746e5SOllivier Robert if (res != 0) 880c0b746e5SOllivier Robert return res; 881c0b746e5SOllivier Robert 882c0b746e5SOllivier Robert /* 883c0b746e5SOllivier Robert * Get the response. If we got a standard error, print a message 884c0b746e5SOllivier Robert */ 885c0b746e5SOllivier Robert res = getresponse(implcode, reqcode, ritems, rsize, rdata); 886c0b746e5SOllivier Robert 887ce265a54SOllivier Robert /* 888ce265a54SOllivier Robert * Try to be compatible with older implementations of ntpd. 889ce265a54SOllivier Robert */ 890ce265a54SOllivier Robert if (res == INFO_ERR_FMT && req_pkt_size != 48) { 891ce265a54SOllivier Robert int oldsize; 892ce265a54SOllivier Robert 893ce265a54SOllivier Robert oldsize = req_pkt_size; 894ce265a54SOllivier Robert 895ce265a54SOllivier Robert switch(req_pkt_size) { 896ce265a54SOllivier Robert case REQ_LEN_NOMAC: 897ce265a54SOllivier Robert req_pkt_size = 48; 898ce265a54SOllivier Robert break; 899ce265a54SOllivier Robert } 900ce265a54SOllivier Robert 901ce265a54SOllivier Robert fprintf(stderr, 902ce265a54SOllivier Robert "***Warning changing the request packet size from %d to %d\n", 903ce265a54SOllivier Robert oldsize, req_pkt_size); 904ce265a54SOllivier Robert goto again; 905ce265a54SOllivier Robert } 906ce265a54SOllivier Robert 907c0b746e5SOllivier Robert /* log error message if not told to be quiet */ 908c0b746e5SOllivier Robert if ((res > 0) && (((1 << res) & quiet_mask) == 0)) { 909c0b746e5SOllivier Robert switch(res) { 910c0b746e5SOllivier Robert case INFO_ERR_IMPL: 911c0b746e5SOllivier Robert (void) fprintf(stderr, 912c0b746e5SOllivier Robert "***Server implementation incompatable with our own\n"); 913c0b746e5SOllivier Robert break; 914c0b746e5SOllivier Robert case INFO_ERR_REQ: 915c0b746e5SOllivier Robert (void) fprintf(stderr, 916c0b746e5SOllivier Robert "***Server doesn't implement this request\n"); 917c0b746e5SOllivier Robert break; 918c0b746e5SOllivier Robert case INFO_ERR_FMT: 919c0b746e5SOllivier Robert (void) fprintf(stderr, 920c0b746e5SOllivier Robert "***Server reports a format error in the received packet (shouldn't happen)\n"); 921c0b746e5SOllivier Robert break; 922c0b746e5SOllivier Robert case INFO_ERR_NODATA: 923c0b746e5SOllivier Robert (void) fprintf(stderr, 924c0b746e5SOllivier Robert "***Server reports data not found\n"); 925c0b746e5SOllivier Robert break; 926c0b746e5SOllivier Robert case INFO_ERR_AUTH: 927c0b746e5SOllivier Robert (void) fprintf(stderr, "***Permission denied\n"); 928c0b746e5SOllivier Robert break; 929c0b746e5SOllivier Robert case ERR_TIMEOUT: 930c0b746e5SOllivier Robert (void) fprintf(stderr, "***Request timed out\n"); 931c0b746e5SOllivier Robert break; 932c0b746e5SOllivier Robert case ERR_INCOMPLETE: 933c0b746e5SOllivier Robert (void) fprintf(stderr, 934c0b746e5SOllivier Robert "***Response from server was incomplete\n"); 935c0b746e5SOllivier Robert break; 936c0b746e5SOllivier Robert default: 937c0b746e5SOllivier Robert (void) fprintf(stderr, 938c0b746e5SOllivier Robert "***Server returns unknown error code %d\n", res); 939c0b746e5SOllivier Robert break; 940c0b746e5SOllivier Robert } 941c0b746e5SOllivier Robert } 942c0b746e5SOllivier Robert return res; 943c0b746e5SOllivier Robert } 944c0b746e5SOllivier Robert 945c0b746e5SOllivier Robert 946c0b746e5SOllivier Robert /* 947c0b746e5SOllivier Robert * getcmds - read commands from the standard input and execute them 948c0b746e5SOllivier Robert */ 949c0b746e5SOllivier Robert static void 950c0b746e5SOllivier Robert getcmds(void) 951c0b746e5SOllivier Robert { 952224ba2bdSOllivier Robert #ifdef HAVE_LIBREADLINE 953224ba2bdSOllivier Robert char *line; 954224ba2bdSOllivier Robert 955224ba2bdSOllivier Robert for (;;) { 956224ba2bdSOllivier Robert if ((line = readline(interactive?prompt:"")) == NULL) return; 957224ba2bdSOllivier Robert if (*line) add_history(line); 958224ba2bdSOllivier Robert docmd(line); 959224ba2bdSOllivier Robert free(line); 960224ba2bdSOllivier Robert } 961224ba2bdSOllivier Robert #else /* not HAVE_LIBREADLINE */ 962c0b746e5SOllivier Robert char line[MAXLINE]; 963c0b746e5SOllivier Robert 964c0b746e5SOllivier Robert for (;;) { 965c0b746e5SOllivier Robert if (interactive) { 966c0b746e5SOllivier Robert #ifdef VMS /* work around a problem with mixing stdout & stderr */ 967c0b746e5SOllivier Robert fputs("",stdout); 968c0b746e5SOllivier Robert #endif 969c0b746e5SOllivier Robert (void) fputs(prompt, stderr); 970c0b746e5SOllivier Robert (void) fflush(stderr); 971c0b746e5SOllivier Robert } 972c0b746e5SOllivier Robert 973c0b746e5SOllivier Robert if (fgets(line, sizeof line, stdin) == NULL) 974c0b746e5SOllivier Robert return; 975c0b746e5SOllivier Robert 976c0b746e5SOllivier Robert docmd(line); 977c0b746e5SOllivier Robert } 978224ba2bdSOllivier Robert #endif /* not HAVE_LIBREADLINE */ 979c0b746e5SOllivier Robert } 980c0b746e5SOllivier Robert 981c0b746e5SOllivier Robert 982c0b746e5SOllivier Robert /* 983c0b746e5SOllivier Robert * abortcmd - catch interrupts and abort the current command 984c0b746e5SOllivier Robert */ 985c0b746e5SOllivier Robert static RETSIGTYPE 986c0b746e5SOllivier Robert abortcmd( 987c0b746e5SOllivier Robert int sig 988c0b746e5SOllivier Robert ) 989c0b746e5SOllivier Robert { 990c0b746e5SOllivier Robert 991c0b746e5SOllivier Robert if (current_output == stdout) 992c0b746e5SOllivier Robert (void) fflush(stdout); 993c0b746e5SOllivier Robert putc('\n', stderr); 994c0b746e5SOllivier Robert (void) fflush(stderr); 995c0b746e5SOllivier Robert if (jump) longjmp(interrupt_buf, 1); 996c0b746e5SOllivier Robert } 997c0b746e5SOllivier Robert 998c0b746e5SOllivier Robert 999c0b746e5SOllivier Robert /* 1000c0b746e5SOllivier Robert * docmd - decode the command line and execute a command 1001c0b746e5SOllivier Robert */ 1002c0b746e5SOllivier Robert static void 1003c0b746e5SOllivier Robert docmd( 1004c0b746e5SOllivier Robert const char *cmdline 1005c0b746e5SOllivier Robert ) 1006c0b746e5SOllivier Robert { 1007c0b746e5SOllivier Robert char *tokens[1+MAXARGS+2]; 1008c0b746e5SOllivier Robert struct parse pcmd; 1009c0b746e5SOllivier Robert int ntok; 1010c0b746e5SOllivier Robert static int i; 1011c0b746e5SOllivier Robert struct xcmd *xcmd; 1012c0b746e5SOllivier Robert 1013c0b746e5SOllivier Robert /* 1014c0b746e5SOllivier Robert * Tokenize the command line. If nothing on it, return. 1015c0b746e5SOllivier Robert */ 1016c0b746e5SOllivier Robert tokenize(cmdline, tokens, &ntok); 1017c0b746e5SOllivier Robert if (ntok == 0) 1018c0b746e5SOllivier Robert return; 1019c0b746e5SOllivier Robert 1020c0b746e5SOllivier Robert /* 1021c0b746e5SOllivier Robert * Find the appropriate command description. 1022c0b746e5SOllivier Robert */ 1023c0b746e5SOllivier Robert i = findcmd(tokens[0], builtins, opcmds, &xcmd); 1024c0b746e5SOllivier Robert if (i == 0) { 1025c0b746e5SOllivier Robert (void) fprintf(stderr, "***Command `%s' unknown\n", 1026c0b746e5SOllivier Robert tokens[0]); 1027c0b746e5SOllivier Robert return; 1028c0b746e5SOllivier Robert } else if (i >= 2) { 1029c0b746e5SOllivier Robert (void) fprintf(stderr, "***Command `%s' ambiguous\n", 1030c0b746e5SOllivier Robert tokens[0]); 1031c0b746e5SOllivier Robert return; 1032c0b746e5SOllivier Robert } 1033c0b746e5SOllivier Robert 1034c0b746e5SOllivier Robert /* 1035c0b746e5SOllivier Robert * Save the keyword, then walk through the arguments, interpreting 1036c0b746e5SOllivier Robert * as we go. 1037c0b746e5SOllivier Robert */ 1038c0b746e5SOllivier Robert pcmd.keyword = tokens[0]; 1039c0b746e5SOllivier Robert pcmd.nargs = 0; 1040c0b746e5SOllivier Robert for (i = 0; i < MAXARGS && xcmd->arg[i] != NO; i++) { 1041c0b746e5SOllivier Robert if ((i+1) >= ntok) { 1042c0b746e5SOllivier Robert if (!(xcmd->arg[i] & OPT)) { 1043c0b746e5SOllivier Robert printusage(xcmd, stderr); 1044c0b746e5SOllivier Robert return; 1045c0b746e5SOllivier Robert } 1046c0b746e5SOllivier Robert break; 1047c0b746e5SOllivier Robert } 1048c0b746e5SOllivier Robert if ((xcmd->arg[i] & OPT) && (*tokens[i+1] == '>')) 1049c0b746e5SOllivier Robert break; 1050c0b746e5SOllivier Robert if (!getarg(tokens[i+1], (int)xcmd->arg[i], &pcmd.argval[i])) 1051c0b746e5SOllivier Robert return; 1052c0b746e5SOllivier Robert pcmd.nargs++; 1053c0b746e5SOllivier Robert } 1054c0b746e5SOllivier Robert 1055c0b746e5SOllivier Robert i++; 1056c0b746e5SOllivier Robert if (i < ntok && *tokens[i] == '>') { 1057c0b746e5SOllivier Robert char *fname; 1058c0b746e5SOllivier Robert 1059c0b746e5SOllivier Robert if (*(tokens[i]+1) != '\0') 1060c0b746e5SOllivier Robert fname = tokens[i]+1; 1061c0b746e5SOllivier Robert else if ((i+1) < ntok) 1062c0b746e5SOllivier Robert fname = tokens[i+1]; 1063c0b746e5SOllivier Robert else { 1064c0b746e5SOllivier Robert (void) fprintf(stderr, "***No file for redirect\n"); 1065c0b746e5SOllivier Robert return; 1066c0b746e5SOllivier Robert } 1067c0b746e5SOllivier Robert 1068c0b746e5SOllivier Robert current_output = fopen(fname, "w"); 1069c0b746e5SOllivier Robert if (current_output == NULL) { 1070c0b746e5SOllivier Robert (void) fprintf(stderr, "***Error opening %s: ", fname); 1071c0b746e5SOllivier Robert perror(""); 1072c0b746e5SOllivier Robert return; 1073c0b746e5SOllivier Robert } 1074c0b746e5SOllivier Robert i = 1; /* flag we need a close */ 1075c0b746e5SOllivier Robert } else { 1076c0b746e5SOllivier Robert current_output = stdout; 1077c0b746e5SOllivier Robert i = 0; /* flag no close */ 1078c0b746e5SOllivier Robert } 1079c0b746e5SOllivier Robert 1080c0b746e5SOllivier Robert if (interactive && setjmp(interrupt_buf)) { 1081c0b746e5SOllivier Robert return; 1082c0b746e5SOllivier Robert } else { 1083c0b746e5SOllivier Robert jump = 1; 1084c0b746e5SOllivier Robert (xcmd->handler)(&pcmd, current_output); 1085c0b746e5SOllivier Robert jump = 0; 1086c0b746e5SOllivier Robert if (i) (void) fclose(current_output); 1087c0b746e5SOllivier Robert } 1088c0b746e5SOllivier Robert } 1089c0b746e5SOllivier Robert 1090c0b746e5SOllivier Robert 1091c0b746e5SOllivier Robert /* 1092c0b746e5SOllivier Robert * tokenize - turn a command line into tokens 1093c0b746e5SOllivier Robert */ 1094c0b746e5SOllivier Robert static void 1095c0b746e5SOllivier Robert tokenize( 1096c0b746e5SOllivier Robert const char *line, 1097c0b746e5SOllivier Robert char **tokens, 1098c0b746e5SOllivier Robert int *ntok 1099c0b746e5SOllivier Robert ) 1100c0b746e5SOllivier Robert { 1101c0b746e5SOllivier Robert register const char *cp; 1102c0b746e5SOllivier Robert register char *sp; 1103c0b746e5SOllivier Robert static char tspace[MAXLINE]; 1104c0b746e5SOllivier Robert 1105c0b746e5SOllivier Robert sp = tspace; 1106c0b746e5SOllivier Robert cp = line; 1107c0b746e5SOllivier Robert for (*ntok = 0; *ntok < MAXTOKENS; (*ntok)++) { 1108c0b746e5SOllivier Robert tokens[*ntok] = sp; 1109c0b746e5SOllivier Robert while (ISSPACE(*cp)) 1110c0b746e5SOllivier Robert cp++; 1111c0b746e5SOllivier Robert if (ISEOL(*cp)) 1112c0b746e5SOllivier Robert break; 1113c0b746e5SOllivier Robert do { 1114c0b746e5SOllivier Robert *sp++ = *cp++; 1115c0b746e5SOllivier Robert } while (!ISSPACE(*cp) && !ISEOL(*cp)); 1116c0b746e5SOllivier Robert 1117c0b746e5SOllivier Robert *sp++ = '\0'; 1118c0b746e5SOllivier Robert } 1119c0b746e5SOllivier Robert } 1120c0b746e5SOllivier Robert 1121c0b746e5SOllivier Robert 1122c0b746e5SOllivier Robert 1123c0b746e5SOllivier Robert /* 1124c0b746e5SOllivier Robert * findcmd - find a command in a command description table 1125c0b746e5SOllivier Robert */ 1126c0b746e5SOllivier Robert static int 1127c0b746e5SOllivier Robert findcmd( 1128c0b746e5SOllivier Robert register char *str, 1129c0b746e5SOllivier Robert struct xcmd *clist1, 1130c0b746e5SOllivier Robert struct xcmd *clist2, 1131c0b746e5SOllivier Robert struct xcmd **cmd 1132c0b746e5SOllivier Robert ) 1133c0b746e5SOllivier Robert { 1134c0b746e5SOllivier Robert register struct xcmd *cl; 1135c0b746e5SOllivier Robert register int clen; 1136c0b746e5SOllivier Robert int nmatch; 1137c0b746e5SOllivier Robert struct xcmd *nearmatch = NULL; 1138c0b746e5SOllivier Robert struct xcmd *clist; 1139c0b746e5SOllivier Robert 1140c0b746e5SOllivier Robert clen = strlen(str); 1141c0b746e5SOllivier Robert nmatch = 0; 1142c0b746e5SOllivier Robert if (clist1 != 0) 1143c0b746e5SOllivier Robert clist = clist1; 1144c0b746e5SOllivier Robert else if (clist2 != 0) 1145c0b746e5SOllivier Robert clist = clist2; 1146c0b746e5SOllivier Robert else 1147c0b746e5SOllivier Robert return 0; 1148c0b746e5SOllivier Robert 1149c0b746e5SOllivier Robert again: 1150c0b746e5SOllivier Robert for (cl = clist; cl->keyword != 0; cl++) { 1151c0b746e5SOllivier Robert /* do a first character check, for efficiency */ 1152c0b746e5SOllivier Robert if (*str != *(cl->keyword)) 1153c0b746e5SOllivier Robert continue; 1154c0b746e5SOllivier Robert if (strncmp(str, cl->keyword, (unsigned)clen) == 0) { 1155c0b746e5SOllivier Robert /* 1156c0b746e5SOllivier Robert * Could be extact match, could be approximate. 1157c0b746e5SOllivier Robert * Is exact if the length of the keyword is the 1158c0b746e5SOllivier Robert * same as the str. 1159c0b746e5SOllivier Robert */ 1160c0b746e5SOllivier Robert if (*((cl->keyword) + clen) == '\0') { 1161c0b746e5SOllivier Robert *cmd = cl; 1162c0b746e5SOllivier Robert return 1; 1163c0b746e5SOllivier Robert } 1164c0b746e5SOllivier Robert nmatch++; 1165c0b746e5SOllivier Robert nearmatch = cl; 1166c0b746e5SOllivier Robert } 1167c0b746e5SOllivier Robert } 1168c0b746e5SOllivier Robert 1169c0b746e5SOllivier Robert /* 1170c0b746e5SOllivier Robert * See if there is more to do. If so, go again. Sorry about the 1171c0b746e5SOllivier Robert * goto, too much looking at BSD sources... 1172c0b746e5SOllivier Robert */ 1173c0b746e5SOllivier Robert if (clist == clist1 && clist2 != 0) { 1174c0b746e5SOllivier Robert clist = clist2; 1175c0b746e5SOllivier Robert goto again; 1176c0b746e5SOllivier Robert } 1177c0b746e5SOllivier Robert 1178c0b746e5SOllivier Robert /* 1179c0b746e5SOllivier Robert * If we got extactly 1 near match, use it, else return number 1180c0b746e5SOllivier Robert * of matches. 1181c0b746e5SOllivier Robert */ 1182c0b746e5SOllivier Robert if (nmatch == 1) { 1183c0b746e5SOllivier Robert *cmd = nearmatch; 1184c0b746e5SOllivier Robert return 1; 1185c0b746e5SOllivier Robert } 1186c0b746e5SOllivier Robert return nmatch; 1187c0b746e5SOllivier Robert } 1188c0b746e5SOllivier Robert 1189c0b746e5SOllivier Robert 1190c0b746e5SOllivier Robert /* 1191c0b746e5SOllivier Robert * getarg - interpret an argument token 1192c0b746e5SOllivier Robert */ 1193c0b746e5SOllivier Robert static int 1194c0b746e5SOllivier Robert getarg( 1195c0b746e5SOllivier Robert char *str, 1196c0b746e5SOllivier Robert int code, 1197c0b746e5SOllivier Robert arg_v *argp 1198c0b746e5SOllivier Robert ) 1199c0b746e5SOllivier Robert { 1200c0b746e5SOllivier Robert int isneg; 1201c0b746e5SOllivier Robert char *cp, *np; 1202c0b746e5SOllivier Robert static const char *digits = "0123456789"; 1203c0b746e5SOllivier Robert 1204c0b746e5SOllivier Robert switch (code & ~OPT) { 1205c0b746e5SOllivier Robert case NTP_STR: 1206c0b746e5SOllivier Robert argp->string = str; 1207c0b746e5SOllivier Robert break; 1208c0b746e5SOllivier Robert case ADD: 1209c0b746e5SOllivier Robert if (!getnetnum(str, &(argp->netnum), (char *)0)) { 1210c0b746e5SOllivier Robert return 0; 1211c0b746e5SOllivier Robert } 1212c0b746e5SOllivier Robert break; 1213c0b746e5SOllivier Robert case INT: 1214c0b746e5SOllivier Robert case UINT: 1215c0b746e5SOllivier Robert isneg = 0; 1216c0b746e5SOllivier Robert np = str; 1217c0b746e5SOllivier Robert if (*np == '-') { 1218c0b746e5SOllivier Robert np++; 1219c0b746e5SOllivier Robert isneg = 1; 1220c0b746e5SOllivier Robert } 1221c0b746e5SOllivier Robert 1222c0b746e5SOllivier Robert argp->uval = 0; 1223c0b746e5SOllivier Robert do { 1224c0b746e5SOllivier Robert cp = strchr(digits, *np); 1225c0b746e5SOllivier Robert if (cp == NULL) { 1226c0b746e5SOllivier Robert (void) fprintf(stderr, 1227c0b746e5SOllivier Robert "***Illegal integer value %s\n", str); 1228c0b746e5SOllivier Robert return 0; 1229c0b746e5SOllivier Robert } 1230c0b746e5SOllivier Robert argp->uval *= 10; 1231c0b746e5SOllivier Robert argp->uval += (cp - digits); 1232c0b746e5SOllivier Robert } while (*(++np) != '\0'); 1233c0b746e5SOllivier Robert 1234c0b746e5SOllivier Robert if (isneg) { 1235c0b746e5SOllivier Robert if ((code & ~OPT) == UINT) { 1236c0b746e5SOllivier Robert (void) fprintf(stderr, 1237c0b746e5SOllivier Robert "***Value %s should be unsigned\n", str); 1238c0b746e5SOllivier Robert return 0; 1239c0b746e5SOllivier Robert } 1240c0b746e5SOllivier Robert argp->ival = -argp->ival; 1241c0b746e5SOllivier Robert } 1242c0b746e5SOllivier Robert break; 1243c0b746e5SOllivier Robert } 1244c0b746e5SOllivier Robert 1245c0b746e5SOllivier Robert return 1; 1246c0b746e5SOllivier Robert } 1247c0b746e5SOllivier Robert 1248c0b746e5SOllivier Robert 1249c0b746e5SOllivier Robert /* 1250c0b746e5SOllivier Robert * getnetnum - given a host name, return its net number 1251c0b746e5SOllivier Robert * and (optional) full name 1252c0b746e5SOllivier Robert */ 1253c0b746e5SOllivier Robert static int 1254c0b746e5SOllivier Robert getnetnum( 1255c0b746e5SOllivier Robert const char *hname, 1256c0b746e5SOllivier Robert u_int32 *num, 1257c0b746e5SOllivier Robert char *fullhost 1258c0b746e5SOllivier Robert ) 1259c0b746e5SOllivier Robert { 1260c0b746e5SOllivier Robert struct hostent *hp; 1261c0b746e5SOllivier Robert 1262c0b746e5SOllivier Robert if (decodenetnum(hname, num)) { 1263c0b746e5SOllivier Robert if (fullhost != 0) { 1264c0b746e5SOllivier Robert (void) sprintf(fullhost, 1265c0b746e5SOllivier Robert "%u.%u.%u.%u", (u_int)((htonl(*num)>>24)&0xff), 1266c0b746e5SOllivier Robert (u_int)((htonl(*num)>>16)&0xff), (u_int)((htonl(*num)>>8)&0xff), 1267c0b746e5SOllivier Robert (u_int)(htonl(*num)&0xff)); 1268c0b746e5SOllivier Robert } 1269c0b746e5SOllivier Robert return 1; 1270c0b746e5SOllivier Robert } else if ((hp = gethostbyname(hname)) != 0) { 1271c0b746e5SOllivier Robert memmove((char *)num, hp->h_addr, sizeof(u_int32)); 1272c0b746e5SOllivier Robert if (fullhost != 0) 1273c0b746e5SOllivier Robert (void) strcpy(fullhost, hp->h_name); 1274c0b746e5SOllivier Robert return 1; 1275c0b746e5SOllivier Robert } else { 1276c0b746e5SOllivier Robert (void) fprintf(stderr, "***Can't find host %s\n", hname); 1277c0b746e5SOllivier Robert return 0; 1278c0b746e5SOllivier Robert } 1279c0b746e5SOllivier Robert /*NOTREACHED*/ 1280c0b746e5SOllivier Robert } 1281c0b746e5SOllivier Robert 1282c0b746e5SOllivier Robert /* 1283c0b746e5SOllivier Robert * nntohost - convert network number to host name. This routine enforces 1284c0b746e5SOllivier Robert * the showhostnames setting. 1285c0b746e5SOllivier Robert */ 1286c0b746e5SOllivier Robert char * 1287c0b746e5SOllivier Robert nntohost( 1288c0b746e5SOllivier Robert u_int32 netnum 1289c0b746e5SOllivier Robert ) 1290c0b746e5SOllivier Robert { 1291c0b746e5SOllivier Robert if (!showhostnames) 1292c0b746e5SOllivier Robert return numtoa(netnum); 1293c0b746e5SOllivier Robert if ((ntohl(netnum) & REFCLOCK_MASK) == REFCLOCK_ADDR) 1294c0b746e5SOllivier Robert return refnumtoa(netnum); 1295c0b746e5SOllivier Robert return numtohost(netnum); 1296c0b746e5SOllivier Robert } 1297c0b746e5SOllivier Robert 1298c0b746e5SOllivier Robert 1299c0b746e5SOllivier Robert /* 1300c0b746e5SOllivier Robert * Finally, the built in command handlers 1301c0b746e5SOllivier Robert */ 1302c0b746e5SOllivier Robert 1303c0b746e5SOllivier Robert /* 1304c0b746e5SOllivier Robert * help - tell about commands, or details of a particular command 1305c0b746e5SOllivier Robert */ 1306c0b746e5SOllivier Robert static void 1307c0b746e5SOllivier Robert help( 1308c0b746e5SOllivier Robert struct parse *pcmd, 1309c0b746e5SOllivier Robert FILE *fp 1310c0b746e5SOllivier Robert ) 1311c0b746e5SOllivier Robert { 1312c0b746e5SOllivier Robert int i; 1313c0b746e5SOllivier Robert int n; 1314c0b746e5SOllivier Robert struct xcmd *xcp; 1315c0b746e5SOllivier Robert char *cmd; 1316c0b746e5SOllivier Robert const char *cmdsort[100]; 1317c0b746e5SOllivier Robert int length[100]; 1318c0b746e5SOllivier Robert int maxlength; 1319c0b746e5SOllivier Robert int numperline; 1320c0b746e5SOllivier Robert static const char *spaces = " "; /* 20 spaces */ 1321c0b746e5SOllivier Robert 1322c0b746e5SOllivier Robert if (pcmd->nargs == 0) { 1323c0b746e5SOllivier Robert n = 0; 1324c0b746e5SOllivier Robert for (xcp = builtins; xcp->keyword != 0; xcp++) { 1325c0b746e5SOllivier Robert if (*(xcp->keyword) != '?') 1326c0b746e5SOllivier Robert cmdsort[n++] = xcp->keyword; 1327c0b746e5SOllivier Robert } 1328c0b746e5SOllivier Robert for (xcp = opcmds; xcp->keyword != 0; xcp++) 1329c0b746e5SOllivier Robert cmdsort[n++] = xcp->keyword; 1330c0b746e5SOllivier Robert 1331c0b746e5SOllivier Robert #ifdef QSORT_USES_VOID_P 1332224ba2bdSOllivier Robert qsort(cmdsort, (size_t)n, sizeof(char *), helpsort); 1333c0b746e5SOllivier Robert #else 1334224ba2bdSOllivier Robert qsort((char *)cmdsort, (size_t)n, sizeof(char *), helpsort); 1335c0b746e5SOllivier Robert #endif 1336c0b746e5SOllivier Robert 1337c0b746e5SOllivier Robert maxlength = 0; 1338c0b746e5SOllivier Robert for (i = 0; i < n; i++) { 1339c0b746e5SOllivier Robert length[i] = strlen(cmdsort[i]); 1340c0b746e5SOllivier Robert if (length[i] > maxlength) 1341c0b746e5SOllivier Robert maxlength = length[i]; 1342c0b746e5SOllivier Robert } 1343c0b746e5SOllivier Robert maxlength++; 1344c0b746e5SOllivier Robert numperline = 76 / maxlength; 1345c0b746e5SOllivier Robert 1346c0b746e5SOllivier Robert (void) fprintf(fp, "Commands available:\n"); 1347c0b746e5SOllivier Robert for (i = 0; i < n; i++) { 1348c0b746e5SOllivier Robert if ((i % numperline) == (numperline-1) 1349c0b746e5SOllivier Robert || i == (n-1)) 1350c0b746e5SOllivier Robert (void) fprintf(fp, "%s\n", cmdsort[i]); 1351c0b746e5SOllivier Robert else 1352c0b746e5SOllivier Robert (void) fprintf(fp, "%s%s", cmdsort[i], 1353c0b746e5SOllivier Robert spaces+20-maxlength+length[i]); 1354c0b746e5SOllivier Robert } 1355c0b746e5SOllivier Robert } else { 1356c0b746e5SOllivier Robert cmd = pcmd->argval[0].string; 1357c0b746e5SOllivier Robert n = findcmd(cmd, builtins, opcmds, &xcp); 1358c0b746e5SOllivier Robert if (n == 0) { 1359c0b746e5SOllivier Robert (void) fprintf(stderr, 1360c0b746e5SOllivier Robert "Command `%s' is unknown\n", cmd); 1361c0b746e5SOllivier Robert return; 1362c0b746e5SOllivier Robert } else if (n >= 2) { 1363c0b746e5SOllivier Robert (void) fprintf(stderr, 1364c0b746e5SOllivier Robert "Command `%s' is ambiguous\n", cmd); 1365c0b746e5SOllivier Robert return; 1366c0b746e5SOllivier Robert } 1367c0b746e5SOllivier Robert (void) fprintf(fp, "function: %s\n", xcp->comment); 1368c0b746e5SOllivier Robert printusage(xcp, fp); 1369c0b746e5SOllivier Robert } 1370c0b746e5SOllivier Robert } 1371c0b746e5SOllivier Robert 1372c0b746e5SOllivier Robert 1373c0b746e5SOllivier Robert /* 1374c0b746e5SOllivier Robert * helpsort - do hostname qsort comparisons 1375c0b746e5SOllivier Robert */ 1376c0b746e5SOllivier Robert #ifdef QSORT_USES_VOID_P 1377c0b746e5SOllivier Robert static int 1378c0b746e5SOllivier Robert helpsort( 1379c0b746e5SOllivier Robert const void *t1, 1380c0b746e5SOllivier Robert const void *t2 1381c0b746e5SOllivier Robert ) 1382c0b746e5SOllivier Robert { 1383c0b746e5SOllivier Robert const char **name1 = (const char **)t1; 1384c0b746e5SOllivier Robert const char **name2 = (const char **)t2; 1385c0b746e5SOllivier Robert 1386c0b746e5SOllivier Robert return strcmp(*name1, *name2); 1387c0b746e5SOllivier Robert } 1388c0b746e5SOllivier Robert #else 1389c0b746e5SOllivier Robert static int 1390c0b746e5SOllivier Robert helpsort( 1391c0b746e5SOllivier Robert char **name1, 1392c0b746e5SOllivier Robert char **name2 1393c0b746e5SOllivier Robert ) 1394c0b746e5SOllivier Robert { 1395c0b746e5SOllivier Robert return strcmp(*name1, *name2); 1396c0b746e5SOllivier Robert } 1397c0b746e5SOllivier Robert #endif 1398c0b746e5SOllivier Robert 1399c0b746e5SOllivier Robert 1400c0b746e5SOllivier Robert /* 1401c0b746e5SOllivier Robert * printusage - print usage information for a command 1402c0b746e5SOllivier Robert */ 1403c0b746e5SOllivier Robert static void 1404c0b746e5SOllivier Robert printusage( 1405c0b746e5SOllivier Robert struct xcmd *xcp, 1406c0b746e5SOllivier Robert FILE *fp 1407c0b746e5SOllivier Robert ) 1408c0b746e5SOllivier Robert { 1409c0b746e5SOllivier Robert register int i; 1410c0b746e5SOllivier Robert 1411c0b746e5SOllivier Robert (void) fprintf(fp, "usage: %s", xcp->keyword); 1412c0b746e5SOllivier Robert for (i = 0; i < MAXARGS && xcp->arg[i] != NO; i++) { 1413c0b746e5SOllivier Robert if (xcp->arg[i] & OPT) 1414c0b746e5SOllivier Robert (void) fprintf(fp, " [ %s ]", xcp->desc[i]); 1415c0b746e5SOllivier Robert else 1416c0b746e5SOllivier Robert (void) fprintf(fp, " %s", xcp->desc[i]); 1417c0b746e5SOllivier Robert } 1418c0b746e5SOllivier Robert (void) fprintf(fp, "\n"); 1419c0b746e5SOllivier Robert } 1420c0b746e5SOllivier Robert 1421c0b746e5SOllivier Robert 1422c0b746e5SOllivier Robert /* 1423c0b746e5SOllivier Robert * timeout - set time out time 1424c0b746e5SOllivier Robert */ 1425c0b746e5SOllivier Robert static void 1426c0b746e5SOllivier Robert timeout( 1427c0b746e5SOllivier Robert struct parse *pcmd, 1428c0b746e5SOllivier Robert FILE *fp 1429c0b746e5SOllivier Robert ) 1430c0b746e5SOllivier Robert { 1431c0b746e5SOllivier Robert int val; 1432c0b746e5SOllivier Robert 1433c0b746e5SOllivier Robert if (pcmd->nargs == 0) { 1434c0b746e5SOllivier Robert val = tvout.tv_sec * 1000 + tvout.tv_usec / 1000; 1435c0b746e5SOllivier Robert (void) fprintf(fp, "primary timeout %d ms\n", val); 1436c0b746e5SOllivier Robert } else { 1437c0b746e5SOllivier Robert tvout.tv_sec = pcmd->argval[0].uval / 1000; 1438c0b746e5SOllivier Robert tvout.tv_usec = (pcmd->argval[0].uval - (tvout.tv_sec * 1000)) 1439c0b746e5SOllivier Robert * 1000; 1440c0b746e5SOllivier Robert } 1441c0b746e5SOllivier Robert } 1442c0b746e5SOllivier Robert 1443c0b746e5SOllivier Robert 1444c0b746e5SOllivier Robert /* 1445c0b746e5SOllivier Robert * my_delay - set delay for auth requests 1446c0b746e5SOllivier Robert */ 1447c0b746e5SOllivier Robert static void 1448c0b746e5SOllivier Robert my_delay( 1449c0b746e5SOllivier Robert struct parse *pcmd, 1450c0b746e5SOllivier Robert FILE *fp 1451c0b746e5SOllivier Robert ) 1452c0b746e5SOllivier Robert { 1453c0b746e5SOllivier Robert int isneg; 1454c0b746e5SOllivier Robert u_long val; 1455c0b746e5SOllivier Robert 1456c0b746e5SOllivier Robert if (pcmd->nargs == 0) { 1457c0b746e5SOllivier Robert val = delay_time.l_ui * 1000 + delay_time.l_uf / 4294967; 1458c0b746e5SOllivier Robert (void) fprintf(fp, "delay %lu ms\n", val); 1459c0b746e5SOllivier Robert } else { 1460c0b746e5SOllivier Robert if (pcmd->argval[0].ival < 0) { 1461c0b746e5SOllivier Robert isneg = 1; 1462c0b746e5SOllivier Robert val = (u_long)(-pcmd->argval[0].ival); 1463c0b746e5SOllivier Robert } else { 1464c0b746e5SOllivier Robert isneg = 0; 1465c0b746e5SOllivier Robert val = (u_long)pcmd->argval[0].ival; 1466c0b746e5SOllivier Robert } 1467c0b746e5SOllivier Robert 1468c0b746e5SOllivier Robert delay_time.l_ui = val / 1000; 1469c0b746e5SOllivier Robert val %= 1000; 1470c0b746e5SOllivier Robert delay_time.l_uf = val * 4294967; /* 2**32/1000 */ 1471c0b746e5SOllivier Robert 1472c0b746e5SOllivier Robert if (isneg) 1473c0b746e5SOllivier Robert L_NEG(&delay_time); 1474c0b746e5SOllivier Robert } 1475c0b746e5SOllivier Robert } 1476c0b746e5SOllivier Robert 1477c0b746e5SOllivier Robert 1478c0b746e5SOllivier Robert /* 1479c0b746e5SOllivier Robert * host - set the host we are dealing with. 1480c0b746e5SOllivier Robert */ 1481c0b746e5SOllivier Robert static void 1482c0b746e5SOllivier Robert host( 1483c0b746e5SOllivier Robert struct parse *pcmd, 1484c0b746e5SOllivier Robert FILE *fp 1485c0b746e5SOllivier Robert ) 1486c0b746e5SOllivier Robert { 1487c0b746e5SOllivier Robert if (pcmd->nargs == 0) { 1488c0b746e5SOllivier Robert if (havehost) 1489c0b746e5SOllivier Robert (void) fprintf(fp, "current host is %s\n", currenthost); 1490c0b746e5SOllivier Robert else 1491c0b746e5SOllivier Robert (void) fprintf(fp, "no current host\n"); 1492c0b746e5SOllivier Robert } else if (openhost(pcmd->argval[0].string)) { 1493c0b746e5SOllivier Robert (void) fprintf(fp, "current host set to %s\n", currenthost); 1494c0b746e5SOllivier Robert } else { 1495c0b746e5SOllivier Robert if (havehost) 1496c0b746e5SOllivier Robert (void) fprintf(fp, 1497c0b746e5SOllivier Robert "current host remains %s\n", currenthost); 1498c0b746e5SOllivier Robert else 1499c0b746e5SOllivier Robert (void) fprintf(fp, "still no current host\n"); 1500c0b746e5SOllivier Robert } 1501c0b746e5SOllivier Robert } 1502c0b746e5SOllivier Robert 1503c0b746e5SOllivier Robert 1504c0b746e5SOllivier Robert /* 1505c0b746e5SOllivier Robert * keyid - get a keyid to use for authenticating requests 1506c0b746e5SOllivier Robert */ 1507c0b746e5SOllivier Robert static void 1508c0b746e5SOllivier Robert keyid( 1509c0b746e5SOllivier Robert struct parse *pcmd, 1510c0b746e5SOllivier Robert FILE *fp 1511c0b746e5SOllivier Robert ) 1512c0b746e5SOllivier Robert { 1513c0b746e5SOllivier Robert if (pcmd->nargs == 0) { 1514c0b746e5SOllivier Robert if (info_auth_keyid == 0) 1515c0b746e5SOllivier Robert (void) fprintf(fp, "no keyid defined\n"); 1516c0b746e5SOllivier Robert else 1517c0b746e5SOllivier Robert (void) fprintf(fp, "keyid is %lu\n", (u_long)info_auth_keyid); 1518c0b746e5SOllivier Robert } else { 1519c0b746e5SOllivier Robert info_auth_keyid = pcmd->argval[0].uval; 1520c0b746e5SOllivier Robert } 1521c0b746e5SOllivier Robert } 1522c0b746e5SOllivier Robert 1523c0b746e5SOllivier Robert 1524c0b746e5SOllivier Robert /* 1525c0b746e5SOllivier Robert * keytype - get type of key to use for authenticating requests 1526c0b746e5SOllivier Robert */ 1527c0b746e5SOllivier Robert static void 1528c0b746e5SOllivier Robert keytype( 1529c0b746e5SOllivier Robert struct parse *pcmd, 1530c0b746e5SOllivier Robert FILE *fp 1531c0b746e5SOllivier Robert ) 1532c0b746e5SOllivier Robert { 1533c0b746e5SOllivier Robert if (pcmd->nargs == 0) 1534c0b746e5SOllivier Robert fprintf(fp, "keytype is %s\n", 1535c0b746e5SOllivier Robert (info_auth_keytype == KEY_TYPE_MD5) ? "MD5" : "DES"); 1536c0b746e5SOllivier Robert else 1537c0b746e5SOllivier Robert switch (*(pcmd->argval[0].string)) { 1538c0b746e5SOllivier Robert case 'm': 1539c0b746e5SOllivier Robert case 'M': 1540c0b746e5SOllivier Robert info_auth_keytype = KEY_TYPE_MD5; 1541c0b746e5SOllivier Robert break; 1542c0b746e5SOllivier Robert 1543c0b746e5SOllivier Robert case 'd': 1544c0b746e5SOllivier Robert case 'D': 1545c0b746e5SOllivier Robert info_auth_keytype = KEY_TYPE_DES; 1546c0b746e5SOllivier Robert break; 1547c0b746e5SOllivier Robert 1548c0b746e5SOllivier Robert default: 1549c0b746e5SOllivier Robert fprintf(fp, "keytype must be 'md5' or 'des'\n"); 1550c0b746e5SOllivier Robert } 1551c0b746e5SOllivier Robert } 1552c0b746e5SOllivier Robert 1553c0b746e5SOllivier Robert 1554c0b746e5SOllivier Robert 1555c0b746e5SOllivier Robert /* 1556c0b746e5SOllivier Robert * passwd - get an authentication key 1557c0b746e5SOllivier Robert */ 1558c0b746e5SOllivier Robert /*ARGSUSED*/ 1559c0b746e5SOllivier Robert static void 1560c0b746e5SOllivier Robert passwd( 1561c0b746e5SOllivier Robert struct parse *pcmd, 1562c0b746e5SOllivier Robert FILE *fp 1563c0b746e5SOllivier Robert ) 1564c0b746e5SOllivier Robert { 1565c0b746e5SOllivier Robert char *pass; 1566c0b746e5SOllivier Robert 1567c0b746e5SOllivier Robert if (info_auth_keyid == 0) { 1568c0b746e5SOllivier Robert info_auth_keyid = getkeyid("Keyid: "); 1569c0b746e5SOllivier Robert if (info_auth_keyid == 0) { 1570c0b746e5SOllivier Robert (void)fprintf(fp, "Keyid must be defined\n"); 1571c0b746e5SOllivier Robert return; 1572c0b746e5SOllivier Robert } 1573c0b746e5SOllivier Robert } 1574c0b746e5SOllivier Robert if (!interactive) { 1575c0b746e5SOllivier Robert authusekey(info_auth_keyid, info_auth_keytype, 1576c0b746e5SOllivier Robert (u_char *)pcmd->argval[0].string); 1577224ba2bdSOllivier Robert authtrust(info_auth_keyid, 1); 1578c0b746e5SOllivier Robert } else { 1579c0b746e5SOllivier Robert pass = getpass((info_auth_keytype == KEY_TYPE_DES) 1580c0b746e5SOllivier Robert ? "DES Password: " 1581c0b746e5SOllivier Robert : "MD5 Password: " 1582c0b746e5SOllivier Robert ); 1583c0b746e5SOllivier Robert if (*pass == '\0') 1584c0b746e5SOllivier Robert (void) fprintf(fp, "Password unchanged\n"); 1585224ba2bdSOllivier Robert else { 1586c0b746e5SOllivier Robert authusekey(info_auth_keyid, info_auth_keytype, 1587c0b746e5SOllivier Robert (u_char *)pass); 1588224ba2bdSOllivier Robert authtrust(info_auth_keyid, 1); 1589224ba2bdSOllivier Robert } 1590c0b746e5SOllivier Robert } 1591c0b746e5SOllivier Robert } 1592c0b746e5SOllivier Robert 1593c0b746e5SOllivier Robert 1594c0b746e5SOllivier Robert /* 1595c0b746e5SOllivier Robert * hostnames - set the showhostnames flag 1596c0b746e5SOllivier Robert */ 1597c0b746e5SOllivier Robert static void 1598c0b746e5SOllivier Robert hostnames( 1599c0b746e5SOllivier Robert struct parse *pcmd, 1600c0b746e5SOllivier Robert FILE *fp 1601c0b746e5SOllivier Robert ) 1602c0b746e5SOllivier Robert { 1603c0b746e5SOllivier Robert if (pcmd->nargs == 0) { 1604c0b746e5SOllivier Robert if (showhostnames) 1605c0b746e5SOllivier Robert (void) fprintf(fp, "hostnames being shown\n"); 1606c0b746e5SOllivier Robert else 1607c0b746e5SOllivier Robert (void) fprintf(fp, "hostnames not being shown\n"); 1608c0b746e5SOllivier Robert } else { 1609c0b746e5SOllivier Robert if (STREQ(pcmd->argval[0].string, "yes")) 1610c0b746e5SOllivier Robert showhostnames = 1; 1611c0b746e5SOllivier Robert else if (STREQ(pcmd->argval[0].string, "no")) 1612c0b746e5SOllivier Robert showhostnames = 0; 1613c0b746e5SOllivier Robert else 1614c0b746e5SOllivier Robert (void)fprintf(stderr, "What?\n"); 1615c0b746e5SOllivier Robert } 1616c0b746e5SOllivier Robert } 1617c0b746e5SOllivier Robert 1618c0b746e5SOllivier Robert 1619c0b746e5SOllivier Robert /* 1620c0b746e5SOllivier Robert * setdebug - set/change debugging level 1621c0b746e5SOllivier Robert */ 1622c0b746e5SOllivier Robert static void 1623c0b746e5SOllivier Robert setdebug( 1624c0b746e5SOllivier Robert struct parse *pcmd, 1625c0b746e5SOllivier Robert FILE *fp 1626c0b746e5SOllivier Robert ) 1627c0b746e5SOllivier Robert { 1628c0b746e5SOllivier Robert if (pcmd->nargs == 0) { 1629c0b746e5SOllivier Robert (void) fprintf(fp, "debug level is %d\n", debug); 1630c0b746e5SOllivier Robert return; 1631c0b746e5SOllivier Robert } else if (STREQ(pcmd->argval[0].string, "no")) { 1632c0b746e5SOllivier Robert debug = 0; 1633c0b746e5SOllivier Robert } else if (STREQ(pcmd->argval[0].string, "more")) { 1634c0b746e5SOllivier Robert debug++; 1635c0b746e5SOllivier Robert } else if (STREQ(pcmd->argval[0].string, "less")) { 1636c0b746e5SOllivier Robert debug--; 1637c0b746e5SOllivier Robert } else { 1638c0b746e5SOllivier Robert (void) fprintf(fp, "What?\n"); 1639c0b746e5SOllivier Robert return; 1640c0b746e5SOllivier Robert } 1641c0b746e5SOllivier Robert (void) fprintf(fp, "debug level set to %d\n", debug); 1642c0b746e5SOllivier Robert } 1643c0b746e5SOllivier Robert 1644c0b746e5SOllivier Robert 1645c0b746e5SOllivier Robert /* 1646c0b746e5SOllivier Robert * quit - stop this nonsense 1647c0b746e5SOllivier Robert */ 1648c0b746e5SOllivier Robert /*ARGSUSED*/ 1649c0b746e5SOllivier Robert static void 1650c0b746e5SOllivier Robert quit( 1651c0b746e5SOllivier Robert struct parse *pcmd, 1652c0b746e5SOllivier Robert FILE *fp 1653c0b746e5SOllivier Robert ) 1654c0b746e5SOllivier Robert { 1655c0b746e5SOllivier Robert if (havehost) 1656c0b746e5SOllivier Robert closesocket(sockfd); 1657c0b746e5SOllivier Robert exit(0); 1658c0b746e5SOllivier Robert } 1659c0b746e5SOllivier Robert 1660c0b746e5SOllivier Robert 1661c0b746e5SOllivier Robert /* 1662c0b746e5SOllivier Robert * version - print the current version number 1663c0b746e5SOllivier Robert */ 1664c0b746e5SOllivier Robert /*ARGSUSED*/ 1665c0b746e5SOllivier Robert static void 1666c0b746e5SOllivier Robert version( 1667c0b746e5SOllivier Robert struct parse *pcmd, 1668c0b746e5SOllivier Robert FILE *fp 1669c0b746e5SOllivier Robert ) 1670c0b746e5SOllivier Robert { 1671c0b746e5SOllivier Robert 1672c0b746e5SOllivier Robert (void) fprintf(fp, "%s\n", Version); 1673c0b746e5SOllivier Robert return; 1674c0b746e5SOllivier Robert } 1675c0b746e5SOllivier Robert 1676c0b746e5SOllivier Robert 1677c0b746e5SOllivier Robert /* 1678c0b746e5SOllivier Robert * warning - print a warning message 1679c0b746e5SOllivier Robert */ 1680c0b746e5SOllivier Robert static void 1681c0b746e5SOllivier Robert warning( 1682c0b746e5SOllivier Robert const char *fmt, 1683c0b746e5SOllivier Robert const char *st1, 1684c0b746e5SOllivier Robert const char *st2 1685c0b746e5SOllivier Robert ) 1686c0b746e5SOllivier Robert { 1687c0b746e5SOllivier Robert (void) fprintf(stderr, "%s: ", progname); 1688c0b746e5SOllivier Robert (void) fprintf(stderr, fmt, st1, st2); 1689c0b746e5SOllivier Robert (void) fprintf(stderr, ": "); 1690c0b746e5SOllivier Robert perror(""); 1691c0b746e5SOllivier Robert } 1692c0b746e5SOllivier Robert 1693c0b746e5SOllivier Robert 1694c0b746e5SOllivier Robert /* 1695c0b746e5SOllivier Robert * error - print a message and exit 1696c0b746e5SOllivier Robert */ 1697c0b746e5SOllivier Robert static void 1698c0b746e5SOllivier Robert error( 1699c0b746e5SOllivier Robert const char *fmt, 1700c0b746e5SOllivier Robert const char *st1, 1701c0b746e5SOllivier Robert const char *st2 1702c0b746e5SOllivier Robert ) 1703c0b746e5SOllivier Robert { 1704c0b746e5SOllivier Robert warning(fmt, st1, st2); 1705c0b746e5SOllivier Robert exit(1); 1706c0b746e5SOllivier Robert } 1707c0b746e5SOllivier Robert 1708c0b746e5SOllivier Robert /* 1709c0b746e5SOllivier Robert * getkeyid - prompt the user for a keyid to use 1710c0b746e5SOllivier Robert */ 1711c0b746e5SOllivier Robert static u_long 1712c0b746e5SOllivier Robert getkeyid( 1713c0b746e5SOllivier Robert const char *keyprompt 1714c0b746e5SOllivier Robert ) 1715c0b746e5SOllivier Robert { 1716c0b746e5SOllivier Robert register char *p; 1717c0b746e5SOllivier Robert register int c; 1718c0b746e5SOllivier Robert FILE *fi; 1719c0b746e5SOllivier Robert char pbuf[20]; 1720c0b746e5SOllivier Robert 1721c0b746e5SOllivier Robert #ifndef SYS_WINNT 1722c0b746e5SOllivier Robert if ((fi = fdopen(open("/dev/tty", 2), "r")) == NULL) 1723c0b746e5SOllivier Robert #else 1724c0b746e5SOllivier Robert if ((fi = _fdopen((int)GetStdHandle(STD_INPUT_HANDLE), "r")) == NULL) 1725c0b746e5SOllivier Robert #endif /* SYS_WINNT */ 1726c0b746e5SOllivier Robert fi = stdin; 1727c0b746e5SOllivier Robert else 1728c0b746e5SOllivier Robert setbuf(fi, (char *)NULL); 1729c0b746e5SOllivier Robert fprintf(stderr, "%s", keyprompt); fflush(stderr); 1730c0b746e5SOllivier Robert for (p=pbuf; (c = getc(fi))!='\n' && c!=EOF;) { 1731c0b746e5SOllivier Robert if (p < &pbuf[18]) 1732c0b746e5SOllivier Robert *p++ = c; 1733c0b746e5SOllivier Robert } 1734c0b746e5SOllivier Robert *p = '\0'; 1735c0b746e5SOllivier Robert if (fi != stdin) 1736c0b746e5SOllivier Robert fclose(fi); 1737c0b746e5SOllivier Robert return (u_int32)atoi(pbuf); 1738c0b746e5SOllivier Robert } 1739