📄 ntp_request.c
字号:
#endif req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); return; } if ((proc->sizeofitem != 0) && ((temp_size * INFO_NITEMS(inpkt->err_nitems)) > (rbufp->recv_length - REQ_LEN_HDR))) {#ifdef DEBUG if (debug > 2) printf("process_private: not enough data\n");#endif req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); return; } switch (inpkt->implementation) { case IMPL_XNTPD: client_v6_capable = 1; break; case IMPL_XNTPD_OLD: client_v6_capable = 0; break; default: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); return; } /* * If we need to authenticate, do so. Note that an * authenticatable packet must include a mac field, must * have used key info_auth_keyid and must have included * a time stamp in the appropriate field. The time stamp * must be within INFO_TS_MAXSKEW of the receive * time stamp. */ if (proc->needs_auth && sys_authenticate) { l_fp ftmp; double dtemp; if (rbufp->recv_length < (int)((REQ_LEN_HDR + (INFO_ITEMSIZE(inpkt->mbz_itemsize) * INFO_NITEMS(inpkt->err_nitems)) + sizeof(struct req_pkt_tail)))) { req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); } tailinpkt = (struct req_pkt_tail *)((char *)&rbufp->recv_pkt + rbufp->recv_length - sizeof(struct req_pkt_tail)); /* * If this guy is restricted from doing this, don't let him * If wrong key was used, or packet doesn't have mac, return. */ if (!INFO_IS_AUTH(inpkt->auth_seq) || info_auth_keyid == 0 || ntohl(tailinpkt->keyid) != info_auth_keyid) {#ifdef DEBUG if (debug > 4) printf("failed auth %d info_auth_keyid %lu pkt keyid %lu\n", INFO_IS_AUTH(inpkt->auth_seq), (u_long)info_auth_keyid, (u_long)ntohl(tailinpkt->keyid)); msyslog(LOG_DEBUG, "process_private: failed auth %d info_auth_keyid %lu pkt keyid %lu\n", INFO_IS_AUTH(inpkt->auth_seq), (u_long)info_auth_keyid, (u_long)ntohl(tailinpkt->keyid));#endif req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); return; } if (rbufp->recv_length > REQ_LEN_MAC) {#ifdef DEBUG if (debug > 4) printf("bad pkt length %d\n", rbufp->recv_length);#endif msyslog(LOG_ERR, "process_private: bad pkt length %d", rbufp->recv_length); req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); return; } if (!mod_okay || !authhavekey(info_auth_keyid)) {#ifdef DEBUG if (debug > 4) printf("failed auth mod_okay %d\n", mod_okay); msyslog(LOG_DEBUG, "process_private: failed auth mod_okay %d\n", mod_okay);#endif req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); return; } /* * calculate absolute time difference between xmit time stamp * and receive time stamp. If too large, too bad. */ NTOHL_FP(&tailinpkt->tstamp, &ftmp); L_SUB(&ftmp, &rbufp->recv_time); LFPTOD(&ftmp, dtemp); if (fabs(dtemp) >= INFO_TS_MAXSKEW) { /* * He's a loser. Tell him. */#ifdef DEBUG if (debug > 4) printf("xmit/rcv timestamp delta > INFO_TS_MAXSKEW\n");#endif req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); return; } /* * So far so good. See if decryption works out okay. */ if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt, rbufp->recv_length - sizeof(struct req_pkt_tail) + REQ_LEN_HDR, sizeof(struct req_pkt_tail) - REQ_LEN_HDR)) {#ifdef DEBUG if (debug > 4) printf("authdecrypt failed\n");#endif req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); return; } }#ifdef DEBUG if (debug > 3) printf("process_private: all okay, into handler\n");#endif /* * Packet is okay. Call the handler to send him data. */ (proc->handler)(srcadr, inter, inpkt);}/* * peer_list - send a list of the peers */static voidpeer_list( struct sockaddr_storage *srcadr, struct interface *inter, struct req_pkt *inpkt ){ register struct info_peer_list *ip; register struct peer *pp; register int i; register int skip = 0; ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt, v6sizeof(struct info_peer_list)); for (i = 0; i < NTP_HASH_SIZE && ip != 0; i++) { pp = peer_hash[i]; while (pp != 0 && ip != 0) { if (pp->srcadr.ss_family == AF_INET6) { if (client_v6_capable) { ip->addr6 = GET_INADDR6(pp->srcadr); ip->v6_flag = 1; skip = 0; } else { skip = 1; break; } } else { ip->addr = GET_INADDR(pp->srcadr); if (client_v6_capable) ip->v6_flag = 0; skip = 0; } if(!skip) { ip->port = NSRCPORT(&pp->srcadr); ip->hmode = pp->hmode; ip->flags = 0; if (pp->flags & FLAG_CONFIG) ip->flags |= INFO_FLAG_CONFIG; if (pp == sys_peer) ip->flags |= INFO_FLAG_SYSPEER; if (pp->status == CTL_PST_SEL_SYNCCAND) ip->flags |= INFO_FLAG_SEL_CANDIDATE; if (pp->status >= CTL_PST_SEL_SYSPEER) ip->flags |= INFO_FLAG_SHORTLIST; ip = (struct info_peer_list *)more_pkt(); } pp = pp->next; } } flush_pkt();}/* * peer_list_sum - return extended peer list */static voidpeer_list_sum( struct sockaddr_storage *srcadr, struct interface *inter, struct req_pkt *inpkt ){ register struct info_peer_summary *ips; register struct peer *pp; register int i; l_fp ltmp; register int skip;#ifdef DEBUG if (debug > 2) printf("wants peer list summary\n");#endif ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt, v6sizeof(struct info_peer_summary)); for (i = 0; i < NTP_HASH_SIZE && ips != 0; i++) { pp = peer_hash[i]; while (pp != 0 && ips != 0) {#ifdef DEBUG if (debug > 3) printf("sum: got one\n");#endif /* * Be careful here not to return v6 peers when we * want only v4. */ if (pp->srcadr.ss_family == AF_INET6) { if (client_v6_capable) { ips->srcadr6 = GET_INADDR6(pp->srcadr); ips->v6_flag = 1; ips->dstadr6 = GET_INADDR6(pp->dstadr->sin); skip = 0; } else { skip = 1; break; } } else { ips->srcadr = GET_INADDR(pp->srcadr); if (client_v6_capable) ips->v6_flag = 0;/* XXX PDM This code is buggy. Need to replace with a straightforward assignment */ ips->dstadr = (pp->processed) ? pp->cast_flags == MDF_BCAST ? GET_INADDR(pp->dstadr->bcast): pp->cast_flags ? GET_INADDR(pp->dstadr->sin) ? GET_INADDR(pp->dstadr->sin): GET_INADDR(pp->dstadr->bcast): 1 : GET_INADDR(pp->dstadr->sin); skip = 0; } if (!skip){ ips->srcport = NSRCPORT(&pp->srcadr); ips->stratum = pp->stratum; ips->hpoll = pp->hpoll; ips->ppoll = pp->ppoll; ips->reach = pp->reach; ips->flags = 0; if (pp == sys_peer) ips->flags |= INFO_FLAG_SYSPEER; if (pp->flags & FLAG_CONFIG) ips->flags |= INFO_FLAG_CONFIG; if (pp->flags & FLAG_REFCLOCK) ips->flags |= INFO_FLAG_REFCLOCK; if (pp->flags & FLAG_AUTHENABLE) ips->flags |= INFO_FLAG_AUTHENABLE; if (pp->flags & FLAG_PREFER) ips->flags |= INFO_FLAG_PREFER; if (pp->flags & FLAG_BURST) ips->flags |= INFO_FLAG_BURST; if (pp->status == CTL_PST_SEL_SYNCCAND) ips->flags |= INFO_FLAG_SEL_CANDIDATE; if (pp->status >= CTL_PST_SEL_SYSPEER) ips->flags |= INFO_FLAG_SHORTLIST; ips->hmode = pp->hmode; ips->delay = HTONS_FP(DTOFP(pp->delay)); DTOLFP(pp->offset, <mp); HTONL_FP(<mp, &ips->offset); ips->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); } pp = pp->next; ips = (struct info_peer_summary *)more_pkt(); } } flush_pkt();}/* * peer_info - send information for one or more peers */static voidpeer_info ( struct sockaddr_storage *srcadr, struct interface *inter, struct req_pkt *inpkt ){ register struct info_peer_list *ipl; register struct peer *pp; register struct info_peer *ip; register int items; register int i, j; struct sockaddr_storage addr; extern struct peer *sys_peer; l_fp ltmp; memset((char *)&addr, 0, sizeof addr); items = INFO_NITEMS(inpkt->err_nitems); ipl = (struct info_peer_list *) inpkt->data; ip = (struct info_peer *)prepare_pkt(srcadr, inter, inpkt, v6sizeof(struct info_peer)); while (items-- > 0 && ip != 0) { memset((char *)&addr, 0, sizeof(addr)); NSRCPORT(&addr) = ipl->port; if (client_v6_capable && ipl->v6_flag != 0) { addr.ss_family = AF_INET6; GET_INADDR6(addr) = ipl->addr6; } else { addr.ss_family = AF_INET; GET_INADDR(addr) = ipl->addr; }#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR addr.ss_len = SOCKLEN(&addr);#endif ipl++; if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0) continue; if (pp->srcadr.ss_family == AF_INET6) { ip->dstadr6 = pp->cast_flags == MDF_BCAST ? GET_INADDR6(pp->dstadr->bcast) : GET_INADDR6(pp->dstadr->sin); ip->srcadr6 = GET_INADDR6(pp->srcadr); ip->v6_flag = 1; } else {/* XXX PDM This code is buggy. Need to replace with a straightforward assignment */ ip->dstadr = (pp->processed) ? pp->cast_flags == MDF_BCAST ? GET_INADDR(pp->dstadr->bcast): pp->cast_flags ? GET_INADDR(pp->dstadr->sin) ? GET_INADDR(pp->dstadr->sin): GET_INADDR(pp->dstadr->bcast): 2 : GET_INADDR(pp->dstadr->sin); ip->srcadr = GET_INADDR(pp->srcadr); if (client_v6_capable) ip->v6_flag = 0; } ip->srcport = NSRCPORT(&pp->srcadr); ip->flags = 0; if (pp == sys_peer) ip->flags |= INFO_FLAG_SYSPEER; if (pp->flags & FLAG_CONFIG) ip->flags |= INFO_FLAG_CONFIG; if (pp->flags & FLAG_REFCLOCK) ip->flags |= INFO_FLAG_REFCLOCK; if (pp->flags & FLAG_AUTHENABLE) ip->flags |= INFO_FLAG_AUTHENABLE; if (pp->flags & FLAG_PREFER) ip->flags |= INFO_FLAG_PREFER; if (pp->flags & FLAG_BURST) ip->flags |= INFO_FLAG_BURST; if (pp->status == CTL_PST_SEL_SYNCCAND) ip->flags |= INFO_FLAG_SEL_CANDIDATE; if (pp->status >= CTL_PST_SEL_SYSPEER) ip->flags |= INFO_FLAG_SHORTLIST; ip->leap = pp->leap; ip->hmode = pp->hmode; ip->keyid = pp->keyid; ip->stratum = pp->stratum; ip->ppoll = pp->ppoll; ip->hpoll = pp->hpoll; ip->precision = pp->precision; ip->version = pp->version; ip->reach = pp->reach; ip->unreach = (u_char) pp->unreach; ip->flash = (u_char)pp->flash; ip->flash2 = (u_short) pp->flash; ip->estbdelay = HTONS_FP(DTOFP(pp->estbdelay)); ip->ttl = pp->ttl; ip->associd = htons(pp->associd); ip->rootdelay = HTONS_FP(DTOUFP(pp->rootdelay)); ip->rootdispersion = HTONS_FP(DTOUFP(pp->rootdispersion)); ip->refid = pp->refid; HTONL_FP(&pp->reftime, &ip->reftime); HTONL_FP(&pp->org, &ip->org); HTONL_FP(&pp->rec, &ip->rec); HTONL_FP(&pp->xmt, &ip->xmt); j = pp->filter_nextpt - 1; for (i = 0; i < NTP_SHIFT; i++, j--) { if (j < 0) j = NTP_SHIFT-1; ip->filtdelay[i] = HTONS_FP(DTOFP(pp->filter_delay[j])); DTOLFP(pp->filter_offset[j], <mp); HTONL_FP(<mp, &ip->filtoffset[i]); ip->order[i] = (u_char)((pp->filter_nextpt+NTP_SHIFT-1) - pp->filter_order[i]); if (ip->order[i] >= NTP_SHIFT) ip->order[i] -= NTP_SHIFT; } DTOLFP(pp->offset, <mp); HTONL_FP(<mp, &ip->offset); ip->delay = HTONS_FP(DTOFP(pp->delay)); ip->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); ip->selectdisp = HTONS_FP(DTOUFP(SQRT(pp->jitter))); ip = (struct info_peer *)more_pkt(); } flush_pkt();}/* * peer_stats - send statistics for one or more peers */static voidpeer_stats ( struct sockaddr_storage *srcadr, struct interface *inter, struct req_pkt *inpkt ){ register struct info_peer_list *ipl; register struct peer *pp; register struct info_peer_stats *ip; register int items; struct sockaddr_storage addr; extern struct peer *sys_peer;#ifdef DEBUG if (debug) printf("peer_stats: called\n");#endif items = INFO_NITEMS(inpkt->err_nitems); ipl = (struct info_peer_list *) inpkt->data; ip = (struct info_peer_stats *)prepare_pkt(srcadr, inter, inpkt, v6sizeof(struct info_peer_stats)); while (items-- > 0 && ip != 0) { memset((char *)&addr, 0, sizeof(addr)); NSRCPORT(&addr) = ipl->port; if (client_v6_capable && ipl->v6_flag) { addr.ss_family = AF_INET6; GET_INADDR6(addr) = ipl->addr6; } else { addr.ss_family = AF_INET; GET_INADDR(addr) = ipl->addr; } #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR addr.ss_len = SOCKLEN(&addr);#endif#ifdef DEBUG if (debug) printf("peer_stats: looking for %s, %d, %d\n", stoa(&addr), ipl->port, ((struct sockaddr_in6 *)&addr)->sin6_port);#endif ipl = (struct info_peer_list *)((char *)ipl + INFO_ITEMSIZE(inpkt->mbz_itemsize)); if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0) continue;#ifdef DEBUG if (debug) printf("peer_stats: found %s\n", stoa(&addr));#endif if (pp->srcadr.ss_family == AF_INET) { ip->dstadr = (pp->processed) ? pp->cast_flags == MDF_BCAST ? GET_INADDR(pp->dstadr->bcast): pp->cast_flags ? GET_INADDR(pp->dstadr->sin) ? GET_INADDR(pp->dstadr->sin): GET_INADDR(pp->dstadr->bcast): 3 : 7; ip->srcadr = GET_INADDR(pp->srcadr); if (client_v6_capable) ip->v6_flag = 0; } else { ip->dstadr6 = pp->cast_flags == MDF_BCAST ? GET_INADDR6(pp->dstadr->bcast): GET_INADDR6(pp->dstadr->sin); ip->srcadr6 = GET_INADDR6(pp->srcadr); ip->v6_flag = 1; } ip->srcport = NSRCPORT(&pp->srcadr); ip->flags = 0; if (pp == sys_peer) ip->flags |= INFO_FLAG_SYSPEER; if (pp->flags & FLAG_CONFIG) ip->flags |= INFO_FLAG_CONFIG; if (pp->flags & FLAG_REFCLOCK) ip->flags |= INFO_FLAG_REFCLOCK; if (pp->flags & FLAG_AUTHENABLE) ip->flags |= INFO_FLAG_AUTHENABLE; if (pp->flags & FLAG_PREFER) ip->flags |= INFO_FLAG_PREFER; if (pp->flags & FLAG_BURST) ip->flags |= INFO_FLAG_BURST;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -