diff options
Diffstat (limited to 'contrib/ntp/ntpd/ntp_request.c')
-rw-r--r-- | contrib/ntp/ntpd/ntp_request.c | 268 |
1 files changed, 200 insertions, 68 deletions
diff --git a/contrib/ntp/ntpd/ntp_request.c b/contrib/ntp/ntpd/ntp_request.c index eacba283f492..b1bc99d6f3f8 100644 --- a/contrib/ntp/ntpd/ntp_request.c +++ b/contrib/ntp/ntpd/ntp_request.c @@ -98,7 +98,9 @@ static void req_clr_trap P((struct sockaddr_storage *, struct interface *, struc static void do_setclr_trap P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int)); static void set_request_keyid P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); static void set_control_keyid P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); -static void get_ctl_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); +static void get_ctl_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); +static void get_if_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); +static void do_if_reload P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); #ifdef KERNEL_PLL static void get_kernel_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); #endif /* KERNEL_PLL */ @@ -171,6 +173,9 @@ static struct req_proc ntp_codes[] = { { REQ_GET_CLKBUGINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32), get_clkbug_info }, #endif + { REQ_IF_STATS, AUTH, 0, 0, get_if_stats }, + { REQ_IF_RELOAD, AUTH, 0, 0, do_if_reload }, + { NO_REQUEST, NOAUTH, 0, 0, 0 } }; @@ -495,17 +500,21 @@ process_private( !(inpkt->implementation == IMPL_XNTPD && inpkt->request == REQ_CONFIG && temp_size == sizeof(struct old_conf_peer))) { +#ifdef DEBUG if (debug > 2) printf("process_private: wrong item size, received %d, should be %d or %d\n", temp_size, proc->sizeofitem, proc->v6_sizeofitem); +#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; } @@ -650,7 +659,7 @@ peer_list( ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt, v6sizeof(struct info_peer_list)); - for (i = 0; i < HASH_SIZE && ip != 0; i++) { + 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) { @@ -712,7 +721,7 @@ peer_list_sum( #endif ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt, v6sizeof(struct info_peer_summary)); - for (i = 0; i < HASH_SIZE && ips != 0; i++) { + for (i = 0; i < NTP_HASH_SIZE && ips != 0; i++) { pp = peer_hash[i]; while (pp != 0 && ips != 0) { #ifdef DEBUG @@ -727,7 +736,10 @@ peer_list_sum( if (client_v6_capable) { ips->srcadr6 = GET_INADDR6(pp->srcadr); ips->v6_flag = 1; - ips->dstadr6 = GET_INADDR6(pp->dstadr->sin); + if (pp->dstadr) + ips->dstadr6 = GET_INADDR6(pp->dstadr->sin); + else + memset(&ips->dstadr6, 0, sizeof(ips->dstadr6)); skip = 0; } else { skip = 1; @@ -738,17 +750,22 @@ peer_list_sum( 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); + + if (pp->dstadr) + 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); + else + memset(&ips->dstadr, 0, sizeof(ips->dstadr)); skip = 0; } + if (!skip){ ips->srcport = NSRCPORT(&pp->srcadr); ips->stratum = pp->stratum; @@ -776,7 +793,7 @@ peer_list_sum( ips->delay = HTONS_FP(DTOFP(pp->delay)); DTOLFP(pp->offset, <mp); HTONL_FP(<mp, &ips->offset); - ips->dispersion = HTONS_FP(DTOUFP(pp->disp)); + ips->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); } pp = pp->next; ips = (struct info_peer_summary *)more_pkt(); @@ -828,21 +845,28 @@ peer_info ( 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); + if (pp->dstadr) + ip->dstadr6 = pp->cast_flags == MDF_BCAST ? + GET_INADDR6(pp->dstadr->bcast) : + GET_INADDR6(pp->dstadr->sin); + else + memset(&ip->dstadr6, 0, sizeof(ip->dstadr6)); + 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); + if (pp->dstadr) + 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); + else + memset(&ip->dstadr, 0, sizeof(ip->dstadr)); ip->srcadr = GET_INADDR(pp->srcadr); if (client_v6_capable) @@ -928,7 +952,10 @@ peer_stats ( struct sockaddr_storage addr; extern struct peer *sys_peer; - printf("peer_stats: called\n"); +#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, @@ -946,30 +973,44 @@ peer_stats ( #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR addr.ss_len = SOCKLEN(&addr); #endif - printf("peer_stats: looking for %s, %d, %d\n", stoa(&addr), +#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; - printf("peer_stats: found %s\n", stoa(&addr)); +#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; + if (pp->dstadr) + 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; + else + memset(&ip->dstadr, 0, sizeof(ip->dstadr)); + 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); + if (pp->dstadr) + ip->dstadr6 = pp->cast_flags == MDF_BCAST ? + GET_INADDR6(pp->dstadr->bcast): + GET_INADDR6(pp->dstadr->sin); + else + memset(&ip->dstadr6, 0, sizeof(ip->dstadr6)); + ip->srcadr6 = GET_INADDR6(pp->srcadr); ip->v6_flag = 1; } @@ -987,10 +1028,13 @@ peer_stats ( ip->flags |= INFO_FLAG_PREFER; if (pp->flags & FLAG_BURST) ip->flags |= INFO_FLAG_BURST; + if (pp->flags & FLAG_IBURST) + ip->flags |= INFO_FLAG_IBURST; 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->flags = htons(ip->flags); ip->timereceived = htonl((u_int32)(current_time - pp->timereceived)); ip->timetosend = htonl(pp->nextdate - current_time); ip->timereachable = htonl((u_int32)(current_time - pp->timereachable)); @@ -1020,24 +1064,6 @@ sys_info( { register struct info_sys *is; - /* - * Importations from the protocol module - */ - extern u_char sys_leap; - extern u_char sys_stratum; - extern s_char sys_precision; - extern double sys_rootdelay; - extern double sys_rootdispersion; - extern u_int32 sys_refid; - extern l_fp sys_reftime; - extern u_char sys_poll; - extern struct peer *sys_peer; - extern int sys_bclient; - extern double sys_bdelay; - extern l_fp sys_authdelay; - extern double clock_stability; - extern double sys_jitter; - is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt, v6sizeof(struct info_sys)); @@ -1065,7 +1091,7 @@ sys_info( is->rootdelay = htonl(DTOFP(sys_rootdelay)); is->rootdispersion = htonl(DTOUFP(sys_rootdispersion)); is->frequency = htonl(DTOFP(sys_jitter)); - is->stability = htonl(DTOUFP(clock_stability * 1e6)); + is->stability = htonl(DTOUFP(clock_stability)); is->refid = sys_refid; HTONL_FP(&sys_reftime, &is->reftime); @@ -1147,7 +1173,7 @@ mem_stats( /* * Importations from the peer module */ - extern int peer_hash_count[HASH_SIZE]; + extern int peer_hash_count[NTP_HASH_SIZE]; extern int peer_free_count; extern u_long peer_timereset; extern u_long findpeer_calls; @@ -1165,7 +1191,7 @@ mem_stats( ms->allocations = htonl((u_int32)peer_allocations); ms->demobilizations = htonl((u_int32)peer_demobilizations); - for (i = 0; i < HASH_SIZE; i++) { + for (i = 0; i < NTP_HASH_SIZE; i++) { if (peer_hash_count[i] > 255) ms->hashcount[i] = 255; else @@ -1266,7 +1292,7 @@ loop_info( extern double last_offset; extern double drift_comp; extern int tc_counter; - extern u_long last_time; + extern u_long sys_clocktime; li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt, sizeof(struct info_loop)); @@ -1276,7 +1302,7 @@ loop_info( DTOLFP(drift_comp * 1e6, <mp); HTONL_FP(<mp, &li->drift_comp); li->compliance = htonl((u_int32)(tc_counter)); - li->watchdog_timer = htonl((u_int32)(current_time - last_time)); + li->watchdog_timer = htonl((u_int32)(current_time - sys_clocktime)); (void) more_pkt(); flush_pkt(); @@ -1319,7 +1345,7 @@ do_conf( && temp_cp.hmode != MODE_BROADCAST) fl = 1; if (temp_cp.flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER - | CONF_FLAG_BURST | CONF_FLAG_SKEY)) + | CONF_FLAG_BURST | CONF_FLAG_IBURST | CONF_FLAG_SKEY)) fl = 1; cp = (struct conf_peer *) ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize)); @@ -1343,13 +1369,16 @@ do_conf( fl = 0; if (temp_cp.flags & CONF_FLAG_AUTHENABLE) - fl |= FLAG_AUTHENABLE; + fl |= FLAG_AUTHENABLE; if (temp_cp.flags & CONF_FLAG_PREFER) - fl |= FLAG_PREFER; + fl |= FLAG_PREFER; if (temp_cp.flags & CONF_FLAG_BURST) fl |= FLAG_BURST; + if (temp_cp.flags & CONF_FLAG_IBURST) + fl |= FLAG_IBURST; if (temp_cp.flags & CONF_FLAG_SKEY) fl |= FLAG_SKEY; + if (client_v6_capable && temp_cp.v6_flag != 0) { peeraddr.ss_family = AF_INET6; GET_INADDR6(peeraddr) = temp_cp.peeraddr6; @@ -1531,7 +1560,10 @@ do_unconf( #endif found = 0; peer = (struct peer *)0; - printf("searching for %s\n", stoa(&peeraddr)); +#ifdef DEBUG + if (debug) + printf("searching for %s\n", stoa(&peeraddr)); +#endif while (!found) { peer = findexistingpeer(&peeraddr, peer, -1); if (peer == (struct peer *)0) @@ -1620,7 +1652,9 @@ setclr_flags( ) { register u_int flags; + int prev_kern_enable; + prev_kern_enable = kern_enable; if (INFO_NITEMS(inpkt->err_nitems) > 1) { msyslog(LOG_ERR, "setclr_flags: err_nitems > 1"); req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); @@ -1628,7 +1662,8 @@ setclr_flags( } flags = ((struct conf_sys_flags *)inpkt->data)->flags; - + flags = ntohl(flags); + if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS | SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR | SYS_FLAG_FILEGEN | SYS_FLAG_AUTH | SYS_FLAG_CAL)) { @@ -1658,6 +1693,12 @@ setclr_flags( if (flags & SYS_FLAG_CAL) proto_config(PROTO_CAL, set, 0., NULL); req_ack(srcadr, inter, inpkt, INFO_OKAY); + + /* Reset the kernel ntp parameters if the kernel flag changed. */ + if (prev_kern_enable && !kern_enable) + loop_config(LOOP_KERN_CLEAR, 0.0); + if (!prev_kern_enable && kern_enable) + loop_config(LOOP_DRIFTCOMP, drift_comp); } @@ -1780,6 +1821,8 @@ do_restrict( cr = (struct conf_restrict *)inpkt->data; bad = 0; + cr->flags = ntohs(cr->flags); + cr->mflags = ntohs(cr->mflags); while (items-- > 0 && !bad) { if (cr->mflags & ~(RESM_NTPONLY)) bad |= 1; @@ -1926,7 +1969,7 @@ mon_getlist_1( : GET_INADDR(md->interface->bcast)) : 4); } - im->flags = md->cast_flags; + im->flags = htonl(md->cast_flags); im->port = md->rmtport; im->mode = md->mode; im->version = md->version; @@ -1974,7 +2017,8 @@ reset_stats( } flags = ((struct reset_flags *)inpkt->data)->flags; - + flags = ntohl(flags); + if (flags & ~RESET_ALLFLAGS) { msyslog(LOG_ERR, "reset_stats: reset leaves %#lx", flags & ~RESET_ALLFLAGS); @@ -2754,3 +2798,91 @@ get_clkbug_info( flush_pkt(); } #endif + +/* + * receiver of interface structures + */ +static void +fill_info_if_stats(void *data, interface_info_t *interface_info) +{ + struct info_if_stats **ifsp = (struct info_if_stats **)data; + struct info_if_stats *ifs = *ifsp; + struct interface *interface = interface_info->interface; + + memset((char*)ifs, 0, sizeof(*ifs)); + + if (interface->sin.ss_family == AF_INET6) { + if (!client_v6_capable) { + return; + } + ifs->v6_flag = 1; + memcpy((char *)&ifs->unaddr.addr6, (char *)&CAST_V6(interface->sin)->sin6_addr, sizeof(struct in6_addr)); + memcpy((char *)&ifs->unbcast.addr6, (char *)&CAST_V6(interface->bcast)->sin6_addr, sizeof(struct in6_addr)); + memcpy((char *)&ifs->unmask.addr6, (char *)&CAST_V6(interface->mask)->sin6_addr, sizeof(struct in6_addr)); + } else { + ifs->v6_flag = 0; + memcpy((char *)&ifs->unaddr.addr, (char *)&CAST_V4(interface->sin)->sin_addr, sizeof(struct in_addr)); + memcpy((char *)&ifs->unbcast.addr, (char *)&CAST_V4(interface->bcast)->sin_addr, sizeof(struct in_addr)); + memcpy((char *)&ifs->unmask.addr, (char *)&CAST_V4(interface->mask)->sin_addr, sizeof(struct in_addr)); + } + ifs->v6_flag = htonl(ifs->v6_flag); + strcpy(ifs->name, interface->name); + ifs->family = htons(interface->family); + ifs->flags = htonl(interface->flags); + ifs->last_ttl = htonl(interface->last_ttl); + ifs->num_mcast = htonl(interface->num_mcast); + ifs->received = htonl(interface->received); + ifs->sent = htonl(interface->sent); + ifs->notsent = htonl(interface->notsent); + ifs->scopeid = htonl(interface->scopeid); + ifs->ifindex = htonl(interface->ifindex); + ifs->ifnum = htonl(interface->ifnum); + ifs->uptime = htonl(current_time - interface->starttime); + ifs->ignore_packets = interface->ignore_packets; + ifs->peercnt = htonl(interface->peercnt); + ifs->action = interface_info->action; + + *ifsp = (struct info_if_stats *)more_pkt(); +} + +/* + * get_if_stats - get interface statistics + */ +static void +get_if_stats( + struct sockaddr_storage *srcadr, + struct interface *inter, + struct req_pkt *inpkt + ) +{ + struct info_if_stats *ifs; + + DPRINTF(3, ("wants interface statistics\n")); + + ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt, + v6sizeof(struct info_if_stats)); + + interface_enumerate(fill_info_if_stats, &ifs); + + flush_pkt(); +} + +static void +do_if_reload( + struct sockaddr_storage *srcadr, + struct interface *inter, + struct req_pkt *inpkt + ) +{ + struct info_if_stats *ifs; + + DPRINTF(3, ("wants interface reload\n")); + + ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt, + v6sizeof(struct info_if_stats)); + + interface_update(fill_info_if_stats, &ifs); + + flush_pkt(); +} + |