ntp_request.c revision 294905
10SN/A/* 214316Sssadetsky * ntp_request.c - respond to information requests 30SN/A */ 40SN/A 50SN/A#ifdef HAVE_CONFIG_H 60SN/A# include <config.h> 72362SN/A#endif 80SN/A 92362SN/A#include "ntpd.h" 100SN/A#include "ntp_io.h" 110SN/A#include "ntp_request.h" 120SN/A#include "ntp_control.h" 130SN/A#include "ntp_refclock.h" 140SN/A#include "ntp_if.h" 150SN/A#include "ntp_stdlib.h" 160SN/A#include "ntp_assert.h" 170SN/A 180SN/A#include <stdio.h> 190SN/A#include <stddef.h> 200SN/A#include <signal.h> 212362SN/A#ifdef HAVE_NETINET_IN_H 222362SN/A#include <netinet/in.h> 232362SN/A#endif 240SN/A#include <arpa/inet.h> 250SN/A 260SN/A#include "recvbuff.h" 2715793Sssadetsky 2815793Sssadetsky#ifdef KERNEL_PLL 290SN/A#include "ntp_syscall.h" 300SN/A#endif /* KERNEL_PLL */ 310SN/A 320SN/A/* 330SN/A * Structure to hold request procedure information 340SN/A */ 350SN/A#define NOAUTH 0 360SN/A#define AUTH 1 370SN/A 380SN/A#define NO_REQUEST (-1) 390SN/A/* 400SN/A * Because we now have v6 addresses in the messages, we need to compensate 4115793Sssadetsky * for the larger size. Therefore, we introduce the alternate size to 420SN/A * keep us friendly with older implementations. A little ugly. 430SN/A */ 440SN/Astatic int client_v6_capable = 0; /* the client can handle longer messages */ 450SN/A 460SN/A#define v6sizeof(type) (client_v6_capable ? sizeof(type) : v4sizeof(type)) 470SN/A 480SN/Astruct req_proc { 490SN/A short request_code; /* defined request code */ 500SN/A short needs_auth; /* true when authentication needed */ 510SN/A short sizeofitem; /* size of request data item (older size)*/ 520SN/A short v6_sizeofitem; /* size of request data item (new size)*/ 530SN/A void (*handler) (sockaddr_u *, endpt *, 540SN/A struct req_pkt *); /* routine to handle request */ 550SN/A}; 560SN/A 570SN/A/* 580SN/A * Universal request codes 590SN/A */ 600SN/Astatic const struct req_proc univ_codes[] = { 610SN/A { NO_REQUEST, NOAUTH, 0, 0, NULL } 620SN/A}; 630SN/A 640SN/Astatic void req_ack (sockaddr_u *, endpt *, struct req_pkt *, int); 650SN/Astatic void * prepare_pkt (sockaddr_u *, endpt *, 660SN/A struct req_pkt *, size_t); 670SN/Astatic void * more_pkt (void); 680SN/Astatic void flush_pkt (void); 6912839Sprrstatic void list_peers (sockaddr_u *, endpt *, struct req_pkt *); 7012839Sprrstatic void list_peers_sum (sockaddr_u *, endpt *, struct req_pkt *); 710SN/Astatic void peer_info (sockaddr_u *, endpt *, struct req_pkt *); 720SN/Astatic void peer_stats (sockaddr_u *, endpt *, struct req_pkt *); 730SN/Astatic void sys_info (sockaddr_u *, endpt *, struct req_pkt *); 740SN/Astatic void sys_stats (sockaddr_u *, endpt *, struct req_pkt *); 750SN/Astatic void mem_stats (sockaddr_u *, endpt *, struct req_pkt *); 760SN/Astatic void io_stats (sockaddr_u *, endpt *, struct req_pkt *); 770SN/Astatic void timer_stats (sockaddr_u *, endpt *, struct req_pkt *); 780SN/Astatic void loop_info (sockaddr_u *, endpt *, struct req_pkt *); 790SN/Astatic void do_conf (sockaddr_u *, endpt *, struct req_pkt *); 800SN/Astatic void do_unconf (sockaddr_u *, endpt *, struct req_pkt *); 810SN/Astatic void set_sys_flag (sockaddr_u *, endpt *, struct req_pkt *); 820SN/Astatic void clr_sys_flag (sockaddr_u *, endpt *, struct req_pkt *); 830SN/Astatic void setclr_flags (sockaddr_u *, endpt *, struct req_pkt *, u_long); 840SN/Astatic void list_restrict4 (const restrict_u *, struct info_restrict **); 850SN/Astatic void list_restrict6 (const restrict_u *, struct info_restrict **); 860SN/Astatic void list_restrict (sockaddr_u *, endpt *, struct req_pkt *); 870SN/Astatic void do_resaddflags (sockaddr_u *, endpt *, struct req_pkt *); 880SN/Astatic void do_ressubflags (sockaddr_u *, endpt *, struct req_pkt *); 890SN/Astatic void do_unrestrict (sockaddr_u *, endpt *, struct req_pkt *); 900SN/Astatic void do_restrict (sockaddr_u *, endpt *, struct req_pkt *, int); 910SN/Astatic void mon_getlist (sockaddr_u *, endpt *, struct req_pkt *); 920SN/Astatic void reset_stats (sockaddr_u *, endpt *, struct req_pkt *); 930SN/Astatic void reset_peer (sockaddr_u *, endpt *, struct req_pkt *); 940SN/Astatic void do_key_reread (sockaddr_u *, endpt *, struct req_pkt *); 950SN/Astatic void trust_key (sockaddr_u *, endpt *, struct req_pkt *); 960SN/Astatic void untrust_key (sockaddr_u *, endpt *, struct req_pkt *); 970SN/Astatic void do_trustkey (sockaddr_u *, endpt *, struct req_pkt *, u_long); 980SN/Astatic void get_auth_info (sockaddr_u *, endpt *, struct req_pkt *); 990SN/Astatic void req_get_traps (sockaddr_u *, endpt *, struct req_pkt *); 1000SN/Astatic void req_set_trap (sockaddr_u *, endpt *, struct req_pkt *); 1010SN/Astatic void req_clr_trap (sockaddr_u *, endpt *, struct req_pkt *); 1020SN/Astatic void do_setclr_trap (sockaddr_u *, endpt *, struct req_pkt *, int); 1030SN/Astatic void set_request_keyid (sockaddr_u *, endpt *, struct req_pkt *); 1040SN/Astatic void set_control_keyid (sockaddr_u *, endpt *, struct req_pkt *); 1050SN/Astatic void get_ctl_stats (sockaddr_u *, endpt *, struct req_pkt *); 1060SN/Astatic void get_if_stats (sockaddr_u *, endpt *, struct req_pkt *); 1070SN/Astatic void do_if_reload (sockaddr_u *, endpt *, struct req_pkt *); 1080SN/A#ifdef KERNEL_PLL 1090SN/Astatic void get_kernel_info (sockaddr_u *, endpt *, struct req_pkt *); 1100SN/A#endif /* KERNEL_PLL */ 1110SN/A#ifdef REFCLOCK 1120SN/Astatic void get_clock_info (sockaddr_u *, endpt *, struct req_pkt *); 1130SN/Astatic void set_clock_fudge (sockaddr_u *, endpt *, struct req_pkt *); 1140SN/A#endif /* REFCLOCK */ 1150SN/A#ifdef REFCLOCK 1160SN/Astatic void get_clkbug_info (sockaddr_u *, endpt *, struct req_pkt *); 1170SN/A#endif /* REFCLOCK */ 1180SN/A 1190SN/A/* 1200SN/A * ntpd request codes 1210SN/A */ 1220SN/Astatic const struct req_proc ntp_codes[] = { 1230SN/A { REQ_PEER_LIST, NOAUTH, 0, 0, list_peers }, 1240SN/A { REQ_PEER_LIST_SUM, NOAUTH, 0, 0, list_peers_sum }, 1250SN/A { REQ_PEER_INFO, NOAUTH, v4sizeof(struct info_peer_list), 1260SN/A sizeof(struct info_peer_list), peer_info}, 1270SN/A { REQ_PEER_STATS, NOAUTH, v4sizeof(struct info_peer_list), 1280SN/A sizeof(struct info_peer_list), peer_stats}, 1290SN/A { REQ_SYS_INFO, NOAUTH, 0, 0, sys_info }, 1300SN/A { REQ_SYS_STATS, NOAUTH, 0, 0, sys_stats }, 1310SN/A { REQ_IO_STATS, NOAUTH, 0, 0, io_stats }, 1320SN/A { REQ_MEM_STATS, NOAUTH, 0, 0, mem_stats }, 1330SN/A { REQ_LOOP_INFO, NOAUTH, 0, 0, loop_info }, 1340SN/A { REQ_TIMER_STATS, NOAUTH, 0, 0, timer_stats }, 1350SN/A { REQ_CONFIG, AUTH, v4sizeof(struct conf_peer), 1360SN/A sizeof(struct conf_peer), do_conf }, 1370SN/A { REQ_UNCONFIG, AUTH, v4sizeof(struct conf_unpeer), 1380SN/A sizeof(struct conf_unpeer), do_unconf }, 1390SN/A { REQ_SET_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), 1400SN/A sizeof(struct conf_sys_flags), set_sys_flag }, 1410SN/A { REQ_CLR_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), 1420SN/A sizeof(struct conf_sys_flags), clr_sys_flag }, 1430SN/A { REQ_GET_RESTRICT, NOAUTH, 0, 0, list_restrict }, 1440SN/A { REQ_RESADDFLAGS, AUTH, v4sizeof(struct conf_restrict), 1450SN/A sizeof(struct conf_restrict), do_resaddflags }, 1460SN/A { REQ_RESSUBFLAGS, AUTH, v4sizeof(struct conf_restrict), 1470SN/A sizeof(struct conf_restrict), do_ressubflags }, 1480SN/A { REQ_UNRESTRICT, AUTH, v4sizeof(struct conf_restrict), 1490SN/A sizeof(struct conf_restrict), do_unrestrict }, 1500SN/A { REQ_MON_GETLIST, NOAUTH, 0, 0, mon_getlist }, 1510SN/A { REQ_MON_GETLIST_1, NOAUTH, 0, 0, mon_getlist }, 1520SN/A { REQ_RESET_STATS, AUTH, sizeof(struct reset_flags), 0, reset_stats }, 1530SN/A { REQ_RESET_PEER, AUTH, v4sizeof(struct conf_unpeer), 1540SN/A sizeof(struct conf_unpeer), reset_peer }, 1550SN/A { REQ_REREAD_KEYS, AUTH, 0, 0, do_key_reread }, 1560SN/A { REQ_TRUSTKEY, AUTH, sizeof(u_long), sizeof(u_long), trust_key }, 1570SN/A { REQ_UNTRUSTKEY, AUTH, sizeof(u_long), sizeof(u_long), untrust_key }, 1580SN/A { REQ_AUTHINFO, NOAUTH, 0, 0, get_auth_info }, 1590SN/A { REQ_TRAPS, NOAUTH, 0, 0, req_get_traps }, 1600SN/A { REQ_ADD_TRAP, AUTH, v4sizeof(struct conf_trap), 1610SN/A sizeof(struct conf_trap), req_set_trap }, 1620SN/A { REQ_CLR_TRAP, AUTH, v4sizeof(struct conf_trap), 1630SN/A sizeof(struct conf_trap), req_clr_trap }, 1640SN/A { REQ_REQUEST_KEY, AUTH, sizeof(u_long), sizeof(u_long), 1650SN/A set_request_keyid }, 1660SN/A { REQ_CONTROL_KEY, AUTH, sizeof(u_long), sizeof(u_long), 1670SN/A set_control_keyid }, 1680SN/A { REQ_GET_CTLSTATS, NOAUTH, 0, 0, get_ctl_stats }, 1690SN/A#ifdef KERNEL_PLL 1700SN/A { REQ_GET_KERNEL, NOAUTH, 0, 0, get_kernel_info }, 1710SN/A#endif 1720SN/A#ifdef REFCLOCK 1730SN/A { REQ_GET_CLOCKINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32), 1740SN/A get_clock_info }, 1750SN/A { REQ_SET_CLKFUDGE, AUTH, sizeof(struct conf_fudge), 1760SN/A sizeof(struct conf_fudge), set_clock_fudge }, 1770SN/A { REQ_GET_CLKBUGINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32), 1780SN/A get_clkbug_info }, 1790SN/A#endif 1800SN/A { REQ_IF_STATS, AUTH, 0, 0, get_if_stats }, 1810SN/A { REQ_IF_RELOAD, AUTH, 0, 0, do_if_reload }, 1820SN/A 1830SN/A { NO_REQUEST, NOAUTH, 0, 0, 0 } 1840SN/A}; 1850SN/A 1860SN/A 1870SN/A/* 1880SN/A * Authentication keyid used to authenticate requests. Zero means we 1890SN/A * don't allow writing anything. 1900SN/A */ 1910SN/Akeyid_t info_auth_keyid; 1920SN/A 1930SN/A/* 1940SN/A * Statistic counters to keep track of requests and responses. 1950SN/A */ 1960SN/Au_long numrequests; /* number of requests we've received */ 1970SN/Au_long numresppkts; /* number of resp packets sent with data */ 1980SN/A 1990SN/A/* 2000SN/A * lazy way to count errors, indexed by the error code 2010SN/A */ 2020SN/Au_long errorcounter[MAX_INFO_ERR + 1]; 2030SN/A 2040SN/A/* 2050SN/A * A hack. To keep the authentication module clear of ntp-ism's, we 2060SN/A * include a time reset variable for its stats here. 2070SN/A */ 2080SN/Au_long auth_timereset; 2090SN/A 2100SN/A/* 2110SN/A * Response packet used by these routines. Also some state information 2120SN/A * so that we can handle packet formatting within a common set of 2130SN/A * subroutines. Note we try to enter data in place whenever possible, 2140SN/A * but the need to set the more bit correctly means we occasionally 2150SN/A * use the extra buffer and copy. 2160SN/A */ 2170SN/Astatic struct resp_pkt rpkt; 2180SN/Astatic int reqver; 2190SN/Astatic int seqno; 2200SN/Astatic int nitems; 2210SN/Astatic int itemsize; 2220SN/Astatic int databytes; 2230SN/Astatic char exbuf[RESP_DATA_SIZE]; 2240SN/Astatic int usingexbuf; 2250SN/Astatic sockaddr_u *toaddr; 2260SN/Astatic endpt *frominter; 2270SN/A 2280SN/A/* 2290SN/A * init_request - initialize request data 2300SN/A */ 2310SN/Avoid 2320SN/Ainit_request (void) 2330SN/A{ 2340SN/A size_t i; 2350SN/A 2360SN/A numrequests = 0; 2370SN/A numresppkts = 0; 2380SN/A auth_timereset = 0; 2390SN/A info_auth_keyid = 0; /* by default, can't do this */ 2400SN/A 2410SN/A for (i = 0; i < sizeof(errorcounter)/sizeof(errorcounter[0]); i++) 2420SN/A errorcounter[i] = 0; 2430SN/A} 2440SN/A 2450SN/A 2460SN/A/* 2470SN/A * req_ack - acknowledge request with no data 2480SN/A */ 2490SN/Astatic void 2500SN/Areq_ack( 2510SN/A sockaddr_u *srcadr, 2520SN/A endpt *inter, 2530SN/A struct req_pkt *inpkt, 2540SN/A int errcode 2550SN/A ) 2560SN/A{ 2570SN/A /* 2580SN/A * fill in the fields 2590SN/A */ 2600SN/A rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver); 2610SN/A rpkt.auth_seq = AUTH_SEQ(0, 0); 2620SN/A rpkt.implementation = inpkt->implementation; 2630SN/A rpkt.request = inpkt->request; 2640SN/A rpkt.err_nitems = ERR_NITEMS(errcode, 0); 2650SN/A rpkt.mbz_itemsize = MBZ_ITEMSIZE(0); 2660SN/A 2670SN/A /* 2680SN/A * send packet and bump counters 2690SN/A */ 2700SN/A sendpkt(srcadr, inter, -1, (struct pkt *)&rpkt, RESP_HEADER_SIZE); 2710SN/A errorcounter[errcode]++; 2720SN/A} 2730SN/A 2740SN/A 2750SN/A/* 2760SN/A * prepare_pkt - prepare response packet for transmission, return pointer 2770SN/A * to storage for data item. 2780SN/A */ 2790SN/Astatic void * 2800SN/Aprepare_pkt( 2810SN/A sockaddr_u *srcadr, 2820SN/A endpt *inter, 2830SN/A struct req_pkt *pkt, 2840SN/A size_t structsize 2850SN/A ) 2860SN/A{ 2870SN/A DPRINTF(4, ("request: preparing pkt\n")); 2880SN/A 2890SN/A /* 2900SN/A * Fill in the implementation, request and itemsize fields 2910SN/A * since these won't change. 2920SN/A */ 2930SN/A rpkt.implementation = pkt->implementation; 2940SN/A rpkt.request = pkt->request; 2950SN/A rpkt.mbz_itemsize = MBZ_ITEMSIZE(structsize); 2960SN/A 2970SN/A /* 2980SN/A * Compute the static data needed to carry on. 2990SN/A */ 3000SN/A toaddr = srcadr; 3010SN/A frominter = inter; 3020SN/A seqno = 0; 3030SN/A nitems = 0; 304820SN/A itemsize = structsize; 3050SN/A databytes = 0; 3060SN/A usingexbuf = 0; 3070SN/A 3080SN/A /* 3090SN/A * return the beginning of the packet buffer. 3100SN/A */ 3110SN/A return &rpkt.u; 3120SN/A} 3130SN/A 3140SN/A 3150SN/A/* 3160SN/A * more_pkt - return a data pointer for a new item. 3170SN/A */ 3180SN/Astatic void * 3190SN/Amore_pkt(void) 3200SN/A{ 3210SN/A /* 3220SN/A * If we were using the extra buffer, send the packet. 3230SN/A */ 3240SN/A if (usingexbuf) { 3250SN/A DPRINTF(3, ("request: sending pkt\n")); 3260SN/A rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, MORE_BIT, reqver); 3270SN/A rpkt.auth_seq = AUTH_SEQ(0, seqno); 3280SN/A rpkt.err_nitems = htons((u_short)nitems); 3290SN/A sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt, 3300SN/A RESP_HEADER_SIZE + databytes); 3310SN/A numresppkts++; 3320SN/A 3330SN/A /* 3340SN/A * Copy data out of exbuf into the packet. 3350SN/A */ 3360SN/A memcpy(&rpkt.u.data[0], exbuf, (unsigned)itemsize); 3370SN/A seqno++; 3380SN/A databytes = 0; 3390SN/A nitems = 0; 3400SN/A usingexbuf = 0; 3410SN/A } 3420SN/A 3430SN/A databytes += itemsize; 3440SN/A nitems++; 3450SN/A if (databytes + itemsize <= RESP_DATA_SIZE) { 3460SN/A DPRINTF(4, ("request: giving him more data\n")); 3470SN/A /* 3480SN/A * More room in packet. Give him the 3490SN/A * next address. 3500SN/A */ 3510SN/A return &rpkt.u.data[databytes]; 3520SN/A } else { 3530SN/A /* 3540SN/A * No room in packet. Give him the extra 3550SN/A * buffer unless this was the last in the sequence. 3560SN/A */ 3570SN/A DPRINTF(4, ("request: into extra buffer\n")); 3580SN/A if (seqno == MAXSEQ) 3590SN/A return NULL; 3600SN/A else { 3610SN/A usingexbuf = 1; 3620SN/A return exbuf; 3630SN/A } 3640SN/A } 3650SN/A} 3660SN/A 3670SN/A 3680SN/A/* 3690SN/A * flush_pkt - we're done, return remaining information. 3700SN/A */ 3710SN/Astatic void 3720SN/Aflush_pkt(void) 3730SN/A{ 3740SN/A DPRINTF(3, ("request: flushing packet, %d items\n", nitems)); 3750SN/A /* 3760SN/A * Must send the last packet. If nothing in here and nothing 3770SN/A * has been sent, send an error saying no data to be found. 3780SN/A */ 3790SN/A if (seqno == 0 && nitems == 0) 3800SN/A req_ack(toaddr, frominter, (struct req_pkt *)&rpkt, 3810SN/A INFO_ERR_NODATA); 3820SN/A else { 3830SN/A rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver); 3840SN/A rpkt.auth_seq = AUTH_SEQ(0, seqno); 3850SN/A rpkt.err_nitems = htons((u_short)nitems); 3860SN/A sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt, 3870SN/A RESP_HEADER_SIZE+databytes); 3880SN/A numresppkts++; 3890SN/A } 3900SN/A} 3910SN/A 3920SN/A 3930SN/A 3940SN/A/* 3950SN/A * Given a buffer, return the packet mode 3960SN/A */ 3970SN/Aint 3980SN/Aget_packet_mode(struct recvbuf *rbufp) 3990SN/A{ 4000SN/A struct req_pkt *inpkt = (struct req_pkt *)&rbufp->recv_pkt; 4010SN/A return (INFO_MODE(inpkt->rm_vn_mode)); 4020SN/A} 4030SN/A 4040SN/A 4052711SN/A/* 4060SN/A * process_private - process private mode (7) packets 4070SN/A */ 4080SN/Avoid 4090SN/Aprocess_private( 4100SN/A struct recvbuf *rbufp, 4110SN/A int mod_okay 4120SN/A ) 4130SN/A{ 4140SN/A static u_long quiet_until; 4152711SN/A struct req_pkt *inpkt; 4160SN/A struct req_pkt_tail *tailinpkt; 4170SN/A sockaddr_u *srcadr; 4180SN/A endpt *inter; 4190SN/A const struct req_proc *proc; 4200SN/A int ec; 4210SN/A short temp_size; 4220SN/A l_fp ftmp; 4230SN/A double dtemp; 4240SN/A size_t recv_len; 4250SN/A size_t noslop_len; 4260SN/A size_t mac_len; 4270SN/A 4280SN/A /* 4290SN/A * Initialize pointers, for convenience 4300SN/A */ 4310SN/A recv_len = rbufp->recv_length; 4320SN/A inpkt = (struct req_pkt *)&rbufp->recv_pkt; 4330SN/A srcadr = &rbufp->recv_srcadr; 4340SN/A inter = rbufp->dstadr; 4350SN/A 4360SN/A DPRINTF(3, ("process_private: impl %d req %d\n", 4370SN/A inpkt->implementation, inpkt->request)); 4380SN/A 4390SN/A /* 4400SN/A * Do some sanity checks on the packet. Return a format 4410SN/A * error if it fails. 4422711SN/A */ 4430SN/A ec = 0; 4440SN/A if ( (++ec, ISRESPONSE(inpkt->rm_vn_mode)) 4450SN/A || (++ec, ISMORE(inpkt->rm_vn_mode)) 4460SN/A || (++ec, INFO_VERSION(inpkt->rm_vn_mode) > NTP_VERSION) 4470SN/A || (++ec, INFO_VERSION(inpkt->rm_vn_mode) < NTP_OLDVERSION) 4480SN/A || (++ec, INFO_SEQ(inpkt->auth_seq) != 0) 4490SN/A || (++ec, INFO_ERR(inpkt->err_nitems) != 0) 4500SN/A || (++ec, INFO_MBZ(inpkt->mbz_itemsize) != 0) 4510SN/A || (++ec, rbufp->recv_length < (int)REQ_LEN_HDR) 4520SN/A ) { 4530SN/A NLOG(NLOG_SYSEVENT) 4540SN/A if (current_time >= quiet_until) { 4550SN/A msyslog(LOG_ERR, 4560SN/A "process_private: drop test %d" 4570SN/A " failed, pkt from %s", 4580SN/A ec, stoa(srcadr)); 4590SN/A quiet_until = current_time + 60; 4600SN/A } 4610SN/A return; 4620SN/A } 4632711SN/A 4640SN/A reqver = INFO_VERSION(inpkt->rm_vn_mode); 4650SN/A 4660SN/A /* 4670SN/A * Get the appropriate procedure list to search. 4680SN/A */ 4690SN/A if (inpkt->implementation == IMPL_UNIV) 4700SN/A proc = univ_codes; 4710SN/A else if ((inpkt->implementation == IMPL_XNTPD) || 4720SN/A (inpkt->implementation == IMPL_XNTPD_OLD)) 4730SN/A proc = ntp_codes; 4740SN/A else { 4750SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_IMPL); 4760SN/A return; 4770SN/A } 4780SN/A 4790SN/A /* 4800SN/A * Search the list for the request codes. If it isn't one 4810SN/A * we know, return an error. 4820SN/A */ 4830SN/A while (proc->request_code != NO_REQUEST) { 4840SN/A if (proc->request_code == (short) inpkt->request) 4850SN/A break; 4860SN/A proc++; 4870SN/A } 4880SN/A if (proc->request_code == NO_REQUEST) { 4890SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_REQ); 4900SN/A return; 4910SN/A } 4920SN/A 4930SN/A DPRINTF(4, ("found request in tables\n")); 4940SN/A 4950SN/A /* 4960SN/A * If we need data, check to see if we have some. If we 4970SN/A * don't, check to see that there is none (picky, picky). 4980SN/A */ 4990SN/A 5000SN/A /* This part is a bit tricky, we want to be sure that the size 5010SN/A * returned is either the old or the new size. We also can find 5020SN/A * out if the client can accept both types of messages this way. 5030SN/A * 5040SN/A * Handle the exception of REQ_CONFIG. It can have two data sizes. 5050SN/A */ 5060SN/A temp_size = INFO_ITEMSIZE(inpkt->mbz_itemsize); 5070SN/A if ((temp_size != proc->sizeofitem && 5080SN/A temp_size != proc->v6_sizeofitem) && 5090SN/A !(inpkt->implementation == IMPL_XNTPD && 5100SN/A inpkt->request == REQ_CONFIG && 5110SN/A temp_size == sizeof(struct old_conf_peer))) { 5120SN/A DPRINTF(3, ("process_private: wrong item size, received %d, should be %d or %d\n", 5130SN/A temp_size, proc->sizeofitem, proc->v6_sizeofitem)); 5140SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 5150SN/A return; 5160SN/A } 5170SN/A if ((proc->sizeofitem != 0) && 5180SN/A ((size_t)(temp_size * INFO_NITEMS(inpkt->err_nitems)) > 5190SN/A (recv_len - REQ_LEN_HDR))) { 5200SN/A DPRINTF(3, ("process_private: not enough data\n")); 5210SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 5220SN/A return; 5230SN/A } 5240SN/A 5250SN/A switch (inpkt->implementation) { 5260SN/A case IMPL_XNTPD: 5270SN/A client_v6_capable = 1; 5280SN/A break; 5290SN/A case IMPL_XNTPD_OLD: 5300SN/A client_v6_capable = 0; 5310SN/A break; 5320SN/A default: 5330SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 5340SN/A return; 5350SN/A } 5360SN/A 5370SN/A /* 5380SN/A * If we need to authenticate, do so. Note that an 5390SN/A * authenticatable packet must include a mac field, must 5400SN/A * have used key info_auth_keyid and must have included 5410SN/A * a time stamp in the appropriate field. The time stamp 5420SN/A * must be within INFO_TS_MAXSKEW of the receive 5430SN/A * time stamp. 5440SN/A */ 5450SN/A if (proc->needs_auth && sys_authenticate) { 5460SN/A 5470SN/A if (recv_len < (REQ_LEN_HDR + 5480SN/A (INFO_ITEMSIZE(inpkt->mbz_itemsize) * 5490SN/A INFO_NITEMS(inpkt->err_nitems)) + 5500SN/A REQ_TAIL_MIN)) { 5510SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 5520SN/A return; 5530SN/A } 5540SN/A 5550SN/A /* 5560SN/A * For 16-octet digests, regardless of itemsize and 5570SN/A * nitems, authenticated requests are a fixed size 5580SN/A * with the timestamp, key ID, and digest located 5590SN/A * at the end of the packet. Because the key ID 5600SN/A * determining the digest size precedes the digest, 5610SN/A * for larger digests the fixed size request scheme 5620SN/A * is abandoned and the timestamp, key ID, and digest 5630SN/A * are located relative to the start of the packet, 5640SN/A * with the digest size determined by the packet size. 5650SN/A */ 5660SN/A noslop_len = REQ_LEN_HDR 5670SN/A + INFO_ITEMSIZE(inpkt->mbz_itemsize) * 5680SN/A INFO_NITEMS(inpkt->err_nitems) 5690SN/A + sizeof(inpkt->tstamp); 5700SN/A /* 32-bit alignment */ 5710SN/A noslop_len = (noslop_len + 3) & ~3; 5720SN/A if (recv_len > (noslop_len + MAX_MAC_LEN)) 57315793Sssadetsky mac_len = 20; 57415793Sssadetsky else 5750SN/A mac_len = recv_len - noslop_len; 57615793Sssadetsky 5770SN/A tailinpkt = (void *)((char *)inpkt + recv_len - 5780SN/A (mac_len + sizeof(inpkt->tstamp))); 5790SN/A 5800SN/A /* 5810SN/A * If this guy is restricted from doing this, don't let 5820SN/A * him. If the wrong key was used, or packet doesn't 5830SN/A * have mac, return. 58414316Sssadetsky */ 5850SN/A if (!INFO_IS_AUTH(inpkt->auth_seq) || !info_auth_keyid 58614316Sssadetsky || ntohl(tailinpkt->keyid) != info_auth_keyid) { 58714316Sssadetsky DPRINTF(5, ("failed auth %d info_auth_keyid %u pkt keyid %u maclen %lu\n", 58814316Sssadetsky INFO_IS_AUTH(inpkt->auth_seq), 58915793Sssadetsky info_auth_keyid, 59015793Sssadetsky ntohl(tailinpkt->keyid), (u_long)mac_len)); 59115793Sssadetsky#ifdef DEBUG 59215793Sssadetsky msyslog(LOG_DEBUG, 59315793Sssadetsky "process_private: failed auth %d info_auth_keyid %u pkt keyid %u maclen %lu\n", 59415793Sssadetsky INFO_IS_AUTH(inpkt->auth_seq), 59515793Sssadetsky info_auth_keyid, 59615793Sssadetsky ntohl(tailinpkt->keyid), (u_long)mac_len); 59715793Sssadetsky#endif 59815793Sssadetsky req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 59915793Sssadetsky return; 60015793Sssadetsky } 60115793Sssadetsky if (recv_len > REQ_LEN_NOMAC + MAX_MAC_LEN) { 60215793Sssadetsky DPRINTF(5, ("bad pkt length %zu\n", recv_len)); 60315793Sssadetsky msyslog(LOG_ERR, 60415793Sssadetsky "process_private: bad pkt length %zu", 60515793Sssadetsky recv_len); 60615793Sssadetsky req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 60715793Sssadetsky return; 6080SN/A } 6090SN/A if (!mod_okay || !authhavekey(info_auth_keyid)) { 6100SN/A DPRINTF(5, ("failed auth mod_okay %d\n", 6110SN/A mod_okay)); 6120SN/A#ifdef DEBUG 6130SN/A msyslog(LOG_DEBUG, 6140SN/A "process_private: failed auth mod_okay %d\n", 6150SN/A mod_okay); 6160SN/A#endif 6170SN/A if (!mod_okay) { 6180SN/A sys_restricted++; 6190SN/A } 6200SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 6210SN/A return; 6220SN/A } 6230SN/A 6240SN/A /* 6250SN/A * calculate absolute time difference between xmit time stamp 6260SN/A * and receive time stamp. If too large, too bad. 6270SN/A */ 6280SN/A NTOHL_FP(&tailinpkt->tstamp, &ftmp); 6290SN/A L_SUB(&ftmp, &rbufp->recv_time); 6300SN/A LFPTOD(&ftmp, dtemp); 6310SN/A if (fabs(dtemp) > INFO_TS_MAXSKEW) { 6320SN/A /* 6330SN/A * He's a loser. Tell him. 6340SN/A */ 6350SN/A DPRINTF(5, ("xmit/rcv timestamp delta %g > INFO_TS_MAXSKEW %g\n", 6360SN/A dtemp, INFO_TS_MAXSKEW)); 6370SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 6380SN/A return; 6390SN/A } 6400SN/A 6410SN/A /* 6420SN/A * So far so good. See if decryption works out okay. 6430SN/A */ 6440SN/A if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt, 6450SN/A recv_len - mac_len, mac_len)) { 6460SN/A DPRINTF(5, ("authdecrypt failed\n")); 6470SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 6480SN/A return; 6490SN/A } 6500SN/A } 6510SN/A 6520SN/A DPRINTF(3, ("process_private: all okay, into handler\n")); 6530SN/A /* 6540SN/A * Packet is okay. Call the handler to send him data. 6550SN/A */ 6560SN/A (proc->handler)(srcadr, inter, inpkt); 6570SN/A} 6580SN/A 6590SN/A 6600SN/A/* 6610SN/A * list_peers - send a list of the peers 6620SN/A */ 6630SN/Astatic void 6640SN/Alist_peers( 66514316Sssadetsky sockaddr_u *srcadr, 66614316Sssadetsky endpt *inter, 66714316Sssadetsky struct req_pkt *inpkt 66814316Sssadetsky ) 66914316Sssadetsky{ 67014316Sssadetsky struct info_peer_list * ip; 67114316Sssadetsky const struct peer * pp; 67214316Sssadetsky 67314316Sssadetsky ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt, 67414316Sssadetsky v6sizeof(struct info_peer_list)); 67514316Sssadetsky for (pp = peer_list; pp != NULL && ip != NULL; pp = pp->p_link) { 67614316Sssadetsky if (IS_IPV6(&pp->srcadr)) { 67715272Sssadetsky if (!client_v6_capable) 67815272Sssadetsky continue; 67915272Sssadetsky ip->addr6 = SOCK_ADDR6(&pp->srcadr); 68015272Sssadetsky ip->v6_flag = 1; 68115272Sssadetsky } else { 68215272Sssadetsky ip->addr = NSRCADR(&pp->srcadr); 68315272Sssadetsky if (client_v6_capable) 68415272Sssadetsky ip->v6_flag = 0; 68515272Sssadetsky } 68615272Sssadetsky 68715272Sssadetsky ip->port = NSRCPORT(&pp->srcadr); 68814316Sssadetsky ip->hmode = pp->hmode; 68914316Sssadetsky ip->flags = 0; 69014316Sssadetsky if (pp->flags & FLAG_CONFIG) 69114316Sssadetsky ip->flags |= INFO_FLAG_CONFIG; 69214316Sssadetsky if (pp == sys_peer) 69314316Sssadetsky ip->flags |= INFO_FLAG_SYSPEER; 69414316Sssadetsky if (pp->status == CTL_PST_SEL_SYNCCAND) 69514316Sssadetsky ip->flags |= INFO_FLAG_SEL_CANDIDATE; 69614316Sssadetsky if (pp->status >= CTL_PST_SEL_SYSPEER) 69714316Sssadetsky ip->flags |= INFO_FLAG_SHORTLIST; 69814316Sssadetsky ip = (struct info_peer_list *)more_pkt(); 69914316Sssadetsky } /* for pp */ 70014316Sssadetsky 70114316Sssadetsky flush_pkt(); 7020SN/A} 7030SN/A 7040SN/A 7050SN/A/* 7060SN/A * list_peers_sum - return extended peer list 7070SN/A */ 7080SN/Astatic void 7090SN/Alist_peers_sum( 7100SN/A sockaddr_u *srcadr, 7110SN/A endpt *inter, 7120SN/A struct req_pkt *inpkt 7130SN/A ) 7140SN/A{ 7150SN/A struct info_peer_summary * ips; 7160SN/A const struct peer * pp; 7170SN/A l_fp ltmp; 7180SN/A 7190SN/A DPRINTF(3, ("wants peer list summary\n")); 7200SN/A 7210SN/A ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt, 7220SN/A v6sizeof(struct info_peer_summary)); 7230SN/A for (pp = peer_list; pp != NULL && ips != NULL; pp = pp->p_link) { 7240SN/A DPRINTF(4, ("sum: got one\n")); 7250SN/A /* 7260SN/A * Be careful here not to return v6 peers when we 7270SN/A * want only v4. 7280SN/A */ 7290SN/A if (IS_IPV6(&pp->srcadr)) { 7300SN/A if (!client_v6_capable) 7310SN/A continue; 7320SN/A ips->srcadr6 = SOCK_ADDR6(&pp->srcadr); 7330SN/A ips->v6_flag = 1; 7340SN/A if (pp->dstadr) 7350SN/A ips->dstadr6 = SOCK_ADDR6(&pp->dstadr->sin); 7360SN/A else 7370SN/A ZERO(ips->dstadr6); 7380SN/A } else { 7390SN/A ips->srcadr = NSRCADR(&pp->srcadr); 7400SN/A if (client_v6_capable) 7410SN/A ips->v6_flag = 0; 7420SN/A 7430SN/A if (pp->dstadr) { 7440SN/A if (!pp->processed) 7450SN/A ips->dstadr = NSRCADR(&pp->dstadr->sin); 7460SN/A else { 7470SN/A if (MDF_BCAST == pp->cast_flags) 7480SN/A ips->dstadr = NSRCADR(&pp->dstadr->bcast); 7490SN/A else if (pp->cast_flags) { 7500SN/A ips->dstadr = NSRCADR(&pp->dstadr->sin); 7510SN/A if (!ips->dstadr) 7520SN/A ips->dstadr = NSRCADR(&pp->dstadr->bcast); 7530SN/A } 7540SN/A } 7550SN/A } else { 7560SN/A ips->dstadr = 0; 7570SN/A } 7580SN/A } 7590SN/A 7600SN/A ips->srcport = NSRCPORT(&pp->srcadr); 7610SN/A ips->stratum = pp->stratum; 7620SN/A ips->hpoll = pp->hpoll; 7630SN/A ips->ppoll = pp->ppoll; 7640SN/A ips->reach = pp->reach; 7650SN/A ips->flags = 0; 7660SN/A if (pp == sys_peer) 7670SN/A ips->flags |= INFO_FLAG_SYSPEER; 7680SN/A if (pp->flags & FLAG_CONFIG) 7690SN/A ips->flags |= INFO_FLAG_CONFIG; 7700SN/A if (pp->flags & FLAG_REFCLOCK) 7710SN/A ips->flags |= INFO_FLAG_REFCLOCK; 7720SN/A if (pp->flags & FLAG_PREFER) 7730SN/A ips->flags |= INFO_FLAG_PREFER; 7740SN/A if (pp->flags & FLAG_BURST) 7750SN/A ips->flags |= INFO_FLAG_BURST; 7760SN/A if (pp->status == CTL_PST_SEL_SYNCCAND) 7770SN/A ips->flags |= INFO_FLAG_SEL_CANDIDATE; 7780SN/A if (pp->status >= CTL_PST_SEL_SYSPEER) 7790SN/A ips->flags |= INFO_FLAG_SHORTLIST; 7800SN/A ips->hmode = pp->hmode; 7810SN/A ips->delay = HTONS_FP(DTOFP(pp->delay)); 7820SN/A DTOLFP(pp->offset, <mp); 7830SN/A HTONL_FP(<mp, &ips->offset); 7840SN/A ips->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); 7850SN/A 7860SN/A ips = (struct info_peer_summary *)more_pkt(); 7870SN/A } /* for pp */ 7880SN/A 7890SN/A flush_pkt(); 7900SN/A} 7910SN/A 7920SN/A 7930SN/A/* 7940SN/A * peer_info - send information for one or more peers 7950SN/A */ 7960SN/Astatic void 7970SN/Apeer_info ( 7980SN/A sockaddr_u *srcadr, 7990SN/A endpt *inter, 8000SN/A struct req_pkt *inpkt 8010SN/A ) 8020SN/A{ 80314339Sssadetsky u_short items; 80414339Sssadetsky size_t item_sz; 80514339Sssadetsky char * datap; 80614339Sssadetsky struct info_peer_list ipl; 80714339Sssadetsky struct peer * pp; 80814339Sssadetsky struct info_peer * ip; 80914339Sssadetsky int i; 81014339Sssadetsky int j; 81114339Sssadetsky sockaddr_u addr; 8120SN/A l_fp ltmp; 8130SN/A 8140SN/A items = INFO_NITEMS(inpkt->err_nitems); 8150SN/A item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 8160SN/A datap = inpkt->u.data; 8170SN/A if (item_sz != sizeof(ipl)) { 8180SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 8190SN/A return; 8200SN/A } 8210SN/A ip = prepare_pkt(srcadr, inter, inpkt, 8220SN/A v6sizeof(struct info_peer)); 8230SN/A while (items-- > 0 && ip != NULL) { 8240SN/A ZERO(ipl); 8250SN/A memcpy(&ipl, datap, item_sz); 8260SN/A ZERO_SOCK(&addr); 8270SN/A NSRCPORT(&addr) = ipl.port; 8280SN/A if (client_v6_capable && ipl.v6_flag) { 8290SN/A AF(&addr) = AF_INET6; 8300SN/A SOCK_ADDR6(&addr) = ipl.addr6; 8310SN/A } else { 8320SN/A AF(&addr) = AF_INET; 8330SN/A NSRCADR(&addr) = ipl.addr; 8340SN/A } 8350SN/A#ifdef ISC_PLATFORM_HAVESALEN 8360SN/A addr.sa.sa_len = SOCKLEN(&addr); 8370SN/A#endif 8380SN/A datap += item_sz; 8390SN/A 8400SN/A pp = findexistingpeer(&addr, NULL, NULL, -1, 0); 8410SN/A if (NULL == pp) 8420SN/A continue; 8430SN/A if (IS_IPV6(srcadr)) { 8440SN/A if (pp->dstadr) 84514339Sssadetsky ip->dstadr6 = 84614339Sssadetsky (MDF_BCAST == pp->cast_flags) 8470SN/A ? SOCK_ADDR6(&pp->dstadr->bcast) 84814339Sssadetsky : SOCK_ADDR6(&pp->dstadr->sin); 84914339Sssadetsky else 8500SN/A ZERO(ip->dstadr6); 8510SN/A 8520SN/A ip->srcadr6 = SOCK_ADDR6(&pp->srcadr); 8530SN/A ip->v6_flag = 1; 8540SN/A } else { 8550SN/A if (pp->dstadr) { 85614339Sssadetsky if (!pp->processed) 85714339Sssadetsky ip->dstadr = NSRCADR(&pp->dstadr->sin); 8580SN/A else { 8590SN/A if (MDF_BCAST == pp->cast_flags) 8600SN/A ip->dstadr = NSRCADR(&pp->dstadr->bcast); 8610SN/A else if (pp->cast_flags) { 8620SN/A ip->dstadr = NSRCADR(&pp->dstadr->sin); 8630SN/A if (!ip->dstadr) 8640SN/A ip->dstadr = NSRCADR(&pp->dstadr->bcast); 8650SN/A } 8660SN/A } 8670SN/A } else 8680SN/A ip->dstadr = 0; 8690SN/A 8700SN/A ip->srcadr = NSRCADR(&pp->srcadr); 8710SN/A if (client_v6_capable) 8720SN/A ip->v6_flag = 0; 8730SN/A } 8740SN/A ip->srcport = NSRCPORT(&pp->srcadr); 8750SN/A ip->flags = 0; 8760SN/A if (pp == sys_peer) 8770SN/A ip->flags |= INFO_FLAG_SYSPEER; 8780SN/A if (pp->flags & FLAG_CONFIG) 8790SN/A ip->flags |= INFO_FLAG_CONFIG; 8800SN/A if (pp->flags & FLAG_REFCLOCK) 8810SN/A ip->flags |= INFO_FLAG_REFCLOCK; 8820SN/A if (pp->flags & FLAG_PREFER) 8830SN/A ip->flags |= INFO_FLAG_PREFER; 8840SN/A if (pp->flags & FLAG_BURST) 8850SN/A ip->flags |= INFO_FLAG_BURST; 8860SN/A if (pp->status == CTL_PST_SEL_SYNCCAND) 8870SN/A ip->flags |= INFO_FLAG_SEL_CANDIDATE; 8880SN/A if (pp->status >= CTL_PST_SEL_SYSPEER) 8890SN/A ip->flags |= INFO_FLAG_SHORTLIST; 8900SN/A ip->leap = pp->leap; 8910SN/A ip->hmode = pp->hmode; 8920SN/A ip->keyid = pp->keyid; 8930SN/A ip->stratum = pp->stratum; 8940SN/A ip->ppoll = pp->ppoll; 8950SN/A ip->hpoll = pp->hpoll; 8960SN/A ip->precision = pp->precision; 8970SN/A ip->version = pp->version; 8980SN/A ip->reach = pp->reach; 8990SN/A ip->unreach = (u_char)pp->unreach; 9000SN/A ip->flash = (u_char)pp->flash; 9010SN/A ip->flash2 = (u_short)pp->flash; 9020SN/A ip->estbdelay = HTONS_FP(DTOFP(pp->delay)); 9030SN/A ip->ttl = (u_char)pp->ttl; 9040SN/A ip->associd = htons(pp->associd); 9050SN/A ip->rootdelay = HTONS_FP(DTOUFP(pp->rootdelay)); 9060SN/A ip->rootdispersion = HTONS_FP(DTOUFP(pp->rootdisp)); 9070SN/A ip->refid = pp->refid; 9080SN/A HTONL_FP(&pp->reftime, &ip->reftime); 9090SN/A HTONL_FP(&pp->aorg, &ip->org); 9100SN/A HTONL_FP(&pp->rec, &ip->rec); 9110SN/A HTONL_FP(&pp->xmt, &ip->xmt); 9120SN/A j = pp->filter_nextpt - 1; 9130SN/A for (i = 0; i < NTP_SHIFT; i++, j--) { 9140SN/A if (j < 0) 9150SN/A j = NTP_SHIFT-1; 9160SN/A ip->filtdelay[i] = HTONS_FP(DTOFP(pp->filter_delay[j])); 9170SN/A DTOLFP(pp->filter_offset[j], <mp); 9180SN/A HTONL_FP(<mp, &ip->filtoffset[i]); 9190SN/A ip->order[i] = (u_char)((pp->filter_nextpt + 9200SN/A NTP_SHIFT - 1) - 9210SN/A pp->filter_order[i]); 9220SN/A if (ip->order[i] >= NTP_SHIFT) 9230SN/A ip->order[i] -= NTP_SHIFT; 9240SN/A } 9250SN/A DTOLFP(pp->offset, <mp); 9260SN/A HTONL_FP(<mp, &ip->offset); 9270SN/A ip->delay = HTONS_FP(DTOFP(pp->delay)); 9280SN/A ip->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); 9290SN/A ip->selectdisp = HTONS_FP(DTOUFP(SQRT(pp->jitter))); 9300SN/A ip = more_pkt(); 9310SN/A } 9320SN/A flush_pkt(); 9330SN/A} 9340SN/A 9350SN/A 9360SN/A/* 9370SN/A * peer_stats - send statistics for one or more peers 9380SN/A */ 9390SN/Astatic void 9400SN/Apeer_stats ( 9410SN/A sockaddr_u *srcadr, 9420SN/A endpt *inter, 9430SN/A struct req_pkt *inpkt 9440SN/A ) 9450SN/A{ 9460SN/A u_short items; 9470SN/A size_t item_sz; 9480SN/A char * datap; 9490SN/A struct info_peer_list ipl; 9500SN/A struct peer * pp; 9510SN/A struct info_peer_stats *ip; 9520SN/A sockaddr_u addr; 9530SN/A 9540SN/A DPRINTF(1, ("peer_stats: called\n")); 9550SN/A items = INFO_NITEMS(inpkt->err_nitems); 9560SN/A item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 9570SN/A datap = inpkt->u.data; 9580SN/A if (item_sz > sizeof(ipl)) { 9590SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 9600SN/A return; 9610SN/A } 9620SN/A ip = prepare_pkt(srcadr, inter, inpkt, 9630SN/A v6sizeof(struct info_peer_stats)); 9640SN/A while (items-- > 0 && ip != NULL) { 9650SN/A ZERO(ipl); 9660SN/A memcpy(&ipl, datap, item_sz); 9670SN/A ZERO(addr); 9680SN/A NSRCPORT(&addr) = ipl.port; 9690SN/A if (client_v6_capable && ipl.v6_flag) { 9700SN/A AF(&addr) = AF_INET6; 9710SN/A SOCK_ADDR6(&addr) = ipl.addr6; 9720SN/A } else { 9730SN/A AF(&addr) = AF_INET; 9740SN/A NSRCADR(&addr) = ipl.addr; 9750SN/A } 9760SN/A#ifdef ISC_PLATFORM_HAVESALEN 9770SN/A addr.sa.sa_len = SOCKLEN(&addr); 9780SN/A#endif 9790SN/A DPRINTF(1, ("peer_stats: looking for %s, %d, %d\n", 9800SN/A stoa(&addr), ipl.port, NSRCPORT(&addr))); 9810SN/A 9820SN/A datap += item_sz; 9830SN/A 9840SN/A pp = findexistingpeer(&addr, NULL, NULL, -1, 0); 9850SN/A if (NULL == pp) 9860SN/A continue; 9870SN/A 9880SN/A DPRINTF(1, ("peer_stats: found %s\n", stoa(&addr))); 9890SN/A 9900SN/A if (IS_IPV4(&pp->srcadr)) { 9910SN/A if (pp->dstadr) { 9920SN/A if (!pp->processed) 9930SN/A ip->dstadr = NSRCADR(&pp->dstadr->sin); 9940SN/A else { 9950SN/A if (MDF_BCAST == pp->cast_flags) 9960SN/A ip->dstadr = NSRCADR(&pp->dstadr->bcast); 9970SN/A else if (pp->cast_flags) { 9980SN/A ip->dstadr = NSRCADR(&pp->dstadr->sin); 9995520SN/A if (!ip->dstadr) 10005520SN/A ip->dstadr = NSRCADR(&pp->dstadr->bcast); 10010SN/A } 10020SN/A } 10030SN/A } else 10045520SN/A ip->dstadr = 0; 10055520SN/A 10065520SN/A ip->srcadr = NSRCADR(&pp->srcadr); 10075520SN/A if (client_v6_capable) 10085520SN/A ip->v6_flag = 0; 10095520SN/A } else { 10105520SN/A if (pp->dstadr) 10115520SN/A ip->dstadr6 = 10125520SN/A (MDF_BCAST == pp->cast_flags) 10130SN/A ? SOCK_ADDR6(&pp->dstadr->bcast) 10140SN/A : SOCK_ADDR6(&pp->dstadr->sin); 10150SN/A else 10160SN/A ZERO(ip->dstadr6); 10170SN/A 10180SN/A ip->srcadr6 = SOCK_ADDR6(&pp->srcadr); 10190SN/A ip->v6_flag = 1; 10200SN/A } 10210SN/A ip->srcport = NSRCPORT(&pp->srcadr); 10225520SN/A ip->flags = 0; 10235520SN/A if (pp == sys_peer) 10245520SN/A ip->flags |= INFO_FLAG_SYSPEER; 10250SN/A if (pp->flags & FLAG_CONFIG) 10260SN/A ip->flags |= INFO_FLAG_CONFIG; 10270SN/A if (pp->flags & FLAG_REFCLOCK) 10280SN/A ip->flags |= INFO_FLAG_REFCLOCK; 10290SN/A if (pp->flags & FLAG_PREFER) 10300SN/A ip->flags |= INFO_FLAG_PREFER; 10310SN/A if (pp->flags & FLAG_BURST) 10320SN/A ip->flags |= INFO_FLAG_BURST; 10330SN/A if (pp->flags & FLAG_IBURST) 10340SN/A ip->flags |= INFO_FLAG_IBURST; 10350SN/A if (pp->status == CTL_PST_SEL_SYNCCAND) 103614339Sssadetsky ip->flags |= INFO_FLAG_SEL_CANDIDATE; 103714339Sssadetsky if (pp->status >= CTL_PST_SEL_SYSPEER) 103814339Sssadetsky ip->flags |= INFO_FLAG_SHORTLIST; 103914339Sssadetsky ip->flags = htons(ip->flags); 10400SN/A ip->timereceived = htonl((u_int32)(current_time - pp->timereceived)); 10410SN/A ip->timetosend = htonl(pp->nextdate - current_time); 104214339Sssadetsky ip->timereachable = htonl((u_int32)(current_time - pp->timereachable)); 104314339Sssadetsky ip->sent = htonl((u_int32)(pp->sent)); 104414339Sssadetsky ip->processed = htonl((u_int32)(pp->processed)); 104514339Sssadetsky ip->badauth = htonl((u_int32)(pp->badauth)); 104614339Sssadetsky ip->bogusorg = htonl((u_int32)(pp->bogusorg)); 104714339Sssadetsky ip->oldpkt = htonl((u_int32)(pp->oldpkt)); 104814339Sssadetsky ip->seldisp = htonl((u_int32)(pp->seldisptoolarge)); 104914339Sssadetsky ip->selbroken = htonl((u_int32)(pp->selbroken)); 105014339Sssadetsky ip->candidate = pp->status; 10510SN/A ip = (struct info_peer_stats *)more_pkt(); 10525520SN/A } 10535520SN/A flush_pkt(); 10545520SN/A} 10555520SN/A 10565520SN/A 10575520SN/A/* 10585520SN/A * sys_info - return system info 10595520SN/A */ 10605520SN/Astatic void 106114339Sssadetskysys_info( 106214339Sssadetsky sockaddr_u *srcadr, 106314339Sssadetsky endpt *inter, 10645520SN/A struct req_pkt *inpkt 106514339Sssadetsky ) 106614339Sssadetsky{ 106714339Sssadetsky register struct info_sys *is; 106814339Sssadetsky 10695520SN/A is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt, 10705520SN/A v6sizeof(struct info_sys)); 10710SN/A 10720SN/A if (sys_peer) { 10730SN/A if (IS_IPV4(&sys_peer->srcadr)) { 10740SN/A is->peer = NSRCADR(&sys_peer->srcadr); 10750SN/A if (client_v6_capable) 10760SN/A is->v6_flag = 0; 10770SN/A } else if (client_v6_capable) { 10780SN/A is->peer6 = SOCK_ADDR6(&sys_peer->srcadr); 10790SN/A is->v6_flag = 1; 10800SN/A } 10810SN/A is->peer_mode = sys_peer->hmode; 10820SN/A } else { 10830SN/A is->peer = 0; 10840SN/A if (client_v6_capable) { 10850SN/A is->v6_flag = 0; 10860SN/A } 10870SN/A is->peer_mode = 0; 10880SN/A } 10890SN/A 10900SN/A is->leap = sys_leap; 10910SN/A is->stratum = sys_stratum; 10920SN/A is->precision = sys_precision; 10930SN/A is->rootdelay = htonl(DTOFP(sys_rootdelay)); 10940SN/A is->rootdispersion = htonl(DTOUFP(sys_rootdisp)); 10950SN/A is->frequency = htonl(DTOFP(sys_jitter)); 10960SN/A is->stability = htonl(DTOUFP(clock_stability * 1e6)); 10970SN/A is->refid = sys_refid; 10980SN/A HTONL_FP(&sys_reftime, &is->reftime); 10990SN/A 11000SN/A is->poll = sys_poll; 11010SN/A 11020SN/A is->flags = 0; 11030SN/A if (sys_authenticate) 11040SN/A is->flags |= INFO_FLAG_AUTHENTICATE; 11050SN/A if (sys_bclient) 11060SN/A is->flags |= INFO_FLAG_BCLIENT; 11070SN/A#ifdef REFCLOCK 11080SN/A if (cal_enable) 11090SN/A is->flags |= INFO_FLAG_CAL; 11100SN/A#endif /* REFCLOCK */ 11110SN/A if (kern_enable) 11120SN/A is->flags |= INFO_FLAG_KERNEL; 11130SN/A if (mon_enabled != MON_OFF) 11140SN/A is->flags |= INFO_FLAG_MONITOR; 11150SN/A if (ntp_enable) 11160SN/A is->flags |= INFO_FLAG_NTP; 11170SN/A if (hardpps_enable) 11180SN/A is->flags |= INFO_FLAG_PPS_SYNC; 11190SN/A if (stats_control) 11200SN/A is->flags |= INFO_FLAG_FILEGEN; 11210SN/A is->bdelay = HTONS_FP(DTOFP(sys_bdelay)); 11220SN/A HTONL_UF(sys_authdelay.l_uf, &is->authdelay); 11230SN/A (void) more_pkt(); 11240SN/A flush_pkt(); 11250SN/A} 11260SN/A 11270SN/A 11280SN/A/* 11290SN/A * sys_stats - return system statistics 11300SN/A */ 11310SN/Astatic void 11320SN/Asys_stats( 11330SN/A sockaddr_u *srcadr, 11340SN/A endpt *inter, 11350SN/A struct req_pkt *inpkt 11360SN/A ) 11370SN/A{ 11380SN/A register struct info_sys_stats *ss; 11390SN/A 11400SN/A ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt, 11410SN/A sizeof(struct info_sys_stats)); 11420SN/A ss->timeup = htonl((u_int32)current_time); 11430SN/A ss->timereset = htonl((u_int32)(current_time - sys_stattime)); 11440SN/A ss->denied = htonl((u_int32)sys_restricted); 11450SN/A ss->oldversionpkt = htonl((u_int32)sys_oldversion); 11460SN/A ss->newversionpkt = htonl((u_int32)sys_newversion); 11470SN/A ss->unknownversion = htonl((u_int32)sys_declined); 11480SN/A ss->badlength = htonl((u_int32)sys_badlength); 11490SN/A ss->processed = htonl((u_int32)sys_processed); 11500SN/A ss->badauth = htonl((u_int32)sys_badauth); 11510SN/A ss->limitrejected = htonl((u_int32)sys_limitrejected); 11520SN/A ss->received = htonl((u_int32)sys_received); 11530SN/A (void) more_pkt(); 11540SN/A flush_pkt(); 11550SN/A} 11560SN/A 11570SN/A 11580SN/A/* 11590SN/A * mem_stats - return memory statistics 11600SN/A */ 11610SN/Astatic void 11620SN/Amem_stats( 11630SN/A sockaddr_u *srcadr, 11640SN/A endpt *inter, 11650SN/A struct req_pkt *inpkt 11660SN/A ) 11670SN/A{ 11680SN/A register struct info_mem_stats *ms; 11690SN/A register int i; 11700SN/A 11710SN/A ms = (struct info_mem_stats *)prepare_pkt(srcadr, inter, inpkt, 11720SN/A sizeof(struct info_mem_stats)); 11730SN/A 11740SN/A ms->timereset = htonl((u_int32)(current_time - peer_timereset)); 11750SN/A ms->totalpeermem = htons((u_short)total_peer_structs); 11760SN/A ms->freepeermem = htons((u_short)peer_free_count); 11770SN/A ms->findpeer_calls = htonl((u_int32)findpeer_calls); 11780SN/A ms->allocations = htonl((u_int32)peer_allocations); 11790SN/A ms->demobilizations = htonl((u_int32)peer_demobilizations); 11800SN/A 11810SN/A for (i = 0; i < NTP_HASH_SIZE; i++) 11820SN/A ms->hashcount[i] = (u_char) 11830SN/A max((u_int)peer_hash_count[i], UCHAR_MAX); 11840SN/A 11850SN/A (void) more_pkt(); 11860SN/A flush_pkt(); 11870SN/A} 11880SN/A 11890SN/A 11900SN/A/* 11910SN/A * io_stats - return io statistics 11920SN/A */ 11930SN/Astatic void 11940SN/Aio_stats( 11950SN/A sockaddr_u *srcadr, 11960SN/A endpt *inter, 11970SN/A struct req_pkt *inpkt 11980SN/A ) 11990SN/A{ 12000SN/A struct info_io_stats *io; 12010SN/A 12020SN/A io = (struct info_io_stats *)prepare_pkt(srcadr, inter, inpkt, 12030SN/A sizeof(struct info_io_stats)); 12040SN/A 12050SN/A io->timereset = htonl((u_int32)(current_time - io_timereset)); 12060SN/A io->totalrecvbufs = htons((u_short) total_recvbuffs()); 12070SN/A io->freerecvbufs = htons((u_short) free_recvbuffs()); 12080SN/A io->fullrecvbufs = htons((u_short) full_recvbuffs()); 12090SN/A io->lowwater = htons((u_short) lowater_additions()); 12100SN/A io->dropped = htonl((u_int32)packets_dropped); 12110SN/A io->ignored = htonl((u_int32)packets_ignored); 12120SN/A io->received = htonl((u_int32)packets_received); 12130SN/A io->sent = htonl((u_int32)packets_sent); 12140SN/A io->notsent = htonl((u_int32)packets_notsent); 12150SN/A io->interrupts = htonl((u_int32)handler_calls); 12160SN/A io->int_received = htonl((u_int32)handler_pkts); 121714339Sssadetsky 121814339Sssadetsky (void) more_pkt(); 12190SN/A flush_pkt(); 12200SN/A} 12210SN/A 12220SN/A 12230SN/A/* 12240SN/A * timer_stats - return timer statistics 12250SN/A */ 12260SN/Astatic void 12270SN/Atimer_stats( 12280SN/A sockaddr_u * srcadr, 12290SN/A endpt * inter, 12300SN/A struct req_pkt * inpkt 12310SN/A ) 12320SN/A{ 12330SN/A struct info_timer_stats * ts; 12340SN/A u_long sincereset; 12350SN/A 12360SN/A ts = (struct info_timer_stats *)prepare_pkt(srcadr, inter, 12370SN/A inpkt, sizeof(*ts)); 12380SN/A 12390SN/A sincereset = current_time - timer_timereset; 12400SN/A ts->timereset = htonl((u_int32)sincereset); 12410SN/A ts->alarms = ts->timereset; 12420SN/A ts->overflows = htonl((u_int32)alarm_overflow); 12430SN/A ts->xmtcalls = htonl((u_int32)timer_xmtcalls); 12440SN/A 12450SN/A (void) more_pkt(); 12460SN/A flush_pkt(); 12470SN/A} 12480SN/A 12490SN/A 12500SN/A/* 12510SN/A * loop_info - return the current state of the loop filter 12520SN/A */ 12530SN/Astatic void 12540SN/Aloop_info( 12550SN/A sockaddr_u *srcadr, 12560SN/A endpt *inter, 12570SN/A struct req_pkt *inpkt 12580SN/A ) 12590SN/A{ 12600SN/A struct info_loop *li; 12610SN/A l_fp ltmp; 12620SN/A 12630SN/A li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt, 12640SN/A sizeof(struct info_loop)); 12650SN/A 12660SN/A DTOLFP(last_offset, <mp); 12670SN/A HTONL_FP(<mp, &li->last_offset); 12680SN/A DTOLFP(drift_comp * 1e6, <mp); 12690SN/A HTONL_FP(<mp, &li->drift_comp); 12700SN/A li->compliance = htonl((u_int32)(tc_counter)); 12710SN/A li->watchdog_timer = htonl((u_int32)(current_time - sys_epoch)); 12720SN/A 12730SN/A (void) more_pkt(); 12740SN/A flush_pkt(); 12750SN/A} 12760SN/A 12770SN/A 12780SN/A/* 12790SN/A * do_conf - add a peer to the configuration list 12800SN/A */ 12810SN/Astatic void 12820SN/Ado_conf( 12830SN/A sockaddr_u *srcadr, 12840SN/A endpt *inter, 12850SN/A struct req_pkt *inpkt 12860SN/A ) 12870SN/A{ 12880SN/A u_short items; 12890SN/A size_t item_sz; 12900SN/A u_int fl; 12910SN/A char * datap; 12920SN/A struct conf_peer temp_cp; 12930SN/A sockaddr_u peeraddr; 12940SN/A 12950SN/A /* 12960SN/A * Do a check of everything to see that it looks 12970SN/A * okay. If not, complain about it. Note we are 12980SN/A * very picky here. 12990SN/A */ 13000SN/A items = INFO_NITEMS(inpkt->err_nitems); 13010SN/A item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 13020SN/A datap = inpkt->u.data; 13030SN/A if (item_sz > sizeof(temp_cp)) { 13040SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 13050SN/A return; 13060SN/A } 13070SN/A 13080SN/A while (items-- > 0) { 13090SN/A ZERO(temp_cp); 13100SN/A memcpy(&temp_cp, datap, item_sz); 13110SN/A ZERO_SOCK(&peeraddr); 13120SN/A 13130SN/A fl = 0; 13140SN/A if (temp_cp.flags & CONF_FLAG_PREFER) 13150SN/A fl |= FLAG_PREFER; 13160SN/A if (temp_cp.flags & CONF_FLAG_BURST) 13170SN/A fl |= FLAG_BURST; 13180SN/A if (temp_cp.flags & CONF_FLAG_IBURST) 13190SN/A fl |= FLAG_IBURST; 13200SN/A#ifdef AUTOKEY 13210SN/A if (temp_cp.flags & CONF_FLAG_SKEY) 13220SN/A fl |= FLAG_SKEY; 13230SN/A#endif /* AUTOKEY */ 13240SN/A if (client_v6_capable && temp_cp.v6_flag) { 13250SN/A AF(&peeraddr) = AF_INET6; 13260SN/A SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6; 13270SN/A } else { 13280SN/A AF(&peeraddr) = AF_INET; 13290SN/A NSRCADR(&peeraddr) = temp_cp.peeraddr; 13300SN/A /* 13310SN/A * Make sure the address is valid 13320SN/A */ 13330SN/A if (!ISREFCLOCKADR(&peeraddr) && 13340SN/A ISBADADR(&peeraddr)) { 13350SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 13360SN/A return; 13370SN/A } 13380SN/A 13390SN/A } 13400SN/A NSRCPORT(&peeraddr) = htons(NTP_PORT); 13410SN/A#ifdef ISC_PLATFORM_HAVESALEN 13420SN/A peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 13430SN/A#endif 13440SN/A 13450SN/A /* XXX W2DO? minpoll/maxpoll arguments ??? */ 13460SN/A if (peer_config(&peeraddr, NULL, NULL, 13470SN/A temp_cp.hmode, temp_cp.version, temp_cp.minpoll, 13480SN/A temp_cp.maxpoll, fl, temp_cp.ttl, temp_cp.keyid, 13490SN/A NULL) == 0) { 13500SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 13510SN/A return; 13520SN/A } 13530SN/A 13540SN/A datap += item_sz; 13550SN/A } 13560SN/A req_ack(srcadr, inter, inpkt, INFO_OKAY); 13570SN/A} 13580SN/A 13590SN/A 13600SN/A/* 13610SN/A * do_unconf - remove a peer from the configuration list 13620SN/A */ 13630SN/Astatic void 13640SN/Ado_unconf( 13650SN/A sockaddr_u * srcadr, 13660SN/A endpt * inter, 13670SN/A struct req_pkt *inpkt 13680SN/A ) 13690SN/A{ 13700SN/A u_short items; 13710SN/A size_t item_sz; 13720SN/A char * datap; 13730SN/A struct conf_unpeer temp_cp; 137415167Sssadetsky struct peer * p; 13750SN/A sockaddr_u peeraddr; 13760SN/A int bad; 13770SN/A int found; 13780SN/A 13790SN/A /* 13800SN/A * This is a bit unstructured, but I like to be careful. 138115167Sssadetsky * We check to see that every peer exists and is actually 13820SN/A * configured. If so, we remove them. If not, we return 13830SN/A * an error. 13840SN/A */ 13850SN/A items = INFO_NITEMS(inpkt->err_nitems); 13860SN/A item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 13870SN/A datap = inpkt->u.data; 13880SN/A if (item_sz > sizeof(temp_cp)) { 13890SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 13900SN/A return; 13910SN/A } 13920SN/A 13930SN/A bad = FALSE; 13940SN/A while (items-- > 0 && !bad) { 13950SN/A ZERO(temp_cp); 13960SN/A memcpy(&temp_cp, datap, item_sz); 13970SN/A ZERO_SOCK(&peeraddr); 13980SN/A if (client_v6_capable && temp_cp.v6_flag) { 13990SN/A AF(&peeraddr) = AF_INET6; 14000SN/A SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6; 14010SN/A } else { 14020SN/A AF(&peeraddr) = AF_INET; 14030SN/A NSRCADR(&peeraddr) = temp_cp.peeraddr; 14040SN/A } 14050SN/A SET_PORT(&peeraddr, NTP_PORT); 14060SN/A#ifdef ISC_PLATFORM_HAVESALEN 14070SN/A peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 14080SN/A#endif 14090SN/A found = FALSE; 14100SN/A p = NULL; 14110SN/A 14120SN/A DPRINTF(1, ("searching for %s\n", stoa(&peeraddr))); 14130SN/A 14140SN/A while (!found) { 14150SN/A p = findexistingpeer(&peeraddr, NULL, p, -1, 0); 141615272Sssadetsky if (NULL == p) 141715272Sssadetsky break; 141815272Sssadetsky if (FLAG_CONFIG & p->flags) 141915272Sssadetsky found = TRUE; 142015272Sssadetsky } 14210SN/A if (!found) 142215272Sssadetsky bad = TRUE; 14230SN/A 14240SN/A datap += item_sz; 14250SN/A } 14260SN/A 14270SN/A if (bad) { 14280SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 14290SN/A return; 14300SN/A } 14310SN/A 14320SN/A /* 14330SN/A * Now do it in earnest. 14340SN/A */ 14350SN/A 14360SN/A items = INFO_NITEMS(inpkt->err_nitems); 14370SN/A datap = inpkt->u.data; 14380SN/A 14390SN/A while (items-- > 0) { 14400SN/A ZERO(temp_cp); 14410SN/A memcpy(&temp_cp, datap, item_sz); 14420SN/A ZERO(peeraddr); 14430SN/A if (client_v6_capable && temp_cp.v6_flag) { 14440SN/A AF(&peeraddr) = AF_INET6; 14450SN/A SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6; 14460SN/A } else { 14470SN/A AF(&peeraddr) = AF_INET; 14480SN/A NSRCADR(&peeraddr) = temp_cp.peeraddr; 14490SN/A } 14500SN/A SET_PORT(&peeraddr, NTP_PORT); 14510SN/A#ifdef ISC_PLATFORM_HAVESALEN 14520SN/A peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 14530SN/A#endif 14540SN/A found = FALSE; 14550SN/A p = NULL; 14560SN/A 14570SN/A while (!found) { 14580SN/A p = findexistingpeer(&peeraddr, NULL, p, -1, 0); 14590SN/A if (NULL == p) 14600SN/A break; 14610SN/A if (FLAG_CONFIG & p->flags) 14620SN/A found = TRUE; 14630SN/A } 14640SN/A INSIST(found); 14650SN/A INSIST(NULL != p); 14660SN/A 14670SN/A peer_clear(p, "GONE"); 14680SN/A unpeer(p); 14690SN/A 14700SN/A datap += item_sz; 14710SN/A } 14720SN/A 14730SN/A req_ack(srcadr, inter, inpkt, INFO_OKAY); 14740SN/A} 14750SN/A 14760SN/A 14770SN/A/* 14780SN/A * set_sys_flag - set system flags 14790SN/A */ 14800SN/Astatic void 14810SN/Aset_sys_flag( 14820SN/A sockaddr_u *srcadr, 14830SN/A endpt *inter, 14840SN/A struct req_pkt *inpkt 14850SN/A ) 14860SN/A{ 14870SN/A setclr_flags(srcadr, inter, inpkt, 1); 14880SN/A} 14890SN/A 14900SN/A 14910SN/A/* 14920SN/A * clr_sys_flag - clear system flags 14930SN/A */ 14940SN/Astatic void 14950SN/Aclr_sys_flag( 14960SN/A sockaddr_u *srcadr, 14970SN/A endpt *inter, 14989595SN/A struct req_pkt *inpkt 14990SN/A ) 15000SN/A{ 15010SN/A setclr_flags(srcadr, inter, inpkt, 0); 15020SN/A} 15030SN/A 15040SN/A 15050SN/A/* 15060SN/A * setclr_flags - do the grunge work of flag setting/clearing 15070SN/A */ 15080SN/Astatic void 15090SN/Asetclr_flags( 15100SN/A sockaddr_u *srcadr, 15110SN/A endpt *inter, 15120SN/A struct req_pkt *inpkt, 15130SN/A u_long set 15140SN/A ) 15150SN/A{ 15160SN/A struct conf_sys_flags *sf; 15170SN/A u_int32 flags; 15180SN/A 15190SN/A if (INFO_NITEMS(inpkt->err_nitems) > 1) { 15200SN/A msyslog(LOG_ERR, "setclr_flags: err_nitems > 1"); 15210SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 15220SN/A return; 15230SN/A } 15240SN/A 15250SN/A sf = (struct conf_sys_flags *)&inpkt->u; 15260SN/A flags = ntohl(sf->flags); 15270SN/A 15280SN/A if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS | 15290SN/A SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR | 15300SN/A SYS_FLAG_FILEGEN | SYS_FLAG_AUTH | SYS_FLAG_CAL)) { 15310SN/A msyslog(LOG_ERR, "setclr_flags: extra flags: %#x", 15320SN/A flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS | 15330SN/A SYS_FLAG_NTP | SYS_FLAG_KERNEL | 15340SN/A SYS_FLAG_MONITOR | SYS_FLAG_FILEGEN | 15350SN/A SYS_FLAG_AUTH | SYS_FLAG_CAL)); 15360SN/A req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 15370SN/A return; 15380SN/A } 15390SN/A 15400SN/A if (flags & SYS_FLAG_BCLIENT) 15410SN/A proto_config(PROTO_BROADCLIENT, set, 0., NULL); 15420SN/A if (flags & SYS_FLAG_PPS) 15430SN/A proto_config(PROTO_PPS, set, 0., NULL); 15440SN/A if (flags & SYS_FLAG_NTP) 15450SN/A proto_config(PROTO_NTP, set, 0., NULL); 15460SN/A if (flags & SYS_FLAG_KERNEL) 15470SN/A proto_config(PROTO_KERNEL, set, 0., NULL); 15480SN/A if (flags & SYS_FLAG_MONITOR) 15490SN/A proto_config(PROTO_MONITOR, set, 0., NULL); 15500SN/A if (flags & SYS_FLAG_FILEGEN) 15510SN/A proto_config(PROTO_FILEGEN, set, 0., NULL); 15520SN/A if (flags & SYS_FLAG_AUTH) 15530SN/A proto_config(PROTO_AUTHENTICATE, set, 0., NULL); 15540SN/A if (flags & SYS_FLAG_CAL) 15550SN/A proto_config(PROTO_CAL, set, 0., NULL); 15560SN/A req_ack(srcadr, inter, inpkt, INFO_OKAY); 15570SN/A} 15580SN/A 15590SN/A/* There have been some issues with the restrict list processing, 15600SN/A * ranging from problems with deep recursion (resulting in stack 15610SN/A * overflows) and overfull reply buffers. 15620SN/A * 15630SN/A * To avoid this trouble the list reversal is done iteratively using a 15640SN/A * scratch pad. 15650SN/A */ 15660SN/Atypedef struct RestrictStack RestrictStackT; 15679595SN/Astruct RestrictStack { 15680SN/A RestrictStackT *link; 15690SN/A size_t fcnt; 15700SN/A const restrict_u *pres[63]; 15710SN/A}; 15720SN/A 15730SN/Astatic size_t 15740SN/AgetStackSheetSize( 15750SN/A RestrictStackT *sp 15760SN/A ) 15770SN/A{ 15780SN/A if (sp) 15790SN/A return sizeof(sp->pres)/sizeof(sp->pres[0]); 15800SN/A return 0u; 15810SN/A} 15820SN/A 15830SN/Astatic int/*BOOL*/ 15840SN/ApushRestriction( 15850SN/A RestrictStackT **spp, 15860SN/A const restrict_u *ptr 15870SN/A ) 15880SN/A{ 15890SN/A RestrictStackT *sp; 15900SN/A 15910SN/A if (NULL == (sp = *spp) || 0 == sp->fcnt) { 15920SN/A /* need another sheet in the scratch pad */ 15930SN/A sp = emalloc(sizeof(*sp)); 15940SN/A sp->link = *spp; 15950SN/A sp->fcnt = getStackSheetSize(sp); 15960SN/A *spp = sp; 15970SN/A } 15980SN/A sp->pres[--sp->fcnt] = ptr; 15990SN/A return TRUE; 16000SN/A} 16010SN/A 16020SN/Astatic int/*BOOL*/ 16030SN/ApopRestriction( 16040SN/A RestrictStackT **spp, 16050SN/A const restrict_u **opp 16060SN/A ) 1607{ 1608 RestrictStackT *sp; 1609 1610 if (NULL == (sp = *spp) || sp->fcnt >= getStackSheetSize(sp)) 1611 return FALSE; 1612 1613 *opp = sp->pres[sp->fcnt++]; 1614 if (sp->fcnt >= getStackSheetSize(sp)) { 1615 /* discard sheet from scratch pad */ 1616 *spp = sp->link; 1617 free(sp); 1618 } 1619 return TRUE; 1620} 1621 1622static void 1623flushRestrictionStack( 1624 RestrictStackT **spp 1625 ) 1626{ 1627 RestrictStackT *sp; 1628 1629 while (NULL != (sp = *spp)) { 1630 *spp = sp->link; 1631 free(sp); 1632 } 1633} 1634 1635/* 1636 * list_restrict4 - iterative helper for list_restrict dumps IPv4 1637 * restriction list in reverse order. 1638 */ 1639static void 1640list_restrict4( 1641 const restrict_u * res, 1642 struct info_restrict ** ppir 1643 ) 1644{ 1645 RestrictStackT * rpad; 1646 struct info_restrict * pir; 1647 1648 pir = *ppir; 1649 for (rpad = NULL; res; res = res->link) 1650 if (!pushRestriction(&rpad, res)) 1651 break; 1652 1653 while (pir && popRestriction(&rpad, &res)) { 1654 pir->addr = htonl(res->u.v4.addr); 1655 if (client_v6_capable) 1656 pir->v6_flag = 0; 1657 pir->mask = htonl(res->u.v4.mask); 1658 pir->count = htonl(res->count); 1659 pir->flags = htons(res->flags); 1660 pir->mflags = htons(res->mflags); 1661 pir = (struct info_restrict *)more_pkt(); 1662 } 1663 flushRestrictionStack(&rpad); 1664 *ppir = pir; 1665} 1666 1667/* 1668 * list_restrict6 - iterative helper for list_restrict dumps IPv6 1669 * restriction list in reverse order. 1670 */ 1671static void 1672list_restrict6( 1673 const restrict_u * res, 1674 struct info_restrict ** ppir 1675 ) 1676{ 1677 RestrictStackT * rpad; 1678 struct info_restrict * pir; 1679 1680 pir = *ppir; 1681 for (rpad = NULL; res; res = res->link) 1682 if (!pushRestriction(&rpad, res)) 1683 break; 1684 1685 while (pir && popRestriction(&rpad, &res)) { 1686 pir->addr6 = res->u.v6.addr; 1687 pir->mask6 = res->u.v6.mask; 1688 pir->v6_flag = 1; 1689 pir->count = htonl(res->count); 1690 pir->flags = htons(res->flags); 1691 pir->mflags = htons(res->mflags); 1692 pir = (struct info_restrict *)more_pkt(); 1693 } 1694 flushRestrictionStack(&rpad); 1695 *ppir = pir; 1696} 1697 1698 1699/* 1700 * list_restrict - return the restrict list 1701 */ 1702static void 1703list_restrict( 1704 sockaddr_u *srcadr, 1705 endpt *inter, 1706 struct req_pkt *inpkt 1707 ) 1708{ 1709 struct info_restrict *ir; 1710 1711 DPRINTF(3, ("wants restrict list summary\n")); 1712 1713 ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt, 1714 v6sizeof(struct info_restrict)); 1715 1716 /* 1717 * The restriction lists are kept sorted in the reverse order 1718 * than they were originally. To preserve the output semantics, 1719 * dump each list in reverse order. The workers take care of that. 1720 */ 1721 list_restrict4(restrictlist4, &ir); 1722 if (client_v6_capable) 1723 list_restrict6(restrictlist6, &ir); 1724 flush_pkt(); 1725} 1726 1727 1728/* 1729 * do_resaddflags - add flags to a restrict entry (or create one) 1730 */ 1731static void 1732do_resaddflags( 1733 sockaddr_u *srcadr, 1734 endpt *inter, 1735 struct req_pkt *inpkt 1736 ) 1737{ 1738 do_restrict(srcadr, inter, inpkt, RESTRICT_FLAGS); 1739} 1740 1741 1742 1743/* 1744 * do_ressubflags - remove flags from a restrict entry 1745 */ 1746static void 1747do_ressubflags( 1748 sockaddr_u *srcadr, 1749 endpt *inter, 1750 struct req_pkt *inpkt 1751 ) 1752{ 1753 do_restrict(srcadr, inter, inpkt, RESTRICT_UNFLAG); 1754} 1755 1756 1757/* 1758 * do_unrestrict - remove a restrict entry from the list 1759 */ 1760static void 1761do_unrestrict( 1762 sockaddr_u *srcadr, 1763 endpt *inter, 1764 struct req_pkt *inpkt 1765 ) 1766{ 1767 do_restrict(srcadr, inter, inpkt, RESTRICT_REMOVE); 1768} 1769 1770 1771/* 1772 * do_restrict - do the dirty stuff of dealing with restrictions 1773 */ 1774static void 1775do_restrict( 1776 sockaddr_u *srcadr, 1777 endpt *inter, 1778 struct req_pkt *inpkt, 1779 int op 1780 ) 1781{ 1782 char * datap; 1783 struct conf_restrict cr; 1784 u_short items; 1785 size_t item_sz; 1786 sockaddr_u matchaddr; 1787 sockaddr_u matchmask; 1788 int bad; 1789 1790 /* 1791 * Do a check of the flags to make sure that only 1792 * the NTPPORT flag is set, if any. If not, complain 1793 * about it. Note we are very picky here. 1794 */ 1795 items = INFO_NITEMS(inpkt->err_nitems); 1796 item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 1797 datap = inpkt->u.data; 1798 if (item_sz > sizeof(cr)) { 1799 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1800 return; 1801 } 1802 1803 bad = FALSE; 1804 while (items-- > 0 && !bad) { 1805 memcpy(&cr, datap, item_sz); 1806 cr.flags = ntohs(cr.flags); 1807 cr.mflags = ntohs(cr.mflags); 1808 if (~RESM_NTPONLY & cr.mflags) 1809 bad |= 1; 1810 if (~RES_ALLFLAGS & cr.flags) 1811 bad |= 2; 1812 if (INADDR_ANY != cr.mask) { 1813 if (client_v6_capable && cr.v6_flag) { 1814 if (IN6_IS_ADDR_UNSPECIFIED(&cr.addr6)) 1815 bad |= 4; 1816 } else { 1817 if (INADDR_ANY == cr.addr) 1818 bad |= 8; 1819 } 1820 } 1821 datap += item_sz; 1822 } 1823 1824 if (bad) { 1825 msyslog(LOG_ERR, "do_restrict: bad = %#x", bad); 1826 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1827 return; 1828 } 1829 1830 /* 1831 * Looks okay, try it out. Needs to reload data pointer and 1832 * item counter. (Talos-CAN-0052) 1833 */ 1834 ZERO_SOCK(&matchaddr); 1835 ZERO_SOCK(&matchmask); 1836 items = INFO_NITEMS(inpkt->err_nitems); 1837 datap = inpkt->u.data; 1838 1839 while (items-- > 0) { 1840 memcpy(&cr, datap, item_sz); 1841 cr.flags = ntohs(cr.flags); 1842 cr.mflags = ntohs(cr.mflags); 1843 if (client_v6_capable && cr.v6_flag) { 1844 AF(&matchaddr) = AF_INET6; 1845 AF(&matchmask) = AF_INET6; 1846 SOCK_ADDR6(&matchaddr) = cr.addr6; 1847 SOCK_ADDR6(&matchmask) = cr.mask6; 1848 } else { 1849 AF(&matchaddr) = AF_INET; 1850 AF(&matchmask) = AF_INET; 1851 NSRCADR(&matchaddr) = cr.addr; 1852 NSRCADR(&matchmask) = cr.mask; 1853 } 1854 hack_restrict(op, &matchaddr, &matchmask, cr.mflags, 1855 cr.flags, 0); 1856 datap += item_sz; 1857 } 1858 1859 req_ack(srcadr, inter, inpkt, INFO_OKAY); 1860} 1861 1862 1863/* 1864 * mon_getlist - return monitor data 1865 */ 1866static void 1867mon_getlist( 1868 sockaddr_u *srcadr, 1869 endpt *inter, 1870 struct req_pkt *inpkt 1871 ) 1872{ 1873 req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1874} 1875 1876 1877/* 1878 * Module entry points and the flags they correspond with 1879 */ 1880struct reset_entry { 1881 int flag; /* flag this corresponds to */ 1882 void (*handler)(void); /* routine to handle request */ 1883}; 1884 1885struct reset_entry reset_entries[] = { 1886 { RESET_FLAG_ALLPEERS, peer_all_reset }, 1887 { RESET_FLAG_IO, io_clr_stats }, 1888 { RESET_FLAG_SYS, proto_clr_stats }, 1889 { RESET_FLAG_MEM, peer_clr_stats }, 1890 { RESET_FLAG_TIMER, timer_clr_stats }, 1891 { RESET_FLAG_AUTH, reset_auth_stats }, 1892 { RESET_FLAG_CTL, ctl_clr_stats }, 1893 { 0, 0 } 1894}; 1895 1896/* 1897 * reset_stats - reset statistic counters here and there 1898 */ 1899static void 1900reset_stats( 1901 sockaddr_u *srcadr, 1902 endpt *inter, 1903 struct req_pkt *inpkt 1904 ) 1905{ 1906 struct reset_flags *rflags; 1907 u_long flags; 1908 struct reset_entry *rent; 1909 1910 if (INFO_NITEMS(inpkt->err_nitems) > 1) { 1911 msyslog(LOG_ERR, "reset_stats: err_nitems > 1"); 1912 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1913 return; 1914 } 1915 1916 rflags = (struct reset_flags *)&inpkt->u; 1917 flags = ntohl(rflags->flags); 1918 1919 if (flags & ~RESET_ALLFLAGS) { 1920 msyslog(LOG_ERR, "reset_stats: reset leaves %#lx", 1921 flags & ~RESET_ALLFLAGS); 1922 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1923 return; 1924 } 1925 1926 for (rent = reset_entries; rent->flag != 0; rent++) { 1927 if (flags & rent->flag) 1928 (*rent->handler)(); 1929 } 1930 req_ack(srcadr, inter, inpkt, INFO_OKAY); 1931} 1932 1933 1934/* 1935 * reset_peer - clear a peer's statistics 1936 */ 1937static void 1938reset_peer( 1939 sockaddr_u *srcadr, 1940 endpt *inter, 1941 struct req_pkt *inpkt 1942 ) 1943{ 1944 u_short items; 1945 size_t item_sz; 1946 char * datap; 1947 struct conf_unpeer cp; 1948 struct peer * p; 1949 sockaddr_u peeraddr; 1950 int bad; 1951 1952 /* 1953 * We check first to see that every peer exists. If not, 1954 * we return an error. 1955 */ 1956 1957 items = INFO_NITEMS(inpkt->err_nitems); 1958 item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 1959 datap = inpkt->u.data; 1960 if (item_sz > sizeof(cp)) { 1961 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1962 return; 1963 } 1964 1965 bad = FALSE; 1966 while (items-- > 0 && !bad) { 1967 ZERO(cp); 1968 memcpy(&cp, datap, item_sz); 1969 ZERO_SOCK(&peeraddr); 1970 if (client_v6_capable && cp.v6_flag) { 1971 AF(&peeraddr) = AF_INET6; 1972 SOCK_ADDR6(&peeraddr) = cp.peeraddr6; 1973 } else { 1974 AF(&peeraddr) = AF_INET; 1975 NSRCADR(&peeraddr) = cp.peeraddr; 1976 } 1977 1978#ifdef ISC_PLATFORM_HAVESALEN 1979 peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 1980#endif 1981 p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0); 1982 if (NULL == p) 1983 bad++; 1984 datap += item_sz; 1985 } 1986 1987 if (bad) { 1988 req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1989 return; 1990 } 1991 1992 /* 1993 * Now do it in earnest. Needs to reload data pointer and item 1994 * counter. (Talos-CAN-0052) 1995 */ 1996 1997 items = INFO_NITEMS(inpkt->err_nitems); 1998 datap = inpkt->u.data; 1999 while (items-- > 0) { 2000 ZERO(cp); 2001 memcpy(&cp, datap, item_sz); 2002 ZERO_SOCK(&peeraddr); 2003 if (client_v6_capable && cp.v6_flag) { 2004 AF(&peeraddr) = AF_INET6; 2005 SOCK_ADDR6(&peeraddr) = cp.peeraddr6; 2006 } else { 2007 AF(&peeraddr) = AF_INET; 2008 NSRCADR(&peeraddr) = cp.peeraddr; 2009 } 2010 SET_PORT(&peeraddr, 123); 2011#ifdef ISC_PLATFORM_HAVESALEN 2012 peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 2013#endif 2014 p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0); 2015 while (p != NULL) { 2016 peer_reset(p); 2017 p = findexistingpeer(&peeraddr, NULL, p, -1, 0); 2018 } 2019 datap += item_sz; 2020 } 2021 2022 req_ack(srcadr, inter, inpkt, INFO_OKAY); 2023} 2024 2025 2026/* 2027 * do_key_reread - reread the encryption key file 2028 */ 2029static void 2030do_key_reread( 2031 sockaddr_u *srcadr, 2032 endpt *inter, 2033 struct req_pkt *inpkt 2034 ) 2035{ 2036 rereadkeys(); 2037 req_ack(srcadr, inter, inpkt, INFO_OKAY); 2038} 2039 2040 2041/* 2042 * trust_key - make one or more keys trusted 2043 */ 2044static void 2045trust_key( 2046 sockaddr_u *srcadr, 2047 endpt *inter, 2048 struct req_pkt *inpkt 2049 ) 2050{ 2051 do_trustkey(srcadr, inter, inpkt, 1); 2052} 2053 2054 2055/* 2056 * untrust_key - make one or more keys untrusted 2057 */ 2058static void 2059untrust_key( 2060 sockaddr_u *srcadr, 2061 endpt *inter, 2062 struct req_pkt *inpkt 2063 ) 2064{ 2065 do_trustkey(srcadr, inter, inpkt, 0); 2066} 2067 2068 2069/* 2070 * do_trustkey - make keys either trustable or untrustable 2071 */ 2072static void 2073do_trustkey( 2074 sockaddr_u *srcadr, 2075 endpt *inter, 2076 struct req_pkt *inpkt, 2077 u_long trust 2078 ) 2079{ 2080 register uint32_t *kp; 2081 register int items; 2082 2083 items = INFO_NITEMS(inpkt->err_nitems); 2084 kp = (uint32_t *)&inpkt->u; 2085 while (items-- > 0) { 2086 authtrust(*kp, trust); 2087 kp++; 2088 } 2089 2090 req_ack(srcadr, inter, inpkt, INFO_OKAY); 2091} 2092 2093 2094/* 2095 * get_auth_info - return some stats concerning the authentication module 2096 */ 2097static void 2098get_auth_info( 2099 sockaddr_u *srcadr, 2100 endpt *inter, 2101 struct req_pkt *inpkt 2102 ) 2103{ 2104 register struct info_auth *ia; 2105 2106 ia = (struct info_auth *)prepare_pkt(srcadr, inter, inpkt, 2107 sizeof(struct info_auth)); 2108 2109 ia->numkeys = htonl((u_int32)authnumkeys); 2110 ia->numfreekeys = htonl((u_int32)authnumfreekeys); 2111 ia->keylookups = htonl((u_int32)authkeylookups); 2112 ia->keynotfound = htonl((u_int32)authkeynotfound); 2113 ia->encryptions = htonl((u_int32)authencryptions); 2114 ia->decryptions = htonl((u_int32)authdecryptions); 2115 ia->keyuncached = htonl((u_int32)authkeyuncached); 2116 ia->expired = htonl((u_int32)authkeyexpired); 2117 ia->timereset = htonl((u_int32)(current_time - auth_timereset)); 2118 2119 (void) more_pkt(); 2120 flush_pkt(); 2121} 2122 2123 2124 2125/* 2126 * reset_auth_stats - reset the authentication stat counters. Done here 2127 * to keep ntp-isms out of the authentication module 2128 */ 2129void 2130reset_auth_stats(void) 2131{ 2132 authkeylookups = 0; 2133 authkeynotfound = 0; 2134 authencryptions = 0; 2135 authdecryptions = 0; 2136 authkeyuncached = 0; 2137 auth_timereset = current_time; 2138} 2139 2140 2141/* 2142 * req_get_traps - return information about current trap holders 2143 */ 2144static void 2145req_get_traps( 2146 sockaddr_u *srcadr, 2147 endpt *inter, 2148 struct req_pkt *inpkt 2149 ) 2150{ 2151 struct info_trap *it; 2152 struct ctl_trap *tr; 2153 size_t i; 2154 2155 if (num_ctl_traps == 0) { 2156 req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2157 return; 2158 } 2159 2160 it = (struct info_trap *)prepare_pkt(srcadr, inter, inpkt, 2161 v6sizeof(struct info_trap)); 2162 2163 for (i = 0, tr = ctl_traps; it && i < COUNTOF(ctl_traps); i++, tr++) { 2164 if (tr->tr_flags & TRAP_INUSE) { 2165 if (IS_IPV4(&tr->tr_addr)) { 2166 if (tr->tr_localaddr == any_interface) 2167 it->local_address = 0; 2168 else 2169 it->local_address 2170 = NSRCADR(&tr->tr_localaddr->sin); 2171 it->trap_address = NSRCADR(&tr->tr_addr); 2172 if (client_v6_capable) 2173 it->v6_flag = 0; 2174 } else { 2175 if (!client_v6_capable) 2176 continue; 2177 it->local_address6 2178 = SOCK_ADDR6(&tr->tr_localaddr->sin); 2179 it->trap_address6 = SOCK_ADDR6(&tr->tr_addr); 2180 it->v6_flag = 1; 2181 } 2182 it->trap_port = NSRCPORT(&tr->tr_addr); 2183 it->sequence = htons(tr->tr_sequence); 2184 it->settime = htonl((u_int32)(current_time - tr->tr_settime)); 2185 it->origtime = htonl((u_int32)(current_time - tr->tr_origtime)); 2186 it->resets = htonl((u_int32)tr->tr_resets); 2187 it->flags = htonl((u_int32)tr->tr_flags); 2188 it = (struct info_trap *)more_pkt(); 2189 } 2190 } 2191 flush_pkt(); 2192} 2193 2194 2195/* 2196 * req_set_trap - configure a trap 2197 */ 2198static void 2199req_set_trap( 2200 sockaddr_u *srcadr, 2201 endpt *inter, 2202 struct req_pkt *inpkt 2203 ) 2204{ 2205 do_setclr_trap(srcadr, inter, inpkt, 1); 2206} 2207 2208 2209 2210/* 2211 * req_clr_trap - unconfigure a trap 2212 */ 2213static void 2214req_clr_trap( 2215 sockaddr_u *srcadr, 2216 endpt *inter, 2217 struct req_pkt *inpkt 2218 ) 2219{ 2220 do_setclr_trap(srcadr, inter, inpkt, 0); 2221} 2222 2223 2224 2225/* 2226 * do_setclr_trap - do the grunge work of (un)configuring a trap 2227 */ 2228static void 2229do_setclr_trap( 2230 sockaddr_u *srcadr, 2231 endpt *inter, 2232 struct req_pkt *inpkt, 2233 int set 2234 ) 2235{ 2236 register struct conf_trap *ct; 2237 register endpt *linter; 2238 int res; 2239 sockaddr_u laddr; 2240 2241 /* 2242 * Prepare sockaddr 2243 */ 2244 ZERO_SOCK(&laddr); 2245 AF(&laddr) = AF(srcadr); 2246 SET_PORT(&laddr, NTP_PORT); 2247 2248 /* 2249 * Restrict ourselves to one item only. This eliminates 2250 * the error reporting problem. 2251 */ 2252 if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2253 msyslog(LOG_ERR, "do_setclr_trap: err_nitems > 1"); 2254 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2255 return; 2256 } 2257 ct = (struct conf_trap *)&inpkt->u; 2258 2259 /* 2260 * Look for the local interface. If none, use the default. 2261 */ 2262 if (ct->local_address == 0) { 2263 linter = any_interface; 2264 } else { 2265 if (IS_IPV4(&laddr)) 2266 NSRCADR(&laddr) = ct->local_address; 2267 else 2268 SOCK_ADDR6(&laddr) = ct->local_address6; 2269 linter = findinterface(&laddr); 2270 if (NULL == linter) { 2271 req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2272 return; 2273 } 2274 } 2275 2276 if (IS_IPV4(&laddr)) 2277 NSRCADR(&laddr) = ct->trap_address; 2278 else 2279 SOCK_ADDR6(&laddr) = ct->trap_address6; 2280 if (ct->trap_port) 2281 NSRCPORT(&laddr) = ct->trap_port; 2282 else 2283 SET_PORT(&laddr, TRAPPORT); 2284 2285 if (set) { 2286 res = ctlsettrap(&laddr, linter, 0, 2287 INFO_VERSION(inpkt->rm_vn_mode)); 2288 } else { 2289 res = ctlclrtrap(&laddr, linter, 0); 2290 } 2291 2292 if (!res) { 2293 req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2294 } else { 2295 req_ack(srcadr, inter, inpkt, INFO_OKAY); 2296 } 2297 return; 2298} 2299 2300 2301 2302/* 2303 * set_request_keyid - set the keyid used to authenticate requests 2304 */ 2305static void 2306set_request_keyid( 2307 sockaddr_u *srcadr, 2308 endpt *inter, 2309 struct req_pkt *inpkt 2310 ) 2311{ 2312 keyid_t *pkeyid; 2313 2314 /* 2315 * Restrict ourselves to one item only. 2316 */ 2317 if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2318 msyslog(LOG_ERR, "set_request_keyid: err_nitems > 1"); 2319 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2320 return; 2321 } 2322 2323 pkeyid = (keyid_t *)&inpkt->u; 2324 info_auth_keyid = ntohl(*pkeyid); 2325 req_ack(srcadr, inter, inpkt, INFO_OKAY); 2326} 2327 2328 2329 2330/* 2331 * set_control_keyid - set the keyid used to authenticate requests 2332 */ 2333static void 2334set_control_keyid( 2335 sockaddr_u *srcadr, 2336 endpt *inter, 2337 struct req_pkt *inpkt 2338 ) 2339{ 2340 keyid_t *pkeyid; 2341 2342 /* 2343 * Restrict ourselves to one item only. 2344 */ 2345 if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2346 msyslog(LOG_ERR, "set_control_keyid: err_nitems > 1"); 2347 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2348 return; 2349 } 2350 2351 pkeyid = (keyid_t *)&inpkt->u; 2352 ctl_auth_keyid = ntohl(*pkeyid); 2353 req_ack(srcadr, inter, inpkt, INFO_OKAY); 2354} 2355 2356 2357 2358/* 2359 * get_ctl_stats - return some stats concerning the control message module 2360 */ 2361static void 2362get_ctl_stats( 2363 sockaddr_u *srcadr, 2364 endpt *inter, 2365 struct req_pkt *inpkt 2366 ) 2367{ 2368 register struct info_control *ic; 2369 2370 ic = (struct info_control *)prepare_pkt(srcadr, inter, inpkt, 2371 sizeof(struct info_control)); 2372 2373 ic->ctltimereset = htonl((u_int32)(current_time - ctltimereset)); 2374 ic->numctlreq = htonl((u_int32)numctlreq); 2375 ic->numctlbadpkts = htonl((u_int32)numctlbadpkts); 2376 ic->numctlresponses = htonl((u_int32)numctlresponses); 2377 ic->numctlfrags = htonl((u_int32)numctlfrags); 2378 ic->numctlerrors = htonl((u_int32)numctlerrors); 2379 ic->numctltooshort = htonl((u_int32)numctltooshort); 2380 ic->numctlinputresp = htonl((u_int32)numctlinputresp); 2381 ic->numctlinputfrag = htonl((u_int32)numctlinputfrag); 2382 ic->numctlinputerr = htonl((u_int32)numctlinputerr); 2383 ic->numctlbadoffset = htonl((u_int32)numctlbadoffset); 2384 ic->numctlbadversion = htonl((u_int32)numctlbadversion); 2385 ic->numctldatatooshort = htonl((u_int32)numctldatatooshort); 2386 ic->numctlbadop = htonl((u_int32)numctlbadop); 2387 ic->numasyncmsgs = htonl((u_int32)numasyncmsgs); 2388 2389 (void) more_pkt(); 2390 flush_pkt(); 2391} 2392 2393 2394#ifdef KERNEL_PLL 2395/* 2396 * get_kernel_info - get kernel pll/pps information 2397 */ 2398static void 2399get_kernel_info( 2400 sockaddr_u *srcadr, 2401 endpt *inter, 2402 struct req_pkt *inpkt 2403 ) 2404{ 2405 register struct info_kernel *ik; 2406 struct timex ntx; 2407 2408 if (!pll_control) { 2409 req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2410 return; 2411 } 2412 2413 ZERO(ntx); 2414 if (ntp_adjtime(&ntx) < 0) 2415 msyslog(LOG_ERR, "get_kernel_info: ntp_adjtime() failed: %m"); 2416 ik = (struct info_kernel *)prepare_pkt(srcadr, inter, inpkt, 2417 sizeof(struct info_kernel)); 2418 2419 /* 2420 * pll variables 2421 */ 2422 ik->offset = htonl((u_int32)ntx.offset); 2423 ik->freq = htonl((u_int32)ntx.freq); 2424 ik->maxerror = htonl((u_int32)ntx.maxerror); 2425 ik->esterror = htonl((u_int32)ntx.esterror); 2426 ik->status = htons(ntx.status); 2427 ik->constant = htonl((u_int32)ntx.constant); 2428 ik->precision = htonl((u_int32)ntx.precision); 2429 ik->tolerance = htonl((u_int32)ntx.tolerance); 2430 2431 /* 2432 * pps variables 2433 */ 2434 ik->ppsfreq = htonl((u_int32)ntx.ppsfreq); 2435 ik->jitter = htonl((u_int32)ntx.jitter); 2436 ik->shift = htons(ntx.shift); 2437 ik->stabil = htonl((u_int32)ntx.stabil); 2438 ik->jitcnt = htonl((u_int32)ntx.jitcnt); 2439 ik->calcnt = htonl((u_int32)ntx.calcnt); 2440 ik->errcnt = htonl((u_int32)ntx.errcnt); 2441 ik->stbcnt = htonl((u_int32)ntx.stbcnt); 2442 2443 (void) more_pkt(); 2444 flush_pkt(); 2445} 2446#endif /* KERNEL_PLL */ 2447 2448 2449#ifdef REFCLOCK 2450/* 2451 * get_clock_info - get info about a clock 2452 */ 2453static void 2454get_clock_info( 2455 sockaddr_u *srcadr, 2456 endpt *inter, 2457 struct req_pkt *inpkt 2458 ) 2459{ 2460 register struct info_clock *ic; 2461 register u_int32 *clkaddr; 2462 register int items; 2463 struct refclockstat clock_stat; 2464 sockaddr_u addr; 2465 l_fp ltmp; 2466 2467 ZERO_SOCK(&addr); 2468 AF(&addr) = AF_INET; 2469#ifdef ISC_PLATFORM_HAVESALEN 2470 addr.sa.sa_len = SOCKLEN(&addr); 2471#endif 2472 SET_PORT(&addr, NTP_PORT); 2473 items = INFO_NITEMS(inpkt->err_nitems); 2474 clkaddr = &inpkt->u.u32[0]; 2475 2476 ic = (struct info_clock *)prepare_pkt(srcadr, inter, inpkt, 2477 sizeof(struct info_clock)); 2478 2479 while (items-- > 0 && ic) { 2480 NSRCADR(&addr) = *clkaddr++; 2481 if (!ISREFCLOCKADR(&addr) || NULL == 2482 findexistingpeer(&addr, NULL, NULL, -1, 0)) { 2483 req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2484 return; 2485 } 2486 2487 clock_stat.kv_list = (struct ctl_var *)0; 2488 2489 refclock_control(&addr, NULL, &clock_stat); 2490 2491 ic->clockadr = NSRCADR(&addr); 2492 ic->type = clock_stat.type; 2493 ic->flags = clock_stat.flags; 2494 ic->lastevent = clock_stat.lastevent; 2495 ic->currentstatus = clock_stat.currentstatus; 2496 ic->polls = htonl((u_int32)clock_stat.polls); 2497 ic->noresponse = htonl((u_int32)clock_stat.noresponse); 2498 ic->badformat = htonl((u_int32)clock_stat.badformat); 2499 ic->baddata = htonl((u_int32)clock_stat.baddata); 2500 ic->timestarted = htonl((u_int32)clock_stat.timereset); 2501 DTOLFP(clock_stat.fudgetime1, <mp); 2502 HTONL_FP(<mp, &ic->fudgetime1); 2503 DTOLFP(clock_stat.fudgetime2, <mp); 2504 HTONL_FP(<mp, &ic->fudgetime2); 2505 ic->fudgeval1 = htonl((u_int32)clock_stat.fudgeval1); 2506 ic->fudgeval2 = htonl(clock_stat.fudgeval2); 2507 2508 free_varlist(clock_stat.kv_list); 2509 2510 ic = (struct info_clock *)more_pkt(); 2511 } 2512 flush_pkt(); 2513} 2514 2515 2516 2517/* 2518 * set_clock_fudge - get a clock's fudge factors 2519 */ 2520static void 2521set_clock_fudge( 2522 sockaddr_u *srcadr, 2523 endpt *inter, 2524 struct req_pkt *inpkt 2525 ) 2526{ 2527 register struct conf_fudge *cf; 2528 register int items; 2529 struct refclockstat clock_stat; 2530 sockaddr_u addr; 2531 l_fp ltmp; 2532 2533 ZERO(addr); 2534 ZERO(clock_stat); 2535 items = INFO_NITEMS(inpkt->err_nitems); 2536 cf = (struct conf_fudge *)&inpkt->u; 2537 2538 while (items-- > 0) { 2539 AF(&addr) = AF_INET; 2540 NSRCADR(&addr) = cf->clockadr; 2541#ifdef ISC_PLATFORM_HAVESALEN 2542 addr.sa.sa_len = SOCKLEN(&addr); 2543#endif 2544 SET_PORT(&addr, NTP_PORT); 2545 if (!ISREFCLOCKADR(&addr) || NULL == 2546 findexistingpeer(&addr, NULL, NULL, -1, 0)) { 2547 req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2548 return; 2549 } 2550 2551 switch(ntohl(cf->which)) { 2552 case FUDGE_TIME1: 2553 NTOHL_FP(&cf->fudgetime, <mp); 2554 LFPTOD(<mp, clock_stat.fudgetime1); 2555 clock_stat.haveflags = CLK_HAVETIME1; 2556 break; 2557 case FUDGE_TIME2: 2558 NTOHL_FP(&cf->fudgetime, <mp); 2559 LFPTOD(<mp, clock_stat.fudgetime2); 2560 clock_stat.haveflags = CLK_HAVETIME2; 2561 break; 2562 case FUDGE_VAL1: 2563 clock_stat.fudgeval1 = ntohl(cf->fudgeval_flags); 2564 clock_stat.haveflags = CLK_HAVEVAL1; 2565 break; 2566 case FUDGE_VAL2: 2567 clock_stat.fudgeval2 = ntohl(cf->fudgeval_flags); 2568 clock_stat.haveflags = CLK_HAVEVAL2; 2569 break; 2570 case FUDGE_FLAGS: 2571 clock_stat.flags = (u_char) (ntohl(cf->fudgeval_flags) & 0xf); 2572 clock_stat.haveflags = 2573 (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4); 2574 break; 2575 default: 2576 msyslog(LOG_ERR, "set_clock_fudge: default!"); 2577 req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2578 return; 2579 } 2580 2581 refclock_control(&addr, &clock_stat, (struct refclockstat *)0); 2582 } 2583 2584 req_ack(srcadr, inter, inpkt, INFO_OKAY); 2585} 2586#endif 2587 2588#ifdef REFCLOCK 2589/* 2590 * get_clkbug_info - get debugging info about a clock 2591 */ 2592static void 2593get_clkbug_info( 2594 sockaddr_u *srcadr, 2595 endpt *inter, 2596 struct req_pkt *inpkt 2597 ) 2598{ 2599 register int i; 2600 register struct info_clkbug *ic; 2601 register u_int32 *clkaddr; 2602 register int items; 2603 struct refclockbug bug; 2604 sockaddr_u addr; 2605 2606 ZERO_SOCK(&addr); 2607 AF(&addr) = AF_INET; 2608#ifdef ISC_PLATFORM_HAVESALEN 2609 addr.sa.sa_len = SOCKLEN(&addr); 2610#endif 2611 SET_PORT(&addr, NTP_PORT); 2612 items = INFO_NITEMS(inpkt->err_nitems); 2613 clkaddr = (u_int32 *)&inpkt->u; 2614 2615 ic = (struct info_clkbug *)prepare_pkt(srcadr, inter, inpkt, 2616 sizeof(struct info_clkbug)); 2617 2618 while (items-- > 0 && ic) { 2619 NSRCADR(&addr) = *clkaddr++; 2620 if (!ISREFCLOCKADR(&addr) || NULL == 2621 findexistingpeer(&addr, NULL, NULL, -1, 0)) { 2622 req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2623 return; 2624 } 2625 2626 ZERO(bug); 2627 refclock_buginfo(&addr, &bug); 2628 if (bug.nvalues == 0 && bug.ntimes == 0) { 2629 req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2630 return; 2631 } 2632 2633 ic->clockadr = NSRCADR(&addr); 2634 i = bug.nvalues; 2635 if (i > NUMCBUGVALUES) 2636 i = NUMCBUGVALUES; 2637 ic->nvalues = (u_char)i; 2638 ic->svalues = htons((u_short) (bug.svalues & ((1<<i)-1))); 2639 while (--i >= 0) 2640 ic->values[i] = htonl(bug.values[i]); 2641 2642 i = bug.ntimes; 2643 if (i > NUMCBUGTIMES) 2644 i = NUMCBUGTIMES; 2645 ic->ntimes = (u_char)i; 2646 ic->stimes = htonl(bug.stimes); 2647 while (--i >= 0) { 2648 HTONL_FP(&bug.times[i], &ic->times[i]); 2649 } 2650 2651 ic = (struct info_clkbug *)more_pkt(); 2652 } 2653 flush_pkt(); 2654} 2655#endif 2656 2657/* 2658 * receiver of interface structures 2659 */ 2660static void 2661fill_info_if_stats(void *data, interface_info_t *interface_info) 2662{ 2663 struct info_if_stats **ifsp = (struct info_if_stats **)data; 2664 struct info_if_stats *ifs = *ifsp; 2665 endpt *ep = interface_info->ep; 2666 2667 if (NULL == ifs) 2668 return; 2669 2670 ZERO(*ifs); 2671 2672 if (IS_IPV6(&ep->sin)) { 2673 if (!client_v6_capable) 2674 return; 2675 ifs->v6_flag = 1; 2676 ifs->unaddr.addr6 = SOCK_ADDR6(&ep->sin); 2677 ifs->unbcast.addr6 = SOCK_ADDR6(&ep->bcast); 2678 ifs->unmask.addr6 = SOCK_ADDR6(&ep->mask); 2679 } else { 2680 ifs->v6_flag = 0; 2681 ifs->unaddr.addr = SOCK_ADDR4(&ep->sin); 2682 ifs->unbcast.addr = SOCK_ADDR4(&ep->bcast); 2683 ifs->unmask.addr = SOCK_ADDR4(&ep->mask); 2684 } 2685 ifs->v6_flag = htonl(ifs->v6_flag); 2686 strlcpy(ifs->name, ep->name, sizeof(ifs->name)); 2687 ifs->family = htons(ep->family); 2688 ifs->flags = htonl(ep->flags); 2689 ifs->last_ttl = htonl(ep->last_ttl); 2690 ifs->num_mcast = htonl(ep->num_mcast); 2691 ifs->received = htonl(ep->received); 2692 ifs->sent = htonl(ep->sent); 2693 ifs->notsent = htonl(ep->notsent); 2694 ifs->ifindex = htonl(ep->ifindex); 2695 /* scope no longer in endpt, in in6_addr typically */ 2696 ifs->scopeid = ifs->ifindex; 2697 ifs->ifnum = htonl(ep->ifnum); 2698 ifs->uptime = htonl(current_time - ep->starttime); 2699 ifs->ignore_packets = ep->ignore_packets; 2700 ifs->peercnt = htonl(ep->peercnt); 2701 ifs->action = interface_info->action; 2702 2703 *ifsp = (struct info_if_stats *)more_pkt(); 2704} 2705 2706/* 2707 * get_if_stats - get interface statistics 2708 */ 2709static void 2710get_if_stats( 2711 sockaddr_u *srcadr, 2712 endpt *inter, 2713 struct req_pkt *inpkt 2714 ) 2715{ 2716 struct info_if_stats *ifs; 2717 2718 DPRINTF(3, ("wants interface statistics\n")); 2719 2720 ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt, 2721 v6sizeof(struct info_if_stats)); 2722 2723 interface_enumerate(fill_info_if_stats, &ifs); 2724 2725 flush_pkt(); 2726} 2727 2728static void 2729do_if_reload( 2730 sockaddr_u *srcadr, 2731 endpt *inter, 2732 struct req_pkt *inpkt 2733 ) 2734{ 2735 struct info_if_stats *ifs; 2736 2737 DPRINTF(3, ("wants interface reload\n")); 2738 2739 ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt, 2740 v6sizeof(struct info_if_stats)); 2741 2742 interface_update(fill_info_if_stats, &ifs); 2743 2744 flush_pkt(); 2745} 2746 2747