1c0b746e5SOllivier Robert /* 2c0b746e5SOllivier Robert * ntp_request.c - respond to information requests 3c0b746e5SOllivier Robert */ 49c2daa00SOllivier Robert 5c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H 6c0b746e5SOllivier Robert # include <config.h> 7c0b746e5SOllivier Robert #endif 8c0b746e5SOllivier Robert 9c0b746e5SOllivier Robert #include "ntpd.h" 10c0b746e5SOllivier Robert #include "ntp_io.h" 11c0b746e5SOllivier Robert #include "ntp_request.h" 12c0b746e5SOllivier Robert #include "ntp_control.h" 13c0b746e5SOllivier Robert #include "ntp_refclock.h" 14c0b746e5SOllivier Robert #include "ntp_if.h" 15c0b746e5SOllivier Robert #include "ntp_stdlib.h" 16*2b15cb3dSCy Schubert #include "ntp_assert.h" 17224ba2bdSOllivier Robert 18224ba2bdSOllivier Robert #include <stdio.h> 199c2daa00SOllivier Robert #include <stddef.h> 20224ba2bdSOllivier Robert #include <signal.h> 21*2b15cb3dSCy Schubert #ifdef HAVE_NETINET_IN_H 22224ba2bdSOllivier Robert #include <netinet/in.h> 23*2b15cb3dSCy Schubert #endif 24224ba2bdSOllivier Robert #include <arpa/inet.h> 25224ba2bdSOllivier Robert 26c0b746e5SOllivier Robert #include "recvbuff.h" 27c0b746e5SOllivier Robert 28c0b746e5SOllivier Robert #ifdef KERNEL_PLL 29c0b746e5SOllivier Robert #include "ntp_syscall.h" 30c0b746e5SOllivier Robert #endif /* KERNEL_PLL */ 31c0b746e5SOllivier Robert 32c0b746e5SOllivier Robert /* 33c0b746e5SOllivier Robert * Structure to hold request procedure information 34c0b746e5SOllivier Robert */ 35c0b746e5SOllivier Robert #define NOAUTH 0 36c0b746e5SOllivier Robert #define AUTH 1 37c0b746e5SOllivier Robert 38c0b746e5SOllivier Robert #define NO_REQUEST (-1) 399c2daa00SOllivier Robert /* 409c2daa00SOllivier Robert * Because we now have v6 addresses in the messages, we need to compensate 419c2daa00SOllivier Robert * for the larger size. Therefore, we introduce the alternate size to 429c2daa00SOllivier Robert * keep us friendly with older implementations. A little ugly. 439c2daa00SOllivier Robert */ 449c2daa00SOllivier Robert static int client_v6_capable = 0; /* the client can handle longer messages */ 459c2daa00SOllivier Robert 469c2daa00SOllivier Robert #define v6sizeof(type) (client_v6_capable ? sizeof(type) : v4sizeof(type)) 47c0b746e5SOllivier Robert 48c0b746e5SOllivier Robert struct req_proc { 49c0b746e5SOllivier Robert short request_code; /* defined request code */ 50c0b746e5SOllivier Robert short needs_auth; /* true when authentication needed */ 519c2daa00SOllivier Robert short sizeofitem; /* size of request data item (older size)*/ 529c2daa00SOllivier Robert short v6_sizeofitem; /* size of request data item (new size)*/ 53*2b15cb3dSCy Schubert void (*handler) (sockaddr_u *, endpt *, 54*2b15cb3dSCy Schubert struct req_pkt *); /* routine to handle request */ 55c0b746e5SOllivier Robert }; 56c0b746e5SOllivier Robert 57c0b746e5SOllivier Robert /* 58c0b746e5SOllivier Robert * Universal request codes 59c0b746e5SOllivier Robert */ 60*2b15cb3dSCy Schubert static const struct req_proc univ_codes[] = { 61*2b15cb3dSCy Schubert { NO_REQUEST, NOAUTH, 0, 0, NULL } 62c0b746e5SOllivier Robert }; 63c0b746e5SOllivier Robert 64*2b15cb3dSCy Schubert static void req_ack (sockaddr_u *, endpt *, struct req_pkt *, int); 65*2b15cb3dSCy Schubert static void * prepare_pkt (sockaddr_u *, endpt *, 66*2b15cb3dSCy Schubert struct req_pkt *, size_t); 67*2b15cb3dSCy Schubert static void * more_pkt (void); 68*2b15cb3dSCy Schubert static void flush_pkt (void); 69*2b15cb3dSCy Schubert static void list_peers (sockaddr_u *, endpt *, struct req_pkt *); 70*2b15cb3dSCy Schubert static void list_peers_sum (sockaddr_u *, endpt *, struct req_pkt *); 71*2b15cb3dSCy Schubert static void peer_info (sockaddr_u *, endpt *, struct req_pkt *); 72*2b15cb3dSCy Schubert static void peer_stats (sockaddr_u *, endpt *, struct req_pkt *); 73*2b15cb3dSCy Schubert static void sys_info (sockaddr_u *, endpt *, struct req_pkt *); 74*2b15cb3dSCy Schubert static void sys_stats (sockaddr_u *, endpt *, struct req_pkt *); 75*2b15cb3dSCy Schubert static void mem_stats (sockaddr_u *, endpt *, struct req_pkt *); 76*2b15cb3dSCy Schubert static void io_stats (sockaddr_u *, endpt *, struct req_pkt *); 77*2b15cb3dSCy Schubert static void timer_stats (sockaddr_u *, endpt *, struct req_pkt *); 78*2b15cb3dSCy Schubert static void loop_info (sockaddr_u *, endpt *, struct req_pkt *); 79*2b15cb3dSCy Schubert static void do_conf (sockaddr_u *, endpt *, struct req_pkt *); 80*2b15cb3dSCy Schubert static void do_unconf (sockaddr_u *, endpt *, struct req_pkt *); 81*2b15cb3dSCy Schubert static void set_sys_flag (sockaddr_u *, endpt *, struct req_pkt *); 82*2b15cb3dSCy Schubert static void clr_sys_flag (sockaddr_u *, endpt *, struct req_pkt *); 83*2b15cb3dSCy Schubert static void setclr_flags (sockaddr_u *, endpt *, struct req_pkt *, u_long); 84*2b15cb3dSCy Schubert static void list_restrict4 (restrict_u *, struct info_restrict **); 85*2b15cb3dSCy Schubert static void list_restrict6 (restrict_u *, struct info_restrict **); 86*2b15cb3dSCy Schubert static void list_restrict (sockaddr_u *, endpt *, struct req_pkt *); 87*2b15cb3dSCy Schubert static void do_resaddflags (sockaddr_u *, endpt *, struct req_pkt *); 88*2b15cb3dSCy Schubert static void do_ressubflags (sockaddr_u *, endpt *, struct req_pkt *); 89*2b15cb3dSCy Schubert static void do_unrestrict (sockaddr_u *, endpt *, struct req_pkt *); 90*2b15cb3dSCy Schubert static void do_restrict (sockaddr_u *, endpt *, struct req_pkt *, int); 91*2b15cb3dSCy Schubert static void mon_getlist (sockaddr_u *, endpt *, struct req_pkt *); 92*2b15cb3dSCy Schubert static void reset_stats (sockaddr_u *, endpt *, struct req_pkt *); 93*2b15cb3dSCy Schubert static void reset_peer (sockaddr_u *, endpt *, struct req_pkt *); 94*2b15cb3dSCy Schubert static void do_key_reread (sockaddr_u *, endpt *, struct req_pkt *); 95*2b15cb3dSCy Schubert static void trust_key (sockaddr_u *, endpt *, struct req_pkt *); 96*2b15cb3dSCy Schubert static void untrust_key (sockaddr_u *, endpt *, struct req_pkt *); 97*2b15cb3dSCy Schubert static void do_trustkey (sockaddr_u *, endpt *, struct req_pkt *, u_long); 98*2b15cb3dSCy Schubert static void get_auth_info (sockaddr_u *, endpt *, struct req_pkt *); 99*2b15cb3dSCy Schubert static void req_get_traps (sockaddr_u *, endpt *, struct req_pkt *); 100*2b15cb3dSCy Schubert static void req_set_trap (sockaddr_u *, endpt *, struct req_pkt *); 101*2b15cb3dSCy Schubert static void req_clr_trap (sockaddr_u *, endpt *, struct req_pkt *); 102*2b15cb3dSCy Schubert static void do_setclr_trap (sockaddr_u *, endpt *, struct req_pkt *, int); 103*2b15cb3dSCy Schubert static void set_request_keyid (sockaddr_u *, endpt *, struct req_pkt *); 104*2b15cb3dSCy Schubert static void set_control_keyid (sockaddr_u *, endpt *, struct req_pkt *); 105*2b15cb3dSCy Schubert static void get_ctl_stats (sockaddr_u *, endpt *, struct req_pkt *); 106*2b15cb3dSCy Schubert static void get_if_stats (sockaddr_u *, endpt *, struct req_pkt *); 107*2b15cb3dSCy Schubert static void do_if_reload (sockaddr_u *, endpt *, struct req_pkt *); 108c0b746e5SOllivier Robert #ifdef KERNEL_PLL 109*2b15cb3dSCy Schubert static void get_kernel_info (sockaddr_u *, endpt *, struct req_pkt *); 110c0b746e5SOllivier Robert #endif /* KERNEL_PLL */ 111c0b746e5SOllivier Robert #ifdef REFCLOCK 112*2b15cb3dSCy Schubert static void get_clock_info (sockaddr_u *, endpt *, struct req_pkt *); 113*2b15cb3dSCy Schubert static void set_clock_fudge (sockaddr_u *, endpt *, struct req_pkt *); 114c0b746e5SOllivier Robert #endif /* REFCLOCK */ 115c0b746e5SOllivier Robert #ifdef REFCLOCK 116*2b15cb3dSCy Schubert static void get_clkbug_info (sockaddr_u *, endpt *, struct req_pkt *); 117c0b746e5SOllivier Robert #endif /* REFCLOCK */ 118c0b746e5SOllivier Robert 119c0b746e5SOllivier Robert /* 120c0b746e5SOllivier Robert * ntpd request codes 121c0b746e5SOllivier Robert */ 122*2b15cb3dSCy Schubert static const struct req_proc ntp_codes[] = { 123*2b15cb3dSCy Schubert { REQ_PEER_LIST, NOAUTH, 0, 0, list_peers }, 124*2b15cb3dSCy Schubert { REQ_PEER_LIST_SUM, NOAUTH, 0, 0, list_peers_sum }, 1259c2daa00SOllivier Robert { REQ_PEER_INFO, NOAUTH, v4sizeof(struct info_peer_list), 1269c2daa00SOllivier Robert sizeof(struct info_peer_list), peer_info}, 1279c2daa00SOllivier Robert { REQ_PEER_STATS, NOAUTH, v4sizeof(struct info_peer_list), 1289c2daa00SOllivier Robert sizeof(struct info_peer_list), peer_stats}, 1299c2daa00SOllivier Robert { REQ_SYS_INFO, NOAUTH, 0, 0, sys_info }, 1309c2daa00SOllivier Robert { REQ_SYS_STATS, NOAUTH, 0, 0, sys_stats }, 1319c2daa00SOllivier Robert { REQ_IO_STATS, NOAUTH, 0, 0, io_stats }, 1329c2daa00SOllivier Robert { REQ_MEM_STATS, NOAUTH, 0, 0, mem_stats }, 1339c2daa00SOllivier Robert { REQ_LOOP_INFO, NOAUTH, 0, 0, loop_info }, 1349c2daa00SOllivier Robert { REQ_TIMER_STATS, NOAUTH, 0, 0, timer_stats }, 1359c2daa00SOllivier Robert { REQ_CONFIG, AUTH, v4sizeof(struct conf_peer), 1369c2daa00SOllivier Robert sizeof(struct conf_peer), do_conf }, 1379c2daa00SOllivier Robert { REQ_UNCONFIG, AUTH, v4sizeof(struct conf_unpeer), 1389c2daa00SOllivier Robert sizeof(struct conf_unpeer), do_unconf }, 1399c2daa00SOllivier Robert { REQ_SET_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), 1409c2daa00SOllivier Robert sizeof(struct conf_sys_flags), set_sys_flag }, 1419c2daa00SOllivier Robert { REQ_CLR_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), 1429c2daa00SOllivier Robert sizeof(struct conf_sys_flags), clr_sys_flag }, 1439c2daa00SOllivier Robert { REQ_GET_RESTRICT, NOAUTH, 0, 0, list_restrict }, 1449c2daa00SOllivier Robert { REQ_RESADDFLAGS, AUTH, v4sizeof(struct conf_restrict), 1459c2daa00SOllivier Robert sizeof(struct conf_restrict), do_resaddflags }, 1469c2daa00SOllivier Robert { REQ_RESSUBFLAGS, AUTH, v4sizeof(struct conf_restrict), 1479c2daa00SOllivier Robert sizeof(struct conf_restrict), do_ressubflags }, 1489c2daa00SOllivier Robert { REQ_UNRESTRICT, AUTH, v4sizeof(struct conf_restrict), 1499c2daa00SOllivier Robert sizeof(struct conf_restrict), do_unrestrict }, 150*2b15cb3dSCy Schubert { REQ_MON_GETLIST, NOAUTH, 0, 0, mon_getlist }, 151*2b15cb3dSCy Schubert { REQ_MON_GETLIST_1, NOAUTH, 0, 0, mon_getlist }, 1529c2daa00SOllivier Robert { REQ_RESET_STATS, AUTH, sizeof(struct reset_flags), 0, reset_stats }, 1539c2daa00SOllivier Robert { REQ_RESET_PEER, AUTH, v4sizeof(struct conf_unpeer), 1549c2daa00SOllivier Robert sizeof(struct conf_unpeer), reset_peer }, 1559c2daa00SOllivier Robert { REQ_REREAD_KEYS, AUTH, 0, 0, do_key_reread }, 1569c2daa00SOllivier Robert { REQ_TRUSTKEY, AUTH, sizeof(u_long), sizeof(u_long), trust_key }, 1579c2daa00SOllivier Robert { REQ_UNTRUSTKEY, AUTH, sizeof(u_long), sizeof(u_long), untrust_key }, 1589c2daa00SOllivier Robert { REQ_AUTHINFO, NOAUTH, 0, 0, get_auth_info }, 1599c2daa00SOllivier Robert { REQ_TRAPS, NOAUTH, 0, 0, req_get_traps }, 1609c2daa00SOllivier Robert { REQ_ADD_TRAP, AUTH, v4sizeof(struct conf_trap), 1619c2daa00SOllivier Robert sizeof(struct conf_trap), req_set_trap }, 1629c2daa00SOllivier Robert { REQ_CLR_TRAP, AUTH, v4sizeof(struct conf_trap), 1639c2daa00SOllivier Robert sizeof(struct conf_trap), req_clr_trap }, 1649c2daa00SOllivier Robert { REQ_REQUEST_KEY, AUTH, sizeof(u_long), sizeof(u_long), 1659c2daa00SOllivier Robert set_request_keyid }, 1669c2daa00SOllivier Robert { REQ_CONTROL_KEY, AUTH, sizeof(u_long), sizeof(u_long), 1679c2daa00SOllivier Robert set_control_keyid }, 1689c2daa00SOllivier Robert { REQ_GET_CTLSTATS, NOAUTH, 0, 0, get_ctl_stats }, 169c0b746e5SOllivier Robert #ifdef KERNEL_PLL 1709c2daa00SOllivier Robert { REQ_GET_KERNEL, NOAUTH, 0, 0, get_kernel_info }, 171c0b746e5SOllivier Robert #endif 172c0b746e5SOllivier Robert #ifdef REFCLOCK 1739c2daa00SOllivier Robert { REQ_GET_CLOCKINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32), 1749c2daa00SOllivier Robert get_clock_info }, 1759c2daa00SOllivier Robert { REQ_SET_CLKFUDGE, AUTH, sizeof(struct conf_fudge), 1769c2daa00SOllivier Robert sizeof(struct conf_fudge), set_clock_fudge }, 1779c2daa00SOllivier Robert { REQ_GET_CLKBUGINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32), 1789c2daa00SOllivier Robert get_clkbug_info }, 179c0b746e5SOllivier Robert #endif 180ea906c41SOllivier Robert { REQ_IF_STATS, AUTH, 0, 0, get_if_stats }, 181ea906c41SOllivier Robert { REQ_IF_RELOAD, AUTH, 0, 0, do_if_reload }, 182ea906c41SOllivier Robert 1839c2daa00SOllivier Robert { NO_REQUEST, NOAUTH, 0, 0, 0 } 184c0b746e5SOllivier Robert }; 185c0b746e5SOllivier Robert 186c0b746e5SOllivier Robert 187c0b746e5SOllivier Robert /* 188c0b746e5SOllivier Robert * Authentication keyid used to authenticate requests. Zero means we 189c0b746e5SOllivier Robert * don't allow writing anything. 190c0b746e5SOllivier Robert */ 191224ba2bdSOllivier Robert keyid_t info_auth_keyid; 192c0b746e5SOllivier Robert 193c0b746e5SOllivier Robert /* 194c0b746e5SOllivier Robert * Statistic counters to keep track of requests and responses. 195c0b746e5SOllivier Robert */ 196c0b746e5SOllivier Robert u_long numrequests; /* number of requests we've received */ 197c0b746e5SOllivier Robert u_long numresppkts; /* number of resp packets sent with data */ 198c0b746e5SOllivier Robert 199*2b15cb3dSCy Schubert /* 200*2b15cb3dSCy Schubert * lazy way to count errors, indexed by the error code 201*2b15cb3dSCy Schubert */ 202*2b15cb3dSCy Schubert u_long errorcounter[MAX_INFO_ERR + 1]; 203c0b746e5SOllivier Robert 204c0b746e5SOllivier Robert /* 205c0b746e5SOllivier Robert * A hack. To keep the authentication module clear of ntp-ism's, we 206c0b746e5SOllivier Robert * include a time reset variable for its stats here. 207c0b746e5SOllivier Robert */ 208*2b15cb3dSCy Schubert u_long auth_timereset; 209c0b746e5SOllivier Robert 210c0b746e5SOllivier Robert /* 211c0b746e5SOllivier Robert * Response packet used by these routines. Also some state information 212c0b746e5SOllivier Robert * so that we can handle packet formatting within a common set of 213c0b746e5SOllivier Robert * subroutines. Note we try to enter data in place whenever possible, 214c0b746e5SOllivier Robert * but the need to set the more bit correctly means we occasionally 215c0b746e5SOllivier Robert * use the extra buffer and copy. 216c0b746e5SOllivier Robert */ 217c0b746e5SOllivier Robert static struct resp_pkt rpkt; 218c0b746e5SOllivier Robert static int reqver; 219c0b746e5SOllivier Robert static int seqno; 220c0b746e5SOllivier Robert static int nitems; 221c0b746e5SOllivier Robert static int itemsize; 222c0b746e5SOllivier Robert static int databytes; 223c0b746e5SOllivier Robert static char exbuf[RESP_DATA_SIZE]; 224c0b746e5SOllivier Robert static int usingexbuf; 225*2b15cb3dSCy Schubert static sockaddr_u *toaddr; 226*2b15cb3dSCy Schubert static endpt *frominter; 227c0b746e5SOllivier Robert 228c0b746e5SOllivier Robert /* 229c0b746e5SOllivier Robert * init_request - initialize request data 230c0b746e5SOllivier Robert */ 231c0b746e5SOllivier Robert void 232c0b746e5SOllivier Robert init_request (void) 233c0b746e5SOllivier Robert { 234*2b15cb3dSCy Schubert size_t i; 235c0b746e5SOllivier Robert 236c0b746e5SOllivier Robert numrequests = 0; 237c0b746e5SOllivier Robert numresppkts = 0; 238c0b746e5SOllivier Robert auth_timereset = 0; 239c0b746e5SOllivier Robert info_auth_keyid = 0; /* by default, can't do this */ 240c0b746e5SOllivier Robert 241c0b746e5SOllivier Robert for (i = 0; i < sizeof(errorcounter)/sizeof(errorcounter[0]); i++) 242c0b746e5SOllivier Robert errorcounter[i] = 0; 243c0b746e5SOllivier Robert } 244c0b746e5SOllivier Robert 245c0b746e5SOllivier Robert 246c0b746e5SOllivier Robert /* 247c0b746e5SOllivier Robert * req_ack - acknowledge request with no data 248c0b746e5SOllivier Robert */ 249c0b746e5SOllivier Robert static void 250c0b746e5SOllivier Robert req_ack( 251*2b15cb3dSCy Schubert sockaddr_u *srcadr, 252*2b15cb3dSCy Schubert endpt *inter, 253c0b746e5SOllivier Robert struct req_pkt *inpkt, 254c0b746e5SOllivier Robert int errcode 255c0b746e5SOllivier Robert ) 256c0b746e5SOllivier Robert { 257c0b746e5SOllivier Robert /* 258c0b746e5SOllivier Robert * fill in the fields 259c0b746e5SOllivier Robert */ 260c0b746e5SOllivier Robert rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver); 261c0b746e5SOllivier Robert rpkt.auth_seq = AUTH_SEQ(0, 0); 262c0b746e5SOllivier Robert rpkt.implementation = inpkt->implementation; 263c0b746e5SOllivier Robert rpkt.request = inpkt->request; 264c0b746e5SOllivier Robert rpkt.err_nitems = ERR_NITEMS(errcode, 0); 265c0b746e5SOllivier Robert rpkt.mbz_itemsize = MBZ_ITEMSIZE(0); 266c0b746e5SOllivier Robert 267c0b746e5SOllivier Robert /* 268c0b746e5SOllivier Robert * send packet and bump counters 269c0b746e5SOllivier Robert */ 270c0b746e5SOllivier Robert sendpkt(srcadr, inter, -1, (struct pkt *)&rpkt, RESP_HEADER_SIZE); 271c0b746e5SOllivier Robert errorcounter[errcode]++; 272c0b746e5SOllivier Robert } 273c0b746e5SOllivier Robert 274c0b746e5SOllivier Robert 275c0b746e5SOllivier Robert /* 276c0b746e5SOllivier Robert * prepare_pkt - prepare response packet for transmission, return pointer 277c0b746e5SOllivier Robert * to storage for data item. 278c0b746e5SOllivier Robert */ 279*2b15cb3dSCy Schubert static void * 280c0b746e5SOllivier Robert prepare_pkt( 281*2b15cb3dSCy Schubert sockaddr_u *srcadr, 282*2b15cb3dSCy Schubert endpt *inter, 283c0b746e5SOllivier Robert struct req_pkt *pkt, 284*2b15cb3dSCy Schubert size_t structsize 285c0b746e5SOllivier Robert ) 286c0b746e5SOllivier Robert { 287*2b15cb3dSCy Schubert DPRINTF(4, ("request: preparing pkt\n")); 288c0b746e5SOllivier Robert 289c0b746e5SOllivier Robert /* 2909c2daa00SOllivier Robert * Fill in the implementation, request and itemsize fields 291c0b746e5SOllivier Robert * since these won't change. 292c0b746e5SOllivier Robert */ 293c0b746e5SOllivier Robert rpkt.implementation = pkt->implementation; 294c0b746e5SOllivier Robert rpkt.request = pkt->request; 295c0b746e5SOllivier Robert rpkt.mbz_itemsize = MBZ_ITEMSIZE(structsize); 296c0b746e5SOllivier Robert 297c0b746e5SOllivier Robert /* 298c0b746e5SOllivier Robert * Compute the static data needed to carry on. 299c0b746e5SOllivier Robert */ 300c0b746e5SOllivier Robert toaddr = srcadr; 301c0b746e5SOllivier Robert frominter = inter; 302c0b746e5SOllivier Robert seqno = 0; 303c0b746e5SOllivier Robert nitems = 0; 304c0b746e5SOllivier Robert itemsize = structsize; 305c0b746e5SOllivier Robert databytes = 0; 306c0b746e5SOllivier Robert usingexbuf = 0; 307c0b746e5SOllivier Robert 308c0b746e5SOllivier Robert /* 309c0b746e5SOllivier Robert * return the beginning of the packet buffer. 310c0b746e5SOllivier Robert */ 311*2b15cb3dSCy Schubert return &rpkt.u; 312c0b746e5SOllivier Robert } 313c0b746e5SOllivier Robert 314c0b746e5SOllivier Robert 315c0b746e5SOllivier Robert /* 316c0b746e5SOllivier Robert * more_pkt - return a data pointer for a new item. 317c0b746e5SOllivier Robert */ 318*2b15cb3dSCy Schubert static void * 319c0b746e5SOllivier Robert more_pkt(void) 320c0b746e5SOllivier Robert { 321c0b746e5SOllivier Robert /* 322c0b746e5SOllivier Robert * If we were using the extra buffer, send the packet. 323c0b746e5SOllivier Robert */ 324c0b746e5SOllivier Robert if (usingexbuf) { 325*2b15cb3dSCy Schubert DPRINTF(3, ("request: sending pkt\n")); 326c0b746e5SOllivier Robert rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, MORE_BIT, reqver); 327c0b746e5SOllivier Robert rpkt.auth_seq = AUTH_SEQ(0, seqno); 328c0b746e5SOllivier Robert rpkt.err_nitems = htons((u_short)nitems); 329c0b746e5SOllivier Robert sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt, 330c0b746e5SOllivier Robert RESP_HEADER_SIZE + databytes); 331c0b746e5SOllivier Robert numresppkts++; 332c0b746e5SOllivier Robert 333c0b746e5SOllivier Robert /* 334c0b746e5SOllivier Robert * Copy data out of exbuf into the packet. 335c0b746e5SOllivier Robert */ 336*2b15cb3dSCy Schubert memcpy(&rpkt.u.data[0], exbuf, (unsigned)itemsize); 337c0b746e5SOllivier Robert seqno++; 338c0b746e5SOllivier Robert databytes = 0; 339c0b746e5SOllivier Robert nitems = 0; 340c0b746e5SOllivier Robert usingexbuf = 0; 341c0b746e5SOllivier Robert } 342c0b746e5SOllivier Robert 343c0b746e5SOllivier Robert databytes += itemsize; 344c0b746e5SOllivier Robert nitems++; 345c0b746e5SOllivier Robert if (databytes + itemsize <= RESP_DATA_SIZE) { 346*2b15cb3dSCy Schubert DPRINTF(4, ("request: giving him more data\n")); 347c0b746e5SOllivier Robert /* 348c0b746e5SOllivier Robert * More room in packet. Give him the 349c0b746e5SOllivier Robert * next address. 350c0b746e5SOllivier Robert */ 351*2b15cb3dSCy Schubert return &rpkt.u.data[databytes]; 352c0b746e5SOllivier Robert } else { 353c0b746e5SOllivier Robert /* 354c0b746e5SOllivier Robert * No room in packet. Give him the extra 355c0b746e5SOllivier Robert * buffer unless this was the last in the sequence. 356c0b746e5SOllivier Robert */ 357*2b15cb3dSCy Schubert DPRINTF(4, ("request: into extra buffer\n")); 358c0b746e5SOllivier Robert if (seqno == MAXSEQ) 359*2b15cb3dSCy Schubert return NULL; 360c0b746e5SOllivier Robert else { 361c0b746e5SOllivier Robert usingexbuf = 1; 362c0b746e5SOllivier Robert return exbuf; 363c0b746e5SOllivier Robert } 364c0b746e5SOllivier Robert } 365c0b746e5SOllivier Robert } 366c0b746e5SOllivier Robert 367c0b746e5SOllivier Robert 368c0b746e5SOllivier Robert /* 369c0b746e5SOllivier Robert * flush_pkt - we're done, return remaining information. 370c0b746e5SOllivier Robert */ 371c0b746e5SOllivier Robert static void 372c0b746e5SOllivier Robert flush_pkt(void) 373c0b746e5SOllivier Robert { 374*2b15cb3dSCy Schubert DPRINTF(3, ("request: flushing packet, %d items\n", nitems)); 375c0b746e5SOllivier Robert /* 376c0b746e5SOllivier Robert * Must send the last packet. If nothing in here and nothing 377c0b746e5SOllivier Robert * has been sent, send an error saying no data to be found. 378c0b746e5SOllivier Robert */ 379c0b746e5SOllivier Robert if (seqno == 0 && nitems == 0) 380c0b746e5SOllivier Robert req_ack(toaddr, frominter, (struct req_pkt *)&rpkt, 381c0b746e5SOllivier Robert INFO_ERR_NODATA); 382c0b746e5SOllivier Robert else { 383c0b746e5SOllivier Robert rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver); 384c0b746e5SOllivier Robert rpkt.auth_seq = AUTH_SEQ(0, seqno); 385c0b746e5SOllivier Robert rpkt.err_nitems = htons((u_short)nitems); 386c0b746e5SOllivier Robert sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt, 387c0b746e5SOllivier Robert RESP_HEADER_SIZE+databytes); 388c0b746e5SOllivier Robert numresppkts++; 389c0b746e5SOllivier Robert } 390c0b746e5SOllivier Robert } 391c0b746e5SOllivier Robert 392c0b746e5SOllivier Robert 393c0b746e5SOllivier Robert 394c0b746e5SOllivier Robert /* 395*2b15cb3dSCy Schubert * Given a buffer, return the packet mode 396*2b15cb3dSCy Schubert */ 397*2b15cb3dSCy Schubert int 398*2b15cb3dSCy Schubert get_packet_mode(struct recvbuf *rbufp) 399*2b15cb3dSCy Schubert { 400*2b15cb3dSCy Schubert struct req_pkt *inpkt = (struct req_pkt *)&rbufp->recv_pkt; 401*2b15cb3dSCy Schubert return (INFO_MODE(inpkt->rm_vn_mode)); 402*2b15cb3dSCy Schubert } 403*2b15cb3dSCy Schubert 404*2b15cb3dSCy Schubert 405*2b15cb3dSCy Schubert /* 406c0b746e5SOllivier Robert * process_private - process private mode (7) packets 407c0b746e5SOllivier Robert */ 408c0b746e5SOllivier Robert void 409c0b746e5SOllivier Robert process_private( 410c0b746e5SOllivier Robert struct recvbuf *rbufp, 411c0b746e5SOllivier Robert int mod_okay 412c0b746e5SOllivier Robert ) 413c0b746e5SOllivier Robert { 414eb6d21b4SOllivier Robert static u_long quiet_until; 415c0b746e5SOllivier Robert struct req_pkt *inpkt; 416ce265a54SOllivier Robert struct req_pkt_tail *tailinpkt; 417*2b15cb3dSCy Schubert sockaddr_u *srcadr; 418*2b15cb3dSCy Schubert endpt *inter; 419*2b15cb3dSCy Schubert const struct req_proc *proc; 420224ba2bdSOllivier Robert int ec; 4219c2daa00SOllivier Robert short temp_size; 422*2b15cb3dSCy Schubert l_fp ftmp; 423*2b15cb3dSCy Schubert double dtemp; 424*2b15cb3dSCy Schubert size_t recv_len; 425*2b15cb3dSCy Schubert size_t noslop_len; 426*2b15cb3dSCy Schubert size_t mac_len; 427c0b746e5SOllivier Robert 428c0b746e5SOllivier Robert /* 429c0b746e5SOllivier Robert * Initialize pointers, for convenience 430c0b746e5SOllivier Robert */ 431*2b15cb3dSCy Schubert recv_len = rbufp->recv_length; 432c0b746e5SOllivier Robert inpkt = (struct req_pkt *)&rbufp->recv_pkt; 433c0b746e5SOllivier Robert srcadr = &rbufp->recv_srcadr; 434c0b746e5SOllivier Robert inter = rbufp->dstadr; 435c0b746e5SOllivier Robert 436*2b15cb3dSCy Schubert DPRINTF(3, ("process_private: impl %d req %d\n", 437*2b15cb3dSCy Schubert inpkt->implementation, inpkt->request)); 438c0b746e5SOllivier Robert 439c0b746e5SOllivier Robert /* 440c0b746e5SOllivier Robert * Do some sanity checks on the packet. Return a format 441c0b746e5SOllivier Robert * error if it fails. 442c0b746e5SOllivier Robert */ 443224ba2bdSOllivier Robert ec = 0; 444224ba2bdSOllivier Robert if ( (++ec, ISRESPONSE(inpkt->rm_vn_mode)) 445224ba2bdSOllivier Robert || (++ec, ISMORE(inpkt->rm_vn_mode)) 446224ba2bdSOllivier Robert || (++ec, INFO_VERSION(inpkt->rm_vn_mode) > NTP_VERSION) 447224ba2bdSOllivier Robert || (++ec, INFO_VERSION(inpkt->rm_vn_mode) < NTP_OLDVERSION) 448224ba2bdSOllivier Robert || (++ec, INFO_SEQ(inpkt->auth_seq) != 0) 449224ba2bdSOllivier Robert || (++ec, INFO_ERR(inpkt->err_nitems) != 0) 450224ba2bdSOllivier Robert || (++ec, INFO_MBZ(inpkt->mbz_itemsize) != 0) 451*2b15cb3dSCy Schubert || (++ec, rbufp->recv_length < (int)REQ_LEN_HDR) 452224ba2bdSOllivier Robert ) { 453eb6d21b4SOllivier Robert NLOG(NLOG_SYSEVENT) 454eb6d21b4SOllivier Robert if (current_time >= quiet_until) { 455eb6d21b4SOllivier Robert msyslog(LOG_ERR, 456eb6d21b4SOllivier Robert "process_private: drop test %d" 457eb6d21b4SOllivier Robert " failed, pkt from %s", 458eb6d21b4SOllivier Robert ec, stoa(srcadr)); 459eb6d21b4SOllivier Robert quiet_until = current_time + 60; 460eb6d21b4SOllivier Robert } 461c0b746e5SOllivier Robert return; 462c0b746e5SOllivier Robert } 463c0b746e5SOllivier Robert 464c0b746e5SOllivier Robert reqver = INFO_VERSION(inpkt->rm_vn_mode); 465c0b746e5SOllivier Robert 466c0b746e5SOllivier Robert /* 467c0b746e5SOllivier Robert * Get the appropriate procedure list to search. 468c0b746e5SOllivier Robert */ 469c0b746e5SOllivier Robert if (inpkt->implementation == IMPL_UNIV) 470c0b746e5SOllivier Robert proc = univ_codes; 4719c2daa00SOllivier Robert else if ((inpkt->implementation == IMPL_XNTPD) || 4729c2daa00SOllivier Robert (inpkt->implementation == IMPL_XNTPD_OLD)) 473c0b746e5SOllivier Robert proc = ntp_codes; 474c0b746e5SOllivier Robert else { 475c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_IMPL); 476c0b746e5SOllivier Robert return; 477c0b746e5SOllivier Robert } 478c0b746e5SOllivier Robert 479c0b746e5SOllivier Robert /* 480c0b746e5SOllivier Robert * Search the list for the request codes. If it isn't one 481c0b746e5SOllivier Robert * we know, return an error. 482c0b746e5SOllivier Robert */ 483c0b746e5SOllivier Robert while (proc->request_code != NO_REQUEST) { 484c0b746e5SOllivier Robert if (proc->request_code == (short) inpkt->request) 485c0b746e5SOllivier Robert break; 486c0b746e5SOllivier Robert proc++; 487c0b746e5SOllivier Robert } 488c0b746e5SOllivier Robert if (proc->request_code == NO_REQUEST) { 489c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_REQ); 490c0b746e5SOllivier Robert return; 491c0b746e5SOllivier Robert } 492c0b746e5SOllivier Robert 493*2b15cb3dSCy Schubert DPRINTF(4, ("found request in tables\n")); 494c0b746e5SOllivier Robert 495c0b746e5SOllivier Robert /* 4969c2daa00SOllivier Robert * If we need data, check to see if we have some. If we 4979c2daa00SOllivier Robert * don't, check to see that there is none (picky, picky). 4989c2daa00SOllivier Robert */ 4999c2daa00SOllivier Robert 5009c2daa00SOllivier Robert /* This part is a bit tricky, we want to be sure that the size 5019c2daa00SOllivier Robert * returned is either the old or the new size. We also can find 5029c2daa00SOllivier Robert * out if the client can accept both types of messages this way. 5039c2daa00SOllivier Robert * 5049c2daa00SOllivier Robert * Handle the exception of REQ_CONFIG. It can have two data sizes. 5059c2daa00SOllivier Robert */ 5069c2daa00SOllivier Robert temp_size = INFO_ITEMSIZE(inpkt->mbz_itemsize); 5079c2daa00SOllivier Robert if ((temp_size != proc->sizeofitem && 5089c2daa00SOllivier Robert temp_size != proc->v6_sizeofitem) && 5099c2daa00SOllivier Robert !(inpkt->implementation == IMPL_XNTPD && 5109c2daa00SOllivier Robert inpkt->request == REQ_CONFIG && 5119c2daa00SOllivier Robert temp_size == sizeof(struct old_conf_peer))) { 512*2b15cb3dSCy Schubert DPRINTF(3, ("process_private: wrong item size, received %d, should be %d or %d\n", 513*2b15cb3dSCy Schubert temp_size, proc->sizeofitem, proc->v6_sizeofitem)); 5149c2daa00SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 5159c2daa00SOllivier Robert return; 5169c2daa00SOllivier Robert } 5179c2daa00SOllivier Robert if ((proc->sizeofitem != 0) && 518*2b15cb3dSCy Schubert ((size_t)(temp_size * INFO_NITEMS(inpkt->err_nitems)) > 519*2b15cb3dSCy Schubert (recv_len - REQ_LEN_HDR))) { 520*2b15cb3dSCy Schubert DPRINTF(3, ("process_private: not enough data\n")); 5219c2daa00SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 5229c2daa00SOllivier Robert return; 5239c2daa00SOllivier Robert } 5249c2daa00SOllivier Robert 5259c2daa00SOllivier Robert switch (inpkt->implementation) { 5269c2daa00SOllivier Robert case IMPL_XNTPD: 5279c2daa00SOllivier Robert client_v6_capable = 1; 5289c2daa00SOllivier Robert break; 5299c2daa00SOllivier Robert case IMPL_XNTPD_OLD: 5309c2daa00SOllivier Robert client_v6_capable = 0; 5319c2daa00SOllivier Robert break; 5329c2daa00SOllivier Robert default: 5339c2daa00SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 5349c2daa00SOllivier Robert return; 5359c2daa00SOllivier Robert } 5369c2daa00SOllivier Robert 5379c2daa00SOllivier Robert /* 538c0b746e5SOllivier Robert * If we need to authenticate, do so. Note that an 539c0b746e5SOllivier Robert * authenticatable packet must include a mac field, must 540c0b746e5SOllivier Robert * have used key info_auth_keyid and must have included 541c0b746e5SOllivier Robert * a time stamp in the appropriate field. The time stamp 542c0b746e5SOllivier Robert * must be within INFO_TS_MAXSKEW of the receive 543c0b746e5SOllivier Robert * time stamp. 544c0b746e5SOllivier Robert */ 545c0b746e5SOllivier Robert if (proc->needs_auth && sys_authenticate) { 546c0b746e5SOllivier Robert 547*2b15cb3dSCy Schubert if (recv_len < (REQ_LEN_HDR + 548ce265a54SOllivier Robert (INFO_ITEMSIZE(inpkt->mbz_itemsize) * 549*2b15cb3dSCy Schubert INFO_NITEMS(inpkt->err_nitems)) + 550*2b15cb3dSCy Schubert REQ_TAIL_MIN)) { 551ce265a54SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 552*2b15cb3dSCy Schubert return; 553ce265a54SOllivier Robert } 554ce265a54SOllivier Robert 555c0b746e5SOllivier Robert /* 556*2b15cb3dSCy Schubert * For 16-octet digests, regardless of itemsize and 557*2b15cb3dSCy Schubert * nitems, authenticated requests are a fixed size 558*2b15cb3dSCy Schubert * with the timestamp, key ID, and digest located 559*2b15cb3dSCy Schubert * at the end of the packet. Because the key ID 560*2b15cb3dSCy Schubert * determining the digest size precedes the digest, 561*2b15cb3dSCy Schubert * for larger digests the fixed size request scheme 562*2b15cb3dSCy Schubert * is abandoned and the timestamp, key ID, and digest 563*2b15cb3dSCy Schubert * are located relative to the start of the packet, 564*2b15cb3dSCy Schubert * with the digest size determined by the packet size. 565c0b746e5SOllivier Robert */ 566*2b15cb3dSCy Schubert noslop_len = REQ_LEN_HDR 567*2b15cb3dSCy Schubert + INFO_ITEMSIZE(inpkt->mbz_itemsize) * 568*2b15cb3dSCy Schubert INFO_NITEMS(inpkt->err_nitems) 569*2b15cb3dSCy Schubert + sizeof(inpkt->tstamp); 570*2b15cb3dSCy Schubert /* 32-bit alignment */ 571*2b15cb3dSCy Schubert noslop_len = (noslop_len + 3) & ~3; 572*2b15cb3dSCy Schubert if (recv_len > (noslop_len + MAX_MAC_LEN)) 573*2b15cb3dSCy Schubert mac_len = 20; 574*2b15cb3dSCy Schubert else 575*2b15cb3dSCy Schubert mac_len = recv_len - noslop_len; 576*2b15cb3dSCy Schubert 577*2b15cb3dSCy Schubert tailinpkt = (void *)((char *)inpkt + recv_len - 578*2b15cb3dSCy Schubert (mac_len + sizeof(inpkt->tstamp))); 579*2b15cb3dSCy Schubert 580*2b15cb3dSCy Schubert /* 581*2b15cb3dSCy Schubert * If this guy is restricted from doing this, don't let 582*2b15cb3dSCy Schubert * him. If the wrong key was used, or packet doesn't 583*2b15cb3dSCy Schubert * have mac, return. 584*2b15cb3dSCy Schubert */ 585*2b15cb3dSCy Schubert if (!INFO_IS_AUTH(inpkt->auth_seq) || !info_auth_keyid 586ce265a54SOllivier Robert || ntohl(tailinpkt->keyid) != info_auth_keyid) { 587*2b15cb3dSCy Schubert DPRINTF(5, ("failed auth %d info_auth_keyid %u pkt keyid %u maclen %lu\n", 588*2b15cb3dSCy Schubert INFO_IS_AUTH(inpkt->auth_seq), 589*2b15cb3dSCy Schubert info_auth_keyid, 590*2b15cb3dSCy Schubert ntohl(tailinpkt->keyid), (u_long)mac_len)); 591c0b746e5SOllivier Robert #ifdef DEBUG 5929c2daa00SOllivier Robert msyslog(LOG_DEBUG, 593*2b15cb3dSCy Schubert "process_private: failed auth %d info_auth_keyid %u pkt keyid %u maclen %lu\n", 5949c2daa00SOllivier Robert INFO_IS_AUTH(inpkt->auth_seq), 595*2b15cb3dSCy Schubert info_auth_keyid, 596*2b15cb3dSCy Schubert ntohl(tailinpkt->keyid), (u_long)mac_len); 597c0b746e5SOllivier Robert #endif 598c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 599c0b746e5SOllivier Robert return; 600c0b746e5SOllivier Robert } 601*2b15cb3dSCy Schubert if (recv_len > REQ_LEN_NOMAC + MAX_MAC_LEN) { 602*2b15cb3dSCy Schubert DPRINTF(5, ("bad pkt length %zu\n", recv_len)); 603*2b15cb3dSCy Schubert msyslog(LOG_ERR, 604*2b15cb3dSCy Schubert "process_private: bad pkt length %zu", 605*2b15cb3dSCy Schubert recv_len); 606c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 607c0b746e5SOllivier Robert return; 608c0b746e5SOllivier Robert } 609c0b746e5SOllivier Robert if (!mod_okay || !authhavekey(info_auth_keyid)) { 610*2b15cb3dSCy Schubert DPRINTF(5, ("failed auth mod_okay %d\n", 611*2b15cb3dSCy Schubert mod_okay)); 612c0b746e5SOllivier Robert #ifdef DEBUG 6139c2daa00SOllivier Robert msyslog(LOG_DEBUG, 6149c2daa00SOllivier Robert "process_private: failed auth mod_okay %d\n", 6159c2daa00SOllivier Robert mod_okay); 616c0b746e5SOllivier Robert #endif 617*2b15cb3dSCy Schubert if (!mod_okay) { 618*2b15cb3dSCy Schubert sys_restricted++; 619*2b15cb3dSCy Schubert } 620c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 621c0b746e5SOllivier Robert return; 622c0b746e5SOllivier Robert } 623c0b746e5SOllivier Robert 624c0b746e5SOllivier Robert /* 625c0b746e5SOllivier Robert * calculate absolute time difference between xmit time stamp 626c0b746e5SOllivier Robert * and receive time stamp. If too large, too bad. 627c0b746e5SOllivier Robert */ 628ce265a54SOllivier Robert NTOHL_FP(&tailinpkt->tstamp, &ftmp); 629c0b746e5SOllivier Robert L_SUB(&ftmp, &rbufp->recv_time); 630c0b746e5SOllivier Robert LFPTOD(&ftmp, dtemp); 631*2b15cb3dSCy Schubert if (fabs(dtemp) > INFO_TS_MAXSKEW) { 632c0b746e5SOllivier Robert /* 633c0b746e5SOllivier Robert * He's a loser. Tell him. 634c0b746e5SOllivier Robert */ 635*2b15cb3dSCy Schubert DPRINTF(5, ("xmit/rcv timestamp delta %g > INFO_TS_MAXSKEW %g\n", 636*2b15cb3dSCy Schubert dtemp, INFO_TS_MAXSKEW)); 637c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 638c0b746e5SOllivier Robert return; 639c0b746e5SOllivier Robert } 640c0b746e5SOllivier Robert 641c0b746e5SOllivier Robert /* 642c0b746e5SOllivier Robert * So far so good. See if decryption works out okay. 643c0b746e5SOllivier Robert */ 644c0b746e5SOllivier Robert if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt, 645*2b15cb3dSCy Schubert recv_len - mac_len, mac_len)) { 646*2b15cb3dSCy Schubert DPRINTF(5, ("authdecrypt failed\n")); 647c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 648c0b746e5SOllivier Robert return; 649c0b746e5SOllivier Robert } 650c0b746e5SOllivier Robert } 651c0b746e5SOllivier Robert 652*2b15cb3dSCy Schubert DPRINTF(3, ("process_private: all okay, into handler\n")); 653c0b746e5SOllivier Robert /* 654c0b746e5SOllivier Robert * Packet is okay. Call the handler to send him data. 655c0b746e5SOllivier Robert */ 656c0b746e5SOllivier Robert (proc->handler)(srcadr, inter, inpkt); 657c0b746e5SOllivier Robert } 658c0b746e5SOllivier Robert 659c0b746e5SOllivier Robert 660c0b746e5SOllivier Robert /* 661*2b15cb3dSCy Schubert * list_peers - send a list of the peers 662c0b746e5SOllivier Robert */ 663c0b746e5SOllivier Robert static void 664*2b15cb3dSCy Schubert list_peers( 665*2b15cb3dSCy Schubert sockaddr_u *srcadr, 666*2b15cb3dSCy Schubert endpt *inter, 667c0b746e5SOllivier Robert struct req_pkt *inpkt 668c0b746e5SOllivier Robert ) 669c0b746e5SOllivier Robert { 670*2b15cb3dSCy Schubert struct info_peer_list *ip; 671*2b15cb3dSCy Schubert struct peer *pp; 672*2b15cb3dSCy Schubert int skip = 0; 673c0b746e5SOllivier Robert 674c0b746e5SOllivier Robert ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt, 6759c2daa00SOllivier Robert v6sizeof(struct info_peer_list)); 676*2b15cb3dSCy Schubert for (pp = peer_list; pp != NULL && ip != NULL; pp = pp->p_link) { 677*2b15cb3dSCy Schubert if (IS_IPV6(&pp->srcadr)) { 6789c2daa00SOllivier Robert if (client_v6_capable) { 679*2b15cb3dSCy Schubert ip->addr6 = SOCK_ADDR6(&pp->srcadr); 6809c2daa00SOllivier Robert ip->v6_flag = 1; 6819c2daa00SOllivier Robert skip = 0; 6829c2daa00SOllivier Robert } else { 6839c2daa00SOllivier Robert skip = 1; 6849c2daa00SOllivier Robert break; 6859c2daa00SOllivier Robert } 6869c2daa00SOllivier Robert } else { 687*2b15cb3dSCy Schubert ip->addr = NSRCADR(&pp->srcadr); 6889c2daa00SOllivier Robert if (client_v6_capable) 6899c2daa00SOllivier Robert ip->v6_flag = 0; 6909c2daa00SOllivier Robert skip = 0; 6919c2daa00SOllivier Robert } 6929c2daa00SOllivier Robert 6939c2daa00SOllivier Robert if (!skip) { 6949c2daa00SOllivier Robert ip->port = NSRCPORT(&pp->srcadr); 695c0b746e5SOllivier Robert ip->hmode = pp->hmode; 696c0b746e5SOllivier Robert ip->flags = 0; 697c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 698c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 699c0b746e5SOllivier Robert if (pp == sys_peer) 700c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 701c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 702c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 703c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 704c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 705c0b746e5SOllivier Robert ip = (struct info_peer_list *)more_pkt(); 7069c2daa00SOllivier Robert } 707*2b15cb3dSCy Schubert } /* for pp */ 708*2b15cb3dSCy Schubert 709c0b746e5SOllivier Robert flush_pkt(); 710c0b746e5SOllivier Robert } 711c0b746e5SOllivier Robert 712c0b746e5SOllivier Robert 713c0b746e5SOllivier Robert /* 714*2b15cb3dSCy Schubert * list_peers_sum - return extended peer list 715c0b746e5SOllivier Robert */ 716c0b746e5SOllivier Robert static void 717*2b15cb3dSCy Schubert list_peers_sum( 718*2b15cb3dSCy Schubert sockaddr_u *srcadr, 719*2b15cb3dSCy Schubert endpt *inter, 720c0b746e5SOllivier Robert struct req_pkt *inpkt 721c0b746e5SOllivier Robert ) 722c0b746e5SOllivier Robert { 723c0b746e5SOllivier Robert register struct info_peer_summary *ips; 724c0b746e5SOllivier Robert register struct peer *pp; 725c0b746e5SOllivier Robert l_fp ltmp; 7269c2daa00SOllivier Robert register int skip; 727c0b746e5SOllivier Robert 728*2b15cb3dSCy Schubert DPRINTF(3, ("wants peer list summary\n")); 729*2b15cb3dSCy Schubert 730c0b746e5SOllivier Robert ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt, 7319c2daa00SOllivier Robert v6sizeof(struct info_peer_summary)); 732*2b15cb3dSCy Schubert for (pp = peer_list; pp != NULL && ips != NULL; pp = pp->p_link) { 733*2b15cb3dSCy Schubert DPRINTF(4, ("sum: got one\n")); 7349c2daa00SOllivier Robert /* 7359c2daa00SOllivier Robert * Be careful here not to return v6 peers when we 7369c2daa00SOllivier Robert * want only v4. 7379c2daa00SOllivier Robert */ 738*2b15cb3dSCy Schubert if (IS_IPV6(&pp->srcadr)) { 7399c2daa00SOllivier Robert if (client_v6_capable) { 740*2b15cb3dSCy Schubert ips->srcadr6 = SOCK_ADDR6(&pp->srcadr); 7419c2daa00SOllivier Robert ips->v6_flag = 1; 742ea906c41SOllivier Robert if (pp->dstadr) 743*2b15cb3dSCy Schubert ips->dstadr6 = SOCK_ADDR6(&pp->dstadr->sin); 744ea906c41SOllivier Robert else 745*2b15cb3dSCy Schubert ZERO(ips->dstadr6); 7469c2daa00SOllivier Robert skip = 0; 7479c2daa00SOllivier Robert } else { 7489c2daa00SOllivier Robert skip = 1; 7499c2daa00SOllivier Robert break; 7509c2daa00SOllivier Robert } 7519c2daa00SOllivier Robert } else { 752*2b15cb3dSCy Schubert ips->srcadr = NSRCADR(&pp->srcadr); 7539c2daa00SOllivier Robert if (client_v6_capable) 7549c2daa00SOllivier Robert ips->v6_flag = 0; 755ea906c41SOllivier Robert 756*2b15cb3dSCy Schubert if (pp->dstadr) { 757*2b15cb3dSCy Schubert if (!pp->processed) 758*2b15cb3dSCy Schubert ips->dstadr = NSRCADR(&pp->dstadr->sin); 759*2b15cb3dSCy Schubert else { 760*2b15cb3dSCy Schubert if (MDF_BCAST == pp->cast_flags) 761*2b15cb3dSCy Schubert ips->dstadr = NSRCADR(&pp->dstadr->bcast); 762*2b15cb3dSCy Schubert else if (pp->cast_flags) { 763*2b15cb3dSCy Schubert ips->dstadr = NSRCADR(&pp->dstadr->sin); 764*2b15cb3dSCy Schubert if (!ips->dstadr) 765*2b15cb3dSCy Schubert ips->dstadr = NSRCADR(&pp->dstadr->bcast); 766*2b15cb3dSCy Schubert } 767*2b15cb3dSCy Schubert } 768*2b15cb3dSCy Schubert } else 769*2b15cb3dSCy Schubert ips->dstadr = 0; 7709c2daa00SOllivier Robert 7719c2daa00SOllivier Robert skip = 0; 7729c2daa00SOllivier Robert } 773ea906c41SOllivier Robert 7749c2daa00SOllivier Robert if (!skip) { 7759c2daa00SOllivier Robert ips->srcport = NSRCPORT(&pp->srcadr); 776c0b746e5SOllivier Robert ips->stratum = pp->stratum; 777c0b746e5SOllivier Robert ips->hpoll = pp->hpoll; 778c0b746e5SOllivier Robert ips->ppoll = pp->ppoll; 779c0b746e5SOllivier Robert ips->reach = pp->reach; 780c0b746e5SOllivier Robert ips->flags = 0; 781c0b746e5SOllivier Robert if (pp == sys_peer) 782c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SYSPEER; 783c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 784c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_CONFIG; 785c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 786c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_REFCLOCK; 787c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 788c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_PREFER; 789c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 790c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_BURST; 791c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 792c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SEL_CANDIDATE; 793c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 794c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SHORTLIST; 795c0b746e5SOllivier Robert ips->hmode = pp->hmode; 796c0b746e5SOllivier Robert ips->delay = HTONS_FP(DTOFP(pp->delay)); 797c0b746e5SOllivier Robert DTOLFP(pp->offset, <mp); 798c0b746e5SOllivier Robert HTONL_FP(<mp, &ips->offset); 799ea906c41SOllivier Robert ips->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); 8009c2daa00SOllivier Robert } 801c0b746e5SOllivier Robert ips = (struct info_peer_summary *)more_pkt(); 802*2b15cb3dSCy Schubert } /* for pp */ 803*2b15cb3dSCy Schubert 804c0b746e5SOllivier Robert flush_pkt(); 805c0b746e5SOllivier Robert } 806c0b746e5SOllivier Robert 807c0b746e5SOllivier Robert 808c0b746e5SOllivier Robert /* 809c0b746e5SOllivier Robert * peer_info - send information for one or more peers 810c0b746e5SOllivier Robert */ 811c0b746e5SOllivier Robert static void 812c0b746e5SOllivier Robert peer_info ( 813*2b15cb3dSCy Schubert sockaddr_u *srcadr, 814*2b15cb3dSCy Schubert endpt *inter, 815c0b746e5SOllivier Robert struct req_pkt *inpkt 816c0b746e5SOllivier Robert ) 817c0b746e5SOllivier Robert { 818*2b15cb3dSCy Schubert u_short items; 819*2b15cb3dSCy Schubert size_t item_sz; 820*2b15cb3dSCy Schubert char * datap; 821*2b15cb3dSCy Schubert struct info_peer_list ipl; 822*2b15cb3dSCy Schubert struct peer * pp; 823*2b15cb3dSCy Schubert struct info_peer * ip; 824*2b15cb3dSCy Schubert int i; 825*2b15cb3dSCy Schubert int j; 826*2b15cb3dSCy Schubert sockaddr_u addr; 827c0b746e5SOllivier Robert l_fp ltmp; 828c0b746e5SOllivier Robert 829c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 830*2b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 831*2b15cb3dSCy Schubert datap = inpkt->u.data; 832*2b15cb3dSCy Schubert if (item_sz != sizeof(ipl)) { 833*2b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 834*2b15cb3dSCy Schubert return; 8359c2daa00SOllivier Robert } 836*2b15cb3dSCy Schubert ip = prepare_pkt(srcadr, inter, inpkt, 837*2b15cb3dSCy Schubert v6sizeof(struct info_peer)); 838*2b15cb3dSCy Schubert while (items-- > 0 && ip != NULL) { 839*2b15cb3dSCy Schubert ZERO(ipl); 840*2b15cb3dSCy Schubert memcpy(&ipl, datap, item_sz); 841*2b15cb3dSCy Schubert ZERO_SOCK(&addr); 842*2b15cb3dSCy Schubert NSRCPORT(&addr) = ipl.port; 843*2b15cb3dSCy Schubert if (client_v6_capable && ipl.v6_flag) { 844*2b15cb3dSCy Schubert AF(&addr) = AF_INET6; 845*2b15cb3dSCy Schubert SOCK_ADDR6(&addr) = ipl.addr6; 846*2b15cb3dSCy Schubert } else { 847*2b15cb3dSCy Schubert AF(&addr) = AF_INET; 848*2b15cb3dSCy Schubert NSRCADR(&addr) = ipl.addr; 849*2b15cb3dSCy Schubert } 850*2b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 851*2b15cb3dSCy Schubert addr.sa.sa_len = SOCKLEN(&addr); 8529c2daa00SOllivier Robert #endif 853*2b15cb3dSCy Schubert datap += item_sz; 854ea906c41SOllivier Robert 855*2b15cb3dSCy Schubert pp = findexistingpeer(&addr, NULL, NULL, -1, 0); 856*2b15cb3dSCy Schubert if (NULL == pp) 857*2b15cb3dSCy Schubert continue; 858*2b15cb3dSCy Schubert if (IS_IPV6(srcadr)) { 859*2b15cb3dSCy Schubert if (pp->dstadr) 860*2b15cb3dSCy Schubert ip->dstadr6 = 861*2b15cb3dSCy Schubert (MDF_BCAST == pp->cast_flags) 862*2b15cb3dSCy Schubert ? SOCK_ADDR6(&pp->dstadr->bcast) 863*2b15cb3dSCy Schubert : SOCK_ADDR6(&pp->dstadr->sin); 864*2b15cb3dSCy Schubert else 865*2b15cb3dSCy Schubert ZERO(ip->dstadr6); 866*2b15cb3dSCy Schubert 867*2b15cb3dSCy Schubert ip->srcadr6 = SOCK_ADDR6(&pp->srcadr); 8689c2daa00SOllivier Robert ip->v6_flag = 1; 8699c2daa00SOllivier Robert } else { 870*2b15cb3dSCy Schubert if (pp->dstadr) { 871*2b15cb3dSCy Schubert if (!pp->processed) 872*2b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->sin); 873*2b15cb3dSCy Schubert else { 874*2b15cb3dSCy Schubert if (MDF_BCAST == pp->cast_flags) 875*2b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->bcast); 876*2b15cb3dSCy Schubert else if (pp->cast_flags) { 877*2b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->sin); 878*2b15cb3dSCy Schubert if (!ip->dstadr) 879*2b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->bcast); 880*2b15cb3dSCy Schubert } 881*2b15cb3dSCy Schubert } 882*2b15cb3dSCy Schubert } else 883*2b15cb3dSCy Schubert ip->dstadr = 0; 8849c2daa00SOllivier Robert 885*2b15cb3dSCy Schubert ip->srcadr = NSRCADR(&pp->srcadr); 8869c2daa00SOllivier Robert if (client_v6_capable) 8879c2daa00SOllivier Robert ip->v6_flag = 0; 8889c2daa00SOllivier Robert } 889c0b746e5SOllivier Robert ip->srcport = NSRCPORT(&pp->srcadr); 890c0b746e5SOllivier Robert ip->flags = 0; 891c0b746e5SOllivier Robert if (pp == sys_peer) 892c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 893c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 894c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 895c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 896c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_REFCLOCK; 897c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 898c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_PREFER; 899c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 900c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_BURST; 901c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 902c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 903c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 904c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 905c0b746e5SOllivier Robert ip->leap = pp->leap; 906c0b746e5SOllivier Robert ip->hmode = pp->hmode; 907c0b746e5SOllivier Robert ip->keyid = pp->keyid; 908c0b746e5SOllivier Robert ip->stratum = pp->stratum; 909c0b746e5SOllivier Robert ip->ppoll = pp->ppoll; 910c0b746e5SOllivier Robert ip->hpoll = pp->hpoll; 911c0b746e5SOllivier Robert ip->precision = pp->precision; 912c0b746e5SOllivier Robert ip->version = pp->version; 913c0b746e5SOllivier Robert ip->reach = pp->reach; 9149c2daa00SOllivier Robert ip->unreach = (u_char)pp->unreach; 915c0b746e5SOllivier Robert ip->flash = (u_char)pp->flash; 9169c2daa00SOllivier Robert ip->flash2 = (u_short)pp->flash; 917*2b15cb3dSCy Schubert ip->estbdelay = HTONS_FP(DTOFP(pp->delay)); 918*2b15cb3dSCy Schubert ip->ttl = (u_char)pp->ttl; 919c0b746e5SOllivier Robert ip->associd = htons(pp->associd); 920c0b746e5SOllivier Robert ip->rootdelay = HTONS_FP(DTOUFP(pp->rootdelay)); 921*2b15cb3dSCy Schubert ip->rootdispersion = HTONS_FP(DTOUFP(pp->rootdisp)); 922c0b746e5SOllivier Robert ip->refid = pp->refid; 923c0b746e5SOllivier Robert HTONL_FP(&pp->reftime, &ip->reftime); 924*2b15cb3dSCy Schubert HTONL_FP(&pp->aorg, &ip->org); 925c0b746e5SOllivier Robert HTONL_FP(&pp->rec, &ip->rec); 926c0b746e5SOllivier Robert HTONL_FP(&pp->xmt, &ip->xmt); 927c0b746e5SOllivier Robert j = pp->filter_nextpt - 1; 928c0b746e5SOllivier Robert for (i = 0; i < NTP_SHIFT; i++, j--) { 929c0b746e5SOllivier Robert if (j < 0) 930c0b746e5SOllivier Robert j = NTP_SHIFT-1; 931c0b746e5SOllivier Robert ip->filtdelay[i] = HTONS_FP(DTOFP(pp->filter_delay[j])); 932c0b746e5SOllivier Robert DTOLFP(pp->filter_offset[j], <mp); 933c0b746e5SOllivier Robert HTONL_FP(<mp, &ip->filtoffset[i]); 934*2b15cb3dSCy Schubert ip->order[i] = (u_char)((pp->filter_nextpt + 935*2b15cb3dSCy Schubert NTP_SHIFT - 1) - 936*2b15cb3dSCy Schubert pp->filter_order[i]); 937c0b746e5SOllivier Robert if (ip->order[i] >= NTP_SHIFT) 938c0b746e5SOllivier Robert ip->order[i] -= NTP_SHIFT; 939c0b746e5SOllivier Robert } 940c0b746e5SOllivier Robert DTOLFP(pp->offset, <mp); 941c0b746e5SOllivier Robert HTONL_FP(<mp, &ip->offset); 942c0b746e5SOllivier Robert ip->delay = HTONS_FP(DTOFP(pp->delay)); 943c0b746e5SOllivier Robert ip->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); 944224ba2bdSOllivier Robert ip->selectdisp = HTONS_FP(DTOUFP(SQRT(pp->jitter))); 945*2b15cb3dSCy Schubert ip = more_pkt(); 946c0b746e5SOllivier Robert } 947c0b746e5SOllivier Robert flush_pkt(); 948c0b746e5SOllivier Robert } 949c0b746e5SOllivier Robert 950c0b746e5SOllivier Robert 951c0b746e5SOllivier Robert /* 952c0b746e5SOllivier Robert * peer_stats - send statistics for one or more peers 953c0b746e5SOllivier Robert */ 954c0b746e5SOllivier Robert static void 955c0b746e5SOllivier Robert peer_stats ( 956*2b15cb3dSCy Schubert sockaddr_u *srcadr, 957*2b15cb3dSCy Schubert endpt *inter, 958c0b746e5SOllivier Robert struct req_pkt *inpkt 959c0b746e5SOllivier Robert ) 960c0b746e5SOllivier Robert { 961*2b15cb3dSCy Schubert u_short items; 962*2b15cb3dSCy Schubert size_t item_sz; 963*2b15cb3dSCy Schubert char * datap; 964*2b15cb3dSCy Schubert struct info_peer_list ipl; 965*2b15cb3dSCy Schubert struct peer * pp; 966*2b15cb3dSCy Schubert struct info_peer_stats *ip; 967*2b15cb3dSCy Schubert sockaddr_u addr; 968c0b746e5SOllivier Robert 969*2b15cb3dSCy Schubert DPRINTF(1, ("peer_stats: called\n")); 970c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 971*2b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 972*2b15cb3dSCy Schubert datap = inpkt->u.data; 973*2b15cb3dSCy Schubert if (item_sz > sizeof(ipl)) { 974*2b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 975*2b15cb3dSCy Schubert return; 9769c2daa00SOllivier Robert } 977*2b15cb3dSCy Schubert ip = prepare_pkt(srcadr, inter, inpkt, 978*2b15cb3dSCy Schubert v6sizeof(struct info_peer_stats)); 979*2b15cb3dSCy Schubert while (items-- > 0 && ip != NULL) { 980*2b15cb3dSCy Schubert ZERO(ipl); 981*2b15cb3dSCy Schubert memcpy(&ipl, datap, item_sz); 982*2b15cb3dSCy Schubert ZERO(addr); 983*2b15cb3dSCy Schubert NSRCPORT(&addr) = ipl.port; 984*2b15cb3dSCy Schubert if (client_v6_capable && ipl.v6_flag) { 985*2b15cb3dSCy Schubert AF(&addr) = AF_INET6; 986*2b15cb3dSCy Schubert SOCK_ADDR6(&addr) = ipl.addr6; 987*2b15cb3dSCy Schubert } else { 988*2b15cb3dSCy Schubert AF(&addr) = AF_INET; 989*2b15cb3dSCy Schubert NSRCADR(&addr) = ipl.addr; 990*2b15cb3dSCy Schubert } 991*2b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 992*2b15cb3dSCy Schubert addr.sa.sa_len = SOCKLEN(&addr); 9939c2daa00SOllivier Robert #endif 994*2b15cb3dSCy Schubert DPRINTF(1, ("peer_stats: looking for %s, %d, %d\n", 995*2b15cb3dSCy Schubert stoa(&addr), ipl.port, NSRCPORT(&addr))); 9969c2daa00SOllivier Robert 997*2b15cb3dSCy Schubert datap += item_sz; 998*2b15cb3dSCy Schubert 999*2b15cb3dSCy Schubert pp = findexistingpeer(&addr, NULL, NULL, -1, 0); 1000*2b15cb3dSCy Schubert if (NULL == pp) 1001c0b746e5SOllivier Robert continue; 1002ea906c41SOllivier Robert 1003*2b15cb3dSCy Schubert DPRINTF(1, ("peer_stats: found %s\n", stoa(&addr))); 1004*2b15cb3dSCy Schubert 1005*2b15cb3dSCy Schubert if (IS_IPV4(&pp->srcadr)) { 1006*2b15cb3dSCy Schubert if (pp->dstadr) { 1007*2b15cb3dSCy Schubert if (!pp->processed) 1008*2b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->sin); 1009*2b15cb3dSCy Schubert else { 1010*2b15cb3dSCy Schubert if (MDF_BCAST == pp->cast_flags) 1011*2b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->bcast); 1012*2b15cb3dSCy Schubert else if (pp->cast_flags) { 1013*2b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->sin); 1014*2b15cb3dSCy Schubert if (!ip->dstadr) 1015*2b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->bcast); 1016*2b15cb3dSCy Schubert } 1017*2b15cb3dSCy Schubert } 1018*2b15cb3dSCy Schubert } else 1019*2b15cb3dSCy Schubert ip->dstadr = 0; 1020*2b15cb3dSCy Schubert 1021*2b15cb3dSCy Schubert ip->srcadr = NSRCADR(&pp->srcadr); 10229c2daa00SOllivier Robert if (client_v6_capable) 10239c2daa00SOllivier Robert ip->v6_flag = 0; 10249c2daa00SOllivier Robert } else { 1025ea906c41SOllivier Robert if (pp->dstadr) 1026*2b15cb3dSCy Schubert ip->dstadr6 = 1027*2b15cb3dSCy Schubert (MDF_BCAST == pp->cast_flags) 1028*2b15cb3dSCy Schubert ? SOCK_ADDR6(&pp->dstadr->bcast) 1029*2b15cb3dSCy Schubert : SOCK_ADDR6(&pp->dstadr->sin); 1030ea906c41SOllivier Robert else 1031*2b15cb3dSCy Schubert ZERO(ip->dstadr6); 1032ea906c41SOllivier Robert 1033*2b15cb3dSCy Schubert ip->srcadr6 = SOCK_ADDR6(&pp->srcadr); 10349c2daa00SOllivier Robert ip->v6_flag = 1; 10359c2daa00SOllivier Robert } 1036c0b746e5SOllivier Robert ip->srcport = NSRCPORT(&pp->srcadr); 1037c0b746e5SOllivier Robert ip->flags = 0; 1038c0b746e5SOllivier Robert if (pp == sys_peer) 1039c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 1040c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 1041c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 1042c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 1043c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_REFCLOCK; 1044c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 1045c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_PREFER; 1046c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 1047c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_BURST; 1048ea906c41SOllivier Robert if (pp->flags & FLAG_IBURST) 1049ea906c41SOllivier Robert ip->flags |= INFO_FLAG_IBURST; 1050c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 1051c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 1052c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 1053c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 1054ea906c41SOllivier Robert ip->flags = htons(ip->flags); 1055c0b746e5SOllivier Robert ip->timereceived = htonl((u_int32)(current_time - pp->timereceived)); 1056c0b746e5SOllivier Robert ip->timetosend = htonl(pp->nextdate - current_time); 1057c0b746e5SOllivier Robert ip->timereachable = htonl((u_int32)(current_time - pp->timereachable)); 1058c0b746e5SOllivier Robert ip->sent = htonl((u_int32)(pp->sent)); 1059c0b746e5SOllivier Robert ip->processed = htonl((u_int32)(pp->processed)); 1060c0b746e5SOllivier Robert ip->badauth = htonl((u_int32)(pp->badauth)); 1061c0b746e5SOllivier Robert ip->bogusorg = htonl((u_int32)(pp->bogusorg)); 1062c0b746e5SOllivier Robert ip->oldpkt = htonl((u_int32)(pp->oldpkt)); 1063c0b746e5SOllivier Robert ip->seldisp = htonl((u_int32)(pp->seldisptoolarge)); 1064c0b746e5SOllivier Robert ip->selbroken = htonl((u_int32)(pp->selbroken)); 1065c0b746e5SOllivier Robert ip->candidate = pp->status; 1066c0b746e5SOllivier Robert ip = (struct info_peer_stats *)more_pkt(); 1067c0b746e5SOllivier Robert } 1068c0b746e5SOllivier Robert flush_pkt(); 1069c0b746e5SOllivier Robert } 1070c0b746e5SOllivier Robert 1071c0b746e5SOllivier Robert 1072c0b746e5SOllivier Robert /* 1073c0b746e5SOllivier Robert * sys_info - return system info 1074c0b746e5SOllivier Robert */ 1075c0b746e5SOllivier Robert static void 1076c0b746e5SOllivier Robert sys_info( 1077*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1078*2b15cb3dSCy Schubert endpt *inter, 1079c0b746e5SOllivier Robert struct req_pkt *inpkt 1080c0b746e5SOllivier Robert ) 1081c0b746e5SOllivier Robert { 1082c0b746e5SOllivier Robert register struct info_sys *is; 1083c0b746e5SOllivier Robert 1084c0b746e5SOllivier Robert is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt, 10859c2daa00SOllivier Robert v6sizeof(struct info_sys)); 1086c0b746e5SOllivier Robert 1087*2b15cb3dSCy Schubert if (sys_peer) { 1088*2b15cb3dSCy Schubert if (IS_IPV4(&sys_peer->srcadr)) { 1089*2b15cb3dSCy Schubert is->peer = NSRCADR(&sys_peer->srcadr); 10909c2daa00SOllivier Robert if (client_v6_capable) 10919c2daa00SOllivier Robert is->v6_flag = 0; 10929c2daa00SOllivier Robert } else if (client_v6_capable) { 1093*2b15cb3dSCy Schubert is->peer6 = SOCK_ADDR6(&sys_peer->srcadr); 10949c2daa00SOllivier Robert is->v6_flag = 1; 10959c2daa00SOllivier Robert } 1096c0b746e5SOllivier Robert is->peer_mode = sys_peer->hmode; 1097c0b746e5SOllivier Robert } else { 1098c0b746e5SOllivier Robert is->peer = 0; 10999c2daa00SOllivier Robert if (client_v6_capable) { 11009c2daa00SOllivier Robert is->v6_flag = 0; 11019c2daa00SOllivier Robert } 1102c0b746e5SOllivier Robert is->peer_mode = 0; 1103c0b746e5SOllivier Robert } 11049c2daa00SOllivier Robert 1105c0b746e5SOllivier Robert is->leap = sys_leap; 1106c0b746e5SOllivier Robert is->stratum = sys_stratum; 1107c0b746e5SOllivier Robert is->precision = sys_precision; 1108c0b746e5SOllivier Robert is->rootdelay = htonl(DTOFP(sys_rootdelay)); 1109*2b15cb3dSCy Schubert is->rootdispersion = htonl(DTOUFP(sys_rootdisp)); 1110224ba2bdSOllivier Robert is->frequency = htonl(DTOFP(sys_jitter)); 1111*2b15cb3dSCy Schubert is->stability = htonl(DTOUFP(clock_stability * 1e6)); 1112c0b746e5SOllivier Robert is->refid = sys_refid; 1113c0b746e5SOllivier Robert HTONL_FP(&sys_reftime, &is->reftime); 1114c0b746e5SOllivier Robert 1115c0b746e5SOllivier Robert is->poll = sys_poll; 1116c0b746e5SOllivier Robert 1117c0b746e5SOllivier Robert is->flags = 0; 1118c0b746e5SOllivier Robert if (sys_authenticate) 1119c0b746e5SOllivier Robert is->flags |= INFO_FLAG_AUTHENTICATE; 1120ce265a54SOllivier Robert if (sys_bclient) 1121ce265a54SOllivier Robert is->flags |= INFO_FLAG_BCLIENT; 1122ce265a54SOllivier Robert #ifdef REFCLOCK 1123ce265a54SOllivier Robert if (cal_enable) 1124ce265a54SOllivier Robert is->flags |= INFO_FLAG_CAL; 1125ce265a54SOllivier Robert #endif /* REFCLOCK */ 1126c0b746e5SOllivier Robert if (kern_enable) 1127c0b746e5SOllivier Robert is->flags |= INFO_FLAG_KERNEL; 1128c0b746e5SOllivier Robert if (mon_enabled != MON_OFF) 1129c0b746e5SOllivier Robert is->flags |= INFO_FLAG_MONITOR; 1130ce265a54SOllivier Robert if (ntp_enable) 1131ce265a54SOllivier Robert is->flags |= INFO_FLAG_NTP; 1132*2b15cb3dSCy Schubert if (hardpps_enable) 1133ce265a54SOllivier Robert is->flags |= INFO_FLAG_PPS_SYNC; 1134c0b746e5SOllivier Robert if (stats_control) 1135c0b746e5SOllivier Robert is->flags |= INFO_FLAG_FILEGEN; 1136c0b746e5SOllivier Robert is->bdelay = HTONS_FP(DTOFP(sys_bdelay)); 1137*2b15cb3dSCy Schubert HTONL_UF(sys_authdelay.l_uf, &is->authdelay); 1138c0b746e5SOllivier Robert (void) more_pkt(); 1139c0b746e5SOllivier Robert flush_pkt(); 1140c0b746e5SOllivier Robert } 1141c0b746e5SOllivier Robert 1142c0b746e5SOllivier Robert 1143c0b746e5SOllivier Robert /* 1144c0b746e5SOllivier Robert * sys_stats - return system statistics 1145c0b746e5SOllivier Robert */ 1146c0b746e5SOllivier Robert static void 1147c0b746e5SOllivier Robert sys_stats( 1148*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1149*2b15cb3dSCy Schubert endpt *inter, 1150c0b746e5SOllivier Robert struct req_pkt *inpkt 1151c0b746e5SOllivier Robert ) 1152c0b746e5SOllivier Robert { 1153c0b746e5SOllivier Robert register struct info_sys_stats *ss; 1154c0b746e5SOllivier Robert 1155c0b746e5SOllivier Robert ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt, 1156c0b746e5SOllivier Robert sizeof(struct info_sys_stats)); 1157c0b746e5SOllivier Robert ss->timeup = htonl((u_int32)current_time); 1158c0b746e5SOllivier Robert ss->timereset = htonl((u_int32)(current_time - sys_stattime)); 11599c2daa00SOllivier Robert ss->denied = htonl((u_int32)sys_restricted); 1160*2b15cb3dSCy Schubert ss->oldversionpkt = htonl((u_int32)sys_oldversion); 1161*2b15cb3dSCy Schubert ss->newversionpkt = htonl((u_int32)sys_newversion); 1162*2b15cb3dSCy Schubert ss->unknownversion = htonl((u_int32)sys_declined); 1163c0b746e5SOllivier Robert ss->badlength = htonl((u_int32)sys_badlength); 1164c0b746e5SOllivier Robert ss->processed = htonl((u_int32)sys_processed); 1165c0b746e5SOllivier Robert ss->badauth = htonl((u_int32)sys_badauth); 1166c0b746e5SOllivier Robert ss->limitrejected = htonl((u_int32)sys_limitrejected); 11679c2daa00SOllivier Robert ss->received = htonl((u_int32)sys_received); 1168c0b746e5SOllivier Robert (void) more_pkt(); 1169c0b746e5SOllivier Robert flush_pkt(); 1170c0b746e5SOllivier Robert } 1171c0b746e5SOllivier Robert 1172c0b746e5SOllivier Robert 1173c0b746e5SOllivier Robert /* 1174c0b746e5SOllivier Robert * mem_stats - return memory statistics 1175c0b746e5SOllivier Robert */ 1176c0b746e5SOllivier Robert static void 1177c0b746e5SOllivier Robert mem_stats( 1178*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1179*2b15cb3dSCy Schubert endpt *inter, 1180c0b746e5SOllivier Robert struct req_pkt *inpkt 1181c0b746e5SOllivier Robert ) 1182c0b746e5SOllivier Robert { 1183c0b746e5SOllivier Robert register struct info_mem_stats *ms; 1184c0b746e5SOllivier Robert register int i; 1185c0b746e5SOllivier Robert 1186c0b746e5SOllivier Robert ms = (struct info_mem_stats *)prepare_pkt(srcadr, inter, inpkt, 1187c0b746e5SOllivier Robert sizeof(struct info_mem_stats)); 1188c0b746e5SOllivier Robert 1189c0b746e5SOllivier Robert ms->timereset = htonl((u_int32)(current_time - peer_timereset)); 1190c0b746e5SOllivier Robert ms->totalpeermem = htons((u_short)total_peer_structs); 1191c0b746e5SOllivier Robert ms->freepeermem = htons((u_short)peer_free_count); 1192c0b746e5SOllivier Robert ms->findpeer_calls = htonl((u_int32)findpeer_calls); 1193c0b746e5SOllivier Robert ms->allocations = htonl((u_int32)peer_allocations); 1194c0b746e5SOllivier Robert ms->demobilizations = htonl((u_int32)peer_demobilizations); 1195c0b746e5SOllivier Robert 1196*2b15cb3dSCy Schubert for (i = 0; i < NTP_HASH_SIZE; i++) 1197*2b15cb3dSCy Schubert ms->hashcount[i] = (u_char) 1198*2b15cb3dSCy Schubert max((u_int)peer_hash_count[i], UCHAR_MAX); 1199c0b746e5SOllivier Robert 1200*2b15cb3dSCy Schubert more_pkt(); 1201c0b746e5SOllivier Robert flush_pkt(); 1202c0b746e5SOllivier Robert } 1203c0b746e5SOllivier Robert 1204c0b746e5SOllivier Robert 1205c0b746e5SOllivier Robert /* 1206c0b746e5SOllivier Robert * io_stats - return io statistics 1207c0b746e5SOllivier Robert */ 1208c0b746e5SOllivier Robert static void 1209c0b746e5SOllivier Robert io_stats( 1210*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1211*2b15cb3dSCy Schubert endpt *inter, 1212c0b746e5SOllivier Robert struct req_pkt *inpkt 1213c0b746e5SOllivier Robert ) 1214c0b746e5SOllivier Robert { 1215*2b15cb3dSCy Schubert struct info_io_stats *io; 1216c0b746e5SOllivier Robert 1217c0b746e5SOllivier Robert io = (struct info_io_stats *)prepare_pkt(srcadr, inter, inpkt, 1218c0b746e5SOllivier Robert sizeof(struct info_io_stats)); 1219c0b746e5SOllivier Robert 1220c0b746e5SOllivier Robert io->timereset = htonl((u_int32)(current_time - io_timereset)); 1221c0b746e5SOllivier Robert io->totalrecvbufs = htons((u_short) total_recvbuffs()); 1222c0b746e5SOllivier Robert io->freerecvbufs = htons((u_short) free_recvbuffs()); 1223c0b746e5SOllivier Robert io->fullrecvbufs = htons((u_short) full_recvbuffs()); 1224c0b746e5SOllivier Robert io->lowwater = htons((u_short) lowater_additions()); 1225c0b746e5SOllivier Robert io->dropped = htonl((u_int32)packets_dropped); 1226c0b746e5SOllivier Robert io->ignored = htonl((u_int32)packets_ignored); 1227c0b746e5SOllivier Robert io->received = htonl((u_int32)packets_received); 1228c0b746e5SOllivier Robert io->sent = htonl((u_int32)packets_sent); 1229c0b746e5SOllivier Robert io->notsent = htonl((u_int32)packets_notsent); 1230c0b746e5SOllivier Robert io->interrupts = htonl((u_int32)handler_calls); 1231c0b746e5SOllivier Robert io->int_received = htonl((u_int32)handler_pkts); 1232c0b746e5SOllivier Robert 1233c0b746e5SOllivier Robert (void) more_pkt(); 1234c0b746e5SOllivier Robert flush_pkt(); 1235c0b746e5SOllivier Robert } 1236c0b746e5SOllivier Robert 1237c0b746e5SOllivier Robert 1238c0b746e5SOllivier Robert /* 1239c0b746e5SOllivier Robert * timer_stats - return timer statistics 1240c0b746e5SOllivier Robert */ 1241c0b746e5SOllivier Robert static void 1242c0b746e5SOllivier Robert timer_stats( 1243*2b15cb3dSCy Schubert sockaddr_u * srcadr, 1244*2b15cb3dSCy Schubert endpt * inter, 1245c0b746e5SOllivier Robert struct req_pkt * inpkt 1246c0b746e5SOllivier Robert ) 1247c0b746e5SOllivier Robert { 1248*2b15cb3dSCy Schubert struct info_timer_stats * ts; 1249*2b15cb3dSCy Schubert u_long sincereset; 1250c0b746e5SOllivier Robert 1251*2b15cb3dSCy Schubert ts = (struct info_timer_stats *)prepare_pkt(srcadr, inter, 1252*2b15cb3dSCy Schubert inpkt, sizeof(*ts)); 1253c0b746e5SOllivier Robert 1254*2b15cb3dSCy Schubert sincereset = current_time - timer_timereset; 1255*2b15cb3dSCy Schubert ts->timereset = htonl((u_int32)sincereset); 1256*2b15cb3dSCy Schubert ts->alarms = ts->timereset; 1257*2b15cb3dSCy Schubert ts->overflows = htonl((u_int32)alarm_overflow); 1258c0b746e5SOllivier Robert ts->xmtcalls = htonl((u_int32)timer_xmtcalls); 1259c0b746e5SOllivier Robert 1260c0b746e5SOllivier Robert (void) more_pkt(); 1261c0b746e5SOllivier Robert flush_pkt(); 1262c0b746e5SOllivier Robert } 1263c0b746e5SOllivier Robert 1264c0b746e5SOllivier Robert 1265c0b746e5SOllivier Robert /* 1266c0b746e5SOllivier Robert * loop_info - return the current state of the loop filter 1267c0b746e5SOllivier Robert */ 1268c0b746e5SOllivier Robert static void 1269c0b746e5SOllivier Robert loop_info( 1270*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1271*2b15cb3dSCy Schubert endpt *inter, 1272c0b746e5SOllivier Robert struct req_pkt *inpkt 1273c0b746e5SOllivier Robert ) 1274c0b746e5SOllivier Robert { 1275*2b15cb3dSCy Schubert struct info_loop *li; 1276c0b746e5SOllivier Robert l_fp ltmp; 1277c0b746e5SOllivier Robert 1278c0b746e5SOllivier Robert li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt, 1279c0b746e5SOllivier Robert sizeof(struct info_loop)); 1280c0b746e5SOllivier Robert 1281c0b746e5SOllivier Robert DTOLFP(last_offset, <mp); 1282c0b746e5SOllivier Robert HTONL_FP(<mp, &li->last_offset); 1283c0b746e5SOllivier Robert DTOLFP(drift_comp * 1e6, <mp); 1284c0b746e5SOllivier Robert HTONL_FP(<mp, &li->drift_comp); 1285c0b746e5SOllivier Robert li->compliance = htonl((u_int32)(tc_counter)); 1286*2b15cb3dSCy Schubert li->watchdog_timer = htonl((u_int32)(current_time - sys_epoch)); 1287c0b746e5SOllivier Robert 1288*2b15cb3dSCy Schubert more_pkt(); 1289c0b746e5SOllivier Robert flush_pkt(); 1290c0b746e5SOllivier Robert } 1291c0b746e5SOllivier Robert 1292c0b746e5SOllivier Robert 1293c0b746e5SOllivier Robert /* 1294c0b746e5SOllivier Robert * do_conf - add a peer to the configuration list 1295c0b746e5SOllivier Robert */ 1296c0b746e5SOllivier Robert static void 1297c0b746e5SOllivier Robert do_conf( 1298*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1299*2b15cb3dSCy Schubert endpt *inter, 1300c0b746e5SOllivier Robert struct req_pkt *inpkt 1301c0b746e5SOllivier Robert ) 1302c0b746e5SOllivier Robert { 1303*2b15cb3dSCy Schubert u_short items; 1304*2b15cb3dSCy Schubert size_t item_sz; 1305224ba2bdSOllivier Robert u_int fl; 1306*2b15cb3dSCy Schubert char * datap; 13079c2daa00SOllivier Robert struct conf_peer temp_cp; 1308*2b15cb3dSCy Schubert sockaddr_u peeraddr; 1309c0b746e5SOllivier Robert 1310c0b746e5SOllivier Robert /* 1311c0b746e5SOllivier Robert * Do a check of everything to see that it looks 1312c0b746e5SOllivier Robert * okay. If not, complain about it. Note we are 1313c0b746e5SOllivier Robert * very picky here. 1314c0b746e5SOllivier Robert */ 1315c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1316*2b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 1317*2b15cb3dSCy Schubert datap = inpkt->u.data; 1318*2b15cb3dSCy Schubert if (item_sz > sizeof(temp_cp)) { 1319c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1320c0b746e5SOllivier Robert return; 1321c0b746e5SOllivier Robert } 1322c0b746e5SOllivier Robert 13239c2daa00SOllivier Robert while (items-- > 0) { 1324*2b15cb3dSCy Schubert ZERO(temp_cp); 1325*2b15cb3dSCy Schubert memcpy(&temp_cp, datap, item_sz); 1326*2b15cb3dSCy Schubert ZERO_SOCK(&peeraddr); 13279c2daa00SOllivier Robert 13289c2daa00SOllivier Robert fl = 0; 13299c2daa00SOllivier Robert if (temp_cp.flags & CONF_FLAG_PREFER) 13309c2daa00SOllivier Robert fl |= FLAG_PREFER; 13319c2daa00SOllivier Robert if (temp_cp.flags & CONF_FLAG_BURST) 13329c2daa00SOllivier Robert fl |= FLAG_BURST; 1333ea906c41SOllivier Robert if (temp_cp.flags & CONF_FLAG_IBURST) 1334ea906c41SOllivier Robert fl |= FLAG_IBURST; 1335*2b15cb3dSCy Schubert #ifdef AUTOKEY 13369c2daa00SOllivier Robert if (temp_cp.flags & CONF_FLAG_SKEY) 13379c2daa00SOllivier Robert fl |= FLAG_SKEY; 1338*2b15cb3dSCy Schubert #endif /* AUTOKEY */ 1339*2b15cb3dSCy Schubert if (client_v6_capable && temp_cp.v6_flag) { 1340*2b15cb3dSCy Schubert AF(&peeraddr) = AF_INET6; 1341*2b15cb3dSCy Schubert SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6; 13429c2daa00SOllivier Robert } else { 1343*2b15cb3dSCy Schubert AF(&peeraddr) = AF_INET; 1344*2b15cb3dSCy Schubert NSRCADR(&peeraddr) = temp_cp.peeraddr; 1345c0b746e5SOllivier Robert /* 1346c0b746e5SOllivier Robert * Make sure the address is valid 1347c0b746e5SOllivier Robert */ 1348*2b15cb3dSCy Schubert if (!ISREFCLOCKADR(&peeraddr) && 1349*2b15cb3dSCy Schubert ISBADADR(&peeraddr)) { 1350c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1351c0b746e5SOllivier Robert return; 1352c0b746e5SOllivier Robert } 1353c0b746e5SOllivier Robert 13549c2daa00SOllivier Robert } 13559c2daa00SOllivier Robert NSRCPORT(&peeraddr) = htons(NTP_PORT); 1356*2b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 1357*2b15cb3dSCy Schubert peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 13589c2daa00SOllivier Robert #endif 13599c2daa00SOllivier Robert 1360c0b746e5SOllivier Robert /* XXX W2DO? minpoll/maxpoll arguments ??? */ 1361*2b15cb3dSCy Schubert if (peer_config(&peeraddr, NULL, NULL, 13629c2daa00SOllivier Robert temp_cp.hmode, temp_cp.version, temp_cp.minpoll, 13639c2daa00SOllivier Robert temp_cp.maxpoll, fl, temp_cp.ttl, temp_cp.keyid, 13649c2daa00SOllivier Robert NULL) == 0) { 1365c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1366c0b746e5SOllivier Robert return; 1367c0b746e5SOllivier Robert } 1368eb6d21b4SOllivier Robert 1369*2b15cb3dSCy Schubert datap += item_sz; 1370eb6d21b4SOllivier Robert } 1371c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1372c0b746e5SOllivier Robert } 1373c0b746e5SOllivier Robert 1374224ba2bdSOllivier Robert 1375224ba2bdSOllivier Robert /* 1376c0b746e5SOllivier Robert * do_unconf - remove a peer from the configuration list 1377c0b746e5SOllivier Robert */ 1378c0b746e5SOllivier Robert static void 1379c0b746e5SOllivier Robert do_unconf( 1380*2b15cb3dSCy Schubert sockaddr_u * srcadr, 1381*2b15cb3dSCy Schubert endpt * inter, 1382c0b746e5SOllivier Robert struct req_pkt *inpkt 1383c0b746e5SOllivier Robert ) 1384c0b746e5SOllivier Robert { 1385*2b15cb3dSCy Schubert u_short items; 1386*2b15cb3dSCy Schubert size_t item_sz; 1387*2b15cb3dSCy Schubert char * datap; 13889c2daa00SOllivier Robert struct conf_unpeer temp_cp; 1389*2b15cb3dSCy Schubert struct peer * p; 1390*2b15cb3dSCy Schubert sockaddr_u peeraddr; 1391*2b15cb3dSCy Schubert int bad; 1392*2b15cb3dSCy Schubert int found; 1393c0b746e5SOllivier Robert 1394c0b746e5SOllivier Robert /* 1395c0b746e5SOllivier Robert * This is a bit unstructured, but I like to be careful. 1396c0b746e5SOllivier Robert * We check to see that every peer exists and is actually 1397c0b746e5SOllivier Robert * configured. If so, we remove them. If not, we return 1398c0b746e5SOllivier Robert * an error. 1399c0b746e5SOllivier Robert */ 1400c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1401*2b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 1402*2b15cb3dSCy Schubert datap = inpkt->u.data; 1403*2b15cb3dSCy Schubert if (item_sz > sizeof(temp_cp)) { 1404*2b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1405*2b15cb3dSCy Schubert return; 14069c2daa00SOllivier Robert } 1407*2b15cb3dSCy Schubert 1408*2b15cb3dSCy Schubert bad = FALSE; 1409*2b15cb3dSCy Schubert while (items-- > 0 && !bad) { 1410*2b15cb3dSCy Schubert ZERO(temp_cp); 1411*2b15cb3dSCy Schubert memcpy(&temp_cp, datap, item_sz); 1412*2b15cb3dSCy Schubert ZERO_SOCK(&peeraddr); 1413*2b15cb3dSCy Schubert if (client_v6_capable && temp_cp.v6_flag) { 1414*2b15cb3dSCy Schubert AF(&peeraddr) = AF_INET6; 1415*2b15cb3dSCy Schubert SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6; 1416*2b15cb3dSCy Schubert } else { 1417*2b15cb3dSCy Schubert AF(&peeraddr) = AF_INET; 1418*2b15cb3dSCy Schubert NSRCADR(&peeraddr) = temp_cp.peeraddr; 1419*2b15cb3dSCy Schubert } 1420*2b15cb3dSCy Schubert SET_PORT(&peeraddr, NTP_PORT); 1421*2b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 1422*2b15cb3dSCy Schubert peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 14239c2daa00SOllivier Robert #endif 1424*2b15cb3dSCy Schubert found = FALSE; 1425*2b15cb3dSCy Schubert p = NULL; 1426*2b15cb3dSCy Schubert 1427*2b15cb3dSCy Schubert DPRINTF(1, ("searching for %s\n", stoa(&peeraddr))); 1428*2b15cb3dSCy Schubert 1429c0b746e5SOllivier Robert while (!found) { 1430*2b15cb3dSCy Schubert p = findexistingpeer(&peeraddr, NULL, p, -1, 0); 1431*2b15cb3dSCy Schubert if (NULL == p) 1432c0b746e5SOllivier Robert break; 1433*2b15cb3dSCy Schubert if (FLAG_CONFIG & p->flags) 1434*2b15cb3dSCy Schubert found = TRUE; 1435c0b746e5SOllivier Robert } 1436c0b746e5SOllivier Robert if (!found) 1437*2b15cb3dSCy Schubert bad = TRUE; 1438*2b15cb3dSCy Schubert 1439*2b15cb3dSCy Schubert datap += item_sz; 1440c0b746e5SOllivier Robert } 1441c0b746e5SOllivier Robert 1442c0b746e5SOllivier Robert if (bad) { 1443c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1444c0b746e5SOllivier Robert return; 1445c0b746e5SOllivier Robert } 1446c0b746e5SOllivier Robert 1447c0b746e5SOllivier Robert /* 1448c0b746e5SOllivier Robert * Now do it in earnest. 1449c0b746e5SOllivier Robert */ 1450c0b746e5SOllivier Robert 1451c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1452*2b15cb3dSCy Schubert datap = inpkt->u.data; 1453*2b15cb3dSCy Schubert 1454c0b746e5SOllivier Robert while (items-- > 0) { 1455*2b15cb3dSCy Schubert ZERO(temp_cp); 1456*2b15cb3dSCy Schubert memcpy(&temp_cp, datap, item_sz); 1457*2b15cb3dSCy Schubert ZERO(peeraddr); 1458*2b15cb3dSCy Schubert if (client_v6_capable && temp_cp.v6_flag) { 1459*2b15cb3dSCy Schubert AF(&peeraddr) = AF_INET6; 1460*2b15cb3dSCy Schubert SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6; 14619c2daa00SOllivier Robert } else { 1462*2b15cb3dSCy Schubert AF(&peeraddr) = AF_INET; 1463*2b15cb3dSCy Schubert NSRCADR(&peeraddr) = temp_cp.peeraddr; 14649c2daa00SOllivier Robert } 1465*2b15cb3dSCy Schubert SET_PORT(&peeraddr, NTP_PORT); 1466*2b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 1467*2b15cb3dSCy Schubert peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 14689c2daa00SOllivier Robert #endif 1469*2b15cb3dSCy Schubert found = FALSE; 1470*2b15cb3dSCy Schubert p = NULL; 1471*2b15cb3dSCy Schubert 1472*2b15cb3dSCy Schubert while (!found) { 1473*2b15cb3dSCy Schubert p = findexistingpeer(&peeraddr, NULL, p, -1, 0); 1474*2b15cb3dSCy Schubert if (NULL == p) 1475*2b15cb3dSCy Schubert break; 1476*2b15cb3dSCy Schubert if (FLAG_CONFIG & p->flags) 1477*2b15cb3dSCy Schubert found = TRUE; 1478*2b15cb3dSCy Schubert } 1479*2b15cb3dSCy Schubert INSIST(found); 1480*2b15cb3dSCy Schubert INSIST(NULL != p); 1481*2b15cb3dSCy Schubert 1482*2b15cb3dSCy Schubert peer_clear(p, "GONE"); 1483*2b15cb3dSCy Schubert unpeer(p); 1484*2b15cb3dSCy Schubert 1485*2b15cb3dSCy Schubert datap += item_sz; 1486c0b746e5SOllivier Robert } 1487c0b746e5SOllivier Robert 1488c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1489c0b746e5SOllivier Robert } 1490c0b746e5SOllivier Robert 1491c0b746e5SOllivier Robert 1492c0b746e5SOllivier Robert /* 1493c0b746e5SOllivier Robert * set_sys_flag - set system flags 1494c0b746e5SOllivier Robert */ 1495c0b746e5SOllivier Robert static void 1496c0b746e5SOllivier Robert set_sys_flag( 1497*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1498*2b15cb3dSCy Schubert endpt *inter, 1499c0b746e5SOllivier Robert struct req_pkt *inpkt 1500c0b746e5SOllivier Robert ) 1501c0b746e5SOllivier Robert { 1502c0b746e5SOllivier Robert setclr_flags(srcadr, inter, inpkt, 1); 1503c0b746e5SOllivier Robert } 1504c0b746e5SOllivier Robert 1505c0b746e5SOllivier Robert 1506c0b746e5SOllivier Robert /* 1507c0b746e5SOllivier Robert * clr_sys_flag - clear system flags 1508c0b746e5SOllivier Robert */ 1509c0b746e5SOllivier Robert static void 1510c0b746e5SOllivier Robert clr_sys_flag( 1511*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1512*2b15cb3dSCy Schubert endpt *inter, 1513c0b746e5SOllivier Robert struct req_pkt *inpkt 1514c0b746e5SOllivier Robert ) 1515c0b746e5SOllivier Robert { 1516c0b746e5SOllivier Robert setclr_flags(srcadr, inter, inpkt, 0); 1517c0b746e5SOllivier Robert } 1518c0b746e5SOllivier Robert 1519c0b746e5SOllivier Robert 1520c0b746e5SOllivier Robert /* 1521c0b746e5SOllivier Robert * setclr_flags - do the grunge work of flag setting/clearing 1522c0b746e5SOllivier Robert */ 1523c0b746e5SOllivier Robert static void 1524c0b746e5SOllivier Robert setclr_flags( 1525*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1526*2b15cb3dSCy Schubert endpt *inter, 1527c0b746e5SOllivier Robert struct req_pkt *inpkt, 1528c0b746e5SOllivier Robert u_long set 1529c0b746e5SOllivier Robert ) 1530c0b746e5SOllivier Robert { 1531*2b15cb3dSCy Schubert struct conf_sys_flags *sf; 1532*2b15cb3dSCy Schubert u_int32 flags; 1533c0b746e5SOllivier Robert 1534c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 1535224ba2bdSOllivier Robert msyslog(LOG_ERR, "setclr_flags: err_nitems > 1"); 1536c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1537c0b746e5SOllivier Robert return; 1538c0b746e5SOllivier Robert } 1539c0b746e5SOllivier Robert 1540*2b15cb3dSCy Schubert sf = (struct conf_sys_flags *)&inpkt->u; 1541*2b15cb3dSCy Schubert flags = ntohl(sf->flags); 1542c0b746e5SOllivier Robert 1543224ba2bdSOllivier Robert if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS | 1544c0b746e5SOllivier Robert SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR | 1545ce265a54SOllivier Robert SYS_FLAG_FILEGEN | SYS_FLAG_AUTH | SYS_FLAG_CAL)) { 1546224ba2bdSOllivier Robert msyslog(LOG_ERR, "setclr_flags: extra flags: %#x", 1547224ba2bdSOllivier Robert flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS | 1548224ba2bdSOllivier Robert SYS_FLAG_NTP | SYS_FLAG_KERNEL | 1549ce265a54SOllivier Robert SYS_FLAG_MONITOR | SYS_FLAG_FILEGEN | 1550ce265a54SOllivier Robert SYS_FLAG_AUTH | SYS_FLAG_CAL)); 1551c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1552c0b746e5SOllivier Robert return; 1553c0b746e5SOllivier Robert } 1554c0b746e5SOllivier Robert 1555c0b746e5SOllivier Robert if (flags & SYS_FLAG_BCLIENT) 15569c2daa00SOllivier Robert proto_config(PROTO_BROADCLIENT, set, 0., NULL); 1557224ba2bdSOllivier Robert if (flags & SYS_FLAG_PPS) 15589c2daa00SOllivier Robert proto_config(PROTO_PPS, set, 0., NULL); 1559c0b746e5SOllivier Robert if (flags & SYS_FLAG_NTP) 15609c2daa00SOllivier Robert proto_config(PROTO_NTP, set, 0., NULL); 1561c0b746e5SOllivier Robert if (flags & SYS_FLAG_KERNEL) 15629c2daa00SOllivier Robert proto_config(PROTO_KERNEL, set, 0., NULL); 1563c0b746e5SOllivier Robert if (flags & SYS_FLAG_MONITOR) 15649c2daa00SOllivier Robert proto_config(PROTO_MONITOR, set, 0., NULL); 1565c0b746e5SOllivier Robert if (flags & SYS_FLAG_FILEGEN) 15669c2daa00SOllivier Robert proto_config(PROTO_FILEGEN, set, 0., NULL); 1567ce265a54SOllivier Robert if (flags & SYS_FLAG_AUTH) 15689c2daa00SOllivier Robert proto_config(PROTO_AUTHENTICATE, set, 0., NULL); 1569ce265a54SOllivier Robert if (flags & SYS_FLAG_CAL) 15709c2daa00SOllivier Robert proto_config(PROTO_CAL, set, 0., NULL); 1571c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1572*2b15cb3dSCy Schubert } 1573ea906c41SOllivier Robert 1574*2b15cb3dSCy Schubert /* 1575*2b15cb3dSCy Schubert * list_restrict4 - recursive helper for list_restrict dumps IPv4 1576*2b15cb3dSCy Schubert * restriction list in reverse order. 1577*2b15cb3dSCy Schubert */ 1578*2b15cb3dSCy Schubert static void 1579*2b15cb3dSCy Schubert list_restrict4( 1580*2b15cb3dSCy Schubert restrict_u * res, 1581*2b15cb3dSCy Schubert struct info_restrict ** ppir 1582*2b15cb3dSCy Schubert ) 1583*2b15cb3dSCy Schubert { 1584*2b15cb3dSCy Schubert struct info_restrict * pir; 1585*2b15cb3dSCy Schubert 1586*2b15cb3dSCy Schubert if (res->link != NULL) 1587*2b15cb3dSCy Schubert list_restrict4(res->link, ppir); 1588*2b15cb3dSCy Schubert 1589*2b15cb3dSCy Schubert pir = *ppir; 1590*2b15cb3dSCy Schubert pir->addr = htonl(res->u.v4.addr); 1591*2b15cb3dSCy Schubert if (client_v6_capable) 1592*2b15cb3dSCy Schubert pir->v6_flag = 0; 1593*2b15cb3dSCy Schubert pir->mask = htonl(res->u.v4.mask); 1594*2b15cb3dSCy Schubert pir->count = htonl(res->count); 1595*2b15cb3dSCy Schubert pir->flags = htons(res->flags); 1596*2b15cb3dSCy Schubert pir->mflags = htons(res->mflags); 1597*2b15cb3dSCy Schubert *ppir = (struct info_restrict *)more_pkt(); 1598*2b15cb3dSCy Schubert } 1599*2b15cb3dSCy Schubert 1600*2b15cb3dSCy Schubert 1601*2b15cb3dSCy Schubert /* 1602*2b15cb3dSCy Schubert * list_restrict6 - recursive helper for list_restrict dumps IPv6 1603*2b15cb3dSCy Schubert * restriction list in reverse order. 1604*2b15cb3dSCy Schubert */ 1605*2b15cb3dSCy Schubert static void 1606*2b15cb3dSCy Schubert list_restrict6( 1607*2b15cb3dSCy Schubert restrict_u * res, 1608*2b15cb3dSCy Schubert struct info_restrict ** ppir 1609*2b15cb3dSCy Schubert ) 1610*2b15cb3dSCy Schubert { 1611*2b15cb3dSCy Schubert struct info_restrict * pir; 1612*2b15cb3dSCy Schubert 1613*2b15cb3dSCy Schubert if (res->link != NULL) 1614*2b15cb3dSCy Schubert list_restrict6(res->link, ppir); 1615*2b15cb3dSCy Schubert 1616*2b15cb3dSCy Schubert pir = *ppir; 1617*2b15cb3dSCy Schubert pir->addr6 = res->u.v6.addr; 1618*2b15cb3dSCy Schubert pir->mask6 = res->u.v6.mask; 1619*2b15cb3dSCy Schubert pir->v6_flag = 1; 1620*2b15cb3dSCy Schubert pir->count = htonl(res->count); 1621*2b15cb3dSCy Schubert pir->flags = htons(res->flags); 1622*2b15cb3dSCy Schubert pir->mflags = htons(res->mflags); 1623*2b15cb3dSCy Schubert *ppir = (struct info_restrict *)more_pkt(); 1624c0b746e5SOllivier Robert } 1625c0b746e5SOllivier Robert 1626c0b746e5SOllivier Robert 1627c0b746e5SOllivier Robert /* 1628c0b746e5SOllivier Robert * list_restrict - return the restrict list 1629c0b746e5SOllivier Robert */ 1630c0b746e5SOllivier Robert static void 1631c0b746e5SOllivier Robert list_restrict( 1632*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1633*2b15cb3dSCy Schubert endpt *inter, 1634c0b746e5SOllivier Robert struct req_pkt *inpkt 1635c0b746e5SOllivier Robert ) 1636c0b746e5SOllivier Robert { 1637*2b15cb3dSCy Schubert struct info_restrict *ir; 1638c0b746e5SOllivier Robert 1639*2b15cb3dSCy Schubert DPRINTF(3, ("wants restrict list summary\n")); 1640c0b746e5SOllivier Robert 1641c0b746e5SOllivier Robert ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt, 16429c2daa00SOllivier Robert v6sizeof(struct info_restrict)); 16439c2daa00SOllivier Robert 1644*2b15cb3dSCy Schubert /* 1645*2b15cb3dSCy Schubert * The restriction lists are kept sorted in the reverse order 1646*2b15cb3dSCy Schubert * than they were originally. To preserve the output semantics, 1647*2b15cb3dSCy Schubert * dump each list in reverse order. A recursive helper function 1648*2b15cb3dSCy Schubert * achieves that. 1649*2b15cb3dSCy Schubert */ 1650*2b15cb3dSCy Schubert list_restrict4(restrictlist4, &ir); 16519c2daa00SOllivier Robert if (client_v6_capable) 1652*2b15cb3dSCy Schubert list_restrict6(restrictlist6, &ir); 1653c0b746e5SOllivier Robert flush_pkt(); 1654c0b746e5SOllivier Robert } 1655c0b746e5SOllivier Robert 1656c0b746e5SOllivier Robert 1657c0b746e5SOllivier Robert /* 1658c0b746e5SOllivier Robert * do_resaddflags - add flags to a restrict entry (or create one) 1659c0b746e5SOllivier Robert */ 1660c0b746e5SOllivier Robert static void 1661c0b746e5SOllivier Robert do_resaddflags( 1662*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1663*2b15cb3dSCy Schubert endpt *inter, 1664c0b746e5SOllivier Robert struct req_pkt *inpkt 1665c0b746e5SOllivier Robert ) 1666c0b746e5SOllivier Robert { 1667c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_FLAGS); 1668c0b746e5SOllivier Robert } 1669c0b746e5SOllivier Robert 1670c0b746e5SOllivier Robert 1671c0b746e5SOllivier Robert 1672c0b746e5SOllivier Robert /* 1673c0b746e5SOllivier Robert * do_ressubflags - remove flags from a restrict entry 1674c0b746e5SOllivier Robert */ 1675c0b746e5SOllivier Robert static void 1676c0b746e5SOllivier Robert do_ressubflags( 1677*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1678*2b15cb3dSCy Schubert endpt *inter, 1679c0b746e5SOllivier Robert struct req_pkt *inpkt 1680c0b746e5SOllivier Robert ) 1681c0b746e5SOllivier Robert { 1682c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_UNFLAG); 1683c0b746e5SOllivier Robert } 1684c0b746e5SOllivier Robert 1685c0b746e5SOllivier Robert 1686c0b746e5SOllivier Robert /* 1687c0b746e5SOllivier Robert * do_unrestrict - remove a restrict entry from the list 1688c0b746e5SOllivier Robert */ 1689c0b746e5SOllivier Robert static void 1690c0b746e5SOllivier Robert do_unrestrict( 1691*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1692*2b15cb3dSCy Schubert endpt *inter, 1693c0b746e5SOllivier Robert struct req_pkt *inpkt 1694c0b746e5SOllivier Robert ) 1695c0b746e5SOllivier Robert { 1696c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_REMOVE); 1697c0b746e5SOllivier Robert } 1698c0b746e5SOllivier Robert 1699c0b746e5SOllivier Robert 1700c0b746e5SOllivier Robert /* 1701c0b746e5SOllivier Robert * do_restrict - do the dirty stuff of dealing with restrictions 1702c0b746e5SOllivier Robert */ 1703c0b746e5SOllivier Robert static void 1704c0b746e5SOllivier Robert do_restrict( 1705*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1706*2b15cb3dSCy Schubert endpt *inter, 1707c0b746e5SOllivier Robert struct req_pkt *inpkt, 1708c0b746e5SOllivier Robert int op 1709c0b746e5SOllivier Robert ) 1710c0b746e5SOllivier Robert { 1711*2b15cb3dSCy Schubert char * datap; 1712*2b15cb3dSCy Schubert struct conf_restrict cr; 1713*2b15cb3dSCy Schubert u_short items; 1714*2b15cb3dSCy Schubert size_t item_sz; 1715*2b15cb3dSCy Schubert sockaddr_u matchaddr; 1716*2b15cb3dSCy Schubert sockaddr_u matchmask; 1717c0b746e5SOllivier Robert int bad; 1718c0b746e5SOllivier Robert 1719c0b746e5SOllivier Robert /* 1720c0b746e5SOllivier Robert * Do a check of the flags to make sure that only 1721c0b746e5SOllivier Robert * the NTPPORT flag is set, if any. If not, complain 1722c0b746e5SOllivier Robert * about it. Note we are very picky here. 1723c0b746e5SOllivier Robert */ 1724c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1725*2b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 1726*2b15cb3dSCy Schubert datap = inpkt->u.data; 1727*2b15cb3dSCy Schubert if (item_sz > sizeof(cr)) { 1728*2b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1729*2b15cb3dSCy Schubert return; 1730*2b15cb3dSCy Schubert } 1731c0b746e5SOllivier Robert 1732*2b15cb3dSCy Schubert bad = FALSE; 1733c0b746e5SOllivier Robert while (items-- > 0 && !bad) { 1734*2b15cb3dSCy Schubert memcpy(&cr, datap, item_sz); 1735*2b15cb3dSCy Schubert cr.flags = ntohs(cr.flags); 1736*2b15cb3dSCy Schubert cr.mflags = ntohs(cr.mflags); 1737*2b15cb3dSCy Schubert if (~RESM_NTPONLY & cr.mflags) 1738224ba2bdSOllivier Robert bad |= 1; 1739*2b15cb3dSCy Schubert if (~RES_ALLFLAGS & cr.flags) 1740224ba2bdSOllivier Robert bad |= 2; 1741*2b15cb3dSCy Schubert if (INADDR_ANY != cr.mask) { 1742*2b15cb3dSCy Schubert if (client_v6_capable && cr.v6_flag) { 1743*2b15cb3dSCy Schubert if (IN6_IS_ADDR_UNSPECIFIED(&cr.addr6)) 1744224ba2bdSOllivier Robert bad |= 4; 1745*2b15cb3dSCy Schubert } else { 1746*2b15cb3dSCy Schubert if (INADDR_ANY == cr.addr) 17479c2daa00SOllivier Robert bad |= 8; 17489c2daa00SOllivier Robert } 1749*2b15cb3dSCy Schubert } 1750*2b15cb3dSCy Schubert datap += item_sz; 1751c0b746e5SOllivier Robert } 1752c0b746e5SOllivier Robert 1753c0b746e5SOllivier Robert if (bad) { 1754224ba2bdSOllivier Robert msyslog(LOG_ERR, "do_restrict: bad = %#x", bad); 1755c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1756c0b746e5SOllivier Robert return; 1757c0b746e5SOllivier Robert } 1758c0b746e5SOllivier Robert 1759c0b746e5SOllivier Robert /* 1760c0b746e5SOllivier Robert * Looks okay, try it out 1761c0b746e5SOllivier Robert */ 1762*2b15cb3dSCy Schubert ZERO_SOCK(&matchaddr); 1763*2b15cb3dSCy Schubert ZERO_SOCK(&matchmask); 1764*2b15cb3dSCy Schubert datap = inpkt->u.data; 1765c0b746e5SOllivier Robert 1766c0b746e5SOllivier Robert while (items-- > 0) { 1767*2b15cb3dSCy Schubert memcpy(&cr, datap, item_sz); 1768*2b15cb3dSCy Schubert cr.flags = ntohs(cr.flags); 1769*2b15cb3dSCy Schubert cr.mflags = ntohs(cr.mflags); 1770*2b15cb3dSCy Schubert if (client_v6_capable && cr.v6_flag) { 1771*2b15cb3dSCy Schubert AF(&matchaddr) = AF_INET6; 1772*2b15cb3dSCy Schubert AF(&matchmask) = AF_INET6; 1773*2b15cb3dSCy Schubert SOCK_ADDR6(&matchaddr) = cr.addr6; 1774*2b15cb3dSCy Schubert SOCK_ADDR6(&matchmask) = cr.mask6; 17759c2daa00SOllivier Robert } else { 1776*2b15cb3dSCy Schubert AF(&matchaddr) = AF_INET; 1777*2b15cb3dSCy Schubert AF(&matchmask) = AF_INET; 1778*2b15cb3dSCy Schubert NSRCADR(&matchaddr) = cr.addr; 1779*2b15cb3dSCy Schubert NSRCADR(&matchmask) = cr.mask; 17809c2daa00SOllivier Robert } 1781*2b15cb3dSCy Schubert hack_restrict(op, &matchaddr, &matchmask, cr.mflags, 1782*2b15cb3dSCy Schubert cr.flags, 0); 1783*2b15cb3dSCy Schubert datap += item_sz; 1784c0b746e5SOllivier Robert } 1785c0b746e5SOllivier Robert 1786c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1787c0b746e5SOllivier Robert } 1788c0b746e5SOllivier Robert 1789c0b746e5SOllivier Robert 1790c0b746e5SOllivier Robert /* 1791c0b746e5SOllivier Robert * mon_getlist - return monitor data 1792c0b746e5SOllivier Robert */ 1793c0b746e5SOllivier Robert static void 1794*2b15cb3dSCy Schubert mon_getlist( 1795*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1796*2b15cb3dSCy Schubert endpt *inter, 1797c0b746e5SOllivier Robert struct req_pkt *inpkt 1798c0b746e5SOllivier Robert ) 1799c0b746e5SOllivier Robert { 1800*2b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1801c0b746e5SOllivier Robert } 1802c0b746e5SOllivier Robert 1803c0b746e5SOllivier Robert 1804c0b746e5SOllivier Robert /* 1805c0b746e5SOllivier Robert * Module entry points and the flags they correspond with 1806c0b746e5SOllivier Robert */ 1807c0b746e5SOllivier Robert struct reset_entry { 1808c0b746e5SOllivier Robert int flag; /* flag this corresponds to */ 1809*2b15cb3dSCy Schubert void (*handler)(void); /* routine to handle request */ 1810c0b746e5SOllivier Robert }; 1811c0b746e5SOllivier Robert 1812c0b746e5SOllivier Robert struct reset_entry reset_entries[] = { 1813c0b746e5SOllivier Robert { RESET_FLAG_ALLPEERS, peer_all_reset }, 1814c0b746e5SOllivier Robert { RESET_FLAG_IO, io_clr_stats }, 1815c0b746e5SOllivier Robert { RESET_FLAG_SYS, proto_clr_stats }, 1816c0b746e5SOllivier Robert { RESET_FLAG_MEM, peer_clr_stats }, 1817c0b746e5SOllivier Robert { RESET_FLAG_TIMER, timer_clr_stats }, 1818c0b746e5SOllivier Robert { RESET_FLAG_AUTH, reset_auth_stats }, 1819c0b746e5SOllivier Robert { RESET_FLAG_CTL, ctl_clr_stats }, 1820c0b746e5SOllivier Robert { 0, 0 } 1821c0b746e5SOllivier Robert }; 1822c0b746e5SOllivier Robert 1823c0b746e5SOllivier Robert /* 1824c0b746e5SOllivier Robert * reset_stats - reset statistic counters here and there 1825c0b746e5SOllivier Robert */ 1826c0b746e5SOllivier Robert static void 1827c0b746e5SOllivier Robert reset_stats( 1828*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1829*2b15cb3dSCy Schubert endpt *inter, 1830c0b746e5SOllivier Robert struct req_pkt *inpkt 1831c0b746e5SOllivier Robert ) 1832c0b746e5SOllivier Robert { 1833*2b15cb3dSCy Schubert struct reset_flags *rflags; 1834c0b746e5SOllivier Robert u_long flags; 1835c0b746e5SOllivier Robert struct reset_entry *rent; 1836c0b746e5SOllivier Robert 1837c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 1838224ba2bdSOllivier Robert msyslog(LOG_ERR, "reset_stats: err_nitems > 1"); 1839c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1840c0b746e5SOllivier Robert return; 1841c0b746e5SOllivier Robert } 1842c0b746e5SOllivier Robert 1843*2b15cb3dSCy Schubert rflags = (struct reset_flags *)&inpkt->u; 1844*2b15cb3dSCy Schubert flags = ntohl(rflags->flags); 1845c0b746e5SOllivier Robert 1846c0b746e5SOllivier Robert if (flags & ~RESET_ALLFLAGS) { 1847224ba2bdSOllivier Robert msyslog(LOG_ERR, "reset_stats: reset leaves %#lx", 1848224ba2bdSOllivier Robert flags & ~RESET_ALLFLAGS); 1849c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1850c0b746e5SOllivier Robert return; 1851c0b746e5SOllivier Robert } 1852c0b746e5SOllivier Robert 1853c0b746e5SOllivier Robert for (rent = reset_entries; rent->flag != 0; rent++) { 1854c0b746e5SOllivier Robert if (flags & rent->flag) 1855*2b15cb3dSCy Schubert (*rent->handler)(); 1856c0b746e5SOllivier Robert } 1857c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1858c0b746e5SOllivier Robert } 1859c0b746e5SOllivier Robert 1860c0b746e5SOllivier Robert 1861c0b746e5SOllivier Robert /* 1862c0b746e5SOllivier Robert * reset_peer - clear a peer's statistics 1863c0b746e5SOllivier Robert */ 1864c0b746e5SOllivier Robert static void 1865c0b746e5SOllivier Robert reset_peer( 1866*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1867*2b15cb3dSCy Schubert endpt *inter, 1868c0b746e5SOllivier Robert struct req_pkt *inpkt 1869c0b746e5SOllivier Robert ) 1870c0b746e5SOllivier Robert { 1871*2b15cb3dSCy Schubert u_short items; 1872*2b15cb3dSCy Schubert size_t item_sz; 1873*2b15cb3dSCy Schubert char * datap; 1874*2b15cb3dSCy Schubert struct conf_unpeer cp; 1875*2b15cb3dSCy Schubert struct peer * p; 1876*2b15cb3dSCy Schubert sockaddr_u peeraddr; 1877c0b746e5SOllivier Robert int bad; 1878c0b746e5SOllivier Robert 1879c0b746e5SOllivier Robert /* 1880c0b746e5SOllivier Robert * We check first to see that every peer exists. If not, 1881c0b746e5SOllivier Robert * we return an error. 1882c0b746e5SOllivier Robert */ 1883c0b746e5SOllivier Robert 1884c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1885*2b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 1886*2b15cb3dSCy Schubert datap = inpkt->u.data; 1887*2b15cb3dSCy Schubert if (item_sz > sizeof(cp)) { 1888*2b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1889*2b15cb3dSCy Schubert return; 18909c2daa00SOllivier Robert } 1891*2b15cb3dSCy Schubert 1892*2b15cb3dSCy Schubert bad = FALSE; 1893*2b15cb3dSCy Schubert while (items-- > 0 && !bad) { 1894*2b15cb3dSCy Schubert ZERO(cp); 1895*2b15cb3dSCy Schubert memcpy(&cp, datap, item_sz); 1896*2b15cb3dSCy Schubert ZERO_SOCK(&peeraddr); 1897*2b15cb3dSCy Schubert if (client_v6_capable && cp.v6_flag) { 1898*2b15cb3dSCy Schubert AF(&peeraddr) = AF_INET6; 1899*2b15cb3dSCy Schubert SOCK_ADDR6(&peeraddr) = cp.peeraddr6; 1900*2b15cb3dSCy Schubert } else { 1901*2b15cb3dSCy Schubert AF(&peeraddr) = AF_INET; 1902*2b15cb3dSCy Schubert NSRCADR(&peeraddr) = cp.peeraddr; 1903*2b15cb3dSCy Schubert } 1904*2b15cb3dSCy Schubert 1905*2b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 1906*2b15cb3dSCy Schubert peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 19079c2daa00SOllivier Robert #endif 1908*2b15cb3dSCy Schubert p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0); 1909*2b15cb3dSCy Schubert if (NULL == p) 1910c0b746e5SOllivier Robert bad++; 1911*2b15cb3dSCy Schubert datap += item_sz; 1912c0b746e5SOllivier Robert } 1913c0b746e5SOllivier Robert 1914c0b746e5SOllivier Robert if (bad) { 1915c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1916c0b746e5SOllivier Robert return; 1917c0b746e5SOllivier Robert } 1918c0b746e5SOllivier Robert 1919c0b746e5SOllivier Robert /* 1920c0b746e5SOllivier Robert * Now do it in earnest. 1921c0b746e5SOllivier Robert */ 1922c0b746e5SOllivier Robert 1923*2b15cb3dSCy Schubert datap = inpkt->u.data; 1924c0b746e5SOllivier Robert while (items-- > 0) { 1925*2b15cb3dSCy Schubert ZERO(cp); 1926*2b15cb3dSCy Schubert memcpy(&cp, datap, item_sz); 1927*2b15cb3dSCy Schubert ZERO_SOCK(&peeraddr); 1928*2b15cb3dSCy Schubert if (client_v6_capable && cp.v6_flag) { 1929*2b15cb3dSCy Schubert AF(&peeraddr) = AF_INET6; 1930*2b15cb3dSCy Schubert SOCK_ADDR6(&peeraddr) = cp.peeraddr6; 19319c2daa00SOllivier Robert } else { 1932*2b15cb3dSCy Schubert AF(&peeraddr) = AF_INET; 1933*2b15cb3dSCy Schubert NSRCADR(&peeraddr) = cp.peeraddr; 19349c2daa00SOllivier Robert } 1935*2b15cb3dSCy Schubert SET_PORT(&peeraddr, 123); 1936*2b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 1937*2b15cb3dSCy Schubert peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 19389c2daa00SOllivier Robert #endif 1939*2b15cb3dSCy Schubert p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0); 1940*2b15cb3dSCy Schubert while (p != NULL) { 1941*2b15cb3dSCy Schubert peer_reset(p); 1942*2b15cb3dSCy Schubert p = findexistingpeer(&peeraddr, NULL, p, -1, 0); 1943c0b746e5SOllivier Robert } 1944*2b15cb3dSCy Schubert datap += item_sz; 1945c0b746e5SOllivier Robert } 1946c0b746e5SOllivier Robert 1947c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1948c0b746e5SOllivier Robert } 1949c0b746e5SOllivier Robert 1950c0b746e5SOllivier Robert 1951c0b746e5SOllivier Robert /* 1952c0b746e5SOllivier Robert * do_key_reread - reread the encryption key file 1953c0b746e5SOllivier Robert */ 1954c0b746e5SOllivier Robert static void 1955c0b746e5SOllivier Robert do_key_reread( 1956*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1957*2b15cb3dSCy Schubert endpt *inter, 1958c0b746e5SOllivier Robert struct req_pkt *inpkt 1959c0b746e5SOllivier Robert ) 1960c0b746e5SOllivier Robert { 1961c0b746e5SOllivier Robert rereadkeys(); 1962c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1963c0b746e5SOllivier Robert } 1964c0b746e5SOllivier Robert 1965c0b746e5SOllivier Robert 1966c0b746e5SOllivier Robert /* 1967c0b746e5SOllivier Robert * trust_key - make one or more keys trusted 1968c0b746e5SOllivier Robert */ 1969c0b746e5SOllivier Robert static void 1970c0b746e5SOllivier Robert trust_key( 1971*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1972*2b15cb3dSCy Schubert endpt *inter, 1973c0b746e5SOllivier Robert struct req_pkt *inpkt 1974c0b746e5SOllivier Robert ) 1975c0b746e5SOllivier Robert { 1976c0b746e5SOllivier Robert do_trustkey(srcadr, inter, inpkt, 1); 1977c0b746e5SOllivier Robert } 1978c0b746e5SOllivier Robert 1979c0b746e5SOllivier Robert 1980c0b746e5SOllivier Robert /* 1981c0b746e5SOllivier Robert * untrust_key - make one or more keys untrusted 1982c0b746e5SOllivier Robert */ 1983c0b746e5SOllivier Robert static void 1984c0b746e5SOllivier Robert untrust_key( 1985*2b15cb3dSCy Schubert sockaddr_u *srcadr, 1986*2b15cb3dSCy Schubert endpt *inter, 1987c0b746e5SOllivier Robert struct req_pkt *inpkt 1988c0b746e5SOllivier Robert ) 1989c0b746e5SOllivier Robert { 1990c0b746e5SOllivier Robert do_trustkey(srcadr, inter, inpkt, 0); 1991c0b746e5SOllivier Robert } 1992c0b746e5SOllivier Robert 1993c0b746e5SOllivier Robert 1994c0b746e5SOllivier Robert /* 1995c0b746e5SOllivier Robert * do_trustkey - make keys either trustable or untrustable 1996c0b746e5SOllivier Robert */ 1997c0b746e5SOllivier Robert static void 1998c0b746e5SOllivier Robert do_trustkey( 1999*2b15cb3dSCy Schubert sockaddr_u *srcadr, 2000*2b15cb3dSCy Schubert endpt *inter, 2001c0b746e5SOllivier Robert struct req_pkt *inpkt, 2002224ba2bdSOllivier Robert u_long trust 2003c0b746e5SOllivier Robert ) 2004c0b746e5SOllivier Robert { 2005c0b746e5SOllivier Robert register u_long *kp; 2006c0b746e5SOllivier Robert register int items; 2007c0b746e5SOllivier Robert 2008c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2009*2b15cb3dSCy Schubert kp = (u_long *)&inpkt->u; 2010c0b746e5SOllivier Robert while (items-- > 0) { 2011c0b746e5SOllivier Robert authtrust(*kp, trust); 2012c0b746e5SOllivier Robert kp++; 2013c0b746e5SOllivier Robert } 2014c0b746e5SOllivier Robert 2015c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2016c0b746e5SOllivier Robert } 2017c0b746e5SOllivier Robert 2018c0b746e5SOllivier Robert 2019c0b746e5SOllivier Robert /* 2020c0b746e5SOllivier Robert * get_auth_info - return some stats concerning the authentication module 2021c0b746e5SOllivier Robert */ 2022c0b746e5SOllivier Robert static void 2023c0b746e5SOllivier Robert get_auth_info( 2024*2b15cb3dSCy Schubert sockaddr_u *srcadr, 2025*2b15cb3dSCy Schubert endpt *inter, 2026c0b746e5SOllivier Robert struct req_pkt *inpkt 2027c0b746e5SOllivier Robert ) 2028c0b746e5SOllivier Robert { 2029c0b746e5SOllivier Robert register struct info_auth *ia; 2030c0b746e5SOllivier Robert 2031c0b746e5SOllivier Robert ia = (struct info_auth *)prepare_pkt(srcadr, inter, inpkt, 2032c0b746e5SOllivier Robert sizeof(struct info_auth)); 2033c0b746e5SOllivier Robert 2034c0b746e5SOllivier Robert ia->numkeys = htonl((u_int32)authnumkeys); 2035c0b746e5SOllivier Robert ia->numfreekeys = htonl((u_int32)authnumfreekeys); 2036c0b746e5SOllivier Robert ia->keylookups = htonl((u_int32)authkeylookups); 2037c0b746e5SOllivier Robert ia->keynotfound = htonl((u_int32)authkeynotfound); 2038c0b746e5SOllivier Robert ia->encryptions = htonl((u_int32)authencryptions); 2039c0b746e5SOllivier Robert ia->decryptions = htonl((u_int32)authdecryptions); 2040c0b746e5SOllivier Robert ia->keyuncached = htonl((u_int32)authkeyuncached); 2041c0b746e5SOllivier Robert ia->expired = htonl((u_int32)authkeyexpired); 2042c0b746e5SOllivier Robert ia->timereset = htonl((u_int32)(current_time - auth_timereset)); 2043c0b746e5SOllivier Robert 2044c0b746e5SOllivier Robert (void) more_pkt(); 2045c0b746e5SOllivier Robert flush_pkt(); 2046c0b746e5SOllivier Robert } 2047c0b746e5SOllivier Robert 2048c0b746e5SOllivier Robert 2049c0b746e5SOllivier Robert 2050c0b746e5SOllivier Robert /* 2051c0b746e5SOllivier Robert * reset_auth_stats - reset the authentication stat counters. Done here 2052c0b746e5SOllivier Robert * to keep ntp-isms out of the authentication module 2053c0b746e5SOllivier Robert */ 2054*2b15cb3dSCy Schubert void 2055c0b746e5SOllivier Robert reset_auth_stats(void) 2056c0b746e5SOllivier Robert { 2057c0b746e5SOllivier Robert authkeylookups = 0; 2058c0b746e5SOllivier Robert authkeynotfound = 0; 2059c0b746e5SOllivier Robert authencryptions = 0; 2060c0b746e5SOllivier Robert authdecryptions = 0; 2061c0b746e5SOllivier Robert authkeyuncached = 0; 2062c0b746e5SOllivier Robert auth_timereset = current_time; 2063c0b746e5SOllivier Robert } 2064c0b746e5SOllivier Robert 2065c0b746e5SOllivier Robert 2066c0b746e5SOllivier Robert /* 2067c0b746e5SOllivier Robert * req_get_traps - return information about current trap holders 2068c0b746e5SOllivier Robert */ 2069c0b746e5SOllivier Robert static void 2070c0b746e5SOllivier Robert req_get_traps( 2071*2b15cb3dSCy Schubert sockaddr_u *srcadr, 2072*2b15cb3dSCy Schubert endpt *inter, 2073c0b746e5SOllivier Robert struct req_pkt *inpkt 2074c0b746e5SOllivier Robert ) 2075c0b746e5SOllivier Robert { 2076*2b15cb3dSCy Schubert struct info_trap *it; 2077*2b15cb3dSCy Schubert struct ctl_trap *tr; 2078*2b15cb3dSCy Schubert size_t i; 2079c0b746e5SOllivier Robert 2080c0b746e5SOllivier Robert if (num_ctl_traps == 0) { 2081c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2082c0b746e5SOllivier Robert return; 2083c0b746e5SOllivier Robert } 2084c0b746e5SOllivier Robert 2085c0b746e5SOllivier Robert it = (struct info_trap *)prepare_pkt(srcadr, inter, inpkt, 20869c2daa00SOllivier Robert v6sizeof(struct info_trap)); 2087c0b746e5SOllivier Robert 2088*2b15cb3dSCy Schubert for (i = 0, tr = ctl_traps; i < COUNTOF(ctl_traps); i++, tr++) { 2089c0b746e5SOllivier Robert if (tr->tr_flags & TRAP_INUSE) { 2090*2b15cb3dSCy Schubert if (IS_IPV4(&tr->tr_addr)) { 2091c0b746e5SOllivier Robert if (tr->tr_localaddr == any_interface) 2092c0b746e5SOllivier Robert it->local_address = 0; 2093c0b746e5SOllivier Robert else 2094c0b746e5SOllivier Robert it->local_address 2095*2b15cb3dSCy Schubert = NSRCADR(&tr->tr_localaddr->sin); 2096*2b15cb3dSCy Schubert it->trap_address = NSRCADR(&tr->tr_addr); 20979c2daa00SOllivier Robert if (client_v6_capable) 20989c2daa00SOllivier Robert it->v6_flag = 0; 20999c2daa00SOllivier Robert } else { 21009c2daa00SOllivier Robert if (!client_v6_capable) 21019c2daa00SOllivier Robert continue; 21029c2daa00SOllivier Robert it->local_address6 2103*2b15cb3dSCy Schubert = SOCK_ADDR6(&tr->tr_localaddr->sin); 2104*2b15cb3dSCy Schubert it->trap_address6 = SOCK_ADDR6(&tr->tr_addr); 21059c2daa00SOllivier Robert it->v6_flag = 1; 21069c2daa00SOllivier Robert } 2107c0b746e5SOllivier Robert it->trap_port = NSRCPORT(&tr->tr_addr); 2108c0b746e5SOllivier Robert it->sequence = htons(tr->tr_sequence); 2109c0b746e5SOllivier Robert it->settime = htonl((u_int32)(current_time - tr->tr_settime)); 2110c0b746e5SOllivier Robert it->origtime = htonl((u_int32)(current_time - tr->tr_origtime)); 2111c0b746e5SOllivier Robert it->resets = htonl((u_int32)tr->tr_resets); 2112c0b746e5SOllivier Robert it->flags = htonl((u_int32)tr->tr_flags); 2113c0b746e5SOllivier Robert it = (struct info_trap *)more_pkt(); 2114c0b746e5SOllivier Robert } 2115c0b746e5SOllivier Robert } 2116c0b746e5SOllivier Robert flush_pkt(); 2117c0b746e5SOllivier Robert } 2118c0b746e5SOllivier Robert 2119c0b746e5SOllivier Robert 2120c0b746e5SOllivier Robert /* 2121c0b746e5SOllivier Robert * req_set_trap - configure a trap 2122c0b746e5SOllivier Robert */ 2123c0b746e5SOllivier Robert static void 2124c0b746e5SOllivier Robert req_set_trap( 2125*2b15cb3dSCy Schubert sockaddr_u *srcadr, 2126*2b15cb3dSCy Schubert endpt *inter, 2127c0b746e5SOllivier Robert struct req_pkt *inpkt 2128c0b746e5SOllivier Robert ) 2129c0b746e5SOllivier Robert { 2130c0b746e5SOllivier Robert do_setclr_trap(srcadr, inter, inpkt, 1); 2131c0b746e5SOllivier Robert } 2132c0b746e5SOllivier Robert 2133c0b746e5SOllivier Robert 2134c0b746e5SOllivier Robert 2135c0b746e5SOllivier Robert /* 2136c0b746e5SOllivier Robert * req_clr_trap - unconfigure a trap 2137c0b746e5SOllivier Robert */ 2138c0b746e5SOllivier Robert static void 2139c0b746e5SOllivier Robert req_clr_trap( 2140*2b15cb3dSCy Schubert sockaddr_u *srcadr, 2141*2b15cb3dSCy Schubert endpt *inter, 2142c0b746e5SOllivier Robert struct req_pkt *inpkt 2143c0b746e5SOllivier Robert ) 2144c0b746e5SOllivier Robert { 2145c0b746e5SOllivier Robert do_setclr_trap(srcadr, inter, inpkt, 0); 2146c0b746e5SOllivier Robert } 2147c0b746e5SOllivier Robert 2148c0b746e5SOllivier Robert 2149c0b746e5SOllivier Robert 2150c0b746e5SOllivier Robert /* 2151c0b746e5SOllivier Robert * do_setclr_trap - do the grunge work of (un)configuring a trap 2152c0b746e5SOllivier Robert */ 2153c0b746e5SOllivier Robert static void 2154c0b746e5SOllivier Robert do_setclr_trap( 2155*2b15cb3dSCy Schubert sockaddr_u *srcadr, 2156*2b15cb3dSCy Schubert endpt *inter, 2157c0b746e5SOllivier Robert struct req_pkt *inpkt, 2158c0b746e5SOllivier Robert int set 2159c0b746e5SOllivier Robert ) 2160c0b746e5SOllivier Robert { 2161c0b746e5SOllivier Robert register struct conf_trap *ct; 2162*2b15cb3dSCy Schubert register endpt *linter; 2163c0b746e5SOllivier Robert int res; 2164*2b15cb3dSCy Schubert sockaddr_u laddr; 2165c0b746e5SOllivier Robert 2166c0b746e5SOllivier Robert /* 2167*2b15cb3dSCy Schubert * Prepare sockaddr 2168c0b746e5SOllivier Robert */ 2169*2b15cb3dSCy Schubert ZERO_SOCK(&laddr); 2170*2b15cb3dSCy Schubert AF(&laddr) = AF(srcadr); 2171*2b15cb3dSCy Schubert SET_PORT(&laddr, NTP_PORT); 2172c0b746e5SOllivier Robert 2173c0b746e5SOllivier Robert /* 2174c0b746e5SOllivier Robert * Restrict ourselves to one item only. This eliminates 2175c0b746e5SOllivier Robert * the error reporting problem. 2176c0b746e5SOllivier Robert */ 2177c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2178224ba2bdSOllivier Robert msyslog(LOG_ERR, "do_setclr_trap: err_nitems > 1"); 2179c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2180c0b746e5SOllivier Robert return; 2181c0b746e5SOllivier Robert } 2182*2b15cb3dSCy Schubert ct = (struct conf_trap *)&inpkt->u; 2183c0b746e5SOllivier Robert 2184c0b746e5SOllivier Robert /* 2185c0b746e5SOllivier Robert * Look for the local interface. If none, use the default. 2186c0b746e5SOllivier Robert */ 2187c0b746e5SOllivier Robert if (ct->local_address == 0) { 2188c0b746e5SOllivier Robert linter = any_interface; 2189c0b746e5SOllivier Robert } else { 2190*2b15cb3dSCy Schubert if (IS_IPV4(&laddr)) 2191*2b15cb3dSCy Schubert NSRCADR(&laddr) = ct->local_address; 21929c2daa00SOllivier Robert else 2193*2b15cb3dSCy Schubert SOCK_ADDR6(&laddr) = ct->local_address6; 2194c0b746e5SOllivier Robert linter = findinterface(&laddr); 2195*2b15cb3dSCy Schubert if (NULL == linter) { 2196c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2197c0b746e5SOllivier Robert return; 2198c0b746e5SOllivier Robert } 2199c0b746e5SOllivier Robert } 2200c0b746e5SOllivier Robert 2201*2b15cb3dSCy Schubert if (IS_IPV4(&laddr)) 2202*2b15cb3dSCy Schubert NSRCADR(&laddr) = ct->trap_address; 2203c0b746e5SOllivier Robert else 2204*2b15cb3dSCy Schubert SOCK_ADDR6(&laddr) = ct->trap_address6; 2205*2b15cb3dSCy Schubert if (ct->trap_port) 22069c2daa00SOllivier Robert NSRCPORT(&laddr) = ct->trap_port; 22079c2daa00SOllivier Robert else 2208*2b15cb3dSCy Schubert SET_PORT(&laddr, TRAPPORT); 2209c0b746e5SOllivier Robert 2210c0b746e5SOllivier Robert if (set) { 2211c0b746e5SOllivier Robert res = ctlsettrap(&laddr, linter, 0, 2212c0b746e5SOllivier Robert INFO_VERSION(inpkt->rm_vn_mode)); 2213c0b746e5SOllivier Robert } else { 2214c0b746e5SOllivier Robert res = ctlclrtrap(&laddr, linter, 0); 2215c0b746e5SOllivier Robert } 2216c0b746e5SOllivier Robert 2217c0b746e5SOllivier Robert if (!res) { 2218c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2219c0b746e5SOllivier Robert } else { 2220c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2221c0b746e5SOllivier Robert } 2222c0b746e5SOllivier Robert return; 2223c0b746e5SOllivier Robert } 2224c0b746e5SOllivier Robert 2225c0b746e5SOllivier Robert 2226c0b746e5SOllivier Robert 2227c0b746e5SOllivier Robert /* 2228c0b746e5SOllivier Robert * set_request_keyid - set the keyid used to authenticate requests 2229c0b746e5SOllivier Robert */ 2230c0b746e5SOllivier Robert static void 2231c0b746e5SOllivier Robert set_request_keyid( 2232*2b15cb3dSCy Schubert sockaddr_u *srcadr, 2233*2b15cb3dSCy Schubert endpt *inter, 2234c0b746e5SOllivier Robert struct req_pkt *inpkt 2235c0b746e5SOllivier Robert ) 2236c0b746e5SOllivier Robert { 2237*2b15cb3dSCy Schubert keyid_t *pkeyid; 2238c0b746e5SOllivier Robert 2239c0b746e5SOllivier Robert /* 2240c0b746e5SOllivier Robert * Restrict ourselves to one item only. 2241c0b746e5SOllivier Robert */ 2242c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2243224ba2bdSOllivier Robert msyslog(LOG_ERR, "set_request_keyid: err_nitems > 1"); 2244c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2245c0b746e5SOllivier Robert return; 2246c0b746e5SOllivier Robert } 2247c0b746e5SOllivier Robert 2248*2b15cb3dSCy Schubert pkeyid = (keyid_t *)&inpkt->u; 2249*2b15cb3dSCy Schubert info_auth_keyid = ntohl(*pkeyid); 2250c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2251c0b746e5SOllivier Robert } 2252c0b746e5SOllivier Robert 2253c0b746e5SOllivier Robert 2254c0b746e5SOllivier Robert 2255c0b746e5SOllivier Robert /* 2256c0b746e5SOllivier Robert * set_control_keyid - set the keyid used to authenticate requests 2257c0b746e5SOllivier Robert */ 2258c0b746e5SOllivier Robert static void 2259c0b746e5SOllivier Robert set_control_keyid( 2260*2b15cb3dSCy Schubert sockaddr_u *srcadr, 2261*2b15cb3dSCy Schubert endpt *inter, 2262c0b746e5SOllivier Robert struct req_pkt *inpkt 2263c0b746e5SOllivier Robert ) 2264c0b746e5SOllivier Robert { 2265*2b15cb3dSCy Schubert keyid_t *pkeyid; 2266c0b746e5SOllivier Robert 2267c0b746e5SOllivier Robert /* 2268c0b746e5SOllivier Robert * Restrict ourselves to one item only. 2269c0b746e5SOllivier Robert */ 2270c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2271224ba2bdSOllivier Robert msyslog(LOG_ERR, "set_control_keyid: err_nitems > 1"); 2272c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2273c0b746e5SOllivier Robert return; 2274c0b746e5SOllivier Robert } 2275c0b746e5SOllivier Robert 2276*2b15cb3dSCy Schubert pkeyid = (keyid_t *)&inpkt->u; 2277*2b15cb3dSCy Schubert ctl_auth_keyid = ntohl(*pkeyid); 2278c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2279c0b746e5SOllivier Robert } 2280c0b746e5SOllivier Robert 2281c0b746e5SOllivier Robert 2282c0b746e5SOllivier Robert 2283c0b746e5SOllivier Robert /* 2284c0b746e5SOllivier Robert * get_ctl_stats - return some stats concerning the control message module 2285c0b746e5SOllivier Robert */ 2286c0b746e5SOllivier Robert static void 2287c0b746e5SOllivier Robert get_ctl_stats( 2288*2b15cb3dSCy Schubert sockaddr_u *srcadr, 2289*2b15cb3dSCy Schubert endpt *inter, 2290c0b746e5SOllivier Robert struct req_pkt *inpkt 2291c0b746e5SOllivier Robert ) 2292c0b746e5SOllivier Robert { 2293c0b746e5SOllivier Robert register struct info_control *ic; 2294c0b746e5SOllivier Robert 2295c0b746e5SOllivier Robert ic = (struct info_control *)prepare_pkt(srcadr, inter, inpkt, 2296c0b746e5SOllivier Robert sizeof(struct info_control)); 2297c0b746e5SOllivier Robert 2298c0b746e5SOllivier Robert ic->ctltimereset = htonl((u_int32)(current_time - ctltimereset)); 2299c0b746e5SOllivier Robert ic->numctlreq = htonl((u_int32)numctlreq); 2300c0b746e5SOllivier Robert ic->numctlbadpkts = htonl((u_int32)numctlbadpkts); 2301c0b746e5SOllivier Robert ic->numctlresponses = htonl((u_int32)numctlresponses); 2302c0b746e5SOllivier Robert ic->numctlfrags = htonl((u_int32)numctlfrags); 2303c0b746e5SOllivier Robert ic->numctlerrors = htonl((u_int32)numctlerrors); 2304c0b746e5SOllivier Robert ic->numctltooshort = htonl((u_int32)numctltooshort); 2305c0b746e5SOllivier Robert ic->numctlinputresp = htonl((u_int32)numctlinputresp); 2306c0b746e5SOllivier Robert ic->numctlinputfrag = htonl((u_int32)numctlinputfrag); 2307c0b746e5SOllivier Robert ic->numctlinputerr = htonl((u_int32)numctlinputerr); 2308c0b746e5SOllivier Robert ic->numctlbadoffset = htonl((u_int32)numctlbadoffset); 2309c0b746e5SOllivier Robert ic->numctlbadversion = htonl((u_int32)numctlbadversion); 2310c0b746e5SOllivier Robert ic->numctldatatooshort = htonl((u_int32)numctldatatooshort); 2311c0b746e5SOllivier Robert ic->numctlbadop = htonl((u_int32)numctlbadop); 2312c0b746e5SOllivier Robert ic->numasyncmsgs = htonl((u_int32)numasyncmsgs); 2313c0b746e5SOllivier Robert 2314c0b746e5SOllivier Robert (void) more_pkt(); 2315c0b746e5SOllivier Robert flush_pkt(); 2316c0b746e5SOllivier Robert } 2317c0b746e5SOllivier Robert 2318c0b746e5SOllivier Robert 2319c0b746e5SOllivier Robert #ifdef KERNEL_PLL 2320c0b746e5SOllivier Robert /* 2321c0b746e5SOllivier Robert * get_kernel_info - get kernel pll/pps information 2322c0b746e5SOllivier Robert */ 2323c0b746e5SOllivier Robert static void 2324c0b746e5SOllivier Robert get_kernel_info( 2325*2b15cb3dSCy Schubert sockaddr_u *srcadr, 2326*2b15cb3dSCy Schubert endpt *inter, 2327c0b746e5SOllivier Robert struct req_pkt *inpkt 2328c0b746e5SOllivier Robert ) 2329c0b746e5SOllivier Robert { 2330c0b746e5SOllivier Robert register struct info_kernel *ik; 2331c0b746e5SOllivier Robert struct timex ntx; 2332c0b746e5SOllivier Robert 2333c0b746e5SOllivier Robert if (!pll_control) { 2334c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2335c0b746e5SOllivier Robert return; 2336c0b746e5SOllivier Robert } 2337c0b746e5SOllivier Robert 2338*2b15cb3dSCy Schubert ZERO(ntx); 2339c0b746e5SOllivier Robert if (ntp_adjtime(&ntx) < 0) 2340c0b746e5SOllivier Robert msyslog(LOG_ERR, "get_kernel_info: ntp_adjtime() failed: %m"); 2341c0b746e5SOllivier Robert ik = (struct info_kernel *)prepare_pkt(srcadr, inter, inpkt, 2342c0b746e5SOllivier Robert sizeof(struct info_kernel)); 2343c0b746e5SOllivier Robert 2344c0b746e5SOllivier Robert /* 2345c0b746e5SOllivier Robert * pll variables 2346c0b746e5SOllivier Robert */ 2347c0b746e5SOllivier Robert ik->offset = htonl((u_int32)ntx.offset); 2348c0b746e5SOllivier Robert ik->freq = htonl((u_int32)ntx.freq); 2349c0b746e5SOllivier Robert ik->maxerror = htonl((u_int32)ntx.maxerror); 2350c0b746e5SOllivier Robert ik->esterror = htonl((u_int32)ntx.esterror); 2351c0b746e5SOllivier Robert ik->status = htons(ntx.status); 2352c0b746e5SOllivier Robert ik->constant = htonl((u_int32)ntx.constant); 2353c0b746e5SOllivier Robert ik->precision = htonl((u_int32)ntx.precision); 2354c0b746e5SOllivier Robert ik->tolerance = htonl((u_int32)ntx.tolerance); 2355c0b746e5SOllivier Robert 2356c0b746e5SOllivier Robert /* 2357c0b746e5SOllivier Robert * pps variables 2358c0b746e5SOllivier Robert */ 2359c0b746e5SOllivier Robert ik->ppsfreq = htonl((u_int32)ntx.ppsfreq); 2360c0b746e5SOllivier Robert ik->jitter = htonl((u_int32)ntx.jitter); 2361c0b746e5SOllivier Robert ik->shift = htons(ntx.shift); 2362c0b746e5SOllivier Robert ik->stabil = htonl((u_int32)ntx.stabil); 2363c0b746e5SOllivier Robert ik->jitcnt = htonl((u_int32)ntx.jitcnt); 2364c0b746e5SOllivier Robert ik->calcnt = htonl((u_int32)ntx.calcnt); 2365c0b746e5SOllivier Robert ik->errcnt = htonl((u_int32)ntx.errcnt); 2366c0b746e5SOllivier Robert ik->stbcnt = htonl((u_int32)ntx.stbcnt); 2367c0b746e5SOllivier Robert 2368c0b746e5SOllivier Robert (void) more_pkt(); 2369c0b746e5SOllivier Robert flush_pkt(); 2370c0b746e5SOllivier Robert } 2371c0b746e5SOllivier Robert #endif /* KERNEL_PLL */ 2372c0b746e5SOllivier Robert 2373c0b746e5SOllivier Robert 2374c0b746e5SOllivier Robert #ifdef REFCLOCK 2375c0b746e5SOllivier Robert /* 2376c0b746e5SOllivier Robert * get_clock_info - get info about a clock 2377c0b746e5SOllivier Robert */ 2378c0b746e5SOllivier Robert static void 2379c0b746e5SOllivier Robert get_clock_info( 2380*2b15cb3dSCy Schubert sockaddr_u *srcadr, 2381*2b15cb3dSCy Schubert endpt *inter, 2382c0b746e5SOllivier Robert struct req_pkt *inpkt 2383c0b746e5SOllivier Robert ) 2384c0b746e5SOllivier Robert { 2385c0b746e5SOllivier Robert register struct info_clock *ic; 2386c0b746e5SOllivier Robert register u_int32 *clkaddr; 2387c0b746e5SOllivier Robert register int items; 2388c0b746e5SOllivier Robert struct refclockstat clock_stat; 2389*2b15cb3dSCy Schubert sockaddr_u addr; 2390c0b746e5SOllivier Robert l_fp ltmp; 2391c0b746e5SOllivier Robert 2392*2b15cb3dSCy Schubert ZERO_SOCK(&addr); 2393*2b15cb3dSCy Schubert AF(&addr) = AF_INET; 2394*2b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 2395*2b15cb3dSCy Schubert addr.sa.sa_len = SOCKLEN(&addr); 23969c2daa00SOllivier Robert #endif 2397*2b15cb3dSCy Schubert SET_PORT(&addr, NTP_PORT); 2398c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2399*2b15cb3dSCy Schubert clkaddr = &inpkt->u.u32[0]; 2400c0b746e5SOllivier Robert 2401c0b746e5SOllivier Robert ic = (struct info_clock *)prepare_pkt(srcadr, inter, inpkt, 2402c0b746e5SOllivier Robert sizeof(struct info_clock)); 2403c0b746e5SOllivier Robert 2404c0b746e5SOllivier Robert while (items-- > 0) { 2405*2b15cb3dSCy Schubert NSRCADR(&addr) = *clkaddr++; 2406*2b15cb3dSCy Schubert if (!ISREFCLOCKADR(&addr) || NULL == 2407*2b15cb3dSCy Schubert findexistingpeer(&addr, NULL, NULL, -1, 0)) { 2408c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2409c0b746e5SOllivier Robert return; 2410c0b746e5SOllivier Robert } 2411c0b746e5SOllivier Robert 2412c0b746e5SOllivier Robert clock_stat.kv_list = (struct ctl_var *)0; 2413c0b746e5SOllivier Robert 2414*2b15cb3dSCy Schubert refclock_control(&addr, NULL, &clock_stat); 2415c0b746e5SOllivier Robert 2416*2b15cb3dSCy Schubert ic->clockadr = NSRCADR(&addr); 2417c0b746e5SOllivier Robert ic->type = clock_stat.type; 2418c0b746e5SOllivier Robert ic->flags = clock_stat.flags; 2419c0b746e5SOllivier Robert ic->lastevent = clock_stat.lastevent; 2420c0b746e5SOllivier Robert ic->currentstatus = clock_stat.currentstatus; 2421c0b746e5SOllivier Robert ic->polls = htonl((u_int32)clock_stat.polls); 2422c0b746e5SOllivier Robert ic->noresponse = htonl((u_int32)clock_stat.noresponse); 2423c0b746e5SOllivier Robert ic->badformat = htonl((u_int32)clock_stat.badformat); 2424c0b746e5SOllivier Robert ic->baddata = htonl((u_int32)clock_stat.baddata); 2425c0b746e5SOllivier Robert ic->timestarted = htonl((u_int32)clock_stat.timereset); 2426c0b746e5SOllivier Robert DTOLFP(clock_stat.fudgetime1, <mp); 2427c0b746e5SOllivier Robert HTONL_FP(<mp, &ic->fudgetime1); 24289c2daa00SOllivier Robert DTOLFP(clock_stat.fudgetime2, <mp); 2429c0b746e5SOllivier Robert HTONL_FP(<mp, &ic->fudgetime2); 2430c0b746e5SOllivier Robert ic->fudgeval1 = htonl((u_int32)clock_stat.fudgeval1); 2431*2b15cb3dSCy Schubert ic->fudgeval2 = htonl(clock_stat.fudgeval2); 2432c0b746e5SOllivier Robert 2433c0b746e5SOllivier Robert free_varlist(clock_stat.kv_list); 2434c0b746e5SOllivier Robert 2435c0b746e5SOllivier Robert ic = (struct info_clock *)more_pkt(); 2436c0b746e5SOllivier Robert } 2437c0b746e5SOllivier Robert flush_pkt(); 2438c0b746e5SOllivier Robert } 2439c0b746e5SOllivier Robert 2440c0b746e5SOllivier Robert 2441c0b746e5SOllivier Robert 2442c0b746e5SOllivier Robert /* 2443c0b746e5SOllivier Robert * set_clock_fudge - get a clock's fudge factors 2444c0b746e5SOllivier Robert */ 2445c0b746e5SOllivier Robert static void 2446c0b746e5SOllivier Robert set_clock_fudge( 2447*2b15cb3dSCy Schubert sockaddr_u *srcadr, 2448*2b15cb3dSCy Schubert endpt *inter, 2449c0b746e5SOllivier Robert struct req_pkt *inpkt 2450c0b746e5SOllivier Robert ) 2451c0b746e5SOllivier Robert { 2452c0b746e5SOllivier Robert register struct conf_fudge *cf; 2453c0b746e5SOllivier Robert register int items; 2454c0b746e5SOllivier Robert struct refclockstat clock_stat; 2455*2b15cb3dSCy Schubert sockaddr_u addr; 2456c0b746e5SOllivier Robert l_fp ltmp; 2457c0b746e5SOllivier Robert 2458*2b15cb3dSCy Schubert ZERO(addr); 2459*2b15cb3dSCy Schubert ZERO(clock_stat); 2460c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2461*2b15cb3dSCy Schubert cf = (struct conf_fudge *)&inpkt->u; 2462c0b746e5SOllivier Robert 2463c0b746e5SOllivier Robert while (items-- > 0) { 2464*2b15cb3dSCy Schubert AF(&addr) = AF_INET; 2465*2b15cb3dSCy Schubert NSRCADR(&addr) = cf->clockadr; 2466*2b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 2467*2b15cb3dSCy Schubert addr.sa.sa_len = SOCKLEN(&addr); 24689c2daa00SOllivier Robert #endif 2469*2b15cb3dSCy Schubert SET_PORT(&addr, NTP_PORT); 2470*2b15cb3dSCy Schubert if (!ISREFCLOCKADR(&addr) || NULL == 2471*2b15cb3dSCy Schubert findexistingpeer(&addr, NULL, NULL, -1, 0)) { 2472c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2473c0b746e5SOllivier Robert return; 2474c0b746e5SOllivier Robert } 2475c0b746e5SOllivier Robert 2476c0b746e5SOllivier Robert switch(ntohl(cf->which)) { 2477c0b746e5SOllivier Robert case FUDGE_TIME1: 2478c0b746e5SOllivier Robert NTOHL_FP(&cf->fudgetime, <mp); 2479c0b746e5SOllivier Robert LFPTOD(<mp, clock_stat.fudgetime1); 2480c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVETIME1; 2481c0b746e5SOllivier Robert break; 2482c0b746e5SOllivier Robert case FUDGE_TIME2: 2483c0b746e5SOllivier Robert NTOHL_FP(&cf->fudgetime, <mp); 2484c0b746e5SOllivier Robert LFPTOD(<mp, clock_stat.fudgetime2); 2485c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVETIME2; 2486c0b746e5SOllivier Robert break; 2487c0b746e5SOllivier Robert case FUDGE_VAL1: 2488c0b746e5SOllivier Robert clock_stat.fudgeval1 = ntohl(cf->fudgeval_flags); 2489c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVEVAL1; 2490c0b746e5SOllivier Robert break; 2491c0b746e5SOllivier Robert case FUDGE_VAL2: 2492c0b746e5SOllivier Robert clock_stat.fudgeval2 = ntohl(cf->fudgeval_flags); 2493c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVEVAL2; 2494c0b746e5SOllivier Robert break; 2495c0b746e5SOllivier Robert case FUDGE_FLAGS: 24969c2daa00SOllivier Robert clock_stat.flags = (u_char) (ntohl(cf->fudgeval_flags) & 0xf); 2497c0b746e5SOllivier Robert clock_stat.haveflags = 2498c0b746e5SOllivier Robert (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4); 2499c0b746e5SOllivier Robert break; 2500c0b746e5SOllivier Robert default: 2501224ba2bdSOllivier Robert msyslog(LOG_ERR, "set_clock_fudge: default!"); 2502c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2503c0b746e5SOllivier Robert return; 2504c0b746e5SOllivier Robert } 2505c0b746e5SOllivier Robert 2506c0b746e5SOllivier Robert refclock_control(&addr, &clock_stat, (struct refclockstat *)0); 2507c0b746e5SOllivier Robert } 2508c0b746e5SOllivier Robert 2509c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2510c0b746e5SOllivier Robert } 2511c0b746e5SOllivier Robert #endif 2512c0b746e5SOllivier Robert 2513c0b746e5SOllivier Robert #ifdef REFCLOCK 2514c0b746e5SOllivier Robert /* 2515c0b746e5SOllivier Robert * get_clkbug_info - get debugging info about a clock 2516c0b746e5SOllivier Robert */ 2517c0b746e5SOllivier Robert static void 2518c0b746e5SOllivier Robert get_clkbug_info( 2519*2b15cb3dSCy Schubert sockaddr_u *srcadr, 2520*2b15cb3dSCy Schubert endpt *inter, 2521c0b746e5SOllivier Robert struct req_pkt *inpkt 2522c0b746e5SOllivier Robert ) 2523c0b746e5SOllivier Robert { 2524c0b746e5SOllivier Robert register int i; 2525c0b746e5SOllivier Robert register struct info_clkbug *ic; 2526c0b746e5SOllivier Robert register u_int32 *clkaddr; 2527c0b746e5SOllivier Robert register int items; 2528c0b746e5SOllivier Robert struct refclockbug bug; 2529*2b15cb3dSCy Schubert sockaddr_u addr; 2530c0b746e5SOllivier Robert 2531*2b15cb3dSCy Schubert ZERO_SOCK(&addr); 2532*2b15cb3dSCy Schubert AF(&addr) = AF_INET; 2533*2b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 2534*2b15cb3dSCy Schubert addr.sa.sa_len = SOCKLEN(&addr); 25359c2daa00SOllivier Robert #endif 2536*2b15cb3dSCy Schubert SET_PORT(&addr, NTP_PORT); 2537c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2538*2b15cb3dSCy Schubert clkaddr = (u_int32 *)&inpkt->u; 2539c0b746e5SOllivier Robert 2540c0b746e5SOllivier Robert ic = (struct info_clkbug *)prepare_pkt(srcadr, inter, inpkt, 2541c0b746e5SOllivier Robert sizeof(struct info_clkbug)); 2542c0b746e5SOllivier Robert 2543c0b746e5SOllivier Robert while (items-- > 0) { 2544*2b15cb3dSCy Schubert NSRCADR(&addr) = *clkaddr++; 2545*2b15cb3dSCy Schubert if (!ISREFCLOCKADR(&addr) || NULL == 2546*2b15cb3dSCy Schubert findexistingpeer(&addr, NULL, NULL, -1, 0)) { 2547c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2548c0b746e5SOllivier Robert return; 2549c0b746e5SOllivier Robert } 2550c0b746e5SOllivier Robert 2551*2b15cb3dSCy Schubert ZERO(bug); 2552c0b746e5SOllivier Robert refclock_buginfo(&addr, &bug); 2553c0b746e5SOllivier Robert if (bug.nvalues == 0 && bug.ntimes == 0) { 2554c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2555c0b746e5SOllivier Robert return; 2556c0b746e5SOllivier Robert } 2557c0b746e5SOllivier Robert 2558*2b15cb3dSCy Schubert ic->clockadr = NSRCADR(&addr); 2559c0b746e5SOllivier Robert i = bug.nvalues; 2560c0b746e5SOllivier Robert if (i > NUMCBUGVALUES) 2561c0b746e5SOllivier Robert i = NUMCBUGVALUES; 2562c0b746e5SOllivier Robert ic->nvalues = (u_char)i; 2563c0b746e5SOllivier Robert ic->svalues = htons((u_short) (bug.svalues & ((1<<i)-1))); 2564c0b746e5SOllivier Robert while (--i >= 0) 2565c0b746e5SOllivier Robert ic->values[i] = htonl(bug.values[i]); 2566c0b746e5SOllivier Robert 2567c0b746e5SOllivier Robert i = bug.ntimes; 2568c0b746e5SOllivier Robert if (i > NUMCBUGTIMES) 2569c0b746e5SOllivier Robert i = NUMCBUGTIMES; 2570c0b746e5SOllivier Robert ic->ntimes = (u_char)i; 2571c0b746e5SOllivier Robert ic->stimes = htonl(bug.stimes); 2572c0b746e5SOllivier Robert while (--i >= 0) { 2573c0b746e5SOllivier Robert HTONL_FP(&bug.times[i], &ic->times[i]); 2574c0b746e5SOllivier Robert } 2575c0b746e5SOllivier Robert 2576c0b746e5SOllivier Robert ic = (struct info_clkbug *)more_pkt(); 2577c0b746e5SOllivier Robert } 2578c0b746e5SOllivier Robert flush_pkt(); 2579c0b746e5SOllivier Robert } 2580c0b746e5SOllivier Robert #endif 2581ea906c41SOllivier Robert 2582ea906c41SOllivier Robert /* 2583ea906c41SOllivier Robert * receiver of interface structures 2584ea906c41SOllivier Robert */ 2585ea906c41SOllivier Robert static void 2586ea906c41SOllivier Robert fill_info_if_stats(void *data, interface_info_t *interface_info) 2587ea906c41SOllivier Robert { 2588ea906c41SOllivier Robert struct info_if_stats **ifsp = (struct info_if_stats **)data; 2589ea906c41SOllivier Robert struct info_if_stats *ifs = *ifsp; 2590*2b15cb3dSCy Schubert endpt *ep = interface_info->ep; 2591ea906c41SOllivier Robert 2592*2b15cb3dSCy Schubert ZERO(*ifs); 2593ea906c41SOllivier Robert 2594*2b15cb3dSCy Schubert if (IS_IPV6(&ep->sin)) { 2595ea906c41SOllivier Robert if (!client_v6_capable) { 2596ea906c41SOllivier Robert return; 2597ea906c41SOllivier Robert } 2598ea906c41SOllivier Robert ifs->v6_flag = 1; 2599*2b15cb3dSCy Schubert ifs->unaddr.addr6 = SOCK_ADDR6(&ep->sin); 2600*2b15cb3dSCy Schubert ifs->unbcast.addr6 = SOCK_ADDR6(&ep->bcast); 2601*2b15cb3dSCy Schubert ifs->unmask.addr6 = SOCK_ADDR6(&ep->mask); 2602ea906c41SOllivier Robert } else { 2603ea906c41SOllivier Robert ifs->v6_flag = 0; 2604*2b15cb3dSCy Schubert ifs->unaddr.addr = SOCK_ADDR4(&ep->sin); 2605*2b15cb3dSCy Schubert ifs->unbcast.addr = SOCK_ADDR4(&ep->bcast); 2606*2b15cb3dSCy Schubert ifs->unmask.addr = SOCK_ADDR4(&ep->mask); 2607ea906c41SOllivier Robert } 2608ea906c41SOllivier Robert ifs->v6_flag = htonl(ifs->v6_flag); 2609*2b15cb3dSCy Schubert strlcpy(ifs->name, ep->name, sizeof(ifs->name)); 2610*2b15cb3dSCy Schubert ifs->family = htons(ep->family); 2611*2b15cb3dSCy Schubert ifs->flags = htonl(ep->flags); 2612*2b15cb3dSCy Schubert ifs->last_ttl = htonl(ep->last_ttl); 2613*2b15cb3dSCy Schubert ifs->num_mcast = htonl(ep->num_mcast); 2614*2b15cb3dSCy Schubert ifs->received = htonl(ep->received); 2615*2b15cb3dSCy Schubert ifs->sent = htonl(ep->sent); 2616*2b15cb3dSCy Schubert ifs->notsent = htonl(ep->notsent); 2617*2b15cb3dSCy Schubert ifs->ifindex = htonl(ep->ifindex); 2618*2b15cb3dSCy Schubert /* scope no longer in endpt, in in6_addr typically */ 2619*2b15cb3dSCy Schubert ifs->scopeid = ifs->ifindex; 2620*2b15cb3dSCy Schubert ifs->ifnum = htonl(ep->ifnum); 2621*2b15cb3dSCy Schubert ifs->uptime = htonl(current_time - ep->starttime); 2622*2b15cb3dSCy Schubert ifs->ignore_packets = ep->ignore_packets; 2623*2b15cb3dSCy Schubert ifs->peercnt = htonl(ep->peercnt); 2624ea906c41SOllivier Robert ifs->action = interface_info->action; 2625ea906c41SOllivier Robert 2626ea906c41SOllivier Robert *ifsp = (struct info_if_stats *)more_pkt(); 2627ea906c41SOllivier Robert } 2628ea906c41SOllivier Robert 2629ea906c41SOllivier Robert /* 2630ea906c41SOllivier Robert * get_if_stats - get interface statistics 2631ea906c41SOllivier Robert */ 2632ea906c41SOllivier Robert static void 2633ea906c41SOllivier Robert get_if_stats( 2634*2b15cb3dSCy Schubert sockaddr_u *srcadr, 2635*2b15cb3dSCy Schubert endpt *inter, 2636ea906c41SOllivier Robert struct req_pkt *inpkt 2637ea906c41SOllivier Robert ) 2638ea906c41SOllivier Robert { 2639ea906c41SOllivier Robert struct info_if_stats *ifs; 2640ea906c41SOllivier Robert 2641ea906c41SOllivier Robert DPRINTF(3, ("wants interface statistics\n")); 2642ea906c41SOllivier Robert 2643ea906c41SOllivier Robert ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt, 2644ea906c41SOllivier Robert v6sizeof(struct info_if_stats)); 2645ea906c41SOllivier Robert 2646ea906c41SOllivier Robert interface_enumerate(fill_info_if_stats, &ifs); 2647ea906c41SOllivier Robert 2648ea906c41SOllivier Robert flush_pkt(); 2649ea906c41SOllivier Robert } 2650ea906c41SOllivier Robert 2651ea906c41SOllivier Robert static void 2652ea906c41SOllivier Robert do_if_reload( 2653*2b15cb3dSCy Schubert sockaddr_u *srcadr, 2654*2b15cb3dSCy Schubert endpt *inter, 2655ea906c41SOllivier Robert struct req_pkt *inpkt 2656ea906c41SOllivier Robert ) 2657ea906c41SOllivier Robert { 2658ea906c41SOllivier Robert struct info_if_stats *ifs; 2659ea906c41SOllivier Robert 2660ea906c41SOllivier Robert DPRINTF(3, ("wants interface reload\n")); 2661ea906c41SOllivier Robert 2662ea906c41SOllivier Robert ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt, 2663ea906c41SOllivier Robert v6sizeof(struct info_if_stats)); 2664ea906c41SOllivier Robert 2665ea906c41SOllivier Robert interface_update(fill_info_if_stats, &ifs); 2666ea906c41SOllivier Robert 2667ea906c41SOllivier Robert flush_pkt(); 2668ea906c41SOllivier Robert } 2669ea906c41SOllivier Robert 2670