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" 162b15cb3dSCy Schubert #include "ntp_assert.h" 17224ba2bdSOllivier Robert 18224ba2bdSOllivier Robert #include <stdio.h> 199c2daa00SOllivier Robert #include <stddef.h> 20224ba2bdSOllivier Robert #include <signal.h> 212b15cb3dSCy Schubert #ifdef HAVE_NETINET_IN_H 22224ba2bdSOllivier Robert #include <netinet/in.h> 232b15cb3dSCy 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)*/ 532b15cb3dSCy Schubert void (*handler) (sockaddr_u *, endpt *, 542b15cb3dSCy Schubert struct req_pkt *); /* routine to handle request */ 55c0b746e5SOllivier Robert }; 56c0b746e5SOllivier Robert 57c0b746e5SOllivier Robert /* 58c0b746e5SOllivier Robert * Universal request codes 59c0b746e5SOllivier Robert */ 602b15cb3dSCy Schubert static const struct req_proc univ_codes[] = { 612b15cb3dSCy Schubert { NO_REQUEST, NOAUTH, 0, 0, NULL } 62c0b746e5SOllivier Robert }; 63c0b746e5SOllivier Robert 642b15cb3dSCy Schubert static void req_ack (sockaddr_u *, endpt *, struct req_pkt *, int); 652b15cb3dSCy Schubert static void * prepare_pkt (sockaddr_u *, endpt *, 662b15cb3dSCy Schubert struct req_pkt *, size_t); 672b15cb3dSCy Schubert static void * more_pkt (void); 682b15cb3dSCy Schubert static void flush_pkt (void); 692b15cb3dSCy Schubert static void list_peers (sockaddr_u *, endpt *, struct req_pkt *); 702b15cb3dSCy Schubert static void list_peers_sum (sockaddr_u *, endpt *, struct req_pkt *); 712b15cb3dSCy Schubert static void peer_info (sockaddr_u *, endpt *, struct req_pkt *); 722b15cb3dSCy Schubert static void peer_stats (sockaddr_u *, endpt *, struct req_pkt *); 732b15cb3dSCy Schubert static void sys_info (sockaddr_u *, endpt *, struct req_pkt *); 742b15cb3dSCy Schubert static void sys_stats (sockaddr_u *, endpt *, struct req_pkt *); 752b15cb3dSCy Schubert static void mem_stats (sockaddr_u *, endpt *, struct req_pkt *); 762b15cb3dSCy Schubert static void io_stats (sockaddr_u *, endpt *, struct req_pkt *); 772b15cb3dSCy Schubert static void timer_stats (sockaddr_u *, endpt *, struct req_pkt *); 782b15cb3dSCy Schubert static void loop_info (sockaddr_u *, endpt *, struct req_pkt *); 792b15cb3dSCy Schubert static void do_conf (sockaddr_u *, endpt *, struct req_pkt *); 802b15cb3dSCy Schubert static void do_unconf (sockaddr_u *, endpt *, struct req_pkt *); 812b15cb3dSCy Schubert static void set_sys_flag (sockaddr_u *, endpt *, struct req_pkt *); 822b15cb3dSCy Schubert static void clr_sys_flag (sockaddr_u *, endpt *, struct req_pkt *); 832b15cb3dSCy Schubert static void setclr_flags (sockaddr_u *, endpt *, struct req_pkt *, u_long); 8468ba7e87SXin LI static void list_restrict4 (const restrict_u *, struct info_restrict **); 8568ba7e87SXin LI static void list_restrict6 (const restrict_u *, struct info_restrict **); 862b15cb3dSCy Schubert static void list_restrict (sockaddr_u *, endpt *, struct req_pkt *); 872b15cb3dSCy Schubert static void do_resaddflags (sockaddr_u *, endpt *, struct req_pkt *); 882b15cb3dSCy Schubert static void do_ressubflags (sockaddr_u *, endpt *, struct req_pkt *); 892b15cb3dSCy Schubert static void do_unrestrict (sockaddr_u *, endpt *, struct req_pkt *); 9009100258SXin LI static void do_restrict (sockaddr_u *, endpt *, struct req_pkt *, restrict_op); 912b15cb3dSCy Schubert static void mon_getlist (sockaddr_u *, endpt *, struct req_pkt *); 922b15cb3dSCy Schubert static void reset_stats (sockaddr_u *, endpt *, struct req_pkt *); 932b15cb3dSCy Schubert static void reset_peer (sockaddr_u *, endpt *, struct req_pkt *); 942b15cb3dSCy Schubert static void do_key_reread (sockaddr_u *, endpt *, struct req_pkt *); 952b15cb3dSCy Schubert static void trust_key (sockaddr_u *, endpt *, struct req_pkt *); 962b15cb3dSCy Schubert static void untrust_key (sockaddr_u *, endpt *, struct req_pkt *); 972b15cb3dSCy Schubert static void do_trustkey (sockaddr_u *, endpt *, struct req_pkt *, u_long); 982b15cb3dSCy Schubert static void get_auth_info (sockaddr_u *, endpt *, struct req_pkt *); 992b15cb3dSCy Schubert static void req_get_traps (sockaddr_u *, endpt *, struct req_pkt *); 1002b15cb3dSCy Schubert static void req_set_trap (sockaddr_u *, endpt *, struct req_pkt *); 1012b15cb3dSCy Schubert static void req_clr_trap (sockaddr_u *, endpt *, struct req_pkt *); 1022b15cb3dSCy Schubert static void do_setclr_trap (sockaddr_u *, endpt *, struct req_pkt *, int); 1032b15cb3dSCy Schubert static void set_request_keyid (sockaddr_u *, endpt *, struct req_pkt *); 1042b15cb3dSCy Schubert static void set_control_keyid (sockaddr_u *, endpt *, struct req_pkt *); 1052b15cb3dSCy Schubert static void get_ctl_stats (sockaddr_u *, endpt *, struct req_pkt *); 1062b15cb3dSCy Schubert static void get_if_stats (sockaddr_u *, endpt *, struct req_pkt *); 1072b15cb3dSCy Schubert static void do_if_reload (sockaddr_u *, endpt *, struct req_pkt *); 108c0b746e5SOllivier Robert #ifdef KERNEL_PLL 1092b15cb3dSCy Schubert static void get_kernel_info (sockaddr_u *, endpt *, struct req_pkt *); 110c0b746e5SOllivier Robert #endif /* KERNEL_PLL */ 111c0b746e5SOllivier Robert #ifdef REFCLOCK 1122b15cb3dSCy Schubert static void get_clock_info (sockaddr_u *, endpt *, struct req_pkt *); 1132b15cb3dSCy Schubert static void set_clock_fudge (sockaddr_u *, endpt *, struct req_pkt *); 114c0b746e5SOllivier Robert #endif /* REFCLOCK */ 115c0b746e5SOllivier Robert #ifdef REFCLOCK 1162b15cb3dSCy 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 */ 1222b15cb3dSCy Schubert static const struct req_proc ntp_codes[] = { 1232b15cb3dSCy Schubert { REQ_PEER_LIST, NOAUTH, 0, 0, list_peers }, 1242b15cb3dSCy 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 }, 1502b15cb3dSCy Schubert { REQ_MON_GETLIST, NOAUTH, 0, 0, mon_getlist }, 1512b15cb3dSCy 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 1992b15cb3dSCy Schubert /* 2002b15cb3dSCy Schubert * lazy way to count errors, indexed by the error code 2012b15cb3dSCy Schubert */ 2022b15cb3dSCy 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 */ 2082b15cb3dSCy 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; 2252b15cb3dSCy Schubert static sockaddr_u *toaddr; 2262b15cb3dSCy 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 { 2342b15cb3dSCy 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( 2512b15cb3dSCy Schubert sockaddr_u *srcadr, 2522b15cb3dSCy 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 */ 2792b15cb3dSCy Schubert static void * 280c0b746e5SOllivier Robert prepare_pkt( 2812b15cb3dSCy Schubert sockaddr_u *srcadr, 2822b15cb3dSCy Schubert endpt *inter, 283c0b746e5SOllivier Robert struct req_pkt *pkt, 2842b15cb3dSCy Schubert size_t structsize 285c0b746e5SOllivier Robert ) 286c0b746e5SOllivier Robert { 2872b15cb3dSCy 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 */ 3112b15cb3dSCy 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 */ 3182b15cb3dSCy 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) { 3252b15cb3dSCy 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 */ 3362b15cb3dSCy 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) { 3462b15cb3dSCy 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 */ 3512b15cb3dSCy 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 */ 3572b15cb3dSCy Schubert DPRINTF(4, ("request: into extra buffer\n")); 358c0b746e5SOllivier Robert if (seqno == MAXSEQ) 3592b15cb3dSCy 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 { 3742b15cb3dSCy 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 /* 3952b15cb3dSCy Schubert * Given a buffer, return the packet mode 3962b15cb3dSCy Schubert */ 3972b15cb3dSCy Schubert int 3982b15cb3dSCy Schubert get_packet_mode(struct recvbuf *rbufp) 3992b15cb3dSCy Schubert { 4002b15cb3dSCy Schubert struct req_pkt *inpkt = (struct req_pkt *)&rbufp->recv_pkt; 4012b15cb3dSCy Schubert return (INFO_MODE(inpkt->rm_vn_mode)); 4022b15cb3dSCy Schubert } 4032b15cb3dSCy Schubert 4042b15cb3dSCy Schubert 4052b15cb3dSCy 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; 4172b15cb3dSCy Schubert sockaddr_u *srcadr; 4182b15cb3dSCy Schubert endpt *inter; 4192b15cb3dSCy Schubert const struct req_proc *proc; 420224ba2bdSOllivier Robert int ec; 4219c2daa00SOllivier Robert short temp_size; 4222b15cb3dSCy Schubert l_fp ftmp; 4232b15cb3dSCy Schubert double dtemp; 4242b15cb3dSCy Schubert size_t recv_len; 4252b15cb3dSCy Schubert size_t noslop_len; 4262b15cb3dSCy Schubert size_t mac_len; 427c0b746e5SOllivier Robert 428c0b746e5SOllivier Robert /* 429c0b746e5SOllivier Robert * Initialize pointers, for convenience 430c0b746e5SOllivier Robert */ 4312b15cb3dSCy 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 4362b15cb3dSCy Schubert DPRINTF(3, ("process_private: impl %d req %d\n", 4372b15cb3dSCy 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) 4512b15cb3dSCy 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 4932b15cb3dSCy 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))) { 5122b15cb3dSCy Schubert DPRINTF(3, ("process_private: wrong item size, received %d, should be %d or %d\n", 5132b15cb3dSCy 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) && 5182b15cb3dSCy Schubert ((size_t)(temp_size * INFO_NITEMS(inpkt->err_nitems)) > 5192b15cb3dSCy Schubert (recv_len - REQ_LEN_HDR))) { 5202b15cb3dSCy 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 5472b15cb3dSCy Schubert if (recv_len < (REQ_LEN_HDR + 548ce265a54SOllivier Robert (INFO_ITEMSIZE(inpkt->mbz_itemsize) * 5492b15cb3dSCy Schubert INFO_NITEMS(inpkt->err_nitems)) + 5502b15cb3dSCy Schubert REQ_TAIL_MIN)) { 551ce265a54SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 5522b15cb3dSCy Schubert return; 553ce265a54SOllivier Robert } 554ce265a54SOllivier Robert 555c0b746e5SOllivier Robert /* 5562b15cb3dSCy Schubert * For 16-octet digests, regardless of itemsize and 5572b15cb3dSCy Schubert * nitems, authenticated requests are a fixed size 5582b15cb3dSCy Schubert * with the timestamp, key ID, and digest located 5592b15cb3dSCy Schubert * at the end of the packet. Because the key ID 5602b15cb3dSCy Schubert * determining the digest size precedes the digest, 5612b15cb3dSCy Schubert * for larger digests the fixed size request scheme 5622b15cb3dSCy Schubert * is abandoned and the timestamp, key ID, and digest 5632b15cb3dSCy Schubert * are located relative to the start of the packet, 5642b15cb3dSCy Schubert * with the digest size determined by the packet size. 565c0b746e5SOllivier Robert */ 5662b15cb3dSCy Schubert noslop_len = REQ_LEN_HDR 5672b15cb3dSCy Schubert + INFO_ITEMSIZE(inpkt->mbz_itemsize) * 5682b15cb3dSCy Schubert INFO_NITEMS(inpkt->err_nitems) 5692b15cb3dSCy Schubert + sizeof(inpkt->tstamp); 5702b15cb3dSCy Schubert /* 32-bit alignment */ 5712b15cb3dSCy Schubert noslop_len = (noslop_len + 3) & ~3; 5722b15cb3dSCy Schubert if (recv_len > (noslop_len + MAX_MAC_LEN)) 5732b15cb3dSCy Schubert mac_len = 20; 5742b15cb3dSCy Schubert else 5752b15cb3dSCy Schubert mac_len = recv_len - noslop_len; 5762b15cb3dSCy Schubert 5772b15cb3dSCy Schubert tailinpkt = (void *)((char *)inpkt + recv_len - 5782b15cb3dSCy Schubert (mac_len + sizeof(inpkt->tstamp))); 5792b15cb3dSCy Schubert 5802b15cb3dSCy Schubert /* 5812b15cb3dSCy Schubert * If this guy is restricted from doing this, don't let 5822b15cb3dSCy Schubert * him. If the wrong key was used, or packet doesn't 5832b15cb3dSCy Schubert * have mac, return. 5842b15cb3dSCy Schubert */ 58509100258SXin LI /* XXX: Use authistrustedip(), or equivalent. */ 5862b15cb3dSCy Schubert if (!INFO_IS_AUTH(inpkt->auth_seq) || !info_auth_keyid 587ce265a54SOllivier Robert || ntohl(tailinpkt->keyid) != info_auth_keyid) { 5882b15cb3dSCy Schubert DPRINTF(5, ("failed auth %d info_auth_keyid %u pkt keyid %u maclen %lu\n", 5892b15cb3dSCy Schubert INFO_IS_AUTH(inpkt->auth_seq), 5902b15cb3dSCy Schubert info_auth_keyid, 5912b15cb3dSCy Schubert ntohl(tailinpkt->keyid), (u_long)mac_len)); 592c0b746e5SOllivier Robert #ifdef DEBUG 5939c2daa00SOllivier Robert msyslog(LOG_DEBUG, 5942b15cb3dSCy Schubert "process_private: failed auth %d info_auth_keyid %u pkt keyid %u maclen %lu\n", 5959c2daa00SOllivier Robert INFO_IS_AUTH(inpkt->auth_seq), 5962b15cb3dSCy Schubert info_auth_keyid, 5972b15cb3dSCy Schubert ntohl(tailinpkt->keyid), (u_long)mac_len); 598c0b746e5SOllivier Robert #endif 599c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 600c0b746e5SOllivier Robert return; 601c0b746e5SOllivier Robert } 6022b15cb3dSCy Schubert if (recv_len > REQ_LEN_NOMAC + MAX_MAC_LEN) { 6032b15cb3dSCy Schubert DPRINTF(5, ("bad pkt length %zu\n", recv_len)); 6042b15cb3dSCy Schubert msyslog(LOG_ERR, 6052b15cb3dSCy Schubert "process_private: bad pkt length %zu", 6062b15cb3dSCy Schubert recv_len); 607c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 608c0b746e5SOllivier Robert return; 609c0b746e5SOllivier Robert } 610c0b746e5SOllivier Robert if (!mod_okay || !authhavekey(info_auth_keyid)) { 6112b15cb3dSCy Schubert DPRINTF(5, ("failed auth mod_okay %d\n", 6122b15cb3dSCy Schubert mod_okay)); 613c0b746e5SOllivier Robert #ifdef DEBUG 6149c2daa00SOllivier Robert msyslog(LOG_DEBUG, 6159c2daa00SOllivier Robert "process_private: failed auth mod_okay %d\n", 6169c2daa00SOllivier Robert mod_okay); 617c0b746e5SOllivier Robert #endif 6182b15cb3dSCy Schubert if (!mod_okay) { 6192b15cb3dSCy Schubert sys_restricted++; 6202b15cb3dSCy Schubert } 621c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 622c0b746e5SOllivier Robert return; 623c0b746e5SOllivier Robert } 624c0b746e5SOllivier Robert 625c0b746e5SOllivier Robert /* 626c0b746e5SOllivier Robert * calculate absolute time difference between xmit time stamp 627c0b746e5SOllivier Robert * and receive time stamp. If too large, too bad. 628c0b746e5SOllivier Robert */ 629ce265a54SOllivier Robert NTOHL_FP(&tailinpkt->tstamp, &ftmp); 630c0b746e5SOllivier Robert L_SUB(&ftmp, &rbufp->recv_time); 631c0b746e5SOllivier Robert LFPTOD(&ftmp, dtemp); 6322b15cb3dSCy Schubert if (fabs(dtemp) > INFO_TS_MAXSKEW) { 633c0b746e5SOllivier Robert /* 634c0b746e5SOllivier Robert * He's a loser. Tell him. 635c0b746e5SOllivier Robert */ 6362b15cb3dSCy Schubert DPRINTF(5, ("xmit/rcv timestamp delta %g > INFO_TS_MAXSKEW %g\n", 6372b15cb3dSCy Schubert dtemp, INFO_TS_MAXSKEW)); 638c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 639c0b746e5SOllivier Robert return; 640c0b746e5SOllivier Robert } 641c0b746e5SOllivier Robert 642c0b746e5SOllivier Robert /* 643c0b746e5SOllivier Robert * So far so good. See if decryption works out okay. 644c0b746e5SOllivier Robert */ 645c0b746e5SOllivier Robert if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt, 6462b15cb3dSCy Schubert recv_len - mac_len, mac_len)) { 6472b15cb3dSCy Schubert DPRINTF(5, ("authdecrypt failed\n")); 648c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 649c0b746e5SOllivier Robert return; 650c0b746e5SOllivier Robert } 651c0b746e5SOllivier Robert } 652c0b746e5SOllivier Robert 6532b15cb3dSCy Schubert DPRINTF(3, ("process_private: all okay, into handler\n")); 654c0b746e5SOllivier Robert /* 655c0b746e5SOllivier Robert * Packet is okay. Call the handler to send him data. 656c0b746e5SOllivier Robert */ 657c0b746e5SOllivier Robert (proc->handler)(srcadr, inter, inpkt); 658c0b746e5SOllivier Robert } 659c0b746e5SOllivier Robert 660c0b746e5SOllivier Robert 661c0b746e5SOllivier Robert /* 6622b15cb3dSCy Schubert * list_peers - send a list of the peers 663c0b746e5SOllivier Robert */ 664c0b746e5SOllivier Robert static void 6652b15cb3dSCy Schubert list_peers( 6662b15cb3dSCy Schubert sockaddr_u *srcadr, 6672b15cb3dSCy Schubert endpt *inter, 668c0b746e5SOllivier Robert struct req_pkt *inpkt 669c0b746e5SOllivier Robert ) 670c0b746e5SOllivier Robert { 6712b15cb3dSCy Schubert struct info_peer_list * ip; 67268ba7e87SXin LI const struct peer * pp; 673c0b746e5SOllivier Robert 674c0b746e5SOllivier Robert ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt, 6759c2daa00SOllivier Robert v6sizeof(struct info_peer_list)); 6762b15cb3dSCy Schubert for (pp = peer_list; pp != NULL && ip != NULL; pp = pp->p_link) { 6772b15cb3dSCy Schubert if (IS_IPV6(&pp->srcadr)) { 67868ba7e87SXin LI if (!client_v6_capable) 67968ba7e87SXin LI continue; 6802b15cb3dSCy Schubert ip->addr6 = SOCK_ADDR6(&pp->srcadr); 6819c2daa00SOllivier Robert ip->v6_flag = 1; 6829c2daa00SOllivier Robert } else { 6832b15cb3dSCy Schubert ip->addr = NSRCADR(&pp->srcadr); 6849c2daa00SOllivier Robert if (client_v6_capable) 6859c2daa00SOllivier Robert ip->v6_flag = 0; 6869c2daa00SOllivier Robert } 6879c2daa00SOllivier Robert 6889c2daa00SOllivier Robert ip->port = NSRCPORT(&pp->srcadr); 689c0b746e5SOllivier Robert ip->hmode = pp->hmode; 690c0b746e5SOllivier Robert ip->flags = 0; 691c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 692c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 693c0b746e5SOllivier Robert if (pp == sys_peer) 694c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 695c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 696c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 697c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 698c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 699c0b746e5SOllivier Robert ip = (struct info_peer_list *)more_pkt(); 7002b15cb3dSCy Schubert } /* for pp */ 7012b15cb3dSCy Schubert 702c0b746e5SOllivier Robert flush_pkt(); 703c0b746e5SOllivier Robert } 704c0b746e5SOllivier Robert 705c0b746e5SOllivier Robert 706c0b746e5SOllivier Robert /* 7072b15cb3dSCy Schubert * list_peers_sum - return extended peer list 708c0b746e5SOllivier Robert */ 709c0b746e5SOllivier Robert static void 7102b15cb3dSCy Schubert list_peers_sum( 7112b15cb3dSCy Schubert sockaddr_u *srcadr, 7122b15cb3dSCy Schubert endpt *inter, 713c0b746e5SOllivier Robert struct req_pkt *inpkt 714c0b746e5SOllivier Robert ) 715c0b746e5SOllivier Robert { 71668ba7e87SXin LI struct info_peer_summary * ips; 71768ba7e87SXin LI const struct peer * pp; 718c0b746e5SOllivier Robert l_fp ltmp; 719c0b746e5SOllivier Robert 7202b15cb3dSCy Schubert DPRINTF(3, ("wants peer list summary\n")); 7212b15cb3dSCy Schubert 722c0b746e5SOllivier Robert ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt, 7239c2daa00SOllivier Robert v6sizeof(struct info_peer_summary)); 7242b15cb3dSCy Schubert for (pp = peer_list; pp != NULL && ips != NULL; pp = pp->p_link) { 7252b15cb3dSCy Schubert DPRINTF(4, ("sum: got one\n")); 7269c2daa00SOllivier Robert /* 7279c2daa00SOllivier Robert * Be careful here not to return v6 peers when we 7289c2daa00SOllivier Robert * want only v4. 7299c2daa00SOllivier Robert */ 7302b15cb3dSCy Schubert if (IS_IPV6(&pp->srcadr)) { 73168ba7e87SXin LI if (!client_v6_capable) 73268ba7e87SXin LI continue; 7332b15cb3dSCy Schubert ips->srcadr6 = SOCK_ADDR6(&pp->srcadr); 7349c2daa00SOllivier Robert ips->v6_flag = 1; 735ea906c41SOllivier Robert if (pp->dstadr) 7362b15cb3dSCy Schubert ips->dstadr6 = SOCK_ADDR6(&pp->dstadr->sin); 737ea906c41SOllivier Robert else 7382b15cb3dSCy Schubert ZERO(ips->dstadr6); 7399c2daa00SOllivier Robert } else { 7402b15cb3dSCy Schubert ips->srcadr = NSRCADR(&pp->srcadr); 7419c2daa00SOllivier Robert if (client_v6_capable) 7429c2daa00SOllivier Robert ips->v6_flag = 0; 743ea906c41SOllivier Robert 7442b15cb3dSCy Schubert if (pp->dstadr) { 7452b15cb3dSCy Schubert if (!pp->processed) 7462b15cb3dSCy Schubert ips->dstadr = NSRCADR(&pp->dstadr->sin); 7472b15cb3dSCy Schubert else { 7482b15cb3dSCy Schubert if (MDF_BCAST == pp->cast_flags) 7492b15cb3dSCy Schubert ips->dstadr = NSRCADR(&pp->dstadr->bcast); 7502b15cb3dSCy Schubert else if (pp->cast_flags) { 7512b15cb3dSCy Schubert ips->dstadr = NSRCADR(&pp->dstadr->sin); 7522b15cb3dSCy Schubert if (!ips->dstadr) 7532b15cb3dSCy Schubert ips->dstadr = NSRCADR(&pp->dstadr->bcast); 7542b15cb3dSCy Schubert } 7552b15cb3dSCy Schubert } 75668ba7e87SXin LI } else { 7572b15cb3dSCy Schubert ips->dstadr = 0; 75868ba7e87SXin LI } 7599c2daa00SOllivier Robert } 760ea906c41SOllivier Robert 7619c2daa00SOllivier Robert ips->srcport = NSRCPORT(&pp->srcadr); 762c0b746e5SOllivier Robert ips->stratum = pp->stratum; 763c0b746e5SOllivier Robert ips->hpoll = pp->hpoll; 764c0b746e5SOllivier Robert ips->ppoll = pp->ppoll; 765c0b746e5SOllivier Robert ips->reach = pp->reach; 766c0b746e5SOllivier Robert ips->flags = 0; 767c0b746e5SOllivier Robert if (pp == sys_peer) 768c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SYSPEER; 769c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 770c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_CONFIG; 771c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 772c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_REFCLOCK; 773c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 774c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_PREFER; 775c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 776c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_BURST; 777c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 778c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SEL_CANDIDATE; 779c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 780c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SHORTLIST; 781c0b746e5SOllivier Robert ips->hmode = pp->hmode; 782c0b746e5SOllivier Robert ips->delay = HTONS_FP(DTOFP(pp->delay)); 783c0b746e5SOllivier Robert DTOLFP(pp->offset, <mp); 784c0b746e5SOllivier Robert HTONL_FP(<mp, &ips->offset); 785ea906c41SOllivier Robert ips->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); 78668ba7e87SXin LI 787c0b746e5SOllivier Robert ips = (struct info_peer_summary *)more_pkt(); 7882b15cb3dSCy Schubert } /* for pp */ 7892b15cb3dSCy Schubert 790c0b746e5SOllivier Robert flush_pkt(); 791c0b746e5SOllivier Robert } 792c0b746e5SOllivier Robert 793c0b746e5SOllivier Robert 794c0b746e5SOllivier Robert /* 795c0b746e5SOllivier Robert * peer_info - send information for one or more peers 796c0b746e5SOllivier Robert */ 797c0b746e5SOllivier Robert static void 798c0b746e5SOllivier Robert peer_info ( 7992b15cb3dSCy Schubert sockaddr_u *srcadr, 8002b15cb3dSCy Schubert endpt *inter, 801c0b746e5SOllivier Robert struct req_pkt *inpkt 802c0b746e5SOllivier Robert ) 803c0b746e5SOllivier Robert { 8042b15cb3dSCy Schubert u_short items; 8052b15cb3dSCy Schubert size_t item_sz; 8062b15cb3dSCy Schubert char * datap; 8072b15cb3dSCy Schubert struct info_peer_list ipl; 8082b15cb3dSCy Schubert struct peer * pp; 8092b15cb3dSCy Schubert struct info_peer * ip; 8102b15cb3dSCy Schubert int i; 8112b15cb3dSCy Schubert int j; 8122b15cb3dSCy Schubert sockaddr_u addr; 813c0b746e5SOllivier Robert l_fp ltmp; 814c0b746e5SOllivier Robert 815c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 8162b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 8172b15cb3dSCy Schubert datap = inpkt->u.data; 8182b15cb3dSCy Schubert if (item_sz != sizeof(ipl)) { 8192b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 8202b15cb3dSCy Schubert return; 8219c2daa00SOllivier Robert } 8222b15cb3dSCy Schubert ip = prepare_pkt(srcadr, inter, inpkt, 8232b15cb3dSCy Schubert v6sizeof(struct info_peer)); 8242b15cb3dSCy Schubert while (items-- > 0 && ip != NULL) { 8252b15cb3dSCy Schubert ZERO(ipl); 8262b15cb3dSCy Schubert memcpy(&ipl, datap, item_sz); 8272b15cb3dSCy Schubert ZERO_SOCK(&addr); 8282b15cb3dSCy Schubert NSRCPORT(&addr) = ipl.port; 8292b15cb3dSCy Schubert if (client_v6_capable && ipl.v6_flag) { 8302b15cb3dSCy Schubert AF(&addr) = AF_INET6; 8312b15cb3dSCy Schubert SOCK_ADDR6(&addr) = ipl.addr6; 8322b15cb3dSCy Schubert } else { 8332b15cb3dSCy Schubert AF(&addr) = AF_INET; 8342b15cb3dSCy Schubert NSRCADR(&addr) = ipl.addr; 8352b15cb3dSCy Schubert } 8362b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 8372b15cb3dSCy Schubert addr.sa.sa_len = SOCKLEN(&addr); 8389c2daa00SOllivier Robert #endif 8392b15cb3dSCy Schubert datap += item_sz; 840ea906c41SOllivier Robert 84109100258SXin LI pp = findexistingpeer(&addr, NULL, NULL, -1, 0, NULL); 8422b15cb3dSCy Schubert if (NULL == pp) 8432b15cb3dSCy Schubert continue; 8442d4e511cSCy Schubert if (IS_IPV6(&pp->srcadr)) { 8452b15cb3dSCy Schubert if (pp->dstadr) 8462b15cb3dSCy Schubert ip->dstadr6 = 8472b15cb3dSCy Schubert (MDF_BCAST == pp->cast_flags) 8482b15cb3dSCy Schubert ? SOCK_ADDR6(&pp->dstadr->bcast) 8492b15cb3dSCy Schubert : SOCK_ADDR6(&pp->dstadr->sin); 8502b15cb3dSCy Schubert else 8512b15cb3dSCy Schubert ZERO(ip->dstadr6); 8522b15cb3dSCy Schubert 8532b15cb3dSCy Schubert ip->srcadr6 = SOCK_ADDR6(&pp->srcadr); 8549c2daa00SOllivier Robert ip->v6_flag = 1; 8559c2daa00SOllivier Robert } else { 8562b15cb3dSCy Schubert if (pp->dstadr) { 8572b15cb3dSCy Schubert if (!pp->processed) 8582b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->sin); 8592b15cb3dSCy Schubert else { 8602b15cb3dSCy Schubert if (MDF_BCAST == pp->cast_flags) 8612b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->bcast); 8622b15cb3dSCy Schubert else if (pp->cast_flags) { 8632b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->sin); 8642b15cb3dSCy Schubert if (!ip->dstadr) 8652b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->bcast); 8662b15cb3dSCy Schubert } 8672b15cb3dSCy Schubert } 8682b15cb3dSCy Schubert } else 8692b15cb3dSCy Schubert ip->dstadr = 0; 8709c2daa00SOllivier Robert 8712b15cb3dSCy Schubert ip->srcadr = NSRCADR(&pp->srcadr); 8729c2daa00SOllivier Robert if (client_v6_capable) 8739c2daa00SOllivier Robert ip->v6_flag = 0; 8749c2daa00SOllivier Robert } 875c0b746e5SOllivier Robert ip->srcport = NSRCPORT(&pp->srcadr); 876c0b746e5SOllivier Robert ip->flags = 0; 877c0b746e5SOllivier Robert if (pp == sys_peer) 878c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 879c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 880c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 881c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 882c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_REFCLOCK; 883c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 884c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_PREFER; 885c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 886c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_BURST; 887c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 888c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 889c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 890c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 891c0b746e5SOllivier Robert ip->leap = pp->leap; 892c0b746e5SOllivier Robert ip->hmode = pp->hmode; 8934e1ef62aSXin LI ip->pmode = pp->pmode; 894c0b746e5SOllivier Robert ip->keyid = pp->keyid; 895c0b746e5SOllivier Robert ip->stratum = pp->stratum; 896c0b746e5SOllivier Robert ip->ppoll = pp->ppoll; 897c0b746e5SOllivier Robert ip->hpoll = pp->hpoll; 898c0b746e5SOllivier Robert ip->precision = pp->precision; 899c0b746e5SOllivier Robert ip->version = pp->version; 900c0b746e5SOllivier Robert ip->reach = pp->reach; 9019c2daa00SOllivier Robert ip->unreach = (u_char)pp->unreach; 902c0b746e5SOllivier Robert ip->flash = (u_char)pp->flash; 9039c2daa00SOllivier Robert ip->flash2 = (u_short)pp->flash; 9042b15cb3dSCy Schubert ip->estbdelay = HTONS_FP(DTOFP(pp->delay)); 9052b15cb3dSCy Schubert ip->ttl = (u_char)pp->ttl; 906c0b746e5SOllivier Robert ip->associd = htons(pp->associd); 907c0b746e5SOllivier Robert ip->rootdelay = HTONS_FP(DTOUFP(pp->rootdelay)); 9082b15cb3dSCy Schubert ip->rootdispersion = HTONS_FP(DTOUFP(pp->rootdisp)); 909c0b746e5SOllivier Robert ip->refid = pp->refid; 910c0b746e5SOllivier Robert HTONL_FP(&pp->reftime, &ip->reftime); 9112b15cb3dSCy Schubert HTONL_FP(&pp->aorg, &ip->org); 912c0b746e5SOllivier Robert HTONL_FP(&pp->rec, &ip->rec); 913c0b746e5SOllivier Robert HTONL_FP(&pp->xmt, &ip->xmt); 914c0b746e5SOllivier Robert j = pp->filter_nextpt - 1; 915c0b746e5SOllivier Robert for (i = 0; i < NTP_SHIFT; i++, j--) { 916c0b746e5SOllivier Robert if (j < 0) 917c0b746e5SOllivier Robert j = NTP_SHIFT-1; 918c0b746e5SOllivier Robert ip->filtdelay[i] = HTONS_FP(DTOFP(pp->filter_delay[j])); 919c0b746e5SOllivier Robert DTOLFP(pp->filter_offset[j], <mp); 920c0b746e5SOllivier Robert HTONL_FP(<mp, &ip->filtoffset[i]); 9212b15cb3dSCy Schubert ip->order[i] = (u_char)((pp->filter_nextpt + 9222b15cb3dSCy Schubert NTP_SHIFT - 1) - 9232b15cb3dSCy Schubert pp->filter_order[i]); 924c0b746e5SOllivier Robert if (ip->order[i] >= NTP_SHIFT) 925c0b746e5SOllivier Robert ip->order[i] -= NTP_SHIFT; 926c0b746e5SOllivier Robert } 927c0b746e5SOllivier Robert DTOLFP(pp->offset, <mp); 928c0b746e5SOllivier Robert HTONL_FP(<mp, &ip->offset); 929c0b746e5SOllivier Robert ip->delay = HTONS_FP(DTOFP(pp->delay)); 930c0b746e5SOllivier Robert ip->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); 931224ba2bdSOllivier Robert ip->selectdisp = HTONS_FP(DTOUFP(SQRT(pp->jitter))); 9322b15cb3dSCy Schubert ip = more_pkt(); 933c0b746e5SOllivier Robert } 934c0b746e5SOllivier Robert flush_pkt(); 935c0b746e5SOllivier Robert } 936c0b746e5SOllivier Robert 937c0b746e5SOllivier Robert 938c0b746e5SOllivier Robert /* 939c0b746e5SOllivier Robert * peer_stats - send statistics for one or more peers 940c0b746e5SOllivier Robert */ 941c0b746e5SOllivier Robert static void 942c0b746e5SOllivier Robert peer_stats ( 9432b15cb3dSCy Schubert sockaddr_u *srcadr, 9442b15cb3dSCy Schubert endpt *inter, 945c0b746e5SOllivier Robert struct req_pkt *inpkt 946c0b746e5SOllivier Robert ) 947c0b746e5SOllivier Robert { 9482b15cb3dSCy Schubert u_short items; 9492b15cb3dSCy Schubert size_t item_sz; 9502b15cb3dSCy Schubert char * datap; 9512b15cb3dSCy Schubert struct info_peer_list ipl; 9522b15cb3dSCy Schubert struct peer * pp; 9532b15cb3dSCy Schubert struct info_peer_stats *ip; 9542b15cb3dSCy Schubert sockaddr_u addr; 955c0b746e5SOllivier Robert 9562b15cb3dSCy Schubert DPRINTF(1, ("peer_stats: called\n")); 957c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 9582b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 9592b15cb3dSCy Schubert datap = inpkt->u.data; 9602b15cb3dSCy Schubert if (item_sz > sizeof(ipl)) { 9612b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 9622b15cb3dSCy Schubert return; 9639c2daa00SOllivier Robert } 9642b15cb3dSCy Schubert ip = prepare_pkt(srcadr, inter, inpkt, 9652b15cb3dSCy Schubert v6sizeof(struct info_peer_stats)); 9662b15cb3dSCy Schubert while (items-- > 0 && ip != NULL) { 9672b15cb3dSCy Schubert ZERO(ipl); 9682b15cb3dSCy Schubert memcpy(&ipl, datap, item_sz); 9692b15cb3dSCy Schubert ZERO(addr); 9702b15cb3dSCy Schubert NSRCPORT(&addr) = ipl.port; 9712b15cb3dSCy Schubert if (client_v6_capable && ipl.v6_flag) { 9722b15cb3dSCy Schubert AF(&addr) = AF_INET6; 9732b15cb3dSCy Schubert SOCK_ADDR6(&addr) = ipl.addr6; 9742b15cb3dSCy Schubert } else { 9752b15cb3dSCy Schubert AF(&addr) = AF_INET; 9762b15cb3dSCy Schubert NSRCADR(&addr) = ipl.addr; 9772b15cb3dSCy Schubert } 9782b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 9792b15cb3dSCy Schubert addr.sa.sa_len = SOCKLEN(&addr); 9809c2daa00SOllivier Robert #endif 9812b15cb3dSCy Schubert DPRINTF(1, ("peer_stats: looking for %s, %d, %d\n", 9822b15cb3dSCy Schubert stoa(&addr), ipl.port, NSRCPORT(&addr))); 9839c2daa00SOllivier Robert 9842b15cb3dSCy Schubert datap += item_sz; 9852b15cb3dSCy Schubert 98609100258SXin LI pp = findexistingpeer(&addr, NULL, NULL, -1, 0, NULL); 9872b15cb3dSCy Schubert if (NULL == pp) 988c0b746e5SOllivier Robert continue; 989ea906c41SOllivier Robert 9902b15cb3dSCy Schubert DPRINTF(1, ("peer_stats: found %s\n", stoa(&addr))); 9912b15cb3dSCy Schubert 9922b15cb3dSCy Schubert if (IS_IPV4(&pp->srcadr)) { 9932b15cb3dSCy Schubert if (pp->dstadr) { 9942b15cb3dSCy Schubert if (!pp->processed) 9952b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->sin); 9962b15cb3dSCy Schubert else { 9972b15cb3dSCy Schubert if (MDF_BCAST == pp->cast_flags) 9982b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->bcast); 9992b15cb3dSCy Schubert else if (pp->cast_flags) { 10002b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->sin); 10012b15cb3dSCy Schubert if (!ip->dstadr) 10022b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->bcast); 10032b15cb3dSCy Schubert } 10042b15cb3dSCy Schubert } 10052b15cb3dSCy Schubert } else 10062b15cb3dSCy Schubert ip->dstadr = 0; 10072b15cb3dSCy Schubert 10082b15cb3dSCy Schubert ip->srcadr = NSRCADR(&pp->srcadr); 10099c2daa00SOllivier Robert if (client_v6_capable) 10109c2daa00SOllivier Robert ip->v6_flag = 0; 10119c2daa00SOllivier Robert } else { 1012ea906c41SOllivier Robert if (pp->dstadr) 10132b15cb3dSCy Schubert ip->dstadr6 = 10142b15cb3dSCy Schubert (MDF_BCAST == pp->cast_flags) 10152b15cb3dSCy Schubert ? SOCK_ADDR6(&pp->dstadr->bcast) 10162b15cb3dSCy Schubert : SOCK_ADDR6(&pp->dstadr->sin); 1017ea906c41SOllivier Robert else 10182b15cb3dSCy Schubert ZERO(ip->dstadr6); 1019ea906c41SOllivier Robert 10202b15cb3dSCy Schubert ip->srcadr6 = SOCK_ADDR6(&pp->srcadr); 10219c2daa00SOllivier Robert ip->v6_flag = 1; 10229c2daa00SOllivier Robert } 1023c0b746e5SOllivier Robert ip->srcport = NSRCPORT(&pp->srcadr); 1024c0b746e5SOllivier Robert ip->flags = 0; 1025c0b746e5SOllivier Robert if (pp == sys_peer) 1026c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 1027c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 1028c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 1029c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 1030c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_REFCLOCK; 1031c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 1032c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_PREFER; 1033c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 1034c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_BURST; 1035ea906c41SOllivier Robert if (pp->flags & FLAG_IBURST) 1036ea906c41SOllivier Robert ip->flags |= INFO_FLAG_IBURST; 1037c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 1038c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 1039c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 1040c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 1041ea906c41SOllivier Robert ip->flags = htons(ip->flags); 1042c0b746e5SOllivier Robert ip->timereceived = htonl((u_int32)(current_time - pp->timereceived)); 1043c0b746e5SOllivier Robert ip->timetosend = htonl(pp->nextdate - current_time); 1044c0b746e5SOllivier Robert ip->timereachable = htonl((u_int32)(current_time - pp->timereachable)); 1045c0b746e5SOllivier Robert ip->sent = htonl((u_int32)(pp->sent)); 1046c0b746e5SOllivier Robert ip->processed = htonl((u_int32)(pp->processed)); 1047c0b746e5SOllivier Robert ip->badauth = htonl((u_int32)(pp->badauth)); 1048c0b746e5SOllivier Robert ip->bogusorg = htonl((u_int32)(pp->bogusorg)); 1049c0b746e5SOllivier Robert ip->oldpkt = htonl((u_int32)(pp->oldpkt)); 1050c0b746e5SOllivier Robert ip->seldisp = htonl((u_int32)(pp->seldisptoolarge)); 1051c0b746e5SOllivier Robert ip->selbroken = htonl((u_int32)(pp->selbroken)); 1052c0b746e5SOllivier Robert ip->candidate = pp->status; 1053c0b746e5SOllivier Robert ip = (struct info_peer_stats *)more_pkt(); 1054c0b746e5SOllivier Robert } 1055c0b746e5SOllivier Robert flush_pkt(); 1056c0b746e5SOllivier Robert } 1057c0b746e5SOllivier Robert 1058c0b746e5SOllivier Robert 1059c0b746e5SOllivier Robert /* 1060c0b746e5SOllivier Robert * sys_info - return system info 1061c0b746e5SOllivier Robert */ 1062c0b746e5SOllivier Robert static void 1063c0b746e5SOllivier Robert sys_info( 10642b15cb3dSCy Schubert sockaddr_u *srcadr, 10652b15cb3dSCy Schubert endpt *inter, 1066c0b746e5SOllivier Robert struct req_pkt *inpkt 1067c0b746e5SOllivier Robert ) 1068c0b746e5SOllivier Robert { 1069c0b746e5SOllivier Robert register struct info_sys *is; 1070c0b746e5SOllivier Robert 1071c0b746e5SOllivier Robert is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt, 10729c2daa00SOllivier Robert v6sizeof(struct info_sys)); 1073c0b746e5SOllivier Robert 10742b15cb3dSCy Schubert if (sys_peer) { 10752b15cb3dSCy Schubert if (IS_IPV4(&sys_peer->srcadr)) { 10762b15cb3dSCy Schubert is->peer = NSRCADR(&sys_peer->srcadr); 10779c2daa00SOllivier Robert if (client_v6_capable) 10789c2daa00SOllivier Robert is->v6_flag = 0; 10799c2daa00SOllivier Robert } else if (client_v6_capable) { 10802b15cb3dSCy Schubert is->peer6 = SOCK_ADDR6(&sys_peer->srcadr); 10819c2daa00SOllivier Robert is->v6_flag = 1; 10829c2daa00SOllivier Robert } 1083c0b746e5SOllivier Robert is->peer_mode = sys_peer->hmode; 1084c0b746e5SOllivier Robert } else { 1085c0b746e5SOllivier Robert is->peer = 0; 10869c2daa00SOllivier Robert if (client_v6_capable) { 10879c2daa00SOllivier Robert is->v6_flag = 0; 10889c2daa00SOllivier Robert } 1089c0b746e5SOllivier Robert is->peer_mode = 0; 1090c0b746e5SOllivier Robert } 10919c2daa00SOllivier Robert 1092c0b746e5SOllivier Robert is->leap = sys_leap; 1093c0b746e5SOllivier Robert is->stratum = sys_stratum; 1094c0b746e5SOllivier Robert is->precision = sys_precision; 1095c0b746e5SOllivier Robert is->rootdelay = htonl(DTOFP(sys_rootdelay)); 10962b15cb3dSCy Schubert is->rootdispersion = htonl(DTOUFP(sys_rootdisp)); 1097224ba2bdSOllivier Robert is->frequency = htonl(DTOFP(sys_jitter)); 10982b15cb3dSCy Schubert is->stability = htonl(DTOUFP(clock_stability * 1e6)); 1099c0b746e5SOllivier Robert is->refid = sys_refid; 1100c0b746e5SOllivier Robert HTONL_FP(&sys_reftime, &is->reftime); 1101c0b746e5SOllivier Robert 1102c0b746e5SOllivier Robert is->poll = sys_poll; 1103c0b746e5SOllivier Robert 1104c0b746e5SOllivier Robert is->flags = 0; 1105c0b746e5SOllivier Robert if (sys_authenticate) 1106c0b746e5SOllivier Robert is->flags |= INFO_FLAG_AUTHENTICATE; 1107a466cc55SCy Schubert if (sys_bclient || sys_mclient) 1108ce265a54SOllivier Robert is->flags |= INFO_FLAG_BCLIENT; 1109ce265a54SOllivier Robert #ifdef REFCLOCK 1110ce265a54SOllivier Robert if (cal_enable) 1111ce265a54SOllivier Robert is->flags |= INFO_FLAG_CAL; 1112ce265a54SOllivier Robert #endif /* REFCLOCK */ 1113c0b746e5SOllivier Robert if (kern_enable) 1114c0b746e5SOllivier Robert is->flags |= INFO_FLAG_KERNEL; 1115c0b746e5SOllivier Robert if (mon_enabled != MON_OFF) 1116c0b746e5SOllivier Robert is->flags |= INFO_FLAG_MONITOR; 1117ce265a54SOllivier Robert if (ntp_enable) 1118ce265a54SOllivier Robert is->flags |= INFO_FLAG_NTP; 11192b15cb3dSCy Schubert if (hardpps_enable) 1120ce265a54SOllivier Robert is->flags |= INFO_FLAG_PPS_SYNC; 1121c0b746e5SOllivier Robert if (stats_control) 1122c0b746e5SOllivier Robert is->flags |= INFO_FLAG_FILEGEN; 1123c0b746e5SOllivier Robert is->bdelay = HTONS_FP(DTOFP(sys_bdelay)); 11242b15cb3dSCy Schubert HTONL_UF(sys_authdelay.l_uf, &is->authdelay); 1125c0b746e5SOllivier Robert (void) more_pkt(); 1126c0b746e5SOllivier Robert flush_pkt(); 1127c0b746e5SOllivier Robert } 1128c0b746e5SOllivier Robert 1129c0b746e5SOllivier Robert 1130c0b746e5SOllivier Robert /* 1131c0b746e5SOllivier Robert * sys_stats - return system statistics 1132c0b746e5SOllivier Robert */ 1133c0b746e5SOllivier Robert static void 1134c0b746e5SOllivier Robert sys_stats( 11352b15cb3dSCy Schubert sockaddr_u *srcadr, 11362b15cb3dSCy Schubert endpt *inter, 1137c0b746e5SOllivier Robert struct req_pkt *inpkt 1138c0b746e5SOllivier Robert ) 1139c0b746e5SOllivier Robert { 1140c0b746e5SOllivier Robert register struct info_sys_stats *ss; 1141c0b746e5SOllivier Robert 1142c0b746e5SOllivier Robert ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt, 1143c0b746e5SOllivier Robert sizeof(struct info_sys_stats)); 1144c0b746e5SOllivier Robert ss->timeup = htonl((u_int32)current_time); 1145c0b746e5SOllivier Robert ss->timereset = htonl((u_int32)(current_time - sys_stattime)); 11469c2daa00SOllivier Robert ss->denied = htonl((u_int32)sys_restricted); 11472b15cb3dSCy Schubert ss->oldversionpkt = htonl((u_int32)sys_oldversion); 11482b15cb3dSCy Schubert ss->newversionpkt = htonl((u_int32)sys_newversion); 11492b15cb3dSCy Schubert ss->unknownversion = htonl((u_int32)sys_declined); 1150c0b746e5SOllivier Robert ss->badlength = htonl((u_int32)sys_badlength); 1151c0b746e5SOllivier Robert ss->processed = htonl((u_int32)sys_processed); 1152c0b746e5SOllivier Robert ss->badauth = htonl((u_int32)sys_badauth); 1153c0b746e5SOllivier Robert ss->limitrejected = htonl((u_int32)sys_limitrejected); 11549c2daa00SOllivier Robert ss->received = htonl((u_int32)sys_received); 115509100258SXin LI ss->lamport = htonl((u_int32)sys_lamport); 115609100258SXin LI ss->tsrounding = htonl((u_int32)sys_tsrounding); 1157c0b746e5SOllivier Robert (void) more_pkt(); 1158c0b746e5SOllivier Robert flush_pkt(); 1159c0b746e5SOllivier Robert } 1160c0b746e5SOllivier Robert 1161c0b746e5SOllivier Robert 1162c0b746e5SOllivier Robert /* 1163c0b746e5SOllivier Robert * mem_stats - return memory statistics 1164c0b746e5SOllivier Robert */ 1165c0b746e5SOllivier Robert static void 1166c0b746e5SOllivier Robert mem_stats( 11672b15cb3dSCy Schubert sockaddr_u *srcadr, 11682b15cb3dSCy Schubert endpt *inter, 1169c0b746e5SOllivier Robert struct req_pkt *inpkt 1170c0b746e5SOllivier Robert ) 1171c0b746e5SOllivier Robert { 1172c0b746e5SOllivier Robert register struct info_mem_stats *ms; 1173c0b746e5SOllivier Robert register int i; 1174c0b746e5SOllivier Robert 1175c0b746e5SOllivier Robert ms = (struct info_mem_stats *)prepare_pkt(srcadr, inter, inpkt, 1176c0b746e5SOllivier Robert sizeof(struct info_mem_stats)); 1177c0b746e5SOllivier Robert 1178c0b746e5SOllivier Robert ms->timereset = htonl((u_int32)(current_time - peer_timereset)); 1179c0b746e5SOllivier Robert ms->totalpeermem = htons((u_short)total_peer_structs); 1180c0b746e5SOllivier Robert ms->freepeermem = htons((u_short)peer_free_count); 1181c0b746e5SOllivier Robert ms->findpeer_calls = htonl((u_int32)findpeer_calls); 1182c0b746e5SOllivier Robert ms->allocations = htonl((u_int32)peer_allocations); 1183c0b746e5SOllivier Robert ms->demobilizations = htonl((u_int32)peer_demobilizations); 1184c0b746e5SOllivier Robert 11852b15cb3dSCy Schubert for (i = 0; i < NTP_HASH_SIZE; i++) 11862b15cb3dSCy Schubert ms->hashcount[i] = (u_char) 1187767173ceSCy Schubert min((u_int)peer_hash_count[i], UCHAR_MAX); 1188c0b746e5SOllivier Robert 118968ba7e87SXin LI (void) more_pkt(); 1190c0b746e5SOllivier Robert flush_pkt(); 1191c0b746e5SOllivier Robert } 1192c0b746e5SOllivier Robert 1193c0b746e5SOllivier Robert 1194c0b746e5SOllivier Robert /* 1195c0b746e5SOllivier Robert * io_stats - return io statistics 1196c0b746e5SOllivier Robert */ 1197c0b746e5SOllivier Robert static void 1198c0b746e5SOllivier Robert io_stats( 11992b15cb3dSCy Schubert sockaddr_u *srcadr, 12002b15cb3dSCy Schubert endpt *inter, 1201c0b746e5SOllivier Robert struct req_pkt *inpkt 1202c0b746e5SOllivier Robert ) 1203c0b746e5SOllivier Robert { 12042b15cb3dSCy Schubert struct info_io_stats *io; 1205c0b746e5SOllivier Robert 1206c0b746e5SOllivier Robert io = (struct info_io_stats *)prepare_pkt(srcadr, inter, inpkt, 1207c0b746e5SOllivier Robert sizeof(struct info_io_stats)); 1208c0b746e5SOllivier Robert 1209c0b746e5SOllivier Robert io->timereset = htonl((u_int32)(current_time - io_timereset)); 1210c0b746e5SOllivier Robert io->totalrecvbufs = htons((u_short) total_recvbuffs()); 1211c0b746e5SOllivier Robert io->freerecvbufs = htons((u_short) free_recvbuffs()); 1212c0b746e5SOllivier Robert io->fullrecvbufs = htons((u_short) full_recvbuffs()); 1213c0b746e5SOllivier Robert io->lowwater = htons((u_short) lowater_additions()); 1214c0b746e5SOllivier Robert io->dropped = htonl((u_int32)packets_dropped); 1215c0b746e5SOllivier Robert io->ignored = htonl((u_int32)packets_ignored); 1216c0b746e5SOllivier Robert io->received = htonl((u_int32)packets_received); 1217c0b746e5SOllivier Robert io->sent = htonl((u_int32)packets_sent); 1218c0b746e5SOllivier Robert io->notsent = htonl((u_int32)packets_notsent); 1219c0b746e5SOllivier Robert io->interrupts = htonl((u_int32)handler_calls); 1220c0b746e5SOllivier Robert io->int_received = htonl((u_int32)handler_pkts); 1221c0b746e5SOllivier Robert 1222c0b746e5SOllivier Robert (void) more_pkt(); 1223c0b746e5SOllivier Robert flush_pkt(); 1224c0b746e5SOllivier Robert } 1225c0b746e5SOllivier Robert 1226c0b746e5SOllivier Robert 1227c0b746e5SOllivier Robert /* 1228c0b746e5SOllivier Robert * timer_stats - return timer statistics 1229c0b746e5SOllivier Robert */ 1230c0b746e5SOllivier Robert static void 1231c0b746e5SOllivier Robert timer_stats( 12322b15cb3dSCy Schubert sockaddr_u * srcadr, 12332b15cb3dSCy Schubert endpt * inter, 1234c0b746e5SOllivier Robert struct req_pkt * inpkt 1235c0b746e5SOllivier Robert ) 1236c0b746e5SOllivier Robert { 12372b15cb3dSCy Schubert struct info_timer_stats * ts; 12382b15cb3dSCy Schubert u_long sincereset; 1239c0b746e5SOllivier Robert 12402b15cb3dSCy Schubert ts = (struct info_timer_stats *)prepare_pkt(srcadr, inter, 12412b15cb3dSCy Schubert inpkt, sizeof(*ts)); 1242c0b746e5SOllivier Robert 12432b15cb3dSCy Schubert sincereset = current_time - timer_timereset; 12442b15cb3dSCy Schubert ts->timereset = htonl((u_int32)sincereset); 12452b15cb3dSCy Schubert ts->alarms = ts->timereset; 12462b15cb3dSCy Schubert ts->overflows = htonl((u_int32)alarm_overflow); 1247c0b746e5SOllivier Robert ts->xmtcalls = htonl((u_int32)timer_xmtcalls); 1248c0b746e5SOllivier Robert 1249c0b746e5SOllivier Robert (void) more_pkt(); 1250c0b746e5SOllivier Robert flush_pkt(); 1251c0b746e5SOllivier Robert } 1252c0b746e5SOllivier Robert 1253c0b746e5SOllivier Robert 1254c0b746e5SOllivier Robert /* 1255c0b746e5SOllivier Robert * loop_info - return the current state of the loop filter 1256c0b746e5SOllivier Robert */ 1257c0b746e5SOllivier Robert static void 1258c0b746e5SOllivier Robert loop_info( 12592b15cb3dSCy Schubert sockaddr_u *srcadr, 12602b15cb3dSCy Schubert endpt *inter, 1261c0b746e5SOllivier Robert struct req_pkt *inpkt 1262c0b746e5SOllivier Robert ) 1263c0b746e5SOllivier Robert { 12642b15cb3dSCy Schubert struct info_loop *li; 1265c0b746e5SOllivier Robert l_fp ltmp; 1266c0b746e5SOllivier Robert 1267c0b746e5SOllivier Robert li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt, 1268c0b746e5SOllivier Robert sizeof(struct info_loop)); 1269c0b746e5SOllivier Robert 1270c0b746e5SOllivier Robert DTOLFP(last_offset, <mp); 1271c0b746e5SOllivier Robert HTONL_FP(<mp, &li->last_offset); 1272c0b746e5SOllivier Robert DTOLFP(drift_comp * 1e6, <mp); 1273c0b746e5SOllivier Robert HTONL_FP(<mp, &li->drift_comp); 1274c0b746e5SOllivier Robert li->compliance = htonl((u_int32)(tc_counter)); 12752b15cb3dSCy Schubert li->watchdog_timer = htonl((u_int32)(current_time - sys_epoch)); 1276c0b746e5SOllivier Robert 127768ba7e87SXin LI (void) more_pkt(); 1278c0b746e5SOllivier Robert flush_pkt(); 1279c0b746e5SOllivier Robert } 1280c0b746e5SOllivier Robert 1281c0b746e5SOllivier Robert 1282c0b746e5SOllivier Robert /* 1283c0b746e5SOllivier Robert * do_conf - add a peer to the configuration list 1284c0b746e5SOllivier Robert */ 1285c0b746e5SOllivier Robert static void 1286c0b746e5SOllivier Robert do_conf( 12872b15cb3dSCy Schubert sockaddr_u *srcadr, 12882b15cb3dSCy Schubert endpt *inter, 1289c0b746e5SOllivier Robert struct req_pkt *inpkt 1290c0b746e5SOllivier Robert ) 1291c0b746e5SOllivier Robert { 12922b15cb3dSCy Schubert u_short items; 12932b15cb3dSCy Schubert size_t item_sz; 1294224ba2bdSOllivier Robert u_int fl; 12952b15cb3dSCy Schubert char * datap; 12969c2daa00SOllivier Robert struct conf_peer temp_cp; 12972b15cb3dSCy Schubert sockaddr_u peeraddr; 1298c0b746e5SOllivier Robert 1299c0b746e5SOllivier Robert /* 1300c0b746e5SOllivier Robert * Do a check of everything to see that it looks 1301c0b746e5SOllivier Robert * okay. If not, complain about it. Note we are 1302c0b746e5SOllivier Robert * very picky here. 1303c0b746e5SOllivier Robert */ 1304c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 13052b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 13062b15cb3dSCy Schubert datap = inpkt->u.data; 13072b15cb3dSCy Schubert if (item_sz > sizeof(temp_cp)) { 1308c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1309c0b746e5SOllivier Robert return; 1310c0b746e5SOllivier Robert } 1311c0b746e5SOllivier Robert 13129c2daa00SOllivier Robert while (items-- > 0) { 13132b15cb3dSCy Schubert ZERO(temp_cp); 13142b15cb3dSCy Schubert memcpy(&temp_cp, datap, item_sz); 13152b15cb3dSCy Schubert ZERO_SOCK(&peeraddr); 13169c2daa00SOllivier Robert 13179c2daa00SOllivier Robert fl = 0; 13189c2daa00SOllivier Robert if (temp_cp.flags & CONF_FLAG_PREFER) 13199c2daa00SOllivier Robert fl |= FLAG_PREFER; 13209c2daa00SOllivier Robert if (temp_cp.flags & CONF_FLAG_BURST) 13219c2daa00SOllivier Robert fl |= FLAG_BURST; 1322ea906c41SOllivier Robert if (temp_cp.flags & CONF_FLAG_IBURST) 1323ea906c41SOllivier Robert fl |= FLAG_IBURST; 13242b15cb3dSCy Schubert #ifdef AUTOKEY 13259c2daa00SOllivier Robert if (temp_cp.flags & CONF_FLAG_SKEY) 13269c2daa00SOllivier Robert fl |= FLAG_SKEY; 13272b15cb3dSCy Schubert #endif /* AUTOKEY */ 13282b15cb3dSCy Schubert if (client_v6_capable && temp_cp.v6_flag) { 13292b15cb3dSCy Schubert AF(&peeraddr) = AF_INET6; 13302b15cb3dSCy Schubert SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6; 13319c2daa00SOllivier Robert } else { 13322b15cb3dSCy Schubert AF(&peeraddr) = AF_INET; 13332b15cb3dSCy Schubert NSRCADR(&peeraddr) = temp_cp.peeraddr; 1334c0b746e5SOllivier Robert /* 1335c0b746e5SOllivier Robert * Make sure the address is valid 1336c0b746e5SOllivier Robert */ 13372b15cb3dSCy Schubert if (!ISREFCLOCKADR(&peeraddr) && 13382b15cb3dSCy Schubert ISBADADR(&peeraddr)) { 1339c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1340c0b746e5SOllivier Robert return; 1341c0b746e5SOllivier Robert } 1342c0b746e5SOllivier Robert 13439c2daa00SOllivier Robert } 13449c2daa00SOllivier Robert NSRCPORT(&peeraddr) = htons(NTP_PORT); 13452b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 13462b15cb3dSCy Schubert peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 13479c2daa00SOllivier Robert #endif 13489c2daa00SOllivier Robert 13494990d495SXin LI /* check mode value: 0 <= hmode <= 6 13504990d495SXin LI * 13514990d495SXin LI * There's no good global define for that limit, and 13524990d495SXin LI * using a magic define is as good (or bad, actually) as 13534990d495SXin LI * a magic number. So we use the highest possible peer 13544990d495SXin LI * mode, and that is MODE_BCLIENT. 13554990d495SXin LI * 13564990d495SXin LI * [Bug 3009] claims that a problem occurs for hmode > 7, 13574990d495SXin LI * but the code in ntp_peer.c indicates trouble for any 13584990d495SXin LI * hmode > 6 ( --> MODE_BCLIENT). 13594990d495SXin LI */ 13604990d495SXin LI if (temp_cp.hmode > MODE_BCLIENT) { 13614990d495SXin LI req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 13624990d495SXin LI return; 13634990d495SXin LI } 13644990d495SXin LI 13654990d495SXin LI /* Any more checks on the values? Unchecked at this 13664990d495SXin LI * point: 13674990d495SXin LI * - version 13684990d495SXin LI * - ttl 13694990d495SXin LI * - keyid 13704990d495SXin LI * 13714990d495SXin LI * - minpoll/maxpoll, but they are treated properly 13724990d495SXin LI * for all cases internally. Checking not necessary. 137309100258SXin LI * 137409100258SXin LI * Note that we ignore any previously-specified ippeerlimit. 137509100258SXin LI * If we're told to create the peer, we create the peer. 13764990d495SXin LI */ 13774990d495SXin LI 13784990d495SXin LI /* finally create the peer */ 137909100258SXin LI if (peer_config(&peeraddr, NULL, NULL, -1, 13809c2daa00SOllivier Robert temp_cp.hmode, temp_cp.version, temp_cp.minpoll, 13819c2daa00SOllivier Robert temp_cp.maxpoll, fl, temp_cp.ttl, temp_cp.keyid, 13824990d495SXin LI NULL) == 0) 13834990d495SXin LI { 1384c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1385c0b746e5SOllivier Robert return; 1386c0b746e5SOllivier Robert } 1387eb6d21b4SOllivier Robert 13882b15cb3dSCy Schubert datap += item_sz; 1389eb6d21b4SOllivier Robert } 1390c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1391c0b746e5SOllivier Robert } 1392c0b746e5SOllivier Robert 1393224ba2bdSOllivier Robert 1394224ba2bdSOllivier Robert /* 1395c0b746e5SOllivier Robert * do_unconf - remove a peer from the configuration list 1396c0b746e5SOllivier Robert */ 1397c0b746e5SOllivier Robert static void 1398c0b746e5SOllivier Robert do_unconf( 13992b15cb3dSCy Schubert sockaddr_u * srcadr, 14002b15cb3dSCy Schubert endpt * inter, 1401c0b746e5SOllivier Robert struct req_pkt *inpkt 1402c0b746e5SOllivier Robert ) 1403c0b746e5SOllivier Robert { 14042b15cb3dSCy Schubert u_short items; 14052b15cb3dSCy Schubert size_t item_sz; 14062b15cb3dSCy Schubert char * datap; 14079c2daa00SOllivier Robert struct conf_unpeer temp_cp; 14082b15cb3dSCy Schubert struct peer * p; 14092b15cb3dSCy Schubert sockaddr_u peeraddr; 14104990d495SXin LI int loops; 1411c0b746e5SOllivier Robert 1412c0b746e5SOllivier Robert /* 1413c0b746e5SOllivier Robert * This is a bit unstructured, but I like to be careful. 1414c0b746e5SOllivier Robert * We check to see that every peer exists and is actually 1415c0b746e5SOllivier Robert * configured. If so, we remove them. If not, we return 1416c0b746e5SOllivier Robert * an error. 14174990d495SXin LI * 14184990d495SXin LI * [Bug 3011] Even if we checked all peers given in the request 14194990d495SXin LI * in a dry run, there's still a chance that the caller played 14204990d495SXin LI * unfair and gave the same peer multiple times. So we still 14214990d495SXin LI * have to be prepared for nasty surprises in the second run ;) 1422c0b746e5SOllivier Robert */ 14234990d495SXin LI 14244990d495SXin LI /* basic consistency checks */ 14252b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 14262b15cb3dSCy Schubert if (item_sz > sizeof(temp_cp)) { 14272b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 14282b15cb3dSCy Schubert return; 14299c2daa00SOllivier Robert } 14302b15cb3dSCy Schubert 14314990d495SXin LI /* now do two runs: first a dry run, then a busy one */ 14324990d495SXin LI for (loops = 0; loops != 2; ++loops) { 14334990d495SXin LI items = INFO_NITEMS(inpkt->err_nitems); 14344990d495SXin LI datap = inpkt->u.data; 14354990d495SXin LI while (items-- > 0) { 14364990d495SXin LI /* copy from request to local */ 14372b15cb3dSCy Schubert ZERO(temp_cp); 14382b15cb3dSCy Schubert memcpy(&temp_cp, datap, item_sz); 14394990d495SXin LI /* get address structure */ 14402b15cb3dSCy Schubert ZERO_SOCK(&peeraddr); 14412b15cb3dSCy Schubert if (client_v6_capable && temp_cp.v6_flag) { 14422b15cb3dSCy Schubert AF(&peeraddr) = AF_INET6; 14432b15cb3dSCy Schubert SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6; 14442b15cb3dSCy Schubert } else { 14452b15cb3dSCy Schubert AF(&peeraddr) = AF_INET; 14462b15cb3dSCy Schubert NSRCADR(&peeraddr) = temp_cp.peeraddr; 14472b15cb3dSCy Schubert } 14482b15cb3dSCy Schubert SET_PORT(&peeraddr, NTP_PORT); 14492b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 14502b15cb3dSCy Schubert peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 14519c2daa00SOllivier Robert #endif 14524990d495SXin LI DPRINTF(1, ("searching for %s\n", 14534990d495SXin LI stoa(&peeraddr))); 14544990d495SXin LI 14554990d495SXin LI /* search for matching configred(!) peer */ 14562b15cb3dSCy Schubert p = NULL; 14574990d495SXin LI do { 14584990d495SXin LI p = findexistingpeer( 145909100258SXin LI &peeraddr, NULL, p, -1, 0, NULL); 14604990d495SXin LI } while (p && !(FLAG_CONFIG & p->flags)); 14612b15cb3dSCy Schubert 14624990d495SXin LI if (!loops && !p) { 14634990d495SXin LI /* Item not found in dry run -- bail! */ 14644990d495SXin LI req_ack(srcadr, inter, inpkt, 14654990d495SXin LI INFO_ERR_NODATA); 1466c0b746e5SOllivier Robert return; 14674990d495SXin LI } else if (loops && p) { 14684990d495SXin LI /* Item found in busy run -- remove! */ 14692b15cb3dSCy Schubert peer_clear(p, "GONE"); 14702b15cb3dSCy Schubert unpeer(p); 14714990d495SXin LI } 14722b15cb3dSCy Schubert datap += item_sz; 1473c0b746e5SOllivier Robert } 14744990d495SXin LI } 1475c0b746e5SOllivier Robert 14764990d495SXin LI /* report success */ 1477c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1478c0b746e5SOllivier Robert } 1479c0b746e5SOllivier Robert 1480c0b746e5SOllivier Robert 1481c0b746e5SOllivier Robert /* 1482c0b746e5SOllivier Robert * set_sys_flag - set system flags 1483c0b746e5SOllivier Robert */ 1484c0b746e5SOllivier Robert static void 1485c0b746e5SOllivier Robert set_sys_flag( 14862b15cb3dSCy Schubert sockaddr_u *srcadr, 14872b15cb3dSCy Schubert endpt *inter, 1488c0b746e5SOllivier Robert struct req_pkt *inpkt 1489c0b746e5SOllivier Robert ) 1490c0b746e5SOllivier Robert { 1491c0b746e5SOllivier Robert setclr_flags(srcadr, inter, inpkt, 1); 1492c0b746e5SOllivier Robert } 1493c0b746e5SOllivier Robert 1494c0b746e5SOllivier Robert 1495c0b746e5SOllivier Robert /* 1496c0b746e5SOllivier Robert * clr_sys_flag - clear system flags 1497c0b746e5SOllivier Robert */ 1498c0b746e5SOllivier Robert static void 1499c0b746e5SOllivier Robert clr_sys_flag( 15002b15cb3dSCy Schubert sockaddr_u *srcadr, 15012b15cb3dSCy Schubert endpt *inter, 1502c0b746e5SOllivier Robert struct req_pkt *inpkt 1503c0b746e5SOllivier Robert ) 1504c0b746e5SOllivier Robert { 1505c0b746e5SOllivier Robert setclr_flags(srcadr, inter, inpkt, 0); 1506c0b746e5SOllivier Robert } 1507c0b746e5SOllivier Robert 1508c0b746e5SOllivier Robert 1509c0b746e5SOllivier Robert /* 1510c0b746e5SOllivier Robert * setclr_flags - do the grunge work of flag setting/clearing 1511c0b746e5SOllivier Robert */ 1512c0b746e5SOllivier Robert static void 1513c0b746e5SOllivier Robert setclr_flags( 15142b15cb3dSCy Schubert sockaddr_u *srcadr, 15152b15cb3dSCy Schubert endpt *inter, 1516c0b746e5SOllivier Robert struct req_pkt *inpkt, 1517c0b746e5SOllivier Robert u_long set 1518c0b746e5SOllivier Robert ) 1519c0b746e5SOllivier Robert { 15202b15cb3dSCy Schubert struct conf_sys_flags *sf; 15212b15cb3dSCy Schubert u_int32 flags; 1522c0b746e5SOllivier Robert 1523c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 1524224ba2bdSOllivier Robert msyslog(LOG_ERR, "setclr_flags: err_nitems > 1"); 1525c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1526c0b746e5SOllivier Robert return; 1527c0b746e5SOllivier Robert } 1528c0b746e5SOllivier Robert 15292b15cb3dSCy Schubert sf = (struct conf_sys_flags *)&inpkt->u; 15302b15cb3dSCy Schubert flags = ntohl(sf->flags); 1531c0b746e5SOllivier Robert 1532224ba2bdSOllivier Robert if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS | 1533c0b746e5SOllivier Robert SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR | 1534ce265a54SOllivier Robert SYS_FLAG_FILEGEN | SYS_FLAG_AUTH | SYS_FLAG_CAL)) { 1535224ba2bdSOllivier Robert msyslog(LOG_ERR, "setclr_flags: extra flags: %#x", 1536224ba2bdSOllivier Robert flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS | 1537224ba2bdSOllivier Robert SYS_FLAG_NTP | SYS_FLAG_KERNEL | 1538ce265a54SOllivier Robert SYS_FLAG_MONITOR | SYS_FLAG_FILEGEN | 1539ce265a54SOllivier Robert SYS_FLAG_AUTH | SYS_FLAG_CAL)); 1540c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1541c0b746e5SOllivier Robert return; 1542c0b746e5SOllivier Robert } 1543c0b746e5SOllivier Robert 1544c0b746e5SOllivier Robert if (flags & SYS_FLAG_BCLIENT) 15459c2daa00SOllivier Robert proto_config(PROTO_BROADCLIENT, set, 0., NULL); 1546224ba2bdSOllivier Robert if (flags & SYS_FLAG_PPS) 15479c2daa00SOllivier Robert proto_config(PROTO_PPS, set, 0., NULL); 1548c0b746e5SOllivier Robert if (flags & SYS_FLAG_NTP) 15499c2daa00SOllivier Robert proto_config(PROTO_NTP, set, 0., NULL); 1550c0b746e5SOllivier Robert if (flags & SYS_FLAG_KERNEL) 15519c2daa00SOllivier Robert proto_config(PROTO_KERNEL, set, 0., NULL); 1552c0b746e5SOllivier Robert if (flags & SYS_FLAG_MONITOR) 15539c2daa00SOllivier Robert proto_config(PROTO_MONITOR, set, 0., NULL); 1554c0b746e5SOllivier Robert if (flags & SYS_FLAG_FILEGEN) 15559c2daa00SOllivier Robert proto_config(PROTO_FILEGEN, set, 0., NULL); 1556ce265a54SOllivier Robert if (flags & SYS_FLAG_AUTH) 15579c2daa00SOllivier Robert proto_config(PROTO_AUTHENTICATE, set, 0., NULL); 1558ce265a54SOllivier Robert if (flags & SYS_FLAG_CAL) 15599c2daa00SOllivier Robert proto_config(PROTO_CAL, set, 0., NULL); 1560c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 15612b15cb3dSCy Schubert } 1562ea906c41SOllivier Robert 156368ba7e87SXin LI /* There have been some issues with the restrict list processing, 156468ba7e87SXin LI * ranging from problems with deep recursion (resulting in stack 156568ba7e87SXin LI * overflows) and overfull reply buffers. 156668ba7e87SXin LI * 156768ba7e87SXin LI * To avoid this trouble the list reversal is done iteratively using a 156868ba7e87SXin LI * scratch pad. 156968ba7e87SXin LI */ 157068ba7e87SXin LI typedef struct RestrictStack RestrictStackT; 157168ba7e87SXin LI struct RestrictStack { 157268ba7e87SXin LI RestrictStackT *link; 157368ba7e87SXin LI size_t fcnt; 157468ba7e87SXin LI const restrict_u *pres[63]; 157568ba7e87SXin LI }; 157668ba7e87SXin LI 157768ba7e87SXin LI static size_t 157868ba7e87SXin LI getStackSheetSize( 157968ba7e87SXin LI RestrictStackT *sp 158068ba7e87SXin LI ) 158168ba7e87SXin LI { 158268ba7e87SXin LI if (sp) 158368ba7e87SXin LI return sizeof(sp->pres)/sizeof(sp->pres[0]); 158468ba7e87SXin LI return 0u; 158568ba7e87SXin LI } 158668ba7e87SXin LI 158768ba7e87SXin LI static int/*BOOL*/ 158868ba7e87SXin LI pushRestriction( 158968ba7e87SXin LI RestrictStackT **spp, 159068ba7e87SXin LI const restrict_u *ptr 159168ba7e87SXin LI ) 159268ba7e87SXin LI { 159368ba7e87SXin LI RestrictStackT *sp; 159468ba7e87SXin LI 159568ba7e87SXin LI if (NULL == (sp = *spp) || 0 == sp->fcnt) { 159668ba7e87SXin LI /* need another sheet in the scratch pad */ 159768ba7e87SXin LI sp = emalloc(sizeof(*sp)); 159868ba7e87SXin LI sp->link = *spp; 159968ba7e87SXin LI sp->fcnt = getStackSheetSize(sp); 160068ba7e87SXin LI *spp = sp; 160168ba7e87SXin LI } 160268ba7e87SXin LI sp->pres[--sp->fcnt] = ptr; 160368ba7e87SXin LI return TRUE; 160468ba7e87SXin LI } 160568ba7e87SXin LI 160668ba7e87SXin LI static int/*BOOL*/ 160768ba7e87SXin LI popRestriction( 160868ba7e87SXin LI RestrictStackT **spp, 160968ba7e87SXin LI const restrict_u **opp 161068ba7e87SXin LI ) 161168ba7e87SXin LI { 161268ba7e87SXin LI RestrictStackT *sp; 161368ba7e87SXin LI 161468ba7e87SXin LI if (NULL == (sp = *spp) || sp->fcnt >= getStackSheetSize(sp)) 161568ba7e87SXin LI return FALSE; 161668ba7e87SXin LI 161768ba7e87SXin LI *opp = sp->pres[sp->fcnt++]; 161868ba7e87SXin LI if (sp->fcnt >= getStackSheetSize(sp)) { 161968ba7e87SXin LI /* discard sheet from scratch pad */ 162068ba7e87SXin LI *spp = sp->link; 162168ba7e87SXin LI free(sp); 162268ba7e87SXin LI } 162368ba7e87SXin LI return TRUE; 162468ba7e87SXin LI } 162568ba7e87SXin LI 162668ba7e87SXin LI static void 162768ba7e87SXin LI flushRestrictionStack( 162868ba7e87SXin LI RestrictStackT **spp 162968ba7e87SXin LI ) 163068ba7e87SXin LI { 163168ba7e87SXin LI RestrictStackT *sp; 163268ba7e87SXin LI 163368ba7e87SXin LI while (NULL != (sp = *spp)) { 163468ba7e87SXin LI *spp = sp->link; 163568ba7e87SXin LI free(sp); 163668ba7e87SXin LI } 163768ba7e87SXin LI } 163868ba7e87SXin LI 16392b15cb3dSCy Schubert /* 164068ba7e87SXin LI * list_restrict4 - iterative helper for list_restrict dumps IPv4 16412b15cb3dSCy Schubert * restriction list in reverse order. 16422b15cb3dSCy Schubert */ 16432b15cb3dSCy Schubert static void 16442b15cb3dSCy Schubert list_restrict4( 164568ba7e87SXin LI const restrict_u * res, 16462b15cb3dSCy Schubert struct info_restrict ** ppir 16472b15cb3dSCy Schubert ) 16482b15cb3dSCy Schubert { 164968ba7e87SXin LI RestrictStackT * rpad; 16502b15cb3dSCy Schubert struct info_restrict * pir; 16512b15cb3dSCy Schubert 16522b15cb3dSCy Schubert pir = *ppir; 165368ba7e87SXin LI for (rpad = NULL; res; res = res->link) 165468ba7e87SXin LI if (!pushRestriction(&rpad, res)) 165568ba7e87SXin LI break; 165668ba7e87SXin LI 165768ba7e87SXin LI while (pir && popRestriction(&rpad, &res)) { 16582b15cb3dSCy Schubert pir->addr = htonl(res->u.v4.addr); 16592b15cb3dSCy Schubert if (client_v6_capable) 16602b15cb3dSCy Schubert pir->v6_flag = 0; 16612b15cb3dSCy Schubert pir->mask = htonl(res->u.v4.mask); 16622b15cb3dSCy Schubert pir->count = htonl(res->count); 166309100258SXin LI pir->rflags = htons(res->rflags); 16642b15cb3dSCy Schubert pir->mflags = htons(res->mflags); 166568ba7e87SXin LI pir = (struct info_restrict *)more_pkt(); 166668ba7e87SXin LI } 166768ba7e87SXin LI flushRestrictionStack(&rpad); 166868ba7e87SXin LI *ppir = pir; 16692b15cb3dSCy Schubert } 16702b15cb3dSCy Schubert 16712b15cb3dSCy Schubert /* 167268ba7e87SXin LI * list_restrict6 - iterative helper for list_restrict dumps IPv6 16732b15cb3dSCy Schubert * restriction list in reverse order. 16742b15cb3dSCy Schubert */ 16752b15cb3dSCy Schubert static void 16762b15cb3dSCy Schubert list_restrict6( 167768ba7e87SXin LI const restrict_u * res, 16782b15cb3dSCy Schubert struct info_restrict ** ppir 16792b15cb3dSCy Schubert ) 16802b15cb3dSCy Schubert { 168168ba7e87SXin LI RestrictStackT * rpad; 16822b15cb3dSCy Schubert struct info_restrict * pir; 16832b15cb3dSCy Schubert 16842b15cb3dSCy Schubert pir = *ppir; 168568ba7e87SXin LI for (rpad = NULL; res; res = res->link) 168668ba7e87SXin LI if (!pushRestriction(&rpad, res)) 168768ba7e87SXin LI break; 168868ba7e87SXin LI 168968ba7e87SXin LI while (pir && popRestriction(&rpad, &res)) { 16902b15cb3dSCy Schubert pir->addr6 = res->u.v6.addr; 16912b15cb3dSCy Schubert pir->mask6 = res->u.v6.mask; 16922b15cb3dSCy Schubert pir->v6_flag = 1; 16932b15cb3dSCy Schubert pir->count = htonl(res->count); 169409100258SXin LI pir->rflags = htons(res->rflags); 16952b15cb3dSCy Schubert pir->mflags = htons(res->mflags); 169668ba7e87SXin LI pir = (struct info_restrict *)more_pkt(); 169768ba7e87SXin LI } 169868ba7e87SXin LI flushRestrictionStack(&rpad); 169968ba7e87SXin LI *ppir = pir; 1700c0b746e5SOllivier Robert } 1701c0b746e5SOllivier Robert 1702c0b746e5SOllivier Robert 1703c0b746e5SOllivier Robert /* 1704c0b746e5SOllivier Robert * list_restrict - return the restrict list 1705c0b746e5SOllivier Robert */ 1706c0b746e5SOllivier Robert static void 1707c0b746e5SOllivier Robert list_restrict( 17082b15cb3dSCy Schubert sockaddr_u *srcadr, 17092b15cb3dSCy Schubert endpt *inter, 1710c0b746e5SOllivier Robert struct req_pkt *inpkt 1711c0b746e5SOllivier Robert ) 1712c0b746e5SOllivier Robert { 17132b15cb3dSCy Schubert struct info_restrict *ir; 1714c0b746e5SOllivier Robert 17152b15cb3dSCy Schubert DPRINTF(3, ("wants restrict list summary\n")); 1716c0b746e5SOllivier Robert 1717c0b746e5SOllivier Robert ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt, 17189c2daa00SOllivier Robert v6sizeof(struct info_restrict)); 17199c2daa00SOllivier Robert 17202b15cb3dSCy Schubert /* 17212b15cb3dSCy Schubert * The restriction lists are kept sorted in the reverse order 17222b15cb3dSCy Schubert * than they were originally. To preserve the output semantics, 172368ba7e87SXin LI * dump each list in reverse order. The workers take care of that. 17242b15cb3dSCy Schubert */ 17252b15cb3dSCy Schubert list_restrict4(restrictlist4, &ir); 17269c2daa00SOllivier Robert if (client_v6_capable) 17272b15cb3dSCy Schubert list_restrict6(restrictlist6, &ir); 1728c0b746e5SOllivier Robert flush_pkt(); 1729c0b746e5SOllivier Robert } 1730c0b746e5SOllivier Robert 1731c0b746e5SOllivier Robert 1732c0b746e5SOllivier Robert /* 1733c0b746e5SOllivier Robert * do_resaddflags - add flags to a restrict entry (or create one) 1734c0b746e5SOllivier Robert */ 1735c0b746e5SOllivier Robert static void 1736c0b746e5SOllivier Robert do_resaddflags( 17372b15cb3dSCy Schubert sockaddr_u *srcadr, 17382b15cb3dSCy Schubert endpt *inter, 1739c0b746e5SOllivier Robert struct req_pkt *inpkt 1740c0b746e5SOllivier Robert ) 1741c0b746e5SOllivier Robert { 1742c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_FLAGS); 1743c0b746e5SOllivier Robert } 1744c0b746e5SOllivier Robert 1745c0b746e5SOllivier Robert 1746c0b746e5SOllivier Robert 1747c0b746e5SOllivier Robert /* 1748c0b746e5SOllivier Robert * do_ressubflags - remove flags from a restrict entry 1749c0b746e5SOllivier Robert */ 1750c0b746e5SOllivier Robert static void 1751c0b746e5SOllivier Robert do_ressubflags( 17522b15cb3dSCy Schubert sockaddr_u *srcadr, 17532b15cb3dSCy Schubert endpt *inter, 1754c0b746e5SOllivier Robert struct req_pkt *inpkt 1755c0b746e5SOllivier Robert ) 1756c0b746e5SOllivier Robert { 1757c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_UNFLAG); 1758c0b746e5SOllivier Robert } 1759c0b746e5SOllivier Robert 1760c0b746e5SOllivier Robert 1761c0b746e5SOllivier Robert /* 1762c0b746e5SOllivier Robert * do_unrestrict - remove a restrict entry from the list 1763c0b746e5SOllivier Robert */ 1764c0b746e5SOllivier Robert static void 1765c0b746e5SOllivier Robert do_unrestrict( 17662b15cb3dSCy Schubert sockaddr_u *srcadr, 17672b15cb3dSCy Schubert endpt *inter, 1768c0b746e5SOllivier Robert struct req_pkt *inpkt 1769c0b746e5SOllivier Robert ) 1770c0b746e5SOllivier Robert { 1771c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_REMOVE); 1772c0b746e5SOllivier Robert } 1773c0b746e5SOllivier Robert 1774c0b746e5SOllivier Robert 1775c0b746e5SOllivier Robert /* 1776c0b746e5SOllivier Robert * do_restrict - do the dirty stuff of dealing with restrictions 1777c0b746e5SOllivier Robert */ 1778c0b746e5SOllivier Robert static void 1779c0b746e5SOllivier Robert do_restrict( 17802b15cb3dSCy Schubert sockaddr_u *srcadr, 17812b15cb3dSCy Schubert endpt *inter, 1782c0b746e5SOllivier Robert struct req_pkt *inpkt, 178309100258SXin LI restrict_op op 1784c0b746e5SOllivier Robert ) 1785c0b746e5SOllivier Robert { 17862b15cb3dSCy Schubert char * datap; 17872b15cb3dSCy Schubert struct conf_restrict cr; 17882b15cb3dSCy Schubert u_short items; 17892b15cb3dSCy Schubert size_t item_sz; 17902b15cb3dSCy Schubert sockaddr_u matchaddr; 17912b15cb3dSCy Schubert sockaddr_u matchmask; 1792c0b746e5SOllivier Robert int bad; 1793*f5f40dd6SCy Schubert int/*BOOL*/ success; 1794c0b746e5SOllivier Robert 179509100258SXin LI switch(op) { 179609100258SXin LI case RESTRICT_FLAGS: 179709100258SXin LI case RESTRICT_UNFLAG: 179809100258SXin LI case RESTRICT_REMOVE: 179909100258SXin LI case RESTRICT_REMOVEIF: 180009100258SXin LI break; 180109100258SXin LI 180209100258SXin LI default: 180309100258SXin LI req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 180409100258SXin LI return; 180509100258SXin LI } 180609100258SXin LI 1807c0b746e5SOllivier Robert /* 1808c0b746e5SOllivier Robert * Do a check of the flags to make sure that only 1809c0b746e5SOllivier Robert * the NTPPORT flag is set, if any. If not, complain 1810c0b746e5SOllivier Robert * about it. Note we are very picky here. 1811c0b746e5SOllivier Robert */ 1812c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 18132b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 18142b15cb3dSCy Schubert datap = inpkt->u.data; 18152b15cb3dSCy Schubert if (item_sz > sizeof(cr)) { 18162b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 18172b15cb3dSCy Schubert return; 18182b15cb3dSCy Schubert } 1819c0b746e5SOllivier Robert 182009100258SXin LI bad = 0; 1821c0b746e5SOllivier Robert while (items-- > 0 && !bad) { 18222b15cb3dSCy Schubert memcpy(&cr, datap, item_sz); 18232d4e511cSCy Schubert cr.flags = ntohs(cr.flags); /* XXX */ 18242b15cb3dSCy Schubert cr.mflags = ntohs(cr.mflags); 18252b15cb3dSCy Schubert if (~RESM_NTPONLY & cr.mflags) 1826224ba2bdSOllivier Robert bad |= 1; 18272b15cb3dSCy Schubert if (~RES_ALLFLAGS & cr.flags) 1828224ba2bdSOllivier Robert bad |= 2; 18292b15cb3dSCy Schubert if (INADDR_ANY != cr.mask) { 18302b15cb3dSCy Schubert if (client_v6_capable && cr.v6_flag) { 18312b15cb3dSCy Schubert if (IN6_IS_ADDR_UNSPECIFIED(&cr.addr6)) 1832224ba2bdSOllivier Robert bad |= 4; 18332b15cb3dSCy Schubert } else { 18342b15cb3dSCy Schubert if (INADDR_ANY == cr.addr) 18359c2daa00SOllivier Robert bad |= 8; 18369c2daa00SOllivier Robert } 18372b15cb3dSCy Schubert } 18382b15cb3dSCy Schubert datap += item_sz; 1839c0b746e5SOllivier Robert } 1840c0b746e5SOllivier Robert 1841c0b746e5SOllivier Robert if (bad) { 1842*f5f40dd6SCy Schubert msyslog(LOG_ERR, "%s: bad = 0x%x", __func__, bad); 1843c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1844c0b746e5SOllivier Robert return; 1845c0b746e5SOllivier Robert } 1846c0b746e5SOllivier Robert 1847c0b746e5SOllivier Robert /* 18489034852cSGleb Smirnoff * Looks okay, try it out. Needs to reload data pointer and 18499034852cSGleb Smirnoff * item counter. (Talos-CAN-0052) 1850c0b746e5SOllivier Robert */ 18512b15cb3dSCy Schubert ZERO_SOCK(&matchaddr); 18522b15cb3dSCy Schubert ZERO_SOCK(&matchmask); 18539034852cSGleb Smirnoff items = INFO_NITEMS(inpkt->err_nitems); 18542b15cb3dSCy Schubert datap = inpkt->u.data; 1855c0b746e5SOllivier Robert 1856c0b746e5SOllivier Robert while (items-- > 0) { 18572b15cb3dSCy Schubert memcpy(&cr, datap, item_sz); 18582d4e511cSCy Schubert cr.flags = ntohs(cr.flags); /* XXX: size */ 18592b15cb3dSCy Schubert cr.mflags = ntohs(cr.mflags); 186009100258SXin LI cr.ippeerlimit = ntohs(cr.ippeerlimit); 18612b15cb3dSCy Schubert if (client_v6_capable && cr.v6_flag) { 18622b15cb3dSCy Schubert AF(&matchaddr) = AF_INET6; 18632b15cb3dSCy Schubert AF(&matchmask) = AF_INET6; 18642b15cb3dSCy Schubert SOCK_ADDR6(&matchaddr) = cr.addr6; 18652b15cb3dSCy Schubert SOCK_ADDR6(&matchmask) = cr.mask6; 18669c2daa00SOllivier Robert } else { 18672b15cb3dSCy Schubert AF(&matchaddr) = AF_INET; 18682b15cb3dSCy Schubert AF(&matchmask) = AF_INET; 18692b15cb3dSCy Schubert NSRCADR(&matchaddr) = cr.addr; 18702b15cb3dSCy Schubert NSRCADR(&matchmask) = cr.mask; 18719c2daa00SOllivier Robert } 1872*f5f40dd6SCy Schubert success = hack_restrict(op, &matchaddr, &matchmask, 1873*f5f40dd6SCy Schubert cr.ippeerlimit, cr.mflags, 1874*f5f40dd6SCy Schubert cr.flags, 0); 1875*f5f40dd6SCy Schubert if (!success) { 1876*f5f40dd6SCy Schubert DPRINTF(1, ("%s: %s %s mask %s ippeerlimit %hd %s %s failed", 1877*f5f40dd6SCy Schubert __func__, resop_str(op), 1878*f5f40dd6SCy Schubert stoa(&matchaddr), stoa(&matchmask), 1879*f5f40dd6SCy Schubert cr.ippeerlimit, mflags_str(cr.mflags), 1880*f5f40dd6SCy Schubert rflags_str(cr.flags))); 1881*f5f40dd6SCy Schubert } 18822b15cb3dSCy Schubert datap += item_sz; 1883c0b746e5SOllivier Robert } 1884c0b746e5SOllivier Robert 1885c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1886c0b746e5SOllivier Robert } 1887c0b746e5SOllivier Robert 1888c0b746e5SOllivier Robert 1889c0b746e5SOllivier Robert /* 1890c0b746e5SOllivier Robert * mon_getlist - return monitor data 1891c0b746e5SOllivier Robert */ 1892c0b746e5SOllivier Robert static void 18932b15cb3dSCy Schubert mon_getlist( 18942b15cb3dSCy Schubert sockaddr_u *srcadr, 18952b15cb3dSCy Schubert endpt *inter, 1896c0b746e5SOllivier Robert struct req_pkt *inpkt 1897c0b746e5SOllivier Robert ) 1898c0b746e5SOllivier Robert { 18992b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1900c0b746e5SOllivier Robert } 1901c0b746e5SOllivier Robert 1902c0b746e5SOllivier Robert 1903c0b746e5SOllivier Robert /* 1904c0b746e5SOllivier Robert * Module entry points and the flags they correspond with 1905c0b746e5SOllivier Robert */ 1906c0b746e5SOllivier Robert struct reset_entry { 1907c0b746e5SOllivier Robert int flag; /* flag this corresponds to */ 19082b15cb3dSCy Schubert void (*handler)(void); /* routine to handle request */ 1909c0b746e5SOllivier Robert }; 1910c0b746e5SOllivier Robert 1911c0b746e5SOllivier Robert struct reset_entry reset_entries[] = { 1912c0b746e5SOllivier Robert { RESET_FLAG_ALLPEERS, peer_all_reset }, 1913c0b746e5SOllivier Robert { RESET_FLAG_IO, io_clr_stats }, 1914c0b746e5SOllivier Robert { RESET_FLAG_SYS, proto_clr_stats }, 1915c0b746e5SOllivier Robert { RESET_FLAG_MEM, peer_clr_stats }, 1916c0b746e5SOllivier Robert { RESET_FLAG_TIMER, timer_clr_stats }, 1917c0b746e5SOllivier Robert { RESET_FLAG_AUTH, reset_auth_stats }, 1918c0b746e5SOllivier Robert { RESET_FLAG_CTL, ctl_clr_stats }, 1919c0b746e5SOllivier Robert { 0, 0 } 1920c0b746e5SOllivier Robert }; 1921c0b746e5SOllivier Robert 1922c0b746e5SOllivier Robert /* 1923c0b746e5SOllivier Robert * reset_stats - reset statistic counters here and there 1924c0b746e5SOllivier Robert */ 1925c0b746e5SOllivier Robert static void 1926c0b746e5SOllivier Robert reset_stats( 19272b15cb3dSCy Schubert sockaddr_u *srcadr, 19282b15cb3dSCy Schubert endpt *inter, 1929c0b746e5SOllivier Robert struct req_pkt *inpkt 1930c0b746e5SOllivier Robert ) 1931c0b746e5SOllivier Robert { 19322b15cb3dSCy Schubert struct reset_flags *rflags; 1933c0b746e5SOllivier Robert u_long flags; 1934c0b746e5SOllivier Robert struct reset_entry *rent; 1935c0b746e5SOllivier Robert 1936c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 1937224ba2bdSOllivier Robert msyslog(LOG_ERR, "reset_stats: err_nitems > 1"); 1938c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1939c0b746e5SOllivier Robert return; 1940c0b746e5SOllivier Robert } 1941c0b746e5SOllivier Robert 19422b15cb3dSCy Schubert rflags = (struct reset_flags *)&inpkt->u; 19432b15cb3dSCy Schubert flags = ntohl(rflags->flags); 1944c0b746e5SOllivier Robert 1945c0b746e5SOllivier Robert if (flags & ~RESET_ALLFLAGS) { 1946224ba2bdSOllivier Robert msyslog(LOG_ERR, "reset_stats: reset leaves %#lx", 1947224ba2bdSOllivier Robert flags & ~RESET_ALLFLAGS); 1948c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1949c0b746e5SOllivier Robert return; 1950c0b746e5SOllivier Robert } 1951c0b746e5SOllivier Robert 1952c0b746e5SOllivier Robert for (rent = reset_entries; rent->flag != 0; rent++) { 1953c0b746e5SOllivier Robert if (flags & rent->flag) 19542b15cb3dSCy Schubert (*rent->handler)(); 1955c0b746e5SOllivier Robert } 1956c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1957c0b746e5SOllivier Robert } 1958c0b746e5SOllivier Robert 1959c0b746e5SOllivier Robert 1960c0b746e5SOllivier Robert /* 1961c0b746e5SOllivier Robert * reset_peer - clear a peer's statistics 1962c0b746e5SOllivier Robert */ 1963c0b746e5SOllivier Robert static void 1964c0b746e5SOllivier Robert reset_peer( 19652b15cb3dSCy Schubert sockaddr_u *srcadr, 19662b15cb3dSCy Schubert endpt *inter, 1967c0b746e5SOllivier Robert struct req_pkt *inpkt 1968c0b746e5SOllivier Robert ) 1969c0b746e5SOllivier Robert { 19702b15cb3dSCy Schubert u_short items; 19712b15cb3dSCy Schubert size_t item_sz; 19722b15cb3dSCy Schubert char * datap; 19732b15cb3dSCy Schubert struct conf_unpeer cp; 19742b15cb3dSCy Schubert struct peer * p; 19752b15cb3dSCy Schubert sockaddr_u peeraddr; 1976c0b746e5SOllivier Robert int bad; 1977c0b746e5SOllivier Robert 1978c0b746e5SOllivier Robert /* 1979c0b746e5SOllivier Robert * We check first to see that every peer exists. If not, 1980c0b746e5SOllivier Robert * we return an error. 1981c0b746e5SOllivier Robert */ 1982c0b746e5SOllivier Robert 1983c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 19842b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 19852b15cb3dSCy Schubert datap = inpkt->u.data; 19862b15cb3dSCy Schubert if (item_sz > sizeof(cp)) { 19872b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 19882b15cb3dSCy Schubert return; 19899c2daa00SOllivier Robert } 19902b15cb3dSCy Schubert 19912b15cb3dSCy Schubert bad = FALSE; 19922b15cb3dSCy Schubert while (items-- > 0 && !bad) { 19932b15cb3dSCy Schubert ZERO(cp); 19942b15cb3dSCy Schubert memcpy(&cp, datap, item_sz); 19952b15cb3dSCy Schubert ZERO_SOCK(&peeraddr); 19962b15cb3dSCy Schubert if (client_v6_capable && cp.v6_flag) { 19972b15cb3dSCy Schubert AF(&peeraddr) = AF_INET6; 19982b15cb3dSCy Schubert SOCK_ADDR6(&peeraddr) = cp.peeraddr6; 19992b15cb3dSCy Schubert } else { 20002b15cb3dSCy Schubert AF(&peeraddr) = AF_INET; 20012b15cb3dSCy Schubert NSRCADR(&peeraddr) = cp.peeraddr; 20022b15cb3dSCy Schubert } 20032b15cb3dSCy Schubert 20042b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 20052b15cb3dSCy Schubert peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 20069c2daa00SOllivier Robert #endif 200709100258SXin LI p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0, NULL); 20082b15cb3dSCy Schubert if (NULL == p) 2009c0b746e5SOllivier Robert bad++; 20102b15cb3dSCy Schubert datap += item_sz; 2011c0b746e5SOllivier Robert } 2012c0b746e5SOllivier Robert 2013c0b746e5SOllivier Robert if (bad) { 2014c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2015c0b746e5SOllivier Robert return; 2016c0b746e5SOllivier Robert } 2017c0b746e5SOllivier Robert 2018c0b746e5SOllivier Robert /* 20199034852cSGleb Smirnoff * Now do it in earnest. Needs to reload data pointer and item 20209034852cSGleb Smirnoff * counter. (Talos-CAN-0052) 2021c0b746e5SOllivier Robert */ 2022c0b746e5SOllivier Robert 20239034852cSGleb Smirnoff items = INFO_NITEMS(inpkt->err_nitems); 20242b15cb3dSCy Schubert datap = inpkt->u.data; 2025c0b746e5SOllivier Robert while (items-- > 0) { 20262b15cb3dSCy Schubert ZERO(cp); 20272b15cb3dSCy Schubert memcpy(&cp, datap, item_sz); 20282b15cb3dSCy Schubert ZERO_SOCK(&peeraddr); 20292b15cb3dSCy Schubert if (client_v6_capable && cp.v6_flag) { 20302b15cb3dSCy Schubert AF(&peeraddr) = AF_INET6; 20312b15cb3dSCy Schubert SOCK_ADDR6(&peeraddr) = cp.peeraddr6; 20329c2daa00SOllivier Robert } else { 20332b15cb3dSCy Schubert AF(&peeraddr) = AF_INET; 20342b15cb3dSCy Schubert NSRCADR(&peeraddr) = cp.peeraddr; 20359c2daa00SOllivier Robert } 20362b15cb3dSCy Schubert SET_PORT(&peeraddr, 123); 20372b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 20382b15cb3dSCy Schubert peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 20399c2daa00SOllivier Robert #endif 204009100258SXin LI p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0, NULL); 20412b15cb3dSCy Schubert while (p != NULL) { 20422b15cb3dSCy Schubert peer_reset(p); 204309100258SXin LI p = findexistingpeer(&peeraddr, NULL, p, -1, 0, NULL); 2044c0b746e5SOllivier Robert } 20452b15cb3dSCy Schubert datap += item_sz; 2046c0b746e5SOllivier Robert } 2047c0b746e5SOllivier Robert 2048c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2049c0b746e5SOllivier Robert } 2050c0b746e5SOllivier Robert 2051c0b746e5SOllivier Robert 2052c0b746e5SOllivier Robert /* 2053c0b746e5SOllivier Robert * do_key_reread - reread the encryption key file 2054c0b746e5SOllivier Robert */ 2055c0b746e5SOllivier Robert static void 2056c0b746e5SOllivier Robert do_key_reread( 20572b15cb3dSCy Schubert sockaddr_u *srcadr, 20582b15cb3dSCy Schubert endpt *inter, 2059c0b746e5SOllivier Robert struct req_pkt *inpkt 2060c0b746e5SOllivier Robert ) 2061c0b746e5SOllivier Robert { 2062c0b746e5SOllivier Robert rereadkeys(); 2063c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2064c0b746e5SOllivier Robert } 2065c0b746e5SOllivier Robert 2066c0b746e5SOllivier Robert 2067c0b746e5SOllivier Robert /* 2068c0b746e5SOllivier Robert * trust_key - make one or more keys trusted 2069c0b746e5SOllivier Robert */ 2070c0b746e5SOllivier Robert static void 2071c0b746e5SOllivier Robert trust_key( 20722b15cb3dSCy Schubert sockaddr_u *srcadr, 20732b15cb3dSCy Schubert endpt *inter, 2074c0b746e5SOllivier Robert struct req_pkt *inpkt 2075c0b746e5SOllivier Robert ) 2076c0b746e5SOllivier Robert { 2077c0b746e5SOllivier Robert do_trustkey(srcadr, inter, inpkt, 1); 2078c0b746e5SOllivier Robert } 2079c0b746e5SOllivier Robert 2080c0b746e5SOllivier Robert 2081c0b746e5SOllivier Robert /* 2082c0b746e5SOllivier Robert * untrust_key - make one or more keys untrusted 2083c0b746e5SOllivier Robert */ 2084c0b746e5SOllivier Robert static void 2085c0b746e5SOllivier Robert untrust_key( 20862b15cb3dSCy Schubert sockaddr_u *srcadr, 20872b15cb3dSCy Schubert endpt *inter, 2088c0b746e5SOllivier Robert struct req_pkt *inpkt 2089c0b746e5SOllivier Robert ) 2090c0b746e5SOllivier Robert { 2091c0b746e5SOllivier Robert do_trustkey(srcadr, inter, inpkt, 0); 2092c0b746e5SOllivier Robert } 2093c0b746e5SOllivier Robert 2094c0b746e5SOllivier Robert 2095c0b746e5SOllivier Robert /* 2096c0b746e5SOllivier Robert * do_trustkey - make keys either trustable or untrustable 2097c0b746e5SOllivier Robert */ 2098c0b746e5SOllivier Robert static void 2099c0b746e5SOllivier Robert do_trustkey( 21002b15cb3dSCy Schubert sockaddr_u *srcadr, 21012b15cb3dSCy Schubert endpt *inter, 2102c0b746e5SOllivier Robert struct req_pkt *inpkt, 2103224ba2bdSOllivier Robert u_long trust 2104c0b746e5SOllivier Robert ) 2105c0b746e5SOllivier Robert { 21063311ff84SXin LI register uint32_t *kp; 2107c0b746e5SOllivier Robert register int items; 2108c0b746e5SOllivier Robert 2109c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 21103311ff84SXin LI kp = (uint32_t *)&inpkt->u; 2111c0b746e5SOllivier Robert while (items-- > 0) { 2112c0b746e5SOllivier Robert authtrust(*kp, trust); 2113c0b746e5SOllivier Robert kp++; 2114c0b746e5SOllivier Robert } 2115c0b746e5SOllivier Robert 2116c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2117c0b746e5SOllivier Robert } 2118c0b746e5SOllivier Robert 2119c0b746e5SOllivier Robert 2120c0b746e5SOllivier Robert /* 2121c0b746e5SOllivier Robert * get_auth_info - return some stats concerning the authentication module 2122c0b746e5SOllivier Robert */ 2123c0b746e5SOllivier Robert static void 2124c0b746e5SOllivier Robert get_auth_info( 21252b15cb3dSCy Schubert sockaddr_u *srcadr, 21262b15cb3dSCy Schubert endpt *inter, 2127c0b746e5SOllivier Robert struct req_pkt *inpkt 2128c0b746e5SOllivier Robert ) 2129c0b746e5SOllivier Robert { 2130c0b746e5SOllivier Robert register struct info_auth *ia; 2131c0b746e5SOllivier Robert 2132c0b746e5SOllivier Robert ia = (struct info_auth *)prepare_pkt(srcadr, inter, inpkt, 2133c0b746e5SOllivier Robert sizeof(struct info_auth)); 2134c0b746e5SOllivier Robert 2135c0b746e5SOllivier Robert ia->numkeys = htonl((u_int32)authnumkeys); 2136c0b746e5SOllivier Robert ia->numfreekeys = htonl((u_int32)authnumfreekeys); 2137c0b746e5SOllivier Robert ia->keylookups = htonl((u_int32)authkeylookups); 2138c0b746e5SOllivier Robert ia->keynotfound = htonl((u_int32)authkeynotfound); 2139c0b746e5SOllivier Robert ia->encryptions = htonl((u_int32)authencryptions); 2140c0b746e5SOllivier Robert ia->decryptions = htonl((u_int32)authdecryptions); 2141c0b746e5SOllivier Robert ia->keyuncached = htonl((u_int32)authkeyuncached); 2142c0b746e5SOllivier Robert ia->expired = htonl((u_int32)authkeyexpired); 2143c0b746e5SOllivier Robert ia->timereset = htonl((u_int32)(current_time - auth_timereset)); 2144c0b746e5SOllivier Robert 2145c0b746e5SOllivier Robert (void) more_pkt(); 2146c0b746e5SOllivier Robert flush_pkt(); 2147c0b746e5SOllivier Robert } 2148c0b746e5SOllivier Robert 2149c0b746e5SOllivier Robert 2150c0b746e5SOllivier Robert 2151c0b746e5SOllivier Robert /* 2152c0b746e5SOllivier Robert * reset_auth_stats - reset the authentication stat counters. Done here 2153c0b746e5SOllivier Robert * to keep ntp-isms out of the authentication module 2154c0b746e5SOllivier Robert */ 21552b15cb3dSCy Schubert void 2156c0b746e5SOllivier Robert reset_auth_stats(void) 2157c0b746e5SOllivier Robert { 2158c0b746e5SOllivier Robert authkeylookups = 0; 2159c0b746e5SOllivier Robert authkeynotfound = 0; 2160c0b746e5SOllivier Robert authencryptions = 0; 2161c0b746e5SOllivier Robert authdecryptions = 0; 2162c0b746e5SOllivier Robert authkeyuncached = 0; 2163c0b746e5SOllivier Robert auth_timereset = current_time; 2164c0b746e5SOllivier Robert } 2165c0b746e5SOllivier Robert 2166c0b746e5SOllivier Robert 2167c0b746e5SOllivier Robert /* 2168c0b746e5SOllivier Robert * req_get_traps - return information about current trap holders 2169c0b746e5SOllivier Robert */ 2170c0b746e5SOllivier Robert static void 2171c0b746e5SOllivier Robert req_get_traps( 21722b15cb3dSCy Schubert sockaddr_u *srcadr, 21732b15cb3dSCy Schubert endpt *inter, 2174c0b746e5SOllivier Robert struct req_pkt *inpkt 2175c0b746e5SOllivier Robert ) 2176c0b746e5SOllivier Robert { 21772b15cb3dSCy Schubert struct info_trap *it; 21782b15cb3dSCy Schubert struct ctl_trap *tr; 21792b15cb3dSCy Schubert size_t i; 2180c0b746e5SOllivier Robert 2181c0b746e5SOllivier Robert if (num_ctl_traps == 0) { 2182c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2183c0b746e5SOllivier Robert return; 2184c0b746e5SOllivier Robert } 2185c0b746e5SOllivier Robert 2186c0b746e5SOllivier Robert it = (struct info_trap *)prepare_pkt(srcadr, inter, inpkt, 21879c2daa00SOllivier Robert v6sizeof(struct info_trap)); 2188c0b746e5SOllivier Robert 218968ba7e87SXin LI for (i = 0, tr = ctl_traps; it && i < COUNTOF(ctl_traps); i++, tr++) { 2190c0b746e5SOllivier Robert if (tr->tr_flags & TRAP_INUSE) { 21912b15cb3dSCy Schubert if (IS_IPV4(&tr->tr_addr)) { 2192c0b746e5SOllivier Robert if (tr->tr_localaddr == any_interface) 2193c0b746e5SOllivier Robert it->local_address = 0; 2194c0b746e5SOllivier Robert else 2195c0b746e5SOllivier Robert it->local_address 21962b15cb3dSCy Schubert = NSRCADR(&tr->tr_localaddr->sin); 21972b15cb3dSCy Schubert it->trap_address = NSRCADR(&tr->tr_addr); 21989c2daa00SOllivier Robert if (client_v6_capable) 21999c2daa00SOllivier Robert it->v6_flag = 0; 22009c2daa00SOllivier Robert } else { 22019c2daa00SOllivier Robert if (!client_v6_capable) 22029c2daa00SOllivier Robert continue; 22039c2daa00SOllivier Robert it->local_address6 22042b15cb3dSCy Schubert = SOCK_ADDR6(&tr->tr_localaddr->sin); 22052b15cb3dSCy Schubert it->trap_address6 = SOCK_ADDR6(&tr->tr_addr); 22069c2daa00SOllivier Robert it->v6_flag = 1; 22079c2daa00SOllivier Robert } 2208c0b746e5SOllivier Robert it->trap_port = NSRCPORT(&tr->tr_addr); 2209c0b746e5SOllivier Robert it->sequence = htons(tr->tr_sequence); 2210c0b746e5SOllivier Robert it->settime = htonl((u_int32)(current_time - tr->tr_settime)); 2211c0b746e5SOllivier Robert it->origtime = htonl((u_int32)(current_time - tr->tr_origtime)); 2212c0b746e5SOllivier Robert it->resets = htonl((u_int32)tr->tr_resets); 2213c0b746e5SOllivier Robert it->flags = htonl((u_int32)tr->tr_flags); 2214c0b746e5SOllivier Robert it = (struct info_trap *)more_pkt(); 2215c0b746e5SOllivier Robert } 2216c0b746e5SOllivier Robert } 2217c0b746e5SOllivier Robert flush_pkt(); 2218c0b746e5SOllivier Robert } 2219c0b746e5SOllivier Robert 2220c0b746e5SOllivier Robert 2221c0b746e5SOllivier Robert /* 2222c0b746e5SOllivier Robert * req_set_trap - configure a trap 2223c0b746e5SOllivier Robert */ 2224c0b746e5SOllivier Robert static void 2225c0b746e5SOllivier Robert req_set_trap( 22262b15cb3dSCy Schubert sockaddr_u *srcadr, 22272b15cb3dSCy Schubert endpt *inter, 2228c0b746e5SOllivier Robert struct req_pkt *inpkt 2229c0b746e5SOllivier Robert ) 2230c0b746e5SOllivier Robert { 2231c0b746e5SOllivier Robert do_setclr_trap(srcadr, inter, inpkt, 1); 2232c0b746e5SOllivier Robert } 2233c0b746e5SOllivier Robert 2234c0b746e5SOllivier Robert 2235c0b746e5SOllivier Robert 2236c0b746e5SOllivier Robert /* 2237c0b746e5SOllivier Robert * req_clr_trap - unconfigure a trap 2238c0b746e5SOllivier Robert */ 2239c0b746e5SOllivier Robert static void 2240c0b746e5SOllivier Robert req_clr_trap( 22412b15cb3dSCy Schubert sockaddr_u *srcadr, 22422b15cb3dSCy Schubert endpt *inter, 2243c0b746e5SOllivier Robert struct req_pkt *inpkt 2244c0b746e5SOllivier Robert ) 2245c0b746e5SOllivier Robert { 2246c0b746e5SOllivier Robert do_setclr_trap(srcadr, inter, inpkt, 0); 2247c0b746e5SOllivier Robert } 2248c0b746e5SOllivier Robert 2249c0b746e5SOllivier Robert 2250c0b746e5SOllivier Robert 2251c0b746e5SOllivier Robert /* 2252c0b746e5SOllivier Robert * do_setclr_trap - do the grunge work of (un)configuring a trap 2253c0b746e5SOllivier Robert */ 2254c0b746e5SOllivier Robert static void 2255c0b746e5SOllivier Robert do_setclr_trap( 22562b15cb3dSCy Schubert sockaddr_u *srcadr, 22572b15cb3dSCy Schubert endpt *inter, 2258c0b746e5SOllivier Robert struct req_pkt *inpkt, 2259c0b746e5SOllivier Robert int set 2260c0b746e5SOllivier Robert ) 2261c0b746e5SOllivier Robert { 2262c0b746e5SOllivier Robert register struct conf_trap *ct; 22632b15cb3dSCy Schubert register endpt *linter; 2264c0b746e5SOllivier Robert int res; 22652b15cb3dSCy Schubert sockaddr_u laddr; 2266c0b746e5SOllivier Robert 2267c0b746e5SOllivier Robert /* 22682b15cb3dSCy Schubert * Prepare sockaddr 2269c0b746e5SOllivier Robert */ 22702b15cb3dSCy Schubert ZERO_SOCK(&laddr); 22712b15cb3dSCy Schubert AF(&laddr) = AF(srcadr); 22722b15cb3dSCy Schubert SET_PORT(&laddr, NTP_PORT); 2273c0b746e5SOllivier Robert 2274c0b746e5SOllivier Robert /* 2275c0b746e5SOllivier Robert * Restrict ourselves to one item only. This eliminates 2276c0b746e5SOllivier Robert * the error reporting problem. 2277c0b746e5SOllivier Robert */ 2278c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2279224ba2bdSOllivier Robert msyslog(LOG_ERR, "do_setclr_trap: err_nitems > 1"); 2280c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2281c0b746e5SOllivier Robert return; 2282c0b746e5SOllivier Robert } 22832b15cb3dSCy Schubert ct = (struct conf_trap *)&inpkt->u; 2284c0b746e5SOllivier Robert 2285c0b746e5SOllivier Robert /* 2286c0b746e5SOllivier Robert * Look for the local interface. If none, use the default. 2287c0b746e5SOllivier Robert */ 2288c0b746e5SOllivier Robert if (ct->local_address == 0) { 2289c0b746e5SOllivier Robert linter = any_interface; 2290c0b746e5SOllivier Robert } else { 22912b15cb3dSCy Schubert if (IS_IPV4(&laddr)) 22922b15cb3dSCy Schubert NSRCADR(&laddr) = ct->local_address; 22939c2daa00SOllivier Robert else 22942b15cb3dSCy Schubert SOCK_ADDR6(&laddr) = ct->local_address6; 2295c0b746e5SOllivier Robert linter = findinterface(&laddr); 22962b15cb3dSCy Schubert if (NULL == linter) { 2297c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2298c0b746e5SOllivier Robert return; 2299c0b746e5SOllivier Robert } 2300c0b746e5SOllivier Robert } 2301c0b746e5SOllivier Robert 23022b15cb3dSCy Schubert if (IS_IPV4(&laddr)) 23032b15cb3dSCy Schubert NSRCADR(&laddr) = ct->trap_address; 2304c0b746e5SOllivier Robert else 23052b15cb3dSCy Schubert SOCK_ADDR6(&laddr) = ct->trap_address6; 23062b15cb3dSCy Schubert if (ct->trap_port) 23079c2daa00SOllivier Robert NSRCPORT(&laddr) = ct->trap_port; 23089c2daa00SOllivier Robert else 23092b15cb3dSCy Schubert SET_PORT(&laddr, TRAPPORT); 2310c0b746e5SOllivier Robert 2311c0b746e5SOllivier Robert if (set) { 2312c0b746e5SOllivier Robert res = ctlsettrap(&laddr, linter, 0, 2313c0b746e5SOllivier Robert INFO_VERSION(inpkt->rm_vn_mode)); 2314c0b746e5SOllivier Robert } else { 2315c0b746e5SOllivier Robert res = ctlclrtrap(&laddr, linter, 0); 2316c0b746e5SOllivier Robert } 2317c0b746e5SOllivier Robert 2318c0b746e5SOllivier Robert if (!res) { 2319c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2320c0b746e5SOllivier Robert } else { 2321c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2322c0b746e5SOllivier Robert } 2323c0b746e5SOllivier Robert return; 2324c0b746e5SOllivier Robert } 2325c0b746e5SOllivier Robert 23264990d495SXin LI /* 23274990d495SXin LI * Validate a request packet for a new request or control key: 23284990d495SXin LI * - only one item allowed 23294990d495SXin LI * - key must be valid (that is, known, and not in the autokey range) 23304990d495SXin LI */ 23314990d495SXin LI static void 23324990d495SXin LI set_keyid_checked( 23334990d495SXin LI keyid_t *into, 23344990d495SXin LI const char *what, 23354990d495SXin LI sockaddr_u *srcadr, 23364990d495SXin LI endpt *inter, 23374990d495SXin LI struct req_pkt *inpkt 23384990d495SXin LI ) 23394990d495SXin LI { 23404990d495SXin LI keyid_t *pkeyid; 23414990d495SXin LI keyid_t tmpkey; 2342c0b746e5SOllivier Robert 23434990d495SXin LI /* restrict ourselves to one item only */ 23444990d495SXin LI if (INFO_NITEMS(inpkt->err_nitems) > 1) { 23454990d495SXin LI msyslog(LOG_ERR, "set_keyid_checked[%s]: err_nitems > 1", 23464990d495SXin LI what); 23474990d495SXin LI req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 23484990d495SXin LI return; 23494990d495SXin LI } 23504990d495SXin LI 23514990d495SXin LI /* plug the new key from the packet */ 23524990d495SXin LI pkeyid = (keyid_t *)&inpkt->u; 23534990d495SXin LI tmpkey = ntohl(*pkeyid); 23544990d495SXin LI 23554990d495SXin LI /* validate the new key id, claim data error on failure */ 23564990d495SXin LI if (tmpkey < 1 || tmpkey > NTP_MAXKEY || !auth_havekey(tmpkey)) { 23574990d495SXin LI msyslog(LOG_ERR, "set_keyid_checked[%s]: invalid key id: %ld", 23584990d495SXin LI what, (long)tmpkey); 23594990d495SXin LI req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 23604990d495SXin LI return; 23614990d495SXin LI } 23624990d495SXin LI 23634990d495SXin LI /* if we arrive here, the key is good -- use it */ 23644990d495SXin LI *into = tmpkey; 23654990d495SXin LI req_ack(srcadr, inter, inpkt, INFO_OKAY); 23664990d495SXin LI } 2367c0b746e5SOllivier Robert 2368c0b746e5SOllivier Robert /* 2369c0b746e5SOllivier Robert * set_request_keyid - set the keyid used to authenticate requests 2370c0b746e5SOllivier Robert */ 2371c0b746e5SOllivier Robert static void 2372c0b746e5SOllivier Robert set_request_keyid( 23732b15cb3dSCy Schubert sockaddr_u *srcadr, 23742b15cb3dSCy Schubert endpt *inter, 2375c0b746e5SOllivier Robert struct req_pkt *inpkt 2376c0b746e5SOllivier Robert ) 2377c0b746e5SOllivier Robert { 23784990d495SXin LI set_keyid_checked(&info_auth_keyid, "request", 23794990d495SXin LI srcadr, inter, inpkt); 2380c0b746e5SOllivier Robert } 2381c0b746e5SOllivier Robert 2382c0b746e5SOllivier Robert 2383c0b746e5SOllivier Robert 2384c0b746e5SOllivier Robert /* 2385c0b746e5SOllivier Robert * set_control_keyid - set the keyid used to authenticate requests 2386c0b746e5SOllivier Robert */ 2387c0b746e5SOllivier Robert static void 2388c0b746e5SOllivier Robert set_control_keyid( 23892b15cb3dSCy Schubert sockaddr_u *srcadr, 23902b15cb3dSCy Schubert endpt *inter, 2391c0b746e5SOllivier Robert struct req_pkt *inpkt 2392c0b746e5SOllivier Robert ) 2393c0b746e5SOllivier Robert { 23944990d495SXin LI set_keyid_checked(&ctl_auth_keyid, "control", 23954990d495SXin LI srcadr, inter, inpkt); 2396c0b746e5SOllivier Robert } 2397c0b746e5SOllivier Robert 2398c0b746e5SOllivier Robert 2399c0b746e5SOllivier Robert 2400c0b746e5SOllivier Robert /* 2401c0b746e5SOllivier Robert * get_ctl_stats - return some stats concerning the control message module 2402c0b746e5SOllivier Robert */ 2403c0b746e5SOllivier Robert static void 2404c0b746e5SOllivier Robert get_ctl_stats( 24052b15cb3dSCy Schubert sockaddr_u *srcadr, 24062b15cb3dSCy Schubert endpt *inter, 2407c0b746e5SOllivier Robert struct req_pkt *inpkt 2408c0b746e5SOllivier Robert ) 2409c0b746e5SOllivier Robert { 2410c0b746e5SOllivier Robert register struct info_control *ic; 2411c0b746e5SOllivier Robert 2412c0b746e5SOllivier Robert ic = (struct info_control *)prepare_pkt(srcadr, inter, inpkt, 2413c0b746e5SOllivier Robert sizeof(struct info_control)); 2414c0b746e5SOllivier Robert 2415c0b746e5SOllivier Robert ic->ctltimereset = htonl((u_int32)(current_time - ctltimereset)); 2416c0b746e5SOllivier Robert ic->numctlreq = htonl((u_int32)numctlreq); 2417c0b746e5SOllivier Robert ic->numctlbadpkts = htonl((u_int32)numctlbadpkts); 2418c0b746e5SOllivier Robert ic->numctlresponses = htonl((u_int32)numctlresponses); 2419c0b746e5SOllivier Robert ic->numctlfrags = htonl((u_int32)numctlfrags); 2420c0b746e5SOllivier Robert ic->numctlerrors = htonl((u_int32)numctlerrors); 2421c0b746e5SOllivier Robert ic->numctltooshort = htonl((u_int32)numctltooshort); 2422c0b746e5SOllivier Robert ic->numctlinputresp = htonl((u_int32)numctlinputresp); 2423c0b746e5SOllivier Robert ic->numctlinputfrag = htonl((u_int32)numctlinputfrag); 2424c0b746e5SOllivier Robert ic->numctlinputerr = htonl((u_int32)numctlinputerr); 2425c0b746e5SOllivier Robert ic->numctlbadoffset = htonl((u_int32)numctlbadoffset); 2426c0b746e5SOllivier Robert ic->numctlbadversion = htonl((u_int32)numctlbadversion); 2427c0b746e5SOllivier Robert ic->numctldatatooshort = htonl((u_int32)numctldatatooshort); 2428c0b746e5SOllivier Robert ic->numctlbadop = htonl((u_int32)numctlbadop); 2429c0b746e5SOllivier Robert ic->numasyncmsgs = htonl((u_int32)numasyncmsgs); 2430c0b746e5SOllivier Robert 2431c0b746e5SOllivier Robert (void) more_pkt(); 2432c0b746e5SOllivier Robert flush_pkt(); 2433c0b746e5SOllivier Robert } 2434c0b746e5SOllivier Robert 2435c0b746e5SOllivier Robert 2436c0b746e5SOllivier Robert #ifdef KERNEL_PLL 2437c0b746e5SOllivier Robert /* 2438c0b746e5SOllivier Robert * get_kernel_info - get kernel pll/pps information 2439c0b746e5SOllivier Robert */ 2440c0b746e5SOllivier Robert static void 2441c0b746e5SOllivier Robert get_kernel_info( 24422b15cb3dSCy Schubert sockaddr_u *srcadr, 24432b15cb3dSCy Schubert endpt *inter, 2444c0b746e5SOllivier Robert struct req_pkt *inpkt 2445c0b746e5SOllivier Robert ) 2446c0b746e5SOllivier Robert { 2447c0b746e5SOllivier Robert register struct info_kernel *ik; 2448c0b746e5SOllivier Robert struct timex ntx; 2449c0b746e5SOllivier Robert 2450c0b746e5SOllivier Robert if (!pll_control) { 2451c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2452c0b746e5SOllivier Robert return; 2453c0b746e5SOllivier Robert } 2454c0b746e5SOllivier Robert 24552b15cb3dSCy Schubert ZERO(ntx); 2456c0b746e5SOllivier Robert if (ntp_adjtime(&ntx) < 0) 2457c0b746e5SOllivier Robert msyslog(LOG_ERR, "get_kernel_info: ntp_adjtime() failed: %m"); 2458c0b746e5SOllivier Robert ik = (struct info_kernel *)prepare_pkt(srcadr, inter, inpkt, 2459c0b746e5SOllivier Robert sizeof(struct info_kernel)); 2460c0b746e5SOllivier Robert 2461c0b746e5SOllivier Robert /* 2462c0b746e5SOllivier Robert * pll variables 2463c0b746e5SOllivier Robert */ 2464c0b746e5SOllivier Robert ik->offset = htonl((u_int32)ntx.offset); 2465c0b746e5SOllivier Robert ik->freq = htonl((u_int32)ntx.freq); 2466c0b746e5SOllivier Robert ik->maxerror = htonl((u_int32)ntx.maxerror); 2467c0b746e5SOllivier Robert ik->esterror = htonl((u_int32)ntx.esterror); 2468c0b746e5SOllivier Robert ik->status = htons(ntx.status); 2469c0b746e5SOllivier Robert ik->constant = htonl((u_int32)ntx.constant); 2470c0b746e5SOllivier Robert ik->precision = htonl((u_int32)ntx.precision); 2471c0b746e5SOllivier Robert ik->tolerance = htonl((u_int32)ntx.tolerance); 2472c0b746e5SOllivier Robert 2473c0b746e5SOllivier Robert /* 2474c0b746e5SOllivier Robert * pps variables 2475c0b746e5SOllivier Robert */ 2476c0b746e5SOllivier Robert ik->ppsfreq = htonl((u_int32)ntx.ppsfreq); 2477c0b746e5SOllivier Robert ik->jitter = htonl((u_int32)ntx.jitter); 2478c0b746e5SOllivier Robert ik->shift = htons(ntx.shift); 2479c0b746e5SOllivier Robert ik->stabil = htonl((u_int32)ntx.stabil); 2480c0b746e5SOllivier Robert ik->jitcnt = htonl((u_int32)ntx.jitcnt); 2481c0b746e5SOllivier Robert ik->calcnt = htonl((u_int32)ntx.calcnt); 2482c0b746e5SOllivier Robert ik->errcnt = htonl((u_int32)ntx.errcnt); 2483c0b746e5SOllivier Robert ik->stbcnt = htonl((u_int32)ntx.stbcnt); 2484c0b746e5SOllivier Robert 2485c0b746e5SOllivier Robert (void) more_pkt(); 2486c0b746e5SOllivier Robert flush_pkt(); 2487c0b746e5SOllivier Robert } 2488c0b746e5SOllivier Robert #endif /* KERNEL_PLL */ 2489c0b746e5SOllivier Robert 2490c0b746e5SOllivier Robert 2491c0b746e5SOllivier Robert #ifdef REFCLOCK 2492c0b746e5SOllivier Robert /* 2493c0b746e5SOllivier Robert * get_clock_info - get info about a clock 2494c0b746e5SOllivier Robert */ 2495c0b746e5SOllivier Robert static void 2496c0b746e5SOllivier Robert get_clock_info( 24972b15cb3dSCy Schubert sockaddr_u *srcadr, 24982b15cb3dSCy Schubert endpt *inter, 2499c0b746e5SOllivier Robert struct req_pkt *inpkt 2500c0b746e5SOllivier Robert ) 2501c0b746e5SOllivier Robert { 2502c0b746e5SOllivier Robert register struct info_clock *ic; 2503c0b746e5SOllivier Robert register u_int32 *clkaddr; 2504c0b746e5SOllivier Robert register int items; 2505c0b746e5SOllivier Robert struct refclockstat clock_stat; 25062b15cb3dSCy Schubert sockaddr_u addr; 2507c0b746e5SOllivier Robert l_fp ltmp; 2508c0b746e5SOllivier Robert 25092b15cb3dSCy Schubert ZERO_SOCK(&addr); 25102b15cb3dSCy Schubert AF(&addr) = AF_INET; 25112b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 25122b15cb3dSCy Schubert addr.sa.sa_len = SOCKLEN(&addr); 25139c2daa00SOllivier Robert #endif 25142b15cb3dSCy Schubert SET_PORT(&addr, NTP_PORT); 2515c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 25162b15cb3dSCy Schubert clkaddr = &inpkt->u.u32[0]; 2517c0b746e5SOllivier Robert 2518c0b746e5SOllivier Robert ic = (struct info_clock *)prepare_pkt(srcadr, inter, inpkt, 2519c0b746e5SOllivier Robert sizeof(struct info_clock)); 2520c0b746e5SOllivier Robert 252168ba7e87SXin LI while (items-- > 0 && ic) { 25222b15cb3dSCy Schubert NSRCADR(&addr) = *clkaddr++; 25232b15cb3dSCy Schubert if (!ISREFCLOCKADR(&addr) || NULL == 252409100258SXin LI findexistingpeer(&addr, NULL, NULL, -1, 0, NULL)) { 2525c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2526c0b746e5SOllivier Robert return; 2527c0b746e5SOllivier Robert } 2528c0b746e5SOllivier Robert 2529c0b746e5SOllivier Robert clock_stat.kv_list = (struct ctl_var *)0; 2530c0b746e5SOllivier Robert 25312b15cb3dSCy Schubert refclock_control(&addr, NULL, &clock_stat); 2532c0b746e5SOllivier Robert 25332b15cb3dSCy Schubert ic->clockadr = NSRCADR(&addr); 2534c0b746e5SOllivier Robert ic->type = clock_stat.type; 2535c0b746e5SOllivier Robert ic->flags = clock_stat.flags; 2536c0b746e5SOllivier Robert ic->lastevent = clock_stat.lastevent; 2537c0b746e5SOllivier Robert ic->currentstatus = clock_stat.currentstatus; 2538c0b746e5SOllivier Robert ic->polls = htonl((u_int32)clock_stat.polls); 2539c0b746e5SOllivier Robert ic->noresponse = htonl((u_int32)clock_stat.noresponse); 2540c0b746e5SOllivier Robert ic->badformat = htonl((u_int32)clock_stat.badformat); 2541c0b746e5SOllivier Robert ic->baddata = htonl((u_int32)clock_stat.baddata); 2542c0b746e5SOllivier Robert ic->timestarted = htonl((u_int32)clock_stat.timereset); 2543c0b746e5SOllivier Robert DTOLFP(clock_stat.fudgetime1, <mp); 2544c0b746e5SOllivier Robert HTONL_FP(<mp, &ic->fudgetime1); 25459c2daa00SOllivier Robert DTOLFP(clock_stat.fudgetime2, <mp); 2546c0b746e5SOllivier Robert HTONL_FP(<mp, &ic->fudgetime2); 2547c0b746e5SOllivier Robert ic->fudgeval1 = htonl((u_int32)clock_stat.fudgeval1); 2548052d159aSCy Schubert /* [Bug3527] Backward Incompatible: ic->fudgeval2 is 2549052d159aSCy Schubert * a string, instantiated via memcpy() so there is no 2550052d159aSCy Schubert * endian issue to correct. 2551052d159aSCy Schubert */ 2552052d159aSCy Schubert #ifdef DISABLE_BUG3527_FIX 25532b15cb3dSCy Schubert ic->fudgeval2 = htonl(clock_stat.fudgeval2); 2554052d159aSCy Schubert #else 2555052d159aSCy Schubert ic->fudgeval2 = clock_stat.fudgeval2; 2556052d159aSCy Schubert #endif 2557c0b746e5SOllivier Robert 2558c0b746e5SOllivier Robert free_varlist(clock_stat.kv_list); 2559c0b746e5SOllivier Robert 2560c0b746e5SOllivier Robert ic = (struct info_clock *)more_pkt(); 2561c0b746e5SOllivier Robert } 2562c0b746e5SOllivier Robert flush_pkt(); 2563c0b746e5SOllivier Robert } 2564c0b746e5SOllivier Robert 2565c0b746e5SOllivier Robert 2566c0b746e5SOllivier Robert 2567c0b746e5SOllivier Robert /* 2568c0b746e5SOllivier Robert * set_clock_fudge - get a clock's fudge factors 2569c0b746e5SOllivier Robert */ 2570c0b746e5SOllivier Robert static void 2571c0b746e5SOllivier Robert set_clock_fudge( 25722b15cb3dSCy Schubert sockaddr_u *srcadr, 25732b15cb3dSCy Schubert endpt *inter, 2574c0b746e5SOllivier Robert struct req_pkt *inpkt 2575c0b746e5SOllivier Robert ) 2576c0b746e5SOllivier Robert { 2577c0b746e5SOllivier Robert register struct conf_fudge *cf; 2578c0b746e5SOllivier Robert register int items; 2579c0b746e5SOllivier Robert struct refclockstat clock_stat; 25802b15cb3dSCy Schubert sockaddr_u addr; 2581c0b746e5SOllivier Robert l_fp ltmp; 2582c0b746e5SOllivier Robert 25832b15cb3dSCy Schubert ZERO(addr); 25842b15cb3dSCy Schubert ZERO(clock_stat); 2585c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 25862b15cb3dSCy Schubert cf = (struct conf_fudge *)&inpkt->u; 2587c0b746e5SOllivier Robert 2588c0b746e5SOllivier Robert while (items-- > 0) { 25892b15cb3dSCy Schubert AF(&addr) = AF_INET; 25902b15cb3dSCy Schubert NSRCADR(&addr) = cf->clockadr; 25912b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 25922b15cb3dSCy Schubert addr.sa.sa_len = SOCKLEN(&addr); 25939c2daa00SOllivier Robert #endif 25942b15cb3dSCy Schubert SET_PORT(&addr, NTP_PORT); 25952b15cb3dSCy Schubert if (!ISREFCLOCKADR(&addr) || NULL == 259609100258SXin LI findexistingpeer(&addr, NULL, NULL, -1, 0, NULL)) { 2597c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2598c0b746e5SOllivier Robert return; 2599c0b746e5SOllivier Robert } 2600c0b746e5SOllivier Robert 2601c0b746e5SOllivier Robert switch(ntohl(cf->which)) { 2602c0b746e5SOllivier Robert case FUDGE_TIME1: 2603c0b746e5SOllivier Robert NTOHL_FP(&cf->fudgetime, <mp); 2604c0b746e5SOllivier Robert LFPTOD(<mp, clock_stat.fudgetime1); 2605c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVETIME1; 2606c0b746e5SOllivier Robert break; 2607c0b746e5SOllivier Robert case FUDGE_TIME2: 2608c0b746e5SOllivier Robert NTOHL_FP(&cf->fudgetime, <mp); 2609c0b746e5SOllivier Robert LFPTOD(<mp, clock_stat.fudgetime2); 2610c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVETIME2; 2611c0b746e5SOllivier Robert break; 2612c0b746e5SOllivier Robert case FUDGE_VAL1: 2613c0b746e5SOllivier Robert clock_stat.fudgeval1 = ntohl(cf->fudgeval_flags); 2614c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVEVAL1; 2615c0b746e5SOllivier Robert break; 2616c0b746e5SOllivier Robert case FUDGE_VAL2: 2617c0b746e5SOllivier Robert clock_stat.fudgeval2 = ntohl(cf->fudgeval_flags); 2618c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVEVAL2; 2619c0b746e5SOllivier Robert break; 2620c0b746e5SOllivier Robert case FUDGE_FLAGS: 26219c2daa00SOllivier Robert clock_stat.flags = (u_char) (ntohl(cf->fudgeval_flags) & 0xf); 2622c0b746e5SOllivier Robert clock_stat.haveflags = 2623c0b746e5SOllivier Robert (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4); 2624c0b746e5SOllivier Robert break; 2625c0b746e5SOllivier Robert default: 2626224ba2bdSOllivier Robert msyslog(LOG_ERR, "set_clock_fudge: default!"); 2627c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2628c0b746e5SOllivier Robert return; 2629c0b746e5SOllivier Robert } 2630c0b746e5SOllivier Robert 2631c0b746e5SOllivier Robert refclock_control(&addr, &clock_stat, (struct refclockstat *)0); 2632c0b746e5SOllivier Robert } 2633c0b746e5SOllivier Robert 2634c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2635c0b746e5SOllivier Robert } 2636c0b746e5SOllivier Robert #endif 2637c0b746e5SOllivier Robert 2638c0b746e5SOllivier Robert #ifdef REFCLOCK 2639c0b746e5SOllivier Robert /* 2640c0b746e5SOllivier Robert * get_clkbug_info - get debugging info about a clock 2641c0b746e5SOllivier Robert */ 2642c0b746e5SOllivier Robert static void 2643c0b746e5SOllivier Robert get_clkbug_info( 26442b15cb3dSCy Schubert sockaddr_u *srcadr, 26452b15cb3dSCy Schubert endpt *inter, 2646c0b746e5SOllivier Robert struct req_pkt *inpkt 2647c0b746e5SOllivier Robert ) 2648c0b746e5SOllivier Robert { 2649c0b746e5SOllivier Robert register int i; 2650c0b746e5SOllivier Robert register struct info_clkbug *ic; 2651c0b746e5SOllivier Robert register u_int32 *clkaddr; 2652c0b746e5SOllivier Robert register int items; 2653c0b746e5SOllivier Robert struct refclockbug bug; 26542b15cb3dSCy Schubert sockaddr_u addr; 2655c0b746e5SOllivier Robert 26562b15cb3dSCy Schubert ZERO_SOCK(&addr); 26572b15cb3dSCy Schubert AF(&addr) = AF_INET; 26582b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 26592b15cb3dSCy Schubert addr.sa.sa_len = SOCKLEN(&addr); 26609c2daa00SOllivier Robert #endif 26612b15cb3dSCy Schubert SET_PORT(&addr, NTP_PORT); 2662c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 26632b15cb3dSCy Schubert clkaddr = (u_int32 *)&inpkt->u; 2664c0b746e5SOllivier Robert 2665c0b746e5SOllivier Robert ic = (struct info_clkbug *)prepare_pkt(srcadr, inter, inpkt, 2666c0b746e5SOllivier Robert sizeof(struct info_clkbug)); 2667c0b746e5SOllivier Robert 266868ba7e87SXin LI while (items-- > 0 && ic) { 26692b15cb3dSCy Schubert NSRCADR(&addr) = *clkaddr++; 26702b15cb3dSCy Schubert if (!ISREFCLOCKADR(&addr) || NULL == 267109100258SXin LI findexistingpeer(&addr, NULL, NULL, -1, 0, NULL)) { 2672c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2673c0b746e5SOllivier Robert return; 2674c0b746e5SOllivier Robert } 2675c0b746e5SOllivier Robert 26762b15cb3dSCy Schubert ZERO(bug); 2677c0b746e5SOllivier Robert refclock_buginfo(&addr, &bug); 2678c0b746e5SOllivier Robert if (bug.nvalues == 0 && bug.ntimes == 0) { 2679c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2680c0b746e5SOllivier Robert return; 2681c0b746e5SOllivier Robert } 2682c0b746e5SOllivier Robert 26832b15cb3dSCy Schubert ic->clockadr = NSRCADR(&addr); 2684c0b746e5SOllivier Robert i = bug.nvalues; 2685c0b746e5SOllivier Robert if (i > NUMCBUGVALUES) 2686c0b746e5SOllivier Robert i = NUMCBUGVALUES; 2687c0b746e5SOllivier Robert ic->nvalues = (u_char)i; 2688c0b746e5SOllivier Robert ic->svalues = htons((u_short) (bug.svalues & ((1<<i)-1))); 2689c0b746e5SOllivier Robert while (--i >= 0) 2690c0b746e5SOllivier Robert ic->values[i] = htonl(bug.values[i]); 2691c0b746e5SOllivier Robert 2692c0b746e5SOllivier Robert i = bug.ntimes; 2693c0b746e5SOllivier Robert if (i > NUMCBUGTIMES) 2694c0b746e5SOllivier Robert i = NUMCBUGTIMES; 2695c0b746e5SOllivier Robert ic->ntimes = (u_char)i; 2696c0b746e5SOllivier Robert ic->stimes = htonl(bug.stimes); 2697c0b746e5SOllivier Robert while (--i >= 0) { 2698c0b746e5SOllivier Robert HTONL_FP(&bug.times[i], &ic->times[i]); 2699c0b746e5SOllivier Robert } 2700c0b746e5SOllivier Robert 2701c0b746e5SOllivier Robert ic = (struct info_clkbug *)more_pkt(); 2702c0b746e5SOllivier Robert } 2703c0b746e5SOllivier Robert flush_pkt(); 2704c0b746e5SOllivier Robert } 2705c0b746e5SOllivier Robert #endif 2706ea906c41SOllivier Robert 2707ea906c41SOllivier Robert /* 2708ea906c41SOllivier Robert * receiver of interface structures 2709ea906c41SOllivier Robert */ 2710ea906c41SOllivier Robert static void 2711ea906c41SOllivier Robert fill_info_if_stats(void *data, interface_info_t *interface_info) 2712ea906c41SOllivier Robert { 2713ea906c41SOllivier Robert struct info_if_stats **ifsp = (struct info_if_stats **)data; 2714ea906c41SOllivier Robert struct info_if_stats *ifs = *ifsp; 27152b15cb3dSCy Schubert endpt *ep = interface_info->ep; 2716ea906c41SOllivier Robert 271768ba7e87SXin LI if (NULL == ifs) 271868ba7e87SXin LI return; 271968ba7e87SXin LI 27202b15cb3dSCy Schubert ZERO(*ifs); 2721ea906c41SOllivier Robert 27222b15cb3dSCy Schubert if (IS_IPV6(&ep->sin)) { 272368ba7e87SXin LI if (!client_v6_capable) 2724ea906c41SOllivier Robert return; 2725ea906c41SOllivier Robert ifs->v6_flag = 1; 27262b15cb3dSCy Schubert ifs->unaddr.addr6 = SOCK_ADDR6(&ep->sin); 27272b15cb3dSCy Schubert ifs->unbcast.addr6 = SOCK_ADDR6(&ep->bcast); 27282b15cb3dSCy Schubert ifs->unmask.addr6 = SOCK_ADDR6(&ep->mask); 2729ea906c41SOllivier Robert } else { 2730ea906c41SOllivier Robert ifs->v6_flag = 0; 27312b15cb3dSCy Schubert ifs->unaddr.addr = SOCK_ADDR4(&ep->sin); 27322b15cb3dSCy Schubert ifs->unbcast.addr = SOCK_ADDR4(&ep->bcast); 27332b15cb3dSCy Schubert ifs->unmask.addr = SOCK_ADDR4(&ep->mask); 2734ea906c41SOllivier Robert } 2735ea906c41SOllivier Robert ifs->v6_flag = htonl(ifs->v6_flag); 27362b15cb3dSCy Schubert strlcpy(ifs->name, ep->name, sizeof(ifs->name)); 27372b15cb3dSCy Schubert ifs->family = htons(ep->family); 27382b15cb3dSCy Schubert ifs->flags = htonl(ep->flags); 27392b15cb3dSCy Schubert ifs->last_ttl = htonl(ep->last_ttl); 27402b15cb3dSCy Schubert ifs->num_mcast = htonl(ep->num_mcast); 27412b15cb3dSCy Schubert ifs->received = htonl(ep->received); 27422b15cb3dSCy Schubert ifs->sent = htonl(ep->sent); 27432b15cb3dSCy Schubert ifs->notsent = htonl(ep->notsent); 27442b15cb3dSCy Schubert ifs->ifindex = htonl(ep->ifindex); 27452b15cb3dSCy Schubert /* scope no longer in endpt, in in6_addr typically */ 27462b15cb3dSCy Schubert ifs->scopeid = ifs->ifindex; 27472b15cb3dSCy Schubert ifs->ifnum = htonl(ep->ifnum); 27482b15cb3dSCy Schubert ifs->uptime = htonl(current_time - ep->starttime); 27492b15cb3dSCy Schubert ifs->ignore_packets = ep->ignore_packets; 27502b15cb3dSCy Schubert ifs->peercnt = htonl(ep->peercnt); 2751ea906c41SOllivier Robert ifs->action = interface_info->action; 2752ea906c41SOllivier Robert 2753ea906c41SOllivier Robert *ifsp = (struct info_if_stats *)more_pkt(); 2754ea906c41SOllivier Robert } 2755ea906c41SOllivier Robert 2756ea906c41SOllivier Robert /* 2757ea906c41SOllivier Robert * get_if_stats - get interface statistics 2758ea906c41SOllivier Robert */ 2759ea906c41SOllivier Robert static void 2760ea906c41SOllivier Robert get_if_stats( 27612b15cb3dSCy Schubert sockaddr_u *srcadr, 27622b15cb3dSCy Schubert endpt *inter, 2763ea906c41SOllivier Robert struct req_pkt *inpkt 2764ea906c41SOllivier Robert ) 2765ea906c41SOllivier Robert { 2766ea906c41SOllivier Robert struct info_if_stats *ifs; 2767ea906c41SOllivier Robert 2768ea906c41SOllivier Robert DPRINTF(3, ("wants interface statistics\n")); 2769ea906c41SOllivier Robert 2770ea906c41SOllivier Robert ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt, 2771ea906c41SOllivier Robert v6sizeof(struct info_if_stats)); 2772ea906c41SOllivier Robert 2773ea906c41SOllivier Robert interface_enumerate(fill_info_if_stats, &ifs); 2774ea906c41SOllivier Robert 2775ea906c41SOllivier Robert flush_pkt(); 2776ea906c41SOllivier Robert } 2777ea906c41SOllivier Robert 2778ea906c41SOllivier Robert static void 2779ea906c41SOllivier Robert do_if_reload( 27802b15cb3dSCy Schubert sockaddr_u *srcadr, 27812b15cb3dSCy Schubert endpt *inter, 2782ea906c41SOllivier Robert struct req_pkt *inpkt 2783ea906c41SOllivier Robert ) 2784ea906c41SOllivier Robert { 2785ea906c41SOllivier Robert struct info_if_stats *ifs; 2786ea906c41SOllivier Robert 2787ea906c41SOllivier Robert DPRINTF(3, ("wants interface reload\n")); 2788ea906c41SOllivier Robert 2789ea906c41SOllivier Robert ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt, 2790ea906c41SOllivier Robert v6sizeof(struct info_if_stats)); 2791ea906c41SOllivier Robert 2792ea906c41SOllivier Robert interface_update(fill_info_if_stats, &ifs); 2793ea906c41SOllivier Robert 2794ea906c41SOllivier Robert flush_pkt(); 2795ea906c41SOllivier Robert } 2796ea906c41SOllivier Robert 2797