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" 16224ba2bdSOllivier Robert 17224ba2bdSOllivier Robert #include <stdio.h> 189c2daa00SOllivier Robert #include <stddef.h> 19224ba2bdSOllivier Robert #include <signal.h> 20224ba2bdSOllivier Robert #include <netinet/in.h> 21224ba2bdSOllivier Robert #include <arpa/inet.h> 22224ba2bdSOllivier Robert 23c0b746e5SOllivier Robert #include "recvbuff.h" 24c0b746e5SOllivier Robert 25c0b746e5SOllivier Robert #ifdef KERNEL_PLL 26c0b746e5SOllivier Robert #include "ntp_syscall.h" 27c0b746e5SOllivier Robert #endif /* KERNEL_PLL */ 28c0b746e5SOllivier Robert 29c0b746e5SOllivier Robert /* 30c0b746e5SOllivier Robert * Structure to hold request procedure information 31c0b746e5SOllivier Robert */ 32c0b746e5SOllivier Robert #define NOAUTH 0 33c0b746e5SOllivier Robert #define AUTH 1 34c0b746e5SOllivier Robert 35c0b746e5SOllivier Robert #define NO_REQUEST (-1) 369c2daa00SOllivier Robert /* 379c2daa00SOllivier Robert * Because we now have v6 addresses in the messages, we need to compensate 389c2daa00SOllivier Robert * for the larger size. Therefore, we introduce the alternate size to 399c2daa00SOllivier Robert * keep us friendly with older implementations. A little ugly. 409c2daa00SOllivier Robert */ 419c2daa00SOllivier Robert static int client_v6_capable = 0; /* the client can handle longer messages */ 429c2daa00SOllivier Robert 439c2daa00SOllivier Robert #define v6sizeof(type) (client_v6_capable ? sizeof(type) : v4sizeof(type)) 44c0b746e5SOllivier Robert 45c0b746e5SOllivier Robert struct req_proc { 46c0b746e5SOllivier Robert short request_code; /* defined request code */ 47c0b746e5SOllivier Robert short needs_auth; /* true when authentication needed */ 489c2daa00SOllivier Robert short sizeofitem; /* size of request data item (older size)*/ 499c2daa00SOllivier Robert short v6_sizeofitem; /* size of request data item (new size)*/ 509c2daa00SOllivier Robert void (*handler) P((struct sockaddr_storage *, struct interface *, 51c0b746e5SOllivier Robert struct req_pkt *)); /* routine to handle request */ 52c0b746e5SOllivier Robert }; 53c0b746e5SOllivier Robert 54c0b746e5SOllivier Robert /* 55c0b746e5SOllivier Robert * Universal request codes 56c0b746e5SOllivier Robert */ 57c0b746e5SOllivier Robert static struct req_proc univ_codes[] = { 58c0b746e5SOllivier Robert { NO_REQUEST, NOAUTH, 0, 0 } 59c0b746e5SOllivier Robert }; 60c0b746e5SOllivier Robert 619c2daa00SOllivier Robert static void req_ack P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int)); 629c2daa00SOllivier Robert static char * prepare_pkt P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_int)); 63c0b746e5SOllivier Robert static char * more_pkt P((void)); 64c0b746e5SOllivier Robert static void flush_pkt P((void)); 659c2daa00SOllivier Robert static void peer_list P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 669c2daa00SOllivier Robert static void peer_list_sum P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 679c2daa00SOllivier Robert static void peer_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 689c2daa00SOllivier Robert static void peer_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 699c2daa00SOllivier Robert static void sys_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 709c2daa00SOllivier Robert static void sys_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 719c2daa00SOllivier Robert static void mem_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 729c2daa00SOllivier Robert static void io_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 739c2daa00SOllivier Robert static void timer_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 749c2daa00SOllivier Robert static void loop_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 759c2daa00SOllivier Robert static void do_conf P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 769c2daa00SOllivier Robert static void do_unconf P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 779c2daa00SOllivier Robert static void set_sys_flag P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 789c2daa00SOllivier Robert static void clr_sys_flag P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 799c2daa00SOllivier Robert static void setclr_flags P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_long)); 809c2daa00SOllivier Robert static void list_restrict P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 819c2daa00SOllivier Robert static void do_resaddflags P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 829c2daa00SOllivier Robert static void do_ressubflags P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 839c2daa00SOllivier Robert static void do_unrestrict P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 849c2daa00SOllivier Robert static void do_restrict P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int)); 859c2daa00SOllivier Robert static void mon_getlist_0 P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 869c2daa00SOllivier Robert static void mon_getlist_1 P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 879c2daa00SOllivier Robert static void reset_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 889c2daa00SOllivier Robert static void reset_peer P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 899c2daa00SOllivier Robert static void do_key_reread P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 909c2daa00SOllivier Robert static void trust_key P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 919c2daa00SOllivier Robert static void untrust_key P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 929c2daa00SOllivier Robert static void do_trustkey P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_long)); 939c2daa00SOllivier Robert static void get_auth_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 94c0b746e5SOllivier Robert static void reset_auth_stats P((void)); 959c2daa00SOllivier Robert static void req_get_traps P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 969c2daa00SOllivier Robert static void req_set_trap P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 979c2daa00SOllivier Robert static void req_clr_trap P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 989c2daa00SOllivier Robert static void do_setclr_trap P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int)); 999c2daa00SOllivier Robert static void set_request_keyid P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 1009c2daa00SOllivier Robert static void set_control_keyid P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 1019c2daa00SOllivier Robert static void get_ctl_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 102ea906c41SOllivier Robert static void get_if_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 103ea906c41SOllivier Robert static void do_if_reload P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 104c0b746e5SOllivier Robert #ifdef KERNEL_PLL 1059c2daa00SOllivier Robert static void get_kernel_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 106c0b746e5SOllivier Robert #endif /* KERNEL_PLL */ 107c0b746e5SOllivier Robert #ifdef REFCLOCK 1089c2daa00SOllivier Robert static void get_clock_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 1099c2daa00SOllivier Robert static void set_clock_fudge P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 110c0b746e5SOllivier Robert #endif /* REFCLOCK */ 111c0b746e5SOllivier Robert #ifdef REFCLOCK 1129c2daa00SOllivier Robert static void get_clkbug_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 113c0b746e5SOllivier Robert #endif /* REFCLOCK */ 114c0b746e5SOllivier Robert 115c0b746e5SOllivier Robert /* 116c0b746e5SOllivier Robert * ntpd request codes 117c0b746e5SOllivier Robert */ 118c0b746e5SOllivier Robert static struct req_proc ntp_codes[] = { 1199c2daa00SOllivier Robert { REQ_PEER_LIST, NOAUTH, 0, 0, peer_list }, 1209c2daa00SOllivier Robert { REQ_PEER_LIST_SUM, NOAUTH, 0, 0, peer_list_sum }, 1219c2daa00SOllivier Robert { REQ_PEER_INFO, NOAUTH, v4sizeof(struct info_peer_list), 1229c2daa00SOllivier Robert sizeof(struct info_peer_list), peer_info}, 1239c2daa00SOllivier Robert { REQ_PEER_STATS, NOAUTH, v4sizeof(struct info_peer_list), 1249c2daa00SOllivier Robert sizeof(struct info_peer_list), peer_stats}, 1259c2daa00SOllivier Robert { REQ_SYS_INFO, NOAUTH, 0, 0, sys_info }, 1269c2daa00SOllivier Robert { REQ_SYS_STATS, NOAUTH, 0, 0, sys_stats }, 1279c2daa00SOllivier Robert { REQ_IO_STATS, NOAUTH, 0, 0, io_stats }, 1289c2daa00SOllivier Robert { REQ_MEM_STATS, NOAUTH, 0, 0, mem_stats }, 1299c2daa00SOllivier Robert { REQ_LOOP_INFO, NOAUTH, 0, 0, loop_info }, 1309c2daa00SOllivier Robert { REQ_TIMER_STATS, NOAUTH, 0, 0, timer_stats }, 1319c2daa00SOllivier Robert { REQ_CONFIG, AUTH, v4sizeof(struct conf_peer), 1329c2daa00SOllivier Robert sizeof(struct conf_peer), do_conf }, 1339c2daa00SOllivier Robert { REQ_UNCONFIG, AUTH, v4sizeof(struct conf_unpeer), 1349c2daa00SOllivier Robert sizeof(struct conf_unpeer), do_unconf }, 1359c2daa00SOllivier Robert { REQ_SET_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), 1369c2daa00SOllivier Robert sizeof(struct conf_sys_flags), set_sys_flag }, 1379c2daa00SOllivier Robert { REQ_CLR_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), 1389c2daa00SOllivier Robert sizeof(struct conf_sys_flags), clr_sys_flag }, 1399c2daa00SOllivier Robert { REQ_GET_RESTRICT, NOAUTH, 0, 0, list_restrict }, 1409c2daa00SOllivier Robert { REQ_RESADDFLAGS, AUTH, v4sizeof(struct conf_restrict), 1419c2daa00SOllivier Robert sizeof(struct conf_restrict), do_resaddflags }, 1429c2daa00SOllivier Robert { REQ_RESSUBFLAGS, AUTH, v4sizeof(struct conf_restrict), 1439c2daa00SOllivier Robert sizeof(struct conf_restrict), do_ressubflags }, 1449c2daa00SOllivier Robert { REQ_UNRESTRICT, AUTH, v4sizeof(struct conf_restrict), 1459c2daa00SOllivier Robert sizeof(struct conf_restrict), do_unrestrict }, 1469c2daa00SOllivier Robert { REQ_MON_GETLIST, NOAUTH, 0, 0, mon_getlist_0 }, 1479c2daa00SOllivier Robert { REQ_MON_GETLIST_1, NOAUTH, 0, 0, mon_getlist_1 }, 1489c2daa00SOllivier Robert { REQ_RESET_STATS, AUTH, sizeof(struct reset_flags), 0, reset_stats }, 1499c2daa00SOllivier Robert { REQ_RESET_PEER, AUTH, v4sizeof(struct conf_unpeer), 1509c2daa00SOllivier Robert sizeof(struct conf_unpeer), reset_peer }, 1519c2daa00SOllivier Robert { REQ_REREAD_KEYS, AUTH, 0, 0, do_key_reread }, 1529c2daa00SOllivier Robert { REQ_TRUSTKEY, AUTH, sizeof(u_long), sizeof(u_long), trust_key }, 1539c2daa00SOllivier Robert { REQ_UNTRUSTKEY, AUTH, sizeof(u_long), sizeof(u_long), untrust_key }, 1549c2daa00SOllivier Robert { REQ_AUTHINFO, NOAUTH, 0, 0, get_auth_info }, 1559c2daa00SOllivier Robert { REQ_TRAPS, NOAUTH, 0, 0, req_get_traps }, 1569c2daa00SOllivier Robert { REQ_ADD_TRAP, AUTH, v4sizeof(struct conf_trap), 1579c2daa00SOllivier Robert sizeof(struct conf_trap), req_set_trap }, 1589c2daa00SOllivier Robert { REQ_CLR_TRAP, AUTH, v4sizeof(struct conf_trap), 1599c2daa00SOllivier Robert sizeof(struct conf_trap), req_clr_trap }, 1609c2daa00SOllivier Robert { REQ_REQUEST_KEY, AUTH, sizeof(u_long), sizeof(u_long), 1619c2daa00SOllivier Robert set_request_keyid }, 1629c2daa00SOllivier Robert { REQ_CONTROL_KEY, AUTH, sizeof(u_long), sizeof(u_long), 1639c2daa00SOllivier Robert set_control_keyid }, 1649c2daa00SOllivier Robert { REQ_GET_CTLSTATS, NOAUTH, 0, 0, get_ctl_stats }, 165c0b746e5SOllivier Robert #ifdef KERNEL_PLL 1669c2daa00SOllivier Robert { REQ_GET_KERNEL, NOAUTH, 0, 0, get_kernel_info }, 167c0b746e5SOllivier Robert #endif 168c0b746e5SOllivier Robert #ifdef REFCLOCK 1699c2daa00SOllivier Robert { REQ_GET_CLOCKINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32), 1709c2daa00SOllivier Robert get_clock_info }, 1719c2daa00SOllivier Robert { REQ_SET_CLKFUDGE, AUTH, sizeof(struct conf_fudge), 1729c2daa00SOllivier Robert sizeof(struct conf_fudge), set_clock_fudge }, 1739c2daa00SOllivier Robert { REQ_GET_CLKBUGINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32), 1749c2daa00SOllivier Robert get_clkbug_info }, 175c0b746e5SOllivier Robert #endif 176ea906c41SOllivier Robert { REQ_IF_STATS, AUTH, 0, 0, get_if_stats }, 177ea906c41SOllivier Robert { REQ_IF_RELOAD, AUTH, 0, 0, do_if_reload }, 178ea906c41SOllivier Robert 1799c2daa00SOllivier Robert { NO_REQUEST, NOAUTH, 0, 0, 0 } 180c0b746e5SOllivier Robert }; 181c0b746e5SOllivier Robert 182c0b746e5SOllivier Robert 183c0b746e5SOllivier Robert /* 184c0b746e5SOllivier Robert * Authentication keyid used to authenticate requests. Zero means we 185c0b746e5SOllivier Robert * don't allow writing anything. 186c0b746e5SOllivier Robert */ 187224ba2bdSOllivier Robert keyid_t info_auth_keyid; 188c0b746e5SOllivier Robert 189c0b746e5SOllivier Robert /* 190c0b746e5SOllivier Robert * Statistic counters to keep track of requests and responses. 191c0b746e5SOllivier Robert */ 192c0b746e5SOllivier Robert u_long numrequests; /* number of requests we've received */ 193c0b746e5SOllivier Robert u_long numresppkts; /* number of resp packets sent with data */ 194c0b746e5SOllivier Robert 195c0b746e5SOllivier Robert u_long errorcounter[INFO_ERR_AUTH+1]; /* lazy way to count errors, indexed */ 196c0b746e5SOllivier Robert /* by the error code */ 197c0b746e5SOllivier Robert 198c0b746e5SOllivier Robert /* 199c0b746e5SOllivier Robert * A hack. To keep the authentication module clear of ntp-ism's, we 200c0b746e5SOllivier Robert * include a time reset variable for its stats here. 201c0b746e5SOllivier Robert */ 202c0b746e5SOllivier Robert static u_long auth_timereset; 203c0b746e5SOllivier Robert 204c0b746e5SOllivier Robert /* 205c0b746e5SOllivier Robert * Response packet used by these routines. Also some state information 206c0b746e5SOllivier Robert * so that we can handle packet formatting within a common set of 207c0b746e5SOllivier Robert * subroutines. Note we try to enter data in place whenever possible, 208c0b746e5SOllivier Robert * but the need to set the more bit correctly means we occasionally 209c0b746e5SOllivier Robert * use the extra buffer and copy. 210c0b746e5SOllivier Robert */ 211c0b746e5SOllivier Robert static struct resp_pkt rpkt; 212c0b746e5SOllivier Robert static int reqver; 213c0b746e5SOllivier Robert static int seqno; 214c0b746e5SOllivier Robert static int nitems; 215c0b746e5SOllivier Robert static int itemsize; 216c0b746e5SOllivier Robert static int databytes; 217c0b746e5SOllivier Robert static char exbuf[RESP_DATA_SIZE]; 218c0b746e5SOllivier Robert static int usingexbuf; 2199c2daa00SOllivier Robert static struct sockaddr_storage *toaddr; 220c0b746e5SOllivier Robert static struct interface *frominter; 221c0b746e5SOllivier Robert 222c0b746e5SOllivier Robert /* 223c0b746e5SOllivier Robert * init_request - initialize request data 224c0b746e5SOllivier Robert */ 225c0b746e5SOllivier Robert void 226c0b746e5SOllivier Robert init_request (void) 227c0b746e5SOllivier Robert { 228c0b746e5SOllivier Robert int i; 229c0b746e5SOllivier Robert 230c0b746e5SOllivier Robert numrequests = 0; 231c0b746e5SOllivier Robert numresppkts = 0; 232c0b746e5SOllivier Robert auth_timereset = 0; 233c0b746e5SOllivier Robert info_auth_keyid = 0; /* by default, can't do this */ 234c0b746e5SOllivier Robert 235c0b746e5SOllivier Robert for (i = 0; i < sizeof(errorcounter)/sizeof(errorcounter[0]); i++) 236c0b746e5SOllivier Robert errorcounter[i] = 0; 237c0b746e5SOllivier Robert } 238c0b746e5SOllivier Robert 239c0b746e5SOllivier Robert 240c0b746e5SOllivier Robert /* 241c0b746e5SOllivier Robert * req_ack - acknowledge request with no data 242c0b746e5SOllivier Robert */ 243c0b746e5SOllivier Robert static void 244c0b746e5SOllivier Robert req_ack( 2459c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 246c0b746e5SOllivier Robert struct interface *inter, 247c0b746e5SOllivier Robert struct req_pkt *inpkt, 248c0b746e5SOllivier Robert int errcode 249c0b746e5SOllivier Robert ) 250c0b746e5SOllivier Robert { 251c0b746e5SOllivier Robert /* 252c0b746e5SOllivier Robert * fill in the fields 253c0b746e5SOllivier Robert */ 254c0b746e5SOllivier Robert rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver); 255c0b746e5SOllivier Robert rpkt.auth_seq = AUTH_SEQ(0, 0); 256c0b746e5SOllivier Robert rpkt.implementation = inpkt->implementation; 257c0b746e5SOllivier Robert rpkt.request = inpkt->request; 258c0b746e5SOllivier Robert rpkt.err_nitems = ERR_NITEMS(errcode, 0); 259c0b746e5SOllivier Robert rpkt.mbz_itemsize = MBZ_ITEMSIZE(0); 260c0b746e5SOllivier Robert 261c0b746e5SOllivier Robert /* 262c0b746e5SOllivier Robert * send packet and bump counters 263c0b746e5SOllivier Robert */ 264c0b746e5SOllivier Robert sendpkt(srcadr, inter, -1, (struct pkt *)&rpkt, RESP_HEADER_SIZE); 265c0b746e5SOllivier Robert errorcounter[errcode]++; 266c0b746e5SOllivier Robert } 267c0b746e5SOllivier Robert 268c0b746e5SOllivier Robert 269c0b746e5SOllivier Robert /* 270c0b746e5SOllivier Robert * prepare_pkt - prepare response packet for transmission, return pointer 271c0b746e5SOllivier Robert * to storage for data item. 272c0b746e5SOllivier Robert */ 273c0b746e5SOllivier Robert static char * 274c0b746e5SOllivier Robert prepare_pkt( 2759c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 276c0b746e5SOllivier Robert struct interface *inter, 277c0b746e5SOllivier Robert struct req_pkt *pkt, 278c0b746e5SOllivier Robert u_int structsize 279c0b746e5SOllivier Robert ) 280c0b746e5SOllivier Robert { 281c0b746e5SOllivier Robert #ifdef DEBUG 282c0b746e5SOllivier Robert if (debug > 3) 283c0b746e5SOllivier Robert printf("request: preparing pkt\n"); 284c0b746e5SOllivier Robert #endif 285c0b746e5SOllivier Robert 286c0b746e5SOllivier Robert /* 2879c2daa00SOllivier Robert * Fill in the implementation, request and itemsize fields 288c0b746e5SOllivier Robert * since these won't change. 289c0b746e5SOllivier Robert */ 290c0b746e5SOllivier Robert rpkt.implementation = pkt->implementation; 291c0b746e5SOllivier Robert rpkt.request = pkt->request; 292c0b746e5SOllivier Robert rpkt.mbz_itemsize = MBZ_ITEMSIZE(structsize); 293c0b746e5SOllivier Robert 294c0b746e5SOllivier Robert /* 295c0b746e5SOllivier Robert * Compute the static data needed to carry on. 296c0b746e5SOllivier Robert */ 297c0b746e5SOllivier Robert toaddr = srcadr; 298c0b746e5SOllivier Robert frominter = inter; 299c0b746e5SOllivier Robert seqno = 0; 300c0b746e5SOllivier Robert nitems = 0; 301c0b746e5SOllivier Robert itemsize = structsize; 302c0b746e5SOllivier Robert databytes = 0; 303c0b746e5SOllivier Robert usingexbuf = 0; 304c0b746e5SOllivier Robert 305c0b746e5SOllivier Robert /* 306c0b746e5SOllivier Robert * return the beginning of the packet buffer. 307c0b746e5SOllivier Robert */ 308c0b746e5SOllivier Robert return &rpkt.data[0]; 309c0b746e5SOllivier Robert } 310c0b746e5SOllivier Robert 311c0b746e5SOllivier Robert 312c0b746e5SOllivier Robert /* 313c0b746e5SOllivier Robert * more_pkt - return a data pointer for a new item. 314c0b746e5SOllivier Robert */ 315c0b746e5SOllivier Robert static char * 316c0b746e5SOllivier Robert more_pkt(void) 317c0b746e5SOllivier Robert { 318c0b746e5SOllivier Robert /* 319c0b746e5SOllivier Robert * If we were using the extra buffer, send the packet. 320c0b746e5SOllivier Robert */ 321c0b746e5SOllivier Robert if (usingexbuf) { 322c0b746e5SOllivier Robert #ifdef DEBUG 323c0b746e5SOllivier Robert if (debug > 2) 324c0b746e5SOllivier Robert printf("request: sending pkt\n"); 325c0b746e5SOllivier Robert #endif 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 */ 336c0b746e5SOllivier Robert memmove(&rpkt.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) { 346c0b746e5SOllivier Robert #ifdef DEBUG 347c0b746e5SOllivier Robert if (debug > 3) 348c0b746e5SOllivier Robert printf("request: giving him more data\n"); 349c0b746e5SOllivier Robert #endif 350c0b746e5SOllivier Robert /* 351c0b746e5SOllivier Robert * More room in packet. Give him the 352c0b746e5SOllivier Robert * next address. 353c0b746e5SOllivier Robert */ 354c0b746e5SOllivier Robert return &rpkt.data[databytes]; 355c0b746e5SOllivier Robert } else { 356c0b746e5SOllivier Robert /* 357c0b746e5SOllivier Robert * No room in packet. Give him the extra 358c0b746e5SOllivier Robert * buffer unless this was the last in the sequence. 359c0b746e5SOllivier Robert */ 360c0b746e5SOllivier Robert #ifdef DEBUG 361c0b746e5SOllivier Robert if (debug > 3) 362c0b746e5SOllivier Robert printf("request: into extra buffer\n"); 363c0b746e5SOllivier Robert #endif 364c0b746e5SOllivier Robert if (seqno == MAXSEQ) 365c0b746e5SOllivier Robert return (char *)0; 366c0b746e5SOllivier Robert else { 367c0b746e5SOllivier Robert usingexbuf = 1; 368c0b746e5SOllivier Robert return exbuf; 369c0b746e5SOllivier Robert } 370c0b746e5SOllivier Robert } 371c0b746e5SOllivier Robert } 372c0b746e5SOllivier Robert 373c0b746e5SOllivier Robert 374c0b746e5SOllivier Robert /* 375c0b746e5SOllivier Robert * flush_pkt - we're done, return remaining information. 376c0b746e5SOllivier Robert */ 377c0b746e5SOllivier Robert static void 378c0b746e5SOllivier Robert flush_pkt(void) 379c0b746e5SOllivier Robert { 380c0b746e5SOllivier Robert #ifdef DEBUG 381c0b746e5SOllivier Robert if (debug > 2) 382c0b746e5SOllivier Robert printf("request: flushing packet, %d items\n", nitems); 383c0b746e5SOllivier Robert #endif 384c0b746e5SOllivier Robert /* 385c0b746e5SOllivier Robert * Must send the last packet. If nothing in here and nothing 386c0b746e5SOllivier Robert * has been sent, send an error saying no data to be found. 387c0b746e5SOllivier Robert */ 388c0b746e5SOllivier Robert if (seqno == 0 && nitems == 0) 389c0b746e5SOllivier Robert req_ack(toaddr, frominter, (struct req_pkt *)&rpkt, 390c0b746e5SOllivier Robert INFO_ERR_NODATA); 391c0b746e5SOllivier Robert else { 392c0b746e5SOllivier Robert rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver); 393c0b746e5SOllivier Robert rpkt.auth_seq = AUTH_SEQ(0, seqno); 394c0b746e5SOllivier Robert rpkt.err_nitems = htons((u_short)nitems); 395c0b746e5SOllivier Robert sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt, 396c0b746e5SOllivier Robert RESP_HEADER_SIZE+databytes); 397c0b746e5SOllivier Robert numresppkts++; 398c0b746e5SOllivier Robert } 399c0b746e5SOllivier Robert } 400c0b746e5SOllivier Robert 401c0b746e5SOllivier Robert 402c0b746e5SOllivier Robert 403c0b746e5SOllivier Robert /* 404c0b746e5SOllivier Robert * process_private - process private mode (7) packets 405c0b746e5SOllivier Robert */ 406c0b746e5SOllivier Robert void 407c0b746e5SOllivier Robert process_private( 408c0b746e5SOllivier Robert struct recvbuf *rbufp, 409c0b746e5SOllivier Robert int mod_okay 410c0b746e5SOllivier Robert ) 411c0b746e5SOllivier Robert { 412eb6d21b4SOllivier Robert static u_long quiet_until; 413c0b746e5SOllivier Robert struct req_pkt *inpkt; 414ce265a54SOllivier Robert struct req_pkt_tail *tailinpkt; 4159c2daa00SOllivier Robert struct sockaddr_storage *srcadr; 416c0b746e5SOllivier Robert struct interface *inter; 417c0b746e5SOllivier Robert struct req_proc *proc; 418224ba2bdSOllivier Robert int ec; 4199c2daa00SOllivier Robert short temp_size; 420c0b746e5SOllivier Robert 421c0b746e5SOllivier Robert /* 422c0b746e5SOllivier Robert * Initialize pointers, for convenience 423c0b746e5SOllivier Robert */ 424c0b746e5SOllivier Robert inpkt = (struct req_pkt *)&rbufp->recv_pkt; 425c0b746e5SOllivier Robert srcadr = &rbufp->recv_srcadr; 426c0b746e5SOllivier Robert inter = rbufp->dstadr; 427c0b746e5SOllivier Robert 428c0b746e5SOllivier Robert #ifdef DEBUG 429c0b746e5SOllivier Robert if (debug > 2) 430224ba2bdSOllivier Robert printf("process_private: impl %d req %d\n", 431c0b746e5SOllivier Robert inpkt->implementation, inpkt->request); 432c0b746e5SOllivier Robert #endif 433c0b746e5SOllivier Robert 434c0b746e5SOllivier Robert /* 435c0b746e5SOllivier Robert * Do some sanity checks on the packet. Return a format 436c0b746e5SOllivier Robert * error if it fails. 437c0b746e5SOllivier Robert */ 438224ba2bdSOllivier Robert ec = 0; 439224ba2bdSOllivier Robert if ( (++ec, ISRESPONSE(inpkt->rm_vn_mode)) 440224ba2bdSOllivier Robert || (++ec, ISMORE(inpkt->rm_vn_mode)) 441224ba2bdSOllivier Robert || (++ec, INFO_VERSION(inpkt->rm_vn_mode) > NTP_VERSION) 442224ba2bdSOllivier Robert || (++ec, INFO_VERSION(inpkt->rm_vn_mode) < NTP_OLDVERSION) 443224ba2bdSOllivier Robert || (++ec, INFO_SEQ(inpkt->auth_seq) != 0) 444224ba2bdSOllivier Robert || (++ec, INFO_ERR(inpkt->err_nitems) != 0) 445224ba2bdSOllivier Robert || (++ec, INFO_MBZ(inpkt->mbz_itemsize) != 0) 446ce265a54SOllivier Robert || (++ec, rbufp->recv_length < REQ_LEN_HDR) 447224ba2bdSOllivier Robert ) { 448eb6d21b4SOllivier Robert NLOG(NLOG_SYSEVENT) 449eb6d21b4SOllivier Robert if (current_time >= quiet_until) { 450eb6d21b4SOllivier Robert msyslog(LOG_ERR, 451eb6d21b4SOllivier Robert "process_private: drop test %d" 452eb6d21b4SOllivier Robert " failed, pkt from %s", 453eb6d21b4SOllivier Robert ec, stoa(srcadr)); 454eb6d21b4SOllivier Robert quiet_until = current_time + 60; 455eb6d21b4SOllivier Robert } 456c0b746e5SOllivier Robert return; 457c0b746e5SOllivier Robert } 458c0b746e5SOllivier Robert 459c0b746e5SOllivier Robert reqver = INFO_VERSION(inpkt->rm_vn_mode); 460c0b746e5SOllivier Robert 461c0b746e5SOllivier Robert /* 462c0b746e5SOllivier Robert * Get the appropriate procedure list to search. 463c0b746e5SOllivier Robert */ 464c0b746e5SOllivier Robert if (inpkt->implementation == IMPL_UNIV) 465c0b746e5SOllivier Robert proc = univ_codes; 4669c2daa00SOllivier Robert else if ((inpkt->implementation == IMPL_XNTPD) || 4679c2daa00SOllivier Robert (inpkt->implementation == IMPL_XNTPD_OLD)) 468c0b746e5SOllivier Robert proc = ntp_codes; 469c0b746e5SOllivier Robert else { 470c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_IMPL); 471c0b746e5SOllivier Robert return; 472c0b746e5SOllivier Robert } 473c0b746e5SOllivier Robert 474c0b746e5SOllivier Robert /* 475c0b746e5SOllivier Robert * Search the list for the request codes. If it isn't one 476c0b746e5SOllivier Robert * we know, return an error. 477c0b746e5SOllivier Robert */ 478c0b746e5SOllivier Robert while (proc->request_code != NO_REQUEST) { 479c0b746e5SOllivier Robert if (proc->request_code == (short) inpkt->request) 480c0b746e5SOllivier Robert break; 481c0b746e5SOllivier Robert proc++; 482c0b746e5SOllivier Robert } 483c0b746e5SOllivier Robert if (proc->request_code == NO_REQUEST) { 484c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_REQ); 485c0b746e5SOllivier Robert return; 486c0b746e5SOllivier Robert } 487c0b746e5SOllivier Robert 488c0b746e5SOllivier Robert #ifdef DEBUG 489c0b746e5SOllivier Robert if (debug > 3) 490c0b746e5SOllivier Robert printf("found request in tables\n"); 491c0b746e5SOllivier Robert #endif 492c0b746e5SOllivier Robert 493c0b746e5SOllivier Robert /* 4949c2daa00SOllivier Robert * If we need data, check to see if we have some. If we 4959c2daa00SOllivier Robert * don't, check to see that there is none (picky, picky). 4969c2daa00SOllivier Robert */ 4979c2daa00SOllivier Robert 4989c2daa00SOllivier Robert /* This part is a bit tricky, we want to be sure that the size 4999c2daa00SOllivier Robert * returned is either the old or the new size. We also can find 5009c2daa00SOllivier Robert * out if the client can accept both types of messages this way. 5019c2daa00SOllivier Robert * 5029c2daa00SOllivier Robert * Handle the exception of REQ_CONFIG. It can have two data sizes. 5039c2daa00SOllivier Robert */ 5049c2daa00SOllivier Robert temp_size = INFO_ITEMSIZE(inpkt->mbz_itemsize); 5059c2daa00SOllivier Robert if ((temp_size != proc->sizeofitem && 5069c2daa00SOllivier Robert temp_size != proc->v6_sizeofitem) && 5079c2daa00SOllivier Robert !(inpkt->implementation == IMPL_XNTPD && 5089c2daa00SOllivier Robert inpkt->request == REQ_CONFIG && 5099c2daa00SOllivier Robert temp_size == sizeof(struct old_conf_peer))) { 510ea906c41SOllivier Robert #ifdef DEBUG 5119c2daa00SOllivier Robert if (debug > 2) 5129c2daa00SOllivier Robert printf("process_private: wrong item size, received %d, should be %d or %d\n", 5139c2daa00SOllivier Robert temp_size, proc->sizeofitem, proc->v6_sizeofitem); 514ea906c41SOllivier Robert #endif 5159c2daa00SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 5169c2daa00SOllivier Robert return; 5179c2daa00SOllivier Robert } 5189c2daa00SOllivier Robert if ((proc->sizeofitem != 0) && 5199c2daa00SOllivier Robert ((temp_size * INFO_NITEMS(inpkt->err_nitems)) > 5209c2daa00SOllivier Robert (rbufp->recv_length - REQ_LEN_HDR))) { 521ea906c41SOllivier Robert #ifdef DEBUG 5229c2daa00SOllivier Robert if (debug > 2) 5239c2daa00SOllivier Robert printf("process_private: not enough data\n"); 524ea906c41SOllivier Robert #endif 5259c2daa00SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 5269c2daa00SOllivier Robert return; 5279c2daa00SOllivier Robert } 5289c2daa00SOllivier Robert 5299c2daa00SOllivier Robert switch (inpkt->implementation) { 5309c2daa00SOllivier Robert case IMPL_XNTPD: 5319c2daa00SOllivier Robert client_v6_capable = 1; 5329c2daa00SOllivier Robert break; 5339c2daa00SOllivier Robert case IMPL_XNTPD_OLD: 5349c2daa00SOllivier Robert client_v6_capable = 0; 5359c2daa00SOllivier Robert break; 5369c2daa00SOllivier Robert default: 5379c2daa00SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 5389c2daa00SOllivier Robert return; 5399c2daa00SOllivier Robert } 5409c2daa00SOllivier Robert 5419c2daa00SOllivier Robert /* 542c0b746e5SOllivier Robert * If we need to authenticate, do so. Note that an 543c0b746e5SOllivier Robert * authenticatable packet must include a mac field, must 544c0b746e5SOllivier Robert * have used key info_auth_keyid and must have included 545c0b746e5SOllivier Robert * a time stamp in the appropriate field. The time stamp 546c0b746e5SOllivier Robert * must be within INFO_TS_MAXSKEW of the receive 547c0b746e5SOllivier Robert * time stamp. 548c0b746e5SOllivier Robert */ 549c0b746e5SOllivier Robert if (proc->needs_auth && sys_authenticate) { 550c0b746e5SOllivier Robert l_fp ftmp; 551c0b746e5SOllivier Robert double dtemp; 552c0b746e5SOllivier Robert 5539c2daa00SOllivier Robert if (rbufp->recv_length < (int)((REQ_LEN_HDR + 554ce265a54SOllivier Robert (INFO_ITEMSIZE(inpkt->mbz_itemsize) * 555ce265a54SOllivier Robert INFO_NITEMS(inpkt->err_nitems)) 5569c2daa00SOllivier Robert + sizeof(struct req_pkt_tail)))) { 557ce265a54SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 558ce265a54SOllivier Robert } 559ce265a54SOllivier Robert tailinpkt = (struct req_pkt_tail *)((char *)&rbufp->recv_pkt + 560ce265a54SOllivier Robert rbufp->recv_length - sizeof(struct req_pkt_tail)); 561ce265a54SOllivier Robert 562c0b746e5SOllivier Robert /* 563c0b746e5SOllivier Robert * If this guy is restricted from doing this, don't let him 564c0b746e5SOllivier Robert * If wrong key was used, or packet doesn't have mac, return. 565c0b746e5SOllivier Robert */ 566c0b746e5SOllivier Robert if (!INFO_IS_AUTH(inpkt->auth_seq) || info_auth_keyid == 0 567ce265a54SOllivier Robert || ntohl(tailinpkt->keyid) != info_auth_keyid) { 568c0b746e5SOllivier Robert #ifdef DEBUG 569c0b746e5SOllivier Robert if (debug > 4) 570c0b746e5SOllivier Robert printf("failed auth %d info_auth_keyid %lu pkt keyid %lu\n", 571c0b746e5SOllivier Robert INFO_IS_AUTH(inpkt->auth_seq), 572c0b746e5SOllivier Robert (u_long)info_auth_keyid, 573ce265a54SOllivier Robert (u_long)ntohl(tailinpkt->keyid)); 5749c2daa00SOllivier Robert msyslog(LOG_DEBUG, 5759c2daa00SOllivier Robert "process_private: failed auth %d info_auth_keyid %lu pkt keyid %lu\n", 5769c2daa00SOllivier Robert INFO_IS_AUTH(inpkt->auth_seq), 5779c2daa00SOllivier Robert (u_long)info_auth_keyid, 5789c2daa00SOllivier Robert (u_long)ntohl(tailinpkt->keyid)); 579c0b746e5SOllivier Robert #endif 580c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 581c0b746e5SOllivier Robert return; 582c0b746e5SOllivier Robert } 583c0b746e5SOllivier Robert if (rbufp->recv_length > REQ_LEN_MAC) { 584c0b746e5SOllivier Robert #ifdef DEBUG 585c0b746e5SOllivier Robert if (debug > 4) 586c0b746e5SOllivier Robert printf("bad pkt length %d\n", 587c0b746e5SOllivier Robert rbufp->recv_length); 588c0b746e5SOllivier Robert #endif 589224ba2bdSOllivier Robert msyslog(LOG_ERR, "process_private: bad pkt length %d", 590224ba2bdSOllivier Robert rbufp->recv_length); 591c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 592c0b746e5SOllivier Robert return; 593c0b746e5SOllivier Robert } 594c0b746e5SOllivier Robert if (!mod_okay || !authhavekey(info_auth_keyid)) { 595c0b746e5SOllivier Robert #ifdef DEBUG 596c0b746e5SOllivier Robert if (debug > 4) 597c0b746e5SOllivier Robert printf("failed auth mod_okay %d\n", mod_okay); 5989c2daa00SOllivier Robert msyslog(LOG_DEBUG, 5999c2daa00SOllivier Robert "process_private: failed auth mod_okay %d\n", 6009c2daa00SOllivier Robert mod_okay); 601c0b746e5SOllivier Robert #endif 602c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 603c0b746e5SOllivier Robert return; 604c0b746e5SOllivier Robert } 605c0b746e5SOllivier Robert 606c0b746e5SOllivier Robert /* 607c0b746e5SOllivier Robert * calculate absolute time difference between xmit time stamp 608c0b746e5SOllivier Robert * and receive time stamp. If too large, too bad. 609c0b746e5SOllivier Robert */ 610ce265a54SOllivier Robert NTOHL_FP(&tailinpkt->tstamp, &ftmp); 611c0b746e5SOllivier Robert L_SUB(&ftmp, &rbufp->recv_time); 612c0b746e5SOllivier Robert LFPTOD(&ftmp, dtemp); 613c0b746e5SOllivier Robert if (fabs(dtemp) >= INFO_TS_MAXSKEW) { 614c0b746e5SOllivier Robert /* 615c0b746e5SOllivier Robert * He's a loser. Tell him. 616c0b746e5SOllivier Robert */ 6179c2daa00SOllivier Robert #ifdef DEBUG 6189c2daa00SOllivier Robert if (debug > 4) 6199c2daa00SOllivier Robert printf("xmit/rcv timestamp delta > INFO_TS_MAXSKEW\n"); 6209c2daa00SOllivier Robert #endif 621c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 622c0b746e5SOllivier Robert return; 623c0b746e5SOllivier Robert } 624c0b746e5SOllivier Robert 625c0b746e5SOllivier Robert /* 626c0b746e5SOllivier Robert * So far so good. See if decryption works out okay. 627c0b746e5SOllivier Robert */ 628c0b746e5SOllivier Robert if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt, 629ce265a54SOllivier Robert rbufp->recv_length - sizeof(struct req_pkt_tail) + 630ce265a54SOllivier Robert REQ_LEN_HDR, sizeof(struct req_pkt_tail) - REQ_LEN_HDR)) { 6319c2daa00SOllivier Robert #ifdef DEBUG 6329c2daa00SOllivier Robert if (debug > 4) 6339c2daa00SOllivier Robert printf("authdecrypt failed\n"); 6349c2daa00SOllivier Robert #endif 635c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 636c0b746e5SOllivier Robert return; 637c0b746e5SOllivier Robert } 638c0b746e5SOllivier Robert } 639c0b746e5SOllivier Robert 640c0b746e5SOllivier Robert #ifdef DEBUG 641c0b746e5SOllivier Robert if (debug > 3) 642c0b746e5SOllivier Robert printf("process_private: all okay, into handler\n"); 643c0b746e5SOllivier Robert #endif 644c0b746e5SOllivier Robert 645c0b746e5SOllivier Robert /* 646c0b746e5SOllivier Robert * Packet is okay. Call the handler to send him data. 647c0b746e5SOllivier Robert */ 648c0b746e5SOllivier Robert (proc->handler)(srcadr, inter, inpkt); 649c0b746e5SOllivier Robert } 650c0b746e5SOllivier Robert 651c0b746e5SOllivier Robert 652c0b746e5SOllivier Robert /* 653c0b746e5SOllivier Robert * peer_list - send a list of the peers 654c0b746e5SOllivier Robert */ 655c0b746e5SOllivier Robert static void 656c0b746e5SOllivier Robert peer_list( 6579c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 658c0b746e5SOllivier Robert struct interface *inter, 659c0b746e5SOllivier Robert struct req_pkt *inpkt 660c0b746e5SOllivier Robert ) 661c0b746e5SOllivier Robert { 662c0b746e5SOllivier Robert register struct info_peer_list *ip; 663c0b746e5SOllivier Robert register struct peer *pp; 664c0b746e5SOllivier Robert register int i; 6659c2daa00SOllivier Robert register int skip = 0; 666c0b746e5SOllivier Robert 667c0b746e5SOllivier Robert ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt, 6689c2daa00SOllivier Robert v6sizeof(struct info_peer_list)); 669ea906c41SOllivier Robert for (i = 0; i < NTP_HASH_SIZE && ip != 0; i++) { 670c0b746e5SOllivier Robert pp = peer_hash[i]; 671c0b746e5SOllivier Robert while (pp != 0 && ip != 0) { 6729c2daa00SOllivier Robert if (pp->srcadr.ss_family == AF_INET6) { 6739c2daa00SOllivier Robert if (client_v6_capable) { 6749c2daa00SOllivier Robert ip->addr6 = GET_INADDR6(pp->srcadr); 6759c2daa00SOllivier Robert ip->v6_flag = 1; 6769c2daa00SOllivier Robert skip = 0; 6779c2daa00SOllivier Robert } else { 6789c2daa00SOllivier Robert skip = 1; 6799c2daa00SOllivier Robert break; 6809c2daa00SOllivier Robert } 6819c2daa00SOllivier Robert } else { 6829c2daa00SOllivier Robert ip->addr = GET_INADDR(pp->srcadr); 6839c2daa00SOllivier Robert if (client_v6_capable) 6849c2daa00SOllivier Robert ip->v6_flag = 0; 6859c2daa00SOllivier Robert skip = 0; 6869c2daa00SOllivier Robert } 6879c2daa00SOllivier Robert 6889c2daa00SOllivier Robert if(!skip) { 6899c2daa00SOllivier Robert ip->port = NSRCPORT(&pp->srcadr); 690c0b746e5SOllivier Robert ip->hmode = pp->hmode; 691c0b746e5SOllivier Robert ip->flags = 0; 692c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 693c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 694c0b746e5SOllivier Robert if (pp == sys_peer) 695c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 696c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 697c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 698c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 699c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 700c0b746e5SOllivier Robert ip = (struct info_peer_list *)more_pkt(); 7019c2daa00SOllivier Robert } 702c0b746e5SOllivier Robert pp = pp->next; 703c0b746e5SOllivier Robert } 704c0b746e5SOllivier Robert } 705c0b746e5SOllivier Robert flush_pkt(); 706c0b746e5SOllivier Robert } 707c0b746e5SOllivier Robert 708c0b746e5SOllivier Robert 709c0b746e5SOllivier Robert /* 710c0b746e5SOllivier Robert * peer_list_sum - return extended peer list 711c0b746e5SOllivier Robert */ 712c0b746e5SOllivier Robert static void 713c0b746e5SOllivier Robert peer_list_sum( 7149c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 715c0b746e5SOllivier Robert struct interface *inter, 716c0b746e5SOllivier Robert struct req_pkt *inpkt 717c0b746e5SOllivier Robert ) 718c0b746e5SOllivier Robert { 719c0b746e5SOllivier Robert register struct info_peer_summary *ips; 720c0b746e5SOllivier Robert register struct peer *pp; 721c0b746e5SOllivier Robert register int i; 722c0b746e5SOllivier Robert l_fp ltmp; 7239c2daa00SOllivier Robert register int skip; 724c0b746e5SOllivier Robert 725c0b746e5SOllivier Robert #ifdef DEBUG 726c0b746e5SOllivier Robert if (debug > 2) 727c0b746e5SOllivier Robert printf("wants peer list summary\n"); 728c0b746e5SOllivier Robert #endif 729c0b746e5SOllivier Robert ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt, 7309c2daa00SOllivier Robert v6sizeof(struct info_peer_summary)); 731ea906c41SOllivier Robert for (i = 0; i < NTP_HASH_SIZE && ips != 0; i++) { 732c0b746e5SOllivier Robert pp = peer_hash[i]; 733c0b746e5SOllivier Robert while (pp != 0 && ips != 0) { 734c0b746e5SOllivier Robert #ifdef DEBUG 735c0b746e5SOllivier Robert if (debug > 3) 736c0b746e5SOllivier Robert printf("sum: got one\n"); 737c0b746e5SOllivier Robert #endif 7389c2daa00SOllivier Robert /* 7399c2daa00SOllivier Robert * Be careful here not to return v6 peers when we 7409c2daa00SOllivier Robert * want only v4. 7419c2daa00SOllivier Robert */ 7429c2daa00SOllivier Robert if (pp->srcadr.ss_family == AF_INET6) { 7439c2daa00SOllivier Robert if (client_v6_capable) { 7449c2daa00SOllivier Robert ips->srcadr6 = GET_INADDR6(pp->srcadr); 7459c2daa00SOllivier Robert ips->v6_flag = 1; 746ea906c41SOllivier Robert if (pp->dstadr) 7479c2daa00SOllivier Robert ips->dstadr6 = GET_INADDR6(pp->dstadr->sin); 748ea906c41SOllivier Robert else 749ea906c41SOllivier Robert memset(&ips->dstadr6, 0, sizeof(ips->dstadr6)); 7509c2daa00SOllivier Robert skip = 0; 7519c2daa00SOllivier Robert } else { 7529c2daa00SOllivier Robert skip = 1; 7539c2daa00SOllivier Robert break; 7549c2daa00SOllivier Robert } 7559c2daa00SOllivier Robert } else { 7569c2daa00SOllivier Robert ips->srcadr = GET_INADDR(pp->srcadr); 7579c2daa00SOllivier Robert if (client_v6_capable) 7589c2daa00SOllivier Robert ips->v6_flag = 0; 7599c2daa00SOllivier Robert /* XXX PDM This code is buggy. Need to replace with a straightforward assignment */ 760ea906c41SOllivier Robert 761ea906c41SOllivier Robert if (pp->dstadr) 7629c2daa00SOllivier Robert ips->dstadr = (pp->processed) ? 7639c2daa00SOllivier Robert pp->cast_flags == MDF_BCAST ? 7649c2daa00SOllivier Robert GET_INADDR(pp->dstadr->bcast): 7659c2daa00SOllivier Robert pp->cast_flags ? 7669c2daa00SOllivier Robert GET_INADDR(pp->dstadr->sin) ? 7679c2daa00SOllivier Robert GET_INADDR(pp->dstadr->sin): 7689c2daa00SOllivier Robert GET_INADDR(pp->dstadr->bcast): 7699c2daa00SOllivier Robert 1 : GET_INADDR(pp->dstadr->sin); 770ea906c41SOllivier Robert else 771ea906c41SOllivier Robert memset(&ips->dstadr, 0, sizeof(ips->dstadr)); 7729c2daa00SOllivier Robert 7739c2daa00SOllivier Robert skip = 0; 7749c2daa00SOllivier Robert } 775ea906c41SOllivier Robert 7769c2daa00SOllivier Robert if (!skip){ 7779c2daa00SOllivier Robert ips->srcport = NSRCPORT(&pp->srcadr); 778c0b746e5SOllivier Robert ips->stratum = pp->stratum; 779c0b746e5SOllivier Robert ips->hpoll = pp->hpoll; 780c0b746e5SOllivier Robert ips->ppoll = pp->ppoll; 781c0b746e5SOllivier Robert ips->reach = pp->reach; 782c0b746e5SOllivier Robert ips->flags = 0; 783c0b746e5SOllivier Robert if (pp == sys_peer) 784c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SYSPEER; 785c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 786c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_CONFIG; 787c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 788c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_REFCLOCK; 789c0b746e5SOllivier Robert if (pp->flags & FLAG_AUTHENABLE) 790c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_AUTHENABLE; 791c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 792c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_PREFER; 793c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 794c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_BURST; 795c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 796c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SEL_CANDIDATE; 797c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 798c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SHORTLIST; 799c0b746e5SOllivier Robert ips->hmode = pp->hmode; 800c0b746e5SOllivier Robert ips->delay = HTONS_FP(DTOFP(pp->delay)); 801c0b746e5SOllivier Robert DTOLFP(pp->offset, <mp); 802c0b746e5SOllivier Robert HTONL_FP(<mp, &ips->offset); 803ea906c41SOllivier Robert ips->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); 8049c2daa00SOllivier Robert } 805c0b746e5SOllivier Robert pp = pp->next; 806c0b746e5SOllivier Robert ips = (struct info_peer_summary *)more_pkt(); 807c0b746e5SOllivier Robert } 808c0b746e5SOllivier Robert } 809c0b746e5SOllivier Robert flush_pkt(); 810c0b746e5SOllivier Robert } 811c0b746e5SOllivier Robert 812c0b746e5SOllivier Robert 813c0b746e5SOllivier Robert /* 814c0b746e5SOllivier Robert * peer_info - send information for one or more peers 815c0b746e5SOllivier Robert */ 816c0b746e5SOllivier Robert static void 817c0b746e5SOllivier Robert peer_info ( 8189c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 819c0b746e5SOllivier Robert struct interface *inter, 820c0b746e5SOllivier Robert struct req_pkt *inpkt 821c0b746e5SOllivier Robert ) 822c0b746e5SOllivier Robert { 823c0b746e5SOllivier Robert register struct info_peer_list *ipl; 824c0b746e5SOllivier Robert register struct peer *pp; 825c0b746e5SOllivier Robert register struct info_peer *ip; 826c0b746e5SOllivier Robert register int items; 827c0b746e5SOllivier Robert register int i, j; 8289c2daa00SOllivier Robert struct sockaddr_storage addr; 829c0b746e5SOllivier Robert extern struct peer *sys_peer; 830c0b746e5SOllivier Robert l_fp ltmp; 831c0b746e5SOllivier Robert 832c0b746e5SOllivier Robert memset((char *)&addr, 0, sizeof addr); 833c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 834c0b746e5SOllivier Robert ipl = (struct info_peer_list *) inpkt->data; 8359c2daa00SOllivier Robert 836c0b746e5SOllivier Robert ip = (struct info_peer *)prepare_pkt(srcadr, inter, inpkt, 8379c2daa00SOllivier Robert v6sizeof(struct info_peer)); 838c0b746e5SOllivier Robert while (items-- > 0 && ip != 0) { 8399c2daa00SOllivier Robert memset((char *)&addr, 0, sizeof(addr)); 8409c2daa00SOllivier Robert NSRCPORT(&addr) = ipl->port; 8419c2daa00SOllivier Robert if (client_v6_capable && ipl->v6_flag != 0) { 8429c2daa00SOllivier Robert addr.ss_family = AF_INET6; 8439c2daa00SOllivier Robert GET_INADDR6(addr) = ipl->addr6; 8449c2daa00SOllivier Robert } else { 8459c2daa00SOllivier Robert addr.ss_family = AF_INET; 8469c2daa00SOllivier Robert GET_INADDR(addr) = ipl->addr; 8479c2daa00SOllivier Robert } 8489c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 8499c2daa00SOllivier Robert addr.ss_len = SOCKLEN(&addr); 8509c2daa00SOllivier Robert #endif 851c0b746e5SOllivier Robert ipl++; 852c0b746e5SOllivier Robert if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0) 853c0b746e5SOllivier Robert continue; 8549c2daa00SOllivier Robert if (pp->srcadr.ss_family == AF_INET6) { 855ea906c41SOllivier Robert if (pp->dstadr) 8569c2daa00SOllivier Robert ip->dstadr6 = pp->cast_flags == MDF_BCAST ? 8579c2daa00SOllivier Robert GET_INADDR6(pp->dstadr->bcast) : 8589c2daa00SOllivier Robert GET_INADDR6(pp->dstadr->sin); 859ea906c41SOllivier Robert else 860ea906c41SOllivier Robert memset(&ip->dstadr6, 0, sizeof(ip->dstadr6)); 861ea906c41SOllivier Robert 8629c2daa00SOllivier Robert ip->srcadr6 = GET_INADDR6(pp->srcadr); 8639c2daa00SOllivier Robert ip->v6_flag = 1; 8649c2daa00SOllivier Robert } else { 8659c2daa00SOllivier Robert /* XXX PDM This code is buggy. Need to replace with a straightforward assignment */ 866ea906c41SOllivier Robert if (pp->dstadr) 8679c2daa00SOllivier Robert ip->dstadr = (pp->processed) ? 8689c2daa00SOllivier Robert pp->cast_flags == MDF_BCAST ? 8699c2daa00SOllivier Robert GET_INADDR(pp->dstadr->bcast): 8709c2daa00SOllivier Robert pp->cast_flags ? 8719c2daa00SOllivier Robert GET_INADDR(pp->dstadr->sin) ? 8729c2daa00SOllivier Robert GET_INADDR(pp->dstadr->sin): 8739c2daa00SOllivier Robert GET_INADDR(pp->dstadr->bcast): 8749c2daa00SOllivier Robert 2 : GET_INADDR(pp->dstadr->sin); 875ea906c41SOllivier Robert else 876ea906c41SOllivier Robert memset(&ip->dstadr, 0, sizeof(ip->dstadr)); 8779c2daa00SOllivier Robert 8789c2daa00SOllivier Robert ip->srcadr = GET_INADDR(pp->srcadr); 8799c2daa00SOllivier Robert if (client_v6_capable) 8809c2daa00SOllivier Robert ip->v6_flag = 0; 8819c2daa00SOllivier Robert } 882c0b746e5SOllivier Robert ip->srcport = NSRCPORT(&pp->srcadr); 883c0b746e5SOllivier Robert ip->flags = 0; 884c0b746e5SOllivier Robert if (pp == sys_peer) 885c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 886c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 887c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 888c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 889c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_REFCLOCK; 890c0b746e5SOllivier Robert if (pp->flags & FLAG_AUTHENABLE) 891c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_AUTHENABLE; 892c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 893c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_PREFER; 894c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 895c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_BURST; 896c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 897c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 898c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 899c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 900c0b746e5SOllivier Robert ip->leap = pp->leap; 901c0b746e5SOllivier Robert ip->hmode = pp->hmode; 902c0b746e5SOllivier Robert ip->keyid = pp->keyid; 903c0b746e5SOllivier Robert ip->stratum = pp->stratum; 904c0b746e5SOllivier Robert ip->ppoll = pp->ppoll; 905c0b746e5SOllivier Robert ip->hpoll = pp->hpoll; 906c0b746e5SOllivier Robert ip->precision = pp->precision; 907c0b746e5SOllivier Robert ip->version = pp->version; 908c0b746e5SOllivier Robert ip->reach = pp->reach; 9099c2daa00SOllivier Robert ip->unreach = (u_char) pp->unreach; 910c0b746e5SOllivier Robert ip->flash = (u_char)pp->flash; 9119c2daa00SOllivier Robert ip->flash2 = (u_short) pp->flash; 912c0b746e5SOllivier Robert ip->estbdelay = HTONS_FP(DTOFP(pp->estbdelay)); 913c0b746e5SOllivier Robert ip->ttl = pp->ttl; 914c0b746e5SOllivier Robert ip->associd = htons(pp->associd); 915c0b746e5SOllivier Robert ip->rootdelay = HTONS_FP(DTOUFP(pp->rootdelay)); 916c0b746e5SOllivier Robert ip->rootdispersion = HTONS_FP(DTOUFP(pp->rootdispersion)); 917c0b746e5SOllivier Robert ip->refid = pp->refid; 918c0b746e5SOllivier Robert HTONL_FP(&pp->reftime, &ip->reftime); 919c0b746e5SOllivier Robert HTONL_FP(&pp->org, &ip->org); 920c0b746e5SOllivier Robert HTONL_FP(&pp->rec, &ip->rec); 921c0b746e5SOllivier Robert HTONL_FP(&pp->xmt, &ip->xmt); 922c0b746e5SOllivier Robert j = pp->filter_nextpt - 1; 923c0b746e5SOllivier Robert for (i = 0; i < NTP_SHIFT; i++, j--) { 924c0b746e5SOllivier Robert if (j < 0) 925c0b746e5SOllivier Robert j = NTP_SHIFT-1; 926c0b746e5SOllivier Robert ip->filtdelay[i] = HTONS_FP(DTOFP(pp->filter_delay[j])); 927c0b746e5SOllivier Robert DTOLFP(pp->filter_offset[j], <mp); 928c0b746e5SOllivier Robert HTONL_FP(<mp, &ip->filtoffset[i]); 9299c2daa00SOllivier Robert ip->order[i] = (u_char)((pp->filter_nextpt+NTP_SHIFT-1) 9309c2daa00SOllivier Robert - pp->filter_order[i]); 931c0b746e5SOllivier Robert if (ip->order[i] >= NTP_SHIFT) 932c0b746e5SOllivier Robert ip->order[i] -= NTP_SHIFT; 933c0b746e5SOllivier Robert } 934c0b746e5SOllivier Robert DTOLFP(pp->offset, <mp); 935c0b746e5SOllivier Robert HTONL_FP(<mp, &ip->offset); 936c0b746e5SOllivier Robert ip->delay = HTONS_FP(DTOFP(pp->delay)); 937c0b746e5SOllivier Robert ip->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); 938224ba2bdSOllivier Robert ip->selectdisp = HTONS_FP(DTOUFP(SQRT(pp->jitter))); 939c0b746e5SOllivier Robert ip = (struct info_peer *)more_pkt(); 940c0b746e5SOllivier Robert } 941c0b746e5SOllivier Robert flush_pkt(); 942c0b746e5SOllivier Robert } 943c0b746e5SOllivier Robert 944c0b746e5SOllivier Robert 945c0b746e5SOllivier Robert /* 946c0b746e5SOllivier Robert * peer_stats - send statistics for one or more peers 947c0b746e5SOllivier Robert */ 948c0b746e5SOllivier Robert static void 949c0b746e5SOllivier Robert peer_stats ( 9509c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 951c0b746e5SOllivier Robert struct interface *inter, 952c0b746e5SOllivier Robert struct req_pkt *inpkt 953c0b746e5SOllivier Robert ) 954c0b746e5SOllivier Robert { 955c0b746e5SOllivier Robert register struct info_peer_list *ipl; 956c0b746e5SOllivier Robert register struct peer *pp; 957c0b746e5SOllivier Robert register struct info_peer_stats *ip; 958c0b746e5SOllivier Robert register int items; 9599c2daa00SOllivier Robert struct sockaddr_storage addr; 960c0b746e5SOllivier Robert extern struct peer *sys_peer; 961c0b746e5SOllivier Robert 962ea906c41SOllivier Robert #ifdef DEBUG 963ea906c41SOllivier Robert if (debug) 9649c2daa00SOllivier Robert printf("peer_stats: called\n"); 965ea906c41SOllivier Robert #endif 966c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 967c0b746e5SOllivier Robert ipl = (struct info_peer_list *) inpkt->data; 968c0b746e5SOllivier Robert ip = (struct info_peer_stats *)prepare_pkt(srcadr, inter, inpkt, 9699c2daa00SOllivier Robert v6sizeof(struct info_peer_stats)); 970c0b746e5SOllivier Robert while (items-- > 0 && ip != 0) { 9719c2daa00SOllivier Robert memset((char *)&addr, 0, sizeof(addr)); 9729c2daa00SOllivier Robert NSRCPORT(&addr) = ipl->port; 9739c2daa00SOllivier Robert if (client_v6_capable && ipl->v6_flag) { 9749c2daa00SOllivier Robert addr.ss_family = AF_INET6; 9759c2daa00SOllivier Robert GET_INADDR6(addr) = ipl->addr6; 9769c2daa00SOllivier Robert } else { 9779c2daa00SOllivier Robert addr.ss_family = AF_INET; 9789c2daa00SOllivier Robert GET_INADDR(addr) = ipl->addr; 9799c2daa00SOllivier Robert } 9809c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 9819c2daa00SOllivier Robert addr.ss_len = SOCKLEN(&addr); 9829c2daa00SOllivier Robert #endif 983ea906c41SOllivier Robert #ifdef DEBUG 984ea906c41SOllivier Robert if (debug) 9859c2daa00SOllivier Robert printf("peer_stats: looking for %s, %d, %d\n", stoa(&addr), 9869c2daa00SOllivier Robert ipl->port, ((struct sockaddr_in6 *)&addr)->sin6_port); 987ea906c41SOllivier Robert #endif 9889c2daa00SOllivier Robert ipl = (struct info_peer_list *)((char *)ipl + 9899c2daa00SOllivier Robert INFO_ITEMSIZE(inpkt->mbz_itemsize)); 9909c2daa00SOllivier Robert 991c0b746e5SOllivier Robert if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0) 992c0b746e5SOllivier Robert continue; 993ea906c41SOllivier Robert #ifdef DEBUG 994ea906c41SOllivier Robert if (debug) 9959c2daa00SOllivier Robert printf("peer_stats: found %s\n", stoa(&addr)); 996ea906c41SOllivier Robert #endif 9979c2daa00SOllivier Robert if (pp->srcadr.ss_family == AF_INET) { 998ea906c41SOllivier Robert if (pp->dstadr) 9999c2daa00SOllivier Robert ip->dstadr = (pp->processed) ? 10009c2daa00SOllivier Robert pp->cast_flags == MDF_BCAST ? 10019c2daa00SOllivier Robert GET_INADDR(pp->dstadr->bcast): 10029c2daa00SOllivier Robert pp->cast_flags ? 10039c2daa00SOllivier Robert GET_INADDR(pp->dstadr->sin) ? 10049c2daa00SOllivier Robert GET_INADDR(pp->dstadr->sin): 10059c2daa00SOllivier Robert GET_INADDR(pp->dstadr->bcast): 10069c2daa00SOllivier Robert 3 : 7; 1007ea906c41SOllivier Robert else 1008ea906c41SOllivier Robert memset(&ip->dstadr, 0, sizeof(ip->dstadr)); 1009ea906c41SOllivier Robert 10109c2daa00SOllivier Robert ip->srcadr = GET_INADDR(pp->srcadr); 10119c2daa00SOllivier Robert if (client_v6_capable) 10129c2daa00SOllivier Robert ip->v6_flag = 0; 10139c2daa00SOllivier Robert } else { 1014ea906c41SOllivier Robert if (pp->dstadr) 10159c2daa00SOllivier Robert ip->dstadr6 = pp->cast_flags == MDF_BCAST ? 10169c2daa00SOllivier Robert GET_INADDR6(pp->dstadr->bcast): 10179c2daa00SOllivier Robert GET_INADDR6(pp->dstadr->sin); 1018ea906c41SOllivier Robert else 1019ea906c41SOllivier Robert memset(&ip->dstadr6, 0, sizeof(ip->dstadr6)); 1020ea906c41SOllivier Robert 10219c2daa00SOllivier Robert ip->srcadr6 = GET_INADDR6(pp->srcadr); 10229c2daa00SOllivier Robert ip->v6_flag = 1; 10239c2daa00SOllivier Robert } 1024c0b746e5SOllivier Robert ip->srcport = NSRCPORT(&pp->srcadr); 1025c0b746e5SOllivier Robert ip->flags = 0; 1026c0b746e5SOllivier Robert if (pp == sys_peer) 1027c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 1028c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 1029c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 1030c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 1031c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_REFCLOCK; 1032c0b746e5SOllivier Robert if (pp->flags & FLAG_AUTHENABLE) 1033c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_AUTHENABLE; 1034c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 1035c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_PREFER; 1036c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 1037c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_BURST; 1038ea906c41SOllivier Robert if (pp->flags & FLAG_IBURST) 1039ea906c41SOllivier Robert ip->flags |= INFO_FLAG_IBURST; 1040c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 1041c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 1042c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 1043c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 1044ea906c41SOllivier Robert ip->flags = htons(ip->flags); 1045c0b746e5SOllivier Robert ip->timereceived = htonl((u_int32)(current_time - pp->timereceived)); 1046c0b746e5SOllivier Robert ip->timetosend = htonl(pp->nextdate - current_time); 1047c0b746e5SOllivier Robert ip->timereachable = htonl((u_int32)(current_time - pp->timereachable)); 1048c0b746e5SOllivier Robert ip->sent = htonl((u_int32)(pp->sent)); 1049c0b746e5SOllivier Robert ip->processed = htonl((u_int32)(pp->processed)); 1050c0b746e5SOllivier Robert ip->badauth = htonl((u_int32)(pp->badauth)); 1051c0b746e5SOllivier Robert ip->bogusorg = htonl((u_int32)(pp->bogusorg)); 1052c0b746e5SOllivier Robert ip->oldpkt = htonl((u_int32)(pp->oldpkt)); 1053c0b746e5SOllivier Robert ip->seldisp = htonl((u_int32)(pp->seldisptoolarge)); 1054c0b746e5SOllivier Robert ip->selbroken = htonl((u_int32)(pp->selbroken)); 1055c0b746e5SOllivier Robert ip->candidate = pp->status; 1056c0b746e5SOllivier Robert ip = (struct info_peer_stats *)more_pkt(); 1057c0b746e5SOllivier Robert } 1058c0b746e5SOllivier Robert flush_pkt(); 1059c0b746e5SOllivier Robert } 1060c0b746e5SOllivier Robert 1061c0b746e5SOllivier Robert 1062c0b746e5SOllivier Robert /* 1063c0b746e5SOllivier Robert * sys_info - return system info 1064c0b746e5SOllivier Robert */ 1065c0b746e5SOllivier Robert static void 1066c0b746e5SOllivier Robert sys_info( 10679c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1068c0b746e5SOllivier Robert struct interface *inter, 1069c0b746e5SOllivier Robert struct req_pkt *inpkt 1070c0b746e5SOllivier Robert ) 1071c0b746e5SOllivier Robert { 1072c0b746e5SOllivier Robert register struct info_sys *is; 1073c0b746e5SOllivier Robert 1074c0b746e5SOllivier Robert is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt, 10759c2daa00SOllivier Robert v6sizeof(struct info_sys)); 1076c0b746e5SOllivier Robert 1077c0b746e5SOllivier Robert if (sys_peer != 0) { 10789c2daa00SOllivier Robert if (sys_peer->srcadr.ss_family == AF_INET) { 10799c2daa00SOllivier Robert is->peer = GET_INADDR(sys_peer->srcadr); 10809c2daa00SOllivier Robert if (client_v6_capable) 10819c2daa00SOllivier Robert is->v6_flag = 0; 10829c2daa00SOllivier Robert } else if (client_v6_capable) { 10839c2daa00SOllivier Robert is->peer6 = GET_INADDR6(sys_peer->srcadr); 10849c2daa00SOllivier Robert is->v6_flag = 1; 10859c2daa00SOllivier Robert } 1086c0b746e5SOllivier Robert is->peer_mode = sys_peer->hmode; 1087c0b746e5SOllivier Robert } else { 1088c0b746e5SOllivier Robert is->peer = 0; 10899c2daa00SOllivier Robert if (client_v6_capable) { 10909c2daa00SOllivier Robert is->v6_flag = 0; 10919c2daa00SOllivier Robert } 1092c0b746e5SOllivier Robert is->peer_mode = 0; 1093c0b746e5SOllivier Robert } 10949c2daa00SOllivier Robert 1095c0b746e5SOllivier Robert is->leap = sys_leap; 1096c0b746e5SOllivier Robert is->stratum = sys_stratum; 1097c0b746e5SOllivier Robert is->precision = sys_precision; 1098c0b746e5SOllivier Robert is->rootdelay = htonl(DTOFP(sys_rootdelay)); 1099c0b746e5SOllivier Robert is->rootdispersion = htonl(DTOUFP(sys_rootdispersion)); 1100224ba2bdSOllivier Robert is->frequency = htonl(DTOFP(sys_jitter)); 1101ea906c41SOllivier Robert is->stability = htonl(DTOUFP(clock_stability)); 1102c0b746e5SOllivier Robert is->refid = sys_refid; 1103c0b746e5SOllivier Robert HTONL_FP(&sys_reftime, &is->reftime); 1104c0b746e5SOllivier Robert 1105c0b746e5SOllivier Robert is->poll = sys_poll; 1106c0b746e5SOllivier Robert 1107c0b746e5SOllivier Robert is->flags = 0; 1108c0b746e5SOllivier Robert if (sys_authenticate) 1109c0b746e5SOllivier Robert is->flags |= INFO_FLAG_AUTHENTICATE; 1110ce265a54SOllivier Robert if (sys_bclient) 1111ce265a54SOllivier Robert is->flags |= INFO_FLAG_BCLIENT; 1112ce265a54SOllivier Robert #ifdef REFCLOCK 1113ce265a54SOllivier Robert if (cal_enable) 1114ce265a54SOllivier Robert is->flags |= INFO_FLAG_CAL; 1115ce265a54SOllivier Robert #endif /* REFCLOCK */ 1116c0b746e5SOllivier Robert if (kern_enable) 1117c0b746e5SOllivier Robert is->flags |= INFO_FLAG_KERNEL; 1118c0b746e5SOllivier Robert if (mon_enabled != MON_OFF) 1119c0b746e5SOllivier Robert is->flags |= INFO_FLAG_MONITOR; 1120ce265a54SOllivier Robert if (ntp_enable) 1121ce265a54SOllivier Robert is->flags |= INFO_FLAG_NTP; 1122ce265a54SOllivier Robert if (pps_enable) 1123ce265a54SOllivier Robert is->flags |= INFO_FLAG_PPS_SYNC; 1124c0b746e5SOllivier Robert if (stats_control) 1125c0b746e5SOllivier Robert is->flags |= INFO_FLAG_FILEGEN; 1126c0b746e5SOllivier Robert is->bdelay = HTONS_FP(DTOFP(sys_bdelay)); 1127c0b746e5SOllivier Robert HTONL_UF(sys_authdelay.l_f, &is->authdelay); 1128c0b746e5SOllivier Robert 1129c0b746e5SOllivier Robert (void) more_pkt(); 1130c0b746e5SOllivier Robert flush_pkt(); 1131c0b746e5SOllivier Robert } 1132c0b746e5SOllivier Robert 1133c0b746e5SOllivier Robert 1134c0b746e5SOllivier Robert /* 1135c0b746e5SOllivier Robert * sys_stats - return system statistics 1136c0b746e5SOllivier Robert */ 1137c0b746e5SOllivier Robert static void 1138c0b746e5SOllivier Robert sys_stats( 11399c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1140c0b746e5SOllivier Robert struct interface *inter, 1141c0b746e5SOllivier Robert struct req_pkt *inpkt 1142c0b746e5SOllivier Robert ) 1143c0b746e5SOllivier Robert { 1144c0b746e5SOllivier Robert register struct info_sys_stats *ss; 1145c0b746e5SOllivier Robert 1146c0b746e5SOllivier Robert /* 1147c0b746e5SOllivier Robert * Importations from the protocol module 1148c0b746e5SOllivier Robert */ 1149c0b746e5SOllivier Robert ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt, 1150c0b746e5SOllivier Robert sizeof(struct info_sys_stats)); 1151c0b746e5SOllivier Robert ss->timeup = htonl((u_int32)current_time); 1152c0b746e5SOllivier Robert ss->timereset = htonl((u_int32)(current_time - sys_stattime)); 11539c2daa00SOllivier Robert ss->denied = htonl((u_int32)sys_restricted); 1154c0b746e5SOllivier Robert ss->oldversionpkt = htonl((u_int32)sys_oldversionpkt); 1155c0b746e5SOllivier Robert ss->newversionpkt = htonl((u_int32)sys_newversionpkt); 1156c0b746e5SOllivier Robert ss->unknownversion = htonl((u_int32)sys_unknownversion); 1157c0b746e5SOllivier Robert ss->badlength = htonl((u_int32)sys_badlength); 1158c0b746e5SOllivier Robert ss->processed = htonl((u_int32)sys_processed); 1159c0b746e5SOllivier Robert ss->badauth = htonl((u_int32)sys_badauth); 1160c0b746e5SOllivier Robert ss->limitrejected = htonl((u_int32)sys_limitrejected); 11619c2daa00SOllivier Robert ss->received = htonl((u_int32)sys_received); 1162c0b746e5SOllivier Robert (void) more_pkt(); 1163c0b746e5SOllivier Robert flush_pkt(); 1164c0b746e5SOllivier Robert } 1165c0b746e5SOllivier Robert 1166c0b746e5SOllivier Robert 1167c0b746e5SOllivier Robert /* 1168c0b746e5SOllivier Robert * mem_stats - return memory statistics 1169c0b746e5SOllivier Robert */ 1170c0b746e5SOllivier Robert static void 1171c0b746e5SOllivier Robert mem_stats( 11729c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1173c0b746e5SOllivier Robert struct interface *inter, 1174c0b746e5SOllivier Robert struct req_pkt *inpkt 1175c0b746e5SOllivier Robert ) 1176c0b746e5SOllivier Robert { 1177c0b746e5SOllivier Robert register struct info_mem_stats *ms; 1178c0b746e5SOllivier Robert register int i; 1179c0b746e5SOllivier Robert 1180c0b746e5SOllivier Robert /* 1181c0b746e5SOllivier Robert * Importations from the peer module 1182c0b746e5SOllivier Robert */ 1183ea906c41SOllivier Robert extern int peer_hash_count[NTP_HASH_SIZE]; 1184c0b746e5SOllivier Robert extern int peer_free_count; 1185c0b746e5SOllivier Robert extern u_long peer_timereset; 1186c0b746e5SOllivier Robert extern u_long findpeer_calls; 1187c0b746e5SOllivier Robert extern u_long peer_allocations; 1188c0b746e5SOllivier Robert extern u_long peer_demobilizations; 1189c0b746e5SOllivier Robert extern int total_peer_structs; 1190c0b746e5SOllivier Robert 1191c0b746e5SOllivier Robert ms = (struct info_mem_stats *)prepare_pkt(srcadr, inter, inpkt, 1192c0b746e5SOllivier Robert sizeof(struct info_mem_stats)); 1193c0b746e5SOllivier Robert 1194c0b746e5SOllivier Robert ms->timereset = htonl((u_int32)(current_time - peer_timereset)); 1195c0b746e5SOllivier Robert ms->totalpeermem = htons((u_short)total_peer_structs); 1196c0b746e5SOllivier Robert ms->freepeermem = htons((u_short)peer_free_count); 1197c0b746e5SOllivier Robert ms->findpeer_calls = htonl((u_int32)findpeer_calls); 1198c0b746e5SOllivier Robert ms->allocations = htonl((u_int32)peer_allocations); 1199c0b746e5SOllivier Robert ms->demobilizations = htonl((u_int32)peer_demobilizations); 1200c0b746e5SOllivier Robert 1201ea906c41SOllivier Robert for (i = 0; i < NTP_HASH_SIZE; i++) { 1202c0b746e5SOllivier Robert if (peer_hash_count[i] > 255) 1203c0b746e5SOllivier Robert ms->hashcount[i] = 255; 1204c0b746e5SOllivier Robert else 1205c0b746e5SOllivier Robert ms->hashcount[i] = (u_char)peer_hash_count[i]; 1206c0b746e5SOllivier Robert } 1207c0b746e5SOllivier Robert 1208c0b746e5SOllivier Robert (void) more_pkt(); 1209c0b746e5SOllivier Robert flush_pkt(); 1210c0b746e5SOllivier Robert } 1211c0b746e5SOllivier Robert 1212c0b746e5SOllivier Robert 1213c0b746e5SOllivier Robert /* 1214c0b746e5SOllivier Robert * io_stats - return io statistics 1215c0b746e5SOllivier Robert */ 1216c0b746e5SOllivier Robert static void 1217c0b746e5SOllivier Robert io_stats( 12189c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1219c0b746e5SOllivier Robert struct interface *inter, 1220c0b746e5SOllivier Robert struct req_pkt *inpkt 1221c0b746e5SOllivier Robert ) 1222c0b746e5SOllivier Robert { 1223c0b746e5SOllivier Robert register struct info_io_stats *io; 1224c0b746e5SOllivier Robert 1225c0b746e5SOllivier Robert /* 1226c0b746e5SOllivier Robert * Importations from the io module 1227c0b746e5SOllivier Robert */ 1228c0b746e5SOllivier Robert extern u_long io_timereset; 1229c0b746e5SOllivier Robert 1230c0b746e5SOllivier Robert io = (struct info_io_stats *)prepare_pkt(srcadr, inter, inpkt, 1231c0b746e5SOllivier Robert sizeof(struct info_io_stats)); 1232c0b746e5SOllivier Robert 1233c0b746e5SOllivier Robert io->timereset = htonl((u_int32)(current_time - io_timereset)); 1234c0b746e5SOllivier Robert io->totalrecvbufs = htons((u_short) total_recvbuffs()); 1235c0b746e5SOllivier Robert io->freerecvbufs = htons((u_short) free_recvbuffs()); 1236c0b746e5SOllivier Robert io->fullrecvbufs = htons((u_short) full_recvbuffs()); 1237c0b746e5SOllivier Robert io->lowwater = htons((u_short) lowater_additions()); 1238c0b746e5SOllivier Robert io->dropped = htonl((u_int32)packets_dropped); 1239c0b746e5SOllivier Robert io->ignored = htonl((u_int32)packets_ignored); 1240c0b746e5SOllivier Robert io->received = htonl((u_int32)packets_received); 1241c0b746e5SOllivier Robert io->sent = htonl((u_int32)packets_sent); 1242c0b746e5SOllivier Robert io->notsent = htonl((u_int32)packets_notsent); 1243c0b746e5SOllivier Robert io->interrupts = htonl((u_int32)handler_calls); 1244c0b746e5SOllivier Robert io->int_received = htonl((u_int32)handler_pkts); 1245c0b746e5SOllivier Robert 1246c0b746e5SOllivier Robert (void) more_pkt(); 1247c0b746e5SOllivier Robert flush_pkt(); 1248c0b746e5SOllivier Robert } 1249c0b746e5SOllivier Robert 1250c0b746e5SOllivier Robert 1251c0b746e5SOllivier Robert /* 1252c0b746e5SOllivier Robert * timer_stats - return timer statistics 1253c0b746e5SOllivier Robert */ 1254c0b746e5SOllivier Robert static void 1255c0b746e5SOllivier Robert timer_stats( 12569c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1257c0b746e5SOllivier Robert struct interface *inter, 1258c0b746e5SOllivier Robert struct req_pkt *inpkt 1259c0b746e5SOllivier Robert ) 1260c0b746e5SOllivier Robert { 1261c0b746e5SOllivier Robert register struct info_timer_stats *ts; 1262c0b746e5SOllivier Robert 1263c0b746e5SOllivier Robert /* 1264c0b746e5SOllivier Robert * Importations from the timer module 1265c0b746e5SOllivier Robert */ 1266c0b746e5SOllivier Robert extern u_long timer_timereset; 1267c0b746e5SOllivier Robert extern u_long timer_overflows; 1268c0b746e5SOllivier Robert extern u_long timer_xmtcalls; 1269c0b746e5SOllivier Robert 1270c0b746e5SOllivier Robert ts = (struct info_timer_stats *)prepare_pkt(srcadr, inter, inpkt, 1271c0b746e5SOllivier Robert sizeof(struct info_timer_stats)); 1272c0b746e5SOllivier Robert 1273c0b746e5SOllivier Robert ts->timereset = htonl((u_int32)(current_time - timer_timereset)); 1274c0b746e5SOllivier Robert ts->alarms = htonl((u_int32)alarm_overflow); 1275c0b746e5SOllivier Robert ts->overflows = htonl((u_int32)timer_overflows); 1276c0b746e5SOllivier Robert ts->xmtcalls = htonl((u_int32)timer_xmtcalls); 1277c0b746e5SOllivier Robert 1278c0b746e5SOllivier Robert (void) more_pkt(); 1279c0b746e5SOllivier Robert flush_pkt(); 1280c0b746e5SOllivier Robert } 1281c0b746e5SOllivier Robert 1282c0b746e5SOllivier Robert 1283c0b746e5SOllivier Robert /* 1284c0b746e5SOllivier Robert * loop_info - return the current state of the loop filter 1285c0b746e5SOllivier Robert */ 1286c0b746e5SOllivier Robert static void 1287c0b746e5SOllivier Robert loop_info( 12889c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1289c0b746e5SOllivier Robert struct interface *inter, 1290c0b746e5SOllivier Robert struct req_pkt *inpkt 1291c0b746e5SOllivier Robert ) 1292c0b746e5SOllivier Robert { 1293c0b746e5SOllivier Robert register struct info_loop *li; 1294c0b746e5SOllivier Robert l_fp ltmp; 1295c0b746e5SOllivier Robert 1296c0b746e5SOllivier Robert /* 1297c0b746e5SOllivier Robert * Importations from the loop filter module 1298c0b746e5SOllivier Robert */ 1299c0b746e5SOllivier Robert extern double last_offset; 1300c0b746e5SOllivier Robert extern double drift_comp; 1301c0b746e5SOllivier Robert extern int tc_counter; 1302ea906c41SOllivier Robert extern u_long sys_clocktime; 1303c0b746e5SOllivier Robert 1304c0b746e5SOllivier Robert li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt, 1305c0b746e5SOllivier Robert sizeof(struct info_loop)); 1306c0b746e5SOllivier Robert 1307c0b746e5SOllivier Robert DTOLFP(last_offset, <mp); 1308c0b746e5SOllivier Robert HTONL_FP(<mp, &li->last_offset); 1309c0b746e5SOllivier Robert DTOLFP(drift_comp * 1e6, <mp); 1310c0b746e5SOllivier Robert HTONL_FP(<mp, &li->drift_comp); 1311c0b746e5SOllivier Robert li->compliance = htonl((u_int32)(tc_counter)); 1312ea906c41SOllivier Robert li->watchdog_timer = htonl((u_int32)(current_time - sys_clocktime)); 1313c0b746e5SOllivier Robert 1314c0b746e5SOllivier Robert (void) more_pkt(); 1315c0b746e5SOllivier Robert flush_pkt(); 1316c0b746e5SOllivier Robert } 1317c0b746e5SOllivier Robert 1318c0b746e5SOllivier Robert 1319c0b746e5SOllivier Robert /* 1320c0b746e5SOllivier Robert * do_conf - add a peer to the configuration list 1321c0b746e5SOllivier Robert */ 1322c0b746e5SOllivier Robert static void 1323c0b746e5SOllivier Robert do_conf( 13249c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1325c0b746e5SOllivier Robert struct interface *inter, 1326c0b746e5SOllivier Robert struct req_pkt *inpkt 1327c0b746e5SOllivier Robert ) 1328c0b746e5SOllivier Robert { 1329eb6d21b4SOllivier Robert static u_long soonest_ifrescan_time = 0; 13309c2daa00SOllivier Robert int items; 1331224ba2bdSOllivier Robert u_int fl; 1332ce265a54SOllivier Robert struct conf_peer *cp; 13339c2daa00SOllivier Robert struct conf_peer temp_cp; 13349c2daa00SOllivier Robert struct sockaddr_storage peeraddr; 13359c2daa00SOllivier Robert struct sockaddr_in tmp_clock; 1336c0b746e5SOllivier Robert 1337c0b746e5SOllivier Robert /* 1338c0b746e5SOllivier Robert * Do a check of everything to see that it looks 1339c0b746e5SOllivier Robert * okay. If not, complain about it. Note we are 1340c0b746e5SOllivier Robert * very picky here. 1341c0b746e5SOllivier Robert */ 1342c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1343c0b746e5SOllivier Robert cp = (struct conf_peer *)inpkt->data; 13449c2daa00SOllivier Robert memset(&temp_cp, 0, sizeof(struct conf_peer)); 13459c2daa00SOllivier Robert memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize)); 1346c0b746e5SOllivier Robert fl = 0; 1347c0b746e5SOllivier Robert while (items-- > 0 && !fl) { 13489c2daa00SOllivier Robert if (((temp_cp.version) > NTP_VERSION) 13499c2daa00SOllivier Robert || ((temp_cp.version) < NTP_OLDVERSION)) 1350c0b746e5SOllivier Robert fl = 1; 13519c2daa00SOllivier Robert if (temp_cp.hmode != MODE_ACTIVE 13529c2daa00SOllivier Robert && temp_cp.hmode != MODE_CLIENT 13539c2daa00SOllivier Robert && temp_cp.hmode != MODE_BROADCAST) 1354c0b746e5SOllivier Robert fl = 1; 13559c2daa00SOllivier Robert if (temp_cp.flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER 1356ea906c41SOllivier Robert | CONF_FLAG_BURST | CONF_FLAG_IBURST | CONF_FLAG_SKEY)) 1357c0b746e5SOllivier Robert fl = 1; 13589c2daa00SOllivier Robert cp = (struct conf_peer *) 13599c2daa00SOllivier Robert ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize)); 1360c0b746e5SOllivier Robert } 1361c0b746e5SOllivier Robert 1362c0b746e5SOllivier Robert if (fl) { 1363c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1364c0b746e5SOllivier Robert return; 1365c0b746e5SOllivier Robert } 1366c0b746e5SOllivier Robert 1367c0b746e5SOllivier Robert /* 1368c0b746e5SOllivier Robert * Looks okay, try it out 1369c0b746e5SOllivier Robert */ 1370c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1371c0b746e5SOllivier Robert cp = (struct conf_peer *)inpkt->data; 1372c0b746e5SOllivier Robert 13739c2daa00SOllivier Robert while (items-- > 0) { 13749c2daa00SOllivier Robert memset(&temp_cp, 0, sizeof(struct conf_peer)); 13759c2daa00SOllivier Robert memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize)); 13769c2daa00SOllivier Robert memset((char *)&peeraddr, 0, sizeof(struct sockaddr_storage)); 13779c2daa00SOllivier Robert 13789c2daa00SOllivier Robert fl = 0; 13799c2daa00SOllivier Robert if (temp_cp.flags & CONF_FLAG_AUTHENABLE) 13809c2daa00SOllivier Robert fl |= FLAG_AUTHENABLE; 13819c2daa00SOllivier Robert if (temp_cp.flags & CONF_FLAG_PREFER) 13829c2daa00SOllivier Robert fl |= FLAG_PREFER; 13839c2daa00SOllivier Robert if (temp_cp.flags & CONF_FLAG_BURST) 13849c2daa00SOllivier Robert fl |= FLAG_BURST; 1385ea906c41SOllivier Robert if (temp_cp.flags & CONF_FLAG_IBURST) 1386ea906c41SOllivier Robert fl |= FLAG_IBURST; 13879c2daa00SOllivier Robert if (temp_cp.flags & CONF_FLAG_SKEY) 13889c2daa00SOllivier Robert fl |= FLAG_SKEY; 1389ea906c41SOllivier Robert 13909c2daa00SOllivier Robert if (client_v6_capable && temp_cp.v6_flag != 0) { 13919c2daa00SOllivier Robert peeraddr.ss_family = AF_INET6; 13929c2daa00SOllivier Robert GET_INADDR6(peeraddr) = temp_cp.peeraddr6; 13939c2daa00SOllivier Robert } else { 13949c2daa00SOllivier Robert peeraddr.ss_family = AF_INET; 13959c2daa00SOllivier Robert GET_INADDR(peeraddr) = temp_cp.peeraddr; 1396c0b746e5SOllivier Robert /* 1397c0b746e5SOllivier Robert * Make sure the address is valid 1398c0b746e5SOllivier Robert */ 13999c2daa00SOllivier Robert tmp_clock = *CAST_V4(peeraddr); 1400c0b746e5SOllivier Robert if ( 1401c0b746e5SOllivier Robert #ifdef REFCLOCK 14029c2daa00SOllivier Robert !ISREFCLOCKADR(&tmp_clock) && 1403c0b746e5SOllivier Robert #endif 14049c2daa00SOllivier Robert ISBADADR(&tmp_clock)) { 1405c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1406c0b746e5SOllivier Robert return; 1407c0b746e5SOllivier Robert } 1408c0b746e5SOllivier Robert 14099c2daa00SOllivier Robert } 14109c2daa00SOllivier Robert NSRCPORT(&peeraddr) = htons(NTP_PORT); 14119c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 14129c2daa00SOllivier Robert peeraddr.ss_len = SOCKLEN(&peeraddr); 14139c2daa00SOllivier Robert #endif 14149c2daa00SOllivier Robert 1415c0b746e5SOllivier Robert /* XXX W2DO? minpoll/maxpoll arguments ??? */ 14169c2daa00SOllivier Robert if (peer_config(&peeraddr, (struct interface *)0, 14179c2daa00SOllivier Robert temp_cp.hmode, temp_cp.version, temp_cp.minpoll, 14189c2daa00SOllivier Robert temp_cp.maxpoll, fl, temp_cp.ttl, temp_cp.keyid, 14199c2daa00SOllivier Robert NULL) == 0) { 1420c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1421c0b746e5SOllivier Robert return; 1422c0b746e5SOllivier Robert } 1423eb6d21b4SOllivier Robert 1424eb6d21b4SOllivier Robert /* 1425eb6d21b4SOllivier Robert * ntp_intres.c uses REQ_CONFIG/doconf() to add each 1426eb6d21b4SOllivier Robert * server after its name is resolved. If we have been 1427eb6d21b4SOllivier Robert * disconnected from the network, it may notice the 1428eb6d21b4SOllivier Robert * network has returned and add the first server while 1429eb6d21b4SOllivier Robert * the relevant interface is still disabled, awaiting 1430eb6d21b4SOllivier Robert * the next interface rescan. To get things moving 1431eb6d21b4SOllivier Robert * more quickly, trigger an interface scan now, except 1432eb6d21b4SOllivier Robert * if we have done so in the last half minute. 1433eb6d21b4SOllivier Robert */ 1434eb6d21b4SOllivier Robert if (soonest_ifrescan_time < current_time) { 1435eb6d21b4SOllivier Robert soonest_ifrescan_time = current_time + 30; 1436eb6d21b4SOllivier Robert timer_interfacetimeout(current_time); 1437eb6d21b4SOllivier Robert DPRINTF(1, ("do_conf triggering interface rescan\n")); 1438eb6d21b4SOllivier Robert } 1439eb6d21b4SOllivier Robert 14409c2daa00SOllivier Robert cp = (struct conf_peer *) 14419c2daa00SOllivier Robert ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize)); 1442c0b746e5SOllivier Robert } 1443c0b746e5SOllivier Robert 1444c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1445c0b746e5SOllivier Robert } 1446c0b746e5SOllivier Robert 14479c2daa00SOllivier Robert #if 0 14489c2daa00SOllivier Robert /* XXX */ 1449c0b746e5SOllivier Robert /* 1450224ba2bdSOllivier Robert * dns_a - Snarf DNS info for an association ID 1451224ba2bdSOllivier Robert */ 1452224ba2bdSOllivier Robert static void 1453224ba2bdSOllivier Robert dns_a( 14549c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1455224ba2bdSOllivier Robert struct interface *inter, 1456224ba2bdSOllivier Robert struct req_pkt *inpkt 1457224ba2bdSOllivier Robert ) 1458224ba2bdSOllivier Robert { 1459224ba2bdSOllivier Robert register struct info_dns_assoc *dp; 1460224ba2bdSOllivier Robert register int items; 1461224ba2bdSOllivier Robert struct sockaddr_in peeraddr; 1462224ba2bdSOllivier Robert 1463224ba2bdSOllivier Robert /* 1464224ba2bdSOllivier Robert * Do a check of everything to see that it looks 1465224ba2bdSOllivier Robert * okay. If not, complain about it. Note we are 1466224ba2bdSOllivier Robert * very picky here. 1467224ba2bdSOllivier Robert */ 1468224ba2bdSOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1469224ba2bdSOllivier Robert dp = (struct info_dns_assoc *)inpkt->data; 1470224ba2bdSOllivier Robert 1471224ba2bdSOllivier Robert /* 1472224ba2bdSOllivier Robert * Looks okay, try it out 1473224ba2bdSOllivier Robert */ 1474224ba2bdSOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1475224ba2bdSOllivier Robert dp = (struct info_dns_assoc *)inpkt->data; 1476224ba2bdSOllivier Robert memset((char *)&peeraddr, 0, sizeof(struct sockaddr_in)); 1477224ba2bdSOllivier Robert peeraddr.sin_family = AF_INET; 1478224ba2bdSOllivier Robert peeraddr.sin_port = htons(NTP_PORT); 1479224ba2bdSOllivier Robert 1480224ba2bdSOllivier Robert /* 1481224ba2bdSOllivier Robert * Make sure the address is valid 1482224ba2bdSOllivier Robert */ 1483224ba2bdSOllivier Robert if ( 1484224ba2bdSOllivier Robert #ifdef REFCLOCK 1485224ba2bdSOllivier Robert !ISREFCLOCKADR(&peeraddr) && 1486224ba2bdSOllivier Robert #endif 1487224ba2bdSOllivier Robert ISBADADR(&peeraddr)) { 1488224ba2bdSOllivier Robert #ifdef REFCLOCK 1489224ba2bdSOllivier Robert msyslog(LOG_ERR, "dns_a: !ISREFCLOCK && ISBADADR"); 1490224ba2bdSOllivier Robert #else 1491224ba2bdSOllivier Robert msyslog(LOG_ERR, "dns_a: ISBADADR"); 1492224ba2bdSOllivier Robert #endif 1493224ba2bdSOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1494224ba2bdSOllivier Robert return; 1495224ba2bdSOllivier Robert } 1496224ba2bdSOllivier Robert 1497224ba2bdSOllivier Robert while (items-- > 0) { 1498224ba2bdSOllivier Robert associd_t associd; 1499224ba2bdSOllivier Robert size_t hnl; 1500224ba2bdSOllivier Robert struct peer *peer; 1501224ba2bdSOllivier Robert int bogon = 0; 1502224ba2bdSOllivier Robert 1503224ba2bdSOllivier Robert associd = dp->associd; 1504224ba2bdSOllivier Robert peer = findpeerbyassoc(associd); 1505224ba2bdSOllivier Robert if (peer == 0 || peer->flags & FLAG_REFCLOCK) { 1506224ba2bdSOllivier Robert msyslog(LOG_ERR, "dns_a: %s", 1507224ba2bdSOllivier Robert (peer == 0) 1508224ba2bdSOllivier Robert ? "peer == 0" 1509224ba2bdSOllivier Robert : "peer->flags & FLAG_REFCLOCK"); 1510224ba2bdSOllivier Robert ++bogon; 1511224ba2bdSOllivier Robert } 1512224ba2bdSOllivier Robert peeraddr.sin_addr.s_addr = dp->peeraddr; 1513224ba2bdSOllivier Robert for (hnl = 0; dp->hostname[hnl] && hnl < sizeof dp->hostname; ++hnl) ; 1514224ba2bdSOllivier Robert if (hnl >= sizeof dp->hostname) { 1515224ba2bdSOllivier Robert msyslog(LOG_ERR, "dns_a: hnl (%ld) >= %ld", 1516224ba2bdSOllivier Robert (long)hnl, (long)sizeof dp->hostname); 1517224ba2bdSOllivier Robert ++bogon; 1518224ba2bdSOllivier Robert } 1519224ba2bdSOllivier Robert 1520224ba2bdSOllivier Robert msyslog(LOG_INFO, "dns_a: <%s> for %s, AssocID %d, bogon %d", 15219c2daa00SOllivier Robert dp->hostname, 15229c2daa00SOllivier Robert stoa((struct sockaddr_storage *)&peeraddr), associd, 1523224ba2bdSOllivier Robert bogon); 1524224ba2bdSOllivier Robert 1525224ba2bdSOllivier Robert if (bogon) { 1526224ba2bdSOllivier Robert /* If it didn't work */ 1527224ba2bdSOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1528224ba2bdSOllivier Robert return; 1529224ba2bdSOllivier Robert } else { 1530224ba2bdSOllivier Robert #if 0 1531224ba2bdSOllivier Robert #ifdef PUBKEY 1532224ba2bdSOllivier Robert crypto_public(peer, dp->hostname); 1533224ba2bdSOllivier Robert #endif /* PUBKEY */ 1534224ba2bdSOllivier Robert #endif 1535224ba2bdSOllivier Robert } 1536224ba2bdSOllivier Robert 1537224ba2bdSOllivier Robert dp++; 1538224ba2bdSOllivier Robert } 1539224ba2bdSOllivier Robert 1540224ba2bdSOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1541224ba2bdSOllivier Robert } 15429c2daa00SOllivier Robert #endif /* 0 */ 1543224ba2bdSOllivier Robert 1544224ba2bdSOllivier Robert /* 1545c0b746e5SOllivier Robert * do_unconf - remove a peer from the configuration list 1546c0b746e5SOllivier Robert */ 1547c0b746e5SOllivier Robert static void 1548c0b746e5SOllivier Robert do_unconf( 15499c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1550c0b746e5SOllivier Robert struct interface *inter, 1551c0b746e5SOllivier Robert struct req_pkt *inpkt 1552c0b746e5SOllivier Robert ) 1553c0b746e5SOllivier Robert { 1554c0b746e5SOllivier Robert register struct conf_unpeer *cp; 15559c2daa00SOllivier Robert struct conf_unpeer temp_cp; 1556c0b746e5SOllivier Robert register int items; 1557c0b746e5SOllivier Robert register struct peer *peer; 15589c2daa00SOllivier Robert struct sockaddr_storage peeraddr; 1559c0b746e5SOllivier Robert int bad, found; 1560c0b746e5SOllivier Robert 1561c0b746e5SOllivier Robert /* 1562c0b746e5SOllivier Robert * This is a bit unstructured, but I like to be careful. 1563c0b746e5SOllivier Robert * We check to see that every peer exists and is actually 1564c0b746e5SOllivier Robert * configured. If so, we remove them. If not, we return 1565c0b746e5SOllivier Robert * an error. 1566c0b746e5SOllivier Robert */ 1567c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1568c0b746e5SOllivier Robert cp = (struct conf_unpeer *)inpkt->data; 1569c0b746e5SOllivier Robert 1570c0b746e5SOllivier Robert bad = 0; 1571c0b746e5SOllivier Robert while (items-- > 0 && !bad) { 15729c2daa00SOllivier Robert memset(&temp_cp, 0, sizeof(temp_cp)); 15739c2daa00SOllivier Robert memset(&peeraddr, 0, sizeof(peeraddr)); 15749c2daa00SOllivier Robert memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize)); 15759c2daa00SOllivier Robert if (client_v6_capable && temp_cp.v6_flag != 0) { 15769c2daa00SOllivier Robert peeraddr.ss_family = AF_INET6; 15779c2daa00SOllivier Robert GET_INADDR6(peeraddr) = temp_cp.peeraddr6; 15789c2daa00SOllivier Robert } else { 15799c2daa00SOllivier Robert peeraddr.ss_family = AF_INET; 15809c2daa00SOllivier Robert GET_INADDR(peeraddr) = temp_cp.peeraddr; 15819c2daa00SOllivier Robert } 15829c2daa00SOllivier Robert NSRCPORT(&peeraddr) = htons(NTP_PORT); 15839c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 15849c2daa00SOllivier Robert peeraddr.ss_len = SOCKLEN(&peeraddr); 15859c2daa00SOllivier Robert #endif 1586c0b746e5SOllivier Robert found = 0; 1587c0b746e5SOllivier Robert peer = (struct peer *)0; 1588ea906c41SOllivier Robert #ifdef DEBUG 1589ea906c41SOllivier Robert if (debug) 15909c2daa00SOllivier Robert printf("searching for %s\n", stoa(&peeraddr)); 1591ea906c41SOllivier Robert #endif 1592c0b746e5SOllivier Robert while (!found) { 1593c0b746e5SOllivier Robert peer = findexistingpeer(&peeraddr, peer, -1); 1594c0b746e5SOllivier Robert if (peer == (struct peer *)0) 1595c0b746e5SOllivier Robert break; 1596c0b746e5SOllivier Robert if (peer->flags & FLAG_CONFIG) 1597c0b746e5SOllivier Robert found = 1; 1598c0b746e5SOllivier Robert } 1599c0b746e5SOllivier Robert if (!found) 1600c0b746e5SOllivier Robert bad = 1; 16019c2daa00SOllivier Robert cp = (struct conf_unpeer *) 16029c2daa00SOllivier Robert ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize)); 1603c0b746e5SOllivier Robert } 1604c0b746e5SOllivier Robert 1605c0b746e5SOllivier Robert if (bad) { 1606c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1607c0b746e5SOllivier Robert return; 1608c0b746e5SOllivier Robert } 1609c0b746e5SOllivier Robert 1610c0b746e5SOllivier Robert /* 1611c0b746e5SOllivier Robert * Now do it in earnest. 1612c0b746e5SOllivier Robert */ 1613c0b746e5SOllivier Robert 1614c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1615c0b746e5SOllivier Robert cp = (struct conf_unpeer *)inpkt->data; 1616c0b746e5SOllivier Robert while (items-- > 0) { 16179c2daa00SOllivier Robert memset(&temp_cp, 0, sizeof(temp_cp)); 16189c2daa00SOllivier Robert memset(&peeraddr, 0, sizeof(peeraddr)); 16199c2daa00SOllivier Robert memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize)); 16209c2daa00SOllivier Robert if (client_v6_capable && temp_cp.v6_flag != 0) { 16219c2daa00SOllivier Robert peeraddr.ss_family = AF_INET6; 16229c2daa00SOllivier Robert GET_INADDR6(peeraddr) = temp_cp.peeraddr6; 16239c2daa00SOllivier Robert } else { 16249c2daa00SOllivier Robert peeraddr.ss_family = AF_INET; 16259c2daa00SOllivier Robert GET_INADDR(peeraddr) = temp_cp.peeraddr; 16269c2daa00SOllivier Robert } 16279c2daa00SOllivier Robert NSRCPORT(&peeraddr) = htons(NTP_PORT); 16289c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 16299c2daa00SOllivier Robert peeraddr.ss_len = SOCKLEN(&peeraddr); 16309c2daa00SOllivier Robert #endif 1631c0b746e5SOllivier Robert peer_unconfig(&peeraddr, (struct interface *)0, -1); 16329c2daa00SOllivier Robert cp = (struct conf_unpeer *) 16339c2daa00SOllivier Robert ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize)); 1634c0b746e5SOllivier Robert } 1635c0b746e5SOllivier Robert 1636c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1637c0b746e5SOllivier Robert } 1638c0b746e5SOllivier Robert 1639c0b746e5SOllivier Robert 1640c0b746e5SOllivier Robert /* 1641c0b746e5SOllivier Robert * set_sys_flag - set system flags 1642c0b746e5SOllivier Robert */ 1643c0b746e5SOllivier Robert static void 1644c0b746e5SOllivier Robert set_sys_flag( 16459c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1646c0b746e5SOllivier Robert struct interface *inter, 1647c0b746e5SOllivier Robert struct req_pkt *inpkt 1648c0b746e5SOllivier Robert ) 1649c0b746e5SOllivier Robert { 1650c0b746e5SOllivier Robert setclr_flags(srcadr, inter, inpkt, 1); 1651c0b746e5SOllivier Robert } 1652c0b746e5SOllivier Robert 1653c0b746e5SOllivier Robert 1654c0b746e5SOllivier Robert /* 1655c0b746e5SOllivier Robert * clr_sys_flag - clear system flags 1656c0b746e5SOllivier Robert */ 1657c0b746e5SOllivier Robert static void 1658c0b746e5SOllivier Robert clr_sys_flag( 16599c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1660c0b746e5SOllivier Robert struct interface *inter, 1661c0b746e5SOllivier Robert struct req_pkt *inpkt 1662c0b746e5SOllivier Robert ) 1663c0b746e5SOllivier Robert { 1664c0b746e5SOllivier Robert setclr_flags(srcadr, inter, inpkt, 0); 1665c0b746e5SOllivier Robert } 1666c0b746e5SOllivier Robert 1667c0b746e5SOllivier Robert 1668c0b746e5SOllivier Robert /* 1669c0b746e5SOllivier Robert * setclr_flags - do the grunge work of flag setting/clearing 1670c0b746e5SOllivier Robert */ 1671c0b746e5SOllivier Robert static void 1672c0b746e5SOllivier Robert setclr_flags( 16739c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1674c0b746e5SOllivier Robert struct interface *inter, 1675c0b746e5SOllivier Robert struct req_pkt *inpkt, 1676c0b746e5SOllivier Robert u_long set 1677c0b746e5SOllivier Robert ) 1678c0b746e5SOllivier Robert { 1679224ba2bdSOllivier Robert register u_int flags; 1680ea906c41SOllivier Robert int prev_kern_enable; 1681c0b746e5SOllivier Robert 1682ea906c41SOllivier Robert prev_kern_enable = kern_enable; 1683c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 1684224ba2bdSOllivier Robert msyslog(LOG_ERR, "setclr_flags: err_nitems > 1"); 1685c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1686c0b746e5SOllivier Robert return; 1687c0b746e5SOllivier Robert } 1688c0b746e5SOllivier Robert 1689c0b746e5SOllivier Robert flags = ((struct conf_sys_flags *)inpkt->data)->flags; 1690ea906c41SOllivier Robert flags = ntohl(flags); 1691c0b746e5SOllivier Robert 1692224ba2bdSOllivier Robert if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS | 1693c0b746e5SOllivier Robert SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR | 1694ce265a54SOllivier Robert SYS_FLAG_FILEGEN | SYS_FLAG_AUTH | SYS_FLAG_CAL)) { 1695224ba2bdSOllivier Robert msyslog(LOG_ERR, "setclr_flags: extra flags: %#x", 1696224ba2bdSOllivier Robert flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS | 1697224ba2bdSOllivier Robert SYS_FLAG_NTP | SYS_FLAG_KERNEL | 1698ce265a54SOllivier Robert SYS_FLAG_MONITOR | SYS_FLAG_FILEGEN | 1699ce265a54SOllivier Robert SYS_FLAG_AUTH | SYS_FLAG_CAL)); 1700c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1701c0b746e5SOllivier Robert return; 1702c0b746e5SOllivier Robert } 1703c0b746e5SOllivier Robert 1704c0b746e5SOllivier Robert if (flags & SYS_FLAG_BCLIENT) 17059c2daa00SOllivier Robert proto_config(PROTO_BROADCLIENT, set, 0., NULL); 1706224ba2bdSOllivier Robert if (flags & SYS_FLAG_PPS) 17079c2daa00SOllivier Robert proto_config(PROTO_PPS, set, 0., NULL); 1708c0b746e5SOllivier Robert if (flags & SYS_FLAG_NTP) 17099c2daa00SOllivier Robert proto_config(PROTO_NTP, set, 0., NULL); 1710c0b746e5SOllivier Robert if (flags & SYS_FLAG_KERNEL) 17119c2daa00SOllivier Robert proto_config(PROTO_KERNEL, set, 0., NULL); 1712c0b746e5SOllivier Robert if (flags & SYS_FLAG_MONITOR) 17139c2daa00SOllivier Robert proto_config(PROTO_MONITOR, set, 0., NULL); 1714c0b746e5SOllivier Robert if (flags & SYS_FLAG_FILEGEN) 17159c2daa00SOllivier Robert proto_config(PROTO_FILEGEN, set, 0., NULL); 1716ce265a54SOllivier Robert if (flags & SYS_FLAG_AUTH) 17179c2daa00SOllivier Robert proto_config(PROTO_AUTHENTICATE, set, 0., NULL); 1718ce265a54SOllivier Robert if (flags & SYS_FLAG_CAL) 17199c2daa00SOllivier Robert proto_config(PROTO_CAL, set, 0., NULL); 1720c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1721ea906c41SOllivier Robert 1722ea906c41SOllivier Robert /* Reset the kernel ntp parameters if the kernel flag changed. */ 1723ea906c41SOllivier Robert if (prev_kern_enable && !kern_enable) 1724ea906c41SOllivier Robert loop_config(LOOP_KERN_CLEAR, 0.0); 1725ea906c41SOllivier Robert if (!prev_kern_enable && kern_enable) 1726ea906c41SOllivier Robert loop_config(LOOP_DRIFTCOMP, drift_comp); 1727c0b746e5SOllivier Robert } 1728c0b746e5SOllivier Robert 1729c0b746e5SOllivier Robert 1730c0b746e5SOllivier Robert /* 1731c0b746e5SOllivier Robert * list_restrict - return the restrict list 1732c0b746e5SOllivier Robert */ 1733c0b746e5SOllivier Robert static void 1734c0b746e5SOllivier Robert list_restrict( 17359c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1736c0b746e5SOllivier Robert struct interface *inter, 1737c0b746e5SOllivier Robert struct req_pkt *inpkt 1738c0b746e5SOllivier Robert ) 1739c0b746e5SOllivier Robert { 1740c0b746e5SOllivier Robert register struct info_restrict *ir; 1741c0b746e5SOllivier Robert register struct restrictlist *rl; 17429c2daa00SOllivier Robert register struct restrictlist6 *rl6; 1743c0b746e5SOllivier Robert 1744c0b746e5SOllivier Robert #ifdef DEBUG 1745c0b746e5SOllivier Robert if (debug > 2) 17469c2daa00SOllivier Robert printf("wants restrict list summary\n"); 1747c0b746e5SOllivier Robert #endif 1748c0b746e5SOllivier Robert 1749c0b746e5SOllivier Robert ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt, 17509c2daa00SOllivier Robert v6sizeof(struct info_restrict)); 17519c2daa00SOllivier Robert 1752c0b746e5SOllivier Robert for (rl = restrictlist; rl != 0 && ir != 0; rl = rl->next) { 1753c0b746e5SOllivier Robert ir->addr = htonl(rl->addr); 17549c2daa00SOllivier Robert if (client_v6_capable) 17559c2daa00SOllivier Robert ir->v6_flag = 0; 1756c0b746e5SOllivier Robert ir->mask = htonl(rl->mask); 1757c0b746e5SOllivier Robert ir->count = htonl((u_int32)rl->count); 1758c0b746e5SOllivier Robert ir->flags = htons(rl->flags); 1759c0b746e5SOllivier Robert ir->mflags = htons(rl->mflags); 1760c0b746e5SOllivier Robert ir = (struct info_restrict *)more_pkt(); 1761c0b746e5SOllivier Robert } 17629c2daa00SOllivier Robert if (client_v6_capable) 17639c2daa00SOllivier Robert for (rl6 = restrictlist6; rl6 != 0 && ir != 0; rl6 = rl6->next) { 17649c2daa00SOllivier Robert ir->addr6 = rl6->addr6; 17659c2daa00SOllivier Robert ir->mask6 = rl6->mask6; 17669c2daa00SOllivier Robert ir->v6_flag = 1; 17679c2daa00SOllivier Robert ir->count = htonl((u_int32)rl6->count); 17689c2daa00SOllivier Robert ir->flags = htons(rl6->flags); 17699c2daa00SOllivier Robert ir->mflags = htons(rl6->mflags); 17709c2daa00SOllivier Robert ir = (struct info_restrict *)more_pkt(); 17719c2daa00SOllivier Robert } 1772c0b746e5SOllivier Robert flush_pkt(); 1773c0b746e5SOllivier Robert } 1774c0b746e5SOllivier Robert 1775c0b746e5SOllivier Robert 1776c0b746e5SOllivier Robert 1777c0b746e5SOllivier Robert /* 1778c0b746e5SOllivier Robert * do_resaddflags - add flags to a restrict entry (or create one) 1779c0b746e5SOllivier Robert */ 1780c0b746e5SOllivier Robert static void 1781c0b746e5SOllivier Robert do_resaddflags( 17829c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1783c0b746e5SOllivier Robert struct interface *inter, 1784c0b746e5SOllivier Robert struct req_pkt *inpkt 1785c0b746e5SOllivier Robert ) 1786c0b746e5SOllivier Robert { 1787c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_FLAGS); 1788c0b746e5SOllivier Robert } 1789c0b746e5SOllivier Robert 1790c0b746e5SOllivier Robert 1791c0b746e5SOllivier Robert 1792c0b746e5SOllivier Robert /* 1793c0b746e5SOllivier Robert * do_ressubflags - remove flags from a restrict entry 1794c0b746e5SOllivier Robert */ 1795c0b746e5SOllivier Robert static void 1796c0b746e5SOllivier Robert do_ressubflags( 17979c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1798c0b746e5SOllivier Robert struct interface *inter, 1799c0b746e5SOllivier Robert struct req_pkt *inpkt 1800c0b746e5SOllivier Robert ) 1801c0b746e5SOllivier Robert { 1802c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_UNFLAG); 1803c0b746e5SOllivier Robert } 1804c0b746e5SOllivier Robert 1805c0b746e5SOllivier Robert 1806c0b746e5SOllivier Robert /* 1807c0b746e5SOllivier Robert * do_unrestrict - remove a restrict entry from the list 1808c0b746e5SOllivier Robert */ 1809c0b746e5SOllivier Robert static void 1810c0b746e5SOllivier Robert do_unrestrict( 18119c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1812c0b746e5SOllivier Robert struct interface *inter, 1813c0b746e5SOllivier Robert struct req_pkt *inpkt 1814c0b746e5SOllivier Robert ) 1815c0b746e5SOllivier Robert { 1816c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_REMOVE); 1817c0b746e5SOllivier Robert } 1818c0b746e5SOllivier Robert 1819c0b746e5SOllivier Robert 1820c0b746e5SOllivier Robert 1821c0b746e5SOllivier Robert 1822c0b746e5SOllivier Robert 1823c0b746e5SOllivier Robert /* 1824c0b746e5SOllivier Robert * do_restrict - do the dirty stuff of dealing with restrictions 1825c0b746e5SOllivier Robert */ 1826c0b746e5SOllivier Robert static void 1827c0b746e5SOllivier Robert do_restrict( 18289c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1829c0b746e5SOllivier Robert struct interface *inter, 1830c0b746e5SOllivier Robert struct req_pkt *inpkt, 1831c0b746e5SOllivier Robert int op 1832c0b746e5SOllivier Robert ) 1833c0b746e5SOllivier Robert { 1834c0b746e5SOllivier Robert register struct conf_restrict *cr; 1835c0b746e5SOllivier Robert register int items; 18369c2daa00SOllivier Robert struct sockaddr_storage matchaddr; 18379c2daa00SOllivier Robert struct sockaddr_storage matchmask; 1838c0b746e5SOllivier Robert int bad; 1839c0b746e5SOllivier Robert 1840c0b746e5SOllivier Robert /* 1841c0b746e5SOllivier Robert * Do a check of the flags to make sure that only 1842c0b746e5SOllivier Robert * the NTPPORT flag is set, if any. If not, complain 1843c0b746e5SOllivier Robert * about it. Note we are very picky here. 1844c0b746e5SOllivier Robert */ 1845c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1846c0b746e5SOllivier Robert cr = (struct conf_restrict *)inpkt->data; 1847c0b746e5SOllivier Robert 1848c0b746e5SOllivier Robert bad = 0; 1849ea906c41SOllivier Robert cr->flags = ntohs(cr->flags); 1850ea906c41SOllivier Robert cr->mflags = ntohs(cr->mflags); 1851c0b746e5SOllivier Robert while (items-- > 0 && !bad) { 1852c0b746e5SOllivier Robert if (cr->mflags & ~(RESM_NTPONLY)) 1853224ba2bdSOllivier Robert bad |= 1; 1854c0b746e5SOllivier Robert if (cr->flags & ~(RES_ALLFLAGS)) 1855224ba2bdSOllivier Robert bad |= 2; 18569c2daa00SOllivier Robert if (cr->mask != htonl(INADDR_ANY)) { 18579c2daa00SOllivier Robert if (client_v6_capable && cr->v6_flag != 0) { 18589c2daa00SOllivier Robert if (IN6_IS_ADDR_UNSPECIFIED(&cr->addr6)) 1859224ba2bdSOllivier Robert bad |= 4; 18609c2daa00SOllivier Robert } else 18619c2daa00SOllivier Robert if (cr->addr == htonl(INADDR_ANY)) 18629c2daa00SOllivier Robert bad |= 8; 18639c2daa00SOllivier Robert } 18649c2daa00SOllivier Robert cr = (struct conf_restrict *)((char *)cr + 18659c2daa00SOllivier Robert INFO_ITEMSIZE(inpkt->mbz_itemsize)); 1866c0b746e5SOllivier Robert } 1867c0b746e5SOllivier Robert 1868c0b746e5SOllivier Robert if (bad) { 1869224ba2bdSOllivier Robert msyslog(LOG_ERR, "do_restrict: bad = %#x", bad); 1870c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1871c0b746e5SOllivier Robert return; 1872c0b746e5SOllivier Robert } 1873c0b746e5SOllivier Robert 1874c0b746e5SOllivier Robert /* 1875c0b746e5SOllivier Robert * Looks okay, try it out 1876c0b746e5SOllivier Robert */ 1877c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1878c0b746e5SOllivier Robert cr = (struct conf_restrict *)inpkt->data; 18799c2daa00SOllivier Robert memset((char *)&matchaddr, 0, sizeof(struct sockaddr_storage)); 18809c2daa00SOllivier Robert memset((char *)&matchmask, 0, sizeof(struct sockaddr_storage)); 1881c0b746e5SOllivier Robert 1882c0b746e5SOllivier Robert while (items-- > 0) { 18839c2daa00SOllivier Robert if (client_v6_capable && cr->v6_flag != 0) { 18849c2daa00SOllivier Robert GET_INADDR6(matchaddr) = cr->addr6; 18859c2daa00SOllivier Robert GET_INADDR6(matchmask) = cr->mask6; 18869c2daa00SOllivier Robert matchaddr.ss_family = AF_INET6; 18879c2daa00SOllivier Robert matchmask.ss_family = AF_INET6; 18889c2daa00SOllivier Robert } else { 18899c2daa00SOllivier Robert GET_INADDR(matchaddr) = cr->addr; 18909c2daa00SOllivier Robert GET_INADDR(matchmask) = cr->mask; 18919c2daa00SOllivier Robert matchaddr.ss_family = AF_INET; 18929c2daa00SOllivier Robert matchmask.ss_family = AF_INET; 18939c2daa00SOllivier Robert } 1894c0b746e5SOllivier Robert hack_restrict(op, &matchaddr, &matchmask, cr->mflags, 1895c0b746e5SOllivier Robert cr->flags); 1896c0b746e5SOllivier Robert cr++; 1897c0b746e5SOllivier Robert } 1898c0b746e5SOllivier Robert 1899c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1900c0b746e5SOllivier Robert } 1901c0b746e5SOllivier Robert 1902c0b746e5SOllivier Robert 1903c0b746e5SOllivier Robert /* 1904c0b746e5SOllivier Robert * mon_getlist - return monitor data 1905c0b746e5SOllivier Robert */ 1906c0b746e5SOllivier Robert static void 1907c0b746e5SOllivier Robert mon_getlist_0( 19089c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1909c0b746e5SOllivier Robert struct interface *inter, 1910c0b746e5SOllivier Robert struct req_pkt *inpkt 1911c0b746e5SOllivier Robert ) 1912c0b746e5SOllivier Robert { 1913c0b746e5SOllivier Robert register struct info_monitor *im; 1914c0b746e5SOllivier Robert register struct mon_data *md; 1915c0b746e5SOllivier Robert extern struct mon_data mon_mru_list; 1916c0b746e5SOllivier Robert extern int mon_enabled; 1917c0b746e5SOllivier Robert 1918c0b746e5SOllivier Robert #ifdef DEBUG 1919c0b746e5SOllivier Robert if (debug > 2) 1920c0b746e5SOllivier Robert printf("wants monitor 0 list\n"); 1921c0b746e5SOllivier Robert #endif 1922c0b746e5SOllivier Robert if (!mon_enabled) { 1923c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1924c0b746e5SOllivier Robert return; 1925c0b746e5SOllivier Robert } 1926c0b746e5SOllivier Robert im = (struct info_monitor *)prepare_pkt(srcadr, inter, inpkt, 19279c2daa00SOllivier Robert v6sizeof(struct info_monitor)); 1928c0b746e5SOllivier Robert for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0; 1929c0b746e5SOllivier Robert md = md->mru_next) { 19309c2daa00SOllivier Robert im->lasttime = htonl((u_int32)md->avg_interval); 19319c2daa00SOllivier Robert im->firsttime = htonl((u_int32)(current_time - md->lasttime)); 19329c2daa00SOllivier Robert im->lastdrop = htonl((u_int32)md->drop_count); 1933c0b746e5SOllivier Robert im->count = htonl((u_int32)(md->count)); 19349c2daa00SOllivier Robert if (md->rmtadr.ss_family == AF_INET6) { 19359c2daa00SOllivier Robert if (!client_v6_capable) 19369c2daa00SOllivier Robert continue; 19379c2daa00SOllivier Robert im->addr6 = GET_INADDR6(md->rmtadr); 19389c2daa00SOllivier Robert im->v6_flag = 1; 19399c2daa00SOllivier Robert } else { 19409c2daa00SOllivier Robert im->addr = GET_INADDR(md->rmtadr); 19419c2daa00SOllivier Robert if (client_v6_capable) 19429c2daa00SOllivier Robert im->v6_flag = 0; 19439c2daa00SOllivier Robert } 1944c0b746e5SOllivier Robert im->port = md->rmtport; 1945c0b746e5SOllivier Robert im->mode = md->mode; 1946c0b746e5SOllivier Robert im->version = md->version; 1947c0b746e5SOllivier Robert im = (struct info_monitor *)more_pkt(); 1948c0b746e5SOllivier Robert } 1949c0b746e5SOllivier Robert flush_pkt(); 1950c0b746e5SOllivier Robert } 1951c0b746e5SOllivier Robert 1952c0b746e5SOllivier Robert /* 1953c0b746e5SOllivier Robert * mon_getlist - return monitor data 1954c0b746e5SOllivier Robert */ 1955c0b746e5SOllivier Robert static void 1956c0b746e5SOllivier Robert mon_getlist_1( 19579c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1958c0b746e5SOllivier Robert struct interface *inter, 1959c0b746e5SOllivier Robert struct req_pkt *inpkt 1960c0b746e5SOllivier Robert ) 1961c0b746e5SOllivier Robert { 1962c0b746e5SOllivier Robert register struct info_monitor_1 *im; 1963c0b746e5SOllivier Robert register struct mon_data *md; 1964c0b746e5SOllivier Robert extern struct mon_data mon_mru_list; 1965c0b746e5SOllivier Robert extern int mon_enabled; 1966c0b746e5SOllivier Robert 1967c0b746e5SOllivier Robert if (!mon_enabled) { 1968c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1969c0b746e5SOllivier Robert return; 1970c0b746e5SOllivier Robert } 1971c0b746e5SOllivier Robert im = (struct info_monitor_1 *)prepare_pkt(srcadr, inter, inpkt, 19729c2daa00SOllivier Robert v6sizeof(struct info_monitor_1)); 1973c0b746e5SOllivier Robert for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0; 1974c0b746e5SOllivier Robert md = md->mru_next) { 19759c2daa00SOllivier Robert im->lasttime = htonl((u_int32)md->avg_interval); 19769c2daa00SOllivier Robert im->firsttime = htonl((u_int32)(current_time - md->lasttime)); 19779c2daa00SOllivier Robert im->lastdrop = htonl((u_int32)md->drop_count); 1978c0b746e5SOllivier Robert im->count = htonl((u_int32)md->count); 19799c2daa00SOllivier Robert if (md->rmtadr.ss_family == AF_INET6) { 19809c2daa00SOllivier Robert if (!client_v6_capable) 19819c2daa00SOllivier Robert continue; 19829c2daa00SOllivier Robert im->addr6 = GET_INADDR6(md->rmtadr); 19839c2daa00SOllivier Robert im->v6_flag = 1; 19849c2daa00SOllivier Robert im->daddr6 = GET_INADDR6(md->interface->sin); 19859c2daa00SOllivier Robert } else { 19869c2daa00SOllivier Robert im->addr = GET_INADDR(md->rmtadr); 19879c2daa00SOllivier Robert if (client_v6_capable) 19889c2daa00SOllivier Robert im->v6_flag = 0; 19899c2daa00SOllivier Robert im->daddr = (md->cast_flags == MDF_BCAST) 19909c2daa00SOllivier Robert ? GET_INADDR(md->interface->bcast) 1991c0b746e5SOllivier Robert : (md->cast_flags 19929c2daa00SOllivier Robert ? (GET_INADDR(md->interface->sin) 19939c2daa00SOllivier Robert ? GET_INADDR(md->interface->sin) 19949c2daa00SOllivier Robert : GET_INADDR(md->interface->bcast)) 1995c0b746e5SOllivier Robert : 4); 19969c2daa00SOllivier Robert } 1997ea906c41SOllivier Robert im->flags = htonl(md->cast_flags); 1998c0b746e5SOllivier Robert im->port = md->rmtport; 1999c0b746e5SOllivier Robert im->mode = md->mode; 2000c0b746e5SOllivier Robert im->version = md->version; 2001c0b746e5SOllivier Robert im = (struct info_monitor_1 *)more_pkt(); 2002c0b746e5SOllivier Robert } 2003c0b746e5SOllivier Robert flush_pkt(); 2004c0b746e5SOllivier Robert } 2005c0b746e5SOllivier Robert 2006c0b746e5SOllivier Robert /* 2007c0b746e5SOllivier Robert * Module entry points and the flags they correspond with 2008c0b746e5SOllivier Robert */ 2009c0b746e5SOllivier Robert struct reset_entry { 2010c0b746e5SOllivier Robert int flag; /* flag this corresponds to */ 2011c0b746e5SOllivier Robert void (*handler) P((void)); /* routine to handle request */ 2012c0b746e5SOllivier Robert }; 2013c0b746e5SOllivier Robert 2014c0b746e5SOllivier Robert struct reset_entry reset_entries[] = { 2015c0b746e5SOllivier Robert { RESET_FLAG_ALLPEERS, peer_all_reset }, 2016c0b746e5SOllivier Robert { RESET_FLAG_IO, io_clr_stats }, 2017c0b746e5SOllivier Robert { RESET_FLAG_SYS, proto_clr_stats }, 2018c0b746e5SOllivier Robert { RESET_FLAG_MEM, peer_clr_stats }, 2019c0b746e5SOllivier Robert { RESET_FLAG_TIMER, timer_clr_stats }, 2020c0b746e5SOllivier Robert { RESET_FLAG_AUTH, reset_auth_stats }, 2021c0b746e5SOllivier Robert { RESET_FLAG_CTL, ctl_clr_stats }, 2022c0b746e5SOllivier Robert { 0, 0 } 2023c0b746e5SOllivier Robert }; 2024c0b746e5SOllivier Robert 2025c0b746e5SOllivier Robert /* 2026c0b746e5SOllivier Robert * reset_stats - reset statistic counters here and there 2027c0b746e5SOllivier Robert */ 2028c0b746e5SOllivier Robert static void 2029c0b746e5SOllivier Robert reset_stats( 20309c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2031c0b746e5SOllivier Robert struct interface *inter, 2032c0b746e5SOllivier Robert struct req_pkt *inpkt 2033c0b746e5SOllivier Robert ) 2034c0b746e5SOllivier Robert { 2035c0b746e5SOllivier Robert u_long flags; 2036c0b746e5SOllivier Robert struct reset_entry *rent; 2037c0b746e5SOllivier Robert 2038c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2039224ba2bdSOllivier Robert msyslog(LOG_ERR, "reset_stats: err_nitems > 1"); 2040c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2041c0b746e5SOllivier Robert return; 2042c0b746e5SOllivier Robert } 2043c0b746e5SOllivier Robert 2044c0b746e5SOllivier Robert flags = ((struct reset_flags *)inpkt->data)->flags; 2045ea906c41SOllivier Robert flags = ntohl(flags); 2046c0b746e5SOllivier Robert 2047c0b746e5SOllivier Robert if (flags & ~RESET_ALLFLAGS) { 2048224ba2bdSOllivier Robert msyslog(LOG_ERR, "reset_stats: reset leaves %#lx", 2049224ba2bdSOllivier Robert flags & ~RESET_ALLFLAGS); 2050c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2051c0b746e5SOllivier Robert return; 2052c0b746e5SOllivier Robert } 2053c0b746e5SOllivier Robert 2054c0b746e5SOllivier Robert for (rent = reset_entries; rent->flag != 0; rent++) { 2055c0b746e5SOllivier Robert if (flags & rent->flag) 2056c0b746e5SOllivier Robert (rent->handler)(); 2057c0b746e5SOllivier Robert } 2058c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2059c0b746e5SOllivier Robert } 2060c0b746e5SOllivier Robert 2061c0b746e5SOllivier Robert 2062c0b746e5SOllivier Robert /* 2063c0b746e5SOllivier Robert * reset_peer - clear a peer's statistics 2064c0b746e5SOllivier Robert */ 2065c0b746e5SOllivier Robert static void 2066c0b746e5SOllivier Robert reset_peer( 20679c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2068c0b746e5SOllivier Robert struct interface *inter, 2069c0b746e5SOllivier Robert struct req_pkt *inpkt 2070c0b746e5SOllivier Robert ) 2071c0b746e5SOllivier Robert { 2072c0b746e5SOllivier Robert register struct conf_unpeer *cp; 2073c0b746e5SOllivier Robert register int items; 2074c0b746e5SOllivier Robert register struct peer *peer; 20759c2daa00SOllivier Robert struct sockaddr_storage peeraddr; 2076c0b746e5SOllivier Robert int bad; 2077c0b746e5SOllivier Robert 2078c0b746e5SOllivier Robert /* 2079c0b746e5SOllivier Robert * We check first to see that every peer exists. If not, 2080c0b746e5SOllivier Robert * we return an error. 2081c0b746e5SOllivier Robert */ 2082c0b746e5SOllivier Robert 2083c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2084c0b746e5SOllivier Robert cp = (struct conf_unpeer *)inpkt->data; 2085c0b746e5SOllivier Robert 2086c0b746e5SOllivier Robert bad = 0; 2087c0b746e5SOllivier Robert while (items-- > 0 && !bad) { 20889c2daa00SOllivier Robert memset((char *)&peeraddr, 0, sizeof(peeraddr)); 20899c2daa00SOllivier Robert if (client_v6_capable && cp->v6_flag != 0) { 20909c2daa00SOllivier Robert GET_INADDR6(peeraddr) = cp->peeraddr6; 20919c2daa00SOllivier Robert peeraddr.ss_family = AF_INET6; 20929c2daa00SOllivier Robert } else { 20939c2daa00SOllivier Robert GET_INADDR(peeraddr) = cp->peeraddr; 20949c2daa00SOllivier Robert peeraddr.ss_family = AF_INET; 20959c2daa00SOllivier Robert } 20969c2daa00SOllivier Robert NSRCPORT(&peeraddr) = htons(NTP_PORT); 20979c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 20989c2daa00SOllivier Robert peeraddr.ss_len = SOCKLEN(&peeraddr); 20999c2daa00SOllivier Robert #endif 2100c0b746e5SOllivier Robert peer = findexistingpeer(&peeraddr, (struct peer *)0, -1); 2101c0b746e5SOllivier Robert if (peer == (struct peer *)0) 2102c0b746e5SOllivier Robert bad++; 21039c2daa00SOllivier Robert cp = (struct conf_unpeer *)((char *)cp + 21049c2daa00SOllivier Robert INFO_ITEMSIZE(inpkt->mbz_itemsize)); 2105c0b746e5SOllivier Robert } 2106c0b746e5SOllivier Robert 2107c0b746e5SOllivier Robert if (bad) { 2108c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2109c0b746e5SOllivier Robert return; 2110c0b746e5SOllivier Robert } 2111c0b746e5SOllivier Robert 2112c0b746e5SOllivier Robert /* 2113c0b746e5SOllivier Robert * Now do it in earnest. 2114c0b746e5SOllivier Robert */ 2115c0b746e5SOllivier Robert 2116c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2117c0b746e5SOllivier Robert cp = (struct conf_unpeer *)inpkt->data; 2118c0b746e5SOllivier Robert while (items-- > 0) { 21199c2daa00SOllivier Robert memset((char *)&peeraddr, 0, sizeof(peeraddr)); 21209c2daa00SOllivier Robert if (client_v6_capable && cp->v6_flag != 0) { 21219c2daa00SOllivier Robert GET_INADDR6(peeraddr) = cp->peeraddr6; 21229c2daa00SOllivier Robert peeraddr.ss_family = AF_INET6; 21239c2daa00SOllivier Robert } else { 21249c2daa00SOllivier Robert GET_INADDR(peeraddr) = cp->peeraddr; 21259c2daa00SOllivier Robert peeraddr.ss_family = AF_INET; 21269c2daa00SOllivier Robert } 21279c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 21289c2daa00SOllivier Robert peeraddr.ss_len = SOCKLEN(&peeraddr); 21299c2daa00SOllivier Robert #endif 2130c0b746e5SOllivier Robert peer = findexistingpeer(&peeraddr, (struct peer *)0, -1); 2131c0b746e5SOllivier Robert while (peer != 0) { 2132c0b746e5SOllivier Robert peer_reset(peer); 2133c0b746e5SOllivier Robert peer = findexistingpeer(&peeraddr, (struct peer *)peer, -1); 2134c0b746e5SOllivier Robert } 21359c2daa00SOllivier Robert cp = (struct conf_unpeer *)((char *)cp + 21369c2daa00SOllivier Robert INFO_ITEMSIZE(inpkt->mbz_itemsize)); 2137c0b746e5SOllivier Robert } 2138c0b746e5SOllivier Robert 2139c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2140c0b746e5SOllivier Robert } 2141c0b746e5SOllivier Robert 2142c0b746e5SOllivier Robert 2143c0b746e5SOllivier Robert /* 2144c0b746e5SOllivier Robert * do_key_reread - reread the encryption key file 2145c0b746e5SOllivier Robert */ 2146c0b746e5SOllivier Robert static void 2147c0b746e5SOllivier Robert do_key_reread( 21489c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2149c0b746e5SOllivier Robert struct interface *inter, 2150c0b746e5SOllivier Robert struct req_pkt *inpkt 2151c0b746e5SOllivier Robert ) 2152c0b746e5SOllivier Robert { 2153c0b746e5SOllivier Robert rereadkeys(); 2154c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2155c0b746e5SOllivier Robert } 2156c0b746e5SOllivier Robert 2157c0b746e5SOllivier Robert 2158c0b746e5SOllivier Robert /* 2159c0b746e5SOllivier Robert * trust_key - make one or more keys trusted 2160c0b746e5SOllivier Robert */ 2161c0b746e5SOllivier Robert static void 2162c0b746e5SOllivier Robert trust_key( 21639c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2164c0b746e5SOllivier Robert struct interface *inter, 2165c0b746e5SOllivier Robert struct req_pkt *inpkt 2166c0b746e5SOllivier Robert ) 2167c0b746e5SOllivier Robert { 2168c0b746e5SOllivier Robert do_trustkey(srcadr, inter, inpkt, 1); 2169c0b746e5SOllivier Robert } 2170c0b746e5SOllivier Robert 2171c0b746e5SOllivier Robert 2172c0b746e5SOllivier Robert /* 2173c0b746e5SOllivier Robert * untrust_key - make one or more keys untrusted 2174c0b746e5SOllivier Robert */ 2175c0b746e5SOllivier Robert static void 2176c0b746e5SOllivier Robert untrust_key( 21779c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2178c0b746e5SOllivier Robert struct interface *inter, 2179c0b746e5SOllivier Robert struct req_pkt *inpkt 2180c0b746e5SOllivier Robert ) 2181c0b746e5SOllivier Robert { 2182c0b746e5SOllivier Robert do_trustkey(srcadr, inter, inpkt, 0); 2183c0b746e5SOllivier Robert } 2184c0b746e5SOllivier Robert 2185c0b746e5SOllivier Robert 2186c0b746e5SOllivier Robert /* 2187c0b746e5SOllivier Robert * do_trustkey - make keys either trustable or untrustable 2188c0b746e5SOllivier Robert */ 2189c0b746e5SOllivier Robert static void 2190c0b746e5SOllivier Robert do_trustkey( 21919c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2192c0b746e5SOllivier Robert struct interface *inter, 2193c0b746e5SOllivier Robert struct req_pkt *inpkt, 2194224ba2bdSOllivier Robert u_long trust 2195c0b746e5SOllivier Robert ) 2196c0b746e5SOllivier Robert { 2197c0b746e5SOllivier Robert register u_long *kp; 2198c0b746e5SOllivier Robert register int items; 2199c0b746e5SOllivier Robert 2200c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2201c0b746e5SOllivier Robert kp = (u_long *)inpkt->data; 2202c0b746e5SOllivier Robert while (items-- > 0) { 2203c0b746e5SOllivier Robert authtrust(*kp, trust); 2204c0b746e5SOllivier Robert kp++; 2205c0b746e5SOllivier Robert } 2206c0b746e5SOllivier Robert 2207c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2208c0b746e5SOllivier Robert } 2209c0b746e5SOllivier Robert 2210c0b746e5SOllivier Robert 2211c0b746e5SOllivier Robert /* 2212c0b746e5SOllivier Robert * get_auth_info - return some stats concerning the authentication module 2213c0b746e5SOllivier Robert */ 2214c0b746e5SOllivier Robert static void 2215c0b746e5SOllivier Robert get_auth_info( 22169c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2217c0b746e5SOllivier Robert struct interface *inter, 2218c0b746e5SOllivier Robert struct req_pkt *inpkt 2219c0b746e5SOllivier Robert ) 2220c0b746e5SOllivier Robert { 2221c0b746e5SOllivier Robert register struct info_auth *ia; 2222c0b746e5SOllivier Robert 2223c0b746e5SOllivier Robert /* 2224c0b746e5SOllivier Robert * Importations from the authentication module 2225c0b746e5SOllivier Robert */ 2226c0b746e5SOllivier Robert extern u_long authnumkeys; 2227c0b746e5SOllivier Robert extern int authnumfreekeys; 2228c0b746e5SOllivier Robert extern u_long authkeylookups; 2229c0b746e5SOllivier Robert extern u_long authkeynotfound; 2230c0b746e5SOllivier Robert extern u_long authencryptions; 2231c0b746e5SOllivier Robert extern u_long authdecryptions; 2232c0b746e5SOllivier Robert extern u_long authkeyuncached; 2233c0b746e5SOllivier Robert extern u_long authkeyexpired; 2234c0b746e5SOllivier Robert 2235c0b746e5SOllivier Robert ia = (struct info_auth *)prepare_pkt(srcadr, inter, inpkt, 2236c0b746e5SOllivier Robert sizeof(struct info_auth)); 2237c0b746e5SOllivier Robert 2238c0b746e5SOllivier Robert ia->numkeys = htonl((u_int32)authnumkeys); 2239c0b746e5SOllivier Robert ia->numfreekeys = htonl((u_int32)authnumfreekeys); 2240c0b746e5SOllivier Robert ia->keylookups = htonl((u_int32)authkeylookups); 2241c0b746e5SOllivier Robert ia->keynotfound = htonl((u_int32)authkeynotfound); 2242c0b746e5SOllivier Robert ia->encryptions = htonl((u_int32)authencryptions); 2243c0b746e5SOllivier Robert ia->decryptions = htonl((u_int32)authdecryptions); 2244c0b746e5SOllivier Robert ia->keyuncached = htonl((u_int32)authkeyuncached); 2245c0b746e5SOllivier Robert ia->expired = htonl((u_int32)authkeyexpired); 2246c0b746e5SOllivier Robert ia->timereset = htonl((u_int32)(current_time - auth_timereset)); 2247c0b746e5SOllivier Robert 2248c0b746e5SOllivier Robert (void) more_pkt(); 2249c0b746e5SOllivier Robert flush_pkt(); 2250c0b746e5SOllivier Robert } 2251c0b746e5SOllivier Robert 2252c0b746e5SOllivier Robert 2253c0b746e5SOllivier Robert 2254c0b746e5SOllivier Robert /* 2255c0b746e5SOllivier Robert * reset_auth_stats - reset the authentication stat counters. Done here 2256c0b746e5SOllivier Robert * to keep ntp-isms out of the authentication module 2257c0b746e5SOllivier Robert */ 2258c0b746e5SOllivier Robert static void 2259c0b746e5SOllivier Robert reset_auth_stats(void) 2260c0b746e5SOllivier Robert { 2261c0b746e5SOllivier Robert /* 2262c0b746e5SOllivier Robert * Importations from the authentication module 2263c0b746e5SOllivier Robert */ 2264c0b746e5SOllivier Robert extern u_long authkeylookups; 2265c0b746e5SOllivier Robert extern u_long authkeynotfound; 2266c0b746e5SOllivier Robert extern u_long authencryptions; 2267c0b746e5SOllivier Robert extern u_long authdecryptions; 2268c0b746e5SOllivier Robert extern u_long authkeyuncached; 2269c0b746e5SOllivier Robert 2270c0b746e5SOllivier Robert authkeylookups = 0; 2271c0b746e5SOllivier Robert authkeynotfound = 0; 2272c0b746e5SOllivier Robert authencryptions = 0; 2273c0b746e5SOllivier Robert authdecryptions = 0; 2274c0b746e5SOllivier Robert authkeyuncached = 0; 2275c0b746e5SOllivier Robert auth_timereset = current_time; 2276c0b746e5SOllivier Robert } 2277c0b746e5SOllivier Robert 2278c0b746e5SOllivier Robert 2279c0b746e5SOllivier Robert /* 2280c0b746e5SOllivier Robert * req_get_traps - return information about current trap holders 2281c0b746e5SOllivier Robert */ 2282c0b746e5SOllivier Robert static void 2283c0b746e5SOllivier Robert req_get_traps( 22849c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2285c0b746e5SOllivier Robert struct interface *inter, 2286c0b746e5SOllivier Robert struct req_pkt *inpkt 2287c0b746e5SOllivier Robert ) 2288c0b746e5SOllivier Robert { 2289c0b746e5SOllivier Robert register struct info_trap *it; 2290c0b746e5SOllivier Robert register struct ctl_trap *tr; 2291c0b746e5SOllivier Robert register int i; 2292c0b746e5SOllivier Robert 2293c0b746e5SOllivier Robert /* 2294c0b746e5SOllivier Robert * Imported from the control module 2295c0b746e5SOllivier Robert */ 2296c0b746e5SOllivier Robert extern struct ctl_trap ctl_trap[]; 2297c0b746e5SOllivier Robert extern int num_ctl_traps; 2298c0b746e5SOllivier Robert 2299c0b746e5SOllivier Robert if (num_ctl_traps == 0) { 2300c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2301c0b746e5SOllivier Robert return; 2302c0b746e5SOllivier Robert } 2303c0b746e5SOllivier Robert 2304c0b746e5SOllivier Robert it = (struct info_trap *)prepare_pkt(srcadr, inter, inpkt, 23059c2daa00SOllivier Robert v6sizeof(struct info_trap)); 2306c0b746e5SOllivier Robert 2307c0b746e5SOllivier Robert for (i = 0, tr = ctl_trap; i < CTL_MAXTRAPS; i++, tr++) { 2308c0b746e5SOllivier Robert if (tr->tr_flags & TRAP_INUSE) { 23099c2daa00SOllivier Robert if (tr->tr_addr.ss_family == AF_INET) { 2310c0b746e5SOllivier Robert if (tr->tr_localaddr == any_interface) 2311c0b746e5SOllivier Robert it->local_address = 0; 2312c0b746e5SOllivier Robert else 2313c0b746e5SOllivier Robert it->local_address 23149c2daa00SOllivier Robert = GET_INADDR(tr->tr_localaddr->sin); 23159c2daa00SOllivier Robert it->trap_address = GET_INADDR(tr->tr_addr); 23169c2daa00SOllivier Robert if (client_v6_capable) 23179c2daa00SOllivier Robert it->v6_flag = 0; 23189c2daa00SOllivier Robert } else { 23199c2daa00SOllivier Robert if (!client_v6_capable) 23209c2daa00SOllivier Robert continue; 23219c2daa00SOllivier Robert it->local_address6 23229c2daa00SOllivier Robert = GET_INADDR6(tr->tr_localaddr->sin); 23239c2daa00SOllivier Robert it->trap_address6 = GET_INADDR6(tr->tr_addr); 23249c2daa00SOllivier Robert it->v6_flag = 1; 23259c2daa00SOllivier Robert } 2326c0b746e5SOllivier Robert it->trap_port = NSRCPORT(&tr->tr_addr); 2327c0b746e5SOllivier Robert it->sequence = htons(tr->tr_sequence); 2328c0b746e5SOllivier Robert it->settime = htonl((u_int32)(current_time - tr->tr_settime)); 2329c0b746e5SOllivier Robert it->origtime = htonl((u_int32)(current_time - tr->tr_origtime)); 2330c0b746e5SOllivier Robert it->resets = htonl((u_int32)tr->tr_resets); 2331c0b746e5SOllivier Robert it->flags = htonl((u_int32)tr->tr_flags); 2332c0b746e5SOllivier Robert it = (struct info_trap *)more_pkt(); 2333c0b746e5SOllivier Robert } 2334c0b746e5SOllivier Robert } 2335c0b746e5SOllivier Robert flush_pkt(); 2336c0b746e5SOllivier Robert } 2337c0b746e5SOllivier Robert 2338c0b746e5SOllivier Robert 2339c0b746e5SOllivier Robert /* 2340c0b746e5SOllivier Robert * req_set_trap - configure a trap 2341c0b746e5SOllivier Robert */ 2342c0b746e5SOllivier Robert static void 2343c0b746e5SOllivier Robert req_set_trap( 23449c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2345c0b746e5SOllivier Robert struct interface *inter, 2346c0b746e5SOllivier Robert struct req_pkt *inpkt 2347c0b746e5SOllivier Robert ) 2348c0b746e5SOllivier Robert { 2349c0b746e5SOllivier Robert do_setclr_trap(srcadr, inter, inpkt, 1); 2350c0b746e5SOllivier Robert } 2351c0b746e5SOllivier Robert 2352c0b746e5SOllivier Robert 2353c0b746e5SOllivier Robert 2354c0b746e5SOllivier Robert /* 2355c0b746e5SOllivier Robert * req_clr_trap - unconfigure a trap 2356c0b746e5SOllivier Robert */ 2357c0b746e5SOllivier Robert static void 2358c0b746e5SOllivier Robert req_clr_trap( 23599c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2360c0b746e5SOllivier Robert struct interface *inter, 2361c0b746e5SOllivier Robert struct req_pkt *inpkt 2362c0b746e5SOllivier Robert ) 2363c0b746e5SOllivier Robert { 2364c0b746e5SOllivier Robert do_setclr_trap(srcadr, inter, inpkt, 0); 2365c0b746e5SOllivier Robert } 2366c0b746e5SOllivier Robert 2367c0b746e5SOllivier Robert 2368c0b746e5SOllivier Robert 2369c0b746e5SOllivier Robert /* 2370c0b746e5SOllivier Robert * do_setclr_trap - do the grunge work of (un)configuring a trap 2371c0b746e5SOllivier Robert */ 2372c0b746e5SOllivier Robert static void 2373c0b746e5SOllivier Robert do_setclr_trap( 23749c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2375c0b746e5SOllivier Robert struct interface *inter, 2376c0b746e5SOllivier Robert struct req_pkt *inpkt, 2377c0b746e5SOllivier Robert int set 2378c0b746e5SOllivier Robert ) 2379c0b746e5SOllivier Robert { 2380c0b746e5SOllivier Robert register struct conf_trap *ct; 2381c0b746e5SOllivier Robert register struct interface *linter; 2382c0b746e5SOllivier Robert int res; 23839c2daa00SOllivier Robert struct sockaddr_storage laddr; 2384c0b746e5SOllivier Robert 2385c0b746e5SOllivier Robert /* 23869c2daa00SOllivier Robert * Prepare sockaddr_storage structure 2387c0b746e5SOllivier Robert */ 2388c0b746e5SOllivier Robert memset((char *)&laddr, 0, sizeof laddr); 23899c2daa00SOllivier Robert laddr.ss_family = srcadr->ss_family; 23909c2daa00SOllivier Robert NSRCPORT(&laddr) = ntohs(NTP_PORT); 2391c0b746e5SOllivier Robert 2392c0b746e5SOllivier Robert /* 2393c0b746e5SOllivier Robert * Restrict ourselves to one item only. This eliminates 2394c0b746e5SOllivier Robert * the error reporting problem. 2395c0b746e5SOllivier Robert */ 2396c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2397224ba2bdSOllivier Robert msyslog(LOG_ERR, "do_setclr_trap: err_nitems > 1"); 2398c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2399c0b746e5SOllivier Robert return; 2400c0b746e5SOllivier Robert } 2401c0b746e5SOllivier Robert ct = (struct conf_trap *)inpkt->data; 2402c0b746e5SOllivier Robert 2403c0b746e5SOllivier Robert /* 2404c0b746e5SOllivier Robert * Look for the local interface. If none, use the default. 2405c0b746e5SOllivier Robert */ 2406c0b746e5SOllivier Robert if (ct->local_address == 0) { 2407c0b746e5SOllivier Robert linter = any_interface; 2408c0b746e5SOllivier Robert } else { 24099c2daa00SOllivier Robert if (laddr.ss_family == AF_INET) 24109c2daa00SOllivier Robert GET_INADDR(laddr) = ct->local_address; 24119c2daa00SOllivier Robert else 24129c2daa00SOllivier Robert GET_INADDR6(laddr) = ct->local_address6; 2413c0b746e5SOllivier Robert linter = findinterface(&laddr); 2414c0b746e5SOllivier Robert if (linter == NULL) { 2415c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2416c0b746e5SOllivier Robert return; 2417c0b746e5SOllivier Robert } 2418c0b746e5SOllivier Robert } 2419c0b746e5SOllivier Robert 24209c2daa00SOllivier Robert if (laddr.ss_family == AF_INET) 24219c2daa00SOllivier Robert GET_INADDR(laddr) = ct->trap_address; 2422c0b746e5SOllivier Robert else 24239c2daa00SOllivier Robert GET_INADDR6(laddr) = ct->trap_address6; 24249c2daa00SOllivier Robert if (ct->trap_port != 0) 24259c2daa00SOllivier Robert NSRCPORT(&laddr) = ct->trap_port; 24269c2daa00SOllivier Robert else 24279c2daa00SOllivier Robert NSRCPORT(&laddr) = htons(TRAPPORT); 2428c0b746e5SOllivier Robert 2429c0b746e5SOllivier Robert if (set) { 2430c0b746e5SOllivier Robert res = ctlsettrap(&laddr, linter, 0, 2431c0b746e5SOllivier Robert INFO_VERSION(inpkt->rm_vn_mode)); 2432c0b746e5SOllivier Robert } else { 2433c0b746e5SOllivier Robert res = ctlclrtrap(&laddr, linter, 0); 2434c0b746e5SOllivier Robert } 2435c0b746e5SOllivier Robert 2436c0b746e5SOllivier Robert if (!res) { 2437c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2438c0b746e5SOllivier Robert } else { 2439c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2440c0b746e5SOllivier Robert } 2441c0b746e5SOllivier Robert return; 2442c0b746e5SOllivier Robert } 2443c0b746e5SOllivier Robert 2444c0b746e5SOllivier Robert 2445c0b746e5SOllivier Robert 2446c0b746e5SOllivier Robert /* 2447c0b746e5SOllivier Robert * set_request_keyid - set the keyid used to authenticate requests 2448c0b746e5SOllivier Robert */ 2449c0b746e5SOllivier Robert static void 2450c0b746e5SOllivier Robert set_request_keyid( 24519c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2452c0b746e5SOllivier Robert struct interface *inter, 2453c0b746e5SOllivier Robert struct req_pkt *inpkt 2454c0b746e5SOllivier Robert ) 2455c0b746e5SOllivier Robert { 2456224ba2bdSOllivier Robert keyid_t keyid; 2457c0b746e5SOllivier Robert 2458c0b746e5SOllivier Robert /* 2459c0b746e5SOllivier Robert * Restrict ourselves to one item only. 2460c0b746e5SOllivier Robert */ 2461c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2462224ba2bdSOllivier Robert msyslog(LOG_ERR, "set_request_keyid: err_nitems > 1"); 2463c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2464c0b746e5SOllivier Robert return; 2465c0b746e5SOllivier Robert } 2466c0b746e5SOllivier Robert 2467c0b746e5SOllivier Robert keyid = ntohl(*((u_int32 *)(inpkt->data))); 2468c0b746e5SOllivier Robert info_auth_keyid = keyid; 2469c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2470c0b746e5SOllivier Robert } 2471c0b746e5SOllivier Robert 2472c0b746e5SOllivier Robert 2473c0b746e5SOllivier Robert 2474c0b746e5SOllivier Robert /* 2475c0b746e5SOllivier Robert * set_control_keyid - set the keyid used to authenticate requests 2476c0b746e5SOllivier Robert */ 2477c0b746e5SOllivier Robert static void 2478c0b746e5SOllivier Robert set_control_keyid( 24799c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2480c0b746e5SOllivier Robert struct interface *inter, 2481c0b746e5SOllivier Robert struct req_pkt *inpkt 2482c0b746e5SOllivier Robert ) 2483c0b746e5SOllivier Robert { 2484224ba2bdSOllivier Robert keyid_t keyid; 2485224ba2bdSOllivier Robert extern keyid_t ctl_auth_keyid; 2486c0b746e5SOllivier Robert 2487c0b746e5SOllivier Robert /* 2488c0b746e5SOllivier Robert * Restrict ourselves to one item only. 2489c0b746e5SOllivier Robert */ 2490c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2491224ba2bdSOllivier Robert msyslog(LOG_ERR, "set_control_keyid: err_nitems > 1"); 2492c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2493c0b746e5SOllivier Robert return; 2494c0b746e5SOllivier Robert } 2495c0b746e5SOllivier Robert 2496c0b746e5SOllivier Robert keyid = ntohl(*((u_int32 *)(inpkt->data))); 2497c0b746e5SOllivier Robert ctl_auth_keyid = keyid; 2498c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2499c0b746e5SOllivier Robert } 2500c0b746e5SOllivier Robert 2501c0b746e5SOllivier Robert 2502c0b746e5SOllivier Robert 2503c0b746e5SOllivier Robert /* 2504c0b746e5SOllivier Robert * get_ctl_stats - return some stats concerning the control message module 2505c0b746e5SOllivier Robert */ 2506c0b746e5SOllivier Robert static void 2507c0b746e5SOllivier Robert get_ctl_stats( 25089c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2509c0b746e5SOllivier Robert struct interface *inter, 2510c0b746e5SOllivier Robert struct req_pkt *inpkt 2511c0b746e5SOllivier Robert ) 2512c0b746e5SOllivier Robert { 2513c0b746e5SOllivier Robert register struct info_control *ic; 2514c0b746e5SOllivier Robert 2515c0b746e5SOllivier Robert /* 2516c0b746e5SOllivier Robert * Importations from the control module 2517c0b746e5SOllivier Robert */ 2518c0b746e5SOllivier Robert extern u_long ctltimereset; 2519c0b746e5SOllivier Robert extern u_long numctlreq; 2520c0b746e5SOllivier Robert extern u_long numctlbadpkts; 2521c0b746e5SOllivier Robert extern u_long numctlresponses; 2522c0b746e5SOllivier Robert extern u_long numctlfrags; 2523c0b746e5SOllivier Robert extern u_long numctlerrors; 2524c0b746e5SOllivier Robert extern u_long numctltooshort; 2525c0b746e5SOllivier Robert extern u_long numctlinputresp; 2526c0b746e5SOllivier Robert extern u_long numctlinputfrag; 2527c0b746e5SOllivier Robert extern u_long numctlinputerr; 2528c0b746e5SOllivier Robert extern u_long numctlbadoffset; 2529c0b746e5SOllivier Robert extern u_long numctlbadversion; 2530c0b746e5SOllivier Robert extern u_long numctldatatooshort; 2531c0b746e5SOllivier Robert extern u_long numctlbadop; 2532c0b746e5SOllivier Robert extern u_long numasyncmsgs; 2533c0b746e5SOllivier Robert 2534c0b746e5SOllivier Robert ic = (struct info_control *)prepare_pkt(srcadr, inter, inpkt, 2535c0b746e5SOllivier Robert sizeof(struct info_control)); 2536c0b746e5SOllivier Robert 2537c0b746e5SOllivier Robert ic->ctltimereset = htonl((u_int32)(current_time - ctltimereset)); 2538c0b746e5SOllivier Robert ic->numctlreq = htonl((u_int32)numctlreq); 2539c0b746e5SOllivier Robert ic->numctlbadpkts = htonl((u_int32)numctlbadpkts); 2540c0b746e5SOllivier Robert ic->numctlresponses = htonl((u_int32)numctlresponses); 2541c0b746e5SOllivier Robert ic->numctlfrags = htonl((u_int32)numctlfrags); 2542c0b746e5SOllivier Robert ic->numctlerrors = htonl((u_int32)numctlerrors); 2543c0b746e5SOllivier Robert ic->numctltooshort = htonl((u_int32)numctltooshort); 2544c0b746e5SOllivier Robert ic->numctlinputresp = htonl((u_int32)numctlinputresp); 2545c0b746e5SOllivier Robert ic->numctlinputfrag = htonl((u_int32)numctlinputfrag); 2546c0b746e5SOllivier Robert ic->numctlinputerr = htonl((u_int32)numctlinputerr); 2547c0b746e5SOllivier Robert ic->numctlbadoffset = htonl((u_int32)numctlbadoffset); 2548c0b746e5SOllivier Robert ic->numctlbadversion = htonl((u_int32)numctlbadversion); 2549c0b746e5SOllivier Robert ic->numctldatatooshort = htonl((u_int32)numctldatatooshort); 2550c0b746e5SOllivier Robert ic->numctlbadop = htonl((u_int32)numctlbadop); 2551c0b746e5SOllivier Robert ic->numasyncmsgs = htonl((u_int32)numasyncmsgs); 2552c0b746e5SOllivier Robert 2553c0b746e5SOllivier Robert (void) more_pkt(); 2554c0b746e5SOllivier Robert flush_pkt(); 2555c0b746e5SOllivier Robert } 2556c0b746e5SOllivier Robert 2557c0b746e5SOllivier Robert 2558c0b746e5SOllivier Robert #ifdef KERNEL_PLL 2559c0b746e5SOllivier Robert /* 2560c0b746e5SOllivier Robert * get_kernel_info - get kernel pll/pps information 2561c0b746e5SOllivier Robert */ 2562c0b746e5SOllivier Robert static void 2563c0b746e5SOllivier Robert get_kernel_info( 25649c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2565c0b746e5SOllivier Robert struct interface *inter, 2566c0b746e5SOllivier Robert struct req_pkt *inpkt 2567c0b746e5SOllivier Robert ) 2568c0b746e5SOllivier Robert { 2569c0b746e5SOllivier Robert register struct info_kernel *ik; 2570c0b746e5SOllivier Robert struct timex ntx; 2571c0b746e5SOllivier Robert 2572c0b746e5SOllivier Robert if (!pll_control) { 2573c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2574c0b746e5SOllivier Robert return; 2575c0b746e5SOllivier Robert } 2576c0b746e5SOllivier Robert 2577c0b746e5SOllivier Robert memset((char *)&ntx, 0, sizeof(ntx)); 2578c0b746e5SOllivier Robert if (ntp_adjtime(&ntx) < 0) 2579c0b746e5SOllivier Robert msyslog(LOG_ERR, "get_kernel_info: ntp_adjtime() failed: %m"); 2580c0b746e5SOllivier Robert ik = (struct info_kernel *)prepare_pkt(srcadr, inter, inpkt, 2581c0b746e5SOllivier Robert sizeof(struct info_kernel)); 2582c0b746e5SOllivier Robert 2583c0b746e5SOllivier Robert /* 2584c0b746e5SOllivier Robert * pll variables 2585c0b746e5SOllivier Robert */ 2586c0b746e5SOllivier Robert ik->offset = htonl((u_int32)ntx.offset); 2587c0b746e5SOllivier Robert ik->freq = htonl((u_int32)ntx.freq); 2588c0b746e5SOllivier Robert ik->maxerror = htonl((u_int32)ntx.maxerror); 2589c0b746e5SOllivier Robert ik->esterror = htonl((u_int32)ntx.esterror); 2590c0b746e5SOllivier Robert ik->status = htons(ntx.status); 2591c0b746e5SOllivier Robert ik->constant = htonl((u_int32)ntx.constant); 2592c0b746e5SOllivier Robert ik->precision = htonl((u_int32)ntx.precision); 2593c0b746e5SOllivier Robert ik->tolerance = htonl((u_int32)ntx.tolerance); 2594c0b746e5SOllivier Robert 2595c0b746e5SOllivier Robert /* 2596c0b746e5SOllivier Robert * pps variables 2597c0b746e5SOllivier Robert */ 2598c0b746e5SOllivier Robert ik->ppsfreq = htonl((u_int32)ntx.ppsfreq); 2599c0b746e5SOllivier Robert ik->jitter = htonl((u_int32)ntx.jitter); 2600c0b746e5SOllivier Robert ik->shift = htons(ntx.shift); 2601c0b746e5SOllivier Robert ik->stabil = htonl((u_int32)ntx.stabil); 2602c0b746e5SOllivier Robert ik->jitcnt = htonl((u_int32)ntx.jitcnt); 2603c0b746e5SOllivier Robert ik->calcnt = htonl((u_int32)ntx.calcnt); 2604c0b746e5SOllivier Robert ik->errcnt = htonl((u_int32)ntx.errcnt); 2605c0b746e5SOllivier Robert ik->stbcnt = htonl((u_int32)ntx.stbcnt); 2606c0b746e5SOllivier Robert 2607c0b746e5SOllivier Robert (void) more_pkt(); 2608c0b746e5SOllivier Robert flush_pkt(); 2609c0b746e5SOllivier Robert } 2610c0b746e5SOllivier Robert #endif /* KERNEL_PLL */ 2611c0b746e5SOllivier Robert 2612c0b746e5SOllivier Robert 2613c0b746e5SOllivier Robert #ifdef REFCLOCK 2614c0b746e5SOllivier Robert /* 2615c0b746e5SOllivier Robert * get_clock_info - get info about a clock 2616c0b746e5SOllivier Robert */ 2617c0b746e5SOllivier Robert static void 2618c0b746e5SOllivier Robert get_clock_info( 26199c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2620c0b746e5SOllivier Robert struct interface *inter, 2621c0b746e5SOllivier Robert struct req_pkt *inpkt 2622c0b746e5SOllivier Robert ) 2623c0b746e5SOllivier Robert { 2624c0b746e5SOllivier Robert register struct info_clock *ic; 2625c0b746e5SOllivier Robert register u_int32 *clkaddr; 2626c0b746e5SOllivier Robert register int items; 2627c0b746e5SOllivier Robert struct refclockstat clock_stat; 26289c2daa00SOllivier Robert struct sockaddr_storage addr; 26299c2daa00SOllivier Robert struct sockaddr_in tmp_clock; 2630c0b746e5SOllivier Robert l_fp ltmp; 2631c0b746e5SOllivier Robert 2632c0b746e5SOllivier Robert memset((char *)&addr, 0, sizeof addr); 26339c2daa00SOllivier Robert addr.ss_family = AF_INET; 26349c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 26359c2daa00SOllivier Robert addr.ss_len = SOCKLEN(&addr); 26369c2daa00SOllivier Robert #endif 26379c2daa00SOllivier Robert NSRCPORT(&addr) = htons(NTP_PORT); 2638c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2639c0b746e5SOllivier Robert clkaddr = (u_int32 *) inpkt->data; 2640c0b746e5SOllivier Robert 2641c0b746e5SOllivier Robert ic = (struct info_clock *)prepare_pkt(srcadr, inter, inpkt, 2642c0b746e5SOllivier Robert sizeof(struct info_clock)); 2643c0b746e5SOllivier Robert 2644c0b746e5SOllivier Robert while (items-- > 0) { 26459c2daa00SOllivier Robert tmp_clock.sin_addr.s_addr = *clkaddr++; 26469c2daa00SOllivier Robert CAST_V4(addr)->sin_addr = tmp_clock.sin_addr; 26479c2daa00SOllivier Robert if (!ISREFCLOCKADR(&tmp_clock) || 2648c0b746e5SOllivier Robert findexistingpeer(&addr, (struct peer *)0, -1) == 0) { 2649c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2650c0b746e5SOllivier Robert return; 2651c0b746e5SOllivier Robert } 2652c0b746e5SOllivier Robert 2653c0b746e5SOllivier Robert clock_stat.kv_list = (struct ctl_var *)0; 2654c0b746e5SOllivier Robert 2655c0b746e5SOllivier Robert refclock_control(&addr, (struct refclockstat *)0, &clock_stat); 2656c0b746e5SOllivier Robert 26579c2daa00SOllivier Robert ic->clockadr = tmp_clock.sin_addr.s_addr; 2658c0b746e5SOllivier Robert ic->type = clock_stat.type; 2659c0b746e5SOllivier Robert ic->flags = clock_stat.flags; 2660c0b746e5SOllivier Robert ic->lastevent = clock_stat.lastevent; 2661c0b746e5SOllivier Robert ic->currentstatus = clock_stat.currentstatus; 2662c0b746e5SOllivier Robert ic->polls = htonl((u_int32)clock_stat.polls); 2663c0b746e5SOllivier Robert ic->noresponse = htonl((u_int32)clock_stat.noresponse); 2664c0b746e5SOllivier Robert ic->badformat = htonl((u_int32)clock_stat.badformat); 2665c0b746e5SOllivier Robert ic->baddata = htonl((u_int32)clock_stat.baddata); 2666c0b746e5SOllivier Robert ic->timestarted = htonl((u_int32)clock_stat.timereset); 2667c0b746e5SOllivier Robert DTOLFP(clock_stat.fudgetime1, <mp); 2668c0b746e5SOllivier Robert HTONL_FP(<mp, &ic->fudgetime1); 26699c2daa00SOllivier Robert DTOLFP(clock_stat.fudgetime2, <mp); 2670c0b746e5SOllivier Robert HTONL_FP(<mp, &ic->fudgetime2); 2671c0b746e5SOllivier Robert ic->fudgeval1 = htonl((u_int32)clock_stat.fudgeval1); 2672c0b746e5SOllivier Robert ic->fudgeval2 = htonl((u_int32)clock_stat.fudgeval2); 2673c0b746e5SOllivier Robert 2674c0b746e5SOllivier Robert free_varlist(clock_stat.kv_list); 2675c0b746e5SOllivier Robert 2676c0b746e5SOllivier Robert ic = (struct info_clock *)more_pkt(); 2677c0b746e5SOllivier Robert } 2678c0b746e5SOllivier Robert flush_pkt(); 2679c0b746e5SOllivier Robert } 2680c0b746e5SOllivier Robert 2681c0b746e5SOllivier Robert 2682c0b746e5SOllivier Robert 2683c0b746e5SOllivier Robert /* 2684c0b746e5SOllivier Robert * set_clock_fudge - get a clock's fudge factors 2685c0b746e5SOllivier Robert */ 2686c0b746e5SOllivier Robert static void 2687c0b746e5SOllivier Robert set_clock_fudge( 26889c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2689c0b746e5SOllivier Robert struct interface *inter, 2690c0b746e5SOllivier Robert struct req_pkt *inpkt 2691c0b746e5SOllivier Robert ) 2692c0b746e5SOllivier Robert { 2693c0b746e5SOllivier Robert register struct conf_fudge *cf; 2694c0b746e5SOllivier Robert register int items; 2695c0b746e5SOllivier Robert struct refclockstat clock_stat; 26969c2daa00SOllivier Robert struct sockaddr_storage addr; 26979c2daa00SOllivier Robert struct sockaddr_in tmp_clock; 2698c0b746e5SOllivier Robert l_fp ltmp; 2699c0b746e5SOllivier Robert 2700c0b746e5SOllivier Robert memset((char *)&addr, 0, sizeof addr); 2701c0b746e5SOllivier Robert memset((char *)&clock_stat, 0, sizeof clock_stat); 2702c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2703c0b746e5SOllivier Robert cf = (struct conf_fudge *) inpkt->data; 2704c0b746e5SOllivier Robert 2705c0b746e5SOllivier Robert while (items-- > 0) { 27069c2daa00SOllivier Robert tmp_clock.sin_addr.s_addr = cf->clockadr; 27079c2daa00SOllivier Robert *CAST_V4(addr) = tmp_clock; 27089c2daa00SOllivier Robert addr.ss_family = AF_INET; 27099c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 27109c2daa00SOllivier Robert addr.ss_len = SOCKLEN(&addr); 27119c2daa00SOllivier Robert #endif 27129c2daa00SOllivier Robert NSRCPORT(&addr) = htons(NTP_PORT); 27139c2daa00SOllivier Robert if (!ISREFCLOCKADR(&tmp_clock) || 2714c0b746e5SOllivier Robert findexistingpeer(&addr, (struct peer *)0, -1) == 0) { 2715c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2716c0b746e5SOllivier Robert return; 2717c0b746e5SOllivier Robert } 2718c0b746e5SOllivier Robert 2719c0b746e5SOllivier Robert switch(ntohl(cf->which)) { 2720c0b746e5SOllivier Robert case FUDGE_TIME1: 2721c0b746e5SOllivier Robert NTOHL_FP(&cf->fudgetime, <mp); 2722c0b746e5SOllivier Robert LFPTOD(<mp, clock_stat.fudgetime1); 2723c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVETIME1; 2724c0b746e5SOllivier Robert break; 2725c0b746e5SOllivier Robert case FUDGE_TIME2: 2726c0b746e5SOllivier Robert NTOHL_FP(&cf->fudgetime, <mp); 2727c0b746e5SOllivier Robert LFPTOD(<mp, clock_stat.fudgetime2); 2728c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVETIME2; 2729c0b746e5SOllivier Robert break; 2730c0b746e5SOllivier Robert case FUDGE_VAL1: 2731c0b746e5SOllivier Robert clock_stat.fudgeval1 = ntohl(cf->fudgeval_flags); 2732c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVEVAL1; 2733c0b746e5SOllivier Robert break; 2734c0b746e5SOllivier Robert case FUDGE_VAL2: 2735c0b746e5SOllivier Robert clock_stat.fudgeval2 = ntohl(cf->fudgeval_flags); 2736c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVEVAL2; 2737c0b746e5SOllivier Robert break; 2738c0b746e5SOllivier Robert case FUDGE_FLAGS: 27399c2daa00SOllivier Robert clock_stat.flags = (u_char) (ntohl(cf->fudgeval_flags) & 0xf); 2740c0b746e5SOllivier Robert clock_stat.haveflags = 2741c0b746e5SOllivier Robert (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4); 2742c0b746e5SOllivier Robert break; 2743c0b746e5SOllivier Robert default: 2744224ba2bdSOllivier Robert msyslog(LOG_ERR, "set_clock_fudge: default!"); 2745c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2746c0b746e5SOllivier Robert return; 2747c0b746e5SOllivier Robert } 2748c0b746e5SOllivier Robert 2749c0b746e5SOllivier Robert refclock_control(&addr, &clock_stat, (struct refclockstat *)0); 2750c0b746e5SOllivier Robert } 2751c0b746e5SOllivier Robert 2752c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2753c0b746e5SOllivier Robert } 2754c0b746e5SOllivier Robert #endif 2755c0b746e5SOllivier Robert 2756c0b746e5SOllivier Robert #ifdef REFCLOCK 2757c0b746e5SOllivier Robert /* 2758c0b746e5SOllivier Robert * get_clkbug_info - get debugging info about a clock 2759c0b746e5SOllivier Robert */ 2760c0b746e5SOllivier Robert static void 2761c0b746e5SOllivier Robert get_clkbug_info( 27629c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2763c0b746e5SOllivier Robert struct interface *inter, 2764c0b746e5SOllivier Robert struct req_pkt *inpkt 2765c0b746e5SOllivier Robert ) 2766c0b746e5SOllivier Robert { 2767c0b746e5SOllivier Robert register int i; 2768c0b746e5SOllivier Robert register struct info_clkbug *ic; 2769c0b746e5SOllivier Robert register u_int32 *clkaddr; 2770c0b746e5SOllivier Robert register int items; 2771c0b746e5SOllivier Robert struct refclockbug bug; 27729c2daa00SOllivier Robert struct sockaddr_storage addr; 27739c2daa00SOllivier Robert struct sockaddr_in tmp_clock; 2774c0b746e5SOllivier Robert 2775c0b746e5SOllivier Robert memset((char *)&addr, 0, sizeof addr); 27769c2daa00SOllivier Robert addr.ss_family = AF_INET; 27779c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 27789c2daa00SOllivier Robert addr.ss_len = SOCKLEN(&addr); 27799c2daa00SOllivier Robert #endif 27809c2daa00SOllivier Robert NSRCPORT(&addr) = htons(NTP_PORT); 2781c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2782c0b746e5SOllivier Robert clkaddr = (u_int32 *) inpkt->data; 2783c0b746e5SOllivier Robert 2784c0b746e5SOllivier Robert ic = (struct info_clkbug *)prepare_pkt(srcadr, inter, inpkt, 2785c0b746e5SOllivier Robert sizeof(struct info_clkbug)); 2786c0b746e5SOllivier Robert 2787c0b746e5SOllivier Robert while (items-- > 0) { 27889c2daa00SOllivier Robert tmp_clock.sin_addr.s_addr = *clkaddr++; 27899c2daa00SOllivier Robert GET_INADDR(addr) = tmp_clock.sin_addr.s_addr; 27909c2daa00SOllivier Robert if (!ISREFCLOCKADR(&tmp_clock) || 2791c0b746e5SOllivier Robert findexistingpeer(&addr, (struct peer *)0, -1) == 0) { 2792c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2793c0b746e5SOllivier Robert return; 2794c0b746e5SOllivier Robert } 2795c0b746e5SOllivier Robert 2796c0b746e5SOllivier Robert memset((char *)&bug, 0, sizeof bug); 2797c0b746e5SOllivier Robert refclock_buginfo(&addr, &bug); 2798c0b746e5SOllivier Robert if (bug.nvalues == 0 && bug.ntimes == 0) { 2799c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2800c0b746e5SOllivier Robert return; 2801c0b746e5SOllivier Robert } 2802c0b746e5SOllivier Robert 28039c2daa00SOllivier Robert ic->clockadr = tmp_clock.sin_addr.s_addr; 2804c0b746e5SOllivier Robert i = bug.nvalues; 2805c0b746e5SOllivier Robert if (i > NUMCBUGVALUES) 2806c0b746e5SOllivier Robert i = NUMCBUGVALUES; 2807c0b746e5SOllivier Robert ic->nvalues = (u_char)i; 2808c0b746e5SOllivier Robert ic->svalues = htons((u_short) (bug.svalues & ((1<<i)-1))); 2809c0b746e5SOllivier Robert while (--i >= 0) 2810c0b746e5SOllivier Robert ic->values[i] = htonl(bug.values[i]); 2811c0b746e5SOllivier Robert 2812c0b746e5SOllivier Robert i = bug.ntimes; 2813c0b746e5SOllivier Robert if (i > NUMCBUGTIMES) 2814c0b746e5SOllivier Robert i = NUMCBUGTIMES; 2815c0b746e5SOllivier Robert ic->ntimes = (u_char)i; 2816c0b746e5SOllivier Robert ic->stimes = htonl(bug.stimes); 2817c0b746e5SOllivier Robert while (--i >= 0) { 2818c0b746e5SOllivier Robert HTONL_FP(&bug.times[i], &ic->times[i]); 2819c0b746e5SOllivier Robert } 2820c0b746e5SOllivier Robert 2821c0b746e5SOllivier Robert ic = (struct info_clkbug *)more_pkt(); 2822c0b746e5SOllivier Robert } 2823c0b746e5SOllivier Robert flush_pkt(); 2824c0b746e5SOllivier Robert } 2825c0b746e5SOllivier Robert #endif 2826ea906c41SOllivier Robert 2827ea906c41SOllivier Robert /* 2828ea906c41SOllivier Robert * receiver of interface structures 2829ea906c41SOllivier Robert */ 2830ea906c41SOllivier Robert static void 2831ea906c41SOllivier Robert fill_info_if_stats(void *data, interface_info_t *interface_info) 2832ea906c41SOllivier Robert { 2833ea906c41SOllivier Robert struct info_if_stats **ifsp = (struct info_if_stats **)data; 2834ea906c41SOllivier Robert struct info_if_stats *ifs = *ifsp; 2835ea906c41SOllivier Robert struct interface *interface = interface_info->interface; 2836ea906c41SOllivier Robert 2837ea906c41SOllivier Robert memset((char*)ifs, 0, sizeof(*ifs)); 2838ea906c41SOllivier Robert 2839ea906c41SOllivier Robert if (interface->sin.ss_family == AF_INET6) { 2840ea906c41SOllivier Robert if (!client_v6_capable) { 2841ea906c41SOllivier Robert return; 2842ea906c41SOllivier Robert } 2843ea906c41SOllivier Robert ifs->v6_flag = 1; 2844ea906c41SOllivier Robert memcpy((char *)&ifs->unaddr.addr6, (char *)&CAST_V6(interface->sin)->sin6_addr, sizeof(struct in6_addr)); 2845ea906c41SOllivier Robert memcpy((char *)&ifs->unbcast.addr6, (char *)&CAST_V6(interface->bcast)->sin6_addr, sizeof(struct in6_addr)); 2846ea906c41SOllivier Robert memcpy((char *)&ifs->unmask.addr6, (char *)&CAST_V6(interface->mask)->sin6_addr, sizeof(struct in6_addr)); 2847ea906c41SOllivier Robert } else { 2848ea906c41SOllivier Robert ifs->v6_flag = 0; 2849ea906c41SOllivier Robert memcpy((char *)&ifs->unaddr.addr, (char *)&CAST_V4(interface->sin)->sin_addr, sizeof(struct in_addr)); 2850ea906c41SOllivier Robert memcpy((char *)&ifs->unbcast.addr, (char *)&CAST_V4(interface->bcast)->sin_addr, sizeof(struct in_addr)); 2851ea906c41SOllivier Robert memcpy((char *)&ifs->unmask.addr, (char *)&CAST_V4(interface->mask)->sin_addr, sizeof(struct in_addr)); 2852ea906c41SOllivier Robert } 2853ea906c41SOllivier Robert ifs->v6_flag = htonl(ifs->v6_flag); 2854ea906c41SOllivier Robert strcpy(ifs->name, interface->name); 2855ea906c41SOllivier Robert ifs->family = htons(interface->family); 2856ea906c41SOllivier Robert ifs->flags = htonl(interface->flags); 2857ea906c41SOllivier Robert ifs->last_ttl = htonl(interface->last_ttl); 2858ea906c41SOllivier Robert ifs->num_mcast = htonl(interface->num_mcast); 2859ea906c41SOllivier Robert ifs->received = htonl(interface->received); 2860ea906c41SOllivier Robert ifs->sent = htonl(interface->sent); 2861ea906c41SOllivier Robert ifs->notsent = htonl(interface->notsent); 2862ea906c41SOllivier Robert ifs->scopeid = htonl(interface->scopeid); 2863ea906c41SOllivier Robert ifs->ifindex = htonl(interface->ifindex); 2864ea906c41SOllivier Robert ifs->ifnum = htonl(interface->ifnum); 2865ea906c41SOllivier Robert ifs->uptime = htonl(current_time - interface->starttime); 2866ea906c41SOllivier Robert ifs->ignore_packets = interface->ignore_packets; 2867ea906c41SOllivier Robert ifs->peercnt = htonl(interface->peercnt); 2868ea906c41SOllivier Robert ifs->action = interface_info->action; 2869ea906c41SOllivier Robert 2870ea906c41SOllivier Robert *ifsp = (struct info_if_stats *)more_pkt(); 2871ea906c41SOllivier Robert } 2872ea906c41SOllivier Robert 2873ea906c41SOllivier Robert /* 2874ea906c41SOllivier Robert * get_if_stats - get interface statistics 2875ea906c41SOllivier Robert */ 2876ea906c41SOllivier Robert static void 2877ea906c41SOllivier Robert get_if_stats( 2878ea906c41SOllivier Robert struct sockaddr_storage *srcadr, 2879ea906c41SOllivier Robert struct interface *inter, 2880ea906c41SOllivier Robert struct req_pkt *inpkt 2881ea906c41SOllivier Robert ) 2882ea906c41SOllivier Robert { 2883ea906c41SOllivier Robert struct info_if_stats *ifs; 2884ea906c41SOllivier Robert 2885ea906c41SOllivier Robert DPRINTF(3, ("wants interface statistics\n")); 2886ea906c41SOllivier Robert 2887ea906c41SOllivier Robert ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt, 2888ea906c41SOllivier Robert v6sizeof(struct info_if_stats)); 2889ea906c41SOllivier Robert 2890ea906c41SOllivier Robert interface_enumerate(fill_info_if_stats, &ifs); 2891ea906c41SOllivier Robert 2892ea906c41SOllivier Robert flush_pkt(); 2893ea906c41SOllivier Robert } 2894ea906c41SOllivier Robert 2895ea906c41SOllivier Robert static void 2896ea906c41SOllivier Robert do_if_reload( 2897ea906c41SOllivier Robert struct sockaddr_storage *srcadr, 2898ea906c41SOllivier Robert struct interface *inter, 2899ea906c41SOllivier Robert struct req_pkt *inpkt 2900ea906c41SOllivier Robert ) 2901ea906c41SOllivier Robert { 2902ea906c41SOllivier Robert struct info_if_stats *ifs; 2903ea906c41SOllivier Robert 2904ea906c41SOllivier Robert DPRINTF(3, ("wants interface reload\n")); 2905ea906c41SOllivier Robert 2906ea906c41SOllivier Robert ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt, 2907ea906c41SOllivier Robert v6sizeof(struct info_if_stats)); 2908ea906c41SOllivier Robert 2909ea906c41SOllivier Robert interface_update(fill_info_if_stats, &ifs); 2910ea906c41SOllivier Robert 2911ea906c41SOllivier Robert flush_pkt(); 2912ea906c41SOllivier Robert } 2913ea906c41SOllivier Robert 2914