📄 ntpdc.c
字号:
else tvo = tvsout; FD_SET(sockfd, &fds); n = select(sockfd+1, &fds, (fd_set *)0, (fd_set *)0, &tvo); if (n == -1) { warning("select fails", "", ""); return -1; } if (n == 0) { /* * Timed out. Return what we have */ if (firstpkt) { (void) fprintf(stderr, "%s: timed out, nothing received\n", currenthost); return ERR_TIMEOUT; } else { (void) fprintf(stderr, "%s: timed out with incomplete data\n", currenthost); if (debug) { printf("Received sequence numbers"); for (n = 0; n <= MAXSEQ; n++) if (haveseq[n]) printf(" %d,", n); if (lastseq != 999) printf(" last frame received\n"); else printf(" last frame not received\n"); } return ERR_INCOMPLETE; } } n = recv(sockfd, (char *)&rpkt, sizeof(rpkt), 0); if (n == -1) { warning("read", "", ""); return -1; } /* * Check for format errors. Bug proofing. */ if (n < RESP_HEADER_SIZE) { if (debug) printf("Short (%d byte) packet received\n", n); goto again; } if (INFO_VERSION(rpkt.rm_vn_mode) > NTP_VERSION || INFO_VERSION(rpkt.rm_vn_mode) < NTP_OLDVERSION) { if (debug) printf("Packet received with version %d\n", INFO_VERSION(rpkt.rm_vn_mode)); goto again; } if (INFO_MODE(rpkt.rm_vn_mode) != MODE_PRIVATE) { if (debug) printf("Packet received with mode %d\n", INFO_MODE(rpkt.rm_vn_mode)); goto again; } if (INFO_IS_AUTH(rpkt.auth_seq)) { if (debug) printf("Encrypted packet received\n"); goto again; } if (!ISRESPONSE(rpkt.rm_vn_mode)) { if (debug) printf("Received request packet, wanted response\n"); goto again; } if (INFO_MBZ(rpkt.mbz_itemsize) != 0) { if (debug) printf("Received packet with nonzero MBZ field!\n"); goto again; } /* * Check implementation/request. Could be old data getting to us. */ if (rpkt.implementation != implcode || rpkt.request != reqcode) { if (debug) printf( "Received implementation/request of %d/%d, wanted %d/%d", rpkt.implementation, rpkt.request, implcode, reqcode); goto again; } /* * Check the error code. If non-zero, return it. */ if (INFO_ERR(rpkt.err_nitems) != INFO_OKAY) { if (debug && ISMORE(rpkt.rm_vn_mode)) { printf("Error code %d received on not-final packet\n", INFO_ERR(rpkt.err_nitems)); } return (int)INFO_ERR(rpkt.err_nitems); } /* * Collect items and size. Make sure they make sense. */ items = INFO_NITEMS(rpkt.err_nitems); size = INFO_ITEMSIZE(rpkt.mbz_itemsize); if (esize > size) pad = esize - size; else pad = 0; if ((datasize = items*size) > (n-RESP_HEADER_SIZE)) { if (debug) printf( "Received items %d, size %d (total %d), data in packet is %d\n", items, size, datasize, n-RESP_HEADER_SIZE); goto again; } /* * If this isn't our first packet, make sure the size matches * the other ones. */ if (!firstpkt && esize != *rsize) { if (debug) printf("Received itemsize %d, previous %d\n", size, *rsize); goto again; } /* * If we've received this before, +toss it */ seq = INFO_SEQ(rpkt.auth_seq); if (haveseq[seq]) { if (debug) printf("Received duplicate sequence number %d\n", seq); goto again; } haveseq[seq] = 1; /* * If this is the last in the sequence, record that. */ if (!ISMORE(rpkt.rm_vn_mode)) { if (lastseq != 999) { printf("Received second end sequence packet\n"); goto again; } lastseq = seq; } /* * So far, so good. Copy this data into the output array. */ if ((datap + datasize + (pad * items)) > (pktdata + pktdatasize)) { int offset = datap - pktdata; growpktdata(); *rdata = pktdata; /* might have been realloced ! */ datap = pktdata + offset; } /* * We now move the pointer along according to size and number of * items. This is so we can play nice with older implementations */ tmp_data = (char *)rpkt.data; for(i = 0; i <items; i++){ memmove(datap, tmp_data, (unsigned)size); tmp_data += size; memset(datap + size, 0, pad); datap += size + pad; } if (firstpkt) { firstpkt = 0; *rsize = size + pad; } *ritems += items; /* * Finally, check the count of received packets. If we've got them * all, return */ ++numrecv; if (numrecv <= lastseq) goto again; return INFO_OKAY;}/* * sendrequest - format and send a request packet */static intsendrequest( int implcode, int reqcode, int auth, int qitems, int qsize, char *qdata ){ struct req_pkt qpkt; int datasize; memset((char *)&qpkt, 0, sizeof qpkt); qpkt.rm_vn_mode = RM_VN_MODE(0, 0, 0); qpkt.implementation = (u_char)implcode; qpkt.request = (u_char)reqcode; datasize = qitems * qsize; if (datasize != 0 && qdata != NULL) { memmove((char *)qpkt.data, qdata, (unsigned)datasize); qpkt.err_nitems = ERR_NITEMS(0, qitems); qpkt.mbz_itemsize = MBZ_ITEMSIZE(qsize); } else { qpkt.err_nitems = ERR_NITEMS(0, 0); qpkt.mbz_itemsize = MBZ_ITEMSIZE(0); } if (!auth) { qpkt.auth_seq = AUTH_SEQ(0, 0); return sendpkt((char *)&qpkt, req_pkt_size); } else { l_fp ts; int maclen = 0; const char *pass = "\0"; struct req_pkt_tail *qpktail; qpktail = (struct req_pkt_tail *)((char *)&qpkt + req_pkt_size + MAX_MAC_LEN - sizeof(struct req_pkt_tail)); if (info_auth_keyid == 0) { if (((struct conf_peer *)qpkt.data)->keyid > 0) info_auth_keyid = ((struct conf_peer *)qpkt.data)->keyid; else { maclen = getkeyid("Keyid: "); if (maclen == 0) { (void) fprintf(stderr, "Invalid key identifier\n"); return 1; } info_auth_keyid = maclen; } } if (!authistrusted(info_auth_keyid)) { pass = getpass("MD5 Password: "); if (*pass == '\0') { (void) fprintf(stderr, "Invalid password\n"); return (1); } } authusekey(info_auth_keyid, info_auth_keytype, (const u_char *)pass); authtrust(info_auth_keyid, 1); qpkt.auth_seq = AUTH_SEQ(1, 0); qpktail->keyid = htonl(info_auth_keyid); get_systime(&ts); L_ADD(&ts, &delay_time); HTONL_FP(&ts, &qpktail->tstamp); maclen = authencrypt(info_auth_keyid, (u_int32 *)&qpkt, req_pkt_size); if (maclen == 0) { (void) fprintf(stderr, "Key not found\n"); return (1); } return sendpkt((char *)&qpkt, (int)(req_pkt_size + maclen)); } /*NOTREACHED*/}/* * doquery - send a request and process the response */intdoquery( int implcode, int reqcode, int auth, int qitems, int qsize, char *qdata, int *ritems, int *rsize, char **rdata, int quiet_mask, int esize ){ int res; char junk[512]; fd_set fds; struct timeval tvzero; /* * Check to make sure host is open */ if (!havehost) { (void) fprintf(stderr, "***No host open, use `host' command\n"); return -1; } /* * Poll the socket and clear out any pending data */again: do { tvzero.tv_sec = tvzero.tv_usec = 0; FD_ZERO(&fds); FD_SET(sockfd, &fds); res = select(sockfd+1, &fds, (fd_set *)0, (fd_set *)0, &tvzero); if (res == -1) { warning("polling select", "", ""); return -1; } else if (res > 0) (void) recv(sockfd, junk, sizeof junk, 0); } while (res > 0); /* * send a request */ res = sendrequest(implcode, reqcode, auth, qitems, qsize, qdata); if (res != 0) return res; /* * Get the response. If we got a standard error, print a message */ res = getresponse(implcode, reqcode, ritems, rsize, rdata, esize); /* * Try to be compatible with older implementations of ntpd. */ if (res == INFO_ERR_FMT && req_pkt_size != 48) { int oldsize; oldsize = req_pkt_size; switch(req_pkt_size) { case REQ_LEN_NOMAC: req_pkt_size = 160; break; case 160: req_pkt_size = 48; break; } if (impl_ver == IMPL_XNTPD) { fprintf(stderr, "***Warning changing to older implementation\n"); return INFO_ERR_IMPL; } fprintf(stderr, "***Warning changing the request packet size from %d to %d\n", oldsize, req_pkt_size); goto again; } /* log error message if not told to be quiet */ if ((res > 0) && (((1 << res) & quiet_mask) == 0)) { switch(res) { case INFO_ERR_IMPL: /* Give us a chance to try the older implementation. */ if (implcode == IMPL_XNTPD) break; (void) fprintf(stderr, "***Server implementation incompatable with our own\n"); break; case INFO_ERR_REQ: (void) fprintf(stderr, "***Server doesn't implement this request\n"); break; case INFO_ERR_FMT: (void) fprintf(stderr, "***Server reports a format error in the received packet (shouldn't happen)\n"); break; case INFO_ERR_NODATA: (void) fprintf(stderr, "***Server reports data not found\n"); break; case INFO_ERR_AUTH: (void) fprintf(stderr, "***Permission denied\n"); break; case ERR_TIMEOUT: (void) fprintf(stderr, "***Request timed out\n"); break; case ERR_INCOMPLETE: (void) fprintf(stderr, "***Response from server was incomplete\n"); break; default: (void) fprintf(stderr, "***Server returns unknown error code %d\n", res); break; } } return res;}/* * getcmds - read commands from the standard input and execute them */static voidgetcmds(void){#if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDIT) char *line; for (;;) { if ((line = readline(interactive?prompt:"")) == NULL) return; if (*line) add_history(line); docmd(line); free(line); }#else /* not (HAVE_LIBREADLINE || HAVE_LIBEDIT) */ char line[MAXLINE]; for (;;) { if (interactive) {#ifdef VMS /* work around a problem with mixing stdout & stderr */ fputs("",stdout);#endif (void) fputs(prompt, stderr); (void) fflush(stderr); } if (fgets(line, sizeof line, stdin) == NULL) return; docmd(line); }#endif /* not HAVE_LIBREADLINE || HAVE_LIBEDIT */}#ifndef SYS_WINNT /* Under NT cannot handle SIGINT, WIN32 spawns a handler *//* * abortcmd - catch interrupts and abort the current command */static RETSIGTYPEabortcmd( int sig ){ if (current_output == stdout) (void) fflush(stdout); putc('\n', stderr); (void) fflush(stderr); if (jump) longjmp(interrupt_buf, 1);}#endif /* SYS_WINNT *//* * docmd - decode the command line and execute a command */static voiddocmd( const char *cmdline ){ char *tokens[1+MAXARGS+2]; struct parse pcmd; int ntok; int i, ti; int rval; struct xcmd *xcmd; ai_fam_templ = ai_fam_default; /* * Tokenize the command line. If nothing on it, return. */ tokenize(cmdline, tokens, &ntok); if (ntok == 0) return; /* * Find the appropriate command description. */ i = findcmd(tokens[0], builtins, opcmds, &xcmd); if (i == 0) { (void) fprintf(stderr, "***Command `%s' unknown\n", tokens[0]); return; } else if (i >= 2) { (void) fprintf(stderr, "***Command `%s' ambiguous\n", tokens[0]); return; } /* * Save the keyword, then walk through the arguments, interpreting * as we go. */ pcmd.keyword = tokens[0]; pcmd.nargs = 0; ti = 1; for (i = 0; i < MAXARGS && xcmd->arg[i] != NO;) { if ((i+ti) >= ntok) { if (!(xcmd->arg[i] & OPT)) { printusage(xcmd, stderr); return; } break; } if ((xcmd->arg[i] & OPT) && (*tokens[i+ti] == '>')) break; rval = getarg(tokens[i+ti], (int)xcmd->arg[i], &pcmd.argval[i]); if (rval == -1) { ti++; continue; } if (rval == 0) return; pcmd.nargs++; i++; } /* Any extra args are assumed to be "OPT|NTP_STR". */ for ( ; i < MAXARGS + MOREARGS;) { if ((i+ti) >= ntok) break; rval = getarg(tokens[i+ti], (int)(OPT|NTP_STR), &pcmd.argval[i]); if (rval == -1) { ti++; continue; } if (rval == 0) return; pcmd.nargs++; i++; } i += ti; if (i < ntok && *tokens[i] == '>') { char *fname; if (*(tokens[i]+1) != '\0') fname = tokens[i]+1; else if ((i+1) < ntok) fname = tokens[i+1]; else { (void) fprintf(stderr, "***No file for redirect\n"); return; } current_output = fopen(fname, "w"); if (current_output == NULL) { (void) fprintf(stderr, "***Error opening %s: ", fname); perror(""); return; } } else { current_output = stdout; } if (interactive && setjmp(interrupt_buf)) { return; } else { jump = 1; (xcmd->handler)(&pcmd, current_output); jump = 0; if (current_output != stdout) (void) fclose(current_output); current_output = NULL; }}/* * tokenize - turn a command line into tokens */static voidtokenize( const char *line, char **tokens, int *ntok ){ register const char *cp; register char *sp; static char tspace[MAXLINE]; sp = tspace; cp = line; for (*ntok = 0; *ntok < MAXTOKENS; (*ntok)++) { tokens[*ntok] = sp; while (ISSPACE(*cp)) cp++; if (ISEOL(*cp)) break; do { *sp++ = *cp++; } while (!ISSPACE(*cp) && !ISEOL(*cp)); *sp++ = '\0'; }}/* * findcmd - find a command in a command description table */static intfindcmd( register char *str, struct xcmd *clist1, struct xcmd *clist2, struct xcmd **cmd ){ register struct xcmd *cl; register int clen; int nmatch; struct xcmd *nearmatch = NULL; struct xcmd *clist; clen = strlen(str); nmatch = 0; if (clist1 != 0) clist = clist1; else if (clist2 != 0) clist = clist2; else return 0; again: for (cl = clist; cl->keyword != 0; cl++) { /* do a first character check, for efficiency */ if (*str != *(cl->keyword))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -