1c0b746e5SOllivier Robert /* 2c0b746e5SOllivier Robert * ntp_request.c - respond to information requests 3c0b746e5SOllivier Robert */ 4c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H 5c0b746e5SOllivier Robert #include <config.h> 6c0b746e5SOllivier Robert #endif 7c0b746e5SOllivier Robert 8c0b746e5SOllivier Robert #include <sys/types.h> 9c0b746e5SOllivier Robert #include <stdio.h> 10c0b746e5SOllivier Robert #include <signal.h> 11c0b746e5SOllivier Robert #include <sys/time.h> 12c0b746e5SOllivier Robert 13c0b746e5SOllivier Robert #include "ntpd.h" 14c0b746e5SOllivier Robert #include "ntp_io.h" 15c0b746e5SOllivier Robert #include "ntp_request.h" 16c0b746e5SOllivier Robert #include "ntp_control.h" 17c0b746e5SOllivier Robert #include "ntp_refclock.h" 18c0b746e5SOllivier Robert #include "ntp_if.h" 19c0b746e5SOllivier Robert #include "ntp_stdlib.h" 20c0b746e5SOllivier Robert #include "recvbuff.h" 21c0b746e5SOllivier Robert 22c0b746e5SOllivier Robert #ifdef KERNEL_PLL 23c0b746e5SOllivier Robert #include "ntp_syscall.h" 24c0b746e5SOllivier Robert #endif /* KERNEL_PLL */ 25c0b746e5SOllivier Robert 26c0b746e5SOllivier Robert /* 27c0b746e5SOllivier Robert * Structure to hold request procedure information 28c0b746e5SOllivier Robert */ 29c0b746e5SOllivier Robert #define NOAUTH 0 30c0b746e5SOllivier Robert #define AUTH 1 31c0b746e5SOllivier Robert 32c0b746e5SOllivier Robert #define NO_REQUEST (-1) 33c0b746e5SOllivier Robert 34c0b746e5SOllivier Robert struct req_proc { 35c0b746e5SOllivier Robert short request_code; /* defined request code */ 36c0b746e5SOllivier Robert short needs_auth; /* true when authentication needed */ 37c0b746e5SOllivier Robert short sizeofitem; /* size of request data item */ 38c0b746e5SOllivier Robert void (*handler) P((struct sockaddr_in *, struct interface *, 39c0b746e5SOllivier Robert struct req_pkt *)); /* routine to handle request */ 40c0b746e5SOllivier Robert }; 41c0b746e5SOllivier Robert 42c0b746e5SOllivier Robert /* 43c0b746e5SOllivier Robert * Universal request codes 44c0b746e5SOllivier Robert */ 45c0b746e5SOllivier Robert static struct req_proc univ_codes[] = { 46c0b746e5SOllivier Robert { NO_REQUEST, NOAUTH, 0, 0 } 47c0b746e5SOllivier Robert }; 48c0b746e5SOllivier Robert 49c0b746e5SOllivier Robert static void req_ack P((struct sockaddr_in *, struct interface *, struct req_pkt *, int)); 50c0b746e5SOllivier Robert static char * prepare_pkt P((struct sockaddr_in *, struct interface *, struct req_pkt *, u_int)); 51c0b746e5SOllivier Robert static char * more_pkt P((void)); 52c0b746e5SOllivier Robert static void flush_pkt P((void)); 53c0b746e5SOllivier Robert static void peer_list P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 54c0b746e5SOllivier Robert static void peer_list_sum P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 55c0b746e5SOllivier Robert static void peer_info P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 56c0b746e5SOllivier Robert static void peer_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 57c0b746e5SOllivier Robert static void sys_info P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 58c0b746e5SOllivier Robert static void sys_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 59c0b746e5SOllivier Robert static void mem_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 60c0b746e5SOllivier Robert static void io_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 61c0b746e5SOllivier Robert static void timer_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 62c0b746e5SOllivier Robert static void loop_info P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 63c0b746e5SOllivier Robert static void do_conf P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 64c0b746e5SOllivier Robert static void do_unconf P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 65c0b746e5SOllivier Robert static void set_sys_flag P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 66c0b746e5SOllivier Robert static void clr_sys_flag P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 67c0b746e5SOllivier Robert static void setclr_flags P((struct sockaddr_in *, struct interface *, struct req_pkt *, u_long)); 68c0b746e5SOllivier Robert static void list_restrict P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 69c0b746e5SOllivier Robert static void do_resaddflags P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 70c0b746e5SOllivier Robert static void do_ressubflags P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 71c0b746e5SOllivier Robert static void do_unrestrict P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 72c0b746e5SOllivier Robert static void do_restrict P((struct sockaddr_in *, struct interface *, struct req_pkt *, int)); 73c0b746e5SOllivier Robert static void mon_getlist_0 P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 74c0b746e5SOllivier Robert static void mon_getlist_1 P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 75c0b746e5SOllivier Robert static void reset_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 76c0b746e5SOllivier Robert static void reset_peer P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 77c0b746e5SOllivier Robert static void do_key_reread P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 78c0b746e5SOllivier Robert static void trust_key P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 79c0b746e5SOllivier Robert static void untrust_key P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 80c0b746e5SOllivier Robert static void do_trustkey P((struct sockaddr_in *, struct interface *, struct req_pkt *, int)); 81c0b746e5SOllivier Robert static void get_auth_info P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 82c0b746e5SOllivier Robert static void reset_auth_stats P((void)); 83c0b746e5SOllivier Robert static void req_get_traps P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 84c0b746e5SOllivier Robert static void req_set_trap P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 85c0b746e5SOllivier Robert static void req_clr_trap P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 86c0b746e5SOllivier Robert static void do_setclr_trap P((struct sockaddr_in *, struct interface *, struct req_pkt *, int)); 87c0b746e5SOllivier Robert static void set_request_keyid P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 88c0b746e5SOllivier Robert static void set_control_keyid P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 89c0b746e5SOllivier Robert static void get_ctl_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 90c0b746e5SOllivier Robert #ifdef KERNEL_PLL 91c0b746e5SOllivier Robert static void get_kernel_info P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 92c0b746e5SOllivier Robert #endif /* KERNEL_PLL */ 93c0b746e5SOllivier Robert #ifdef REFCLOCK 94c0b746e5SOllivier Robert static void get_clock_info P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 95c0b746e5SOllivier Robert static void set_clock_fudge P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 96c0b746e5SOllivier Robert #endif /* REFCLOCK */ 97c0b746e5SOllivier Robert #ifdef REFCLOCK 98c0b746e5SOllivier Robert static void get_clkbug_info P((struct sockaddr_in *, struct interface *, struct req_pkt *)); 99c0b746e5SOllivier Robert #endif /* REFCLOCK */ 100c0b746e5SOllivier Robert 101c0b746e5SOllivier Robert /* 102c0b746e5SOllivier Robert * ntpd request codes 103c0b746e5SOllivier Robert */ 104c0b746e5SOllivier Robert static struct req_proc ntp_codes[] = { 105c0b746e5SOllivier Robert { REQ_PEER_LIST, NOAUTH, 0, peer_list }, 106c0b746e5SOllivier Robert { REQ_PEER_LIST_SUM, NOAUTH, 0, peer_list_sum }, 107c0b746e5SOllivier Robert { REQ_PEER_INFO, NOAUTH, sizeof(struct info_peer_list), peer_info }, 108c0b746e5SOllivier Robert { REQ_PEER_STATS, NOAUTH, sizeof(struct info_peer_list), peer_stats }, 109c0b746e5SOllivier Robert { REQ_SYS_INFO, NOAUTH, 0, sys_info }, 110c0b746e5SOllivier Robert { REQ_SYS_STATS, NOAUTH, 0, sys_stats }, 111c0b746e5SOllivier Robert { REQ_IO_STATS, NOAUTH, 0, io_stats }, 112c0b746e5SOllivier Robert { REQ_MEM_STATS, NOAUTH, 0, mem_stats }, 113c0b746e5SOllivier Robert { REQ_LOOP_INFO, NOAUTH, 0, loop_info }, 114c0b746e5SOllivier Robert { REQ_TIMER_STATS, NOAUTH, 0, timer_stats }, 115c0b746e5SOllivier Robert { REQ_CONFIG, AUTH, sizeof(struct conf_peer), do_conf }, 116c0b746e5SOllivier Robert { REQ_UNCONFIG, AUTH, sizeof(struct conf_unpeer), do_unconf }, 117c0b746e5SOllivier Robert { REQ_SET_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), set_sys_flag }, 118c0b746e5SOllivier Robert { REQ_CLR_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), clr_sys_flag }, 119c0b746e5SOllivier Robert { REQ_GET_RESTRICT, NOAUTH, 0, list_restrict }, 120c0b746e5SOllivier Robert { REQ_RESADDFLAGS, AUTH, sizeof(struct conf_restrict), do_resaddflags }, 121c0b746e5SOllivier Robert { REQ_RESSUBFLAGS, AUTH, sizeof(struct conf_restrict), do_ressubflags }, 122c0b746e5SOllivier Robert { REQ_UNRESTRICT, AUTH, sizeof(struct conf_restrict), do_unrestrict }, 123c0b746e5SOllivier Robert { REQ_MON_GETLIST, NOAUTH, 0, mon_getlist_0 }, 124c0b746e5SOllivier Robert { REQ_MON_GETLIST_1, NOAUTH, 0, mon_getlist_1 }, 125c0b746e5SOllivier Robert { REQ_RESET_STATS, AUTH, sizeof(struct reset_flags), reset_stats }, 126c0b746e5SOllivier Robert { REQ_RESET_PEER, AUTH, sizeof(struct conf_unpeer), reset_peer }, 127c0b746e5SOllivier Robert { REQ_REREAD_KEYS, AUTH, 0, do_key_reread }, 128c0b746e5SOllivier Robert { REQ_TRUSTKEY, AUTH, sizeof(u_long), trust_key }, 129c0b746e5SOllivier Robert { REQ_UNTRUSTKEY, AUTH, sizeof(u_long), untrust_key }, 130c0b746e5SOllivier Robert { REQ_AUTHINFO, NOAUTH, 0, get_auth_info }, 131c0b746e5SOllivier Robert { REQ_TRAPS, NOAUTH, 0, req_get_traps }, 132c0b746e5SOllivier Robert { REQ_ADD_TRAP, AUTH, sizeof(struct conf_trap), req_set_trap }, 133c0b746e5SOllivier Robert { REQ_CLR_TRAP, AUTH, sizeof(struct conf_trap), req_clr_trap }, 134c0b746e5SOllivier Robert { REQ_REQUEST_KEY, AUTH, sizeof(u_long), set_request_keyid }, 135c0b746e5SOllivier Robert { REQ_CONTROL_KEY, AUTH, sizeof(u_long), set_control_keyid }, 136c0b746e5SOllivier Robert { REQ_GET_CTLSTATS, NOAUTH, 0, get_ctl_stats }, 137c0b746e5SOllivier Robert #ifdef KERNEL_PLL 138c0b746e5SOllivier Robert { REQ_GET_KERNEL, NOAUTH, 0, get_kernel_info }, 139c0b746e5SOllivier Robert #endif 140c0b746e5SOllivier Robert #ifdef REFCLOCK 141c0b746e5SOllivier Robert { REQ_GET_CLOCKINFO, NOAUTH, sizeof(u_int32), get_clock_info }, 142c0b746e5SOllivier Robert { REQ_SET_CLKFUDGE, AUTH, sizeof(struct conf_fudge), set_clock_fudge }, 143c0b746e5SOllivier Robert { REQ_GET_CLKBUGINFO, NOAUTH, sizeof(u_int32), get_clkbug_info }, 144c0b746e5SOllivier Robert #endif 145c0b746e5SOllivier Robert { NO_REQUEST, NOAUTH, 0, 0 } 146c0b746e5SOllivier Robert }; 147c0b746e5SOllivier Robert 148c0b746e5SOllivier Robert 149c0b746e5SOllivier Robert /* 150c0b746e5SOllivier Robert * Authentication keyid used to authenticate requests. Zero means we 151c0b746e5SOllivier Robert * don't allow writing anything. 152c0b746e5SOllivier Robert */ 153c0b746e5SOllivier Robert u_long info_auth_keyid; 154c0b746e5SOllivier Robert 155c0b746e5SOllivier Robert /* 156c0b746e5SOllivier Robert * Statistic counters to keep track of requests and responses. 157c0b746e5SOllivier Robert */ 158c0b746e5SOllivier Robert u_long numrequests; /* number of requests we've received */ 159c0b746e5SOllivier Robert u_long numresppkts; /* number of resp packets sent with data */ 160c0b746e5SOllivier Robert 161c0b746e5SOllivier Robert u_long errorcounter[INFO_ERR_AUTH+1]; /* lazy way to count errors, indexed */ 162c0b746e5SOllivier Robert /* by the error code */ 163c0b746e5SOllivier Robert 164c0b746e5SOllivier Robert /* 165c0b746e5SOllivier Robert * A hack. To keep the authentication module clear of ntp-ism's, we 166c0b746e5SOllivier Robert * include a time reset variable for its stats here. 167c0b746e5SOllivier Robert */ 168c0b746e5SOllivier Robert static u_long auth_timereset; 169c0b746e5SOllivier Robert 170c0b746e5SOllivier Robert /* 171c0b746e5SOllivier Robert * Response packet used by these routines. Also some state information 172c0b746e5SOllivier Robert * so that we can handle packet formatting within a common set of 173c0b746e5SOllivier Robert * subroutines. Note we try to enter data in place whenever possible, 174c0b746e5SOllivier Robert * but the need to set the more bit correctly means we occasionally 175c0b746e5SOllivier Robert * use the extra buffer and copy. 176c0b746e5SOllivier Robert */ 177c0b746e5SOllivier Robert static struct resp_pkt rpkt; 178c0b746e5SOllivier Robert static int reqver; 179c0b746e5SOllivier Robert static int seqno; 180c0b746e5SOllivier Robert static int nitems; 181c0b746e5SOllivier Robert static int itemsize; 182c0b746e5SOllivier Robert static int databytes; 183c0b746e5SOllivier Robert static char exbuf[RESP_DATA_SIZE]; 184c0b746e5SOllivier Robert static int usingexbuf; 185c0b746e5SOllivier Robert static struct sockaddr_in *toaddr; 186c0b746e5SOllivier Robert static struct interface *frominter; 187c0b746e5SOllivier Robert 188c0b746e5SOllivier Robert /* 189c0b746e5SOllivier Robert * init_request - initialize request data 190c0b746e5SOllivier Robert */ 191c0b746e5SOllivier Robert void 192c0b746e5SOllivier Robert init_request (void) 193c0b746e5SOllivier Robert { 194c0b746e5SOllivier Robert int i; 195c0b746e5SOllivier Robert 196c0b746e5SOllivier Robert numrequests = 0; 197c0b746e5SOllivier Robert numresppkts = 0; 198c0b746e5SOllivier Robert auth_timereset = 0; 199c0b746e5SOllivier Robert info_auth_keyid = 0; /* by default, can't do this */ 200c0b746e5SOllivier Robert 201c0b746e5SOllivier Robert for (i = 0; i < sizeof(errorcounter)/sizeof(errorcounter[0]); i++) 202c0b746e5SOllivier Robert errorcounter[i] = 0; 203c0b746e5SOllivier Robert } 204c0b746e5SOllivier Robert 205c0b746e5SOllivier Robert 206c0b746e5SOllivier Robert /* 207c0b746e5SOllivier Robert * req_ack - acknowledge request with no data 208c0b746e5SOllivier Robert */ 209c0b746e5SOllivier Robert static void 210c0b746e5SOllivier Robert req_ack( 211c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 212c0b746e5SOllivier Robert struct interface *inter, 213c0b746e5SOllivier Robert struct req_pkt *inpkt, 214c0b746e5SOllivier Robert int errcode 215c0b746e5SOllivier Robert ) 216c0b746e5SOllivier Robert { 217c0b746e5SOllivier Robert /* 218c0b746e5SOllivier Robert * fill in the fields 219c0b746e5SOllivier Robert */ 220c0b746e5SOllivier Robert rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver); 221c0b746e5SOllivier Robert rpkt.auth_seq = AUTH_SEQ(0, 0); 222c0b746e5SOllivier Robert rpkt.implementation = inpkt->implementation; 223c0b746e5SOllivier Robert rpkt.request = inpkt->request; 224c0b746e5SOllivier Robert rpkt.err_nitems = ERR_NITEMS(errcode, 0); 225c0b746e5SOllivier Robert rpkt.mbz_itemsize = MBZ_ITEMSIZE(0); 226c0b746e5SOllivier Robert 227c0b746e5SOllivier Robert /* 228c0b746e5SOllivier Robert * send packet and bump counters 229c0b746e5SOllivier Robert */ 230c0b746e5SOllivier Robert sendpkt(srcadr, inter, -1, (struct pkt *)&rpkt, RESP_HEADER_SIZE); 231c0b746e5SOllivier Robert errorcounter[errcode]++; 232c0b746e5SOllivier Robert } 233c0b746e5SOllivier Robert 234c0b746e5SOllivier Robert 235c0b746e5SOllivier Robert /* 236c0b746e5SOllivier Robert * prepare_pkt - prepare response packet for transmission, return pointer 237c0b746e5SOllivier Robert * to storage for data item. 238c0b746e5SOllivier Robert */ 239c0b746e5SOllivier Robert static char * 240c0b746e5SOllivier Robert prepare_pkt( 241c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 242c0b746e5SOllivier Robert struct interface *inter, 243c0b746e5SOllivier Robert struct req_pkt *pkt, 244c0b746e5SOllivier Robert u_int structsize 245c0b746e5SOllivier Robert ) 246c0b746e5SOllivier Robert { 247c0b746e5SOllivier Robert #ifdef DEBUG 248c0b746e5SOllivier Robert if (debug > 3) 249c0b746e5SOllivier Robert printf("request: preparing pkt\n"); 250c0b746e5SOllivier Robert #endif 251c0b746e5SOllivier Robert 252c0b746e5SOllivier Robert /* 253c0b746e5SOllivier Robert * Fill in the implementation, reqest and itemsize fields 254c0b746e5SOllivier Robert * since these won't change. 255c0b746e5SOllivier Robert */ 256c0b746e5SOllivier Robert rpkt.implementation = pkt->implementation; 257c0b746e5SOllivier Robert rpkt.request = pkt->request; 258c0b746e5SOllivier Robert rpkt.mbz_itemsize = MBZ_ITEMSIZE(structsize); 259c0b746e5SOllivier Robert 260c0b746e5SOllivier Robert /* 261c0b746e5SOllivier Robert * Compute the static data needed to carry on. 262c0b746e5SOllivier Robert */ 263c0b746e5SOllivier Robert toaddr = srcadr; 264c0b746e5SOllivier Robert frominter = inter; 265c0b746e5SOllivier Robert seqno = 0; 266c0b746e5SOllivier Robert nitems = 0; 267c0b746e5SOllivier Robert itemsize = structsize; 268c0b746e5SOllivier Robert databytes = 0; 269c0b746e5SOllivier Robert usingexbuf = 0; 270c0b746e5SOllivier Robert 271c0b746e5SOllivier Robert /* 272c0b746e5SOllivier Robert * return the beginning of the packet buffer. 273c0b746e5SOllivier Robert */ 274c0b746e5SOllivier Robert return &rpkt.data[0]; 275c0b746e5SOllivier Robert } 276c0b746e5SOllivier Robert 277c0b746e5SOllivier Robert 278c0b746e5SOllivier Robert /* 279c0b746e5SOllivier Robert * more_pkt - return a data pointer for a new item. 280c0b746e5SOllivier Robert */ 281c0b746e5SOllivier Robert static char * 282c0b746e5SOllivier Robert more_pkt(void) 283c0b746e5SOllivier Robert { 284c0b746e5SOllivier Robert /* 285c0b746e5SOllivier Robert * If we were using the extra buffer, send the packet. 286c0b746e5SOllivier Robert */ 287c0b746e5SOllivier Robert if (usingexbuf) { 288c0b746e5SOllivier Robert #ifdef DEBUG 289c0b746e5SOllivier Robert if (debug > 2) 290c0b746e5SOllivier Robert printf("request: sending pkt\n"); 291c0b746e5SOllivier Robert #endif 292c0b746e5SOllivier Robert rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, MORE_BIT, reqver); 293c0b746e5SOllivier Robert rpkt.auth_seq = AUTH_SEQ(0, seqno); 294c0b746e5SOllivier Robert rpkt.err_nitems = htons((u_short)nitems); 295c0b746e5SOllivier Robert sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt, 296c0b746e5SOllivier Robert RESP_HEADER_SIZE+databytes); 297c0b746e5SOllivier Robert numresppkts++; 298c0b746e5SOllivier Robert 299c0b746e5SOllivier Robert /* 300c0b746e5SOllivier Robert * Copy data out of exbuf into the packet. 301c0b746e5SOllivier Robert */ 302c0b746e5SOllivier Robert memmove(&rpkt.data[0], exbuf, (unsigned)itemsize); 303c0b746e5SOllivier Robert seqno++; 304c0b746e5SOllivier Robert databytes = 0; 305c0b746e5SOllivier Robert nitems = 0; 306c0b746e5SOllivier Robert usingexbuf = 0; 307c0b746e5SOllivier Robert } 308c0b746e5SOllivier Robert 309c0b746e5SOllivier Robert databytes += itemsize; 310c0b746e5SOllivier Robert nitems++; 311c0b746e5SOllivier Robert if (databytes + itemsize <= RESP_DATA_SIZE) { 312c0b746e5SOllivier Robert #ifdef DEBUG 313c0b746e5SOllivier Robert if (debug > 3) 314c0b746e5SOllivier Robert printf("request: giving him more data\n"); 315c0b746e5SOllivier Robert #endif 316c0b746e5SOllivier Robert /* 317c0b746e5SOllivier Robert * More room in packet. Give him the 318c0b746e5SOllivier Robert * next address. 319c0b746e5SOllivier Robert */ 320c0b746e5SOllivier Robert return &rpkt.data[databytes]; 321c0b746e5SOllivier Robert } else { 322c0b746e5SOllivier Robert /* 323c0b746e5SOllivier Robert * No room in packet. Give him the extra 324c0b746e5SOllivier Robert * buffer unless this was the last in the sequence. 325c0b746e5SOllivier Robert */ 326c0b746e5SOllivier Robert #ifdef DEBUG 327c0b746e5SOllivier Robert if (debug > 3) 328c0b746e5SOllivier Robert printf("request: into extra buffer\n"); 329c0b746e5SOllivier Robert #endif 330c0b746e5SOllivier Robert if (seqno == MAXSEQ) 331c0b746e5SOllivier Robert return (char *)0; 332c0b746e5SOllivier Robert else { 333c0b746e5SOllivier Robert usingexbuf = 1; 334c0b746e5SOllivier Robert return exbuf; 335c0b746e5SOllivier Robert } 336c0b746e5SOllivier Robert } 337c0b746e5SOllivier Robert } 338c0b746e5SOllivier Robert 339c0b746e5SOllivier Robert 340c0b746e5SOllivier Robert /* 341c0b746e5SOllivier Robert * flush_pkt - we're done, return remaining information. 342c0b746e5SOllivier Robert */ 343c0b746e5SOllivier Robert static void 344c0b746e5SOllivier Robert flush_pkt(void) 345c0b746e5SOllivier Robert { 346c0b746e5SOllivier Robert #ifdef DEBUG 347c0b746e5SOllivier Robert if (debug > 2) 348c0b746e5SOllivier Robert printf("request: flushing packet, %d items\n", nitems); 349c0b746e5SOllivier Robert #endif 350c0b746e5SOllivier Robert /* 351c0b746e5SOllivier Robert * Must send the last packet. If nothing in here and nothing 352c0b746e5SOllivier Robert * has been sent, send an error saying no data to be found. 353c0b746e5SOllivier Robert */ 354c0b746e5SOllivier Robert if (seqno == 0 && nitems == 0) 355c0b746e5SOllivier Robert req_ack(toaddr, frominter, (struct req_pkt *)&rpkt, 356c0b746e5SOllivier Robert INFO_ERR_NODATA); 357c0b746e5SOllivier Robert else { 358c0b746e5SOllivier Robert rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver); 359c0b746e5SOllivier Robert rpkt.auth_seq = AUTH_SEQ(0, seqno); 360c0b746e5SOllivier Robert rpkt.err_nitems = htons((u_short)nitems); 361c0b746e5SOllivier Robert sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt, 362c0b746e5SOllivier Robert RESP_HEADER_SIZE+databytes); 363c0b746e5SOllivier Robert numresppkts++; 364c0b746e5SOllivier Robert } 365c0b746e5SOllivier Robert } 366c0b746e5SOllivier Robert 367c0b746e5SOllivier Robert 368c0b746e5SOllivier Robert 369c0b746e5SOllivier Robert /* 370c0b746e5SOllivier Robert * process_private - process private mode (7) packets 371c0b746e5SOllivier Robert */ 372c0b746e5SOllivier Robert void 373c0b746e5SOllivier Robert process_private( 374c0b746e5SOllivier Robert struct recvbuf *rbufp, 375c0b746e5SOllivier Robert int mod_okay 376c0b746e5SOllivier Robert ) 377c0b746e5SOllivier Robert { 378c0b746e5SOllivier Robert struct req_pkt *inpkt; 379c0b746e5SOllivier Robert struct sockaddr_in *srcadr; 380c0b746e5SOllivier Robert struct interface *inter; 381c0b746e5SOllivier Robert struct req_proc *proc; 382c0b746e5SOllivier Robert 383c0b746e5SOllivier Robert /* 384c0b746e5SOllivier Robert * Initialize pointers, for convenience 385c0b746e5SOllivier Robert */ 386c0b746e5SOllivier Robert inpkt = (struct req_pkt *)&rbufp->recv_pkt; 387c0b746e5SOllivier Robert srcadr = &rbufp->recv_srcadr; 388c0b746e5SOllivier Robert inter = rbufp->dstadr; 389c0b746e5SOllivier Robert 390c0b746e5SOllivier Robert #ifdef DEBUG 391c0b746e5SOllivier Robert if (debug > 2) 392c0b746e5SOllivier Robert printf("prepare_pkt: impl %d req %d\n", 393c0b746e5SOllivier Robert inpkt->implementation, inpkt->request); 394c0b746e5SOllivier Robert #endif 395c0b746e5SOllivier Robert 396c0b746e5SOllivier Robert /* 397c0b746e5SOllivier Robert * Do some sanity checks on the packet. Return a format 398c0b746e5SOllivier Robert * error if it fails. 399c0b746e5SOllivier Robert */ 400c0b746e5SOllivier Robert if (ISRESPONSE(inpkt->rm_vn_mode) 401c0b746e5SOllivier Robert || ISMORE(inpkt->rm_vn_mode) 402c0b746e5SOllivier Robert || INFO_VERSION(inpkt->rm_vn_mode) > NTP_VERSION 403c0b746e5SOllivier Robert || INFO_VERSION(inpkt->rm_vn_mode) < NTP_OLDVERSION 404c0b746e5SOllivier Robert || INFO_SEQ(inpkt->auth_seq) != 0 405c0b746e5SOllivier Robert || INFO_ERR(inpkt->err_nitems) != 0 406c0b746e5SOllivier Robert || INFO_MBZ(inpkt->mbz_itemsize) != 0 407c0b746e5SOllivier Robert || rbufp->recv_length > REQ_LEN_MAC 408c0b746e5SOllivier Robert || rbufp->recv_length < REQ_LEN_NOMAC) { 409c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 410c0b746e5SOllivier Robert return; 411c0b746e5SOllivier Robert } 412c0b746e5SOllivier Robert 413c0b746e5SOllivier Robert reqver = INFO_VERSION(inpkt->rm_vn_mode); 414c0b746e5SOllivier Robert 415c0b746e5SOllivier Robert /* 416c0b746e5SOllivier Robert * Get the appropriate procedure list to search. 417c0b746e5SOllivier Robert */ 418c0b746e5SOllivier Robert if (inpkt->implementation == IMPL_UNIV) 419c0b746e5SOllivier Robert proc = univ_codes; 420c0b746e5SOllivier Robert else if (inpkt->implementation == IMPL_XNTPD) 421c0b746e5SOllivier Robert proc = ntp_codes; 422c0b746e5SOllivier Robert else { 423c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_IMPL); 424c0b746e5SOllivier Robert return; 425c0b746e5SOllivier Robert } 426c0b746e5SOllivier Robert 427c0b746e5SOllivier Robert 428c0b746e5SOllivier Robert /* 429c0b746e5SOllivier Robert * Search the list for the request codes. If it isn't one 430c0b746e5SOllivier Robert * we know, return an error. 431c0b746e5SOllivier Robert */ 432c0b746e5SOllivier Robert while (proc->request_code != NO_REQUEST) { 433c0b746e5SOllivier Robert if (proc->request_code == (short) inpkt->request) 434c0b746e5SOllivier Robert break; 435c0b746e5SOllivier Robert proc++; 436c0b746e5SOllivier Robert } 437c0b746e5SOllivier Robert if (proc->request_code == NO_REQUEST) { 438c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_REQ); 439c0b746e5SOllivier Robert return; 440c0b746e5SOllivier Robert } 441c0b746e5SOllivier Robert 442c0b746e5SOllivier Robert #ifdef DEBUG 443c0b746e5SOllivier Robert if (debug > 3) 444c0b746e5SOllivier Robert printf("found request in tables\n"); 445c0b746e5SOllivier Robert #endif 446c0b746e5SOllivier Robert 447c0b746e5SOllivier Robert /* 448c0b746e5SOllivier Robert * If we need to authenticate, do so. Note that an 449c0b746e5SOllivier Robert * authenticatable packet must include a mac field, must 450c0b746e5SOllivier Robert * have used key info_auth_keyid and must have included 451c0b746e5SOllivier Robert * a time stamp in the appropriate field. The time stamp 452c0b746e5SOllivier Robert * must be within INFO_TS_MAXSKEW of the receive 453c0b746e5SOllivier Robert * time stamp. 454c0b746e5SOllivier Robert */ 455c0b746e5SOllivier Robert if (proc->needs_auth && sys_authenticate) { 456c0b746e5SOllivier Robert l_fp ftmp; 457c0b746e5SOllivier Robert double dtemp; 458c0b746e5SOllivier Robert 459c0b746e5SOllivier Robert /* 460c0b746e5SOllivier Robert * If this guy is restricted from doing this, don't let him 461c0b746e5SOllivier Robert * If wrong key was used, or packet doesn't have mac, return. 462c0b746e5SOllivier Robert */ 463c0b746e5SOllivier Robert if (!INFO_IS_AUTH(inpkt->auth_seq) || info_auth_keyid == 0 464c0b746e5SOllivier Robert || ntohl(inpkt->keyid) != info_auth_keyid) { 465c0b746e5SOllivier Robert #ifdef DEBUG 466c0b746e5SOllivier Robert if (debug > 4) 467c0b746e5SOllivier Robert printf("failed auth %d info_auth_keyid %lu pkt keyid %lu\n", 468c0b746e5SOllivier Robert INFO_IS_AUTH(inpkt->auth_seq), 469c0b746e5SOllivier Robert (u_long)info_auth_keyid, 470c0b746e5SOllivier Robert (u_long)ntohl(inpkt->keyid)); 471c0b746e5SOllivier Robert #endif 472c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 473c0b746e5SOllivier Robert return; 474c0b746e5SOllivier Robert } 475c0b746e5SOllivier Robert if (rbufp->recv_length > REQ_LEN_MAC) { 476c0b746e5SOllivier Robert #ifdef DEBUG 477c0b746e5SOllivier Robert if (debug > 4) 478c0b746e5SOllivier Robert printf("bad pkt length %d\n", 479c0b746e5SOllivier Robert rbufp->recv_length); 480c0b746e5SOllivier Robert #endif 481c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 482c0b746e5SOllivier Robert return; 483c0b746e5SOllivier Robert } 484c0b746e5SOllivier Robert if (!mod_okay || !authhavekey(info_auth_keyid)) { 485c0b746e5SOllivier Robert #ifdef DEBUG 486c0b746e5SOllivier Robert if (debug > 4) 487c0b746e5SOllivier Robert printf("failed auth mod_okay %d\n", mod_okay); 488c0b746e5SOllivier Robert #endif 489c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 490c0b746e5SOllivier Robert return; 491c0b746e5SOllivier Robert } 492c0b746e5SOllivier Robert 493c0b746e5SOllivier Robert /* 494c0b746e5SOllivier Robert * calculate absolute time difference between xmit time stamp 495c0b746e5SOllivier Robert * and receive time stamp. If too large, too bad. 496c0b746e5SOllivier Robert */ 497c0b746e5SOllivier Robert NTOHL_FP(&inpkt->tstamp, &ftmp); 498c0b746e5SOllivier Robert L_SUB(&ftmp, &rbufp->recv_time); 499c0b746e5SOllivier Robert LFPTOD(&ftmp, dtemp); 500c0b746e5SOllivier Robert if (fabs(dtemp) >= INFO_TS_MAXSKEW) { 501c0b746e5SOllivier Robert /* 502c0b746e5SOllivier Robert * He's a loser. Tell him. 503c0b746e5SOllivier Robert */ 504c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 505c0b746e5SOllivier Robert return; 506c0b746e5SOllivier Robert } 507c0b746e5SOllivier Robert 508c0b746e5SOllivier Robert /* 509c0b746e5SOllivier Robert * So far so good. See if decryption works out okay. 510c0b746e5SOllivier Robert */ 511c0b746e5SOllivier Robert if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt, 512c0b746e5SOllivier Robert REQ_LEN_NOMAC, (int)(rbufp->recv_length - REQ_LEN_NOMAC))) { 513c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 514c0b746e5SOllivier Robert return; 515c0b746e5SOllivier Robert } 516c0b746e5SOllivier Robert } 517c0b746e5SOllivier Robert 518c0b746e5SOllivier Robert /* 519c0b746e5SOllivier Robert * If we need data, check to see if we have some. If we 520c0b746e5SOllivier Robert * don't, check to see that there is none (picky, picky). 521c0b746e5SOllivier Robert */ 522c0b746e5SOllivier Robert if (INFO_ITEMSIZE(inpkt->mbz_itemsize) != proc->sizeofitem) { 523c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 524c0b746e5SOllivier Robert return; 525c0b746e5SOllivier Robert } 526c0b746e5SOllivier Robert if (proc->sizeofitem != 0) 527c0b746e5SOllivier Robert if (proc->sizeofitem*INFO_NITEMS(inpkt->err_nitems) 528c0b746e5SOllivier Robert > sizeof(inpkt->data)) { 529c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 530c0b746e5SOllivier Robert return; 531c0b746e5SOllivier Robert } 532c0b746e5SOllivier Robert 533c0b746e5SOllivier Robert #ifdef DEBUG 534c0b746e5SOllivier Robert if (debug > 3) 535c0b746e5SOllivier Robert printf("process_private: all okay, into handler\n"); 536c0b746e5SOllivier Robert #endif 537c0b746e5SOllivier Robert 538c0b746e5SOllivier Robert /* 539c0b746e5SOllivier Robert * Packet is okay. Call the handler to send him data. 540c0b746e5SOllivier Robert */ 541c0b746e5SOllivier Robert (proc->handler)(srcadr, inter, inpkt); 542c0b746e5SOllivier Robert } 543c0b746e5SOllivier Robert 544c0b746e5SOllivier Robert 545c0b746e5SOllivier Robert /* 546c0b746e5SOllivier Robert * peer_list - send a list of the peers 547c0b746e5SOllivier Robert */ 548c0b746e5SOllivier Robert static void 549c0b746e5SOllivier Robert peer_list( 550c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 551c0b746e5SOllivier Robert struct interface *inter, 552c0b746e5SOllivier Robert struct req_pkt *inpkt 553c0b746e5SOllivier Robert ) 554c0b746e5SOllivier Robert { 555c0b746e5SOllivier Robert register struct info_peer_list *ip; 556c0b746e5SOllivier Robert register struct peer *pp; 557c0b746e5SOllivier Robert register int i; 558c0b746e5SOllivier Robert 559c0b746e5SOllivier Robert ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt, 560c0b746e5SOllivier Robert sizeof(struct info_peer_list)); 561c0b746e5SOllivier Robert for (i = 0; i < HASH_SIZE && ip != 0; i++) { 562c0b746e5SOllivier Robert pp = peer_hash[i]; 563c0b746e5SOllivier Robert while (pp != 0 && ip != 0) { 564c0b746e5SOllivier Robert ip->address = pp->srcadr.sin_addr.s_addr; 565c0b746e5SOllivier Robert ip->port = pp->srcadr.sin_port; 566c0b746e5SOllivier Robert ip->hmode = pp->hmode; 567c0b746e5SOllivier Robert ip->flags = 0; 568c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 569c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 570c0b746e5SOllivier Robert if (pp == sys_peer) 571c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 572c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 573c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 574c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 575c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 576c0b746e5SOllivier Robert ip = (struct info_peer_list *)more_pkt(); 577c0b746e5SOllivier Robert pp = pp->next; 578c0b746e5SOllivier Robert } 579c0b746e5SOllivier Robert } 580c0b746e5SOllivier Robert flush_pkt(); 581c0b746e5SOllivier Robert } 582c0b746e5SOllivier Robert 583c0b746e5SOllivier Robert 584c0b746e5SOllivier Robert /* 585c0b746e5SOllivier Robert * peer_list_sum - return extended peer list 586c0b746e5SOllivier Robert */ 587c0b746e5SOllivier Robert static void 588c0b746e5SOllivier Robert peer_list_sum( 589c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 590c0b746e5SOllivier Robert struct interface *inter, 591c0b746e5SOllivier Robert struct req_pkt *inpkt 592c0b746e5SOllivier Robert ) 593c0b746e5SOllivier Robert { 594c0b746e5SOllivier Robert register struct info_peer_summary *ips; 595c0b746e5SOllivier Robert register struct peer *pp; 596c0b746e5SOllivier Robert register int i; 597c0b746e5SOllivier Robert l_fp ltmp; 598c0b746e5SOllivier Robert 599c0b746e5SOllivier Robert #ifdef DEBUG 600c0b746e5SOllivier Robert if (debug > 2) 601c0b746e5SOllivier Robert printf("wants peer list summary\n"); 602c0b746e5SOllivier Robert #endif 603c0b746e5SOllivier Robert 604c0b746e5SOllivier Robert ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt, 605c0b746e5SOllivier Robert sizeof(struct info_peer_summary)); 606c0b746e5SOllivier Robert for (i = 0; i < HASH_SIZE && ips != 0; i++) { 607c0b746e5SOllivier Robert pp = peer_hash[i]; 608c0b746e5SOllivier Robert while (pp != 0 && ips != 0) { 609c0b746e5SOllivier Robert #ifdef DEBUG 610c0b746e5SOllivier Robert if (debug > 3) 611c0b746e5SOllivier Robert printf("sum: got one\n"); 612c0b746e5SOllivier Robert #endif 613c0b746e5SOllivier Robert ips->dstadr = (pp->processed) ? 614c0b746e5SOllivier Robert pp->cast_flags == MDF_BCAST ? 615c0b746e5SOllivier Robert pp->dstadr->bcast.sin_addr.s_addr: 616c0b746e5SOllivier Robert pp->cast_flags ? 617c0b746e5SOllivier Robert pp->dstadr->sin.sin_addr.s_addr ? 618c0b746e5SOllivier Robert pp->dstadr->sin.sin_addr.s_addr: 619c0b746e5SOllivier Robert pp->dstadr->bcast.sin_addr.s_addr: 620c0b746e5SOllivier Robert 1 : 5; 621c0b746e5SOllivier Robert ips->srcadr = pp->srcadr.sin_addr.s_addr; 622c0b746e5SOllivier Robert ips->srcport = pp->srcadr.sin_port; 623c0b746e5SOllivier Robert ips->stratum = pp->stratum; 624c0b746e5SOllivier Robert ips->hpoll = pp->hpoll; 625c0b746e5SOllivier Robert ips->ppoll = pp->ppoll; 626c0b746e5SOllivier Robert ips->reach = pp->reach; 627c0b746e5SOllivier Robert ips->flags = 0; 628c0b746e5SOllivier Robert if (pp == sys_peer) 629c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SYSPEER; 630c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 631c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_CONFIG; 632c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 633c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_REFCLOCK; 634c0b746e5SOllivier Robert if (pp->flags & FLAG_AUTHENABLE) 635c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_AUTHENABLE; 636c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 637c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_PREFER; 638c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 639c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_BURST; 640c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 641c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SEL_CANDIDATE; 642c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 643c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SHORTLIST; 644c0b746e5SOllivier Robert ips->hmode = pp->hmode; 645c0b746e5SOllivier Robert ips->delay = HTONS_FP(DTOFP(pp->delay)); 646c0b746e5SOllivier Robert DTOLFP(pp->offset, <mp); 647c0b746e5SOllivier Robert HTONL_FP(<mp, &ips->offset); 648c0b746e5SOllivier Robert ips->dispersion = HTONS_FP(DTOUFP(pp->disp)); 649c0b746e5SOllivier Robert 650c0b746e5SOllivier Robert pp = pp->next; 651c0b746e5SOllivier Robert ips = (struct info_peer_summary *)more_pkt(); 652c0b746e5SOllivier Robert } 653c0b746e5SOllivier Robert } 654c0b746e5SOllivier Robert flush_pkt(); 655c0b746e5SOllivier Robert } 656c0b746e5SOllivier Robert 657c0b746e5SOllivier Robert 658c0b746e5SOllivier Robert /* 659c0b746e5SOllivier Robert * peer_info - send information for one or more peers 660c0b746e5SOllivier Robert */ 661c0b746e5SOllivier Robert static void 662c0b746e5SOllivier Robert peer_info ( 663c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 664c0b746e5SOllivier Robert struct interface *inter, 665c0b746e5SOllivier Robert struct req_pkt *inpkt 666c0b746e5SOllivier Robert ) 667c0b746e5SOllivier Robert { 668c0b746e5SOllivier Robert register struct info_peer_list *ipl; 669c0b746e5SOllivier Robert register struct peer *pp; 670c0b746e5SOllivier Robert register struct info_peer *ip; 671c0b746e5SOllivier Robert register int items; 672c0b746e5SOllivier Robert register int i, j; 673c0b746e5SOllivier Robert struct sockaddr_in addr; 674c0b746e5SOllivier Robert extern struct peer *sys_peer; 675c0b746e5SOllivier Robert l_fp ltmp; 676c0b746e5SOllivier Robert 677c0b746e5SOllivier Robert memset((char *)&addr, 0, sizeof addr); 678c0b746e5SOllivier Robert addr.sin_family = AF_INET; 679c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 680c0b746e5SOllivier Robert ipl = (struct info_peer_list *) inpkt->data; 681c0b746e5SOllivier Robert ip = (struct info_peer *)prepare_pkt(srcadr, inter, inpkt, 682c0b746e5SOllivier Robert sizeof(struct info_peer)); 683c0b746e5SOllivier Robert while (items-- > 0 && ip != 0) { 684c0b746e5SOllivier Robert addr.sin_port = ipl->port; 685c0b746e5SOllivier Robert addr.sin_addr.s_addr = ipl->address; 686c0b746e5SOllivier Robert ipl++; 687c0b746e5SOllivier Robert if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0) 688c0b746e5SOllivier Robert continue; 689c0b746e5SOllivier Robert ip->dstadr = (pp->processed) ? 690c0b746e5SOllivier Robert pp->cast_flags == MDF_BCAST ? 691c0b746e5SOllivier Robert pp->dstadr->bcast.sin_addr.s_addr: 692c0b746e5SOllivier Robert pp->cast_flags ? 693c0b746e5SOllivier Robert pp->dstadr->sin.sin_addr.s_addr ? 694c0b746e5SOllivier Robert pp->dstadr->sin.sin_addr.s_addr: 695c0b746e5SOllivier Robert pp->dstadr->bcast.sin_addr.s_addr: 696c0b746e5SOllivier Robert 2 : 6; 697c0b746e5SOllivier Robert ip->srcadr = NSRCADR(&pp->srcadr); 698c0b746e5SOllivier Robert ip->srcport = NSRCPORT(&pp->srcadr); 699c0b746e5SOllivier Robert ip->flags = 0; 700c0b746e5SOllivier Robert if (pp == sys_peer) 701c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 702c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 703c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 704c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 705c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_REFCLOCK; 706c0b746e5SOllivier Robert if (pp->flags & FLAG_AUTHENABLE) 707c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_AUTHENABLE; 708c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 709c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_PREFER; 710c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 711c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_BURST; 712c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 713c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 714c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 715c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 716c0b746e5SOllivier Robert ip->leap = pp->leap; 717c0b746e5SOllivier Robert ip->hmode = pp->hmode; 718c0b746e5SOllivier Robert ip->keyid = pp->keyid; 719c0b746e5SOllivier Robert ip->stratum = pp->stratum; 720c0b746e5SOllivier Robert ip->ppoll = pp->ppoll; 721c0b746e5SOllivier Robert ip->hpoll = pp->hpoll; 722c0b746e5SOllivier Robert ip->precision = pp->precision; 723c0b746e5SOllivier Robert ip->version = pp->version; 724c0b746e5SOllivier Robert ip->valid = pp->valid; 725c0b746e5SOllivier Robert ip->reach = pp->reach; 726c0b746e5SOllivier Robert ip->unreach = pp->unreach; 727c0b746e5SOllivier Robert ip->flash = (u_char)pp->flash; 728c0b746e5SOllivier Robert ip->flash2 = pp->flash; 729c0b746e5SOllivier Robert ip->estbdelay = HTONS_FP(DTOFP(pp->estbdelay)); 730c0b746e5SOllivier Robert ip->ttl = pp->ttl; 731c0b746e5SOllivier Robert ip->associd = htons(pp->associd); 732c0b746e5SOllivier Robert ip->rootdelay = HTONS_FP(DTOUFP(pp->rootdelay)); 733c0b746e5SOllivier Robert ip->rootdispersion = HTONS_FP(DTOUFP(pp->rootdispersion)); 734c0b746e5SOllivier Robert ip->refid = pp->refid; 735c0b746e5SOllivier Robert HTONL_FP(&pp->reftime, &ip->reftime); 736c0b746e5SOllivier Robert HTONL_FP(&pp->org, &ip->org); 737c0b746e5SOllivier Robert HTONL_FP(&pp->rec, &ip->rec); 738c0b746e5SOllivier Robert HTONL_FP(&pp->xmt, &ip->xmt); 739c0b746e5SOllivier Robert j = pp->filter_nextpt - 1; 740c0b746e5SOllivier Robert for (i = 0; i < NTP_SHIFT; i++, j--) { 741c0b746e5SOllivier Robert if (j < 0) 742c0b746e5SOllivier Robert j = NTP_SHIFT-1; 743c0b746e5SOllivier Robert ip->filtdelay[i] = HTONS_FP(DTOFP(pp->filter_delay[j])); 744c0b746e5SOllivier Robert DTOLFP(pp->filter_offset[j], <mp); 745c0b746e5SOllivier Robert HTONL_FP(<mp, &ip->filtoffset[i]); 746c0b746e5SOllivier Robert ip->order[i] = (pp->filter_nextpt+NTP_SHIFT-1) 747c0b746e5SOllivier Robert - pp->filter_order[i]; 748c0b746e5SOllivier Robert if (ip->order[i] >= NTP_SHIFT) 749c0b746e5SOllivier Robert ip->order[i] -= NTP_SHIFT; 750c0b746e5SOllivier Robert } 751c0b746e5SOllivier Robert DTOLFP(pp->offset, <mp); 752c0b746e5SOllivier Robert HTONL_FP(<mp, &ip->offset); 753c0b746e5SOllivier Robert ip->delay = HTONS_FP(DTOFP(pp->delay)); 754c0b746e5SOllivier Robert ip->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); 755c0b746e5SOllivier Robert ip->selectdisp = HTONS_FP(DTOUFP(SQRT(pp->variance))); 756c0b746e5SOllivier Robert ip = (struct info_peer *)more_pkt(); 757c0b746e5SOllivier Robert } 758c0b746e5SOllivier Robert flush_pkt(); 759c0b746e5SOllivier Robert } 760c0b746e5SOllivier Robert 761c0b746e5SOllivier Robert 762c0b746e5SOllivier Robert /* 763c0b746e5SOllivier Robert * peer_stats - send statistics for one or more peers 764c0b746e5SOllivier Robert */ 765c0b746e5SOllivier Robert static void 766c0b746e5SOllivier Robert peer_stats ( 767c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 768c0b746e5SOllivier Robert struct interface *inter, 769c0b746e5SOllivier Robert struct req_pkt *inpkt 770c0b746e5SOllivier Robert ) 771c0b746e5SOllivier Robert { 772c0b746e5SOllivier Robert register struct info_peer_list *ipl; 773c0b746e5SOllivier Robert register struct peer *pp; 774c0b746e5SOllivier Robert register struct info_peer_stats *ip; 775c0b746e5SOllivier Robert register int items; 776c0b746e5SOllivier Robert struct sockaddr_in addr; 777c0b746e5SOllivier Robert extern struct peer *sys_peer; 778c0b746e5SOllivier Robert 779c0b746e5SOllivier Robert memset((char *)&addr, 0, sizeof addr); 780c0b746e5SOllivier Robert addr.sin_family = AF_INET; 781c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 782c0b746e5SOllivier Robert ipl = (struct info_peer_list *) inpkt->data; 783c0b746e5SOllivier Robert ip = (struct info_peer_stats *)prepare_pkt(srcadr, inter, inpkt, 784c0b746e5SOllivier Robert sizeof(struct info_peer_stats)); 785c0b746e5SOllivier Robert while (items-- > 0 && ip != 0) { 786c0b746e5SOllivier Robert addr.sin_port = ipl->port; 787c0b746e5SOllivier Robert addr.sin_addr.s_addr = ipl->address; 788c0b746e5SOllivier Robert ipl++; 789c0b746e5SOllivier Robert if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0) 790c0b746e5SOllivier Robert continue; 791c0b746e5SOllivier Robert ip->dstadr = (pp->processed) ? 792c0b746e5SOllivier Robert pp->cast_flags == MDF_BCAST ? 793c0b746e5SOllivier Robert pp->dstadr->bcast.sin_addr.s_addr: 794c0b746e5SOllivier Robert pp->cast_flags ? 795c0b746e5SOllivier Robert pp->dstadr->sin.sin_addr.s_addr ? 796c0b746e5SOllivier Robert pp->dstadr->sin.sin_addr.s_addr: 797c0b746e5SOllivier Robert pp->dstadr->bcast.sin_addr.s_addr: 798c0b746e5SOllivier Robert 3 : 7; 799c0b746e5SOllivier Robert ip->srcadr = NSRCADR(&pp->srcadr); 800c0b746e5SOllivier Robert ip->srcport = NSRCPORT(&pp->srcadr); 801c0b746e5SOllivier Robert ip->flags = 0; 802c0b746e5SOllivier Robert if (pp == sys_peer) 803c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 804c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 805c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 806c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 807c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_REFCLOCK; 808c0b746e5SOllivier Robert if (pp->flags & FLAG_AUTHENABLE) 809c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_AUTHENABLE; 810c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 811c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_PREFER; 812c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 813c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_BURST; 814c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 815c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 816c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 817c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 818c0b746e5SOllivier Robert ip->timereceived = htonl((u_int32)(current_time - pp->timereceived)); 819c0b746e5SOllivier Robert ip->timetosend = htonl(pp->nextdate - current_time); 820c0b746e5SOllivier Robert ip->timereachable = htonl((u_int32)(current_time - pp->timereachable)); 821c0b746e5SOllivier Robert ip->sent = htonl((u_int32)(pp->sent)); 822c0b746e5SOllivier Robert ip->processed = htonl((u_int32)(pp->processed)); 823c0b746e5SOllivier Robert ip->badauth = htonl((u_int32)(pp->badauth)); 824c0b746e5SOllivier Robert ip->bogusorg = htonl((u_int32)(pp->bogusorg)); 825c0b746e5SOllivier Robert ip->oldpkt = htonl((u_int32)(pp->oldpkt)); 826c0b746e5SOllivier Robert ip->seldisp = htonl((u_int32)(pp->seldisptoolarge)); 827c0b746e5SOllivier Robert ip->selbroken = htonl((u_int32)(pp->selbroken)); 828c0b746e5SOllivier Robert ip->candidate = pp->status; 829c0b746e5SOllivier Robert ip = (struct info_peer_stats *)more_pkt(); 830c0b746e5SOllivier Robert } 831c0b746e5SOllivier Robert flush_pkt(); 832c0b746e5SOllivier Robert } 833c0b746e5SOllivier Robert 834c0b746e5SOllivier Robert 835c0b746e5SOllivier Robert /* 836c0b746e5SOllivier Robert * sys_info - return system info 837c0b746e5SOllivier Robert */ 838c0b746e5SOllivier Robert static void 839c0b746e5SOllivier Robert sys_info( 840c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 841c0b746e5SOllivier Robert struct interface *inter, 842c0b746e5SOllivier Robert struct req_pkt *inpkt 843c0b746e5SOllivier Robert ) 844c0b746e5SOllivier Robert { 845c0b746e5SOllivier Robert register struct info_sys *is; 846c0b746e5SOllivier Robert 847c0b746e5SOllivier Robert /* 848c0b746e5SOllivier Robert * Importations from the protocol module 849c0b746e5SOllivier Robert */ 850c0b746e5SOllivier Robert extern u_char sys_leap; 851c0b746e5SOllivier Robert extern u_char sys_stratum; 852c0b746e5SOllivier Robert extern s_char sys_precision; 853c0b746e5SOllivier Robert extern double sys_rootdelay; 854c0b746e5SOllivier Robert extern double sys_rootdispersion; 855c0b746e5SOllivier Robert extern u_int32 sys_refid; 856c0b746e5SOllivier Robert extern l_fp sys_reftime; 857c0b746e5SOllivier Robert extern u_char sys_poll; 858c0b746e5SOllivier Robert extern struct peer *sys_peer; 859c0b746e5SOllivier Robert extern int sys_bclient; 860c0b746e5SOllivier Robert extern double sys_bdelay; 861c0b746e5SOllivier Robert extern l_fp sys_authdelay; 862c0b746e5SOllivier Robert extern double clock_stability; 863c0b746e5SOllivier Robert extern double sys_error; 864c0b746e5SOllivier Robert 865c0b746e5SOllivier Robert is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt, 866c0b746e5SOllivier Robert sizeof(struct info_sys)); 867c0b746e5SOllivier Robert 868c0b746e5SOllivier Robert if (sys_peer != 0) { 869c0b746e5SOllivier Robert is->peer = NSRCADR(&sys_peer->srcadr); 870c0b746e5SOllivier Robert is->peer_mode = sys_peer->hmode; 871c0b746e5SOllivier Robert } else { 872c0b746e5SOllivier Robert is->peer = 0; 873c0b746e5SOllivier Robert is->peer_mode = 0; 874c0b746e5SOllivier Robert } 875c0b746e5SOllivier Robert is->leap = sys_leap; 876c0b746e5SOllivier Robert is->stratum = sys_stratum; 877c0b746e5SOllivier Robert is->precision = sys_precision; 878c0b746e5SOllivier Robert is->rootdelay = htonl(DTOFP(sys_rootdelay)); 879c0b746e5SOllivier Robert is->rootdispersion = htonl(DTOUFP(sys_rootdispersion)); 880c0b746e5SOllivier Robert is->frequency = htonl(DTOFP(sys_error)); 881c0b746e5SOllivier Robert is->stability = htonl(DTOUFP(clock_stability * 1e6)); 882c0b746e5SOllivier Robert is->refid = sys_refid; 883c0b746e5SOllivier Robert HTONL_FP(&sys_reftime, &is->reftime); 884c0b746e5SOllivier Robert 885c0b746e5SOllivier Robert is->poll = sys_poll; 886c0b746e5SOllivier Robert 887c0b746e5SOllivier Robert is->flags = 0; 888c0b746e5SOllivier Robert if (sys_bclient) 889c0b746e5SOllivier Robert is->flags |= INFO_FLAG_BCLIENT; 890c0b746e5SOllivier Robert if (sys_authenticate) 891c0b746e5SOllivier Robert is->flags |= INFO_FLAG_AUTHENTICATE; 892c0b746e5SOllivier Robert if (kern_enable) 893c0b746e5SOllivier Robert is->flags |= INFO_FLAG_KERNEL; 894c0b746e5SOllivier Robert if (ntp_enable) 895c0b746e5SOllivier Robert is->flags |= INFO_FLAG_NTP; 896c0b746e5SOllivier Robert if (pll_control) 897c0b746e5SOllivier Robert is->flags |= INFO_FLAG_PLL_SYNC; 898c0b746e5SOllivier Robert if (pps_control) 899c0b746e5SOllivier Robert is->flags |= INFO_FLAG_PPS_SYNC; 900c0b746e5SOllivier Robert if (mon_enabled != MON_OFF) 901c0b746e5SOllivier Robert is->flags |= INFO_FLAG_MONITOR; 902c0b746e5SOllivier Robert if (stats_control) 903c0b746e5SOllivier Robert is->flags |= INFO_FLAG_FILEGEN; 904c0b746e5SOllivier Robert is->bdelay = HTONS_FP(DTOFP(sys_bdelay)); 905c0b746e5SOllivier Robert HTONL_UF(sys_authdelay.l_f, &is->authdelay); 906c0b746e5SOllivier Robert 907c0b746e5SOllivier Robert (void) more_pkt(); 908c0b746e5SOllivier Robert flush_pkt(); 909c0b746e5SOllivier Robert } 910c0b746e5SOllivier Robert 911c0b746e5SOllivier Robert 912c0b746e5SOllivier Robert /* 913c0b746e5SOllivier Robert * sys_stats - return system statistics 914c0b746e5SOllivier Robert */ 915c0b746e5SOllivier Robert static void 916c0b746e5SOllivier Robert sys_stats( 917c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 918c0b746e5SOllivier Robert struct interface *inter, 919c0b746e5SOllivier Robert struct req_pkt *inpkt 920c0b746e5SOllivier Robert ) 921c0b746e5SOllivier Robert { 922c0b746e5SOllivier Robert register struct info_sys_stats *ss; 923c0b746e5SOllivier Robert 924c0b746e5SOllivier Robert /* 925c0b746e5SOllivier Robert * Importations from the protocol module 926c0b746e5SOllivier Robert */ 927c0b746e5SOllivier Robert extern u_long sys_stattime; 928c0b746e5SOllivier Robert extern u_long sys_badstratum; 929c0b746e5SOllivier Robert extern u_long sys_oldversionpkt; 930c0b746e5SOllivier Robert extern u_long sys_newversionpkt; 931c0b746e5SOllivier Robert extern u_long sys_unknownversion; 932c0b746e5SOllivier Robert extern u_long sys_badlength; 933c0b746e5SOllivier Robert extern u_long sys_processed; 934c0b746e5SOllivier Robert extern u_long sys_badauth; 935c0b746e5SOllivier Robert extern u_long sys_limitrejected; 936c0b746e5SOllivier Robert 937c0b746e5SOllivier Robert ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt, 938c0b746e5SOllivier Robert sizeof(struct info_sys_stats)); 939c0b746e5SOllivier Robert 940c0b746e5SOllivier Robert ss->timeup = htonl((u_int32)current_time); 941c0b746e5SOllivier Robert ss->timereset = htonl((u_int32)(current_time - sys_stattime)); 942c0b746e5SOllivier Robert ss->badstratum = htonl((u_int32)sys_badstratum); 943c0b746e5SOllivier Robert ss->oldversionpkt = htonl((u_int32)sys_oldversionpkt); 944c0b746e5SOllivier Robert ss->newversionpkt = htonl((u_int32)sys_newversionpkt); 945c0b746e5SOllivier Robert ss->unknownversion = htonl((u_int32)sys_unknownversion); 946c0b746e5SOllivier Robert ss->badlength = htonl((u_int32)sys_badlength); 947c0b746e5SOllivier Robert ss->processed = htonl((u_int32)sys_processed); 948c0b746e5SOllivier Robert ss->badauth = htonl((u_int32)sys_badauth); 949c0b746e5SOllivier Robert ss->limitrejected = htonl((u_int32)sys_limitrejected); 950c0b746e5SOllivier Robert (void) more_pkt(); 951c0b746e5SOllivier Robert flush_pkt(); 952c0b746e5SOllivier Robert } 953c0b746e5SOllivier Robert 954c0b746e5SOllivier Robert 955c0b746e5SOllivier Robert /* 956c0b746e5SOllivier Robert * mem_stats - return memory statistics 957c0b746e5SOllivier Robert */ 958c0b746e5SOllivier Robert static void 959c0b746e5SOllivier Robert mem_stats( 960c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 961c0b746e5SOllivier Robert struct interface *inter, 962c0b746e5SOllivier Robert struct req_pkt *inpkt 963c0b746e5SOllivier Robert ) 964c0b746e5SOllivier Robert { 965c0b746e5SOllivier Robert register struct info_mem_stats *ms; 966c0b746e5SOllivier Robert register int i; 967c0b746e5SOllivier Robert 968c0b746e5SOllivier Robert /* 969c0b746e5SOllivier Robert * Importations from the peer module 970c0b746e5SOllivier Robert */ 971c0b746e5SOllivier Robert extern int peer_hash_count[HASH_SIZE]; 972c0b746e5SOllivier Robert extern int peer_free_count; 973c0b746e5SOllivier Robert extern u_long peer_timereset; 974c0b746e5SOllivier Robert extern u_long findpeer_calls; 975c0b746e5SOllivier Robert extern u_long peer_allocations; 976c0b746e5SOllivier Robert extern u_long peer_demobilizations; 977c0b746e5SOllivier Robert extern int total_peer_structs; 978c0b746e5SOllivier Robert 979c0b746e5SOllivier Robert ms = (struct info_mem_stats *)prepare_pkt(srcadr, inter, inpkt, 980c0b746e5SOllivier Robert sizeof(struct info_mem_stats)); 981c0b746e5SOllivier Robert 982c0b746e5SOllivier Robert ms->timereset = htonl((u_int32)(current_time - peer_timereset)); 983c0b746e5SOllivier Robert ms->totalpeermem = htons((u_short)total_peer_structs); 984c0b746e5SOllivier Robert ms->freepeermem = htons((u_short)peer_free_count); 985c0b746e5SOllivier Robert ms->findpeer_calls = htonl((u_int32)findpeer_calls); 986c0b746e5SOllivier Robert ms->allocations = htonl((u_int32)peer_allocations); 987c0b746e5SOllivier Robert ms->demobilizations = htonl((u_int32)peer_demobilizations); 988c0b746e5SOllivier Robert 989c0b746e5SOllivier Robert for (i = 0; i < HASH_SIZE; i++) { 990c0b746e5SOllivier Robert if (peer_hash_count[i] > 255) 991c0b746e5SOllivier Robert ms->hashcount[i] = 255; 992c0b746e5SOllivier Robert else 993c0b746e5SOllivier Robert ms->hashcount[i] = (u_char)peer_hash_count[i]; 994c0b746e5SOllivier Robert } 995c0b746e5SOllivier Robert 996c0b746e5SOllivier Robert (void) more_pkt(); 997c0b746e5SOllivier Robert flush_pkt(); 998c0b746e5SOllivier Robert } 999c0b746e5SOllivier Robert 1000c0b746e5SOllivier Robert 1001c0b746e5SOllivier Robert /* 1002c0b746e5SOllivier Robert * io_stats - return io statistics 1003c0b746e5SOllivier Robert */ 1004c0b746e5SOllivier Robert static void 1005c0b746e5SOllivier Robert io_stats( 1006c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1007c0b746e5SOllivier Robert struct interface *inter, 1008c0b746e5SOllivier Robert struct req_pkt *inpkt 1009c0b746e5SOllivier Robert ) 1010c0b746e5SOllivier Robert { 1011c0b746e5SOllivier Robert register struct info_io_stats *io; 1012c0b746e5SOllivier Robert 1013c0b746e5SOllivier Robert /* 1014c0b746e5SOllivier Robert * Importations from the io module 1015c0b746e5SOllivier Robert */ 1016c0b746e5SOllivier Robert extern u_long io_timereset; 1017c0b746e5SOllivier Robert 1018c0b746e5SOllivier Robert io = (struct info_io_stats *)prepare_pkt(srcadr, inter, inpkt, 1019c0b746e5SOllivier Robert sizeof(struct info_io_stats)); 1020c0b746e5SOllivier Robert 1021c0b746e5SOllivier Robert io->timereset = htonl((u_int32)(current_time - io_timereset)); 1022c0b746e5SOllivier Robert io->totalrecvbufs = htons((u_short) total_recvbuffs()); 1023c0b746e5SOllivier Robert io->freerecvbufs = htons((u_short) free_recvbuffs()); 1024c0b746e5SOllivier Robert io->fullrecvbufs = htons((u_short) full_recvbuffs()); 1025c0b746e5SOllivier Robert io->lowwater = htons((u_short) lowater_additions()); 1026c0b746e5SOllivier Robert io->dropped = htonl((u_int32)packets_dropped); 1027c0b746e5SOllivier Robert io->ignored = htonl((u_int32)packets_ignored); 1028c0b746e5SOllivier Robert io->received = htonl((u_int32)packets_received); 1029c0b746e5SOllivier Robert io->sent = htonl((u_int32)packets_sent); 1030c0b746e5SOllivier Robert io->notsent = htonl((u_int32)packets_notsent); 1031c0b746e5SOllivier Robert io->interrupts = htonl((u_int32)handler_calls); 1032c0b746e5SOllivier Robert io->int_received = htonl((u_int32)handler_pkts); 1033c0b746e5SOllivier Robert 1034c0b746e5SOllivier Robert (void) more_pkt(); 1035c0b746e5SOllivier Robert flush_pkt(); 1036c0b746e5SOllivier Robert } 1037c0b746e5SOllivier Robert 1038c0b746e5SOllivier Robert 1039c0b746e5SOllivier Robert /* 1040c0b746e5SOllivier Robert * timer_stats - return timer statistics 1041c0b746e5SOllivier Robert */ 1042c0b746e5SOllivier Robert static void 1043c0b746e5SOllivier Robert timer_stats( 1044c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1045c0b746e5SOllivier Robert struct interface *inter, 1046c0b746e5SOllivier Robert struct req_pkt *inpkt 1047c0b746e5SOllivier Robert ) 1048c0b746e5SOllivier Robert { 1049c0b746e5SOllivier Robert register struct info_timer_stats *ts; 1050c0b746e5SOllivier Robert 1051c0b746e5SOllivier Robert /* 1052c0b746e5SOllivier Robert * Importations from the timer module 1053c0b746e5SOllivier Robert */ 1054c0b746e5SOllivier Robert extern u_long timer_timereset; 1055c0b746e5SOllivier Robert extern u_long timer_overflows; 1056c0b746e5SOllivier Robert extern u_long timer_xmtcalls; 1057c0b746e5SOllivier Robert 1058c0b746e5SOllivier Robert ts = (struct info_timer_stats *)prepare_pkt(srcadr, inter, inpkt, 1059c0b746e5SOllivier Robert sizeof(struct info_timer_stats)); 1060c0b746e5SOllivier Robert 1061c0b746e5SOllivier Robert ts->timereset = htonl((u_int32)(current_time - timer_timereset)); 1062c0b746e5SOllivier Robert ts->alarms = htonl((u_int32)alarm_overflow); 1063c0b746e5SOllivier Robert ts->overflows = htonl((u_int32)timer_overflows); 1064c0b746e5SOllivier Robert ts->xmtcalls = htonl((u_int32)timer_xmtcalls); 1065c0b746e5SOllivier Robert 1066c0b746e5SOllivier Robert (void) more_pkt(); 1067c0b746e5SOllivier Robert flush_pkt(); 1068c0b746e5SOllivier Robert } 1069c0b746e5SOllivier Robert 1070c0b746e5SOllivier Robert 1071c0b746e5SOllivier Robert /* 1072c0b746e5SOllivier Robert * loop_info - return the current state of the loop filter 1073c0b746e5SOllivier Robert */ 1074c0b746e5SOllivier Robert static void 1075c0b746e5SOllivier Robert loop_info( 1076c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1077c0b746e5SOllivier Robert struct interface *inter, 1078c0b746e5SOllivier Robert struct req_pkt *inpkt 1079c0b746e5SOllivier Robert ) 1080c0b746e5SOllivier Robert { 1081c0b746e5SOllivier Robert register struct info_loop *li; 1082c0b746e5SOllivier Robert l_fp ltmp; 1083c0b746e5SOllivier Robert 1084c0b746e5SOllivier Robert /* 1085c0b746e5SOllivier Robert * Importations from the loop filter module 1086c0b746e5SOllivier Robert */ 1087c0b746e5SOllivier Robert extern double last_offset; 1088c0b746e5SOllivier Robert extern double drift_comp; 1089c0b746e5SOllivier Robert extern int tc_counter; 1090c0b746e5SOllivier Robert extern u_long last_time; 1091c0b746e5SOllivier Robert 1092c0b746e5SOllivier Robert li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt, 1093c0b746e5SOllivier Robert sizeof(struct info_loop)); 1094c0b746e5SOllivier Robert 1095c0b746e5SOllivier Robert DTOLFP(last_offset, <mp); 1096c0b746e5SOllivier Robert HTONL_FP(<mp, &li->last_offset); 1097c0b746e5SOllivier Robert DTOLFP(drift_comp * 1e6, <mp); 1098c0b746e5SOllivier Robert HTONL_FP(<mp, &li->drift_comp); 1099c0b746e5SOllivier Robert li->compliance = htonl((u_int32)(tc_counter)); 1100c0b746e5SOllivier Robert li->watchdog_timer = htonl((u_int32)(current_time - last_time)); 1101c0b746e5SOllivier Robert 1102c0b746e5SOllivier Robert (void) more_pkt(); 1103c0b746e5SOllivier Robert flush_pkt(); 1104c0b746e5SOllivier Robert } 1105c0b746e5SOllivier Robert 1106c0b746e5SOllivier Robert 1107c0b746e5SOllivier Robert /* 1108c0b746e5SOllivier Robert * do_conf - add a peer to the configuration list 1109c0b746e5SOllivier Robert */ 1110c0b746e5SOllivier Robert static void 1111c0b746e5SOllivier Robert do_conf( 1112c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1113c0b746e5SOllivier Robert struct interface *inter, 1114c0b746e5SOllivier Robert struct req_pkt *inpkt 1115c0b746e5SOllivier Robert ) 1116c0b746e5SOllivier Robert { 1117c0b746e5SOllivier Robert register struct conf_peer *cp; 1118c0b746e5SOllivier Robert register int items; 1119c0b746e5SOllivier Robert struct sockaddr_in peeraddr; 1120c0b746e5SOllivier Robert int fl; 1121c0b746e5SOllivier Robert 1122c0b746e5SOllivier Robert /* 1123c0b746e5SOllivier Robert * Do a check of everything to see that it looks 1124c0b746e5SOllivier Robert * okay. If not, complain about it. Note we are 1125c0b746e5SOllivier Robert * very picky here. 1126c0b746e5SOllivier Robert */ 1127c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1128c0b746e5SOllivier Robert cp = (struct conf_peer *)inpkt->data; 1129c0b746e5SOllivier Robert 1130c0b746e5SOllivier Robert fl = 0; 1131c0b746e5SOllivier Robert while (items-- > 0 && !fl) { 1132c0b746e5SOllivier Robert if (((cp->version) > NTP_VERSION) 1133c0b746e5SOllivier Robert || ((cp->version) < NTP_OLDVERSION)) 1134c0b746e5SOllivier Robert fl = 1; 1135c0b746e5SOllivier Robert if (cp->hmode != MODE_ACTIVE 1136c0b746e5SOllivier Robert && cp->hmode != MODE_CLIENT 1137c0b746e5SOllivier Robert && cp->hmode != MODE_BROADCAST) 1138c0b746e5SOllivier Robert fl = 1; 1139c0b746e5SOllivier Robert if (cp->flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER 1140c0b746e5SOllivier Robert | CONF_FLAG_NOSELECT | CONF_FLAG_BURST | CONF_FLAG_SKEY)) 1141c0b746e5SOllivier Robert fl = 1; 1142c0b746e5SOllivier Robert cp++; 1143c0b746e5SOllivier Robert } 1144c0b746e5SOllivier Robert 1145c0b746e5SOllivier Robert if (fl) { 1146c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1147c0b746e5SOllivier Robert return; 1148c0b746e5SOllivier Robert } 1149c0b746e5SOllivier Robert 1150c0b746e5SOllivier Robert /* 1151c0b746e5SOllivier Robert * Looks okay, try it out 1152c0b746e5SOllivier Robert */ 1153c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1154c0b746e5SOllivier Robert cp = (struct conf_peer *)inpkt->data; 1155c0b746e5SOllivier Robert memset((char *)&peeraddr, 0, sizeof(struct sockaddr_in)); 1156c0b746e5SOllivier Robert peeraddr.sin_family = AF_INET; 1157c0b746e5SOllivier Robert peeraddr.sin_port = htons(NTP_PORT); 1158c0b746e5SOllivier Robert 1159c0b746e5SOllivier Robert /* 1160c0b746e5SOllivier Robert * Make sure the address is valid 1161c0b746e5SOllivier Robert */ 1162c0b746e5SOllivier Robert if ( 1163c0b746e5SOllivier Robert #ifdef REFCLOCK 1164c0b746e5SOllivier Robert !ISREFCLOCKADR(&peeraddr) && 1165c0b746e5SOllivier Robert #endif 1166c0b746e5SOllivier Robert ISBADADR(&peeraddr)) { 1167c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1168c0b746e5SOllivier Robert return; 1169c0b746e5SOllivier Robert } 1170c0b746e5SOllivier Robert 1171c0b746e5SOllivier Robert while (items-- > 0) { 1172c0b746e5SOllivier Robert fl = 0; 1173c0b746e5SOllivier Robert if (cp->flags & CONF_FLAG_AUTHENABLE) 1174c0b746e5SOllivier Robert fl |= FLAG_AUTHENABLE; 1175c0b746e5SOllivier Robert if (cp->flags & CONF_FLAG_PREFER) 1176c0b746e5SOllivier Robert fl |= FLAG_PREFER; 1177c0b746e5SOllivier Robert if (cp->flags & CONF_FLAG_NOSELECT) 1178c0b746e5SOllivier Robert fl |= FLAG_NOSELECT; 1179c0b746e5SOllivier Robert if (cp->flags & CONF_FLAG_BURST) 1180c0b746e5SOllivier Robert fl |= FLAG_BURST; 1181c0b746e5SOllivier Robert if (cp->flags & CONF_FLAG_SKEY) 1182c0b746e5SOllivier Robert fl |= FLAG_SKEY; 1183c0b746e5SOllivier Robert peeraddr.sin_addr.s_addr = cp->peeraddr; 1184c0b746e5SOllivier Robert /* XXX W2DO? minpoll/maxpoll arguments ??? */ 1185c0b746e5SOllivier Robert if (peer_config(&peeraddr, (struct interface *)0, 1186c0b746e5SOllivier Robert cp->hmode, cp->version, cp->minpoll, cp->maxpoll, 1187c0b746e5SOllivier Robert fl, cp->ttl, cp->keyid) == 0) { 1188c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1189c0b746e5SOllivier Robert return; 1190c0b746e5SOllivier Robert } 1191c0b746e5SOllivier Robert cp++; 1192c0b746e5SOllivier Robert } 1193c0b746e5SOllivier Robert 1194c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1195c0b746e5SOllivier Robert } 1196c0b746e5SOllivier Robert 1197c0b746e5SOllivier Robert 1198c0b746e5SOllivier Robert /* 1199c0b746e5SOllivier Robert * do_unconf - remove a peer from the configuration list 1200c0b746e5SOllivier Robert */ 1201c0b746e5SOllivier Robert static void 1202c0b746e5SOllivier Robert do_unconf( 1203c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1204c0b746e5SOllivier Robert struct interface *inter, 1205c0b746e5SOllivier Robert struct req_pkt *inpkt 1206c0b746e5SOllivier Robert ) 1207c0b746e5SOllivier Robert { 1208c0b746e5SOllivier Robert register struct conf_unpeer *cp; 1209c0b746e5SOllivier Robert register int items; 1210c0b746e5SOllivier Robert register struct peer *peer; 1211c0b746e5SOllivier Robert struct sockaddr_in peeraddr; 1212c0b746e5SOllivier Robert int bad, found; 1213c0b746e5SOllivier Robert 1214c0b746e5SOllivier Robert /* 1215c0b746e5SOllivier Robert * This is a bit unstructured, but I like to be careful. 1216c0b746e5SOllivier Robert * We check to see that every peer exists and is actually 1217c0b746e5SOllivier Robert * configured. If so, we remove them. If not, we return 1218c0b746e5SOllivier Robert * an error. 1219c0b746e5SOllivier Robert */ 1220c0b746e5SOllivier Robert peeraddr.sin_family = AF_INET; 1221c0b746e5SOllivier Robert peeraddr.sin_port = htons(NTP_PORT); 1222c0b746e5SOllivier Robert 1223c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1224c0b746e5SOllivier Robert cp = (struct conf_unpeer *)inpkt->data; 1225c0b746e5SOllivier Robert 1226c0b746e5SOllivier Robert bad = 0; 1227c0b746e5SOllivier Robert while (items-- > 0 && !bad) { 1228c0b746e5SOllivier Robert peeraddr.sin_addr.s_addr = cp->peeraddr; 1229c0b746e5SOllivier Robert found = 0; 1230c0b746e5SOllivier Robert peer = (struct peer *)0; 1231c0b746e5SOllivier Robert while (!found) { 1232c0b746e5SOllivier Robert peer = findexistingpeer(&peeraddr, peer, -1); 1233c0b746e5SOllivier Robert if (peer == (struct peer *)0) 1234c0b746e5SOllivier Robert break; 1235c0b746e5SOllivier Robert if (peer->flags & FLAG_CONFIG) 1236c0b746e5SOllivier Robert found = 1; 1237c0b746e5SOllivier Robert } 1238c0b746e5SOllivier Robert if (!found) 1239c0b746e5SOllivier Robert bad = 1; 1240c0b746e5SOllivier Robert cp++; 1241c0b746e5SOllivier Robert } 1242c0b746e5SOllivier Robert 1243c0b746e5SOllivier Robert if (bad) { 1244c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1245c0b746e5SOllivier Robert return; 1246c0b746e5SOllivier Robert } 1247c0b746e5SOllivier Robert 1248c0b746e5SOllivier Robert /* 1249c0b746e5SOllivier Robert * Now do it in earnest. 1250c0b746e5SOllivier Robert */ 1251c0b746e5SOllivier Robert 1252c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1253c0b746e5SOllivier Robert cp = (struct conf_unpeer *)inpkt->data; 1254c0b746e5SOllivier Robert while (items-- > 0) { 1255c0b746e5SOllivier Robert peeraddr.sin_addr.s_addr = cp->peeraddr; 1256c0b746e5SOllivier Robert peer_unconfig(&peeraddr, (struct interface *)0, -1); 1257c0b746e5SOllivier Robert cp++; 1258c0b746e5SOllivier Robert } 1259c0b746e5SOllivier Robert 1260c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1261c0b746e5SOllivier Robert } 1262c0b746e5SOllivier Robert 1263c0b746e5SOllivier Robert 1264c0b746e5SOllivier Robert /* 1265c0b746e5SOllivier Robert * set_sys_flag - set system flags 1266c0b746e5SOllivier Robert */ 1267c0b746e5SOllivier Robert static void 1268c0b746e5SOllivier Robert set_sys_flag( 1269c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1270c0b746e5SOllivier Robert struct interface *inter, 1271c0b746e5SOllivier Robert struct req_pkt *inpkt 1272c0b746e5SOllivier Robert ) 1273c0b746e5SOllivier Robert { 1274c0b746e5SOllivier Robert setclr_flags(srcadr, inter, inpkt, 1); 1275c0b746e5SOllivier Robert } 1276c0b746e5SOllivier Robert 1277c0b746e5SOllivier Robert 1278c0b746e5SOllivier Robert /* 1279c0b746e5SOllivier Robert * clr_sys_flag - clear system flags 1280c0b746e5SOllivier Robert */ 1281c0b746e5SOllivier Robert static void 1282c0b746e5SOllivier Robert clr_sys_flag( 1283c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1284c0b746e5SOllivier Robert struct interface *inter, 1285c0b746e5SOllivier Robert struct req_pkt *inpkt 1286c0b746e5SOllivier Robert ) 1287c0b746e5SOllivier Robert { 1288c0b746e5SOllivier Robert setclr_flags(srcadr, inter, inpkt, 0); 1289c0b746e5SOllivier Robert } 1290c0b746e5SOllivier Robert 1291c0b746e5SOllivier Robert 1292c0b746e5SOllivier Robert /* 1293c0b746e5SOllivier Robert * setclr_flags - do the grunge work of flag setting/clearing 1294c0b746e5SOllivier Robert */ 1295c0b746e5SOllivier Robert static void 1296c0b746e5SOllivier Robert setclr_flags( 1297c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1298c0b746e5SOllivier Robert struct interface *inter, 1299c0b746e5SOllivier Robert struct req_pkt *inpkt, 1300c0b746e5SOllivier Robert u_long set 1301c0b746e5SOllivier Robert ) 1302c0b746e5SOllivier Robert { 1303c0b746e5SOllivier Robert register u_long flags; 1304c0b746e5SOllivier Robert 1305c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 1306c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1307c0b746e5SOllivier Robert return; 1308c0b746e5SOllivier Robert } 1309c0b746e5SOllivier Robert 1310c0b746e5SOllivier Robert flags = ((struct conf_sys_flags *)inpkt->data)->flags; 1311c0b746e5SOllivier Robert 1312c0b746e5SOllivier Robert if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_AUTHENTICATE | 1313c0b746e5SOllivier Robert SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR | 1314c0b746e5SOllivier Robert SYS_FLAG_FILEGEN)) { 1315c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1316c0b746e5SOllivier Robert return; 1317c0b746e5SOllivier Robert } 1318c0b746e5SOllivier Robert 1319c0b746e5SOllivier Robert if (flags & SYS_FLAG_BCLIENT) 1320c0b746e5SOllivier Robert proto_config(PROTO_BROADCLIENT, set, 0.); 1321c0b746e5SOllivier Robert if (flags & SYS_FLAG_AUTHENTICATE) 1322c0b746e5SOllivier Robert proto_config(PROTO_AUTHENTICATE, set, 0.); 1323c0b746e5SOllivier Robert if (flags & SYS_FLAG_NTP) 1324c0b746e5SOllivier Robert proto_config(PROTO_NTP, set, 0.); 1325c0b746e5SOllivier Robert if (flags & SYS_FLAG_KERNEL) 1326c0b746e5SOllivier Robert proto_config(PROTO_KERNEL, set, 0.); 1327c0b746e5SOllivier Robert if (flags & SYS_FLAG_MONITOR) 1328c0b746e5SOllivier Robert proto_config(PROTO_MONITOR, set, 0.); 1329c0b746e5SOllivier Robert if (flags & SYS_FLAG_FILEGEN) 1330c0b746e5SOllivier Robert proto_config(PROTO_FILEGEN, set, 0.); 1331c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1332c0b746e5SOllivier Robert } 1333c0b746e5SOllivier Robert 1334c0b746e5SOllivier Robert 1335c0b746e5SOllivier Robert /* 1336c0b746e5SOllivier Robert * list_restrict - return the restrict list 1337c0b746e5SOllivier Robert */ 1338c0b746e5SOllivier Robert static void 1339c0b746e5SOllivier Robert list_restrict( 1340c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1341c0b746e5SOllivier Robert struct interface *inter, 1342c0b746e5SOllivier Robert struct req_pkt *inpkt 1343c0b746e5SOllivier Robert ) 1344c0b746e5SOllivier Robert { 1345c0b746e5SOllivier Robert register struct info_restrict *ir; 1346c0b746e5SOllivier Robert register struct restrictlist *rl; 1347c0b746e5SOllivier Robert extern struct restrictlist *restrictlist; 1348c0b746e5SOllivier Robert 1349c0b746e5SOllivier Robert #ifdef DEBUG 1350c0b746e5SOllivier Robert if (debug > 2) 1351c0b746e5SOllivier Robert printf("wants peer list summary\n"); 1352c0b746e5SOllivier Robert #endif 1353c0b746e5SOllivier Robert 1354c0b746e5SOllivier Robert ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt, 1355c0b746e5SOllivier Robert sizeof(struct info_restrict)); 1356c0b746e5SOllivier Robert for (rl = restrictlist; rl != 0 && ir != 0; rl = rl->next) { 1357c0b746e5SOllivier Robert ir->addr = htonl(rl->addr); 1358c0b746e5SOllivier Robert ir->mask = htonl(rl->mask); 1359c0b746e5SOllivier Robert ir->count = htonl((u_int32)rl->count); 1360c0b746e5SOllivier Robert ir->flags = htons(rl->flags); 1361c0b746e5SOllivier Robert ir->mflags = htons(rl->mflags); 1362c0b746e5SOllivier Robert ir = (struct info_restrict *)more_pkt(); 1363c0b746e5SOllivier Robert } 1364c0b746e5SOllivier Robert flush_pkt(); 1365c0b746e5SOllivier Robert } 1366c0b746e5SOllivier Robert 1367c0b746e5SOllivier Robert 1368c0b746e5SOllivier Robert 1369c0b746e5SOllivier Robert /* 1370c0b746e5SOllivier Robert * do_resaddflags - add flags to a restrict entry (or create one) 1371c0b746e5SOllivier Robert */ 1372c0b746e5SOllivier Robert static void 1373c0b746e5SOllivier Robert do_resaddflags( 1374c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1375c0b746e5SOllivier Robert struct interface *inter, 1376c0b746e5SOllivier Robert struct req_pkt *inpkt 1377c0b746e5SOllivier Robert ) 1378c0b746e5SOllivier Robert { 1379c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_FLAGS); 1380c0b746e5SOllivier Robert } 1381c0b746e5SOllivier Robert 1382c0b746e5SOllivier Robert 1383c0b746e5SOllivier Robert 1384c0b746e5SOllivier Robert /* 1385c0b746e5SOllivier Robert * do_ressubflags - remove flags from a restrict entry 1386c0b746e5SOllivier Robert */ 1387c0b746e5SOllivier Robert static void 1388c0b746e5SOllivier Robert do_ressubflags( 1389c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1390c0b746e5SOllivier Robert struct interface *inter, 1391c0b746e5SOllivier Robert struct req_pkt *inpkt 1392c0b746e5SOllivier Robert ) 1393c0b746e5SOllivier Robert { 1394c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_UNFLAG); 1395c0b746e5SOllivier Robert } 1396c0b746e5SOllivier Robert 1397c0b746e5SOllivier Robert 1398c0b746e5SOllivier Robert /* 1399c0b746e5SOllivier Robert * do_unrestrict - remove a restrict entry from the list 1400c0b746e5SOllivier Robert */ 1401c0b746e5SOllivier Robert static void 1402c0b746e5SOllivier Robert do_unrestrict( 1403c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1404c0b746e5SOllivier Robert struct interface *inter, 1405c0b746e5SOllivier Robert struct req_pkt *inpkt 1406c0b746e5SOllivier Robert ) 1407c0b746e5SOllivier Robert { 1408c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_REMOVE); 1409c0b746e5SOllivier Robert } 1410c0b746e5SOllivier Robert 1411c0b746e5SOllivier Robert 1412c0b746e5SOllivier Robert 1413c0b746e5SOllivier Robert 1414c0b746e5SOllivier Robert 1415c0b746e5SOllivier Robert /* 1416c0b746e5SOllivier Robert * do_restrict - do the dirty stuff of dealing with restrictions 1417c0b746e5SOllivier Robert */ 1418c0b746e5SOllivier Robert static void 1419c0b746e5SOllivier Robert do_restrict( 1420c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1421c0b746e5SOllivier Robert struct interface *inter, 1422c0b746e5SOllivier Robert struct req_pkt *inpkt, 1423c0b746e5SOllivier Robert int op 1424c0b746e5SOllivier Robert ) 1425c0b746e5SOllivier Robert { 1426c0b746e5SOllivier Robert register struct conf_restrict *cr; 1427c0b746e5SOllivier Robert register int items; 1428c0b746e5SOllivier Robert struct sockaddr_in matchaddr; 1429c0b746e5SOllivier Robert struct sockaddr_in matchmask; 1430c0b746e5SOllivier Robert int bad; 1431c0b746e5SOllivier Robert 1432c0b746e5SOllivier Robert /* 1433c0b746e5SOllivier Robert * Do a check of the flags to make sure that only 1434c0b746e5SOllivier Robert * the NTPPORT flag is set, if any. If not, complain 1435c0b746e5SOllivier Robert * about it. Note we are very picky here. 1436c0b746e5SOllivier Robert */ 1437c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1438c0b746e5SOllivier Robert cr = (struct conf_restrict *)inpkt->data; 1439c0b746e5SOllivier Robert 1440c0b746e5SOllivier Robert bad = 0; 1441c0b746e5SOllivier Robert while (items-- > 0 && !bad) { 1442c0b746e5SOllivier Robert if (cr->mflags & ~(RESM_NTPONLY)) 1443c0b746e5SOllivier Robert bad = 1; 1444c0b746e5SOllivier Robert if (cr->flags & ~(RES_ALLFLAGS)) 1445c0b746e5SOllivier Robert bad = 1; 1446c0b746e5SOllivier Robert if (cr->addr == htonl(INADDR_ANY) && cr->mask != htonl(INADDR_ANY)) 1447c0b746e5SOllivier Robert bad = 1; 1448c0b746e5SOllivier Robert cr++; 1449c0b746e5SOllivier Robert } 1450c0b746e5SOllivier Robert 1451c0b746e5SOllivier Robert if (bad) { 1452c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1453c0b746e5SOllivier Robert return; 1454c0b746e5SOllivier Robert } 1455c0b746e5SOllivier Robert 1456c0b746e5SOllivier Robert /* 1457c0b746e5SOllivier Robert * Looks okay, try it out 1458c0b746e5SOllivier Robert */ 1459c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1460c0b746e5SOllivier Robert cr = (struct conf_restrict *)inpkt->data; 1461c0b746e5SOllivier Robert memset((char *)&matchaddr, 0, sizeof(struct sockaddr_in)); 1462c0b746e5SOllivier Robert memset((char *)&matchmask, 0, sizeof(struct sockaddr_in)); 1463c0b746e5SOllivier Robert matchaddr.sin_family = AF_INET; 1464c0b746e5SOllivier Robert matchmask.sin_family = AF_INET; 1465c0b746e5SOllivier Robert 1466c0b746e5SOllivier Robert while (items-- > 0) { 1467c0b746e5SOllivier Robert matchaddr.sin_addr.s_addr = cr->addr; 1468c0b746e5SOllivier Robert matchmask.sin_addr.s_addr = cr->mask; 1469c0b746e5SOllivier Robert hack_restrict(op, &matchaddr, &matchmask, cr->mflags, 1470c0b746e5SOllivier Robert cr->flags); 1471c0b746e5SOllivier Robert cr++; 1472c0b746e5SOllivier Robert } 1473c0b746e5SOllivier Robert 1474c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1475c0b746e5SOllivier Robert } 1476c0b746e5SOllivier Robert 1477c0b746e5SOllivier Robert 1478c0b746e5SOllivier Robert /* 1479c0b746e5SOllivier Robert * mon_getlist - return monitor data 1480c0b746e5SOllivier Robert */ 1481c0b746e5SOllivier Robert static void 1482c0b746e5SOllivier Robert mon_getlist_0( 1483c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1484c0b746e5SOllivier Robert struct interface *inter, 1485c0b746e5SOllivier Robert struct req_pkt *inpkt 1486c0b746e5SOllivier Robert ) 1487c0b746e5SOllivier Robert { 1488c0b746e5SOllivier Robert register struct info_monitor *im; 1489c0b746e5SOllivier Robert register struct mon_data *md; 1490c0b746e5SOllivier Robert extern struct mon_data mon_mru_list; 1491c0b746e5SOllivier Robert extern int mon_enabled; 1492c0b746e5SOllivier Robert 1493c0b746e5SOllivier Robert #ifdef DEBUG 1494c0b746e5SOllivier Robert if (debug > 2) 1495c0b746e5SOllivier Robert printf("wants monitor 0 list\n"); 1496c0b746e5SOllivier Robert #endif 1497c0b746e5SOllivier Robert if (!mon_enabled) { 1498c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1499c0b746e5SOllivier Robert return; 1500c0b746e5SOllivier Robert } 1501c0b746e5SOllivier Robert 1502c0b746e5SOllivier Robert im = (struct info_monitor *)prepare_pkt(srcadr, inter, inpkt, 1503c0b746e5SOllivier Robert sizeof(struct info_monitor)); 1504c0b746e5SOllivier Robert for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0; 1505c0b746e5SOllivier Robert md = md->mru_next) { 1506c0b746e5SOllivier Robert im->lasttime = htonl((u_int32)(current_time - md->lasttime)); 1507c0b746e5SOllivier Robert im->firsttime = htonl((u_int32)(current_time - md->firsttime)); 1508c0b746e5SOllivier Robert if (md->lastdrop) 1509c0b746e5SOllivier Robert im->lastdrop = htonl((u_int32)(current_time - md->lastdrop)); 1510c0b746e5SOllivier Robert else 1511c0b746e5SOllivier Robert im->lastdrop = 0; 1512c0b746e5SOllivier Robert im->count = htonl((u_int32)(md->count)); 1513c0b746e5SOllivier Robert im->addr = md->rmtadr; 1514c0b746e5SOllivier Robert im->port = md->rmtport; 1515c0b746e5SOllivier Robert im->mode = md->mode; 1516c0b746e5SOllivier Robert im->version = md->version; 1517c0b746e5SOllivier Robert im = (struct info_monitor *)more_pkt(); 1518c0b746e5SOllivier Robert } 1519c0b746e5SOllivier Robert flush_pkt(); 1520c0b746e5SOllivier Robert } 1521c0b746e5SOllivier Robert 1522c0b746e5SOllivier Robert /* 1523c0b746e5SOllivier Robert * mon_getlist - return monitor data 1524c0b746e5SOllivier Robert */ 1525c0b746e5SOllivier Robert static void 1526c0b746e5SOllivier Robert mon_getlist_1( 1527c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1528c0b746e5SOllivier Robert struct interface *inter, 1529c0b746e5SOllivier Robert struct req_pkt *inpkt 1530c0b746e5SOllivier Robert ) 1531c0b746e5SOllivier Robert { 1532c0b746e5SOllivier Robert register struct info_monitor_1 *im; 1533c0b746e5SOllivier Robert register struct mon_data *md; 1534c0b746e5SOllivier Robert extern struct mon_data mon_mru_list; 1535c0b746e5SOllivier Robert extern int mon_enabled; 1536c0b746e5SOllivier Robert 1537c0b746e5SOllivier Robert #ifdef DEBUG 1538c0b746e5SOllivier Robert if (debug > 2) 1539c0b746e5SOllivier Robert printf("wants monitor 1 list\n"); 1540c0b746e5SOllivier Robert #endif 1541c0b746e5SOllivier Robert if (!mon_enabled) { 1542c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1543c0b746e5SOllivier Robert return; 1544c0b746e5SOllivier Robert } 1545c0b746e5SOllivier Robert 1546c0b746e5SOllivier Robert im = (struct info_monitor_1 *)prepare_pkt(srcadr, inter, inpkt, 1547c0b746e5SOllivier Robert sizeof(struct info_monitor_1)); 1548c0b746e5SOllivier Robert for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0; 1549c0b746e5SOllivier Robert md = md->mru_next) { 1550c0b746e5SOllivier Robert im->lasttime = htonl((u_int32)(current_time - md->lasttime)); 1551c0b746e5SOllivier Robert im->firsttime = htonl((u_int32)(current_time - md->firsttime)); 1552c0b746e5SOllivier Robert if (md->lastdrop) 1553c0b746e5SOllivier Robert im->lastdrop = htonl((u_int32)(current_time - md->lastdrop)); 1554c0b746e5SOllivier Robert else 1555c0b746e5SOllivier Robert im->lastdrop = 0; 1556c0b746e5SOllivier Robert im->count = htonl((u_int32)md->count); 1557c0b746e5SOllivier Robert im->addr = md->rmtadr; 1558c0b746e5SOllivier Robert im->daddr = 1559c0b746e5SOllivier Robert (md->cast_flags == MDF_BCAST) 1560c0b746e5SOllivier Robert ? md->interface->bcast.sin_addr.s_addr 1561c0b746e5SOllivier Robert : (md->cast_flags 1562c0b746e5SOllivier Robert ? (md->interface->sin.sin_addr.s_addr 1563c0b746e5SOllivier Robert ? md->interface->sin.sin_addr.s_addr 1564c0b746e5SOllivier Robert : md->interface->bcast.sin_addr.s_addr 1565c0b746e5SOllivier Robert ) 1566c0b746e5SOllivier Robert : 4); 1567c0b746e5SOllivier Robert im->flags = md->cast_flags; 1568c0b746e5SOllivier Robert im->port = md->rmtport; 1569c0b746e5SOllivier Robert im->mode = md->mode; 1570c0b746e5SOllivier Robert im->version = md->version; 1571c0b746e5SOllivier Robert im = (struct info_monitor_1 *)more_pkt(); 1572c0b746e5SOllivier Robert } 1573c0b746e5SOllivier Robert flush_pkt(); 1574c0b746e5SOllivier Robert } 1575c0b746e5SOllivier Robert 1576c0b746e5SOllivier Robert /* 1577c0b746e5SOllivier Robert * Module entry points and the flags they correspond with 1578c0b746e5SOllivier Robert */ 1579c0b746e5SOllivier Robert struct reset_entry { 1580c0b746e5SOllivier Robert int flag; /* flag this corresponds to */ 1581c0b746e5SOllivier Robert void (*handler) P((void)); /* routine to handle request */ 1582c0b746e5SOllivier Robert }; 1583c0b746e5SOllivier Robert 1584c0b746e5SOllivier Robert struct reset_entry reset_entries[] = { 1585c0b746e5SOllivier Robert { RESET_FLAG_ALLPEERS, peer_all_reset }, 1586c0b746e5SOllivier Robert { RESET_FLAG_IO, io_clr_stats }, 1587c0b746e5SOllivier Robert { RESET_FLAG_SYS, proto_clr_stats }, 1588c0b746e5SOllivier Robert { RESET_FLAG_MEM, peer_clr_stats }, 1589c0b746e5SOllivier Robert { RESET_FLAG_TIMER, timer_clr_stats }, 1590c0b746e5SOllivier Robert { RESET_FLAG_AUTH, reset_auth_stats }, 1591c0b746e5SOllivier Robert { RESET_FLAG_CTL, ctl_clr_stats }, 1592c0b746e5SOllivier Robert { 0, 0 } 1593c0b746e5SOllivier Robert }; 1594c0b746e5SOllivier Robert 1595c0b746e5SOllivier Robert /* 1596c0b746e5SOllivier Robert * reset_stats - reset statistic counters here and there 1597c0b746e5SOllivier Robert */ 1598c0b746e5SOllivier Robert static void 1599c0b746e5SOllivier Robert reset_stats( 1600c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1601c0b746e5SOllivier Robert struct interface *inter, 1602c0b746e5SOllivier Robert struct req_pkt *inpkt 1603c0b746e5SOllivier Robert ) 1604c0b746e5SOllivier Robert { 1605c0b746e5SOllivier Robert u_long flags; 1606c0b746e5SOllivier Robert struct reset_entry *rent; 1607c0b746e5SOllivier Robert 1608c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 1609c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1610c0b746e5SOllivier Robert return; 1611c0b746e5SOllivier Robert } 1612c0b746e5SOllivier Robert 1613c0b746e5SOllivier Robert flags = ((struct reset_flags *)inpkt->data)->flags; 1614c0b746e5SOllivier Robert 1615c0b746e5SOllivier Robert if (flags & ~RESET_ALLFLAGS) { 1616c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1617c0b746e5SOllivier Robert return; 1618c0b746e5SOllivier Robert } 1619c0b746e5SOllivier Robert 1620c0b746e5SOllivier Robert for (rent = reset_entries; rent->flag != 0; rent++) { 1621c0b746e5SOllivier Robert if (flags & rent->flag) 1622c0b746e5SOllivier Robert (rent->handler)(); 1623c0b746e5SOllivier Robert } 1624c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1625c0b746e5SOllivier Robert } 1626c0b746e5SOllivier Robert 1627c0b746e5SOllivier Robert 1628c0b746e5SOllivier Robert /* 1629c0b746e5SOllivier Robert * reset_peer - clear a peer's statistics 1630c0b746e5SOllivier Robert */ 1631c0b746e5SOllivier Robert static void 1632c0b746e5SOllivier Robert reset_peer( 1633c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1634c0b746e5SOllivier Robert struct interface *inter, 1635c0b746e5SOllivier Robert struct req_pkt *inpkt 1636c0b746e5SOllivier Robert ) 1637c0b746e5SOllivier Robert { 1638c0b746e5SOllivier Robert register struct conf_unpeer *cp; 1639c0b746e5SOllivier Robert register int items; 1640c0b746e5SOllivier Robert register struct peer *peer; 1641c0b746e5SOllivier Robert struct sockaddr_in peeraddr; 1642c0b746e5SOllivier Robert int bad; 1643c0b746e5SOllivier Robert 1644c0b746e5SOllivier Robert /* 1645c0b746e5SOllivier Robert * We check first to see that every peer exists. If not, 1646c0b746e5SOllivier Robert * we return an error. 1647c0b746e5SOllivier Robert */ 1648c0b746e5SOllivier Robert peeraddr.sin_family = AF_INET; 1649c0b746e5SOllivier Robert peeraddr.sin_port = htons(NTP_PORT); 1650c0b746e5SOllivier Robert 1651c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1652c0b746e5SOllivier Robert cp = (struct conf_unpeer *)inpkt->data; 1653c0b746e5SOllivier Robert 1654c0b746e5SOllivier Robert bad = 0; 1655c0b746e5SOllivier Robert while (items-- > 0 && !bad) { 1656c0b746e5SOllivier Robert peeraddr.sin_addr.s_addr = cp->peeraddr; 1657c0b746e5SOllivier Robert peer = findexistingpeer(&peeraddr, (struct peer *)0, -1); 1658c0b746e5SOllivier Robert if (peer == (struct peer *)0) 1659c0b746e5SOllivier Robert bad++; 1660c0b746e5SOllivier Robert cp++; 1661c0b746e5SOllivier Robert } 1662c0b746e5SOllivier Robert 1663c0b746e5SOllivier Robert if (bad) { 1664c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1665c0b746e5SOllivier Robert return; 1666c0b746e5SOllivier Robert } 1667c0b746e5SOllivier Robert 1668c0b746e5SOllivier Robert /* 1669c0b746e5SOllivier Robert * Now do it in earnest. 1670c0b746e5SOllivier Robert */ 1671c0b746e5SOllivier Robert 1672c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1673c0b746e5SOllivier Robert cp = (struct conf_unpeer *)inpkt->data; 1674c0b746e5SOllivier Robert while (items-- > 0) { 1675c0b746e5SOllivier Robert peeraddr.sin_addr.s_addr = cp->peeraddr; 1676c0b746e5SOllivier Robert peer = findexistingpeer(&peeraddr, (struct peer *)0, -1); 1677c0b746e5SOllivier Robert while (peer != 0) { 1678c0b746e5SOllivier Robert peer_reset(peer); 1679c0b746e5SOllivier Robert peer = findexistingpeer(&peeraddr, (struct peer *)peer, -1); 1680c0b746e5SOllivier Robert } 1681c0b746e5SOllivier Robert cp++; 1682c0b746e5SOllivier Robert } 1683c0b746e5SOllivier Robert 1684c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1685c0b746e5SOllivier Robert } 1686c0b746e5SOllivier Robert 1687c0b746e5SOllivier Robert 1688c0b746e5SOllivier Robert /* 1689c0b746e5SOllivier Robert * do_key_reread - reread the encryption key file 1690c0b746e5SOllivier Robert */ 1691c0b746e5SOllivier Robert static void 1692c0b746e5SOllivier Robert do_key_reread( 1693c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1694c0b746e5SOllivier Robert struct interface *inter, 1695c0b746e5SOllivier Robert struct req_pkt *inpkt 1696c0b746e5SOllivier Robert ) 1697c0b746e5SOllivier Robert { 1698c0b746e5SOllivier Robert rereadkeys(); 1699c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1700c0b746e5SOllivier Robert } 1701c0b746e5SOllivier Robert 1702c0b746e5SOllivier Robert 1703c0b746e5SOllivier Robert /* 1704c0b746e5SOllivier Robert * trust_key - make one or more keys trusted 1705c0b746e5SOllivier Robert */ 1706c0b746e5SOllivier Robert static void 1707c0b746e5SOllivier Robert trust_key( 1708c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1709c0b746e5SOllivier Robert struct interface *inter, 1710c0b746e5SOllivier Robert struct req_pkt *inpkt 1711c0b746e5SOllivier Robert ) 1712c0b746e5SOllivier Robert { 1713c0b746e5SOllivier Robert do_trustkey(srcadr, inter, inpkt, 1); 1714c0b746e5SOllivier Robert } 1715c0b746e5SOllivier Robert 1716c0b746e5SOllivier Robert 1717c0b746e5SOllivier Robert /* 1718c0b746e5SOllivier Robert * untrust_key - make one or more keys untrusted 1719c0b746e5SOllivier Robert */ 1720c0b746e5SOllivier Robert static void 1721c0b746e5SOllivier Robert untrust_key( 1722c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1723c0b746e5SOllivier Robert struct interface *inter, 1724c0b746e5SOllivier Robert struct req_pkt *inpkt 1725c0b746e5SOllivier Robert ) 1726c0b746e5SOllivier Robert { 1727c0b746e5SOllivier Robert do_trustkey(srcadr, inter, inpkt, 0); 1728c0b746e5SOllivier Robert } 1729c0b746e5SOllivier Robert 1730c0b746e5SOllivier Robert 1731c0b746e5SOllivier Robert /* 1732c0b746e5SOllivier Robert * do_trustkey - make keys either trustable or untrustable 1733c0b746e5SOllivier Robert */ 1734c0b746e5SOllivier Robert static void 1735c0b746e5SOllivier Robert do_trustkey( 1736c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1737c0b746e5SOllivier Robert struct interface *inter, 1738c0b746e5SOllivier Robert struct req_pkt *inpkt, 1739c0b746e5SOllivier Robert int trust 1740c0b746e5SOllivier Robert ) 1741c0b746e5SOllivier Robert { 1742c0b746e5SOllivier Robert register u_long *kp; 1743c0b746e5SOllivier Robert register int items; 1744c0b746e5SOllivier Robert 1745c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1746c0b746e5SOllivier Robert kp = (u_long *)inpkt->data; 1747c0b746e5SOllivier Robert while (items-- > 0) { 1748c0b746e5SOllivier Robert authtrust(*kp, trust); 1749c0b746e5SOllivier Robert kp++; 1750c0b746e5SOllivier Robert } 1751c0b746e5SOllivier Robert 1752c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1753c0b746e5SOllivier Robert } 1754c0b746e5SOllivier Robert 1755c0b746e5SOllivier Robert 1756c0b746e5SOllivier Robert /* 1757c0b746e5SOllivier Robert * get_auth_info - return some stats concerning the authentication module 1758c0b746e5SOllivier Robert */ 1759c0b746e5SOllivier Robert static void 1760c0b746e5SOllivier Robert get_auth_info( 1761c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1762c0b746e5SOllivier Robert struct interface *inter, 1763c0b746e5SOllivier Robert struct req_pkt *inpkt 1764c0b746e5SOllivier Robert ) 1765c0b746e5SOllivier Robert { 1766c0b746e5SOllivier Robert register struct info_auth *ia; 1767c0b746e5SOllivier Robert 1768c0b746e5SOllivier Robert /* 1769c0b746e5SOllivier Robert * Importations from the authentication module 1770c0b746e5SOllivier Robert */ 1771c0b746e5SOllivier Robert extern u_long authnumkeys; 1772c0b746e5SOllivier Robert extern int authnumfreekeys; 1773c0b746e5SOllivier Robert extern u_long authkeylookups; 1774c0b746e5SOllivier Robert extern u_long authkeynotfound; 1775c0b746e5SOllivier Robert extern u_long authencryptions; 1776c0b746e5SOllivier Robert extern u_long authdecryptions; 1777c0b746e5SOllivier Robert extern u_long authkeyuncached; 1778c0b746e5SOllivier Robert extern u_long authkeyexpired; 1779c0b746e5SOllivier Robert 1780c0b746e5SOllivier Robert ia = (struct info_auth *)prepare_pkt(srcadr, inter, inpkt, 1781c0b746e5SOllivier Robert sizeof(struct info_auth)); 1782c0b746e5SOllivier Robert 1783c0b746e5SOllivier Robert ia->numkeys = htonl((u_int32)authnumkeys); 1784c0b746e5SOllivier Robert ia->numfreekeys = htonl((u_int32)authnumfreekeys); 1785c0b746e5SOllivier Robert ia->keylookups = htonl((u_int32)authkeylookups); 1786c0b746e5SOllivier Robert ia->keynotfound = htonl((u_int32)authkeynotfound); 1787c0b746e5SOllivier Robert ia->encryptions = htonl((u_int32)authencryptions); 1788c0b746e5SOllivier Robert ia->decryptions = htonl((u_int32)authdecryptions); 1789c0b746e5SOllivier Robert ia->keyuncached = htonl((u_int32)authkeyuncached); 1790c0b746e5SOllivier Robert ia->expired = htonl((u_int32)authkeyexpired); 1791c0b746e5SOllivier Robert ia->timereset = htonl((u_int32)(current_time - auth_timereset)); 1792c0b746e5SOllivier Robert 1793c0b746e5SOllivier Robert (void) more_pkt(); 1794c0b746e5SOllivier Robert flush_pkt(); 1795c0b746e5SOllivier Robert } 1796c0b746e5SOllivier Robert 1797c0b746e5SOllivier Robert 1798c0b746e5SOllivier Robert 1799c0b746e5SOllivier Robert /* 1800c0b746e5SOllivier Robert * reset_auth_stats - reset the authentication stat counters. Done here 1801c0b746e5SOllivier Robert * to keep ntp-isms out of the authentication module 1802c0b746e5SOllivier Robert */ 1803c0b746e5SOllivier Robert static void 1804c0b746e5SOllivier Robert reset_auth_stats(void) 1805c0b746e5SOllivier Robert { 1806c0b746e5SOllivier Robert /* 1807c0b746e5SOllivier Robert * Importations from the authentication module 1808c0b746e5SOllivier Robert */ 1809c0b746e5SOllivier Robert extern u_long authkeylookups; 1810c0b746e5SOllivier Robert extern u_long authkeynotfound; 1811c0b746e5SOllivier Robert extern u_long authencryptions; 1812c0b746e5SOllivier Robert extern u_long authdecryptions; 1813c0b746e5SOllivier Robert extern u_long authkeyuncached; 1814c0b746e5SOllivier Robert 1815c0b746e5SOllivier Robert authkeylookups = 0; 1816c0b746e5SOllivier Robert authkeynotfound = 0; 1817c0b746e5SOllivier Robert authencryptions = 0; 1818c0b746e5SOllivier Robert authdecryptions = 0; 1819c0b746e5SOllivier Robert authkeyuncached = 0; 1820c0b746e5SOllivier Robert auth_timereset = current_time; 1821c0b746e5SOllivier Robert } 1822c0b746e5SOllivier Robert 1823c0b746e5SOllivier Robert 1824c0b746e5SOllivier Robert /* 1825c0b746e5SOllivier Robert * req_get_traps - return information about current trap holders 1826c0b746e5SOllivier Robert */ 1827c0b746e5SOllivier Robert static void 1828c0b746e5SOllivier Robert req_get_traps( 1829c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1830c0b746e5SOllivier Robert struct interface *inter, 1831c0b746e5SOllivier Robert struct req_pkt *inpkt 1832c0b746e5SOllivier Robert ) 1833c0b746e5SOllivier Robert { 1834c0b746e5SOllivier Robert register struct info_trap *it; 1835c0b746e5SOllivier Robert register struct ctl_trap *tr; 1836c0b746e5SOllivier Robert register int i; 1837c0b746e5SOllivier Robert 1838c0b746e5SOllivier Robert /* 1839c0b746e5SOllivier Robert * Imported from the control module 1840c0b746e5SOllivier Robert */ 1841c0b746e5SOllivier Robert extern struct ctl_trap ctl_trap[]; 1842c0b746e5SOllivier Robert extern int num_ctl_traps; 1843c0b746e5SOllivier Robert 1844c0b746e5SOllivier Robert if (num_ctl_traps == 0) { 1845c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1846c0b746e5SOllivier Robert return; 1847c0b746e5SOllivier Robert } 1848c0b746e5SOllivier Robert 1849c0b746e5SOllivier Robert it = (struct info_trap *)prepare_pkt(srcadr, inter, inpkt, 1850c0b746e5SOllivier Robert sizeof(struct info_trap)); 1851c0b746e5SOllivier Robert 1852c0b746e5SOllivier Robert for (i = 0, tr = ctl_trap; i < CTL_MAXTRAPS; i++, tr++) { 1853c0b746e5SOllivier Robert if (tr->tr_flags & TRAP_INUSE) { 1854c0b746e5SOllivier Robert if (tr->tr_localaddr == any_interface) 1855c0b746e5SOllivier Robert it->local_address = 0; 1856c0b746e5SOllivier Robert else 1857c0b746e5SOllivier Robert it->local_address 1858c0b746e5SOllivier Robert = NSRCADR(&tr->tr_localaddr->sin); 1859c0b746e5SOllivier Robert it->trap_address = NSRCADR(&tr->tr_addr); 1860c0b746e5SOllivier Robert it->trap_port = NSRCPORT(&tr->tr_addr); 1861c0b746e5SOllivier Robert it->sequence = htons(tr->tr_sequence); 1862c0b746e5SOllivier Robert it->settime = htonl((u_int32)(current_time - tr->tr_settime)); 1863c0b746e5SOllivier Robert it->origtime = htonl((u_int32)(current_time - tr->tr_origtime)); 1864c0b746e5SOllivier Robert it->resets = htonl((u_int32)tr->tr_resets); 1865c0b746e5SOllivier Robert it->flags = htonl((u_int32)tr->tr_flags); 1866c0b746e5SOllivier Robert it = (struct info_trap *)more_pkt(); 1867c0b746e5SOllivier Robert } 1868c0b746e5SOllivier Robert } 1869c0b746e5SOllivier Robert flush_pkt(); 1870c0b746e5SOllivier Robert } 1871c0b746e5SOllivier Robert 1872c0b746e5SOllivier Robert 1873c0b746e5SOllivier Robert /* 1874c0b746e5SOllivier Robert * req_set_trap - configure a trap 1875c0b746e5SOllivier Robert */ 1876c0b746e5SOllivier Robert static void 1877c0b746e5SOllivier Robert req_set_trap( 1878c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1879c0b746e5SOllivier Robert struct interface *inter, 1880c0b746e5SOllivier Robert struct req_pkt *inpkt 1881c0b746e5SOllivier Robert ) 1882c0b746e5SOllivier Robert { 1883c0b746e5SOllivier Robert do_setclr_trap(srcadr, inter, inpkt, 1); 1884c0b746e5SOllivier Robert } 1885c0b746e5SOllivier Robert 1886c0b746e5SOllivier Robert 1887c0b746e5SOllivier Robert 1888c0b746e5SOllivier Robert /* 1889c0b746e5SOllivier Robert * req_clr_trap - unconfigure a trap 1890c0b746e5SOllivier Robert */ 1891c0b746e5SOllivier Robert static void 1892c0b746e5SOllivier Robert req_clr_trap( 1893c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1894c0b746e5SOllivier Robert struct interface *inter, 1895c0b746e5SOllivier Robert struct req_pkt *inpkt 1896c0b746e5SOllivier Robert ) 1897c0b746e5SOllivier Robert { 1898c0b746e5SOllivier Robert do_setclr_trap(srcadr, inter, inpkt, 0); 1899c0b746e5SOllivier Robert } 1900c0b746e5SOllivier Robert 1901c0b746e5SOllivier Robert 1902c0b746e5SOllivier Robert 1903c0b746e5SOllivier Robert /* 1904c0b746e5SOllivier Robert * do_setclr_trap - do the grunge work of (un)configuring a trap 1905c0b746e5SOllivier Robert */ 1906c0b746e5SOllivier Robert static void 1907c0b746e5SOllivier Robert do_setclr_trap( 1908c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1909c0b746e5SOllivier Robert struct interface *inter, 1910c0b746e5SOllivier Robert struct req_pkt *inpkt, 1911c0b746e5SOllivier Robert int set 1912c0b746e5SOllivier Robert ) 1913c0b746e5SOllivier Robert { 1914c0b746e5SOllivier Robert register struct conf_trap *ct; 1915c0b746e5SOllivier Robert register struct interface *linter; 1916c0b746e5SOllivier Robert int res; 1917c0b746e5SOllivier Robert struct sockaddr_in laddr; 1918c0b746e5SOllivier Robert 1919c0b746e5SOllivier Robert /* 1920c0b746e5SOllivier Robert * Prepare sockaddr_in structure 1921c0b746e5SOllivier Robert */ 1922c0b746e5SOllivier Robert memset((char *)&laddr, 0, sizeof laddr); 1923c0b746e5SOllivier Robert laddr.sin_family = AF_INET; 1924c0b746e5SOllivier Robert laddr.sin_port = ntohs(NTP_PORT); 1925c0b746e5SOllivier Robert 1926c0b746e5SOllivier Robert /* 1927c0b746e5SOllivier Robert * Restrict ourselves to one item only. This eliminates 1928c0b746e5SOllivier Robert * the error reporting problem. 1929c0b746e5SOllivier Robert */ 1930c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 1931c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1932c0b746e5SOllivier Robert return; 1933c0b746e5SOllivier Robert } 1934c0b746e5SOllivier Robert ct = (struct conf_trap *)inpkt->data; 1935c0b746e5SOllivier Robert 1936c0b746e5SOllivier Robert /* 1937c0b746e5SOllivier Robert * Look for the local interface. If none, use the default. 1938c0b746e5SOllivier Robert */ 1939c0b746e5SOllivier Robert if (ct->local_address == 0) { 1940c0b746e5SOllivier Robert linter = any_interface; 1941c0b746e5SOllivier Robert } else { 1942c0b746e5SOllivier Robert laddr.sin_addr.s_addr = ct->local_address; 1943c0b746e5SOllivier Robert linter = findinterface(&laddr); 1944c0b746e5SOllivier Robert if (linter == NULL) { 1945c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1946c0b746e5SOllivier Robert return; 1947c0b746e5SOllivier Robert } 1948c0b746e5SOllivier Robert } 1949c0b746e5SOllivier Robert 1950c0b746e5SOllivier Robert laddr.sin_addr.s_addr = ct->trap_address; 1951c0b746e5SOllivier Robert if (ct->trap_port != 0) 1952c0b746e5SOllivier Robert laddr.sin_port = ct->trap_port; 1953c0b746e5SOllivier Robert else 1954c0b746e5SOllivier Robert laddr.sin_port = htons(TRAPPORT); 1955c0b746e5SOllivier Robert 1956c0b746e5SOllivier Robert if (set) { 1957c0b746e5SOllivier Robert res = ctlsettrap(&laddr, linter, 0, 1958c0b746e5SOllivier Robert INFO_VERSION(inpkt->rm_vn_mode)); 1959c0b746e5SOllivier Robert } else { 1960c0b746e5SOllivier Robert res = ctlclrtrap(&laddr, linter, 0); 1961c0b746e5SOllivier Robert } 1962c0b746e5SOllivier Robert 1963c0b746e5SOllivier Robert if (!res) { 1964c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1965c0b746e5SOllivier Robert } else { 1966c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1967c0b746e5SOllivier Robert } 1968c0b746e5SOllivier Robert return; 1969c0b746e5SOllivier Robert } 1970c0b746e5SOllivier Robert 1971c0b746e5SOllivier Robert 1972c0b746e5SOllivier Robert 1973c0b746e5SOllivier Robert /* 1974c0b746e5SOllivier Robert * set_request_keyid - set the keyid used to authenticate requests 1975c0b746e5SOllivier Robert */ 1976c0b746e5SOllivier Robert static void 1977c0b746e5SOllivier Robert set_request_keyid( 1978c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 1979c0b746e5SOllivier Robert struct interface *inter, 1980c0b746e5SOllivier Robert struct req_pkt *inpkt 1981c0b746e5SOllivier Robert ) 1982c0b746e5SOllivier Robert { 1983c0b746e5SOllivier Robert u_long keyid; 1984c0b746e5SOllivier Robert 1985c0b746e5SOllivier Robert /* 1986c0b746e5SOllivier Robert * Restrict ourselves to one item only. 1987c0b746e5SOllivier Robert */ 1988c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 1989c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1990c0b746e5SOllivier Robert return; 1991c0b746e5SOllivier Robert } 1992c0b746e5SOllivier Robert 1993c0b746e5SOllivier Robert keyid = ntohl(*((u_int32 *)(inpkt->data))); 1994c0b746e5SOllivier Robert info_auth_keyid = keyid; 1995c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1996c0b746e5SOllivier Robert } 1997c0b746e5SOllivier Robert 1998c0b746e5SOllivier Robert 1999c0b746e5SOllivier Robert 2000c0b746e5SOllivier Robert /* 2001c0b746e5SOllivier Robert * set_control_keyid - set the keyid used to authenticate requests 2002c0b746e5SOllivier Robert */ 2003c0b746e5SOllivier Robert static void 2004c0b746e5SOllivier Robert set_control_keyid( 2005c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 2006c0b746e5SOllivier Robert struct interface *inter, 2007c0b746e5SOllivier Robert struct req_pkt *inpkt 2008c0b746e5SOllivier Robert ) 2009c0b746e5SOllivier Robert { 2010c0b746e5SOllivier Robert u_long keyid; 2011c0b746e5SOllivier Robert extern u_long ctl_auth_keyid; 2012c0b746e5SOllivier Robert 2013c0b746e5SOllivier Robert /* 2014c0b746e5SOllivier Robert * Restrict ourselves to one item only. 2015c0b746e5SOllivier Robert */ 2016c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2017c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2018c0b746e5SOllivier Robert return; 2019c0b746e5SOllivier Robert } 2020c0b746e5SOllivier Robert 2021c0b746e5SOllivier Robert keyid = ntohl(*((u_int32 *)(inpkt->data))); 2022c0b746e5SOllivier Robert ctl_auth_keyid = keyid; 2023c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2024c0b746e5SOllivier Robert } 2025c0b746e5SOllivier Robert 2026c0b746e5SOllivier Robert 2027c0b746e5SOllivier Robert 2028c0b746e5SOllivier Robert /* 2029c0b746e5SOllivier Robert * get_ctl_stats - return some stats concerning the control message module 2030c0b746e5SOllivier Robert */ 2031c0b746e5SOllivier Robert static void 2032c0b746e5SOllivier Robert get_ctl_stats( 2033c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 2034c0b746e5SOllivier Robert struct interface *inter, 2035c0b746e5SOllivier Robert struct req_pkt *inpkt 2036c0b746e5SOllivier Robert ) 2037c0b746e5SOllivier Robert { 2038c0b746e5SOllivier Robert register struct info_control *ic; 2039c0b746e5SOllivier Robert 2040c0b746e5SOllivier Robert /* 2041c0b746e5SOllivier Robert * Importations from the control module 2042c0b746e5SOllivier Robert */ 2043c0b746e5SOllivier Robert extern u_long ctltimereset; 2044c0b746e5SOllivier Robert extern u_long numctlreq; 2045c0b746e5SOllivier Robert extern u_long numctlbadpkts; 2046c0b746e5SOllivier Robert extern u_long numctlresponses; 2047c0b746e5SOllivier Robert extern u_long numctlfrags; 2048c0b746e5SOllivier Robert extern u_long numctlerrors; 2049c0b746e5SOllivier Robert extern u_long numctltooshort; 2050c0b746e5SOllivier Robert extern u_long numctlinputresp; 2051c0b746e5SOllivier Robert extern u_long numctlinputfrag; 2052c0b746e5SOllivier Robert extern u_long numctlinputerr; 2053c0b746e5SOllivier Robert extern u_long numctlbadoffset; 2054c0b746e5SOllivier Robert extern u_long numctlbadversion; 2055c0b746e5SOllivier Robert extern u_long numctldatatooshort; 2056c0b746e5SOllivier Robert extern u_long numctlbadop; 2057c0b746e5SOllivier Robert extern u_long numasyncmsgs; 2058c0b746e5SOllivier Robert 2059c0b746e5SOllivier Robert ic = (struct info_control *)prepare_pkt(srcadr, inter, inpkt, 2060c0b746e5SOllivier Robert sizeof(struct info_control)); 2061c0b746e5SOllivier Robert 2062c0b746e5SOllivier Robert ic->ctltimereset = htonl((u_int32)(current_time - ctltimereset)); 2063c0b746e5SOllivier Robert ic->numctlreq = htonl((u_int32)numctlreq); 2064c0b746e5SOllivier Robert ic->numctlbadpkts = htonl((u_int32)numctlbadpkts); 2065c0b746e5SOllivier Robert ic->numctlresponses = htonl((u_int32)numctlresponses); 2066c0b746e5SOllivier Robert ic->numctlfrags = htonl((u_int32)numctlfrags); 2067c0b746e5SOllivier Robert ic->numctlerrors = htonl((u_int32)numctlerrors); 2068c0b746e5SOllivier Robert ic->numctltooshort = htonl((u_int32)numctltooshort); 2069c0b746e5SOllivier Robert ic->numctlinputresp = htonl((u_int32)numctlinputresp); 2070c0b746e5SOllivier Robert ic->numctlinputfrag = htonl((u_int32)numctlinputfrag); 2071c0b746e5SOllivier Robert ic->numctlinputerr = htonl((u_int32)numctlinputerr); 2072c0b746e5SOllivier Robert ic->numctlbadoffset = htonl((u_int32)numctlbadoffset); 2073c0b746e5SOllivier Robert ic->numctlbadversion = htonl((u_int32)numctlbadversion); 2074c0b746e5SOllivier Robert ic->numctldatatooshort = htonl((u_int32)numctldatatooshort); 2075c0b746e5SOllivier Robert ic->numctlbadop = htonl((u_int32)numctlbadop); 2076c0b746e5SOllivier Robert ic->numasyncmsgs = htonl((u_int32)numasyncmsgs); 2077c0b746e5SOllivier Robert 2078c0b746e5SOllivier Robert (void) more_pkt(); 2079c0b746e5SOllivier Robert flush_pkt(); 2080c0b746e5SOllivier Robert } 2081c0b746e5SOllivier Robert 2082c0b746e5SOllivier Robert 2083c0b746e5SOllivier Robert #ifdef KERNEL_PLL 2084c0b746e5SOllivier Robert /* 2085c0b746e5SOllivier Robert * get_kernel_info - get kernel pll/pps information 2086c0b746e5SOllivier Robert */ 2087c0b746e5SOllivier Robert static void 2088c0b746e5SOllivier Robert get_kernel_info( 2089c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 2090c0b746e5SOllivier Robert struct interface *inter, 2091c0b746e5SOllivier Robert struct req_pkt *inpkt 2092c0b746e5SOllivier Robert ) 2093c0b746e5SOllivier Robert { 2094c0b746e5SOllivier Robert register struct info_kernel *ik; 2095c0b746e5SOllivier Robert struct timex ntx; 2096c0b746e5SOllivier Robert 2097c0b746e5SOllivier Robert if (!pll_control) { 2098c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2099c0b746e5SOllivier Robert return; 2100c0b746e5SOllivier Robert } 2101c0b746e5SOllivier Robert 2102c0b746e5SOllivier Robert memset((char *)&ntx, 0, sizeof(ntx)); 2103c0b746e5SOllivier Robert if (ntp_adjtime(&ntx) < 0) 2104c0b746e5SOllivier Robert msyslog(LOG_ERR, "get_kernel_info: ntp_adjtime() failed: %m"); 2105c0b746e5SOllivier Robert ik = (struct info_kernel *)prepare_pkt(srcadr, inter, inpkt, 2106c0b746e5SOllivier Robert sizeof(struct info_kernel)); 2107c0b746e5SOllivier Robert 2108c0b746e5SOllivier Robert /* 2109c0b746e5SOllivier Robert * pll variables 2110c0b746e5SOllivier Robert */ 2111c0b746e5SOllivier Robert ik->offset = htonl((u_int32)ntx.offset); 2112c0b746e5SOllivier Robert ik->freq = htonl((u_int32)ntx.freq); 2113c0b746e5SOllivier Robert ik->maxerror = htonl((u_int32)ntx.maxerror); 2114c0b746e5SOllivier Robert ik->esterror = htonl((u_int32)ntx.esterror); 2115c0b746e5SOllivier Robert ik->status = htons(ntx.status); 2116c0b746e5SOllivier Robert ik->constant = htonl((u_int32)ntx.constant); 2117c0b746e5SOllivier Robert ik->precision = htonl((u_int32)ntx.precision); 2118c0b746e5SOllivier Robert ik->tolerance = htonl((u_int32)ntx.tolerance); 2119c0b746e5SOllivier Robert 2120c0b746e5SOllivier Robert /* 2121c0b746e5SOllivier Robert * pps variables 2122c0b746e5SOllivier Robert */ 2123c0b746e5SOllivier Robert ik->ppsfreq = htonl((u_int32)ntx.ppsfreq); 2124c0b746e5SOllivier Robert ik->jitter = htonl((u_int32)ntx.jitter); 2125c0b746e5SOllivier Robert ik->shift = htons(ntx.shift); 2126c0b746e5SOllivier Robert ik->stabil = htonl((u_int32)ntx.stabil); 2127c0b746e5SOllivier Robert ik->jitcnt = htonl((u_int32)ntx.jitcnt); 2128c0b746e5SOllivier Robert ik->calcnt = htonl((u_int32)ntx.calcnt); 2129c0b746e5SOllivier Robert ik->errcnt = htonl((u_int32)ntx.errcnt); 2130c0b746e5SOllivier Robert ik->stbcnt = htonl((u_int32)ntx.stbcnt); 2131c0b746e5SOllivier Robert 2132c0b746e5SOllivier Robert (void) more_pkt(); 2133c0b746e5SOllivier Robert flush_pkt(); 2134c0b746e5SOllivier Robert } 2135c0b746e5SOllivier Robert #endif /* KERNEL_PLL */ 2136c0b746e5SOllivier Robert 2137c0b746e5SOllivier Robert 2138c0b746e5SOllivier Robert #ifdef REFCLOCK 2139c0b746e5SOllivier Robert /* 2140c0b746e5SOllivier Robert * get_clock_info - get info about a clock 2141c0b746e5SOllivier Robert */ 2142c0b746e5SOllivier Robert static void 2143c0b746e5SOllivier Robert get_clock_info( 2144c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 2145c0b746e5SOllivier Robert struct interface *inter, 2146c0b746e5SOllivier Robert struct req_pkt *inpkt 2147c0b746e5SOllivier Robert ) 2148c0b746e5SOllivier Robert { 2149c0b746e5SOllivier Robert register struct info_clock *ic; 2150c0b746e5SOllivier Robert register u_int32 *clkaddr; 2151c0b746e5SOllivier Robert register int items; 2152c0b746e5SOllivier Robert struct refclockstat clock_stat; 2153c0b746e5SOllivier Robert struct sockaddr_in addr; 2154c0b746e5SOllivier Robert l_fp ltmp; 2155c0b746e5SOllivier Robert 2156c0b746e5SOllivier Robert memset((char *)&addr, 0, sizeof addr); 2157c0b746e5SOllivier Robert addr.sin_family = AF_INET; 2158c0b746e5SOllivier Robert addr.sin_port = htons(NTP_PORT); 2159c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2160c0b746e5SOllivier Robert clkaddr = (u_int32 *) inpkt->data; 2161c0b746e5SOllivier Robert 2162c0b746e5SOllivier Robert ic = (struct info_clock *)prepare_pkt(srcadr, inter, inpkt, 2163c0b746e5SOllivier Robert sizeof(struct info_clock)); 2164c0b746e5SOllivier Robert 2165c0b746e5SOllivier Robert while (items-- > 0) { 2166c0b746e5SOllivier Robert addr.sin_addr.s_addr = *clkaddr++; 2167c0b746e5SOllivier Robert if (!ISREFCLOCKADR(&addr) || 2168c0b746e5SOllivier Robert findexistingpeer(&addr, (struct peer *)0, -1) == 0) { 2169c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2170c0b746e5SOllivier Robert return; 2171c0b746e5SOllivier Robert } 2172c0b746e5SOllivier Robert 2173c0b746e5SOllivier Robert clock_stat.kv_list = (struct ctl_var *)0; 2174c0b746e5SOllivier Robert 2175c0b746e5SOllivier Robert refclock_control(&addr, (struct refclockstat *)0, &clock_stat); 2176c0b746e5SOllivier Robert 2177c0b746e5SOllivier Robert ic->clockadr = addr.sin_addr.s_addr; 2178c0b746e5SOllivier Robert ic->type = clock_stat.type; 2179c0b746e5SOllivier Robert ic->flags = clock_stat.flags; 2180c0b746e5SOllivier Robert ic->lastevent = clock_stat.lastevent; 2181c0b746e5SOllivier Robert ic->currentstatus = clock_stat.currentstatus; 2182c0b746e5SOllivier Robert ic->polls = htonl((u_int32)clock_stat.polls); 2183c0b746e5SOllivier Robert ic->noresponse = htonl((u_int32)clock_stat.noresponse); 2184c0b746e5SOllivier Robert ic->badformat = htonl((u_int32)clock_stat.badformat); 2185c0b746e5SOllivier Robert ic->baddata = htonl((u_int32)clock_stat.baddata); 2186c0b746e5SOllivier Robert ic->timestarted = htonl((u_int32)clock_stat.timereset); 2187c0b746e5SOllivier Robert DTOLFP(clock_stat.fudgetime1, <mp); 2188c0b746e5SOllivier Robert HTONL_FP(<mp, &ic->fudgetime1); 2189c0b746e5SOllivier Robert DTOLFP(clock_stat.fudgetime1, <mp); 2190c0b746e5SOllivier Robert HTONL_FP(<mp, &ic->fudgetime2); 2191c0b746e5SOllivier Robert ic->fudgeval1 = htonl((u_int32)clock_stat.fudgeval1); 2192c0b746e5SOllivier Robert ic->fudgeval2 = htonl((u_int32)clock_stat.fudgeval2); 2193c0b746e5SOllivier Robert 2194c0b746e5SOllivier Robert free_varlist(clock_stat.kv_list); 2195c0b746e5SOllivier Robert 2196c0b746e5SOllivier Robert ic = (struct info_clock *)more_pkt(); 2197c0b746e5SOllivier Robert } 2198c0b746e5SOllivier Robert flush_pkt(); 2199c0b746e5SOllivier Robert } 2200c0b746e5SOllivier Robert 2201c0b746e5SOllivier Robert 2202c0b746e5SOllivier Robert 2203c0b746e5SOllivier Robert /* 2204c0b746e5SOllivier Robert * set_clock_fudge - get a clock's fudge factors 2205c0b746e5SOllivier Robert */ 2206c0b746e5SOllivier Robert static void 2207c0b746e5SOllivier Robert set_clock_fudge( 2208c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 2209c0b746e5SOllivier Robert struct interface *inter, 2210c0b746e5SOllivier Robert struct req_pkt *inpkt 2211c0b746e5SOllivier Robert ) 2212c0b746e5SOllivier Robert { 2213c0b746e5SOllivier Robert register struct conf_fudge *cf; 2214c0b746e5SOllivier Robert register int items; 2215c0b746e5SOllivier Robert struct refclockstat clock_stat; 2216c0b746e5SOllivier Robert struct sockaddr_in addr; 2217c0b746e5SOllivier Robert l_fp ltmp; 2218c0b746e5SOllivier Robert 2219c0b746e5SOllivier Robert memset((char *)&addr, 0, sizeof addr); 2220c0b746e5SOllivier Robert memset((char *)&clock_stat, 0, sizeof clock_stat); 2221c0b746e5SOllivier Robert addr.sin_family = AF_INET; 2222c0b746e5SOllivier Robert addr.sin_port = htons(NTP_PORT); 2223c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2224c0b746e5SOllivier Robert cf = (struct conf_fudge *) inpkt->data; 2225c0b746e5SOllivier Robert 2226c0b746e5SOllivier Robert while (items-- > 0) { 2227c0b746e5SOllivier Robert addr.sin_addr.s_addr = cf->clockadr; 2228c0b746e5SOllivier Robert if (!ISREFCLOCKADR(&addr) || 2229c0b746e5SOllivier Robert findexistingpeer(&addr, (struct peer *)0, -1) == 0) { 2230c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2231c0b746e5SOllivier Robert return; 2232c0b746e5SOllivier Robert } 2233c0b746e5SOllivier Robert 2234c0b746e5SOllivier Robert switch(ntohl(cf->which)) { 2235c0b746e5SOllivier Robert case FUDGE_TIME1: 2236c0b746e5SOllivier Robert NTOHL_FP(&cf->fudgetime, <mp); 2237c0b746e5SOllivier Robert LFPTOD(<mp, clock_stat.fudgetime1); 2238c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVETIME1; 2239c0b746e5SOllivier Robert break; 2240c0b746e5SOllivier Robert case FUDGE_TIME2: 2241c0b746e5SOllivier Robert NTOHL_FP(&cf->fudgetime, <mp); 2242c0b746e5SOllivier Robert LFPTOD(<mp, clock_stat.fudgetime2); 2243c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVETIME2; 2244c0b746e5SOllivier Robert break; 2245c0b746e5SOllivier Robert case FUDGE_VAL1: 2246c0b746e5SOllivier Robert clock_stat.fudgeval1 = ntohl(cf->fudgeval_flags); 2247c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVEVAL1; 2248c0b746e5SOllivier Robert break; 2249c0b746e5SOllivier Robert case FUDGE_VAL2: 2250c0b746e5SOllivier Robert clock_stat.fudgeval2 = ntohl(cf->fudgeval_flags); 2251c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVEVAL2; 2252c0b746e5SOllivier Robert break; 2253c0b746e5SOllivier Robert case FUDGE_FLAGS: 2254c0b746e5SOllivier Robert clock_stat.flags = (u_char) ntohl(cf->fudgeval_flags) & 0xf; 2255c0b746e5SOllivier Robert clock_stat.haveflags = 2256c0b746e5SOllivier Robert (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4); 2257c0b746e5SOllivier Robert break; 2258c0b746e5SOllivier Robert default: 2259c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2260c0b746e5SOllivier Robert return; 2261c0b746e5SOllivier Robert } 2262c0b746e5SOllivier Robert 2263c0b746e5SOllivier Robert refclock_control(&addr, &clock_stat, (struct refclockstat *)0); 2264c0b746e5SOllivier Robert } 2265c0b746e5SOllivier Robert 2266c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2267c0b746e5SOllivier Robert } 2268c0b746e5SOllivier Robert #endif 2269c0b746e5SOllivier Robert 2270c0b746e5SOllivier Robert #ifdef REFCLOCK 2271c0b746e5SOllivier Robert /* 2272c0b746e5SOllivier Robert * get_clkbug_info - get debugging info about a clock 2273c0b746e5SOllivier Robert */ 2274c0b746e5SOllivier Robert static void 2275c0b746e5SOllivier Robert get_clkbug_info( 2276c0b746e5SOllivier Robert struct sockaddr_in *srcadr, 2277c0b746e5SOllivier Robert struct interface *inter, 2278c0b746e5SOllivier Robert struct req_pkt *inpkt 2279c0b746e5SOllivier Robert ) 2280c0b746e5SOllivier Robert { 2281c0b746e5SOllivier Robert register int i; 2282c0b746e5SOllivier Robert register struct info_clkbug *ic; 2283c0b746e5SOllivier Robert register u_int32 *clkaddr; 2284c0b746e5SOllivier Robert register int items; 2285c0b746e5SOllivier Robert struct refclockbug bug; 2286c0b746e5SOllivier Robert struct sockaddr_in addr; 2287c0b746e5SOllivier Robert 2288c0b746e5SOllivier Robert memset((char *)&addr, 0, sizeof addr); 2289c0b746e5SOllivier Robert addr.sin_family = AF_INET; 2290c0b746e5SOllivier Robert addr.sin_port = htons(NTP_PORT); 2291c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2292c0b746e5SOllivier Robert clkaddr = (u_int32 *) inpkt->data; 2293c0b746e5SOllivier Robert 2294c0b746e5SOllivier Robert ic = (struct info_clkbug *)prepare_pkt(srcadr, inter, inpkt, 2295c0b746e5SOllivier Robert sizeof(struct info_clkbug)); 2296c0b746e5SOllivier Robert 2297c0b746e5SOllivier Robert while (items-- > 0) { 2298c0b746e5SOllivier Robert addr.sin_addr.s_addr = *clkaddr++; 2299c0b746e5SOllivier Robert if (!ISREFCLOCKADR(&addr) || 2300c0b746e5SOllivier Robert findexistingpeer(&addr, (struct peer *)0, -1) == 0) { 2301c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2302c0b746e5SOllivier Robert return; 2303c0b746e5SOllivier Robert } 2304c0b746e5SOllivier Robert 2305c0b746e5SOllivier Robert memset((char *)&bug, 0, sizeof bug); 2306c0b746e5SOllivier Robert refclock_buginfo(&addr, &bug); 2307c0b746e5SOllivier Robert if (bug.nvalues == 0 && bug.ntimes == 0) { 2308c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2309c0b746e5SOllivier Robert return; 2310c0b746e5SOllivier Robert } 2311c0b746e5SOllivier Robert 2312c0b746e5SOllivier Robert ic->clockadr = addr.sin_addr.s_addr; 2313c0b746e5SOllivier Robert i = bug.nvalues; 2314c0b746e5SOllivier Robert if (i > NUMCBUGVALUES) 2315c0b746e5SOllivier Robert i = NUMCBUGVALUES; 2316c0b746e5SOllivier Robert ic->nvalues = (u_char)i; 2317c0b746e5SOllivier Robert ic->svalues = htons((u_short) (bug.svalues & ((1<<i)-1))); 2318c0b746e5SOllivier Robert while (--i >= 0) 2319c0b746e5SOllivier Robert ic->values[i] = htonl(bug.values[i]); 2320c0b746e5SOllivier Robert 2321c0b746e5SOllivier Robert i = bug.ntimes; 2322c0b746e5SOllivier Robert if (i > NUMCBUGTIMES) 2323c0b746e5SOllivier Robert i = NUMCBUGTIMES; 2324c0b746e5SOllivier Robert ic->ntimes = (u_char)i; 2325c0b746e5SOllivier Robert ic->stimes = htonl(bug.stimes); 2326c0b746e5SOllivier Robert while (--i >= 0) { 2327c0b746e5SOllivier Robert HTONL_FP(&bug.times[i], &ic->times[i]); 2328c0b746e5SOllivier Robert } 2329c0b746e5SOllivier Robert 2330c0b746e5SOllivier Robert ic = (struct info_clkbug *)more_pkt(); 2331c0b746e5SOllivier Robert } 2332c0b746e5SOllivier Robert flush_pkt(); 2333c0b746e5SOllivier Robert } 2334c0b746e5SOllivier Robert #endif 2335