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); 842b15cb3dSCy Schubert static void list_restrict4 (restrict_u *, struct info_restrict **); 852b15cb3dSCy Schubert static void list_restrict6 (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 *); 902b15cb3dSCy Schubert static void do_restrict (sockaddr_u *, endpt *, struct req_pkt *, int); 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 */ 5852b15cb3dSCy Schubert if (!INFO_IS_AUTH(inpkt->auth_seq) || !info_auth_keyid 586ce265a54SOllivier Robert || ntohl(tailinpkt->keyid) != info_auth_keyid) { 5872b15cb3dSCy Schubert DPRINTF(5, ("failed auth %d info_auth_keyid %u pkt keyid %u maclen %lu\n", 5882b15cb3dSCy Schubert INFO_IS_AUTH(inpkt->auth_seq), 5892b15cb3dSCy Schubert info_auth_keyid, 5902b15cb3dSCy Schubert ntohl(tailinpkt->keyid), (u_long)mac_len)); 591c0b746e5SOllivier Robert #ifdef DEBUG 5929c2daa00SOllivier Robert msyslog(LOG_DEBUG, 5932b15cb3dSCy Schubert "process_private: failed auth %d info_auth_keyid %u pkt keyid %u maclen %lu\n", 5949c2daa00SOllivier Robert INFO_IS_AUTH(inpkt->auth_seq), 5952b15cb3dSCy Schubert info_auth_keyid, 5962b15cb3dSCy Schubert ntohl(tailinpkt->keyid), (u_long)mac_len); 597c0b746e5SOllivier Robert #endif 598c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 599c0b746e5SOllivier Robert return; 600c0b746e5SOllivier Robert } 6012b15cb3dSCy Schubert if (recv_len > REQ_LEN_NOMAC + MAX_MAC_LEN) { 6022b15cb3dSCy Schubert DPRINTF(5, ("bad pkt length %zu\n", recv_len)); 6032b15cb3dSCy Schubert msyslog(LOG_ERR, 6042b15cb3dSCy Schubert "process_private: bad pkt length %zu", 6052b15cb3dSCy Schubert recv_len); 606c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 607c0b746e5SOllivier Robert return; 608c0b746e5SOllivier Robert } 609c0b746e5SOllivier Robert if (!mod_okay || !authhavekey(info_auth_keyid)) { 6102b15cb3dSCy Schubert DPRINTF(5, ("failed auth mod_okay %d\n", 6112b15cb3dSCy Schubert mod_okay)); 612c0b746e5SOllivier Robert #ifdef DEBUG 6139c2daa00SOllivier Robert msyslog(LOG_DEBUG, 6149c2daa00SOllivier Robert "process_private: failed auth mod_okay %d\n", 6159c2daa00SOllivier Robert mod_okay); 616c0b746e5SOllivier Robert #endif 6172b15cb3dSCy Schubert if (!mod_okay) { 6182b15cb3dSCy Schubert sys_restricted++; 6192b15cb3dSCy Schubert } 620c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 621c0b746e5SOllivier Robert return; 622c0b746e5SOllivier Robert } 623c0b746e5SOllivier Robert 624c0b746e5SOllivier Robert /* 625c0b746e5SOllivier Robert * calculate absolute time difference between xmit time stamp 626c0b746e5SOllivier Robert * and receive time stamp. If too large, too bad. 627c0b746e5SOllivier Robert */ 628ce265a54SOllivier Robert NTOHL_FP(&tailinpkt->tstamp, &ftmp); 629c0b746e5SOllivier Robert L_SUB(&ftmp, &rbufp->recv_time); 630c0b746e5SOllivier Robert LFPTOD(&ftmp, dtemp); 6312b15cb3dSCy Schubert if (fabs(dtemp) > INFO_TS_MAXSKEW) { 632c0b746e5SOllivier Robert /* 633c0b746e5SOllivier Robert * He's a loser. Tell him. 634c0b746e5SOllivier Robert */ 6352b15cb3dSCy Schubert DPRINTF(5, ("xmit/rcv timestamp delta %g > INFO_TS_MAXSKEW %g\n", 6362b15cb3dSCy Schubert dtemp, INFO_TS_MAXSKEW)); 637c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 638c0b746e5SOllivier Robert return; 639c0b746e5SOllivier Robert } 640c0b746e5SOllivier Robert 641c0b746e5SOllivier Robert /* 642c0b746e5SOllivier Robert * So far so good. See if decryption works out okay. 643c0b746e5SOllivier Robert */ 644c0b746e5SOllivier Robert if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt, 6452b15cb3dSCy Schubert recv_len - mac_len, mac_len)) { 6462b15cb3dSCy Schubert DPRINTF(5, ("authdecrypt failed\n")); 647c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 648c0b746e5SOllivier Robert return; 649c0b746e5SOllivier Robert } 650c0b746e5SOllivier Robert } 651c0b746e5SOllivier Robert 6522b15cb3dSCy Schubert DPRINTF(3, ("process_private: all okay, into handler\n")); 653c0b746e5SOllivier Robert /* 654c0b746e5SOllivier Robert * Packet is okay. Call the handler to send him data. 655c0b746e5SOllivier Robert */ 656c0b746e5SOllivier Robert (proc->handler)(srcadr, inter, inpkt); 657c0b746e5SOllivier Robert } 658c0b746e5SOllivier Robert 659c0b746e5SOllivier Robert 660c0b746e5SOllivier Robert /* 6612b15cb3dSCy Schubert * list_peers - send a list of the peers 662c0b746e5SOllivier Robert */ 663c0b746e5SOllivier Robert static void 6642b15cb3dSCy Schubert list_peers( 6652b15cb3dSCy Schubert sockaddr_u *srcadr, 6662b15cb3dSCy Schubert endpt *inter, 667c0b746e5SOllivier Robert struct req_pkt *inpkt 668c0b746e5SOllivier Robert ) 669c0b746e5SOllivier Robert { 6702b15cb3dSCy Schubert struct info_peer_list *ip; 6712b15cb3dSCy Schubert struct peer *pp; 6722b15cb3dSCy Schubert int skip = 0; 673c0b746e5SOllivier Robert 674c0b746e5SOllivier Robert ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt, 6759c2daa00SOllivier Robert v6sizeof(struct info_peer_list)); 6762b15cb3dSCy Schubert for (pp = peer_list; pp != NULL && ip != NULL; pp = pp->p_link) { 6772b15cb3dSCy Schubert if (IS_IPV6(&pp->srcadr)) { 6789c2daa00SOllivier Robert if (client_v6_capable) { 6792b15cb3dSCy Schubert ip->addr6 = SOCK_ADDR6(&pp->srcadr); 6809c2daa00SOllivier Robert ip->v6_flag = 1; 6819c2daa00SOllivier Robert skip = 0; 6829c2daa00SOllivier Robert } else { 6839c2daa00SOllivier Robert skip = 1; 6849c2daa00SOllivier Robert break; 6859c2daa00SOllivier Robert } 6869c2daa00SOllivier Robert } else { 6872b15cb3dSCy Schubert ip->addr = NSRCADR(&pp->srcadr); 6889c2daa00SOllivier Robert if (client_v6_capable) 6899c2daa00SOllivier Robert ip->v6_flag = 0; 6909c2daa00SOllivier Robert skip = 0; 6919c2daa00SOllivier Robert } 6929c2daa00SOllivier Robert 6939c2daa00SOllivier Robert if (!skip) { 6949c2daa00SOllivier Robert ip->port = NSRCPORT(&pp->srcadr); 695c0b746e5SOllivier Robert ip->hmode = pp->hmode; 696c0b746e5SOllivier Robert ip->flags = 0; 697c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 698c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 699c0b746e5SOllivier Robert if (pp == sys_peer) 700c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 701c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 702c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 703c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 704c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 705c0b746e5SOllivier Robert ip = (struct info_peer_list *)more_pkt(); 7069c2daa00SOllivier Robert } 7072b15cb3dSCy Schubert } /* for pp */ 7082b15cb3dSCy Schubert 709c0b746e5SOllivier Robert flush_pkt(); 710c0b746e5SOllivier Robert } 711c0b746e5SOllivier Robert 712c0b746e5SOllivier Robert 713c0b746e5SOllivier Robert /* 7142b15cb3dSCy Schubert * list_peers_sum - return extended peer list 715c0b746e5SOllivier Robert */ 716c0b746e5SOllivier Robert static void 7172b15cb3dSCy Schubert list_peers_sum( 7182b15cb3dSCy Schubert sockaddr_u *srcadr, 7192b15cb3dSCy Schubert endpt *inter, 720c0b746e5SOllivier Robert struct req_pkt *inpkt 721c0b746e5SOllivier Robert ) 722c0b746e5SOllivier Robert { 723c0b746e5SOllivier Robert register struct info_peer_summary *ips; 724c0b746e5SOllivier Robert register struct peer *pp; 725c0b746e5SOllivier Robert l_fp ltmp; 7269c2daa00SOllivier Robert register int skip; 727c0b746e5SOllivier Robert 7282b15cb3dSCy Schubert DPRINTF(3, ("wants peer list summary\n")); 7292b15cb3dSCy Schubert 730c0b746e5SOllivier Robert ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt, 7319c2daa00SOllivier Robert v6sizeof(struct info_peer_summary)); 7322b15cb3dSCy Schubert for (pp = peer_list; pp != NULL && ips != NULL; pp = pp->p_link) { 7332b15cb3dSCy Schubert DPRINTF(4, ("sum: got one\n")); 7349c2daa00SOllivier Robert /* 7359c2daa00SOllivier Robert * Be careful here not to return v6 peers when we 7369c2daa00SOllivier Robert * want only v4. 7379c2daa00SOllivier Robert */ 7382b15cb3dSCy Schubert if (IS_IPV6(&pp->srcadr)) { 7399c2daa00SOllivier Robert if (client_v6_capable) { 7402b15cb3dSCy Schubert ips->srcadr6 = SOCK_ADDR6(&pp->srcadr); 7419c2daa00SOllivier Robert ips->v6_flag = 1; 742ea906c41SOllivier Robert if (pp->dstadr) 7432b15cb3dSCy Schubert ips->dstadr6 = SOCK_ADDR6(&pp->dstadr->sin); 744ea906c41SOllivier Robert else 7452b15cb3dSCy Schubert ZERO(ips->dstadr6); 7469c2daa00SOllivier Robert skip = 0; 7479c2daa00SOllivier Robert } else { 7489c2daa00SOllivier Robert skip = 1; 7499c2daa00SOllivier Robert break; 7509c2daa00SOllivier Robert } 7519c2daa00SOllivier Robert } else { 7522b15cb3dSCy Schubert ips->srcadr = NSRCADR(&pp->srcadr); 7539c2daa00SOllivier Robert if (client_v6_capable) 7549c2daa00SOllivier Robert ips->v6_flag = 0; 755ea906c41SOllivier Robert 7562b15cb3dSCy Schubert if (pp->dstadr) { 7572b15cb3dSCy Schubert if (!pp->processed) 7582b15cb3dSCy Schubert ips->dstadr = NSRCADR(&pp->dstadr->sin); 7592b15cb3dSCy Schubert else { 7602b15cb3dSCy Schubert if (MDF_BCAST == pp->cast_flags) 7612b15cb3dSCy Schubert ips->dstadr = NSRCADR(&pp->dstadr->bcast); 7622b15cb3dSCy Schubert else if (pp->cast_flags) { 7632b15cb3dSCy Schubert ips->dstadr = NSRCADR(&pp->dstadr->sin); 7642b15cb3dSCy Schubert if (!ips->dstadr) 7652b15cb3dSCy Schubert ips->dstadr = NSRCADR(&pp->dstadr->bcast); 7662b15cb3dSCy Schubert } 7672b15cb3dSCy Schubert } 7682b15cb3dSCy Schubert } else 7692b15cb3dSCy Schubert ips->dstadr = 0; 7709c2daa00SOllivier Robert 7719c2daa00SOllivier Robert skip = 0; 7729c2daa00SOllivier Robert } 773ea906c41SOllivier Robert 7749c2daa00SOllivier Robert if (!skip) { 7759c2daa00SOllivier Robert ips->srcport = NSRCPORT(&pp->srcadr); 776c0b746e5SOllivier Robert ips->stratum = pp->stratum; 777c0b746e5SOllivier Robert ips->hpoll = pp->hpoll; 778c0b746e5SOllivier Robert ips->ppoll = pp->ppoll; 779c0b746e5SOllivier Robert ips->reach = pp->reach; 780c0b746e5SOllivier Robert ips->flags = 0; 781c0b746e5SOllivier Robert if (pp == sys_peer) 782c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SYSPEER; 783c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 784c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_CONFIG; 785c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 786c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_REFCLOCK; 787c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 788c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_PREFER; 789c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 790c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_BURST; 791c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 792c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SEL_CANDIDATE; 793c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 794c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SHORTLIST; 795c0b746e5SOllivier Robert ips->hmode = pp->hmode; 796c0b746e5SOllivier Robert ips->delay = HTONS_FP(DTOFP(pp->delay)); 797c0b746e5SOllivier Robert DTOLFP(pp->offset, <mp); 798c0b746e5SOllivier Robert HTONL_FP(<mp, &ips->offset); 799ea906c41SOllivier Robert ips->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); 8009c2daa00SOllivier Robert } 801c0b746e5SOllivier Robert ips = (struct info_peer_summary *)more_pkt(); 8022b15cb3dSCy Schubert } /* for pp */ 8032b15cb3dSCy Schubert 804c0b746e5SOllivier Robert flush_pkt(); 805c0b746e5SOllivier Robert } 806c0b746e5SOllivier Robert 807c0b746e5SOllivier Robert 808c0b746e5SOllivier Robert /* 809c0b746e5SOllivier Robert * peer_info - send information for one or more peers 810c0b746e5SOllivier Robert */ 811c0b746e5SOllivier Robert static void 812c0b746e5SOllivier Robert peer_info ( 8132b15cb3dSCy Schubert sockaddr_u *srcadr, 8142b15cb3dSCy Schubert endpt *inter, 815c0b746e5SOllivier Robert struct req_pkt *inpkt 816c0b746e5SOllivier Robert ) 817c0b746e5SOllivier Robert { 8182b15cb3dSCy Schubert u_short items; 8192b15cb3dSCy Schubert size_t item_sz; 8202b15cb3dSCy Schubert char * datap; 8212b15cb3dSCy Schubert struct info_peer_list ipl; 8222b15cb3dSCy Schubert struct peer * pp; 8232b15cb3dSCy Schubert struct info_peer * ip; 8242b15cb3dSCy Schubert int i; 8252b15cb3dSCy Schubert int j; 8262b15cb3dSCy Schubert sockaddr_u addr; 827c0b746e5SOllivier Robert l_fp ltmp; 828c0b746e5SOllivier Robert 829c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 8302b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 8312b15cb3dSCy Schubert datap = inpkt->u.data; 8322b15cb3dSCy Schubert if (item_sz != sizeof(ipl)) { 8332b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 8342b15cb3dSCy Schubert return; 8359c2daa00SOllivier Robert } 8362b15cb3dSCy Schubert ip = prepare_pkt(srcadr, inter, inpkt, 8372b15cb3dSCy Schubert v6sizeof(struct info_peer)); 8382b15cb3dSCy Schubert while (items-- > 0 && ip != NULL) { 8392b15cb3dSCy Schubert ZERO(ipl); 8402b15cb3dSCy Schubert memcpy(&ipl, datap, item_sz); 8412b15cb3dSCy Schubert ZERO_SOCK(&addr); 8422b15cb3dSCy Schubert NSRCPORT(&addr) = ipl.port; 8432b15cb3dSCy Schubert if (client_v6_capable && ipl.v6_flag) { 8442b15cb3dSCy Schubert AF(&addr) = AF_INET6; 8452b15cb3dSCy Schubert SOCK_ADDR6(&addr) = ipl.addr6; 8462b15cb3dSCy Schubert } else { 8472b15cb3dSCy Schubert AF(&addr) = AF_INET; 8482b15cb3dSCy Schubert NSRCADR(&addr) = ipl.addr; 8492b15cb3dSCy Schubert } 8502b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 8512b15cb3dSCy Schubert addr.sa.sa_len = SOCKLEN(&addr); 8529c2daa00SOllivier Robert #endif 8532b15cb3dSCy Schubert datap += item_sz; 854ea906c41SOllivier Robert 8552b15cb3dSCy Schubert pp = findexistingpeer(&addr, NULL, NULL, -1, 0); 8562b15cb3dSCy Schubert if (NULL == pp) 8572b15cb3dSCy Schubert continue; 8582b15cb3dSCy Schubert if (IS_IPV6(srcadr)) { 8592b15cb3dSCy Schubert if (pp->dstadr) 8602b15cb3dSCy Schubert ip->dstadr6 = 8612b15cb3dSCy Schubert (MDF_BCAST == pp->cast_flags) 8622b15cb3dSCy Schubert ? SOCK_ADDR6(&pp->dstadr->bcast) 8632b15cb3dSCy Schubert : SOCK_ADDR6(&pp->dstadr->sin); 8642b15cb3dSCy Schubert else 8652b15cb3dSCy Schubert ZERO(ip->dstadr6); 8662b15cb3dSCy Schubert 8672b15cb3dSCy Schubert ip->srcadr6 = SOCK_ADDR6(&pp->srcadr); 8689c2daa00SOllivier Robert ip->v6_flag = 1; 8699c2daa00SOllivier Robert } else { 8702b15cb3dSCy Schubert if (pp->dstadr) { 8712b15cb3dSCy Schubert if (!pp->processed) 8722b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->sin); 8732b15cb3dSCy Schubert else { 8742b15cb3dSCy Schubert if (MDF_BCAST == pp->cast_flags) 8752b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->bcast); 8762b15cb3dSCy Schubert else if (pp->cast_flags) { 8772b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->sin); 8782b15cb3dSCy Schubert if (!ip->dstadr) 8792b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->bcast); 8802b15cb3dSCy Schubert } 8812b15cb3dSCy Schubert } 8822b15cb3dSCy Schubert } else 8832b15cb3dSCy Schubert ip->dstadr = 0; 8849c2daa00SOllivier Robert 8852b15cb3dSCy Schubert ip->srcadr = NSRCADR(&pp->srcadr); 8869c2daa00SOllivier Robert if (client_v6_capable) 8879c2daa00SOllivier Robert ip->v6_flag = 0; 8889c2daa00SOllivier Robert } 889c0b746e5SOllivier Robert ip->srcport = NSRCPORT(&pp->srcadr); 890c0b746e5SOllivier Robert ip->flags = 0; 891c0b746e5SOllivier Robert if (pp == sys_peer) 892c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 893c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 894c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 895c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 896c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_REFCLOCK; 897c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 898c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_PREFER; 899c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 900c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_BURST; 901c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 902c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 903c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 904c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 905c0b746e5SOllivier Robert ip->leap = pp->leap; 906c0b746e5SOllivier Robert ip->hmode = pp->hmode; 907c0b746e5SOllivier Robert ip->keyid = pp->keyid; 908c0b746e5SOllivier Robert ip->stratum = pp->stratum; 909c0b746e5SOllivier Robert ip->ppoll = pp->ppoll; 910c0b746e5SOllivier Robert ip->hpoll = pp->hpoll; 911c0b746e5SOllivier Robert ip->precision = pp->precision; 912c0b746e5SOllivier Robert ip->version = pp->version; 913c0b746e5SOllivier Robert ip->reach = pp->reach; 9149c2daa00SOllivier Robert ip->unreach = (u_char)pp->unreach; 915c0b746e5SOllivier Robert ip->flash = (u_char)pp->flash; 9169c2daa00SOllivier Robert ip->flash2 = (u_short)pp->flash; 9172b15cb3dSCy Schubert ip->estbdelay = HTONS_FP(DTOFP(pp->delay)); 9182b15cb3dSCy Schubert ip->ttl = (u_char)pp->ttl; 919c0b746e5SOllivier Robert ip->associd = htons(pp->associd); 920c0b746e5SOllivier Robert ip->rootdelay = HTONS_FP(DTOUFP(pp->rootdelay)); 9212b15cb3dSCy Schubert ip->rootdispersion = HTONS_FP(DTOUFP(pp->rootdisp)); 922c0b746e5SOllivier Robert ip->refid = pp->refid; 923c0b746e5SOllivier Robert HTONL_FP(&pp->reftime, &ip->reftime); 9242b15cb3dSCy Schubert HTONL_FP(&pp->aorg, &ip->org); 925c0b746e5SOllivier Robert HTONL_FP(&pp->rec, &ip->rec); 926c0b746e5SOllivier Robert HTONL_FP(&pp->xmt, &ip->xmt); 927c0b746e5SOllivier Robert j = pp->filter_nextpt - 1; 928c0b746e5SOllivier Robert for (i = 0; i < NTP_SHIFT; i++, j--) { 929c0b746e5SOllivier Robert if (j < 0) 930c0b746e5SOllivier Robert j = NTP_SHIFT-1; 931c0b746e5SOllivier Robert ip->filtdelay[i] = HTONS_FP(DTOFP(pp->filter_delay[j])); 932c0b746e5SOllivier Robert DTOLFP(pp->filter_offset[j], <mp); 933c0b746e5SOllivier Robert HTONL_FP(<mp, &ip->filtoffset[i]); 9342b15cb3dSCy Schubert ip->order[i] = (u_char)((pp->filter_nextpt + 9352b15cb3dSCy Schubert NTP_SHIFT - 1) - 9362b15cb3dSCy Schubert pp->filter_order[i]); 937c0b746e5SOllivier Robert if (ip->order[i] >= NTP_SHIFT) 938c0b746e5SOllivier Robert ip->order[i] -= NTP_SHIFT; 939c0b746e5SOllivier Robert } 940c0b746e5SOllivier Robert DTOLFP(pp->offset, <mp); 941c0b746e5SOllivier Robert HTONL_FP(<mp, &ip->offset); 942c0b746e5SOllivier Robert ip->delay = HTONS_FP(DTOFP(pp->delay)); 943c0b746e5SOllivier Robert ip->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); 944224ba2bdSOllivier Robert ip->selectdisp = HTONS_FP(DTOUFP(SQRT(pp->jitter))); 9452b15cb3dSCy Schubert ip = more_pkt(); 946c0b746e5SOllivier Robert } 947c0b746e5SOllivier Robert flush_pkt(); 948c0b746e5SOllivier Robert } 949c0b746e5SOllivier Robert 950c0b746e5SOllivier Robert 951c0b746e5SOllivier Robert /* 952c0b746e5SOllivier Robert * peer_stats - send statistics for one or more peers 953c0b746e5SOllivier Robert */ 954c0b746e5SOllivier Robert static void 955c0b746e5SOllivier Robert peer_stats ( 9562b15cb3dSCy Schubert sockaddr_u *srcadr, 9572b15cb3dSCy Schubert endpt *inter, 958c0b746e5SOllivier Robert struct req_pkt *inpkt 959c0b746e5SOllivier Robert ) 960c0b746e5SOllivier Robert { 9612b15cb3dSCy Schubert u_short items; 9622b15cb3dSCy Schubert size_t item_sz; 9632b15cb3dSCy Schubert char * datap; 9642b15cb3dSCy Schubert struct info_peer_list ipl; 9652b15cb3dSCy Schubert struct peer * pp; 9662b15cb3dSCy Schubert struct info_peer_stats *ip; 9672b15cb3dSCy Schubert sockaddr_u addr; 968c0b746e5SOllivier Robert 9692b15cb3dSCy Schubert DPRINTF(1, ("peer_stats: called\n")); 970c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 9712b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 9722b15cb3dSCy Schubert datap = inpkt->u.data; 9732b15cb3dSCy Schubert if (item_sz > sizeof(ipl)) { 9742b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 9752b15cb3dSCy Schubert return; 9769c2daa00SOllivier Robert } 9772b15cb3dSCy Schubert ip = prepare_pkt(srcadr, inter, inpkt, 9782b15cb3dSCy Schubert v6sizeof(struct info_peer_stats)); 9792b15cb3dSCy Schubert while (items-- > 0 && ip != NULL) { 9802b15cb3dSCy Schubert ZERO(ipl); 9812b15cb3dSCy Schubert memcpy(&ipl, datap, item_sz); 9822b15cb3dSCy Schubert ZERO(addr); 9832b15cb3dSCy Schubert NSRCPORT(&addr) = ipl.port; 9842b15cb3dSCy Schubert if (client_v6_capable && ipl.v6_flag) { 9852b15cb3dSCy Schubert AF(&addr) = AF_INET6; 9862b15cb3dSCy Schubert SOCK_ADDR6(&addr) = ipl.addr6; 9872b15cb3dSCy Schubert } else { 9882b15cb3dSCy Schubert AF(&addr) = AF_INET; 9892b15cb3dSCy Schubert NSRCADR(&addr) = ipl.addr; 9902b15cb3dSCy Schubert } 9912b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 9922b15cb3dSCy Schubert addr.sa.sa_len = SOCKLEN(&addr); 9939c2daa00SOllivier Robert #endif 9942b15cb3dSCy Schubert DPRINTF(1, ("peer_stats: looking for %s, %d, %d\n", 9952b15cb3dSCy Schubert stoa(&addr), ipl.port, NSRCPORT(&addr))); 9969c2daa00SOllivier Robert 9972b15cb3dSCy Schubert datap += item_sz; 9982b15cb3dSCy Schubert 9992b15cb3dSCy Schubert pp = findexistingpeer(&addr, NULL, NULL, -1, 0); 10002b15cb3dSCy Schubert if (NULL == pp) 1001c0b746e5SOllivier Robert continue; 1002ea906c41SOllivier Robert 10032b15cb3dSCy Schubert DPRINTF(1, ("peer_stats: found %s\n", stoa(&addr))); 10042b15cb3dSCy Schubert 10052b15cb3dSCy Schubert if (IS_IPV4(&pp->srcadr)) { 10062b15cb3dSCy Schubert if (pp->dstadr) { 10072b15cb3dSCy Schubert if (!pp->processed) 10082b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->sin); 10092b15cb3dSCy Schubert else { 10102b15cb3dSCy Schubert if (MDF_BCAST == pp->cast_flags) 10112b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->bcast); 10122b15cb3dSCy Schubert else if (pp->cast_flags) { 10132b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->sin); 10142b15cb3dSCy Schubert if (!ip->dstadr) 10152b15cb3dSCy Schubert ip->dstadr = NSRCADR(&pp->dstadr->bcast); 10162b15cb3dSCy Schubert } 10172b15cb3dSCy Schubert } 10182b15cb3dSCy Schubert } else 10192b15cb3dSCy Schubert ip->dstadr = 0; 10202b15cb3dSCy Schubert 10212b15cb3dSCy Schubert ip->srcadr = NSRCADR(&pp->srcadr); 10229c2daa00SOllivier Robert if (client_v6_capable) 10239c2daa00SOllivier Robert ip->v6_flag = 0; 10249c2daa00SOllivier Robert } else { 1025ea906c41SOllivier Robert if (pp->dstadr) 10262b15cb3dSCy Schubert ip->dstadr6 = 10272b15cb3dSCy Schubert (MDF_BCAST == pp->cast_flags) 10282b15cb3dSCy Schubert ? SOCK_ADDR6(&pp->dstadr->bcast) 10292b15cb3dSCy Schubert : SOCK_ADDR6(&pp->dstadr->sin); 1030ea906c41SOllivier Robert else 10312b15cb3dSCy Schubert ZERO(ip->dstadr6); 1032ea906c41SOllivier Robert 10332b15cb3dSCy Schubert ip->srcadr6 = SOCK_ADDR6(&pp->srcadr); 10349c2daa00SOllivier Robert ip->v6_flag = 1; 10359c2daa00SOllivier Robert } 1036c0b746e5SOllivier Robert ip->srcport = NSRCPORT(&pp->srcadr); 1037c0b746e5SOllivier Robert ip->flags = 0; 1038c0b746e5SOllivier Robert if (pp == sys_peer) 1039c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 1040c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 1041c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 1042c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 1043c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_REFCLOCK; 1044c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 1045c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_PREFER; 1046c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 1047c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_BURST; 1048ea906c41SOllivier Robert if (pp->flags & FLAG_IBURST) 1049ea906c41SOllivier Robert ip->flags |= INFO_FLAG_IBURST; 1050c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 1051c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 1052c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 1053c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 1054ea906c41SOllivier Robert ip->flags = htons(ip->flags); 1055c0b746e5SOllivier Robert ip->timereceived = htonl((u_int32)(current_time - pp->timereceived)); 1056c0b746e5SOllivier Robert ip->timetosend = htonl(pp->nextdate - current_time); 1057c0b746e5SOllivier Robert ip->timereachable = htonl((u_int32)(current_time - pp->timereachable)); 1058c0b746e5SOllivier Robert ip->sent = htonl((u_int32)(pp->sent)); 1059c0b746e5SOllivier Robert ip->processed = htonl((u_int32)(pp->processed)); 1060c0b746e5SOllivier Robert ip->badauth = htonl((u_int32)(pp->badauth)); 1061c0b746e5SOllivier Robert ip->bogusorg = htonl((u_int32)(pp->bogusorg)); 1062c0b746e5SOllivier Robert ip->oldpkt = htonl((u_int32)(pp->oldpkt)); 1063c0b746e5SOllivier Robert ip->seldisp = htonl((u_int32)(pp->seldisptoolarge)); 1064c0b746e5SOllivier Robert ip->selbroken = htonl((u_int32)(pp->selbroken)); 1065c0b746e5SOllivier Robert ip->candidate = pp->status; 1066c0b746e5SOllivier Robert ip = (struct info_peer_stats *)more_pkt(); 1067c0b746e5SOllivier Robert } 1068c0b746e5SOllivier Robert flush_pkt(); 1069c0b746e5SOllivier Robert } 1070c0b746e5SOllivier Robert 1071c0b746e5SOllivier Robert 1072c0b746e5SOllivier Robert /* 1073c0b746e5SOllivier Robert * sys_info - return system info 1074c0b746e5SOllivier Robert */ 1075c0b746e5SOllivier Robert static void 1076c0b746e5SOllivier Robert sys_info( 10772b15cb3dSCy Schubert sockaddr_u *srcadr, 10782b15cb3dSCy Schubert endpt *inter, 1079c0b746e5SOllivier Robert struct req_pkt *inpkt 1080c0b746e5SOllivier Robert ) 1081c0b746e5SOllivier Robert { 1082c0b746e5SOllivier Robert register struct info_sys *is; 1083c0b746e5SOllivier Robert 1084c0b746e5SOllivier Robert is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt, 10859c2daa00SOllivier Robert v6sizeof(struct info_sys)); 1086c0b746e5SOllivier Robert 10872b15cb3dSCy Schubert if (sys_peer) { 10882b15cb3dSCy Schubert if (IS_IPV4(&sys_peer->srcadr)) { 10892b15cb3dSCy Schubert is->peer = NSRCADR(&sys_peer->srcadr); 10909c2daa00SOllivier Robert if (client_v6_capable) 10919c2daa00SOllivier Robert is->v6_flag = 0; 10929c2daa00SOllivier Robert } else if (client_v6_capable) { 10932b15cb3dSCy Schubert is->peer6 = SOCK_ADDR6(&sys_peer->srcadr); 10949c2daa00SOllivier Robert is->v6_flag = 1; 10959c2daa00SOllivier Robert } 1096c0b746e5SOllivier Robert is->peer_mode = sys_peer->hmode; 1097c0b746e5SOllivier Robert } else { 1098c0b746e5SOllivier Robert is->peer = 0; 10999c2daa00SOllivier Robert if (client_v6_capable) { 11009c2daa00SOllivier Robert is->v6_flag = 0; 11019c2daa00SOllivier Robert } 1102c0b746e5SOllivier Robert is->peer_mode = 0; 1103c0b746e5SOllivier Robert } 11049c2daa00SOllivier Robert 1105c0b746e5SOllivier Robert is->leap = sys_leap; 1106c0b746e5SOllivier Robert is->stratum = sys_stratum; 1107c0b746e5SOllivier Robert is->precision = sys_precision; 1108c0b746e5SOllivier Robert is->rootdelay = htonl(DTOFP(sys_rootdelay)); 11092b15cb3dSCy Schubert is->rootdispersion = htonl(DTOUFP(sys_rootdisp)); 1110224ba2bdSOllivier Robert is->frequency = htonl(DTOFP(sys_jitter)); 11112b15cb3dSCy Schubert is->stability = htonl(DTOUFP(clock_stability * 1e6)); 1112c0b746e5SOllivier Robert is->refid = sys_refid; 1113c0b746e5SOllivier Robert HTONL_FP(&sys_reftime, &is->reftime); 1114c0b746e5SOllivier Robert 1115c0b746e5SOllivier Robert is->poll = sys_poll; 1116c0b746e5SOllivier Robert 1117c0b746e5SOllivier Robert is->flags = 0; 1118c0b746e5SOllivier Robert if (sys_authenticate) 1119c0b746e5SOllivier Robert is->flags |= INFO_FLAG_AUTHENTICATE; 1120ce265a54SOllivier Robert if (sys_bclient) 1121ce265a54SOllivier Robert is->flags |= INFO_FLAG_BCLIENT; 1122ce265a54SOllivier Robert #ifdef REFCLOCK 1123ce265a54SOllivier Robert if (cal_enable) 1124ce265a54SOllivier Robert is->flags |= INFO_FLAG_CAL; 1125ce265a54SOllivier Robert #endif /* REFCLOCK */ 1126c0b746e5SOllivier Robert if (kern_enable) 1127c0b746e5SOllivier Robert is->flags |= INFO_FLAG_KERNEL; 1128c0b746e5SOllivier Robert if (mon_enabled != MON_OFF) 1129c0b746e5SOllivier Robert is->flags |= INFO_FLAG_MONITOR; 1130ce265a54SOllivier Robert if (ntp_enable) 1131ce265a54SOllivier Robert is->flags |= INFO_FLAG_NTP; 11322b15cb3dSCy Schubert if (hardpps_enable) 1133ce265a54SOllivier Robert is->flags |= INFO_FLAG_PPS_SYNC; 1134c0b746e5SOllivier Robert if (stats_control) 1135c0b746e5SOllivier Robert is->flags |= INFO_FLAG_FILEGEN; 1136c0b746e5SOllivier Robert is->bdelay = HTONS_FP(DTOFP(sys_bdelay)); 11372b15cb3dSCy Schubert HTONL_UF(sys_authdelay.l_uf, &is->authdelay); 1138c0b746e5SOllivier Robert (void) more_pkt(); 1139c0b746e5SOllivier Robert flush_pkt(); 1140c0b746e5SOllivier Robert } 1141c0b746e5SOllivier Robert 1142c0b746e5SOllivier Robert 1143c0b746e5SOllivier Robert /* 1144c0b746e5SOllivier Robert * sys_stats - return system statistics 1145c0b746e5SOllivier Robert */ 1146c0b746e5SOllivier Robert static void 1147c0b746e5SOllivier Robert sys_stats( 11482b15cb3dSCy Schubert sockaddr_u *srcadr, 11492b15cb3dSCy Schubert endpt *inter, 1150c0b746e5SOllivier Robert struct req_pkt *inpkt 1151c0b746e5SOllivier Robert ) 1152c0b746e5SOllivier Robert { 1153c0b746e5SOllivier Robert register struct info_sys_stats *ss; 1154c0b746e5SOllivier Robert 1155c0b746e5SOllivier Robert ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt, 1156c0b746e5SOllivier Robert sizeof(struct info_sys_stats)); 1157c0b746e5SOllivier Robert ss->timeup = htonl((u_int32)current_time); 1158c0b746e5SOllivier Robert ss->timereset = htonl((u_int32)(current_time - sys_stattime)); 11599c2daa00SOllivier Robert ss->denied = htonl((u_int32)sys_restricted); 11602b15cb3dSCy Schubert ss->oldversionpkt = htonl((u_int32)sys_oldversion); 11612b15cb3dSCy Schubert ss->newversionpkt = htonl((u_int32)sys_newversion); 11622b15cb3dSCy Schubert ss->unknownversion = htonl((u_int32)sys_declined); 1163c0b746e5SOllivier Robert ss->badlength = htonl((u_int32)sys_badlength); 1164c0b746e5SOllivier Robert ss->processed = htonl((u_int32)sys_processed); 1165c0b746e5SOllivier Robert ss->badauth = htonl((u_int32)sys_badauth); 1166c0b746e5SOllivier Robert ss->limitrejected = htonl((u_int32)sys_limitrejected); 11679c2daa00SOllivier Robert ss->received = htonl((u_int32)sys_received); 1168c0b746e5SOllivier Robert (void) more_pkt(); 1169c0b746e5SOllivier Robert flush_pkt(); 1170c0b746e5SOllivier Robert } 1171c0b746e5SOllivier Robert 1172c0b746e5SOllivier Robert 1173c0b746e5SOllivier Robert /* 1174c0b746e5SOllivier Robert * mem_stats - return memory statistics 1175c0b746e5SOllivier Robert */ 1176c0b746e5SOllivier Robert static void 1177c0b746e5SOllivier Robert mem_stats( 11782b15cb3dSCy Schubert sockaddr_u *srcadr, 11792b15cb3dSCy Schubert endpt *inter, 1180c0b746e5SOllivier Robert struct req_pkt *inpkt 1181c0b746e5SOllivier Robert ) 1182c0b746e5SOllivier Robert { 1183c0b746e5SOllivier Robert register struct info_mem_stats *ms; 1184c0b746e5SOllivier Robert register int i; 1185c0b746e5SOllivier Robert 1186c0b746e5SOllivier Robert ms = (struct info_mem_stats *)prepare_pkt(srcadr, inter, inpkt, 1187c0b746e5SOllivier Robert sizeof(struct info_mem_stats)); 1188c0b746e5SOllivier Robert 1189c0b746e5SOllivier Robert ms->timereset = htonl((u_int32)(current_time - peer_timereset)); 1190c0b746e5SOllivier Robert ms->totalpeermem = htons((u_short)total_peer_structs); 1191c0b746e5SOllivier Robert ms->freepeermem = htons((u_short)peer_free_count); 1192c0b746e5SOllivier Robert ms->findpeer_calls = htonl((u_int32)findpeer_calls); 1193c0b746e5SOllivier Robert ms->allocations = htonl((u_int32)peer_allocations); 1194c0b746e5SOllivier Robert ms->demobilizations = htonl((u_int32)peer_demobilizations); 1195c0b746e5SOllivier Robert 11962b15cb3dSCy Schubert for (i = 0; i < NTP_HASH_SIZE; i++) 11972b15cb3dSCy Schubert ms->hashcount[i] = (u_char) 11982b15cb3dSCy Schubert max((u_int)peer_hash_count[i], UCHAR_MAX); 1199c0b746e5SOllivier Robert 12002b15cb3dSCy Schubert more_pkt(); 1201c0b746e5SOllivier Robert flush_pkt(); 1202c0b746e5SOllivier Robert } 1203c0b746e5SOllivier Robert 1204c0b746e5SOllivier Robert 1205c0b746e5SOllivier Robert /* 1206c0b746e5SOllivier Robert * io_stats - return io statistics 1207c0b746e5SOllivier Robert */ 1208c0b746e5SOllivier Robert static void 1209c0b746e5SOllivier Robert io_stats( 12102b15cb3dSCy Schubert sockaddr_u *srcadr, 12112b15cb3dSCy Schubert endpt *inter, 1212c0b746e5SOllivier Robert struct req_pkt *inpkt 1213c0b746e5SOllivier Robert ) 1214c0b746e5SOllivier Robert { 12152b15cb3dSCy Schubert struct info_io_stats *io; 1216c0b746e5SOllivier Robert 1217c0b746e5SOllivier Robert io = (struct info_io_stats *)prepare_pkt(srcadr, inter, inpkt, 1218c0b746e5SOllivier Robert sizeof(struct info_io_stats)); 1219c0b746e5SOllivier Robert 1220c0b746e5SOllivier Robert io->timereset = htonl((u_int32)(current_time - io_timereset)); 1221c0b746e5SOllivier Robert io->totalrecvbufs = htons((u_short) total_recvbuffs()); 1222c0b746e5SOllivier Robert io->freerecvbufs = htons((u_short) free_recvbuffs()); 1223c0b746e5SOllivier Robert io->fullrecvbufs = htons((u_short) full_recvbuffs()); 1224c0b746e5SOllivier Robert io->lowwater = htons((u_short) lowater_additions()); 1225c0b746e5SOllivier Robert io->dropped = htonl((u_int32)packets_dropped); 1226c0b746e5SOllivier Robert io->ignored = htonl((u_int32)packets_ignored); 1227c0b746e5SOllivier Robert io->received = htonl((u_int32)packets_received); 1228c0b746e5SOllivier Robert io->sent = htonl((u_int32)packets_sent); 1229c0b746e5SOllivier Robert io->notsent = htonl((u_int32)packets_notsent); 1230c0b746e5SOllivier Robert io->interrupts = htonl((u_int32)handler_calls); 1231c0b746e5SOllivier Robert io->int_received = htonl((u_int32)handler_pkts); 1232c0b746e5SOllivier Robert 1233c0b746e5SOllivier Robert (void) more_pkt(); 1234c0b746e5SOllivier Robert flush_pkt(); 1235c0b746e5SOllivier Robert } 1236c0b746e5SOllivier Robert 1237c0b746e5SOllivier Robert 1238c0b746e5SOllivier Robert /* 1239c0b746e5SOllivier Robert * timer_stats - return timer statistics 1240c0b746e5SOllivier Robert */ 1241c0b746e5SOllivier Robert static void 1242c0b746e5SOllivier Robert timer_stats( 12432b15cb3dSCy Schubert sockaddr_u * srcadr, 12442b15cb3dSCy Schubert endpt * inter, 1245c0b746e5SOllivier Robert struct req_pkt * inpkt 1246c0b746e5SOllivier Robert ) 1247c0b746e5SOllivier Robert { 12482b15cb3dSCy Schubert struct info_timer_stats * ts; 12492b15cb3dSCy Schubert u_long sincereset; 1250c0b746e5SOllivier Robert 12512b15cb3dSCy Schubert ts = (struct info_timer_stats *)prepare_pkt(srcadr, inter, 12522b15cb3dSCy Schubert inpkt, sizeof(*ts)); 1253c0b746e5SOllivier Robert 12542b15cb3dSCy Schubert sincereset = current_time - timer_timereset; 12552b15cb3dSCy Schubert ts->timereset = htonl((u_int32)sincereset); 12562b15cb3dSCy Schubert ts->alarms = ts->timereset; 12572b15cb3dSCy Schubert ts->overflows = htonl((u_int32)alarm_overflow); 1258c0b746e5SOllivier Robert ts->xmtcalls = htonl((u_int32)timer_xmtcalls); 1259c0b746e5SOllivier Robert 1260c0b746e5SOllivier Robert (void) more_pkt(); 1261c0b746e5SOllivier Robert flush_pkt(); 1262c0b746e5SOllivier Robert } 1263c0b746e5SOllivier Robert 1264c0b746e5SOllivier Robert 1265c0b746e5SOllivier Robert /* 1266c0b746e5SOllivier Robert * loop_info - return the current state of the loop filter 1267c0b746e5SOllivier Robert */ 1268c0b746e5SOllivier Robert static void 1269c0b746e5SOllivier Robert loop_info( 12702b15cb3dSCy Schubert sockaddr_u *srcadr, 12712b15cb3dSCy Schubert endpt *inter, 1272c0b746e5SOllivier Robert struct req_pkt *inpkt 1273c0b746e5SOllivier Robert ) 1274c0b746e5SOllivier Robert { 12752b15cb3dSCy Schubert struct info_loop *li; 1276c0b746e5SOllivier Robert l_fp ltmp; 1277c0b746e5SOllivier Robert 1278c0b746e5SOllivier Robert li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt, 1279c0b746e5SOllivier Robert sizeof(struct info_loop)); 1280c0b746e5SOllivier Robert 1281c0b746e5SOllivier Robert DTOLFP(last_offset, <mp); 1282c0b746e5SOllivier Robert HTONL_FP(<mp, &li->last_offset); 1283c0b746e5SOllivier Robert DTOLFP(drift_comp * 1e6, <mp); 1284c0b746e5SOllivier Robert HTONL_FP(<mp, &li->drift_comp); 1285c0b746e5SOllivier Robert li->compliance = htonl((u_int32)(tc_counter)); 12862b15cb3dSCy Schubert li->watchdog_timer = htonl((u_int32)(current_time - sys_epoch)); 1287c0b746e5SOllivier Robert 12882b15cb3dSCy Schubert more_pkt(); 1289c0b746e5SOllivier Robert flush_pkt(); 1290c0b746e5SOllivier Robert } 1291c0b746e5SOllivier Robert 1292c0b746e5SOllivier Robert 1293c0b746e5SOllivier Robert /* 1294c0b746e5SOllivier Robert * do_conf - add a peer to the configuration list 1295c0b746e5SOllivier Robert */ 1296c0b746e5SOllivier Robert static void 1297c0b746e5SOllivier Robert do_conf( 12982b15cb3dSCy Schubert sockaddr_u *srcadr, 12992b15cb3dSCy Schubert endpt *inter, 1300c0b746e5SOllivier Robert struct req_pkt *inpkt 1301c0b746e5SOllivier Robert ) 1302c0b746e5SOllivier Robert { 13032b15cb3dSCy Schubert u_short items; 13042b15cb3dSCy Schubert size_t item_sz; 1305224ba2bdSOllivier Robert u_int fl; 13062b15cb3dSCy Schubert char * datap; 13079c2daa00SOllivier Robert struct conf_peer temp_cp; 13082b15cb3dSCy Schubert sockaddr_u peeraddr; 1309c0b746e5SOllivier Robert 1310c0b746e5SOllivier Robert /* 1311c0b746e5SOllivier Robert * Do a check of everything to see that it looks 1312c0b746e5SOllivier Robert * okay. If not, complain about it. Note we are 1313c0b746e5SOllivier Robert * very picky here. 1314c0b746e5SOllivier Robert */ 1315c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 13162b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 13172b15cb3dSCy Schubert datap = inpkt->u.data; 13182b15cb3dSCy Schubert if (item_sz > sizeof(temp_cp)) { 1319c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1320c0b746e5SOllivier Robert return; 1321c0b746e5SOllivier Robert } 1322c0b746e5SOllivier Robert 13239c2daa00SOllivier Robert while (items-- > 0) { 13242b15cb3dSCy Schubert ZERO(temp_cp); 13252b15cb3dSCy Schubert memcpy(&temp_cp, datap, item_sz); 13262b15cb3dSCy Schubert ZERO_SOCK(&peeraddr); 13279c2daa00SOllivier Robert 13289c2daa00SOllivier Robert fl = 0; 13299c2daa00SOllivier Robert if (temp_cp.flags & CONF_FLAG_PREFER) 13309c2daa00SOllivier Robert fl |= FLAG_PREFER; 13319c2daa00SOllivier Robert if (temp_cp.flags & CONF_FLAG_BURST) 13329c2daa00SOllivier Robert fl |= FLAG_BURST; 1333ea906c41SOllivier Robert if (temp_cp.flags & CONF_FLAG_IBURST) 1334ea906c41SOllivier Robert fl |= FLAG_IBURST; 13352b15cb3dSCy Schubert #ifdef AUTOKEY 13369c2daa00SOllivier Robert if (temp_cp.flags & CONF_FLAG_SKEY) 13379c2daa00SOllivier Robert fl |= FLAG_SKEY; 13382b15cb3dSCy Schubert #endif /* AUTOKEY */ 13392b15cb3dSCy Schubert if (client_v6_capable && temp_cp.v6_flag) { 13402b15cb3dSCy Schubert AF(&peeraddr) = AF_INET6; 13412b15cb3dSCy Schubert SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6; 13429c2daa00SOllivier Robert } else { 13432b15cb3dSCy Schubert AF(&peeraddr) = AF_INET; 13442b15cb3dSCy Schubert NSRCADR(&peeraddr) = temp_cp.peeraddr; 1345c0b746e5SOllivier Robert /* 1346c0b746e5SOllivier Robert * Make sure the address is valid 1347c0b746e5SOllivier Robert */ 13482b15cb3dSCy Schubert if (!ISREFCLOCKADR(&peeraddr) && 13492b15cb3dSCy Schubert ISBADADR(&peeraddr)) { 1350c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1351c0b746e5SOllivier Robert return; 1352c0b746e5SOllivier Robert } 1353c0b746e5SOllivier Robert 13549c2daa00SOllivier Robert } 13559c2daa00SOllivier Robert NSRCPORT(&peeraddr) = htons(NTP_PORT); 13562b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 13572b15cb3dSCy Schubert peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 13589c2daa00SOllivier Robert #endif 13599c2daa00SOllivier Robert 1360c0b746e5SOllivier Robert /* XXX W2DO? minpoll/maxpoll arguments ??? */ 13612b15cb3dSCy Schubert if (peer_config(&peeraddr, NULL, NULL, 13629c2daa00SOllivier Robert temp_cp.hmode, temp_cp.version, temp_cp.minpoll, 13639c2daa00SOllivier Robert temp_cp.maxpoll, fl, temp_cp.ttl, temp_cp.keyid, 13649c2daa00SOllivier Robert NULL) == 0) { 1365c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1366c0b746e5SOllivier Robert return; 1367c0b746e5SOllivier Robert } 1368eb6d21b4SOllivier Robert 13692b15cb3dSCy Schubert datap += item_sz; 1370eb6d21b4SOllivier Robert } 1371c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1372c0b746e5SOllivier Robert } 1373c0b746e5SOllivier Robert 1374224ba2bdSOllivier Robert 1375224ba2bdSOllivier Robert /* 1376c0b746e5SOllivier Robert * do_unconf - remove a peer from the configuration list 1377c0b746e5SOllivier Robert */ 1378c0b746e5SOllivier Robert static void 1379c0b746e5SOllivier Robert do_unconf( 13802b15cb3dSCy Schubert sockaddr_u * srcadr, 13812b15cb3dSCy Schubert endpt * inter, 1382c0b746e5SOllivier Robert struct req_pkt *inpkt 1383c0b746e5SOllivier Robert ) 1384c0b746e5SOllivier Robert { 13852b15cb3dSCy Schubert u_short items; 13862b15cb3dSCy Schubert size_t item_sz; 13872b15cb3dSCy Schubert char * datap; 13889c2daa00SOllivier Robert struct conf_unpeer temp_cp; 13892b15cb3dSCy Schubert struct peer * p; 13902b15cb3dSCy Schubert sockaddr_u peeraddr; 13912b15cb3dSCy Schubert int bad; 13922b15cb3dSCy Schubert int found; 1393c0b746e5SOllivier Robert 1394c0b746e5SOllivier Robert /* 1395c0b746e5SOllivier Robert * This is a bit unstructured, but I like to be careful. 1396c0b746e5SOllivier Robert * We check to see that every peer exists and is actually 1397c0b746e5SOllivier Robert * configured. If so, we remove them. If not, we return 1398c0b746e5SOllivier Robert * an error. 1399c0b746e5SOllivier Robert */ 1400c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 14012b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 14022b15cb3dSCy Schubert datap = inpkt->u.data; 14032b15cb3dSCy Schubert if (item_sz > sizeof(temp_cp)) { 14042b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 14052b15cb3dSCy Schubert return; 14069c2daa00SOllivier Robert } 14072b15cb3dSCy Schubert 14082b15cb3dSCy Schubert bad = FALSE; 14092b15cb3dSCy Schubert while (items-- > 0 && !bad) { 14102b15cb3dSCy Schubert ZERO(temp_cp); 14112b15cb3dSCy Schubert memcpy(&temp_cp, datap, item_sz); 14122b15cb3dSCy Schubert ZERO_SOCK(&peeraddr); 14132b15cb3dSCy Schubert if (client_v6_capable && temp_cp.v6_flag) { 14142b15cb3dSCy Schubert AF(&peeraddr) = AF_INET6; 14152b15cb3dSCy Schubert SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6; 14162b15cb3dSCy Schubert } else { 14172b15cb3dSCy Schubert AF(&peeraddr) = AF_INET; 14182b15cb3dSCy Schubert NSRCADR(&peeraddr) = temp_cp.peeraddr; 14192b15cb3dSCy Schubert } 14202b15cb3dSCy Schubert SET_PORT(&peeraddr, NTP_PORT); 14212b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 14222b15cb3dSCy Schubert peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 14239c2daa00SOllivier Robert #endif 14242b15cb3dSCy Schubert found = FALSE; 14252b15cb3dSCy Schubert p = NULL; 14262b15cb3dSCy Schubert 14272b15cb3dSCy Schubert DPRINTF(1, ("searching for %s\n", stoa(&peeraddr))); 14282b15cb3dSCy Schubert 1429c0b746e5SOllivier Robert while (!found) { 14302b15cb3dSCy Schubert p = findexistingpeer(&peeraddr, NULL, p, -1, 0); 14312b15cb3dSCy Schubert if (NULL == p) 1432c0b746e5SOllivier Robert break; 14332b15cb3dSCy Schubert if (FLAG_CONFIG & p->flags) 14342b15cb3dSCy Schubert found = TRUE; 1435c0b746e5SOllivier Robert } 1436c0b746e5SOllivier Robert if (!found) 14372b15cb3dSCy Schubert bad = TRUE; 14382b15cb3dSCy Schubert 14392b15cb3dSCy Schubert datap += item_sz; 1440c0b746e5SOllivier Robert } 1441c0b746e5SOllivier Robert 1442c0b746e5SOllivier Robert if (bad) { 1443c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1444c0b746e5SOllivier Robert return; 1445c0b746e5SOllivier Robert } 1446c0b746e5SOllivier Robert 1447c0b746e5SOllivier Robert /* 1448c0b746e5SOllivier Robert * Now do it in earnest. 1449c0b746e5SOllivier Robert */ 1450c0b746e5SOllivier Robert 1451c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 14522b15cb3dSCy Schubert datap = inpkt->u.data; 14532b15cb3dSCy Schubert 1454c0b746e5SOllivier Robert while (items-- > 0) { 14552b15cb3dSCy Schubert ZERO(temp_cp); 14562b15cb3dSCy Schubert memcpy(&temp_cp, datap, item_sz); 14572b15cb3dSCy Schubert ZERO(peeraddr); 14582b15cb3dSCy Schubert if (client_v6_capable && temp_cp.v6_flag) { 14592b15cb3dSCy Schubert AF(&peeraddr) = AF_INET6; 14602b15cb3dSCy Schubert SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6; 14619c2daa00SOllivier Robert } else { 14622b15cb3dSCy Schubert AF(&peeraddr) = AF_INET; 14632b15cb3dSCy Schubert NSRCADR(&peeraddr) = temp_cp.peeraddr; 14649c2daa00SOllivier Robert } 14652b15cb3dSCy Schubert SET_PORT(&peeraddr, NTP_PORT); 14662b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 14672b15cb3dSCy Schubert peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 14689c2daa00SOllivier Robert #endif 14692b15cb3dSCy Schubert found = FALSE; 14702b15cb3dSCy Schubert p = NULL; 14712b15cb3dSCy Schubert 14722b15cb3dSCy Schubert while (!found) { 14732b15cb3dSCy Schubert p = findexistingpeer(&peeraddr, NULL, p, -1, 0); 14742b15cb3dSCy Schubert if (NULL == p) 14752b15cb3dSCy Schubert break; 14762b15cb3dSCy Schubert if (FLAG_CONFIG & p->flags) 14772b15cb3dSCy Schubert found = TRUE; 14782b15cb3dSCy Schubert } 14792b15cb3dSCy Schubert INSIST(found); 14802b15cb3dSCy Schubert INSIST(NULL != p); 14812b15cb3dSCy Schubert 14822b15cb3dSCy Schubert peer_clear(p, "GONE"); 14832b15cb3dSCy Schubert unpeer(p); 14842b15cb3dSCy Schubert 14852b15cb3dSCy Schubert datap += item_sz; 1486c0b746e5SOllivier Robert } 1487c0b746e5SOllivier Robert 1488c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1489c0b746e5SOllivier Robert } 1490c0b746e5SOllivier Robert 1491c0b746e5SOllivier Robert 1492c0b746e5SOllivier Robert /* 1493c0b746e5SOllivier Robert * set_sys_flag - set system flags 1494c0b746e5SOllivier Robert */ 1495c0b746e5SOllivier Robert static void 1496c0b746e5SOllivier Robert set_sys_flag( 14972b15cb3dSCy Schubert sockaddr_u *srcadr, 14982b15cb3dSCy Schubert endpt *inter, 1499c0b746e5SOllivier Robert struct req_pkt *inpkt 1500c0b746e5SOllivier Robert ) 1501c0b746e5SOllivier Robert { 1502c0b746e5SOllivier Robert setclr_flags(srcadr, inter, inpkt, 1); 1503c0b746e5SOllivier Robert } 1504c0b746e5SOllivier Robert 1505c0b746e5SOllivier Robert 1506c0b746e5SOllivier Robert /* 1507c0b746e5SOllivier Robert * clr_sys_flag - clear system flags 1508c0b746e5SOllivier Robert */ 1509c0b746e5SOllivier Robert static void 1510c0b746e5SOllivier Robert clr_sys_flag( 15112b15cb3dSCy Schubert sockaddr_u *srcadr, 15122b15cb3dSCy Schubert endpt *inter, 1513c0b746e5SOllivier Robert struct req_pkt *inpkt 1514c0b746e5SOllivier Robert ) 1515c0b746e5SOllivier Robert { 1516c0b746e5SOllivier Robert setclr_flags(srcadr, inter, inpkt, 0); 1517c0b746e5SOllivier Robert } 1518c0b746e5SOllivier Robert 1519c0b746e5SOllivier Robert 1520c0b746e5SOllivier Robert /* 1521c0b746e5SOllivier Robert * setclr_flags - do the grunge work of flag setting/clearing 1522c0b746e5SOllivier Robert */ 1523c0b746e5SOllivier Robert static void 1524c0b746e5SOllivier Robert setclr_flags( 15252b15cb3dSCy Schubert sockaddr_u *srcadr, 15262b15cb3dSCy Schubert endpt *inter, 1527c0b746e5SOllivier Robert struct req_pkt *inpkt, 1528c0b746e5SOllivier Robert u_long set 1529c0b746e5SOllivier Robert ) 1530c0b746e5SOllivier Robert { 15312b15cb3dSCy Schubert struct conf_sys_flags *sf; 15322b15cb3dSCy Schubert u_int32 flags; 1533c0b746e5SOllivier Robert 1534c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 1535224ba2bdSOllivier Robert msyslog(LOG_ERR, "setclr_flags: err_nitems > 1"); 1536c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1537c0b746e5SOllivier Robert return; 1538c0b746e5SOllivier Robert } 1539c0b746e5SOllivier Robert 15402b15cb3dSCy Schubert sf = (struct conf_sys_flags *)&inpkt->u; 15412b15cb3dSCy Schubert flags = ntohl(sf->flags); 1542c0b746e5SOllivier Robert 1543224ba2bdSOllivier Robert if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS | 1544c0b746e5SOllivier Robert SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR | 1545ce265a54SOllivier Robert SYS_FLAG_FILEGEN | SYS_FLAG_AUTH | SYS_FLAG_CAL)) { 1546224ba2bdSOllivier Robert msyslog(LOG_ERR, "setclr_flags: extra flags: %#x", 1547224ba2bdSOllivier Robert flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS | 1548224ba2bdSOllivier Robert SYS_FLAG_NTP | SYS_FLAG_KERNEL | 1549ce265a54SOllivier Robert SYS_FLAG_MONITOR | SYS_FLAG_FILEGEN | 1550ce265a54SOllivier Robert SYS_FLAG_AUTH | SYS_FLAG_CAL)); 1551c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1552c0b746e5SOllivier Robert return; 1553c0b746e5SOllivier Robert } 1554c0b746e5SOllivier Robert 1555c0b746e5SOllivier Robert if (flags & SYS_FLAG_BCLIENT) 15569c2daa00SOllivier Robert proto_config(PROTO_BROADCLIENT, set, 0., NULL); 1557224ba2bdSOllivier Robert if (flags & SYS_FLAG_PPS) 15589c2daa00SOllivier Robert proto_config(PROTO_PPS, set, 0., NULL); 1559c0b746e5SOllivier Robert if (flags & SYS_FLAG_NTP) 15609c2daa00SOllivier Robert proto_config(PROTO_NTP, set, 0., NULL); 1561c0b746e5SOllivier Robert if (flags & SYS_FLAG_KERNEL) 15629c2daa00SOllivier Robert proto_config(PROTO_KERNEL, set, 0., NULL); 1563c0b746e5SOllivier Robert if (flags & SYS_FLAG_MONITOR) 15649c2daa00SOllivier Robert proto_config(PROTO_MONITOR, set, 0., NULL); 1565c0b746e5SOllivier Robert if (flags & SYS_FLAG_FILEGEN) 15669c2daa00SOllivier Robert proto_config(PROTO_FILEGEN, set, 0., NULL); 1567ce265a54SOllivier Robert if (flags & SYS_FLAG_AUTH) 15689c2daa00SOllivier Robert proto_config(PROTO_AUTHENTICATE, set, 0., NULL); 1569ce265a54SOllivier Robert if (flags & SYS_FLAG_CAL) 15709c2daa00SOllivier Robert proto_config(PROTO_CAL, set, 0., NULL); 1571c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 15722b15cb3dSCy Schubert } 1573ea906c41SOllivier Robert 15742b15cb3dSCy Schubert /* 15752b15cb3dSCy Schubert * list_restrict4 - recursive helper for list_restrict dumps IPv4 15762b15cb3dSCy Schubert * restriction list in reverse order. 15772b15cb3dSCy Schubert */ 15782b15cb3dSCy Schubert static void 15792b15cb3dSCy Schubert list_restrict4( 15802b15cb3dSCy Schubert restrict_u * res, 15812b15cb3dSCy Schubert struct info_restrict ** ppir 15822b15cb3dSCy Schubert ) 15832b15cb3dSCy Schubert { 15842b15cb3dSCy Schubert struct info_restrict * pir; 15852b15cb3dSCy Schubert 15862b15cb3dSCy Schubert if (res->link != NULL) 15872b15cb3dSCy Schubert list_restrict4(res->link, ppir); 15882b15cb3dSCy Schubert 15892b15cb3dSCy Schubert pir = *ppir; 15902b15cb3dSCy Schubert pir->addr = htonl(res->u.v4.addr); 15912b15cb3dSCy Schubert if (client_v6_capable) 15922b15cb3dSCy Schubert pir->v6_flag = 0; 15932b15cb3dSCy Schubert pir->mask = htonl(res->u.v4.mask); 15942b15cb3dSCy Schubert pir->count = htonl(res->count); 15952b15cb3dSCy Schubert pir->flags = htons(res->flags); 15962b15cb3dSCy Schubert pir->mflags = htons(res->mflags); 15972b15cb3dSCy Schubert *ppir = (struct info_restrict *)more_pkt(); 15982b15cb3dSCy Schubert } 15992b15cb3dSCy Schubert 16002b15cb3dSCy Schubert 16012b15cb3dSCy Schubert /* 16022b15cb3dSCy Schubert * list_restrict6 - recursive helper for list_restrict dumps IPv6 16032b15cb3dSCy Schubert * restriction list in reverse order. 16042b15cb3dSCy Schubert */ 16052b15cb3dSCy Schubert static void 16062b15cb3dSCy Schubert list_restrict6( 16072b15cb3dSCy Schubert restrict_u * res, 16082b15cb3dSCy Schubert struct info_restrict ** ppir 16092b15cb3dSCy Schubert ) 16102b15cb3dSCy Schubert { 16112b15cb3dSCy Schubert struct info_restrict * pir; 16122b15cb3dSCy Schubert 16132b15cb3dSCy Schubert if (res->link != NULL) 16142b15cb3dSCy Schubert list_restrict6(res->link, ppir); 16152b15cb3dSCy Schubert 16162b15cb3dSCy Schubert pir = *ppir; 16172b15cb3dSCy Schubert pir->addr6 = res->u.v6.addr; 16182b15cb3dSCy Schubert pir->mask6 = res->u.v6.mask; 16192b15cb3dSCy Schubert pir->v6_flag = 1; 16202b15cb3dSCy Schubert pir->count = htonl(res->count); 16212b15cb3dSCy Schubert pir->flags = htons(res->flags); 16222b15cb3dSCy Schubert pir->mflags = htons(res->mflags); 16232b15cb3dSCy Schubert *ppir = (struct info_restrict *)more_pkt(); 1624c0b746e5SOllivier Robert } 1625c0b746e5SOllivier Robert 1626c0b746e5SOllivier Robert 1627c0b746e5SOllivier Robert /* 1628c0b746e5SOllivier Robert * list_restrict - return the restrict list 1629c0b746e5SOllivier Robert */ 1630c0b746e5SOllivier Robert static void 1631c0b746e5SOllivier Robert list_restrict( 16322b15cb3dSCy Schubert sockaddr_u *srcadr, 16332b15cb3dSCy Schubert endpt *inter, 1634c0b746e5SOllivier Robert struct req_pkt *inpkt 1635c0b746e5SOllivier Robert ) 1636c0b746e5SOllivier Robert { 16372b15cb3dSCy Schubert struct info_restrict *ir; 1638c0b746e5SOllivier Robert 16392b15cb3dSCy Schubert DPRINTF(3, ("wants restrict list summary\n")); 1640c0b746e5SOllivier Robert 1641c0b746e5SOllivier Robert ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt, 16429c2daa00SOllivier Robert v6sizeof(struct info_restrict)); 16439c2daa00SOllivier Robert 16442b15cb3dSCy Schubert /* 16452b15cb3dSCy Schubert * The restriction lists are kept sorted in the reverse order 16462b15cb3dSCy Schubert * than they were originally. To preserve the output semantics, 16472b15cb3dSCy Schubert * dump each list in reverse order. A recursive helper function 16482b15cb3dSCy Schubert * achieves that. 16492b15cb3dSCy Schubert */ 16502b15cb3dSCy Schubert list_restrict4(restrictlist4, &ir); 16519c2daa00SOllivier Robert if (client_v6_capable) 16522b15cb3dSCy Schubert list_restrict6(restrictlist6, &ir); 1653c0b746e5SOllivier Robert flush_pkt(); 1654c0b746e5SOllivier Robert } 1655c0b746e5SOllivier Robert 1656c0b746e5SOllivier Robert 1657c0b746e5SOllivier Robert /* 1658c0b746e5SOllivier Robert * do_resaddflags - add flags to a restrict entry (or create one) 1659c0b746e5SOllivier Robert */ 1660c0b746e5SOllivier Robert static void 1661c0b746e5SOllivier Robert do_resaddflags( 16622b15cb3dSCy Schubert sockaddr_u *srcadr, 16632b15cb3dSCy Schubert endpt *inter, 1664c0b746e5SOllivier Robert struct req_pkt *inpkt 1665c0b746e5SOllivier Robert ) 1666c0b746e5SOllivier Robert { 1667c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_FLAGS); 1668c0b746e5SOllivier Robert } 1669c0b746e5SOllivier Robert 1670c0b746e5SOllivier Robert 1671c0b746e5SOllivier Robert 1672c0b746e5SOllivier Robert /* 1673c0b746e5SOllivier Robert * do_ressubflags - remove flags from a restrict entry 1674c0b746e5SOllivier Robert */ 1675c0b746e5SOllivier Robert static void 1676c0b746e5SOllivier Robert do_ressubflags( 16772b15cb3dSCy Schubert sockaddr_u *srcadr, 16782b15cb3dSCy Schubert endpt *inter, 1679c0b746e5SOllivier Robert struct req_pkt *inpkt 1680c0b746e5SOllivier Robert ) 1681c0b746e5SOllivier Robert { 1682c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_UNFLAG); 1683c0b746e5SOllivier Robert } 1684c0b746e5SOllivier Robert 1685c0b746e5SOllivier Robert 1686c0b746e5SOllivier Robert /* 1687c0b746e5SOllivier Robert * do_unrestrict - remove a restrict entry from the list 1688c0b746e5SOllivier Robert */ 1689c0b746e5SOllivier Robert static void 1690c0b746e5SOllivier Robert do_unrestrict( 16912b15cb3dSCy Schubert sockaddr_u *srcadr, 16922b15cb3dSCy Schubert endpt *inter, 1693c0b746e5SOllivier Robert struct req_pkt *inpkt 1694c0b746e5SOllivier Robert ) 1695c0b746e5SOllivier Robert { 1696c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_REMOVE); 1697c0b746e5SOllivier Robert } 1698c0b746e5SOllivier Robert 1699c0b746e5SOllivier Robert 1700c0b746e5SOllivier Robert /* 1701c0b746e5SOllivier Robert * do_restrict - do the dirty stuff of dealing with restrictions 1702c0b746e5SOllivier Robert */ 1703c0b746e5SOllivier Robert static void 1704c0b746e5SOllivier Robert do_restrict( 17052b15cb3dSCy Schubert sockaddr_u *srcadr, 17062b15cb3dSCy Schubert endpt *inter, 1707c0b746e5SOllivier Robert struct req_pkt *inpkt, 1708c0b746e5SOllivier Robert int op 1709c0b746e5SOllivier Robert ) 1710c0b746e5SOllivier Robert { 17112b15cb3dSCy Schubert char * datap; 17122b15cb3dSCy Schubert struct conf_restrict cr; 17132b15cb3dSCy Schubert u_short items; 17142b15cb3dSCy Schubert size_t item_sz; 17152b15cb3dSCy Schubert sockaddr_u matchaddr; 17162b15cb3dSCy Schubert sockaddr_u matchmask; 1717c0b746e5SOllivier Robert int bad; 1718c0b746e5SOllivier Robert 1719c0b746e5SOllivier Robert /* 1720c0b746e5SOllivier Robert * Do a check of the flags to make sure that only 1721c0b746e5SOllivier Robert * the NTPPORT flag is set, if any. If not, complain 1722c0b746e5SOllivier Robert * about it. Note we are very picky here. 1723c0b746e5SOllivier Robert */ 1724c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 17252b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 17262b15cb3dSCy Schubert datap = inpkt->u.data; 17272b15cb3dSCy Schubert if (item_sz > sizeof(cr)) { 17282b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 17292b15cb3dSCy Schubert return; 17302b15cb3dSCy Schubert } 1731c0b746e5SOllivier Robert 17322b15cb3dSCy Schubert bad = FALSE; 1733c0b746e5SOllivier Robert while (items-- > 0 && !bad) { 17342b15cb3dSCy Schubert memcpy(&cr, datap, item_sz); 17352b15cb3dSCy Schubert cr.flags = ntohs(cr.flags); 17362b15cb3dSCy Schubert cr.mflags = ntohs(cr.mflags); 17372b15cb3dSCy Schubert if (~RESM_NTPONLY & cr.mflags) 1738224ba2bdSOllivier Robert bad |= 1; 17392b15cb3dSCy Schubert if (~RES_ALLFLAGS & cr.flags) 1740224ba2bdSOllivier Robert bad |= 2; 17412b15cb3dSCy Schubert if (INADDR_ANY != cr.mask) { 17422b15cb3dSCy Schubert if (client_v6_capable && cr.v6_flag) { 17432b15cb3dSCy Schubert if (IN6_IS_ADDR_UNSPECIFIED(&cr.addr6)) 1744224ba2bdSOllivier Robert bad |= 4; 17452b15cb3dSCy Schubert } else { 17462b15cb3dSCy Schubert if (INADDR_ANY == cr.addr) 17479c2daa00SOllivier Robert bad |= 8; 17489c2daa00SOllivier Robert } 17492b15cb3dSCy Schubert } 17502b15cb3dSCy Schubert datap += item_sz; 1751c0b746e5SOllivier Robert } 1752c0b746e5SOllivier Robert 1753c0b746e5SOllivier Robert if (bad) { 1754224ba2bdSOllivier Robert msyslog(LOG_ERR, "do_restrict: bad = %#x", bad); 1755c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1756c0b746e5SOllivier Robert return; 1757c0b746e5SOllivier Robert } 1758c0b746e5SOllivier Robert 1759c0b746e5SOllivier Robert /* 1760*9034852cSGleb Smirnoff * Looks okay, try it out. Needs to reload data pointer and 1761*9034852cSGleb Smirnoff * item counter. (Talos-CAN-0052) 1762c0b746e5SOllivier Robert */ 17632b15cb3dSCy Schubert ZERO_SOCK(&matchaddr); 17642b15cb3dSCy Schubert ZERO_SOCK(&matchmask); 1765*9034852cSGleb Smirnoff items = INFO_NITEMS(inpkt->err_nitems); 17662b15cb3dSCy Schubert datap = inpkt->u.data; 1767c0b746e5SOllivier Robert 1768c0b746e5SOllivier Robert while (items-- > 0) { 17692b15cb3dSCy Schubert memcpy(&cr, datap, item_sz); 17702b15cb3dSCy Schubert cr.flags = ntohs(cr.flags); 17712b15cb3dSCy Schubert cr.mflags = ntohs(cr.mflags); 17722b15cb3dSCy Schubert if (client_v6_capable && cr.v6_flag) { 17732b15cb3dSCy Schubert AF(&matchaddr) = AF_INET6; 17742b15cb3dSCy Schubert AF(&matchmask) = AF_INET6; 17752b15cb3dSCy Schubert SOCK_ADDR6(&matchaddr) = cr.addr6; 17762b15cb3dSCy Schubert SOCK_ADDR6(&matchmask) = cr.mask6; 17779c2daa00SOllivier Robert } else { 17782b15cb3dSCy Schubert AF(&matchaddr) = AF_INET; 17792b15cb3dSCy Schubert AF(&matchmask) = AF_INET; 17802b15cb3dSCy Schubert NSRCADR(&matchaddr) = cr.addr; 17812b15cb3dSCy Schubert NSRCADR(&matchmask) = cr.mask; 17829c2daa00SOllivier Robert } 17832b15cb3dSCy Schubert hack_restrict(op, &matchaddr, &matchmask, cr.mflags, 17842b15cb3dSCy Schubert cr.flags, 0); 17852b15cb3dSCy Schubert datap += item_sz; 1786c0b746e5SOllivier Robert } 1787c0b746e5SOllivier Robert 1788c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1789c0b746e5SOllivier Robert } 1790c0b746e5SOllivier Robert 1791c0b746e5SOllivier Robert 1792c0b746e5SOllivier Robert /* 1793c0b746e5SOllivier Robert * mon_getlist - return monitor data 1794c0b746e5SOllivier Robert */ 1795c0b746e5SOllivier Robert static void 17962b15cb3dSCy Schubert mon_getlist( 17972b15cb3dSCy Schubert sockaddr_u *srcadr, 17982b15cb3dSCy Schubert endpt *inter, 1799c0b746e5SOllivier Robert struct req_pkt *inpkt 1800c0b746e5SOllivier Robert ) 1801c0b746e5SOllivier Robert { 18022b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1803c0b746e5SOllivier Robert } 1804c0b746e5SOllivier Robert 1805c0b746e5SOllivier Robert 1806c0b746e5SOllivier Robert /* 1807c0b746e5SOllivier Robert * Module entry points and the flags they correspond with 1808c0b746e5SOllivier Robert */ 1809c0b746e5SOllivier Robert struct reset_entry { 1810c0b746e5SOllivier Robert int flag; /* flag this corresponds to */ 18112b15cb3dSCy Schubert void (*handler)(void); /* routine to handle request */ 1812c0b746e5SOllivier Robert }; 1813c0b746e5SOllivier Robert 1814c0b746e5SOllivier Robert struct reset_entry reset_entries[] = { 1815c0b746e5SOllivier Robert { RESET_FLAG_ALLPEERS, peer_all_reset }, 1816c0b746e5SOllivier Robert { RESET_FLAG_IO, io_clr_stats }, 1817c0b746e5SOllivier Robert { RESET_FLAG_SYS, proto_clr_stats }, 1818c0b746e5SOllivier Robert { RESET_FLAG_MEM, peer_clr_stats }, 1819c0b746e5SOllivier Robert { RESET_FLAG_TIMER, timer_clr_stats }, 1820c0b746e5SOllivier Robert { RESET_FLAG_AUTH, reset_auth_stats }, 1821c0b746e5SOllivier Robert { RESET_FLAG_CTL, ctl_clr_stats }, 1822c0b746e5SOllivier Robert { 0, 0 } 1823c0b746e5SOllivier Robert }; 1824c0b746e5SOllivier Robert 1825c0b746e5SOllivier Robert /* 1826c0b746e5SOllivier Robert * reset_stats - reset statistic counters here and there 1827c0b746e5SOllivier Robert */ 1828c0b746e5SOllivier Robert static void 1829c0b746e5SOllivier Robert reset_stats( 18302b15cb3dSCy Schubert sockaddr_u *srcadr, 18312b15cb3dSCy Schubert endpt *inter, 1832c0b746e5SOllivier Robert struct req_pkt *inpkt 1833c0b746e5SOllivier Robert ) 1834c0b746e5SOllivier Robert { 18352b15cb3dSCy Schubert struct reset_flags *rflags; 1836c0b746e5SOllivier Robert u_long flags; 1837c0b746e5SOllivier Robert struct reset_entry *rent; 1838c0b746e5SOllivier Robert 1839c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 1840224ba2bdSOllivier Robert msyslog(LOG_ERR, "reset_stats: err_nitems > 1"); 1841c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1842c0b746e5SOllivier Robert return; 1843c0b746e5SOllivier Robert } 1844c0b746e5SOllivier Robert 18452b15cb3dSCy Schubert rflags = (struct reset_flags *)&inpkt->u; 18462b15cb3dSCy Schubert flags = ntohl(rflags->flags); 1847c0b746e5SOllivier Robert 1848c0b746e5SOllivier Robert if (flags & ~RESET_ALLFLAGS) { 1849224ba2bdSOllivier Robert msyslog(LOG_ERR, "reset_stats: reset leaves %#lx", 1850224ba2bdSOllivier Robert flags & ~RESET_ALLFLAGS); 1851c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1852c0b746e5SOllivier Robert return; 1853c0b746e5SOllivier Robert } 1854c0b746e5SOllivier Robert 1855c0b746e5SOllivier Robert for (rent = reset_entries; rent->flag != 0; rent++) { 1856c0b746e5SOllivier Robert if (flags & rent->flag) 18572b15cb3dSCy Schubert (*rent->handler)(); 1858c0b746e5SOllivier Robert } 1859c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1860c0b746e5SOllivier Robert } 1861c0b746e5SOllivier Robert 1862c0b746e5SOllivier Robert 1863c0b746e5SOllivier Robert /* 1864c0b746e5SOllivier Robert * reset_peer - clear a peer's statistics 1865c0b746e5SOllivier Robert */ 1866c0b746e5SOllivier Robert static void 1867c0b746e5SOllivier Robert reset_peer( 18682b15cb3dSCy Schubert sockaddr_u *srcadr, 18692b15cb3dSCy Schubert endpt *inter, 1870c0b746e5SOllivier Robert struct req_pkt *inpkt 1871c0b746e5SOllivier Robert ) 1872c0b746e5SOllivier Robert { 18732b15cb3dSCy Schubert u_short items; 18742b15cb3dSCy Schubert size_t item_sz; 18752b15cb3dSCy Schubert char * datap; 18762b15cb3dSCy Schubert struct conf_unpeer cp; 18772b15cb3dSCy Schubert struct peer * p; 18782b15cb3dSCy Schubert sockaddr_u peeraddr; 1879c0b746e5SOllivier Robert int bad; 1880c0b746e5SOllivier Robert 1881c0b746e5SOllivier Robert /* 1882c0b746e5SOllivier Robert * We check first to see that every peer exists. If not, 1883c0b746e5SOllivier Robert * we return an error. 1884c0b746e5SOllivier Robert */ 1885c0b746e5SOllivier Robert 1886c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 18872b15cb3dSCy Schubert item_sz = INFO_ITEMSIZE(inpkt->mbz_itemsize); 18882b15cb3dSCy Schubert datap = inpkt->u.data; 18892b15cb3dSCy Schubert if (item_sz > sizeof(cp)) { 18902b15cb3dSCy Schubert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 18912b15cb3dSCy Schubert return; 18929c2daa00SOllivier Robert } 18932b15cb3dSCy Schubert 18942b15cb3dSCy Schubert bad = FALSE; 18952b15cb3dSCy Schubert while (items-- > 0 && !bad) { 18962b15cb3dSCy Schubert ZERO(cp); 18972b15cb3dSCy Schubert memcpy(&cp, datap, item_sz); 18982b15cb3dSCy Schubert ZERO_SOCK(&peeraddr); 18992b15cb3dSCy Schubert if (client_v6_capable && cp.v6_flag) { 19002b15cb3dSCy Schubert AF(&peeraddr) = AF_INET6; 19012b15cb3dSCy Schubert SOCK_ADDR6(&peeraddr) = cp.peeraddr6; 19022b15cb3dSCy Schubert } else { 19032b15cb3dSCy Schubert AF(&peeraddr) = AF_INET; 19042b15cb3dSCy Schubert NSRCADR(&peeraddr) = cp.peeraddr; 19052b15cb3dSCy Schubert } 19062b15cb3dSCy Schubert 19072b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 19082b15cb3dSCy Schubert peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 19099c2daa00SOllivier Robert #endif 19102b15cb3dSCy Schubert p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0); 19112b15cb3dSCy Schubert if (NULL == p) 1912c0b746e5SOllivier Robert bad++; 19132b15cb3dSCy Schubert datap += item_sz; 1914c0b746e5SOllivier Robert } 1915c0b746e5SOllivier Robert 1916c0b746e5SOllivier Robert if (bad) { 1917c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1918c0b746e5SOllivier Robert return; 1919c0b746e5SOllivier Robert } 1920c0b746e5SOllivier Robert 1921c0b746e5SOllivier Robert /* 1922*9034852cSGleb Smirnoff * Now do it in earnest. Needs to reload data pointer and item 1923*9034852cSGleb Smirnoff * counter. (Talos-CAN-0052) 1924c0b746e5SOllivier Robert */ 1925c0b746e5SOllivier Robert 1926*9034852cSGleb Smirnoff items = INFO_NITEMS(inpkt->err_nitems); 19272b15cb3dSCy Schubert datap = inpkt->u.data; 1928c0b746e5SOllivier Robert while (items-- > 0) { 19292b15cb3dSCy Schubert ZERO(cp); 19302b15cb3dSCy Schubert memcpy(&cp, datap, item_sz); 19312b15cb3dSCy Schubert ZERO_SOCK(&peeraddr); 19322b15cb3dSCy Schubert if (client_v6_capable && cp.v6_flag) { 19332b15cb3dSCy Schubert AF(&peeraddr) = AF_INET6; 19342b15cb3dSCy Schubert SOCK_ADDR6(&peeraddr) = cp.peeraddr6; 19359c2daa00SOllivier Robert } else { 19362b15cb3dSCy Schubert AF(&peeraddr) = AF_INET; 19372b15cb3dSCy Schubert NSRCADR(&peeraddr) = cp.peeraddr; 19389c2daa00SOllivier Robert } 19392b15cb3dSCy Schubert SET_PORT(&peeraddr, 123); 19402b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 19412b15cb3dSCy Schubert peeraddr.sa.sa_len = SOCKLEN(&peeraddr); 19429c2daa00SOllivier Robert #endif 19432b15cb3dSCy Schubert p = findexistingpeer(&peeraddr, NULL, NULL, -1, 0); 19442b15cb3dSCy Schubert while (p != NULL) { 19452b15cb3dSCy Schubert peer_reset(p); 19462b15cb3dSCy Schubert p = findexistingpeer(&peeraddr, NULL, p, -1, 0); 1947c0b746e5SOllivier Robert } 19482b15cb3dSCy Schubert datap += item_sz; 1949c0b746e5SOllivier Robert } 1950c0b746e5SOllivier Robert 1951c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1952c0b746e5SOllivier Robert } 1953c0b746e5SOllivier Robert 1954c0b746e5SOllivier Robert 1955c0b746e5SOllivier Robert /* 1956c0b746e5SOllivier Robert * do_key_reread - reread the encryption key file 1957c0b746e5SOllivier Robert */ 1958c0b746e5SOllivier Robert static void 1959c0b746e5SOllivier Robert do_key_reread( 19602b15cb3dSCy Schubert sockaddr_u *srcadr, 19612b15cb3dSCy Schubert endpt *inter, 1962c0b746e5SOllivier Robert struct req_pkt *inpkt 1963c0b746e5SOllivier Robert ) 1964c0b746e5SOllivier Robert { 1965c0b746e5SOllivier Robert rereadkeys(); 1966c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1967c0b746e5SOllivier Robert } 1968c0b746e5SOllivier Robert 1969c0b746e5SOllivier Robert 1970c0b746e5SOllivier Robert /* 1971c0b746e5SOllivier Robert * trust_key - make one or more keys trusted 1972c0b746e5SOllivier Robert */ 1973c0b746e5SOllivier Robert static void 1974c0b746e5SOllivier Robert trust_key( 19752b15cb3dSCy Schubert sockaddr_u *srcadr, 19762b15cb3dSCy Schubert endpt *inter, 1977c0b746e5SOllivier Robert struct req_pkt *inpkt 1978c0b746e5SOllivier Robert ) 1979c0b746e5SOllivier Robert { 1980c0b746e5SOllivier Robert do_trustkey(srcadr, inter, inpkt, 1); 1981c0b746e5SOllivier Robert } 1982c0b746e5SOllivier Robert 1983c0b746e5SOllivier Robert 1984c0b746e5SOllivier Robert /* 1985c0b746e5SOllivier Robert * untrust_key - make one or more keys untrusted 1986c0b746e5SOllivier Robert */ 1987c0b746e5SOllivier Robert static void 1988c0b746e5SOllivier Robert untrust_key( 19892b15cb3dSCy Schubert sockaddr_u *srcadr, 19902b15cb3dSCy Schubert endpt *inter, 1991c0b746e5SOllivier Robert struct req_pkt *inpkt 1992c0b746e5SOllivier Robert ) 1993c0b746e5SOllivier Robert { 1994c0b746e5SOllivier Robert do_trustkey(srcadr, inter, inpkt, 0); 1995c0b746e5SOllivier Robert } 1996c0b746e5SOllivier Robert 1997c0b746e5SOllivier Robert 1998c0b746e5SOllivier Robert /* 1999c0b746e5SOllivier Robert * do_trustkey - make keys either trustable or untrustable 2000c0b746e5SOllivier Robert */ 2001c0b746e5SOllivier Robert static void 2002c0b746e5SOllivier Robert do_trustkey( 20032b15cb3dSCy Schubert sockaddr_u *srcadr, 20042b15cb3dSCy Schubert endpt *inter, 2005c0b746e5SOllivier Robert struct req_pkt *inpkt, 2006224ba2bdSOllivier Robert u_long trust 2007c0b746e5SOllivier Robert ) 2008c0b746e5SOllivier Robert { 2009c0b746e5SOllivier Robert register u_long *kp; 2010c0b746e5SOllivier Robert register int items; 2011c0b746e5SOllivier Robert 2012c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 20132b15cb3dSCy Schubert kp = (u_long *)&inpkt->u; 2014c0b746e5SOllivier Robert while (items-- > 0) { 2015c0b746e5SOllivier Robert authtrust(*kp, trust); 2016c0b746e5SOllivier Robert kp++; 2017c0b746e5SOllivier Robert } 2018c0b746e5SOllivier Robert 2019c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2020c0b746e5SOllivier Robert } 2021c0b746e5SOllivier Robert 2022c0b746e5SOllivier Robert 2023c0b746e5SOllivier Robert /* 2024c0b746e5SOllivier Robert * get_auth_info - return some stats concerning the authentication module 2025c0b746e5SOllivier Robert */ 2026c0b746e5SOllivier Robert static void 2027c0b746e5SOllivier Robert get_auth_info( 20282b15cb3dSCy Schubert sockaddr_u *srcadr, 20292b15cb3dSCy Schubert endpt *inter, 2030c0b746e5SOllivier Robert struct req_pkt *inpkt 2031c0b746e5SOllivier Robert ) 2032c0b746e5SOllivier Robert { 2033c0b746e5SOllivier Robert register struct info_auth *ia; 2034c0b746e5SOllivier Robert 2035c0b746e5SOllivier Robert ia = (struct info_auth *)prepare_pkt(srcadr, inter, inpkt, 2036c0b746e5SOllivier Robert sizeof(struct info_auth)); 2037c0b746e5SOllivier Robert 2038c0b746e5SOllivier Robert ia->numkeys = htonl((u_int32)authnumkeys); 2039c0b746e5SOllivier Robert ia->numfreekeys = htonl((u_int32)authnumfreekeys); 2040c0b746e5SOllivier Robert ia->keylookups = htonl((u_int32)authkeylookups); 2041c0b746e5SOllivier Robert ia->keynotfound = htonl((u_int32)authkeynotfound); 2042c0b746e5SOllivier Robert ia->encryptions = htonl((u_int32)authencryptions); 2043c0b746e5SOllivier Robert ia->decryptions = htonl((u_int32)authdecryptions); 2044c0b746e5SOllivier Robert ia->keyuncached = htonl((u_int32)authkeyuncached); 2045c0b746e5SOllivier Robert ia->expired = htonl((u_int32)authkeyexpired); 2046c0b746e5SOllivier Robert ia->timereset = htonl((u_int32)(current_time - auth_timereset)); 2047c0b746e5SOllivier Robert 2048c0b746e5SOllivier Robert (void) more_pkt(); 2049c0b746e5SOllivier Robert flush_pkt(); 2050c0b746e5SOllivier Robert } 2051c0b746e5SOllivier Robert 2052c0b746e5SOllivier Robert 2053c0b746e5SOllivier Robert 2054c0b746e5SOllivier Robert /* 2055c0b746e5SOllivier Robert * reset_auth_stats - reset the authentication stat counters. Done here 2056c0b746e5SOllivier Robert * to keep ntp-isms out of the authentication module 2057c0b746e5SOllivier Robert */ 20582b15cb3dSCy Schubert void 2059c0b746e5SOllivier Robert reset_auth_stats(void) 2060c0b746e5SOllivier Robert { 2061c0b746e5SOllivier Robert authkeylookups = 0; 2062c0b746e5SOllivier Robert authkeynotfound = 0; 2063c0b746e5SOllivier Robert authencryptions = 0; 2064c0b746e5SOllivier Robert authdecryptions = 0; 2065c0b746e5SOllivier Robert authkeyuncached = 0; 2066c0b746e5SOllivier Robert auth_timereset = current_time; 2067c0b746e5SOllivier Robert } 2068c0b746e5SOllivier Robert 2069c0b746e5SOllivier Robert 2070c0b746e5SOllivier Robert /* 2071c0b746e5SOllivier Robert * req_get_traps - return information about current trap holders 2072c0b746e5SOllivier Robert */ 2073c0b746e5SOllivier Robert static void 2074c0b746e5SOllivier Robert req_get_traps( 20752b15cb3dSCy Schubert sockaddr_u *srcadr, 20762b15cb3dSCy Schubert endpt *inter, 2077c0b746e5SOllivier Robert struct req_pkt *inpkt 2078c0b746e5SOllivier Robert ) 2079c0b746e5SOllivier Robert { 20802b15cb3dSCy Schubert struct info_trap *it; 20812b15cb3dSCy Schubert struct ctl_trap *tr; 20822b15cb3dSCy Schubert size_t i; 2083c0b746e5SOllivier Robert 2084c0b746e5SOllivier Robert if (num_ctl_traps == 0) { 2085c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2086c0b746e5SOllivier Robert return; 2087c0b746e5SOllivier Robert } 2088c0b746e5SOllivier Robert 2089c0b746e5SOllivier Robert it = (struct info_trap *)prepare_pkt(srcadr, inter, inpkt, 20909c2daa00SOllivier Robert v6sizeof(struct info_trap)); 2091c0b746e5SOllivier Robert 20922b15cb3dSCy Schubert for (i = 0, tr = ctl_traps; i < COUNTOF(ctl_traps); i++, tr++) { 2093c0b746e5SOllivier Robert if (tr->tr_flags & TRAP_INUSE) { 20942b15cb3dSCy Schubert if (IS_IPV4(&tr->tr_addr)) { 2095c0b746e5SOllivier Robert if (tr->tr_localaddr == any_interface) 2096c0b746e5SOllivier Robert it->local_address = 0; 2097c0b746e5SOllivier Robert else 2098c0b746e5SOllivier Robert it->local_address 20992b15cb3dSCy Schubert = NSRCADR(&tr->tr_localaddr->sin); 21002b15cb3dSCy Schubert it->trap_address = NSRCADR(&tr->tr_addr); 21019c2daa00SOllivier Robert if (client_v6_capable) 21029c2daa00SOllivier Robert it->v6_flag = 0; 21039c2daa00SOllivier Robert } else { 21049c2daa00SOllivier Robert if (!client_v6_capable) 21059c2daa00SOllivier Robert continue; 21069c2daa00SOllivier Robert it->local_address6 21072b15cb3dSCy Schubert = SOCK_ADDR6(&tr->tr_localaddr->sin); 21082b15cb3dSCy Schubert it->trap_address6 = SOCK_ADDR6(&tr->tr_addr); 21099c2daa00SOllivier Robert it->v6_flag = 1; 21109c2daa00SOllivier Robert } 2111c0b746e5SOllivier Robert it->trap_port = NSRCPORT(&tr->tr_addr); 2112c0b746e5SOllivier Robert it->sequence = htons(tr->tr_sequence); 2113c0b746e5SOllivier Robert it->settime = htonl((u_int32)(current_time - tr->tr_settime)); 2114c0b746e5SOllivier Robert it->origtime = htonl((u_int32)(current_time - tr->tr_origtime)); 2115c0b746e5SOllivier Robert it->resets = htonl((u_int32)tr->tr_resets); 2116c0b746e5SOllivier Robert it->flags = htonl((u_int32)tr->tr_flags); 2117c0b746e5SOllivier Robert it = (struct info_trap *)more_pkt(); 2118c0b746e5SOllivier Robert } 2119c0b746e5SOllivier Robert } 2120c0b746e5SOllivier Robert flush_pkt(); 2121c0b746e5SOllivier Robert } 2122c0b746e5SOllivier Robert 2123c0b746e5SOllivier Robert 2124c0b746e5SOllivier Robert /* 2125c0b746e5SOllivier Robert * req_set_trap - configure a trap 2126c0b746e5SOllivier Robert */ 2127c0b746e5SOllivier Robert static void 2128c0b746e5SOllivier Robert req_set_trap( 21292b15cb3dSCy Schubert sockaddr_u *srcadr, 21302b15cb3dSCy Schubert endpt *inter, 2131c0b746e5SOllivier Robert struct req_pkt *inpkt 2132c0b746e5SOllivier Robert ) 2133c0b746e5SOllivier Robert { 2134c0b746e5SOllivier Robert do_setclr_trap(srcadr, inter, inpkt, 1); 2135c0b746e5SOllivier Robert } 2136c0b746e5SOllivier Robert 2137c0b746e5SOllivier Robert 2138c0b746e5SOllivier Robert 2139c0b746e5SOllivier Robert /* 2140c0b746e5SOllivier Robert * req_clr_trap - unconfigure a trap 2141c0b746e5SOllivier Robert */ 2142c0b746e5SOllivier Robert static void 2143c0b746e5SOllivier Robert req_clr_trap( 21442b15cb3dSCy Schubert sockaddr_u *srcadr, 21452b15cb3dSCy Schubert endpt *inter, 2146c0b746e5SOllivier Robert struct req_pkt *inpkt 2147c0b746e5SOllivier Robert ) 2148c0b746e5SOllivier Robert { 2149c0b746e5SOllivier Robert do_setclr_trap(srcadr, inter, inpkt, 0); 2150c0b746e5SOllivier Robert } 2151c0b746e5SOllivier Robert 2152c0b746e5SOllivier Robert 2153c0b746e5SOllivier Robert 2154c0b746e5SOllivier Robert /* 2155c0b746e5SOllivier Robert * do_setclr_trap - do the grunge work of (un)configuring a trap 2156c0b746e5SOllivier Robert */ 2157c0b746e5SOllivier Robert static void 2158c0b746e5SOllivier Robert do_setclr_trap( 21592b15cb3dSCy Schubert sockaddr_u *srcadr, 21602b15cb3dSCy Schubert endpt *inter, 2161c0b746e5SOllivier Robert struct req_pkt *inpkt, 2162c0b746e5SOllivier Robert int set 2163c0b746e5SOllivier Robert ) 2164c0b746e5SOllivier Robert { 2165c0b746e5SOllivier Robert register struct conf_trap *ct; 21662b15cb3dSCy Schubert register endpt *linter; 2167c0b746e5SOllivier Robert int res; 21682b15cb3dSCy Schubert sockaddr_u laddr; 2169c0b746e5SOllivier Robert 2170c0b746e5SOllivier Robert /* 21712b15cb3dSCy Schubert * Prepare sockaddr 2172c0b746e5SOllivier Robert */ 21732b15cb3dSCy Schubert ZERO_SOCK(&laddr); 21742b15cb3dSCy Schubert AF(&laddr) = AF(srcadr); 21752b15cb3dSCy Schubert SET_PORT(&laddr, NTP_PORT); 2176c0b746e5SOllivier Robert 2177c0b746e5SOllivier Robert /* 2178c0b746e5SOllivier Robert * Restrict ourselves to one item only. This eliminates 2179c0b746e5SOllivier Robert * the error reporting problem. 2180c0b746e5SOllivier Robert */ 2181c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2182224ba2bdSOllivier Robert msyslog(LOG_ERR, "do_setclr_trap: err_nitems > 1"); 2183c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2184c0b746e5SOllivier Robert return; 2185c0b746e5SOllivier Robert } 21862b15cb3dSCy Schubert ct = (struct conf_trap *)&inpkt->u; 2187c0b746e5SOllivier Robert 2188c0b746e5SOllivier Robert /* 2189c0b746e5SOllivier Robert * Look for the local interface. If none, use the default. 2190c0b746e5SOllivier Robert */ 2191c0b746e5SOllivier Robert if (ct->local_address == 0) { 2192c0b746e5SOllivier Robert linter = any_interface; 2193c0b746e5SOllivier Robert } else { 21942b15cb3dSCy Schubert if (IS_IPV4(&laddr)) 21952b15cb3dSCy Schubert NSRCADR(&laddr) = ct->local_address; 21969c2daa00SOllivier Robert else 21972b15cb3dSCy Schubert SOCK_ADDR6(&laddr) = ct->local_address6; 2198c0b746e5SOllivier Robert linter = findinterface(&laddr); 21992b15cb3dSCy Schubert if (NULL == linter) { 2200c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2201c0b746e5SOllivier Robert return; 2202c0b746e5SOllivier Robert } 2203c0b746e5SOllivier Robert } 2204c0b746e5SOllivier Robert 22052b15cb3dSCy Schubert if (IS_IPV4(&laddr)) 22062b15cb3dSCy Schubert NSRCADR(&laddr) = ct->trap_address; 2207c0b746e5SOllivier Robert else 22082b15cb3dSCy Schubert SOCK_ADDR6(&laddr) = ct->trap_address6; 22092b15cb3dSCy Schubert if (ct->trap_port) 22109c2daa00SOllivier Robert NSRCPORT(&laddr) = ct->trap_port; 22119c2daa00SOllivier Robert else 22122b15cb3dSCy Schubert SET_PORT(&laddr, TRAPPORT); 2213c0b746e5SOllivier Robert 2214c0b746e5SOllivier Robert if (set) { 2215c0b746e5SOllivier Robert res = ctlsettrap(&laddr, linter, 0, 2216c0b746e5SOllivier Robert INFO_VERSION(inpkt->rm_vn_mode)); 2217c0b746e5SOllivier Robert } else { 2218c0b746e5SOllivier Robert res = ctlclrtrap(&laddr, linter, 0); 2219c0b746e5SOllivier Robert } 2220c0b746e5SOllivier Robert 2221c0b746e5SOllivier Robert if (!res) { 2222c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2223c0b746e5SOllivier Robert } else { 2224c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2225c0b746e5SOllivier Robert } 2226c0b746e5SOllivier Robert return; 2227c0b746e5SOllivier Robert } 2228c0b746e5SOllivier Robert 2229c0b746e5SOllivier Robert 2230c0b746e5SOllivier Robert 2231c0b746e5SOllivier Robert /* 2232c0b746e5SOllivier Robert * set_request_keyid - set the keyid used to authenticate requests 2233c0b746e5SOllivier Robert */ 2234c0b746e5SOllivier Robert static void 2235c0b746e5SOllivier Robert set_request_keyid( 22362b15cb3dSCy Schubert sockaddr_u *srcadr, 22372b15cb3dSCy Schubert endpt *inter, 2238c0b746e5SOllivier Robert struct req_pkt *inpkt 2239c0b746e5SOllivier Robert ) 2240c0b746e5SOllivier Robert { 22412b15cb3dSCy Schubert keyid_t *pkeyid; 2242c0b746e5SOllivier Robert 2243c0b746e5SOllivier Robert /* 2244c0b746e5SOllivier Robert * Restrict ourselves to one item only. 2245c0b746e5SOllivier Robert */ 2246c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2247224ba2bdSOllivier Robert msyslog(LOG_ERR, "set_request_keyid: err_nitems > 1"); 2248c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2249c0b746e5SOllivier Robert return; 2250c0b746e5SOllivier Robert } 2251c0b746e5SOllivier Robert 22522b15cb3dSCy Schubert pkeyid = (keyid_t *)&inpkt->u; 22532b15cb3dSCy Schubert info_auth_keyid = ntohl(*pkeyid); 2254c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2255c0b746e5SOllivier Robert } 2256c0b746e5SOllivier Robert 2257c0b746e5SOllivier Robert 2258c0b746e5SOllivier Robert 2259c0b746e5SOllivier Robert /* 2260c0b746e5SOllivier Robert * set_control_keyid - set the keyid used to authenticate requests 2261c0b746e5SOllivier Robert */ 2262c0b746e5SOllivier Robert static void 2263c0b746e5SOllivier Robert set_control_keyid( 22642b15cb3dSCy Schubert sockaddr_u *srcadr, 22652b15cb3dSCy Schubert endpt *inter, 2266c0b746e5SOllivier Robert struct req_pkt *inpkt 2267c0b746e5SOllivier Robert ) 2268c0b746e5SOllivier Robert { 22692b15cb3dSCy Schubert keyid_t *pkeyid; 2270c0b746e5SOllivier Robert 2271c0b746e5SOllivier Robert /* 2272c0b746e5SOllivier Robert * Restrict ourselves to one item only. 2273c0b746e5SOllivier Robert */ 2274c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2275224ba2bdSOllivier Robert msyslog(LOG_ERR, "set_control_keyid: err_nitems > 1"); 2276c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2277c0b746e5SOllivier Robert return; 2278c0b746e5SOllivier Robert } 2279c0b746e5SOllivier Robert 22802b15cb3dSCy Schubert pkeyid = (keyid_t *)&inpkt->u; 22812b15cb3dSCy Schubert ctl_auth_keyid = ntohl(*pkeyid); 2282c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2283c0b746e5SOllivier Robert } 2284c0b746e5SOllivier Robert 2285c0b746e5SOllivier Robert 2286c0b746e5SOllivier Robert 2287c0b746e5SOllivier Robert /* 2288c0b746e5SOllivier Robert * get_ctl_stats - return some stats concerning the control message module 2289c0b746e5SOllivier Robert */ 2290c0b746e5SOllivier Robert static void 2291c0b746e5SOllivier Robert get_ctl_stats( 22922b15cb3dSCy Schubert sockaddr_u *srcadr, 22932b15cb3dSCy Schubert endpt *inter, 2294c0b746e5SOllivier Robert struct req_pkt *inpkt 2295c0b746e5SOllivier Robert ) 2296c0b746e5SOllivier Robert { 2297c0b746e5SOllivier Robert register struct info_control *ic; 2298c0b746e5SOllivier Robert 2299c0b746e5SOllivier Robert ic = (struct info_control *)prepare_pkt(srcadr, inter, inpkt, 2300c0b746e5SOllivier Robert sizeof(struct info_control)); 2301c0b746e5SOllivier Robert 2302c0b746e5SOllivier Robert ic->ctltimereset = htonl((u_int32)(current_time - ctltimereset)); 2303c0b746e5SOllivier Robert ic->numctlreq = htonl((u_int32)numctlreq); 2304c0b746e5SOllivier Robert ic->numctlbadpkts = htonl((u_int32)numctlbadpkts); 2305c0b746e5SOllivier Robert ic->numctlresponses = htonl((u_int32)numctlresponses); 2306c0b746e5SOllivier Robert ic->numctlfrags = htonl((u_int32)numctlfrags); 2307c0b746e5SOllivier Robert ic->numctlerrors = htonl((u_int32)numctlerrors); 2308c0b746e5SOllivier Robert ic->numctltooshort = htonl((u_int32)numctltooshort); 2309c0b746e5SOllivier Robert ic->numctlinputresp = htonl((u_int32)numctlinputresp); 2310c0b746e5SOllivier Robert ic->numctlinputfrag = htonl((u_int32)numctlinputfrag); 2311c0b746e5SOllivier Robert ic->numctlinputerr = htonl((u_int32)numctlinputerr); 2312c0b746e5SOllivier Robert ic->numctlbadoffset = htonl((u_int32)numctlbadoffset); 2313c0b746e5SOllivier Robert ic->numctlbadversion = htonl((u_int32)numctlbadversion); 2314c0b746e5SOllivier Robert ic->numctldatatooshort = htonl((u_int32)numctldatatooshort); 2315c0b746e5SOllivier Robert ic->numctlbadop = htonl((u_int32)numctlbadop); 2316c0b746e5SOllivier Robert ic->numasyncmsgs = htonl((u_int32)numasyncmsgs); 2317c0b746e5SOllivier Robert 2318c0b746e5SOllivier Robert (void) more_pkt(); 2319c0b746e5SOllivier Robert flush_pkt(); 2320c0b746e5SOllivier Robert } 2321c0b746e5SOllivier Robert 2322c0b746e5SOllivier Robert 2323c0b746e5SOllivier Robert #ifdef KERNEL_PLL 2324c0b746e5SOllivier Robert /* 2325c0b746e5SOllivier Robert * get_kernel_info - get kernel pll/pps information 2326c0b746e5SOllivier Robert */ 2327c0b746e5SOllivier Robert static void 2328c0b746e5SOllivier Robert get_kernel_info( 23292b15cb3dSCy Schubert sockaddr_u *srcadr, 23302b15cb3dSCy Schubert endpt *inter, 2331c0b746e5SOllivier Robert struct req_pkt *inpkt 2332c0b746e5SOllivier Robert ) 2333c0b746e5SOllivier Robert { 2334c0b746e5SOllivier Robert register struct info_kernel *ik; 2335c0b746e5SOllivier Robert struct timex ntx; 2336c0b746e5SOllivier Robert 2337c0b746e5SOllivier Robert if (!pll_control) { 2338c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2339c0b746e5SOllivier Robert return; 2340c0b746e5SOllivier Robert } 2341c0b746e5SOllivier Robert 23422b15cb3dSCy Schubert ZERO(ntx); 2343c0b746e5SOllivier Robert if (ntp_adjtime(&ntx) < 0) 2344c0b746e5SOllivier Robert msyslog(LOG_ERR, "get_kernel_info: ntp_adjtime() failed: %m"); 2345c0b746e5SOllivier Robert ik = (struct info_kernel *)prepare_pkt(srcadr, inter, inpkt, 2346c0b746e5SOllivier Robert sizeof(struct info_kernel)); 2347c0b746e5SOllivier Robert 2348c0b746e5SOllivier Robert /* 2349c0b746e5SOllivier Robert * pll variables 2350c0b746e5SOllivier Robert */ 2351c0b746e5SOllivier Robert ik->offset = htonl((u_int32)ntx.offset); 2352c0b746e5SOllivier Robert ik->freq = htonl((u_int32)ntx.freq); 2353c0b746e5SOllivier Robert ik->maxerror = htonl((u_int32)ntx.maxerror); 2354c0b746e5SOllivier Robert ik->esterror = htonl((u_int32)ntx.esterror); 2355c0b746e5SOllivier Robert ik->status = htons(ntx.status); 2356c0b746e5SOllivier Robert ik->constant = htonl((u_int32)ntx.constant); 2357c0b746e5SOllivier Robert ik->precision = htonl((u_int32)ntx.precision); 2358c0b746e5SOllivier Robert ik->tolerance = htonl((u_int32)ntx.tolerance); 2359c0b746e5SOllivier Robert 2360c0b746e5SOllivier Robert /* 2361c0b746e5SOllivier Robert * pps variables 2362c0b746e5SOllivier Robert */ 2363c0b746e5SOllivier Robert ik->ppsfreq = htonl((u_int32)ntx.ppsfreq); 2364c0b746e5SOllivier Robert ik->jitter = htonl((u_int32)ntx.jitter); 2365c0b746e5SOllivier Robert ik->shift = htons(ntx.shift); 2366c0b746e5SOllivier Robert ik->stabil = htonl((u_int32)ntx.stabil); 2367c0b746e5SOllivier Robert ik->jitcnt = htonl((u_int32)ntx.jitcnt); 2368c0b746e5SOllivier Robert ik->calcnt = htonl((u_int32)ntx.calcnt); 2369c0b746e5SOllivier Robert ik->errcnt = htonl((u_int32)ntx.errcnt); 2370c0b746e5SOllivier Robert ik->stbcnt = htonl((u_int32)ntx.stbcnt); 2371c0b746e5SOllivier Robert 2372c0b746e5SOllivier Robert (void) more_pkt(); 2373c0b746e5SOllivier Robert flush_pkt(); 2374c0b746e5SOllivier Robert } 2375c0b746e5SOllivier Robert #endif /* KERNEL_PLL */ 2376c0b746e5SOllivier Robert 2377c0b746e5SOllivier Robert 2378c0b746e5SOllivier Robert #ifdef REFCLOCK 2379c0b746e5SOllivier Robert /* 2380c0b746e5SOllivier Robert * get_clock_info - get info about a clock 2381c0b746e5SOllivier Robert */ 2382c0b746e5SOllivier Robert static void 2383c0b746e5SOllivier Robert get_clock_info( 23842b15cb3dSCy Schubert sockaddr_u *srcadr, 23852b15cb3dSCy Schubert endpt *inter, 2386c0b746e5SOllivier Robert struct req_pkt *inpkt 2387c0b746e5SOllivier Robert ) 2388c0b746e5SOllivier Robert { 2389c0b746e5SOllivier Robert register struct info_clock *ic; 2390c0b746e5SOllivier Robert register u_int32 *clkaddr; 2391c0b746e5SOllivier Robert register int items; 2392c0b746e5SOllivier Robert struct refclockstat clock_stat; 23932b15cb3dSCy Schubert sockaddr_u addr; 2394c0b746e5SOllivier Robert l_fp ltmp; 2395c0b746e5SOllivier Robert 23962b15cb3dSCy Schubert ZERO_SOCK(&addr); 23972b15cb3dSCy Schubert AF(&addr) = AF_INET; 23982b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 23992b15cb3dSCy Schubert addr.sa.sa_len = SOCKLEN(&addr); 24009c2daa00SOllivier Robert #endif 24012b15cb3dSCy Schubert SET_PORT(&addr, NTP_PORT); 2402c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 24032b15cb3dSCy Schubert clkaddr = &inpkt->u.u32[0]; 2404c0b746e5SOllivier Robert 2405c0b746e5SOllivier Robert ic = (struct info_clock *)prepare_pkt(srcadr, inter, inpkt, 2406c0b746e5SOllivier Robert sizeof(struct info_clock)); 2407c0b746e5SOllivier Robert 2408c0b746e5SOllivier Robert while (items-- > 0) { 24092b15cb3dSCy Schubert NSRCADR(&addr) = *clkaddr++; 24102b15cb3dSCy Schubert if (!ISREFCLOCKADR(&addr) || NULL == 24112b15cb3dSCy Schubert findexistingpeer(&addr, NULL, NULL, -1, 0)) { 2412c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2413c0b746e5SOllivier Robert return; 2414c0b746e5SOllivier Robert } 2415c0b746e5SOllivier Robert 2416c0b746e5SOllivier Robert clock_stat.kv_list = (struct ctl_var *)0; 2417c0b746e5SOllivier Robert 24182b15cb3dSCy Schubert refclock_control(&addr, NULL, &clock_stat); 2419c0b746e5SOllivier Robert 24202b15cb3dSCy Schubert ic->clockadr = NSRCADR(&addr); 2421c0b746e5SOllivier Robert ic->type = clock_stat.type; 2422c0b746e5SOllivier Robert ic->flags = clock_stat.flags; 2423c0b746e5SOllivier Robert ic->lastevent = clock_stat.lastevent; 2424c0b746e5SOllivier Robert ic->currentstatus = clock_stat.currentstatus; 2425c0b746e5SOllivier Robert ic->polls = htonl((u_int32)clock_stat.polls); 2426c0b746e5SOllivier Robert ic->noresponse = htonl((u_int32)clock_stat.noresponse); 2427c0b746e5SOllivier Robert ic->badformat = htonl((u_int32)clock_stat.badformat); 2428c0b746e5SOllivier Robert ic->baddata = htonl((u_int32)clock_stat.baddata); 2429c0b746e5SOllivier Robert ic->timestarted = htonl((u_int32)clock_stat.timereset); 2430c0b746e5SOllivier Robert DTOLFP(clock_stat.fudgetime1, <mp); 2431c0b746e5SOllivier Robert HTONL_FP(<mp, &ic->fudgetime1); 24329c2daa00SOllivier Robert DTOLFP(clock_stat.fudgetime2, <mp); 2433c0b746e5SOllivier Robert HTONL_FP(<mp, &ic->fudgetime2); 2434c0b746e5SOllivier Robert ic->fudgeval1 = htonl((u_int32)clock_stat.fudgeval1); 24352b15cb3dSCy Schubert ic->fudgeval2 = htonl(clock_stat.fudgeval2); 2436c0b746e5SOllivier Robert 2437c0b746e5SOllivier Robert free_varlist(clock_stat.kv_list); 2438c0b746e5SOllivier Robert 2439c0b746e5SOllivier Robert ic = (struct info_clock *)more_pkt(); 2440c0b746e5SOllivier Robert } 2441c0b746e5SOllivier Robert flush_pkt(); 2442c0b746e5SOllivier Robert } 2443c0b746e5SOllivier Robert 2444c0b746e5SOllivier Robert 2445c0b746e5SOllivier Robert 2446c0b746e5SOllivier Robert /* 2447c0b746e5SOllivier Robert * set_clock_fudge - get a clock's fudge factors 2448c0b746e5SOllivier Robert */ 2449c0b746e5SOllivier Robert static void 2450c0b746e5SOllivier Robert set_clock_fudge( 24512b15cb3dSCy Schubert sockaddr_u *srcadr, 24522b15cb3dSCy Schubert endpt *inter, 2453c0b746e5SOllivier Robert struct req_pkt *inpkt 2454c0b746e5SOllivier Robert ) 2455c0b746e5SOllivier Robert { 2456c0b746e5SOllivier Robert register struct conf_fudge *cf; 2457c0b746e5SOllivier Robert register int items; 2458c0b746e5SOllivier Robert struct refclockstat clock_stat; 24592b15cb3dSCy Schubert sockaddr_u addr; 2460c0b746e5SOllivier Robert l_fp ltmp; 2461c0b746e5SOllivier Robert 24622b15cb3dSCy Schubert ZERO(addr); 24632b15cb3dSCy Schubert ZERO(clock_stat); 2464c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 24652b15cb3dSCy Schubert cf = (struct conf_fudge *)&inpkt->u; 2466c0b746e5SOllivier Robert 2467c0b746e5SOllivier Robert while (items-- > 0) { 24682b15cb3dSCy Schubert AF(&addr) = AF_INET; 24692b15cb3dSCy Schubert NSRCADR(&addr) = cf->clockadr; 24702b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 24712b15cb3dSCy Schubert addr.sa.sa_len = SOCKLEN(&addr); 24729c2daa00SOllivier Robert #endif 24732b15cb3dSCy Schubert SET_PORT(&addr, NTP_PORT); 24742b15cb3dSCy Schubert if (!ISREFCLOCKADR(&addr) || NULL == 24752b15cb3dSCy Schubert findexistingpeer(&addr, NULL, NULL, -1, 0)) { 2476c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2477c0b746e5SOllivier Robert return; 2478c0b746e5SOllivier Robert } 2479c0b746e5SOllivier Robert 2480c0b746e5SOllivier Robert switch(ntohl(cf->which)) { 2481c0b746e5SOllivier Robert case FUDGE_TIME1: 2482c0b746e5SOllivier Robert NTOHL_FP(&cf->fudgetime, <mp); 2483c0b746e5SOllivier Robert LFPTOD(<mp, clock_stat.fudgetime1); 2484c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVETIME1; 2485c0b746e5SOllivier Robert break; 2486c0b746e5SOllivier Robert case FUDGE_TIME2: 2487c0b746e5SOllivier Robert NTOHL_FP(&cf->fudgetime, <mp); 2488c0b746e5SOllivier Robert LFPTOD(<mp, clock_stat.fudgetime2); 2489c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVETIME2; 2490c0b746e5SOllivier Robert break; 2491c0b746e5SOllivier Robert case FUDGE_VAL1: 2492c0b746e5SOllivier Robert clock_stat.fudgeval1 = ntohl(cf->fudgeval_flags); 2493c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVEVAL1; 2494c0b746e5SOllivier Robert break; 2495c0b746e5SOllivier Robert case FUDGE_VAL2: 2496c0b746e5SOllivier Robert clock_stat.fudgeval2 = ntohl(cf->fudgeval_flags); 2497c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVEVAL2; 2498c0b746e5SOllivier Robert break; 2499c0b746e5SOllivier Robert case FUDGE_FLAGS: 25009c2daa00SOllivier Robert clock_stat.flags = (u_char) (ntohl(cf->fudgeval_flags) & 0xf); 2501c0b746e5SOllivier Robert clock_stat.haveflags = 2502c0b746e5SOllivier Robert (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4); 2503c0b746e5SOllivier Robert break; 2504c0b746e5SOllivier Robert default: 2505224ba2bdSOllivier Robert msyslog(LOG_ERR, "set_clock_fudge: default!"); 2506c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2507c0b746e5SOllivier Robert return; 2508c0b746e5SOllivier Robert } 2509c0b746e5SOllivier Robert 2510c0b746e5SOllivier Robert refclock_control(&addr, &clock_stat, (struct refclockstat *)0); 2511c0b746e5SOllivier Robert } 2512c0b746e5SOllivier Robert 2513c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2514c0b746e5SOllivier Robert } 2515c0b746e5SOllivier Robert #endif 2516c0b746e5SOllivier Robert 2517c0b746e5SOllivier Robert #ifdef REFCLOCK 2518c0b746e5SOllivier Robert /* 2519c0b746e5SOllivier Robert * get_clkbug_info - get debugging info about a clock 2520c0b746e5SOllivier Robert */ 2521c0b746e5SOllivier Robert static void 2522c0b746e5SOllivier Robert get_clkbug_info( 25232b15cb3dSCy Schubert sockaddr_u *srcadr, 25242b15cb3dSCy Schubert endpt *inter, 2525c0b746e5SOllivier Robert struct req_pkt *inpkt 2526c0b746e5SOllivier Robert ) 2527c0b746e5SOllivier Robert { 2528c0b746e5SOllivier Robert register int i; 2529c0b746e5SOllivier Robert register struct info_clkbug *ic; 2530c0b746e5SOllivier Robert register u_int32 *clkaddr; 2531c0b746e5SOllivier Robert register int items; 2532c0b746e5SOllivier Robert struct refclockbug bug; 25332b15cb3dSCy Schubert sockaddr_u addr; 2534c0b746e5SOllivier Robert 25352b15cb3dSCy Schubert ZERO_SOCK(&addr); 25362b15cb3dSCy Schubert AF(&addr) = AF_INET; 25372b15cb3dSCy Schubert #ifdef ISC_PLATFORM_HAVESALEN 25382b15cb3dSCy Schubert addr.sa.sa_len = SOCKLEN(&addr); 25399c2daa00SOllivier Robert #endif 25402b15cb3dSCy Schubert SET_PORT(&addr, NTP_PORT); 2541c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 25422b15cb3dSCy Schubert clkaddr = (u_int32 *)&inpkt->u; 2543c0b746e5SOllivier Robert 2544c0b746e5SOllivier Robert ic = (struct info_clkbug *)prepare_pkt(srcadr, inter, inpkt, 2545c0b746e5SOllivier Robert sizeof(struct info_clkbug)); 2546c0b746e5SOllivier Robert 2547c0b746e5SOllivier Robert while (items-- > 0) { 25482b15cb3dSCy Schubert NSRCADR(&addr) = *clkaddr++; 25492b15cb3dSCy Schubert if (!ISREFCLOCKADR(&addr) || NULL == 25502b15cb3dSCy Schubert findexistingpeer(&addr, NULL, NULL, -1, 0)) { 2551c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2552c0b746e5SOllivier Robert return; 2553c0b746e5SOllivier Robert } 2554c0b746e5SOllivier Robert 25552b15cb3dSCy Schubert ZERO(bug); 2556c0b746e5SOllivier Robert refclock_buginfo(&addr, &bug); 2557c0b746e5SOllivier Robert if (bug.nvalues == 0 && bug.ntimes == 0) { 2558c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2559c0b746e5SOllivier Robert return; 2560c0b746e5SOllivier Robert } 2561c0b746e5SOllivier Robert 25622b15cb3dSCy Schubert ic->clockadr = NSRCADR(&addr); 2563c0b746e5SOllivier Robert i = bug.nvalues; 2564c0b746e5SOllivier Robert if (i > NUMCBUGVALUES) 2565c0b746e5SOllivier Robert i = NUMCBUGVALUES; 2566c0b746e5SOllivier Robert ic->nvalues = (u_char)i; 2567c0b746e5SOllivier Robert ic->svalues = htons((u_short) (bug.svalues & ((1<<i)-1))); 2568c0b746e5SOllivier Robert while (--i >= 0) 2569c0b746e5SOllivier Robert ic->values[i] = htonl(bug.values[i]); 2570c0b746e5SOllivier Robert 2571c0b746e5SOllivier Robert i = bug.ntimes; 2572c0b746e5SOllivier Robert if (i > NUMCBUGTIMES) 2573c0b746e5SOllivier Robert i = NUMCBUGTIMES; 2574c0b746e5SOllivier Robert ic->ntimes = (u_char)i; 2575c0b746e5SOllivier Robert ic->stimes = htonl(bug.stimes); 2576c0b746e5SOllivier Robert while (--i >= 0) { 2577c0b746e5SOllivier Robert HTONL_FP(&bug.times[i], &ic->times[i]); 2578c0b746e5SOllivier Robert } 2579c0b746e5SOllivier Robert 2580c0b746e5SOllivier Robert ic = (struct info_clkbug *)more_pkt(); 2581c0b746e5SOllivier Robert } 2582c0b746e5SOllivier Robert flush_pkt(); 2583c0b746e5SOllivier Robert } 2584c0b746e5SOllivier Robert #endif 2585ea906c41SOllivier Robert 2586ea906c41SOllivier Robert /* 2587ea906c41SOllivier Robert * receiver of interface structures 2588ea906c41SOllivier Robert */ 2589ea906c41SOllivier Robert static void 2590ea906c41SOllivier Robert fill_info_if_stats(void *data, interface_info_t *interface_info) 2591ea906c41SOllivier Robert { 2592ea906c41SOllivier Robert struct info_if_stats **ifsp = (struct info_if_stats **)data; 2593ea906c41SOllivier Robert struct info_if_stats *ifs = *ifsp; 25942b15cb3dSCy Schubert endpt *ep = interface_info->ep; 2595ea906c41SOllivier Robert 25962b15cb3dSCy Schubert ZERO(*ifs); 2597ea906c41SOllivier Robert 25982b15cb3dSCy Schubert if (IS_IPV6(&ep->sin)) { 2599ea906c41SOllivier Robert if (!client_v6_capable) { 2600ea906c41SOllivier Robert return; 2601ea906c41SOllivier Robert } 2602ea906c41SOllivier Robert ifs->v6_flag = 1; 26032b15cb3dSCy Schubert ifs->unaddr.addr6 = SOCK_ADDR6(&ep->sin); 26042b15cb3dSCy Schubert ifs->unbcast.addr6 = SOCK_ADDR6(&ep->bcast); 26052b15cb3dSCy Schubert ifs->unmask.addr6 = SOCK_ADDR6(&ep->mask); 2606ea906c41SOllivier Robert } else { 2607ea906c41SOllivier Robert ifs->v6_flag = 0; 26082b15cb3dSCy Schubert ifs->unaddr.addr = SOCK_ADDR4(&ep->sin); 26092b15cb3dSCy Schubert ifs->unbcast.addr = SOCK_ADDR4(&ep->bcast); 26102b15cb3dSCy Schubert ifs->unmask.addr = SOCK_ADDR4(&ep->mask); 2611ea906c41SOllivier Robert } 2612ea906c41SOllivier Robert ifs->v6_flag = htonl(ifs->v6_flag); 26132b15cb3dSCy Schubert strlcpy(ifs->name, ep->name, sizeof(ifs->name)); 26142b15cb3dSCy Schubert ifs->family = htons(ep->family); 26152b15cb3dSCy Schubert ifs->flags = htonl(ep->flags); 26162b15cb3dSCy Schubert ifs->last_ttl = htonl(ep->last_ttl); 26172b15cb3dSCy Schubert ifs->num_mcast = htonl(ep->num_mcast); 26182b15cb3dSCy Schubert ifs->received = htonl(ep->received); 26192b15cb3dSCy Schubert ifs->sent = htonl(ep->sent); 26202b15cb3dSCy Schubert ifs->notsent = htonl(ep->notsent); 26212b15cb3dSCy Schubert ifs->ifindex = htonl(ep->ifindex); 26222b15cb3dSCy Schubert /* scope no longer in endpt, in in6_addr typically */ 26232b15cb3dSCy Schubert ifs->scopeid = ifs->ifindex; 26242b15cb3dSCy Schubert ifs->ifnum = htonl(ep->ifnum); 26252b15cb3dSCy Schubert ifs->uptime = htonl(current_time - ep->starttime); 26262b15cb3dSCy Schubert ifs->ignore_packets = ep->ignore_packets; 26272b15cb3dSCy Schubert ifs->peercnt = htonl(ep->peercnt); 2628ea906c41SOllivier Robert ifs->action = interface_info->action; 2629ea906c41SOllivier Robert 2630ea906c41SOllivier Robert *ifsp = (struct info_if_stats *)more_pkt(); 2631ea906c41SOllivier Robert } 2632ea906c41SOllivier Robert 2633ea906c41SOllivier Robert /* 2634ea906c41SOllivier Robert * get_if_stats - get interface statistics 2635ea906c41SOllivier Robert */ 2636ea906c41SOllivier Robert static void 2637ea906c41SOllivier Robert get_if_stats( 26382b15cb3dSCy Schubert sockaddr_u *srcadr, 26392b15cb3dSCy Schubert endpt *inter, 2640ea906c41SOllivier Robert struct req_pkt *inpkt 2641ea906c41SOllivier Robert ) 2642ea906c41SOllivier Robert { 2643ea906c41SOllivier Robert struct info_if_stats *ifs; 2644ea906c41SOllivier Robert 2645ea906c41SOllivier Robert DPRINTF(3, ("wants interface statistics\n")); 2646ea906c41SOllivier Robert 2647ea906c41SOllivier Robert ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt, 2648ea906c41SOllivier Robert v6sizeof(struct info_if_stats)); 2649ea906c41SOllivier Robert 2650ea906c41SOllivier Robert interface_enumerate(fill_info_if_stats, &ifs); 2651ea906c41SOllivier Robert 2652ea906c41SOllivier Robert flush_pkt(); 2653ea906c41SOllivier Robert } 2654ea906c41SOllivier Robert 2655ea906c41SOllivier Robert static void 2656ea906c41SOllivier Robert do_if_reload( 26572b15cb3dSCy Schubert sockaddr_u *srcadr, 26582b15cb3dSCy Schubert endpt *inter, 2659ea906c41SOllivier Robert struct req_pkt *inpkt 2660ea906c41SOllivier Robert ) 2661ea906c41SOllivier Robert { 2662ea906c41SOllivier Robert struct info_if_stats *ifs; 2663ea906c41SOllivier Robert 2664ea906c41SOllivier Robert DPRINTF(3, ("wants interface reload\n")); 2665ea906c41SOllivier Robert 2666ea906c41SOllivier Robert ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt, 2667ea906c41SOllivier Robert v6sizeof(struct info_if_stats)); 2668ea906c41SOllivier Robert 2669ea906c41SOllivier Robert interface_update(fill_info_if_stats, &ifs); 2670ea906c41SOllivier Robert 2671ea906c41SOllivier Robert flush_pkt(); 2672ea906c41SOllivier Robert } 2673ea906c41SOllivier Robert 2674