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 { 412c0b746e5SOllivier Robert struct req_pkt *inpkt; 413ce265a54SOllivier Robert struct req_pkt_tail *tailinpkt; 4149c2daa00SOllivier Robert struct sockaddr_storage *srcadr; 415c0b746e5SOllivier Robert struct interface *inter; 416c0b746e5SOllivier Robert struct req_proc *proc; 417224ba2bdSOllivier Robert int ec; 4189c2daa00SOllivier Robert short temp_size; 419c0b746e5SOllivier Robert 420c0b746e5SOllivier Robert /* 421c0b746e5SOllivier Robert * Initialize pointers, for convenience 422c0b746e5SOllivier Robert */ 423c0b746e5SOllivier Robert inpkt = (struct req_pkt *)&rbufp->recv_pkt; 424c0b746e5SOllivier Robert srcadr = &rbufp->recv_srcadr; 425c0b746e5SOllivier Robert inter = rbufp->dstadr; 426c0b746e5SOllivier Robert 427c0b746e5SOllivier Robert #ifdef DEBUG 428c0b746e5SOllivier Robert if (debug > 2) 429224ba2bdSOllivier Robert printf("process_private: impl %d req %d\n", 430c0b746e5SOllivier Robert inpkt->implementation, inpkt->request); 431c0b746e5SOllivier Robert #endif 432c0b746e5SOllivier Robert 433c0b746e5SOllivier Robert /* 434c0b746e5SOllivier Robert * Do some sanity checks on the packet. Return a format 435c0b746e5SOllivier Robert * error if it fails. 436c0b746e5SOllivier Robert */ 437224ba2bdSOllivier Robert ec = 0; 438224ba2bdSOllivier Robert if ( (++ec, ISRESPONSE(inpkt->rm_vn_mode)) 439224ba2bdSOllivier Robert || (++ec, ISMORE(inpkt->rm_vn_mode)) 440224ba2bdSOllivier Robert || (++ec, INFO_VERSION(inpkt->rm_vn_mode) > NTP_VERSION) 441224ba2bdSOllivier Robert || (++ec, INFO_VERSION(inpkt->rm_vn_mode) < NTP_OLDVERSION) 442224ba2bdSOllivier Robert || (++ec, INFO_SEQ(inpkt->auth_seq) != 0) 443224ba2bdSOllivier Robert || (++ec, INFO_ERR(inpkt->err_nitems) != 0) 444224ba2bdSOllivier Robert || (++ec, INFO_MBZ(inpkt->mbz_itemsize) != 0) 445ce265a54SOllivier Robert || (++ec, rbufp->recv_length < REQ_LEN_HDR) 446224ba2bdSOllivier Robert ) { 4479c2daa00SOllivier Robert msyslog(LOG_ERR, "process_private: INFO_ERR_FMT: test %d failed, pkt from %s", ec, stoa(srcadr)); 448c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 449c0b746e5SOllivier Robert return; 450c0b746e5SOllivier Robert } 451c0b746e5SOllivier Robert 452c0b746e5SOllivier Robert reqver = INFO_VERSION(inpkt->rm_vn_mode); 453c0b746e5SOllivier Robert 454c0b746e5SOllivier Robert /* 455c0b746e5SOllivier Robert * Get the appropriate procedure list to search. 456c0b746e5SOllivier Robert */ 457c0b746e5SOllivier Robert if (inpkt->implementation == IMPL_UNIV) 458c0b746e5SOllivier Robert proc = univ_codes; 4599c2daa00SOllivier Robert else if ((inpkt->implementation == IMPL_XNTPD) || 4609c2daa00SOllivier Robert (inpkt->implementation == IMPL_XNTPD_OLD)) 461c0b746e5SOllivier Robert proc = ntp_codes; 462c0b746e5SOllivier Robert else { 463c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_IMPL); 464c0b746e5SOllivier Robert return; 465c0b746e5SOllivier Robert } 466c0b746e5SOllivier Robert 467c0b746e5SOllivier Robert /* 468c0b746e5SOllivier Robert * Search the list for the request codes. If it isn't one 469c0b746e5SOllivier Robert * we know, return an error. 470c0b746e5SOllivier Robert */ 471c0b746e5SOllivier Robert while (proc->request_code != NO_REQUEST) { 472c0b746e5SOllivier Robert if (proc->request_code == (short) inpkt->request) 473c0b746e5SOllivier Robert break; 474c0b746e5SOllivier Robert proc++; 475c0b746e5SOllivier Robert } 476c0b746e5SOllivier Robert if (proc->request_code == NO_REQUEST) { 477c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_REQ); 478c0b746e5SOllivier Robert return; 479c0b746e5SOllivier Robert } 480c0b746e5SOllivier Robert 481c0b746e5SOllivier Robert #ifdef DEBUG 482c0b746e5SOllivier Robert if (debug > 3) 483c0b746e5SOllivier Robert printf("found request in tables\n"); 484c0b746e5SOllivier Robert #endif 485c0b746e5SOllivier Robert 486c0b746e5SOllivier Robert /* 4879c2daa00SOllivier Robert * If we need data, check to see if we have some. If we 4889c2daa00SOllivier Robert * don't, check to see that there is none (picky, picky). 4899c2daa00SOllivier Robert */ 4909c2daa00SOllivier Robert 4919c2daa00SOllivier Robert /* This part is a bit tricky, we want to be sure that the size 4929c2daa00SOllivier Robert * returned is either the old or the new size. We also can find 4939c2daa00SOllivier Robert * out if the client can accept both types of messages this way. 4949c2daa00SOllivier Robert * 4959c2daa00SOllivier Robert * Handle the exception of REQ_CONFIG. It can have two data sizes. 4969c2daa00SOllivier Robert */ 4979c2daa00SOllivier Robert temp_size = INFO_ITEMSIZE(inpkt->mbz_itemsize); 4989c2daa00SOllivier Robert if ((temp_size != proc->sizeofitem && 4999c2daa00SOllivier Robert temp_size != proc->v6_sizeofitem) && 5009c2daa00SOllivier Robert !(inpkt->implementation == IMPL_XNTPD && 5019c2daa00SOllivier Robert inpkt->request == REQ_CONFIG && 5029c2daa00SOllivier Robert temp_size == sizeof(struct old_conf_peer))) { 503ea906c41SOllivier Robert #ifdef DEBUG 5049c2daa00SOllivier Robert if (debug > 2) 5059c2daa00SOllivier Robert printf("process_private: wrong item size, received %d, should be %d or %d\n", 5069c2daa00SOllivier Robert temp_size, proc->sizeofitem, proc->v6_sizeofitem); 507ea906c41SOllivier Robert #endif 5089c2daa00SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 5099c2daa00SOllivier Robert return; 5109c2daa00SOllivier Robert } 5119c2daa00SOllivier Robert if ((proc->sizeofitem != 0) && 5129c2daa00SOllivier Robert ((temp_size * INFO_NITEMS(inpkt->err_nitems)) > 5139c2daa00SOllivier Robert (rbufp->recv_length - REQ_LEN_HDR))) { 514ea906c41SOllivier Robert #ifdef DEBUG 5159c2daa00SOllivier Robert if (debug > 2) 5169c2daa00SOllivier Robert printf("process_private: not enough data\n"); 517ea906c41SOllivier Robert #endif 5189c2daa00SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 5199c2daa00SOllivier Robert return; 5209c2daa00SOllivier Robert } 5219c2daa00SOllivier Robert 5229c2daa00SOllivier Robert switch (inpkt->implementation) { 5239c2daa00SOllivier Robert case IMPL_XNTPD: 5249c2daa00SOllivier Robert client_v6_capable = 1; 5259c2daa00SOllivier Robert break; 5269c2daa00SOllivier Robert case IMPL_XNTPD_OLD: 5279c2daa00SOllivier Robert client_v6_capable = 0; 5289c2daa00SOllivier Robert break; 5299c2daa00SOllivier Robert default: 5309c2daa00SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 5319c2daa00SOllivier Robert return; 5329c2daa00SOllivier Robert } 5339c2daa00SOllivier Robert 5349c2daa00SOllivier Robert /* 535c0b746e5SOllivier Robert * If we need to authenticate, do so. Note that an 536c0b746e5SOllivier Robert * authenticatable packet must include a mac field, must 537c0b746e5SOllivier Robert * have used key info_auth_keyid and must have included 538c0b746e5SOllivier Robert * a time stamp in the appropriate field. The time stamp 539c0b746e5SOllivier Robert * must be within INFO_TS_MAXSKEW of the receive 540c0b746e5SOllivier Robert * time stamp. 541c0b746e5SOllivier Robert */ 542c0b746e5SOllivier Robert if (proc->needs_auth && sys_authenticate) { 543c0b746e5SOllivier Robert l_fp ftmp; 544c0b746e5SOllivier Robert double dtemp; 545c0b746e5SOllivier Robert 5469c2daa00SOllivier Robert if (rbufp->recv_length < (int)((REQ_LEN_HDR + 547ce265a54SOllivier Robert (INFO_ITEMSIZE(inpkt->mbz_itemsize) * 548ce265a54SOllivier Robert INFO_NITEMS(inpkt->err_nitems)) 5499c2daa00SOllivier Robert + sizeof(struct req_pkt_tail)))) { 550ce265a54SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 551ce265a54SOllivier Robert } 552ce265a54SOllivier Robert tailinpkt = (struct req_pkt_tail *)((char *)&rbufp->recv_pkt + 553ce265a54SOllivier Robert rbufp->recv_length - sizeof(struct req_pkt_tail)); 554ce265a54SOllivier Robert 555c0b746e5SOllivier Robert /* 556c0b746e5SOllivier Robert * If this guy is restricted from doing this, don't let him 557c0b746e5SOllivier Robert * If wrong key was used, or packet doesn't have mac, return. 558c0b746e5SOllivier Robert */ 559c0b746e5SOllivier Robert if (!INFO_IS_AUTH(inpkt->auth_seq) || info_auth_keyid == 0 560ce265a54SOllivier Robert || ntohl(tailinpkt->keyid) != info_auth_keyid) { 561c0b746e5SOllivier Robert #ifdef DEBUG 562c0b746e5SOllivier Robert if (debug > 4) 563c0b746e5SOllivier Robert printf("failed auth %d info_auth_keyid %lu pkt keyid %lu\n", 564c0b746e5SOllivier Robert INFO_IS_AUTH(inpkt->auth_seq), 565c0b746e5SOllivier Robert (u_long)info_auth_keyid, 566ce265a54SOllivier Robert (u_long)ntohl(tailinpkt->keyid)); 5679c2daa00SOllivier Robert msyslog(LOG_DEBUG, 5689c2daa00SOllivier Robert "process_private: failed auth %d info_auth_keyid %lu pkt keyid %lu\n", 5699c2daa00SOllivier Robert INFO_IS_AUTH(inpkt->auth_seq), 5709c2daa00SOllivier Robert (u_long)info_auth_keyid, 5719c2daa00SOllivier Robert (u_long)ntohl(tailinpkt->keyid)); 572c0b746e5SOllivier Robert #endif 573c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 574c0b746e5SOllivier Robert return; 575c0b746e5SOllivier Robert } 576c0b746e5SOllivier Robert if (rbufp->recv_length > REQ_LEN_MAC) { 577c0b746e5SOllivier Robert #ifdef DEBUG 578c0b746e5SOllivier Robert if (debug > 4) 579c0b746e5SOllivier Robert printf("bad pkt length %d\n", 580c0b746e5SOllivier Robert rbufp->recv_length); 581c0b746e5SOllivier Robert #endif 582224ba2bdSOllivier Robert msyslog(LOG_ERR, "process_private: bad pkt length %d", 583224ba2bdSOllivier Robert rbufp->recv_length); 584c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 585c0b746e5SOllivier Robert return; 586c0b746e5SOllivier Robert } 587c0b746e5SOllivier Robert if (!mod_okay || !authhavekey(info_auth_keyid)) { 588c0b746e5SOllivier Robert #ifdef DEBUG 589c0b746e5SOllivier Robert if (debug > 4) 590c0b746e5SOllivier Robert printf("failed auth mod_okay %d\n", mod_okay); 5919c2daa00SOllivier Robert msyslog(LOG_DEBUG, 5929c2daa00SOllivier Robert "process_private: failed auth mod_okay %d\n", 5939c2daa00SOllivier Robert mod_okay); 594c0b746e5SOllivier Robert #endif 595c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 596c0b746e5SOllivier Robert return; 597c0b746e5SOllivier Robert } 598c0b746e5SOllivier Robert 599c0b746e5SOllivier Robert /* 600c0b746e5SOllivier Robert * calculate absolute time difference between xmit time stamp 601c0b746e5SOllivier Robert * and receive time stamp. If too large, too bad. 602c0b746e5SOllivier Robert */ 603ce265a54SOllivier Robert NTOHL_FP(&tailinpkt->tstamp, &ftmp); 604c0b746e5SOllivier Robert L_SUB(&ftmp, &rbufp->recv_time); 605c0b746e5SOllivier Robert LFPTOD(&ftmp, dtemp); 606c0b746e5SOllivier Robert if (fabs(dtemp) >= INFO_TS_MAXSKEW) { 607c0b746e5SOllivier Robert /* 608c0b746e5SOllivier Robert * He's a loser. Tell him. 609c0b746e5SOllivier Robert */ 6109c2daa00SOllivier Robert #ifdef DEBUG 6119c2daa00SOllivier Robert if (debug > 4) 6129c2daa00SOllivier Robert printf("xmit/rcv timestamp delta > INFO_TS_MAXSKEW\n"); 6139c2daa00SOllivier Robert #endif 614c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 615c0b746e5SOllivier Robert return; 616c0b746e5SOllivier Robert } 617c0b746e5SOllivier Robert 618c0b746e5SOllivier Robert /* 619c0b746e5SOllivier Robert * So far so good. See if decryption works out okay. 620c0b746e5SOllivier Robert */ 621c0b746e5SOllivier Robert if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt, 622ce265a54SOllivier Robert rbufp->recv_length - sizeof(struct req_pkt_tail) + 623ce265a54SOllivier Robert REQ_LEN_HDR, sizeof(struct req_pkt_tail) - REQ_LEN_HDR)) { 6249c2daa00SOllivier Robert #ifdef DEBUG 6259c2daa00SOllivier Robert if (debug > 4) 6269c2daa00SOllivier Robert printf("authdecrypt failed\n"); 6279c2daa00SOllivier Robert #endif 628c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 629c0b746e5SOllivier Robert return; 630c0b746e5SOllivier Robert } 631c0b746e5SOllivier Robert } 632c0b746e5SOllivier Robert 633c0b746e5SOllivier Robert #ifdef DEBUG 634c0b746e5SOllivier Robert if (debug > 3) 635c0b746e5SOllivier Robert printf("process_private: all okay, into handler\n"); 636c0b746e5SOllivier Robert #endif 637c0b746e5SOllivier Robert 638c0b746e5SOllivier Robert /* 639c0b746e5SOllivier Robert * Packet is okay. Call the handler to send him data. 640c0b746e5SOllivier Robert */ 641c0b746e5SOllivier Robert (proc->handler)(srcadr, inter, inpkt); 642c0b746e5SOllivier Robert } 643c0b746e5SOllivier Robert 644c0b746e5SOllivier Robert 645c0b746e5SOllivier Robert /* 646c0b746e5SOllivier Robert * peer_list - send a list of the peers 647c0b746e5SOllivier Robert */ 648c0b746e5SOllivier Robert static void 649c0b746e5SOllivier Robert peer_list( 6509c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 651c0b746e5SOllivier Robert struct interface *inter, 652c0b746e5SOllivier Robert struct req_pkt *inpkt 653c0b746e5SOllivier Robert ) 654c0b746e5SOllivier Robert { 655c0b746e5SOllivier Robert register struct info_peer_list *ip; 656c0b746e5SOllivier Robert register struct peer *pp; 657c0b746e5SOllivier Robert register int i; 6589c2daa00SOllivier Robert register int skip = 0; 659c0b746e5SOllivier Robert 660c0b746e5SOllivier Robert ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt, 6619c2daa00SOllivier Robert v6sizeof(struct info_peer_list)); 662ea906c41SOllivier Robert for (i = 0; i < NTP_HASH_SIZE && ip != 0; i++) { 663c0b746e5SOllivier Robert pp = peer_hash[i]; 664c0b746e5SOllivier Robert while (pp != 0 && ip != 0) { 6659c2daa00SOllivier Robert if (pp->srcadr.ss_family == AF_INET6) { 6669c2daa00SOllivier Robert if (client_v6_capable) { 6679c2daa00SOllivier Robert ip->addr6 = GET_INADDR6(pp->srcadr); 6689c2daa00SOllivier Robert ip->v6_flag = 1; 6699c2daa00SOllivier Robert skip = 0; 6709c2daa00SOllivier Robert } else { 6719c2daa00SOllivier Robert skip = 1; 6729c2daa00SOllivier Robert break; 6739c2daa00SOllivier Robert } 6749c2daa00SOllivier Robert } else { 6759c2daa00SOllivier Robert ip->addr = GET_INADDR(pp->srcadr); 6769c2daa00SOllivier Robert if (client_v6_capable) 6779c2daa00SOllivier Robert ip->v6_flag = 0; 6789c2daa00SOllivier Robert skip = 0; 6799c2daa00SOllivier Robert } 6809c2daa00SOllivier Robert 6819c2daa00SOllivier Robert if(!skip) { 6829c2daa00SOllivier Robert ip->port = NSRCPORT(&pp->srcadr); 683c0b746e5SOllivier Robert ip->hmode = pp->hmode; 684c0b746e5SOllivier Robert ip->flags = 0; 685c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 686c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 687c0b746e5SOllivier Robert if (pp == sys_peer) 688c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 689c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 690c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 691c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 692c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 693c0b746e5SOllivier Robert ip = (struct info_peer_list *)more_pkt(); 6949c2daa00SOllivier Robert } 695c0b746e5SOllivier Robert pp = pp->next; 696c0b746e5SOllivier Robert } 697c0b746e5SOllivier Robert } 698c0b746e5SOllivier Robert flush_pkt(); 699c0b746e5SOllivier Robert } 700c0b746e5SOllivier Robert 701c0b746e5SOllivier Robert 702c0b746e5SOllivier Robert /* 703c0b746e5SOllivier Robert * peer_list_sum - return extended peer list 704c0b746e5SOllivier Robert */ 705c0b746e5SOllivier Robert static void 706c0b746e5SOllivier Robert peer_list_sum( 7079c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 708c0b746e5SOllivier Robert struct interface *inter, 709c0b746e5SOllivier Robert struct req_pkt *inpkt 710c0b746e5SOllivier Robert ) 711c0b746e5SOllivier Robert { 712c0b746e5SOllivier Robert register struct info_peer_summary *ips; 713c0b746e5SOllivier Robert register struct peer *pp; 714c0b746e5SOllivier Robert register int i; 715c0b746e5SOllivier Robert l_fp ltmp; 7169c2daa00SOllivier Robert register int skip; 717c0b746e5SOllivier Robert 718c0b746e5SOllivier Robert #ifdef DEBUG 719c0b746e5SOllivier Robert if (debug > 2) 720c0b746e5SOllivier Robert printf("wants peer list summary\n"); 721c0b746e5SOllivier Robert #endif 722c0b746e5SOllivier Robert ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt, 7239c2daa00SOllivier Robert v6sizeof(struct info_peer_summary)); 724ea906c41SOllivier Robert for (i = 0; i < NTP_HASH_SIZE && ips != 0; i++) { 725c0b746e5SOllivier Robert pp = peer_hash[i]; 726c0b746e5SOllivier Robert while (pp != 0 && ips != 0) { 727c0b746e5SOllivier Robert #ifdef DEBUG 728c0b746e5SOllivier Robert if (debug > 3) 729c0b746e5SOllivier Robert printf("sum: got one\n"); 730c0b746e5SOllivier Robert #endif 7319c2daa00SOllivier Robert /* 7329c2daa00SOllivier Robert * Be careful here not to return v6 peers when we 7339c2daa00SOllivier Robert * want only v4. 7349c2daa00SOllivier Robert */ 7359c2daa00SOllivier Robert if (pp->srcadr.ss_family == AF_INET6) { 7369c2daa00SOllivier Robert if (client_v6_capable) { 7379c2daa00SOllivier Robert ips->srcadr6 = GET_INADDR6(pp->srcadr); 7389c2daa00SOllivier Robert ips->v6_flag = 1; 739ea906c41SOllivier Robert if (pp->dstadr) 7409c2daa00SOllivier Robert ips->dstadr6 = GET_INADDR6(pp->dstadr->sin); 741ea906c41SOllivier Robert else 742ea906c41SOllivier Robert memset(&ips->dstadr6, 0, sizeof(ips->dstadr6)); 7439c2daa00SOllivier Robert skip = 0; 7449c2daa00SOllivier Robert } else { 7459c2daa00SOllivier Robert skip = 1; 7469c2daa00SOllivier Robert break; 7479c2daa00SOllivier Robert } 7489c2daa00SOllivier Robert } else { 7499c2daa00SOllivier Robert ips->srcadr = GET_INADDR(pp->srcadr); 7509c2daa00SOllivier Robert if (client_v6_capable) 7519c2daa00SOllivier Robert ips->v6_flag = 0; 7529c2daa00SOllivier Robert /* XXX PDM This code is buggy. Need to replace with a straightforward assignment */ 753ea906c41SOllivier Robert 754ea906c41SOllivier Robert if (pp->dstadr) 7559c2daa00SOllivier Robert ips->dstadr = (pp->processed) ? 7569c2daa00SOllivier Robert pp->cast_flags == MDF_BCAST ? 7579c2daa00SOllivier Robert GET_INADDR(pp->dstadr->bcast): 7589c2daa00SOllivier Robert pp->cast_flags ? 7599c2daa00SOllivier Robert GET_INADDR(pp->dstadr->sin) ? 7609c2daa00SOllivier Robert GET_INADDR(pp->dstadr->sin): 7619c2daa00SOllivier Robert GET_INADDR(pp->dstadr->bcast): 7629c2daa00SOllivier Robert 1 : GET_INADDR(pp->dstadr->sin); 763ea906c41SOllivier Robert else 764ea906c41SOllivier Robert memset(&ips->dstadr, 0, sizeof(ips->dstadr)); 7659c2daa00SOllivier Robert 7669c2daa00SOllivier Robert skip = 0; 7679c2daa00SOllivier Robert } 768ea906c41SOllivier Robert 7699c2daa00SOllivier Robert if (!skip){ 7709c2daa00SOllivier Robert ips->srcport = NSRCPORT(&pp->srcadr); 771c0b746e5SOllivier Robert ips->stratum = pp->stratum; 772c0b746e5SOllivier Robert ips->hpoll = pp->hpoll; 773c0b746e5SOllivier Robert ips->ppoll = pp->ppoll; 774c0b746e5SOllivier Robert ips->reach = pp->reach; 775c0b746e5SOllivier Robert ips->flags = 0; 776c0b746e5SOllivier Robert if (pp == sys_peer) 777c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SYSPEER; 778c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 779c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_CONFIG; 780c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 781c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_REFCLOCK; 782c0b746e5SOllivier Robert if (pp->flags & FLAG_AUTHENABLE) 783c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_AUTHENABLE; 784c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 785c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_PREFER; 786c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 787c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_BURST; 788c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 789c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SEL_CANDIDATE; 790c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 791c0b746e5SOllivier Robert ips->flags |= INFO_FLAG_SHORTLIST; 792c0b746e5SOllivier Robert ips->hmode = pp->hmode; 793c0b746e5SOllivier Robert ips->delay = HTONS_FP(DTOFP(pp->delay)); 794c0b746e5SOllivier Robert DTOLFP(pp->offset, <mp); 795c0b746e5SOllivier Robert HTONL_FP(<mp, &ips->offset); 796ea906c41SOllivier Robert ips->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); 7979c2daa00SOllivier Robert } 798c0b746e5SOllivier Robert pp = pp->next; 799c0b746e5SOllivier Robert ips = (struct info_peer_summary *)more_pkt(); 800c0b746e5SOllivier Robert } 801c0b746e5SOllivier Robert } 802c0b746e5SOllivier Robert flush_pkt(); 803c0b746e5SOllivier Robert } 804c0b746e5SOllivier Robert 805c0b746e5SOllivier Robert 806c0b746e5SOllivier Robert /* 807c0b746e5SOllivier Robert * peer_info - send information for one or more peers 808c0b746e5SOllivier Robert */ 809c0b746e5SOllivier Robert static void 810c0b746e5SOllivier Robert peer_info ( 8119c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 812c0b746e5SOllivier Robert struct interface *inter, 813c0b746e5SOllivier Robert struct req_pkt *inpkt 814c0b746e5SOllivier Robert ) 815c0b746e5SOllivier Robert { 816c0b746e5SOllivier Robert register struct info_peer_list *ipl; 817c0b746e5SOllivier Robert register struct peer *pp; 818c0b746e5SOllivier Robert register struct info_peer *ip; 819c0b746e5SOllivier Robert register int items; 820c0b746e5SOllivier Robert register int i, j; 8219c2daa00SOllivier Robert struct sockaddr_storage addr; 822c0b746e5SOllivier Robert extern struct peer *sys_peer; 823c0b746e5SOllivier Robert l_fp ltmp; 824c0b746e5SOllivier Robert 825c0b746e5SOllivier Robert memset((char *)&addr, 0, sizeof addr); 826c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 827c0b746e5SOllivier Robert ipl = (struct info_peer_list *) inpkt->data; 8289c2daa00SOllivier Robert 829c0b746e5SOllivier Robert ip = (struct info_peer *)prepare_pkt(srcadr, inter, inpkt, 8309c2daa00SOllivier Robert v6sizeof(struct info_peer)); 831c0b746e5SOllivier Robert while (items-- > 0 && ip != 0) { 8329c2daa00SOllivier Robert memset((char *)&addr, 0, sizeof(addr)); 8339c2daa00SOllivier Robert NSRCPORT(&addr) = ipl->port; 8349c2daa00SOllivier Robert if (client_v6_capable && ipl->v6_flag != 0) { 8359c2daa00SOllivier Robert addr.ss_family = AF_INET6; 8369c2daa00SOllivier Robert GET_INADDR6(addr) = ipl->addr6; 8379c2daa00SOllivier Robert } else { 8389c2daa00SOllivier Robert addr.ss_family = AF_INET; 8399c2daa00SOllivier Robert GET_INADDR(addr) = ipl->addr; 8409c2daa00SOllivier Robert } 8419c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 8429c2daa00SOllivier Robert addr.ss_len = SOCKLEN(&addr); 8439c2daa00SOllivier Robert #endif 844c0b746e5SOllivier Robert ipl++; 845c0b746e5SOllivier Robert if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0) 846c0b746e5SOllivier Robert continue; 8479c2daa00SOllivier Robert if (pp->srcadr.ss_family == AF_INET6) { 848ea906c41SOllivier Robert if (pp->dstadr) 8499c2daa00SOllivier Robert ip->dstadr6 = pp->cast_flags == MDF_BCAST ? 8509c2daa00SOllivier Robert GET_INADDR6(pp->dstadr->bcast) : 8519c2daa00SOllivier Robert GET_INADDR6(pp->dstadr->sin); 852ea906c41SOllivier Robert else 853ea906c41SOllivier Robert memset(&ip->dstadr6, 0, sizeof(ip->dstadr6)); 854ea906c41SOllivier Robert 8559c2daa00SOllivier Robert ip->srcadr6 = GET_INADDR6(pp->srcadr); 8569c2daa00SOllivier Robert ip->v6_flag = 1; 8579c2daa00SOllivier Robert } else { 8589c2daa00SOllivier Robert /* XXX PDM This code is buggy. Need to replace with a straightforward assignment */ 859ea906c41SOllivier Robert if (pp->dstadr) 8609c2daa00SOllivier Robert ip->dstadr = (pp->processed) ? 8619c2daa00SOllivier Robert pp->cast_flags == MDF_BCAST ? 8629c2daa00SOllivier Robert GET_INADDR(pp->dstadr->bcast): 8639c2daa00SOllivier Robert pp->cast_flags ? 8649c2daa00SOllivier Robert GET_INADDR(pp->dstadr->sin) ? 8659c2daa00SOllivier Robert GET_INADDR(pp->dstadr->sin): 8669c2daa00SOllivier Robert GET_INADDR(pp->dstadr->bcast): 8679c2daa00SOllivier Robert 2 : GET_INADDR(pp->dstadr->sin); 868ea906c41SOllivier Robert else 869ea906c41SOllivier Robert memset(&ip->dstadr, 0, sizeof(ip->dstadr)); 8709c2daa00SOllivier Robert 8719c2daa00SOllivier Robert ip->srcadr = GET_INADDR(pp->srcadr); 8729c2daa00SOllivier Robert if (client_v6_capable) 8739c2daa00SOllivier Robert ip->v6_flag = 0; 8749c2daa00SOllivier Robert } 875c0b746e5SOllivier Robert ip->srcport = NSRCPORT(&pp->srcadr); 876c0b746e5SOllivier Robert ip->flags = 0; 877c0b746e5SOllivier Robert if (pp == sys_peer) 878c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 879c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 880c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 881c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 882c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_REFCLOCK; 883c0b746e5SOllivier Robert if (pp->flags & FLAG_AUTHENABLE) 884c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_AUTHENABLE; 885c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 886c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_PREFER; 887c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 888c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_BURST; 889c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 890c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 891c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 892c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 893c0b746e5SOllivier Robert ip->leap = pp->leap; 894c0b746e5SOllivier Robert ip->hmode = pp->hmode; 895c0b746e5SOllivier Robert ip->keyid = pp->keyid; 896c0b746e5SOllivier Robert ip->stratum = pp->stratum; 897c0b746e5SOllivier Robert ip->ppoll = pp->ppoll; 898c0b746e5SOllivier Robert ip->hpoll = pp->hpoll; 899c0b746e5SOllivier Robert ip->precision = pp->precision; 900c0b746e5SOllivier Robert ip->version = pp->version; 901c0b746e5SOllivier Robert ip->reach = pp->reach; 9029c2daa00SOllivier Robert ip->unreach = (u_char) pp->unreach; 903c0b746e5SOllivier Robert ip->flash = (u_char)pp->flash; 9049c2daa00SOllivier Robert ip->flash2 = (u_short) pp->flash; 905c0b746e5SOllivier Robert ip->estbdelay = HTONS_FP(DTOFP(pp->estbdelay)); 906c0b746e5SOllivier Robert ip->ttl = pp->ttl; 907c0b746e5SOllivier Robert ip->associd = htons(pp->associd); 908c0b746e5SOllivier Robert ip->rootdelay = HTONS_FP(DTOUFP(pp->rootdelay)); 909c0b746e5SOllivier Robert ip->rootdispersion = HTONS_FP(DTOUFP(pp->rootdispersion)); 910c0b746e5SOllivier Robert ip->refid = pp->refid; 911c0b746e5SOllivier Robert HTONL_FP(&pp->reftime, &ip->reftime); 912c0b746e5SOllivier Robert HTONL_FP(&pp->org, &ip->org); 913c0b746e5SOllivier Robert HTONL_FP(&pp->rec, &ip->rec); 914c0b746e5SOllivier Robert HTONL_FP(&pp->xmt, &ip->xmt); 915c0b746e5SOllivier Robert j = pp->filter_nextpt - 1; 916c0b746e5SOllivier Robert for (i = 0; i < NTP_SHIFT; i++, j--) { 917c0b746e5SOllivier Robert if (j < 0) 918c0b746e5SOllivier Robert j = NTP_SHIFT-1; 919c0b746e5SOllivier Robert ip->filtdelay[i] = HTONS_FP(DTOFP(pp->filter_delay[j])); 920c0b746e5SOllivier Robert DTOLFP(pp->filter_offset[j], <mp); 921c0b746e5SOllivier Robert HTONL_FP(<mp, &ip->filtoffset[i]); 9229c2daa00SOllivier Robert ip->order[i] = (u_char)((pp->filter_nextpt+NTP_SHIFT-1) 9239c2daa00SOllivier Robert - pp->filter_order[i]); 924c0b746e5SOllivier Robert if (ip->order[i] >= NTP_SHIFT) 925c0b746e5SOllivier Robert ip->order[i] -= NTP_SHIFT; 926c0b746e5SOllivier Robert } 927c0b746e5SOllivier Robert DTOLFP(pp->offset, <mp); 928c0b746e5SOllivier Robert HTONL_FP(<mp, &ip->offset); 929c0b746e5SOllivier Robert ip->delay = HTONS_FP(DTOFP(pp->delay)); 930c0b746e5SOllivier Robert ip->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); 931224ba2bdSOllivier Robert ip->selectdisp = HTONS_FP(DTOUFP(SQRT(pp->jitter))); 932c0b746e5SOllivier Robert ip = (struct info_peer *)more_pkt(); 933c0b746e5SOllivier Robert } 934c0b746e5SOllivier Robert flush_pkt(); 935c0b746e5SOllivier Robert } 936c0b746e5SOllivier Robert 937c0b746e5SOllivier Robert 938c0b746e5SOllivier Robert /* 939c0b746e5SOllivier Robert * peer_stats - send statistics for one or more peers 940c0b746e5SOllivier Robert */ 941c0b746e5SOllivier Robert static void 942c0b746e5SOllivier Robert peer_stats ( 9439c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 944c0b746e5SOllivier Robert struct interface *inter, 945c0b746e5SOllivier Robert struct req_pkt *inpkt 946c0b746e5SOllivier Robert ) 947c0b746e5SOllivier Robert { 948c0b746e5SOllivier Robert register struct info_peer_list *ipl; 949c0b746e5SOllivier Robert register struct peer *pp; 950c0b746e5SOllivier Robert register struct info_peer_stats *ip; 951c0b746e5SOllivier Robert register int items; 9529c2daa00SOllivier Robert struct sockaddr_storage addr; 953c0b746e5SOllivier Robert extern struct peer *sys_peer; 954c0b746e5SOllivier Robert 955ea906c41SOllivier Robert #ifdef DEBUG 956ea906c41SOllivier Robert if (debug) 9579c2daa00SOllivier Robert printf("peer_stats: called\n"); 958ea906c41SOllivier Robert #endif 959c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 960c0b746e5SOllivier Robert ipl = (struct info_peer_list *) inpkt->data; 961c0b746e5SOllivier Robert ip = (struct info_peer_stats *)prepare_pkt(srcadr, inter, inpkt, 9629c2daa00SOllivier Robert v6sizeof(struct info_peer_stats)); 963c0b746e5SOllivier Robert while (items-- > 0 && ip != 0) { 9649c2daa00SOllivier Robert memset((char *)&addr, 0, sizeof(addr)); 9659c2daa00SOllivier Robert NSRCPORT(&addr) = ipl->port; 9669c2daa00SOllivier Robert if (client_v6_capable && ipl->v6_flag) { 9679c2daa00SOllivier Robert addr.ss_family = AF_INET6; 9689c2daa00SOllivier Robert GET_INADDR6(addr) = ipl->addr6; 9699c2daa00SOllivier Robert } else { 9709c2daa00SOllivier Robert addr.ss_family = AF_INET; 9719c2daa00SOllivier Robert GET_INADDR(addr) = ipl->addr; 9729c2daa00SOllivier Robert } 9739c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 9749c2daa00SOllivier Robert addr.ss_len = SOCKLEN(&addr); 9759c2daa00SOllivier Robert #endif 976ea906c41SOllivier Robert #ifdef DEBUG 977ea906c41SOllivier Robert if (debug) 9789c2daa00SOllivier Robert printf("peer_stats: looking for %s, %d, %d\n", stoa(&addr), 9799c2daa00SOllivier Robert ipl->port, ((struct sockaddr_in6 *)&addr)->sin6_port); 980ea906c41SOllivier Robert #endif 9819c2daa00SOllivier Robert ipl = (struct info_peer_list *)((char *)ipl + 9829c2daa00SOllivier Robert INFO_ITEMSIZE(inpkt->mbz_itemsize)); 9839c2daa00SOllivier Robert 984c0b746e5SOllivier Robert if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0) 985c0b746e5SOllivier Robert continue; 986ea906c41SOllivier Robert #ifdef DEBUG 987ea906c41SOllivier Robert if (debug) 9889c2daa00SOllivier Robert printf("peer_stats: found %s\n", stoa(&addr)); 989ea906c41SOllivier Robert #endif 9909c2daa00SOllivier Robert if (pp->srcadr.ss_family == AF_INET) { 991ea906c41SOllivier Robert if (pp->dstadr) 9929c2daa00SOllivier Robert ip->dstadr = (pp->processed) ? 9939c2daa00SOllivier Robert pp->cast_flags == MDF_BCAST ? 9949c2daa00SOllivier Robert GET_INADDR(pp->dstadr->bcast): 9959c2daa00SOllivier Robert pp->cast_flags ? 9969c2daa00SOllivier Robert GET_INADDR(pp->dstadr->sin) ? 9979c2daa00SOllivier Robert GET_INADDR(pp->dstadr->sin): 9989c2daa00SOllivier Robert GET_INADDR(pp->dstadr->bcast): 9999c2daa00SOllivier Robert 3 : 7; 1000ea906c41SOllivier Robert else 1001ea906c41SOllivier Robert memset(&ip->dstadr, 0, sizeof(ip->dstadr)); 1002ea906c41SOllivier Robert 10039c2daa00SOllivier Robert ip->srcadr = GET_INADDR(pp->srcadr); 10049c2daa00SOllivier Robert if (client_v6_capable) 10059c2daa00SOllivier Robert ip->v6_flag = 0; 10069c2daa00SOllivier Robert } else { 1007ea906c41SOllivier Robert if (pp->dstadr) 10089c2daa00SOllivier Robert ip->dstadr6 = pp->cast_flags == MDF_BCAST ? 10099c2daa00SOllivier Robert GET_INADDR6(pp->dstadr->bcast): 10109c2daa00SOllivier Robert GET_INADDR6(pp->dstadr->sin); 1011ea906c41SOllivier Robert else 1012ea906c41SOllivier Robert memset(&ip->dstadr6, 0, sizeof(ip->dstadr6)); 1013ea906c41SOllivier Robert 10149c2daa00SOllivier Robert ip->srcadr6 = GET_INADDR6(pp->srcadr); 10159c2daa00SOllivier Robert ip->v6_flag = 1; 10169c2daa00SOllivier Robert } 1017c0b746e5SOllivier Robert ip->srcport = NSRCPORT(&pp->srcadr); 1018c0b746e5SOllivier Robert ip->flags = 0; 1019c0b746e5SOllivier Robert if (pp == sys_peer) 1020c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SYSPEER; 1021c0b746e5SOllivier Robert if (pp->flags & FLAG_CONFIG) 1022c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_CONFIG; 1023c0b746e5SOllivier Robert if (pp->flags & FLAG_REFCLOCK) 1024c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_REFCLOCK; 1025c0b746e5SOllivier Robert if (pp->flags & FLAG_AUTHENABLE) 1026c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_AUTHENABLE; 1027c0b746e5SOllivier Robert if (pp->flags & FLAG_PREFER) 1028c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_PREFER; 1029c0b746e5SOllivier Robert if (pp->flags & FLAG_BURST) 1030c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_BURST; 1031ea906c41SOllivier Robert if (pp->flags & FLAG_IBURST) 1032ea906c41SOllivier Robert ip->flags |= INFO_FLAG_IBURST; 1033c0b746e5SOllivier Robert if (pp->status == CTL_PST_SEL_SYNCCAND) 1034c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SEL_CANDIDATE; 1035c0b746e5SOllivier Robert if (pp->status >= CTL_PST_SEL_SYSPEER) 1036c0b746e5SOllivier Robert ip->flags |= INFO_FLAG_SHORTLIST; 1037ea906c41SOllivier Robert ip->flags = htons(ip->flags); 1038c0b746e5SOllivier Robert ip->timereceived = htonl((u_int32)(current_time - pp->timereceived)); 1039c0b746e5SOllivier Robert ip->timetosend = htonl(pp->nextdate - current_time); 1040c0b746e5SOllivier Robert ip->timereachable = htonl((u_int32)(current_time - pp->timereachable)); 1041c0b746e5SOllivier Robert ip->sent = htonl((u_int32)(pp->sent)); 1042c0b746e5SOllivier Robert ip->processed = htonl((u_int32)(pp->processed)); 1043c0b746e5SOllivier Robert ip->badauth = htonl((u_int32)(pp->badauth)); 1044c0b746e5SOllivier Robert ip->bogusorg = htonl((u_int32)(pp->bogusorg)); 1045c0b746e5SOllivier Robert ip->oldpkt = htonl((u_int32)(pp->oldpkt)); 1046c0b746e5SOllivier Robert ip->seldisp = htonl((u_int32)(pp->seldisptoolarge)); 1047c0b746e5SOllivier Robert ip->selbroken = htonl((u_int32)(pp->selbroken)); 1048c0b746e5SOllivier Robert ip->candidate = pp->status; 1049c0b746e5SOllivier Robert ip = (struct info_peer_stats *)more_pkt(); 1050c0b746e5SOllivier Robert } 1051c0b746e5SOllivier Robert flush_pkt(); 1052c0b746e5SOllivier Robert } 1053c0b746e5SOllivier Robert 1054c0b746e5SOllivier Robert 1055c0b746e5SOllivier Robert /* 1056c0b746e5SOllivier Robert * sys_info - return system info 1057c0b746e5SOllivier Robert */ 1058c0b746e5SOllivier Robert static void 1059c0b746e5SOllivier Robert sys_info( 10609c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1061c0b746e5SOllivier Robert struct interface *inter, 1062c0b746e5SOllivier Robert struct req_pkt *inpkt 1063c0b746e5SOllivier Robert ) 1064c0b746e5SOllivier Robert { 1065c0b746e5SOllivier Robert register struct info_sys *is; 1066c0b746e5SOllivier Robert 1067c0b746e5SOllivier Robert is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt, 10689c2daa00SOllivier Robert v6sizeof(struct info_sys)); 1069c0b746e5SOllivier Robert 1070c0b746e5SOllivier Robert if (sys_peer != 0) { 10719c2daa00SOllivier Robert if (sys_peer->srcadr.ss_family == AF_INET) { 10729c2daa00SOllivier Robert is->peer = GET_INADDR(sys_peer->srcadr); 10739c2daa00SOllivier Robert if (client_v6_capable) 10749c2daa00SOllivier Robert is->v6_flag = 0; 10759c2daa00SOllivier Robert } else if (client_v6_capable) { 10769c2daa00SOllivier Robert is->peer6 = GET_INADDR6(sys_peer->srcadr); 10779c2daa00SOllivier Robert is->v6_flag = 1; 10789c2daa00SOllivier Robert } 1079c0b746e5SOllivier Robert is->peer_mode = sys_peer->hmode; 1080c0b746e5SOllivier Robert } else { 1081c0b746e5SOllivier Robert is->peer = 0; 10829c2daa00SOllivier Robert if (client_v6_capable) { 10839c2daa00SOllivier Robert is->v6_flag = 0; 10849c2daa00SOllivier Robert } 1085c0b746e5SOllivier Robert is->peer_mode = 0; 1086c0b746e5SOllivier Robert } 10879c2daa00SOllivier Robert 1088c0b746e5SOllivier Robert is->leap = sys_leap; 1089c0b746e5SOllivier Robert is->stratum = sys_stratum; 1090c0b746e5SOllivier Robert is->precision = sys_precision; 1091c0b746e5SOllivier Robert is->rootdelay = htonl(DTOFP(sys_rootdelay)); 1092c0b746e5SOllivier Robert is->rootdispersion = htonl(DTOUFP(sys_rootdispersion)); 1093224ba2bdSOllivier Robert is->frequency = htonl(DTOFP(sys_jitter)); 1094ea906c41SOllivier Robert is->stability = htonl(DTOUFP(clock_stability)); 1095c0b746e5SOllivier Robert is->refid = sys_refid; 1096c0b746e5SOllivier Robert HTONL_FP(&sys_reftime, &is->reftime); 1097c0b746e5SOllivier Robert 1098c0b746e5SOllivier Robert is->poll = sys_poll; 1099c0b746e5SOllivier Robert 1100c0b746e5SOllivier Robert is->flags = 0; 1101c0b746e5SOllivier Robert if (sys_authenticate) 1102c0b746e5SOllivier Robert is->flags |= INFO_FLAG_AUTHENTICATE; 1103ce265a54SOllivier Robert if (sys_bclient) 1104ce265a54SOllivier Robert is->flags |= INFO_FLAG_BCLIENT; 1105ce265a54SOllivier Robert #ifdef REFCLOCK 1106ce265a54SOllivier Robert if (cal_enable) 1107ce265a54SOllivier Robert is->flags |= INFO_FLAG_CAL; 1108ce265a54SOllivier Robert #endif /* REFCLOCK */ 1109c0b746e5SOllivier Robert if (kern_enable) 1110c0b746e5SOllivier Robert is->flags |= INFO_FLAG_KERNEL; 1111c0b746e5SOllivier Robert if (mon_enabled != MON_OFF) 1112c0b746e5SOllivier Robert is->flags |= INFO_FLAG_MONITOR; 1113ce265a54SOllivier Robert if (ntp_enable) 1114ce265a54SOllivier Robert is->flags |= INFO_FLAG_NTP; 1115ce265a54SOllivier Robert if (pps_enable) 1116ce265a54SOllivier Robert is->flags |= INFO_FLAG_PPS_SYNC; 1117c0b746e5SOllivier Robert if (stats_control) 1118c0b746e5SOllivier Robert is->flags |= INFO_FLAG_FILEGEN; 1119c0b746e5SOllivier Robert is->bdelay = HTONS_FP(DTOFP(sys_bdelay)); 1120c0b746e5SOllivier Robert HTONL_UF(sys_authdelay.l_f, &is->authdelay); 1121c0b746e5SOllivier Robert 1122c0b746e5SOllivier Robert (void) more_pkt(); 1123c0b746e5SOllivier Robert flush_pkt(); 1124c0b746e5SOllivier Robert } 1125c0b746e5SOllivier Robert 1126c0b746e5SOllivier Robert 1127c0b746e5SOllivier Robert /* 1128c0b746e5SOllivier Robert * sys_stats - return system statistics 1129c0b746e5SOllivier Robert */ 1130c0b746e5SOllivier Robert static void 1131c0b746e5SOllivier Robert sys_stats( 11329c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1133c0b746e5SOllivier Robert struct interface *inter, 1134c0b746e5SOllivier Robert struct req_pkt *inpkt 1135c0b746e5SOllivier Robert ) 1136c0b746e5SOllivier Robert { 1137c0b746e5SOllivier Robert register struct info_sys_stats *ss; 1138c0b746e5SOllivier Robert 1139c0b746e5SOllivier Robert /* 1140c0b746e5SOllivier Robert * Importations from the protocol module 1141c0b746e5SOllivier Robert */ 1142c0b746e5SOllivier Robert ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt, 1143c0b746e5SOllivier Robert sizeof(struct info_sys_stats)); 1144c0b746e5SOllivier Robert ss->timeup = htonl((u_int32)current_time); 1145c0b746e5SOllivier Robert ss->timereset = htonl((u_int32)(current_time - sys_stattime)); 11469c2daa00SOllivier Robert ss->denied = htonl((u_int32)sys_restricted); 1147c0b746e5SOllivier Robert ss->oldversionpkt = htonl((u_int32)sys_oldversionpkt); 1148c0b746e5SOllivier Robert ss->newversionpkt = htonl((u_int32)sys_newversionpkt); 1149c0b746e5SOllivier Robert ss->unknownversion = htonl((u_int32)sys_unknownversion); 1150c0b746e5SOllivier Robert ss->badlength = htonl((u_int32)sys_badlength); 1151c0b746e5SOllivier Robert ss->processed = htonl((u_int32)sys_processed); 1152c0b746e5SOllivier Robert ss->badauth = htonl((u_int32)sys_badauth); 1153c0b746e5SOllivier Robert ss->limitrejected = htonl((u_int32)sys_limitrejected); 11549c2daa00SOllivier Robert ss->received = htonl((u_int32)sys_received); 1155c0b746e5SOllivier Robert (void) more_pkt(); 1156c0b746e5SOllivier Robert flush_pkt(); 1157c0b746e5SOllivier Robert } 1158c0b746e5SOllivier Robert 1159c0b746e5SOllivier Robert 1160c0b746e5SOllivier Robert /* 1161c0b746e5SOllivier Robert * mem_stats - return memory statistics 1162c0b746e5SOllivier Robert */ 1163c0b746e5SOllivier Robert static void 1164c0b746e5SOllivier Robert mem_stats( 11659c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1166c0b746e5SOllivier Robert struct interface *inter, 1167c0b746e5SOllivier Robert struct req_pkt *inpkt 1168c0b746e5SOllivier Robert ) 1169c0b746e5SOllivier Robert { 1170c0b746e5SOllivier Robert register struct info_mem_stats *ms; 1171c0b746e5SOllivier Robert register int i; 1172c0b746e5SOllivier Robert 1173c0b746e5SOllivier Robert /* 1174c0b746e5SOllivier Robert * Importations from the peer module 1175c0b746e5SOllivier Robert */ 1176ea906c41SOllivier Robert extern int peer_hash_count[NTP_HASH_SIZE]; 1177c0b746e5SOllivier Robert extern int peer_free_count; 1178c0b746e5SOllivier Robert extern u_long peer_timereset; 1179c0b746e5SOllivier Robert extern u_long findpeer_calls; 1180c0b746e5SOllivier Robert extern u_long peer_allocations; 1181c0b746e5SOllivier Robert extern u_long peer_demobilizations; 1182c0b746e5SOllivier Robert extern int total_peer_structs; 1183c0b746e5SOllivier Robert 1184c0b746e5SOllivier Robert ms = (struct info_mem_stats *)prepare_pkt(srcadr, inter, inpkt, 1185c0b746e5SOllivier Robert sizeof(struct info_mem_stats)); 1186c0b746e5SOllivier Robert 1187c0b746e5SOllivier Robert ms->timereset = htonl((u_int32)(current_time - peer_timereset)); 1188c0b746e5SOllivier Robert ms->totalpeermem = htons((u_short)total_peer_structs); 1189c0b746e5SOllivier Robert ms->freepeermem = htons((u_short)peer_free_count); 1190c0b746e5SOllivier Robert ms->findpeer_calls = htonl((u_int32)findpeer_calls); 1191c0b746e5SOllivier Robert ms->allocations = htonl((u_int32)peer_allocations); 1192c0b746e5SOllivier Robert ms->demobilizations = htonl((u_int32)peer_demobilizations); 1193c0b746e5SOllivier Robert 1194ea906c41SOllivier Robert for (i = 0; i < NTP_HASH_SIZE; i++) { 1195c0b746e5SOllivier Robert if (peer_hash_count[i] > 255) 1196c0b746e5SOllivier Robert ms->hashcount[i] = 255; 1197c0b746e5SOllivier Robert else 1198c0b746e5SOllivier Robert ms->hashcount[i] = (u_char)peer_hash_count[i]; 1199c0b746e5SOllivier Robert } 1200c0b746e5SOllivier Robert 1201c0b746e5SOllivier Robert (void) more_pkt(); 1202c0b746e5SOllivier Robert flush_pkt(); 1203c0b746e5SOllivier Robert } 1204c0b746e5SOllivier Robert 1205c0b746e5SOllivier Robert 1206c0b746e5SOllivier Robert /* 1207c0b746e5SOllivier Robert * io_stats - return io statistics 1208c0b746e5SOllivier Robert */ 1209c0b746e5SOllivier Robert static void 1210c0b746e5SOllivier Robert io_stats( 12119c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1212c0b746e5SOllivier Robert struct interface *inter, 1213c0b746e5SOllivier Robert struct req_pkt *inpkt 1214c0b746e5SOllivier Robert ) 1215c0b746e5SOllivier Robert { 1216c0b746e5SOllivier Robert register struct info_io_stats *io; 1217c0b746e5SOllivier Robert 1218c0b746e5SOllivier Robert /* 1219c0b746e5SOllivier Robert * Importations from the io module 1220c0b746e5SOllivier Robert */ 1221c0b746e5SOllivier Robert extern u_long io_timereset; 1222c0b746e5SOllivier Robert 1223c0b746e5SOllivier Robert io = (struct info_io_stats *)prepare_pkt(srcadr, inter, inpkt, 1224c0b746e5SOllivier Robert sizeof(struct info_io_stats)); 1225c0b746e5SOllivier Robert 1226c0b746e5SOllivier Robert io->timereset = htonl((u_int32)(current_time - io_timereset)); 1227c0b746e5SOllivier Robert io->totalrecvbufs = htons((u_short) total_recvbuffs()); 1228c0b746e5SOllivier Robert io->freerecvbufs = htons((u_short) free_recvbuffs()); 1229c0b746e5SOllivier Robert io->fullrecvbufs = htons((u_short) full_recvbuffs()); 1230c0b746e5SOllivier Robert io->lowwater = htons((u_short) lowater_additions()); 1231c0b746e5SOllivier Robert io->dropped = htonl((u_int32)packets_dropped); 1232c0b746e5SOllivier Robert io->ignored = htonl((u_int32)packets_ignored); 1233c0b746e5SOllivier Robert io->received = htonl((u_int32)packets_received); 1234c0b746e5SOllivier Robert io->sent = htonl((u_int32)packets_sent); 1235c0b746e5SOllivier Robert io->notsent = htonl((u_int32)packets_notsent); 1236c0b746e5SOllivier Robert io->interrupts = htonl((u_int32)handler_calls); 1237c0b746e5SOllivier Robert io->int_received = htonl((u_int32)handler_pkts); 1238c0b746e5SOllivier Robert 1239c0b746e5SOllivier Robert (void) more_pkt(); 1240c0b746e5SOllivier Robert flush_pkt(); 1241c0b746e5SOllivier Robert } 1242c0b746e5SOllivier Robert 1243c0b746e5SOllivier Robert 1244c0b746e5SOllivier Robert /* 1245c0b746e5SOllivier Robert * timer_stats - return timer statistics 1246c0b746e5SOllivier Robert */ 1247c0b746e5SOllivier Robert static void 1248c0b746e5SOllivier Robert timer_stats( 12499c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1250c0b746e5SOllivier Robert struct interface *inter, 1251c0b746e5SOllivier Robert struct req_pkt *inpkt 1252c0b746e5SOllivier Robert ) 1253c0b746e5SOllivier Robert { 1254c0b746e5SOllivier Robert register struct info_timer_stats *ts; 1255c0b746e5SOllivier Robert 1256c0b746e5SOllivier Robert /* 1257c0b746e5SOllivier Robert * Importations from the timer module 1258c0b746e5SOllivier Robert */ 1259c0b746e5SOllivier Robert extern u_long timer_timereset; 1260c0b746e5SOllivier Robert extern u_long timer_overflows; 1261c0b746e5SOllivier Robert extern u_long timer_xmtcalls; 1262c0b746e5SOllivier Robert 1263c0b746e5SOllivier Robert ts = (struct info_timer_stats *)prepare_pkt(srcadr, inter, inpkt, 1264c0b746e5SOllivier Robert sizeof(struct info_timer_stats)); 1265c0b746e5SOllivier Robert 1266c0b746e5SOllivier Robert ts->timereset = htonl((u_int32)(current_time - timer_timereset)); 1267c0b746e5SOllivier Robert ts->alarms = htonl((u_int32)alarm_overflow); 1268c0b746e5SOllivier Robert ts->overflows = htonl((u_int32)timer_overflows); 1269c0b746e5SOllivier Robert ts->xmtcalls = htonl((u_int32)timer_xmtcalls); 1270c0b746e5SOllivier Robert 1271c0b746e5SOllivier Robert (void) more_pkt(); 1272c0b746e5SOllivier Robert flush_pkt(); 1273c0b746e5SOllivier Robert } 1274c0b746e5SOllivier Robert 1275c0b746e5SOllivier Robert 1276c0b746e5SOllivier Robert /* 1277c0b746e5SOllivier Robert * loop_info - return the current state of the loop filter 1278c0b746e5SOllivier Robert */ 1279c0b746e5SOllivier Robert static void 1280c0b746e5SOllivier Robert loop_info( 12819c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1282c0b746e5SOllivier Robert struct interface *inter, 1283c0b746e5SOllivier Robert struct req_pkt *inpkt 1284c0b746e5SOllivier Robert ) 1285c0b746e5SOllivier Robert { 1286c0b746e5SOllivier Robert register struct info_loop *li; 1287c0b746e5SOllivier Robert l_fp ltmp; 1288c0b746e5SOllivier Robert 1289c0b746e5SOllivier Robert /* 1290c0b746e5SOllivier Robert * Importations from the loop filter module 1291c0b746e5SOllivier Robert */ 1292c0b746e5SOllivier Robert extern double last_offset; 1293c0b746e5SOllivier Robert extern double drift_comp; 1294c0b746e5SOllivier Robert extern int tc_counter; 1295ea906c41SOllivier Robert extern u_long sys_clocktime; 1296c0b746e5SOllivier Robert 1297c0b746e5SOllivier Robert li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt, 1298c0b746e5SOllivier Robert sizeof(struct info_loop)); 1299c0b746e5SOllivier Robert 1300c0b746e5SOllivier Robert DTOLFP(last_offset, <mp); 1301c0b746e5SOllivier Robert HTONL_FP(<mp, &li->last_offset); 1302c0b746e5SOllivier Robert DTOLFP(drift_comp * 1e6, <mp); 1303c0b746e5SOllivier Robert HTONL_FP(<mp, &li->drift_comp); 1304c0b746e5SOllivier Robert li->compliance = htonl((u_int32)(tc_counter)); 1305ea906c41SOllivier Robert li->watchdog_timer = htonl((u_int32)(current_time - sys_clocktime)); 1306c0b746e5SOllivier Robert 1307c0b746e5SOllivier Robert (void) more_pkt(); 1308c0b746e5SOllivier Robert flush_pkt(); 1309c0b746e5SOllivier Robert } 1310c0b746e5SOllivier Robert 1311c0b746e5SOllivier Robert 1312c0b746e5SOllivier Robert /* 1313c0b746e5SOllivier Robert * do_conf - add a peer to the configuration list 1314c0b746e5SOllivier Robert */ 1315c0b746e5SOllivier Robert static void 1316c0b746e5SOllivier Robert do_conf( 13179c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1318c0b746e5SOllivier Robert struct interface *inter, 1319c0b746e5SOllivier Robert struct req_pkt *inpkt 1320c0b746e5SOllivier Robert ) 1321c0b746e5SOllivier Robert { 13229c2daa00SOllivier Robert int items; 1323224ba2bdSOllivier Robert u_int fl; 1324ce265a54SOllivier Robert struct conf_peer *cp; 13259c2daa00SOllivier Robert struct conf_peer temp_cp; 13269c2daa00SOllivier Robert struct sockaddr_storage peeraddr; 13279c2daa00SOllivier Robert struct sockaddr_in tmp_clock; 1328c0b746e5SOllivier Robert 1329c0b746e5SOllivier Robert /* 1330c0b746e5SOllivier Robert * Do a check of everything to see that it looks 1331c0b746e5SOllivier Robert * okay. If not, complain about it. Note we are 1332c0b746e5SOllivier Robert * very picky here. 1333c0b746e5SOllivier Robert */ 1334c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1335c0b746e5SOllivier Robert cp = (struct conf_peer *)inpkt->data; 13369c2daa00SOllivier Robert memset(&temp_cp, 0, sizeof(struct conf_peer)); 13379c2daa00SOllivier Robert memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize)); 1338c0b746e5SOllivier Robert fl = 0; 1339c0b746e5SOllivier Robert while (items-- > 0 && !fl) { 13409c2daa00SOllivier Robert if (((temp_cp.version) > NTP_VERSION) 13419c2daa00SOllivier Robert || ((temp_cp.version) < NTP_OLDVERSION)) 1342c0b746e5SOllivier Robert fl = 1; 13439c2daa00SOllivier Robert if (temp_cp.hmode != MODE_ACTIVE 13449c2daa00SOllivier Robert && temp_cp.hmode != MODE_CLIENT 13459c2daa00SOllivier Robert && temp_cp.hmode != MODE_BROADCAST) 1346c0b746e5SOllivier Robert fl = 1; 13479c2daa00SOllivier Robert if (temp_cp.flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER 1348ea906c41SOllivier Robert | CONF_FLAG_BURST | CONF_FLAG_IBURST | CONF_FLAG_SKEY)) 1349c0b746e5SOllivier Robert fl = 1; 13509c2daa00SOllivier Robert cp = (struct conf_peer *) 13519c2daa00SOllivier Robert ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize)); 1352c0b746e5SOllivier Robert } 1353c0b746e5SOllivier Robert 1354c0b746e5SOllivier Robert if (fl) { 1355c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1356c0b746e5SOllivier Robert return; 1357c0b746e5SOllivier Robert } 1358c0b746e5SOllivier Robert 1359c0b746e5SOllivier Robert /* 1360c0b746e5SOllivier Robert * Looks okay, try it out 1361c0b746e5SOllivier Robert */ 1362c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1363c0b746e5SOllivier Robert cp = (struct conf_peer *)inpkt->data; 1364c0b746e5SOllivier Robert 13659c2daa00SOllivier Robert while (items-- > 0) { 13669c2daa00SOllivier Robert memset(&temp_cp, 0, sizeof(struct conf_peer)); 13679c2daa00SOllivier Robert memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize)); 13689c2daa00SOllivier Robert memset((char *)&peeraddr, 0, sizeof(struct sockaddr_storage)); 13699c2daa00SOllivier Robert 13709c2daa00SOllivier Robert fl = 0; 13719c2daa00SOllivier Robert if (temp_cp.flags & CONF_FLAG_AUTHENABLE) 13729c2daa00SOllivier Robert fl |= FLAG_AUTHENABLE; 13739c2daa00SOllivier Robert if (temp_cp.flags & CONF_FLAG_PREFER) 13749c2daa00SOllivier Robert fl |= FLAG_PREFER; 13759c2daa00SOllivier Robert if (temp_cp.flags & CONF_FLAG_BURST) 13769c2daa00SOllivier Robert fl |= FLAG_BURST; 1377ea906c41SOllivier Robert if (temp_cp.flags & CONF_FLAG_IBURST) 1378ea906c41SOllivier Robert fl |= FLAG_IBURST; 13799c2daa00SOllivier Robert if (temp_cp.flags & CONF_FLAG_SKEY) 13809c2daa00SOllivier Robert fl |= FLAG_SKEY; 1381ea906c41SOllivier Robert 13829c2daa00SOllivier Robert if (client_v6_capable && temp_cp.v6_flag != 0) { 13839c2daa00SOllivier Robert peeraddr.ss_family = AF_INET6; 13849c2daa00SOllivier Robert GET_INADDR6(peeraddr) = temp_cp.peeraddr6; 13859c2daa00SOllivier Robert } else { 13869c2daa00SOllivier Robert peeraddr.ss_family = AF_INET; 13879c2daa00SOllivier Robert GET_INADDR(peeraddr) = temp_cp.peeraddr; 1388c0b746e5SOllivier Robert /* 1389c0b746e5SOllivier Robert * Make sure the address is valid 1390c0b746e5SOllivier Robert */ 13919c2daa00SOllivier Robert tmp_clock = *CAST_V4(peeraddr); 1392c0b746e5SOllivier Robert if ( 1393c0b746e5SOllivier Robert #ifdef REFCLOCK 13949c2daa00SOllivier Robert !ISREFCLOCKADR(&tmp_clock) && 1395c0b746e5SOllivier Robert #endif 13969c2daa00SOllivier Robert ISBADADR(&tmp_clock)) { 1397c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1398c0b746e5SOllivier Robert return; 1399c0b746e5SOllivier Robert } 1400c0b746e5SOllivier Robert 14019c2daa00SOllivier Robert } 14029c2daa00SOllivier Robert NSRCPORT(&peeraddr) = htons(NTP_PORT); 14039c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 14049c2daa00SOllivier Robert peeraddr.ss_len = SOCKLEN(&peeraddr); 14059c2daa00SOllivier Robert #endif 14069c2daa00SOllivier Robert 1407c0b746e5SOllivier Robert /* XXX W2DO? minpoll/maxpoll arguments ??? */ 14089c2daa00SOllivier Robert if (peer_config(&peeraddr, (struct interface *)0, 14099c2daa00SOllivier Robert temp_cp.hmode, temp_cp.version, temp_cp.minpoll, 14109c2daa00SOllivier Robert temp_cp.maxpoll, fl, temp_cp.ttl, temp_cp.keyid, 14119c2daa00SOllivier Robert NULL) == 0) { 1412c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1413c0b746e5SOllivier Robert return; 1414c0b746e5SOllivier Robert } 14159c2daa00SOllivier Robert cp = (struct conf_peer *) 14169c2daa00SOllivier Robert ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize)); 1417c0b746e5SOllivier Robert } 1418c0b746e5SOllivier Robert 1419c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1420c0b746e5SOllivier Robert } 1421c0b746e5SOllivier Robert 14229c2daa00SOllivier Robert #if 0 14239c2daa00SOllivier Robert /* XXX */ 1424c0b746e5SOllivier Robert /* 1425224ba2bdSOllivier Robert * dns_a - Snarf DNS info for an association ID 1426224ba2bdSOllivier Robert */ 1427224ba2bdSOllivier Robert static void 1428224ba2bdSOllivier Robert dns_a( 14299c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1430224ba2bdSOllivier Robert struct interface *inter, 1431224ba2bdSOllivier Robert struct req_pkt *inpkt 1432224ba2bdSOllivier Robert ) 1433224ba2bdSOllivier Robert { 1434224ba2bdSOllivier Robert register struct info_dns_assoc *dp; 1435224ba2bdSOllivier Robert register int items; 1436224ba2bdSOllivier Robert struct sockaddr_in peeraddr; 1437224ba2bdSOllivier Robert 1438224ba2bdSOllivier Robert /* 1439224ba2bdSOllivier Robert * Do a check of everything to see that it looks 1440224ba2bdSOllivier Robert * okay. If not, complain about it. Note we are 1441224ba2bdSOllivier Robert * very picky here. 1442224ba2bdSOllivier Robert */ 1443224ba2bdSOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1444224ba2bdSOllivier Robert dp = (struct info_dns_assoc *)inpkt->data; 1445224ba2bdSOllivier Robert 1446224ba2bdSOllivier Robert /* 1447224ba2bdSOllivier Robert * Looks okay, try it out 1448224ba2bdSOllivier Robert */ 1449224ba2bdSOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1450224ba2bdSOllivier Robert dp = (struct info_dns_assoc *)inpkt->data; 1451224ba2bdSOllivier Robert memset((char *)&peeraddr, 0, sizeof(struct sockaddr_in)); 1452224ba2bdSOllivier Robert peeraddr.sin_family = AF_INET; 1453224ba2bdSOllivier Robert peeraddr.sin_port = htons(NTP_PORT); 1454224ba2bdSOllivier Robert 1455224ba2bdSOllivier Robert /* 1456224ba2bdSOllivier Robert * Make sure the address is valid 1457224ba2bdSOllivier Robert */ 1458224ba2bdSOllivier Robert if ( 1459224ba2bdSOllivier Robert #ifdef REFCLOCK 1460224ba2bdSOllivier Robert !ISREFCLOCKADR(&peeraddr) && 1461224ba2bdSOllivier Robert #endif 1462224ba2bdSOllivier Robert ISBADADR(&peeraddr)) { 1463224ba2bdSOllivier Robert #ifdef REFCLOCK 1464224ba2bdSOllivier Robert msyslog(LOG_ERR, "dns_a: !ISREFCLOCK && ISBADADR"); 1465224ba2bdSOllivier Robert #else 1466224ba2bdSOllivier Robert msyslog(LOG_ERR, "dns_a: ISBADADR"); 1467224ba2bdSOllivier Robert #endif 1468224ba2bdSOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1469224ba2bdSOllivier Robert return; 1470224ba2bdSOllivier Robert } 1471224ba2bdSOllivier Robert 1472224ba2bdSOllivier Robert while (items-- > 0) { 1473224ba2bdSOllivier Robert associd_t associd; 1474224ba2bdSOllivier Robert size_t hnl; 1475224ba2bdSOllivier Robert struct peer *peer; 1476224ba2bdSOllivier Robert int bogon = 0; 1477224ba2bdSOllivier Robert 1478224ba2bdSOllivier Robert associd = dp->associd; 1479224ba2bdSOllivier Robert peer = findpeerbyassoc(associd); 1480224ba2bdSOllivier Robert if (peer == 0 || peer->flags & FLAG_REFCLOCK) { 1481224ba2bdSOllivier Robert msyslog(LOG_ERR, "dns_a: %s", 1482224ba2bdSOllivier Robert (peer == 0) 1483224ba2bdSOllivier Robert ? "peer == 0" 1484224ba2bdSOllivier Robert : "peer->flags & FLAG_REFCLOCK"); 1485224ba2bdSOllivier Robert ++bogon; 1486224ba2bdSOllivier Robert } 1487224ba2bdSOllivier Robert peeraddr.sin_addr.s_addr = dp->peeraddr; 1488224ba2bdSOllivier Robert for (hnl = 0; dp->hostname[hnl] && hnl < sizeof dp->hostname; ++hnl) ; 1489224ba2bdSOllivier Robert if (hnl >= sizeof dp->hostname) { 1490224ba2bdSOllivier Robert msyslog(LOG_ERR, "dns_a: hnl (%ld) >= %ld", 1491224ba2bdSOllivier Robert (long)hnl, (long)sizeof dp->hostname); 1492224ba2bdSOllivier Robert ++bogon; 1493224ba2bdSOllivier Robert } 1494224ba2bdSOllivier Robert 1495224ba2bdSOllivier Robert msyslog(LOG_INFO, "dns_a: <%s> for %s, AssocID %d, bogon %d", 14969c2daa00SOllivier Robert dp->hostname, 14979c2daa00SOllivier Robert stoa((struct sockaddr_storage *)&peeraddr), associd, 1498224ba2bdSOllivier Robert bogon); 1499224ba2bdSOllivier Robert 1500224ba2bdSOllivier Robert if (bogon) { 1501224ba2bdSOllivier Robert /* If it didn't work */ 1502224ba2bdSOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1503224ba2bdSOllivier Robert return; 1504224ba2bdSOllivier Robert } else { 1505224ba2bdSOllivier Robert #if 0 1506224ba2bdSOllivier Robert #ifdef PUBKEY 1507224ba2bdSOllivier Robert crypto_public(peer, dp->hostname); 1508224ba2bdSOllivier Robert #endif /* PUBKEY */ 1509224ba2bdSOllivier Robert #endif 1510224ba2bdSOllivier Robert } 1511224ba2bdSOllivier Robert 1512224ba2bdSOllivier Robert dp++; 1513224ba2bdSOllivier Robert } 1514224ba2bdSOllivier Robert 1515224ba2bdSOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1516224ba2bdSOllivier Robert } 15179c2daa00SOllivier Robert #endif /* 0 */ 1518224ba2bdSOllivier Robert 1519224ba2bdSOllivier Robert /* 1520c0b746e5SOllivier Robert * do_unconf - remove a peer from the configuration list 1521c0b746e5SOllivier Robert */ 1522c0b746e5SOllivier Robert static void 1523c0b746e5SOllivier Robert do_unconf( 15249c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1525c0b746e5SOllivier Robert struct interface *inter, 1526c0b746e5SOllivier Robert struct req_pkt *inpkt 1527c0b746e5SOllivier Robert ) 1528c0b746e5SOllivier Robert { 1529c0b746e5SOllivier Robert register struct conf_unpeer *cp; 15309c2daa00SOllivier Robert struct conf_unpeer temp_cp; 1531c0b746e5SOllivier Robert register int items; 1532c0b746e5SOllivier Robert register struct peer *peer; 15339c2daa00SOllivier Robert struct sockaddr_storage peeraddr; 1534c0b746e5SOllivier Robert int bad, found; 1535c0b746e5SOllivier Robert 1536c0b746e5SOllivier Robert /* 1537c0b746e5SOllivier Robert * This is a bit unstructured, but I like to be careful. 1538c0b746e5SOllivier Robert * We check to see that every peer exists and is actually 1539c0b746e5SOllivier Robert * configured. If so, we remove them. If not, we return 1540c0b746e5SOllivier Robert * an error. 1541c0b746e5SOllivier Robert */ 1542c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1543c0b746e5SOllivier Robert cp = (struct conf_unpeer *)inpkt->data; 1544c0b746e5SOllivier Robert 1545c0b746e5SOllivier Robert bad = 0; 1546c0b746e5SOllivier Robert while (items-- > 0 && !bad) { 15479c2daa00SOllivier Robert memset(&temp_cp, 0, sizeof(temp_cp)); 15489c2daa00SOllivier Robert memset(&peeraddr, 0, sizeof(peeraddr)); 15499c2daa00SOllivier Robert memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize)); 15509c2daa00SOllivier Robert if (client_v6_capable && temp_cp.v6_flag != 0) { 15519c2daa00SOllivier Robert peeraddr.ss_family = AF_INET6; 15529c2daa00SOllivier Robert GET_INADDR6(peeraddr) = temp_cp.peeraddr6; 15539c2daa00SOllivier Robert } else { 15549c2daa00SOllivier Robert peeraddr.ss_family = AF_INET; 15559c2daa00SOllivier Robert GET_INADDR(peeraddr) = temp_cp.peeraddr; 15569c2daa00SOllivier Robert } 15579c2daa00SOllivier Robert NSRCPORT(&peeraddr) = htons(NTP_PORT); 15589c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 15599c2daa00SOllivier Robert peeraddr.ss_len = SOCKLEN(&peeraddr); 15609c2daa00SOllivier Robert #endif 1561c0b746e5SOllivier Robert found = 0; 1562c0b746e5SOllivier Robert peer = (struct peer *)0; 1563ea906c41SOllivier Robert #ifdef DEBUG 1564ea906c41SOllivier Robert if (debug) 15659c2daa00SOllivier Robert printf("searching for %s\n", stoa(&peeraddr)); 1566ea906c41SOllivier Robert #endif 1567c0b746e5SOllivier Robert while (!found) { 1568c0b746e5SOllivier Robert peer = findexistingpeer(&peeraddr, peer, -1); 1569c0b746e5SOllivier Robert if (peer == (struct peer *)0) 1570c0b746e5SOllivier Robert break; 1571c0b746e5SOllivier Robert if (peer->flags & FLAG_CONFIG) 1572c0b746e5SOllivier Robert found = 1; 1573c0b746e5SOllivier Robert } 1574c0b746e5SOllivier Robert if (!found) 1575c0b746e5SOllivier Robert bad = 1; 15769c2daa00SOllivier Robert cp = (struct conf_unpeer *) 15779c2daa00SOllivier Robert ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize)); 1578c0b746e5SOllivier Robert } 1579c0b746e5SOllivier Robert 1580c0b746e5SOllivier Robert if (bad) { 1581c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1582c0b746e5SOllivier Robert return; 1583c0b746e5SOllivier Robert } 1584c0b746e5SOllivier Robert 1585c0b746e5SOllivier Robert /* 1586c0b746e5SOllivier Robert * Now do it in earnest. 1587c0b746e5SOllivier Robert */ 1588c0b746e5SOllivier Robert 1589c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1590c0b746e5SOllivier Robert cp = (struct conf_unpeer *)inpkt->data; 1591c0b746e5SOllivier Robert while (items-- > 0) { 15929c2daa00SOllivier Robert memset(&temp_cp, 0, sizeof(temp_cp)); 15939c2daa00SOllivier Robert memset(&peeraddr, 0, sizeof(peeraddr)); 15949c2daa00SOllivier Robert memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize)); 15959c2daa00SOllivier Robert if (client_v6_capable && temp_cp.v6_flag != 0) { 15969c2daa00SOllivier Robert peeraddr.ss_family = AF_INET6; 15979c2daa00SOllivier Robert GET_INADDR6(peeraddr) = temp_cp.peeraddr6; 15989c2daa00SOllivier Robert } else { 15999c2daa00SOllivier Robert peeraddr.ss_family = AF_INET; 16009c2daa00SOllivier Robert GET_INADDR(peeraddr) = temp_cp.peeraddr; 16019c2daa00SOllivier Robert } 16029c2daa00SOllivier Robert NSRCPORT(&peeraddr) = htons(NTP_PORT); 16039c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 16049c2daa00SOllivier Robert peeraddr.ss_len = SOCKLEN(&peeraddr); 16059c2daa00SOllivier Robert #endif 1606c0b746e5SOllivier Robert peer_unconfig(&peeraddr, (struct interface *)0, -1); 16079c2daa00SOllivier Robert cp = (struct conf_unpeer *) 16089c2daa00SOllivier Robert ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize)); 1609c0b746e5SOllivier Robert } 1610c0b746e5SOllivier Robert 1611c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1612c0b746e5SOllivier Robert } 1613c0b746e5SOllivier Robert 1614c0b746e5SOllivier Robert 1615c0b746e5SOllivier Robert /* 1616c0b746e5SOllivier Robert * set_sys_flag - set system flags 1617c0b746e5SOllivier Robert */ 1618c0b746e5SOllivier Robert static void 1619c0b746e5SOllivier Robert set_sys_flag( 16209c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1621c0b746e5SOllivier Robert struct interface *inter, 1622c0b746e5SOllivier Robert struct req_pkt *inpkt 1623c0b746e5SOllivier Robert ) 1624c0b746e5SOllivier Robert { 1625c0b746e5SOllivier Robert setclr_flags(srcadr, inter, inpkt, 1); 1626c0b746e5SOllivier Robert } 1627c0b746e5SOllivier Robert 1628c0b746e5SOllivier Robert 1629c0b746e5SOllivier Robert /* 1630c0b746e5SOllivier Robert * clr_sys_flag - clear system flags 1631c0b746e5SOllivier Robert */ 1632c0b746e5SOllivier Robert static void 1633c0b746e5SOllivier Robert clr_sys_flag( 16349c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1635c0b746e5SOllivier Robert struct interface *inter, 1636c0b746e5SOllivier Robert struct req_pkt *inpkt 1637c0b746e5SOllivier Robert ) 1638c0b746e5SOllivier Robert { 1639c0b746e5SOllivier Robert setclr_flags(srcadr, inter, inpkt, 0); 1640c0b746e5SOllivier Robert } 1641c0b746e5SOllivier Robert 1642c0b746e5SOllivier Robert 1643c0b746e5SOllivier Robert /* 1644c0b746e5SOllivier Robert * setclr_flags - do the grunge work of flag setting/clearing 1645c0b746e5SOllivier Robert */ 1646c0b746e5SOllivier Robert static void 1647c0b746e5SOllivier Robert setclr_flags( 16489c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1649c0b746e5SOllivier Robert struct interface *inter, 1650c0b746e5SOllivier Robert struct req_pkt *inpkt, 1651c0b746e5SOllivier Robert u_long set 1652c0b746e5SOllivier Robert ) 1653c0b746e5SOllivier Robert { 1654224ba2bdSOllivier Robert register u_int flags; 1655ea906c41SOllivier Robert int prev_kern_enable; 1656c0b746e5SOllivier Robert 1657ea906c41SOllivier Robert prev_kern_enable = kern_enable; 1658c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 1659224ba2bdSOllivier Robert msyslog(LOG_ERR, "setclr_flags: err_nitems > 1"); 1660c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1661c0b746e5SOllivier Robert return; 1662c0b746e5SOllivier Robert } 1663c0b746e5SOllivier Robert 1664c0b746e5SOllivier Robert flags = ((struct conf_sys_flags *)inpkt->data)->flags; 1665ea906c41SOllivier Robert flags = ntohl(flags); 1666c0b746e5SOllivier Robert 1667224ba2bdSOllivier Robert if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS | 1668c0b746e5SOllivier Robert SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR | 1669ce265a54SOllivier Robert SYS_FLAG_FILEGEN | SYS_FLAG_AUTH | SYS_FLAG_CAL)) { 1670224ba2bdSOllivier Robert msyslog(LOG_ERR, "setclr_flags: extra flags: %#x", 1671224ba2bdSOllivier Robert flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS | 1672224ba2bdSOllivier Robert SYS_FLAG_NTP | SYS_FLAG_KERNEL | 1673ce265a54SOllivier Robert SYS_FLAG_MONITOR | SYS_FLAG_FILEGEN | 1674ce265a54SOllivier Robert SYS_FLAG_AUTH | SYS_FLAG_CAL)); 1675c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1676c0b746e5SOllivier Robert return; 1677c0b746e5SOllivier Robert } 1678c0b746e5SOllivier Robert 1679c0b746e5SOllivier Robert if (flags & SYS_FLAG_BCLIENT) 16809c2daa00SOllivier Robert proto_config(PROTO_BROADCLIENT, set, 0., NULL); 1681224ba2bdSOllivier Robert if (flags & SYS_FLAG_PPS) 16829c2daa00SOllivier Robert proto_config(PROTO_PPS, set, 0., NULL); 1683c0b746e5SOllivier Robert if (flags & SYS_FLAG_NTP) 16849c2daa00SOllivier Robert proto_config(PROTO_NTP, set, 0., NULL); 1685c0b746e5SOllivier Robert if (flags & SYS_FLAG_KERNEL) 16869c2daa00SOllivier Robert proto_config(PROTO_KERNEL, set, 0., NULL); 1687c0b746e5SOllivier Robert if (flags & SYS_FLAG_MONITOR) 16889c2daa00SOllivier Robert proto_config(PROTO_MONITOR, set, 0., NULL); 1689c0b746e5SOllivier Robert if (flags & SYS_FLAG_FILEGEN) 16909c2daa00SOllivier Robert proto_config(PROTO_FILEGEN, set, 0., NULL); 1691ce265a54SOllivier Robert if (flags & SYS_FLAG_AUTH) 16929c2daa00SOllivier Robert proto_config(PROTO_AUTHENTICATE, set, 0., NULL); 1693ce265a54SOllivier Robert if (flags & SYS_FLAG_CAL) 16949c2daa00SOllivier Robert proto_config(PROTO_CAL, set, 0., NULL); 1695c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1696ea906c41SOllivier Robert 1697ea906c41SOllivier Robert /* Reset the kernel ntp parameters if the kernel flag changed. */ 1698ea906c41SOllivier Robert if (prev_kern_enable && !kern_enable) 1699ea906c41SOllivier Robert loop_config(LOOP_KERN_CLEAR, 0.0); 1700ea906c41SOllivier Robert if (!prev_kern_enable && kern_enable) 1701ea906c41SOllivier Robert loop_config(LOOP_DRIFTCOMP, drift_comp); 1702c0b746e5SOllivier Robert } 1703c0b746e5SOllivier Robert 1704c0b746e5SOllivier Robert 1705c0b746e5SOllivier Robert /* 1706c0b746e5SOllivier Robert * list_restrict - return the restrict list 1707c0b746e5SOllivier Robert */ 1708c0b746e5SOllivier Robert static void 1709c0b746e5SOllivier Robert list_restrict( 17109c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1711c0b746e5SOllivier Robert struct interface *inter, 1712c0b746e5SOllivier Robert struct req_pkt *inpkt 1713c0b746e5SOllivier Robert ) 1714c0b746e5SOllivier Robert { 1715c0b746e5SOllivier Robert register struct info_restrict *ir; 1716c0b746e5SOllivier Robert register struct restrictlist *rl; 17179c2daa00SOllivier Robert register struct restrictlist6 *rl6; 1718c0b746e5SOllivier Robert 1719c0b746e5SOllivier Robert #ifdef DEBUG 1720c0b746e5SOllivier Robert if (debug > 2) 17219c2daa00SOllivier Robert printf("wants restrict list summary\n"); 1722c0b746e5SOllivier Robert #endif 1723c0b746e5SOllivier Robert 1724c0b746e5SOllivier Robert ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt, 17259c2daa00SOllivier Robert v6sizeof(struct info_restrict)); 17269c2daa00SOllivier Robert 1727c0b746e5SOllivier Robert for (rl = restrictlist; rl != 0 && ir != 0; rl = rl->next) { 1728c0b746e5SOllivier Robert ir->addr = htonl(rl->addr); 17299c2daa00SOllivier Robert if (client_v6_capable) 17309c2daa00SOllivier Robert ir->v6_flag = 0; 1731c0b746e5SOllivier Robert ir->mask = htonl(rl->mask); 1732c0b746e5SOllivier Robert ir->count = htonl((u_int32)rl->count); 1733c0b746e5SOllivier Robert ir->flags = htons(rl->flags); 1734c0b746e5SOllivier Robert ir->mflags = htons(rl->mflags); 1735c0b746e5SOllivier Robert ir = (struct info_restrict *)more_pkt(); 1736c0b746e5SOllivier Robert } 17379c2daa00SOllivier Robert if (client_v6_capable) 17389c2daa00SOllivier Robert for (rl6 = restrictlist6; rl6 != 0 && ir != 0; rl6 = rl6->next) { 17399c2daa00SOllivier Robert ir->addr6 = rl6->addr6; 17409c2daa00SOllivier Robert ir->mask6 = rl6->mask6; 17419c2daa00SOllivier Robert ir->v6_flag = 1; 17429c2daa00SOllivier Robert ir->count = htonl((u_int32)rl6->count); 17439c2daa00SOllivier Robert ir->flags = htons(rl6->flags); 17449c2daa00SOllivier Robert ir->mflags = htons(rl6->mflags); 17459c2daa00SOllivier Robert ir = (struct info_restrict *)more_pkt(); 17469c2daa00SOllivier Robert } 1747c0b746e5SOllivier Robert flush_pkt(); 1748c0b746e5SOllivier Robert } 1749c0b746e5SOllivier Robert 1750c0b746e5SOllivier Robert 1751c0b746e5SOllivier Robert 1752c0b746e5SOllivier Robert /* 1753c0b746e5SOllivier Robert * do_resaddflags - add flags to a restrict entry (or create one) 1754c0b746e5SOllivier Robert */ 1755c0b746e5SOllivier Robert static void 1756c0b746e5SOllivier Robert do_resaddflags( 17579c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1758c0b746e5SOllivier Robert struct interface *inter, 1759c0b746e5SOllivier Robert struct req_pkt *inpkt 1760c0b746e5SOllivier Robert ) 1761c0b746e5SOllivier Robert { 1762c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_FLAGS); 1763c0b746e5SOllivier Robert } 1764c0b746e5SOllivier Robert 1765c0b746e5SOllivier Robert 1766c0b746e5SOllivier Robert 1767c0b746e5SOllivier Robert /* 1768c0b746e5SOllivier Robert * do_ressubflags - remove flags from a restrict entry 1769c0b746e5SOllivier Robert */ 1770c0b746e5SOllivier Robert static void 1771c0b746e5SOllivier Robert do_ressubflags( 17729c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1773c0b746e5SOllivier Robert struct interface *inter, 1774c0b746e5SOllivier Robert struct req_pkt *inpkt 1775c0b746e5SOllivier Robert ) 1776c0b746e5SOllivier Robert { 1777c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_UNFLAG); 1778c0b746e5SOllivier Robert } 1779c0b746e5SOllivier Robert 1780c0b746e5SOllivier Robert 1781c0b746e5SOllivier Robert /* 1782c0b746e5SOllivier Robert * do_unrestrict - remove a restrict entry from the list 1783c0b746e5SOllivier Robert */ 1784c0b746e5SOllivier Robert static void 1785c0b746e5SOllivier Robert do_unrestrict( 17869c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1787c0b746e5SOllivier Robert struct interface *inter, 1788c0b746e5SOllivier Robert struct req_pkt *inpkt 1789c0b746e5SOllivier Robert ) 1790c0b746e5SOllivier Robert { 1791c0b746e5SOllivier Robert do_restrict(srcadr, inter, inpkt, RESTRICT_REMOVE); 1792c0b746e5SOllivier Robert } 1793c0b746e5SOllivier Robert 1794c0b746e5SOllivier Robert 1795c0b746e5SOllivier Robert 1796c0b746e5SOllivier Robert 1797c0b746e5SOllivier Robert 1798c0b746e5SOllivier Robert /* 1799c0b746e5SOllivier Robert * do_restrict - do the dirty stuff of dealing with restrictions 1800c0b746e5SOllivier Robert */ 1801c0b746e5SOllivier Robert static void 1802c0b746e5SOllivier Robert do_restrict( 18039c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1804c0b746e5SOllivier Robert struct interface *inter, 1805c0b746e5SOllivier Robert struct req_pkt *inpkt, 1806c0b746e5SOllivier Robert int op 1807c0b746e5SOllivier Robert ) 1808c0b746e5SOllivier Robert { 1809c0b746e5SOllivier Robert register struct conf_restrict *cr; 1810c0b746e5SOllivier Robert register int items; 18119c2daa00SOllivier Robert struct sockaddr_storage matchaddr; 18129c2daa00SOllivier Robert struct sockaddr_storage matchmask; 1813c0b746e5SOllivier Robert int bad; 1814c0b746e5SOllivier Robert 1815c0b746e5SOllivier Robert /* 1816c0b746e5SOllivier Robert * Do a check of the flags to make sure that only 1817c0b746e5SOllivier Robert * the NTPPORT flag is set, if any. If not, complain 1818c0b746e5SOllivier Robert * about it. Note we are very picky here. 1819c0b746e5SOllivier Robert */ 1820c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1821c0b746e5SOllivier Robert cr = (struct conf_restrict *)inpkt->data; 1822c0b746e5SOllivier Robert 1823c0b746e5SOllivier Robert bad = 0; 1824ea906c41SOllivier Robert cr->flags = ntohs(cr->flags); 1825ea906c41SOllivier Robert cr->mflags = ntohs(cr->mflags); 1826c0b746e5SOllivier Robert while (items-- > 0 && !bad) { 1827c0b746e5SOllivier Robert if (cr->mflags & ~(RESM_NTPONLY)) 1828224ba2bdSOllivier Robert bad |= 1; 1829c0b746e5SOllivier Robert if (cr->flags & ~(RES_ALLFLAGS)) 1830224ba2bdSOllivier Robert bad |= 2; 18319c2daa00SOllivier Robert if (cr->mask != htonl(INADDR_ANY)) { 18329c2daa00SOllivier Robert if (client_v6_capable && cr->v6_flag != 0) { 18339c2daa00SOllivier Robert if (IN6_IS_ADDR_UNSPECIFIED(&cr->addr6)) 1834224ba2bdSOllivier Robert bad |= 4; 18359c2daa00SOllivier Robert } else 18369c2daa00SOllivier Robert if (cr->addr == htonl(INADDR_ANY)) 18379c2daa00SOllivier Robert bad |= 8; 18389c2daa00SOllivier Robert } 18399c2daa00SOllivier Robert cr = (struct conf_restrict *)((char *)cr + 18409c2daa00SOllivier Robert INFO_ITEMSIZE(inpkt->mbz_itemsize)); 1841c0b746e5SOllivier Robert } 1842c0b746e5SOllivier Robert 1843c0b746e5SOllivier Robert if (bad) { 1844224ba2bdSOllivier Robert msyslog(LOG_ERR, "do_restrict: bad = %#x", bad); 1845c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1846c0b746e5SOllivier Robert return; 1847c0b746e5SOllivier Robert } 1848c0b746e5SOllivier Robert 1849c0b746e5SOllivier Robert /* 1850c0b746e5SOllivier Robert * Looks okay, try it out 1851c0b746e5SOllivier Robert */ 1852c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 1853c0b746e5SOllivier Robert cr = (struct conf_restrict *)inpkt->data; 18549c2daa00SOllivier Robert memset((char *)&matchaddr, 0, sizeof(struct sockaddr_storage)); 18559c2daa00SOllivier Robert memset((char *)&matchmask, 0, sizeof(struct sockaddr_storage)); 1856c0b746e5SOllivier Robert 1857c0b746e5SOllivier Robert while (items-- > 0) { 18589c2daa00SOllivier Robert if (client_v6_capable && cr->v6_flag != 0) { 18599c2daa00SOllivier Robert GET_INADDR6(matchaddr) = cr->addr6; 18609c2daa00SOllivier Robert GET_INADDR6(matchmask) = cr->mask6; 18619c2daa00SOllivier Robert matchaddr.ss_family = AF_INET6; 18629c2daa00SOllivier Robert matchmask.ss_family = AF_INET6; 18639c2daa00SOllivier Robert } else { 18649c2daa00SOllivier Robert GET_INADDR(matchaddr) = cr->addr; 18659c2daa00SOllivier Robert GET_INADDR(matchmask) = cr->mask; 18669c2daa00SOllivier Robert matchaddr.ss_family = AF_INET; 18679c2daa00SOllivier Robert matchmask.ss_family = AF_INET; 18689c2daa00SOllivier Robert } 1869c0b746e5SOllivier Robert hack_restrict(op, &matchaddr, &matchmask, cr->mflags, 1870c0b746e5SOllivier Robert cr->flags); 1871c0b746e5SOllivier Robert cr++; 1872c0b746e5SOllivier Robert } 1873c0b746e5SOllivier Robert 1874c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 1875c0b746e5SOllivier Robert } 1876c0b746e5SOllivier Robert 1877c0b746e5SOllivier Robert 1878c0b746e5SOllivier Robert /* 1879c0b746e5SOllivier Robert * mon_getlist - return monitor data 1880c0b746e5SOllivier Robert */ 1881c0b746e5SOllivier Robert static void 1882c0b746e5SOllivier Robert mon_getlist_0( 18839c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1884c0b746e5SOllivier Robert struct interface *inter, 1885c0b746e5SOllivier Robert struct req_pkt *inpkt 1886c0b746e5SOllivier Robert ) 1887c0b746e5SOllivier Robert { 1888c0b746e5SOllivier Robert register struct info_monitor *im; 1889c0b746e5SOllivier Robert register struct mon_data *md; 1890c0b746e5SOllivier Robert extern struct mon_data mon_mru_list; 1891c0b746e5SOllivier Robert extern int mon_enabled; 1892c0b746e5SOllivier Robert 1893c0b746e5SOllivier Robert #ifdef DEBUG 1894c0b746e5SOllivier Robert if (debug > 2) 1895c0b746e5SOllivier Robert printf("wants monitor 0 list\n"); 1896c0b746e5SOllivier Robert #endif 1897c0b746e5SOllivier Robert if (!mon_enabled) { 1898c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1899c0b746e5SOllivier Robert return; 1900c0b746e5SOllivier Robert } 1901c0b746e5SOllivier Robert im = (struct info_monitor *)prepare_pkt(srcadr, inter, inpkt, 19029c2daa00SOllivier Robert v6sizeof(struct info_monitor)); 1903c0b746e5SOllivier Robert for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0; 1904c0b746e5SOllivier Robert md = md->mru_next) { 19059c2daa00SOllivier Robert im->lasttime = htonl((u_int32)md->avg_interval); 19069c2daa00SOllivier Robert im->firsttime = htonl((u_int32)(current_time - md->lasttime)); 19079c2daa00SOllivier Robert im->lastdrop = htonl((u_int32)md->drop_count); 1908c0b746e5SOllivier Robert im->count = htonl((u_int32)(md->count)); 19099c2daa00SOllivier Robert if (md->rmtadr.ss_family == AF_INET6) { 19109c2daa00SOllivier Robert if (!client_v6_capable) 19119c2daa00SOllivier Robert continue; 19129c2daa00SOllivier Robert im->addr6 = GET_INADDR6(md->rmtadr); 19139c2daa00SOllivier Robert im->v6_flag = 1; 19149c2daa00SOllivier Robert } else { 19159c2daa00SOllivier Robert im->addr = GET_INADDR(md->rmtadr); 19169c2daa00SOllivier Robert if (client_v6_capable) 19179c2daa00SOllivier Robert im->v6_flag = 0; 19189c2daa00SOllivier Robert } 1919c0b746e5SOllivier Robert im->port = md->rmtport; 1920c0b746e5SOllivier Robert im->mode = md->mode; 1921c0b746e5SOllivier Robert im->version = md->version; 1922c0b746e5SOllivier Robert im = (struct info_monitor *)more_pkt(); 1923c0b746e5SOllivier Robert } 1924c0b746e5SOllivier Robert flush_pkt(); 1925c0b746e5SOllivier Robert } 1926c0b746e5SOllivier Robert 1927c0b746e5SOllivier Robert /* 1928c0b746e5SOllivier Robert * mon_getlist - return monitor data 1929c0b746e5SOllivier Robert */ 1930c0b746e5SOllivier Robert static void 1931c0b746e5SOllivier Robert mon_getlist_1( 19329c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 1933c0b746e5SOllivier Robert struct interface *inter, 1934c0b746e5SOllivier Robert struct req_pkt *inpkt 1935c0b746e5SOllivier Robert ) 1936c0b746e5SOllivier Robert { 1937c0b746e5SOllivier Robert register struct info_monitor_1 *im; 1938c0b746e5SOllivier Robert register struct mon_data *md; 1939c0b746e5SOllivier Robert extern struct mon_data mon_mru_list; 1940c0b746e5SOllivier Robert extern int mon_enabled; 1941c0b746e5SOllivier Robert 1942c0b746e5SOllivier Robert if (!mon_enabled) { 1943c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 1944c0b746e5SOllivier Robert return; 1945c0b746e5SOllivier Robert } 1946c0b746e5SOllivier Robert im = (struct info_monitor_1 *)prepare_pkt(srcadr, inter, inpkt, 19479c2daa00SOllivier Robert v6sizeof(struct info_monitor_1)); 1948c0b746e5SOllivier Robert for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0; 1949c0b746e5SOllivier Robert md = md->mru_next) { 19509c2daa00SOllivier Robert im->lasttime = htonl((u_int32)md->avg_interval); 19519c2daa00SOllivier Robert im->firsttime = htonl((u_int32)(current_time - md->lasttime)); 19529c2daa00SOllivier Robert im->lastdrop = htonl((u_int32)md->drop_count); 1953c0b746e5SOllivier Robert im->count = htonl((u_int32)md->count); 19549c2daa00SOllivier Robert if (md->rmtadr.ss_family == AF_INET6) { 19559c2daa00SOllivier Robert if (!client_v6_capable) 19569c2daa00SOllivier Robert continue; 19579c2daa00SOllivier Robert im->addr6 = GET_INADDR6(md->rmtadr); 19589c2daa00SOllivier Robert im->v6_flag = 1; 19599c2daa00SOllivier Robert im->daddr6 = GET_INADDR6(md->interface->sin); 19609c2daa00SOllivier Robert } else { 19619c2daa00SOllivier Robert im->addr = GET_INADDR(md->rmtadr); 19629c2daa00SOllivier Robert if (client_v6_capable) 19639c2daa00SOllivier Robert im->v6_flag = 0; 19649c2daa00SOllivier Robert im->daddr = (md->cast_flags == MDF_BCAST) 19659c2daa00SOllivier Robert ? GET_INADDR(md->interface->bcast) 1966c0b746e5SOllivier Robert : (md->cast_flags 19679c2daa00SOllivier Robert ? (GET_INADDR(md->interface->sin) 19689c2daa00SOllivier Robert ? GET_INADDR(md->interface->sin) 19699c2daa00SOllivier Robert : GET_INADDR(md->interface->bcast)) 1970c0b746e5SOllivier Robert : 4); 19719c2daa00SOllivier Robert } 1972ea906c41SOllivier Robert im->flags = htonl(md->cast_flags); 1973c0b746e5SOllivier Robert im->port = md->rmtport; 1974c0b746e5SOllivier Robert im->mode = md->mode; 1975c0b746e5SOllivier Robert im->version = md->version; 1976c0b746e5SOllivier Robert im = (struct info_monitor_1 *)more_pkt(); 1977c0b746e5SOllivier Robert } 1978c0b746e5SOllivier Robert flush_pkt(); 1979c0b746e5SOllivier Robert } 1980c0b746e5SOllivier Robert 1981c0b746e5SOllivier Robert /* 1982c0b746e5SOllivier Robert * Module entry points and the flags they correspond with 1983c0b746e5SOllivier Robert */ 1984c0b746e5SOllivier Robert struct reset_entry { 1985c0b746e5SOllivier Robert int flag; /* flag this corresponds to */ 1986c0b746e5SOllivier Robert void (*handler) P((void)); /* routine to handle request */ 1987c0b746e5SOllivier Robert }; 1988c0b746e5SOllivier Robert 1989c0b746e5SOllivier Robert struct reset_entry reset_entries[] = { 1990c0b746e5SOllivier Robert { RESET_FLAG_ALLPEERS, peer_all_reset }, 1991c0b746e5SOllivier Robert { RESET_FLAG_IO, io_clr_stats }, 1992c0b746e5SOllivier Robert { RESET_FLAG_SYS, proto_clr_stats }, 1993c0b746e5SOllivier Robert { RESET_FLAG_MEM, peer_clr_stats }, 1994c0b746e5SOllivier Robert { RESET_FLAG_TIMER, timer_clr_stats }, 1995c0b746e5SOllivier Robert { RESET_FLAG_AUTH, reset_auth_stats }, 1996c0b746e5SOllivier Robert { RESET_FLAG_CTL, ctl_clr_stats }, 1997c0b746e5SOllivier Robert { 0, 0 } 1998c0b746e5SOllivier Robert }; 1999c0b746e5SOllivier Robert 2000c0b746e5SOllivier Robert /* 2001c0b746e5SOllivier Robert * reset_stats - reset statistic counters here and there 2002c0b746e5SOllivier Robert */ 2003c0b746e5SOllivier Robert static void 2004c0b746e5SOllivier Robert reset_stats( 20059c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2006c0b746e5SOllivier Robert struct interface *inter, 2007c0b746e5SOllivier Robert struct req_pkt *inpkt 2008c0b746e5SOllivier Robert ) 2009c0b746e5SOllivier Robert { 2010c0b746e5SOllivier Robert u_long flags; 2011c0b746e5SOllivier Robert struct reset_entry *rent; 2012c0b746e5SOllivier Robert 2013c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2014224ba2bdSOllivier Robert msyslog(LOG_ERR, "reset_stats: err_nitems > 1"); 2015c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2016c0b746e5SOllivier Robert return; 2017c0b746e5SOllivier Robert } 2018c0b746e5SOllivier Robert 2019c0b746e5SOllivier Robert flags = ((struct reset_flags *)inpkt->data)->flags; 2020ea906c41SOllivier Robert flags = ntohl(flags); 2021c0b746e5SOllivier Robert 2022c0b746e5SOllivier Robert if (flags & ~RESET_ALLFLAGS) { 2023224ba2bdSOllivier Robert msyslog(LOG_ERR, "reset_stats: reset leaves %#lx", 2024224ba2bdSOllivier Robert flags & ~RESET_ALLFLAGS); 2025c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2026c0b746e5SOllivier Robert return; 2027c0b746e5SOllivier Robert } 2028c0b746e5SOllivier Robert 2029c0b746e5SOllivier Robert for (rent = reset_entries; rent->flag != 0; rent++) { 2030c0b746e5SOllivier Robert if (flags & rent->flag) 2031c0b746e5SOllivier Robert (rent->handler)(); 2032c0b746e5SOllivier Robert } 2033c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2034c0b746e5SOllivier Robert } 2035c0b746e5SOllivier Robert 2036c0b746e5SOllivier Robert 2037c0b746e5SOllivier Robert /* 2038c0b746e5SOllivier Robert * reset_peer - clear a peer's statistics 2039c0b746e5SOllivier Robert */ 2040c0b746e5SOllivier Robert static void 2041c0b746e5SOllivier Robert reset_peer( 20429c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2043c0b746e5SOllivier Robert struct interface *inter, 2044c0b746e5SOllivier Robert struct req_pkt *inpkt 2045c0b746e5SOllivier Robert ) 2046c0b746e5SOllivier Robert { 2047c0b746e5SOllivier Robert register struct conf_unpeer *cp; 2048c0b746e5SOllivier Robert register int items; 2049c0b746e5SOllivier Robert register struct peer *peer; 20509c2daa00SOllivier Robert struct sockaddr_storage peeraddr; 2051c0b746e5SOllivier Robert int bad; 2052c0b746e5SOllivier Robert 2053c0b746e5SOllivier Robert /* 2054c0b746e5SOllivier Robert * We check first to see that every peer exists. If not, 2055c0b746e5SOllivier Robert * we return an error. 2056c0b746e5SOllivier Robert */ 2057c0b746e5SOllivier Robert 2058c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2059c0b746e5SOllivier Robert cp = (struct conf_unpeer *)inpkt->data; 2060c0b746e5SOllivier Robert 2061c0b746e5SOllivier Robert bad = 0; 2062c0b746e5SOllivier Robert while (items-- > 0 && !bad) { 20639c2daa00SOllivier Robert memset((char *)&peeraddr, 0, sizeof(peeraddr)); 20649c2daa00SOllivier Robert if (client_v6_capable && cp->v6_flag != 0) { 20659c2daa00SOllivier Robert GET_INADDR6(peeraddr) = cp->peeraddr6; 20669c2daa00SOllivier Robert peeraddr.ss_family = AF_INET6; 20679c2daa00SOllivier Robert } else { 20689c2daa00SOllivier Robert GET_INADDR(peeraddr) = cp->peeraddr; 20699c2daa00SOllivier Robert peeraddr.ss_family = AF_INET; 20709c2daa00SOllivier Robert } 20719c2daa00SOllivier Robert NSRCPORT(&peeraddr) = htons(NTP_PORT); 20729c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 20739c2daa00SOllivier Robert peeraddr.ss_len = SOCKLEN(&peeraddr); 20749c2daa00SOllivier Robert #endif 2075c0b746e5SOllivier Robert peer = findexistingpeer(&peeraddr, (struct peer *)0, -1); 2076c0b746e5SOllivier Robert if (peer == (struct peer *)0) 2077c0b746e5SOllivier Robert bad++; 20789c2daa00SOllivier Robert cp = (struct conf_unpeer *)((char *)cp + 20799c2daa00SOllivier Robert INFO_ITEMSIZE(inpkt->mbz_itemsize)); 2080c0b746e5SOllivier Robert } 2081c0b746e5SOllivier Robert 2082c0b746e5SOllivier Robert if (bad) { 2083c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2084c0b746e5SOllivier Robert return; 2085c0b746e5SOllivier Robert } 2086c0b746e5SOllivier Robert 2087c0b746e5SOllivier Robert /* 2088c0b746e5SOllivier Robert * Now do it in earnest. 2089c0b746e5SOllivier Robert */ 2090c0b746e5SOllivier Robert 2091c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2092c0b746e5SOllivier Robert cp = (struct conf_unpeer *)inpkt->data; 2093c0b746e5SOllivier Robert while (items-- > 0) { 20949c2daa00SOllivier Robert memset((char *)&peeraddr, 0, sizeof(peeraddr)); 20959c2daa00SOllivier Robert if (client_v6_capable && cp->v6_flag != 0) { 20969c2daa00SOllivier Robert GET_INADDR6(peeraddr) = cp->peeraddr6; 20979c2daa00SOllivier Robert peeraddr.ss_family = AF_INET6; 20989c2daa00SOllivier Robert } else { 20999c2daa00SOllivier Robert GET_INADDR(peeraddr) = cp->peeraddr; 21009c2daa00SOllivier Robert peeraddr.ss_family = AF_INET; 21019c2daa00SOllivier Robert } 21029c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 21039c2daa00SOllivier Robert peeraddr.ss_len = SOCKLEN(&peeraddr); 21049c2daa00SOllivier Robert #endif 2105c0b746e5SOllivier Robert peer = findexistingpeer(&peeraddr, (struct peer *)0, -1); 2106c0b746e5SOllivier Robert while (peer != 0) { 2107c0b746e5SOllivier Robert peer_reset(peer); 2108c0b746e5SOllivier Robert peer = findexistingpeer(&peeraddr, (struct peer *)peer, -1); 2109c0b746e5SOllivier Robert } 21109c2daa00SOllivier Robert cp = (struct conf_unpeer *)((char *)cp + 21119c2daa00SOllivier Robert INFO_ITEMSIZE(inpkt->mbz_itemsize)); 2112c0b746e5SOllivier Robert } 2113c0b746e5SOllivier Robert 2114c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2115c0b746e5SOllivier Robert } 2116c0b746e5SOllivier Robert 2117c0b746e5SOllivier Robert 2118c0b746e5SOllivier Robert /* 2119c0b746e5SOllivier Robert * do_key_reread - reread the encryption key file 2120c0b746e5SOllivier Robert */ 2121c0b746e5SOllivier Robert static void 2122c0b746e5SOllivier Robert do_key_reread( 21239c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2124c0b746e5SOllivier Robert struct interface *inter, 2125c0b746e5SOllivier Robert struct req_pkt *inpkt 2126c0b746e5SOllivier Robert ) 2127c0b746e5SOllivier Robert { 2128c0b746e5SOllivier Robert rereadkeys(); 2129c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2130c0b746e5SOllivier Robert } 2131c0b746e5SOllivier Robert 2132c0b746e5SOllivier Robert 2133c0b746e5SOllivier Robert /* 2134c0b746e5SOllivier Robert * trust_key - make one or more keys trusted 2135c0b746e5SOllivier Robert */ 2136c0b746e5SOllivier Robert static void 2137c0b746e5SOllivier Robert trust_key( 21389c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2139c0b746e5SOllivier Robert struct interface *inter, 2140c0b746e5SOllivier Robert struct req_pkt *inpkt 2141c0b746e5SOllivier Robert ) 2142c0b746e5SOllivier Robert { 2143c0b746e5SOllivier Robert do_trustkey(srcadr, inter, inpkt, 1); 2144c0b746e5SOllivier Robert } 2145c0b746e5SOllivier Robert 2146c0b746e5SOllivier Robert 2147c0b746e5SOllivier Robert /* 2148c0b746e5SOllivier Robert * untrust_key - make one or more keys untrusted 2149c0b746e5SOllivier Robert */ 2150c0b746e5SOllivier Robert static void 2151c0b746e5SOllivier Robert untrust_key( 21529c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2153c0b746e5SOllivier Robert struct interface *inter, 2154c0b746e5SOllivier Robert struct req_pkt *inpkt 2155c0b746e5SOllivier Robert ) 2156c0b746e5SOllivier Robert { 2157c0b746e5SOllivier Robert do_trustkey(srcadr, inter, inpkt, 0); 2158c0b746e5SOllivier Robert } 2159c0b746e5SOllivier Robert 2160c0b746e5SOllivier Robert 2161c0b746e5SOllivier Robert /* 2162c0b746e5SOllivier Robert * do_trustkey - make keys either trustable or untrustable 2163c0b746e5SOllivier Robert */ 2164c0b746e5SOllivier Robert static void 2165c0b746e5SOllivier Robert do_trustkey( 21669c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2167c0b746e5SOllivier Robert struct interface *inter, 2168c0b746e5SOllivier Robert struct req_pkt *inpkt, 2169224ba2bdSOllivier Robert u_long trust 2170c0b746e5SOllivier Robert ) 2171c0b746e5SOllivier Robert { 2172c0b746e5SOllivier Robert register u_long *kp; 2173c0b746e5SOllivier Robert register int items; 2174c0b746e5SOllivier Robert 2175c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2176c0b746e5SOllivier Robert kp = (u_long *)inpkt->data; 2177c0b746e5SOllivier Robert while (items-- > 0) { 2178c0b746e5SOllivier Robert authtrust(*kp, trust); 2179c0b746e5SOllivier Robert kp++; 2180c0b746e5SOllivier Robert } 2181c0b746e5SOllivier Robert 2182c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2183c0b746e5SOllivier Robert } 2184c0b746e5SOllivier Robert 2185c0b746e5SOllivier Robert 2186c0b746e5SOllivier Robert /* 2187c0b746e5SOllivier Robert * get_auth_info - return some stats concerning the authentication module 2188c0b746e5SOllivier Robert */ 2189c0b746e5SOllivier Robert static void 2190c0b746e5SOllivier Robert get_auth_info( 21919c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2192c0b746e5SOllivier Robert struct interface *inter, 2193c0b746e5SOllivier Robert struct req_pkt *inpkt 2194c0b746e5SOllivier Robert ) 2195c0b746e5SOllivier Robert { 2196c0b746e5SOllivier Robert register struct info_auth *ia; 2197c0b746e5SOllivier Robert 2198c0b746e5SOllivier Robert /* 2199c0b746e5SOllivier Robert * Importations from the authentication module 2200c0b746e5SOllivier Robert */ 2201c0b746e5SOllivier Robert extern u_long authnumkeys; 2202c0b746e5SOllivier Robert extern int authnumfreekeys; 2203c0b746e5SOllivier Robert extern u_long authkeylookups; 2204c0b746e5SOllivier Robert extern u_long authkeynotfound; 2205c0b746e5SOllivier Robert extern u_long authencryptions; 2206c0b746e5SOllivier Robert extern u_long authdecryptions; 2207c0b746e5SOllivier Robert extern u_long authkeyuncached; 2208c0b746e5SOllivier Robert extern u_long authkeyexpired; 2209c0b746e5SOllivier Robert 2210c0b746e5SOllivier Robert ia = (struct info_auth *)prepare_pkt(srcadr, inter, inpkt, 2211c0b746e5SOllivier Robert sizeof(struct info_auth)); 2212c0b746e5SOllivier Robert 2213c0b746e5SOllivier Robert ia->numkeys = htonl((u_int32)authnumkeys); 2214c0b746e5SOllivier Robert ia->numfreekeys = htonl((u_int32)authnumfreekeys); 2215c0b746e5SOllivier Robert ia->keylookups = htonl((u_int32)authkeylookups); 2216c0b746e5SOllivier Robert ia->keynotfound = htonl((u_int32)authkeynotfound); 2217c0b746e5SOllivier Robert ia->encryptions = htonl((u_int32)authencryptions); 2218c0b746e5SOllivier Robert ia->decryptions = htonl((u_int32)authdecryptions); 2219c0b746e5SOllivier Robert ia->keyuncached = htonl((u_int32)authkeyuncached); 2220c0b746e5SOllivier Robert ia->expired = htonl((u_int32)authkeyexpired); 2221c0b746e5SOllivier Robert ia->timereset = htonl((u_int32)(current_time - auth_timereset)); 2222c0b746e5SOllivier Robert 2223c0b746e5SOllivier Robert (void) more_pkt(); 2224c0b746e5SOllivier Robert flush_pkt(); 2225c0b746e5SOllivier Robert } 2226c0b746e5SOllivier Robert 2227c0b746e5SOllivier Robert 2228c0b746e5SOllivier Robert 2229c0b746e5SOllivier Robert /* 2230c0b746e5SOllivier Robert * reset_auth_stats - reset the authentication stat counters. Done here 2231c0b746e5SOllivier Robert * to keep ntp-isms out of the authentication module 2232c0b746e5SOllivier Robert */ 2233c0b746e5SOllivier Robert static void 2234c0b746e5SOllivier Robert reset_auth_stats(void) 2235c0b746e5SOllivier Robert { 2236c0b746e5SOllivier Robert /* 2237c0b746e5SOllivier Robert * Importations from the authentication module 2238c0b746e5SOllivier Robert */ 2239c0b746e5SOllivier Robert extern u_long authkeylookups; 2240c0b746e5SOllivier Robert extern u_long authkeynotfound; 2241c0b746e5SOllivier Robert extern u_long authencryptions; 2242c0b746e5SOllivier Robert extern u_long authdecryptions; 2243c0b746e5SOllivier Robert extern u_long authkeyuncached; 2244c0b746e5SOllivier Robert 2245c0b746e5SOllivier Robert authkeylookups = 0; 2246c0b746e5SOllivier Robert authkeynotfound = 0; 2247c0b746e5SOllivier Robert authencryptions = 0; 2248c0b746e5SOllivier Robert authdecryptions = 0; 2249c0b746e5SOllivier Robert authkeyuncached = 0; 2250c0b746e5SOllivier Robert auth_timereset = current_time; 2251c0b746e5SOllivier Robert } 2252c0b746e5SOllivier Robert 2253c0b746e5SOllivier Robert 2254c0b746e5SOllivier Robert /* 2255c0b746e5SOllivier Robert * req_get_traps - return information about current trap holders 2256c0b746e5SOllivier Robert */ 2257c0b746e5SOllivier Robert static void 2258c0b746e5SOllivier Robert req_get_traps( 22599c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2260c0b746e5SOllivier Robert struct interface *inter, 2261c0b746e5SOllivier Robert struct req_pkt *inpkt 2262c0b746e5SOllivier Robert ) 2263c0b746e5SOllivier Robert { 2264c0b746e5SOllivier Robert register struct info_trap *it; 2265c0b746e5SOllivier Robert register struct ctl_trap *tr; 2266c0b746e5SOllivier Robert register int i; 2267c0b746e5SOllivier Robert 2268c0b746e5SOllivier Robert /* 2269c0b746e5SOllivier Robert * Imported from the control module 2270c0b746e5SOllivier Robert */ 2271c0b746e5SOllivier Robert extern struct ctl_trap ctl_trap[]; 2272c0b746e5SOllivier Robert extern int num_ctl_traps; 2273c0b746e5SOllivier Robert 2274c0b746e5SOllivier Robert if (num_ctl_traps == 0) { 2275c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2276c0b746e5SOllivier Robert return; 2277c0b746e5SOllivier Robert } 2278c0b746e5SOllivier Robert 2279c0b746e5SOllivier Robert it = (struct info_trap *)prepare_pkt(srcadr, inter, inpkt, 22809c2daa00SOllivier Robert v6sizeof(struct info_trap)); 2281c0b746e5SOllivier Robert 2282c0b746e5SOllivier Robert for (i = 0, tr = ctl_trap; i < CTL_MAXTRAPS; i++, tr++) { 2283c0b746e5SOllivier Robert if (tr->tr_flags & TRAP_INUSE) { 22849c2daa00SOllivier Robert if (tr->tr_addr.ss_family == AF_INET) { 2285c0b746e5SOllivier Robert if (tr->tr_localaddr == any_interface) 2286c0b746e5SOllivier Robert it->local_address = 0; 2287c0b746e5SOllivier Robert else 2288c0b746e5SOllivier Robert it->local_address 22899c2daa00SOllivier Robert = GET_INADDR(tr->tr_localaddr->sin); 22909c2daa00SOllivier Robert it->trap_address = GET_INADDR(tr->tr_addr); 22919c2daa00SOllivier Robert if (client_v6_capable) 22929c2daa00SOllivier Robert it->v6_flag = 0; 22939c2daa00SOllivier Robert } else { 22949c2daa00SOllivier Robert if (!client_v6_capable) 22959c2daa00SOllivier Robert continue; 22969c2daa00SOllivier Robert it->local_address6 22979c2daa00SOllivier Robert = GET_INADDR6(tr->tr_localaddr->sin); 22989c2daa00SOllivier Robert it->trap_address6 = GET_INADDR6(tr->tr_addr); 22999c2daa00SOllivier Robert it->v6_flag = 1; 23009c2daa00SOllivier Robert } 2301c0b746e5SOllivier Robert it->trap_port = NSRCPORT(&tr->tr_addr); 2302c0b746e5SOllivier Robert it->sequence = htons(tr->tr_sequence); 2303c0b746e5SOllivier Robert it->settime = htonl((u_int32)(current_time - tr->tr_settime)); 2304c0b746e5SOllivier Robert it->origtime = htonl((u_int32)(current_time - tr->tr_origtime)); 2305c0b746e5SOllivier Robert it->resets = htonl((u_int32)tr->tr_resets); 2306c0b746e5SOllivier Robert it->flags = htonl((u_int32)tr->tr_flags); 2307c0b746e5SOllivier Robert it = (struct info_trap *)more_pkt(); 2308c0b746e5SOllivier Robert } 2309c0b746e5SOllivier Robert } 2310c0b746e5SOllivier Robert flush_pkt(); 2311c0b746e5SOllivier Robert } 2312c0b746e5SOllivier Robert 2313c0b746e5SOllivier Robert 2314c0b746e5SOllivier Robert /* 2315c0b746e5SOllivier Robert * req_set_trap - configure a trap 2316c0b746e5SOllivier Robert */ 2317c0b746e5SOllivier Robert static void 2318c0b746e5SOllivier Robert req_set_trap( 23199c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2320c0b746e5SOllivier Robert struct interface *inter, 2321c0b746e5SOllivier Robert struct req_pkt *inpkt 2322c0b746e5SOllivier Robert ) 2323c0b746e5SOllivier Robert { 2324c0b746e5SOllivier Robert do_setclr_trap(srcadr, inter, inpkt, 1); 2325c0b746e5SOllivier Robert } 2326c0b746e5SOllivier Robert 2327c0b746e5SOllivier Robert 2328c0b746e5SOllivier Robert 2329c0b746e5SOllivier Robert /* 2330c0b746e5SOllivier Robert * req_clr_trap - unconfigure a trap 2331c0b746e5SOllivier Robert */ 2332c0b746e5SOllivier Robert static void 2333c0b746e5SOllivier Robert req_clr_trap( 23349c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2335c0b746e5SOllivier Robert struct interface *inter, 2336c0b746e5SOllivier Robert struct req_pkt *inpkt 2337c0b746e5SOllivier Robert ) 2338c0b746e5SOllivier Robert { 2339c0b746e5SOllivier Robert do_setclr_trap(srcadr, inter, inpkt, 0); 2340c0b746e5SOllivier Robert } 2341c0b746e5SOllivier Robert 2342c0b746e5SOllivier Robert 2343c0b746e5SOllivier Robert 2344c0b746e5SOllivier Robert /* 2345c0b746e5SOllivier Robert * do_setclr_trap - do the grunge work of (un)configuring a trap 2346c0b746e5SOllivier Robert */ 2347c0b746e5SOllivier Robert static void 2348c0b746e5SOllivier Robert do_setclr_trap( 23499c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2350c0b746e5SOllivier Robert struct interface *inter, 2351c0b746e5SOllivier Robert struct req_pkt *inpkt, 2352c0b746e5SOllivier Robert int set 2353c0b746e5SOllivier Robert ) 2354c0b746e5SOllivier Robert { 2355c0b746e5SOllivier Robert register struct conf_trap *ct; 2356c0b746e5SOllivier Robert register struct interface *linter; 2357c0b746e5SOllivier Robert int res; 23589c2daa00SOllivier Robert struct sockaddr_storage laddr; 2359c0b746e5SOllivier Robert 2360c0b746e5SOllivier Robert /* 23619c2daa00SOllivier Robert * Prepare sockaddr_storage structure 2362c0b746e5SOllivier Robert */ 2363c0b746e5SOllivier Robert memset((char *)&laddr, 0, sizeof laddr); 23649c2daa00SOllivier Robert laddr.ss_family = srcadr->ss_family; 23659c2daa00SOllivier Robert NSRCPORT(&laddr) = ntohs(NTP_PORT); 2366c0b746e5SOllivier Robert 2367c0b746e5SOllivier Robert /* 2368c0b746e5SOllivier Robert * Restrict ourselves to one item only. This eliminates 2369c0b746e5SOllivier Robert * the error reporting problem. 2370c0b746e5SOllivier Robert */ 2371c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2372224ba2bdSOllivier Robert msyslog(LOG_ERR, "do_setclr_trap: err_nitems > 1"); 2373c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2374c0b746e5SOllivier Robert return; 2375c0b746e5SOllivier Robert } 2376c0b746e5SOllivier Robert ct = (struct conf_trap *)inpkt->data; 2377c0b746e5SOllivier Robert 2378c0b746e5SOllivier Robert /* 2379c0b746e5SOllivier Robert * Look for the local interface. If none, use the default. 2380c0b746e5SOllivier Robert */ 2381c0b746e5SOllivier Robert if (ct->local_address == 0) { 2382c0b746e5SOllivier Robert linter = any_interface; 2383c0b746e5SOllivier Robert } else { 23849c2daa00SOllivier Robert if (laddr.ss_family == AF_INET) 23859c2daa00SOllivier Robert GET_INADDR(laddr) = ct->local_address; 23869c2daa00SOllivier Robert else 23879c2daa00SOllivier Robert GET_INADDR6(laddr) = ct->local_address6; 2388c0b746e5SOllivier Robert linter = findinterface(&laddr); 2389c0b746e5SOllivier Robert if (linter == NULL) { 2390c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2391c0b746e5SOllivier Robert return; 2392c0b746e5SOllivier Robert } 2393c0b746e5SOllivier Robert } 2394c0b746e5SOllivier Robert 23959c2daa00SOllivier Robert if (laddr.ss_family == AF_INET) 23969c2daa00SOllivier Robert GET_INADDR(laddr) = ct->trap_address; 2397c0b746e5SOllivier Robert else 23989c2daa00SOllivier Robert GET_INADDR6(laddr) = ct->trap_address6; 23999c2daa00SOllivier Robert if (ct->trap_port != 0) 24009c2daa00SOllivier Robert NSRCPORT(&laddr) = ct->trap_port; 24019c2daa00SOllivier Robert else 24029c2daa00SOllivier Robert NSRCPORT(&laddr) = htons(TRAPPORT); 2403c0b746e5SOllivier Robert 2404c0b746e5SOllivier Robert if (set) { 2405c0b746e5SOllivier Robert res = ctlsettrap(&laddr, linter, 0, 2406c0b746e5SOllivier Robert INFO_VERSION(inpkt->rm_vn_mode)); 2407c0b746e5SOllivier Robert } else { 2408c0b746e5SOllivier Robert res = ctlclrtrap(&laddr, linter, 0); 2409c0b746e5SOllivier Robert } 2410c0b746e5SOllivier Robert 2411c0b746e5SOllivier Robert if (!res) { 2412c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2413c0b746e5SOllivier Robert } else { 2414c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2415c0b746e5SOllivier Robert } 2416c0b746e5SOllivier Robert return; 2417c0b746e5SOllivier Robert } 2418c0b746e5SOllivier Robert 2419c0b746e5SOllivier Robert 2420c0b746e5SOllivier Robert 2421c0b746e5SOllivier Robert /* 2422c0b746e5SOllivier Robert * set_request_keyid - set the keyid used to authenticate requests 2423c0b746e5SOllivier Robert */ 2424c0b746e5SOllivier Robert static void 2425c0b746e5SOllivier Robert set_request_keyid( 24269c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2427c0b746e5SOllivier Robert struct interface *inter, 2428c0b746e5SOllivier Robert struct req_pkt *inpkt 2429c0b746e5SOllivier Robert ) 2430c0b746e5SOllivier Robert { 2431224ba2bdSOllivier Robert keyid_t keyid; 2432c0b746e5SOllivier Robert 2433c0b746e5SOllivier Robert /* 2434c0b746e5SOllivier Robert * Restrict ourselves to one item only. 2435c0b746e5SOllivier Robert */ 2436c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2437224ba2bdSOllivier Robert msyslog(LOG_ERR, "set_request_keyid: err_nitems > 1"); 2438c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2439c0b746e5SOllivier Robert return; 2440c0b746e5SOllivier Robert } 2441c0b746e5SOllivier Robert 2442c0b746e5SOllivier Robert keyid = ntohl(*((u_int32 *)(inpkt->data))); 2443c0b746e5SOllivier Robert info_auth_keyid = keyid; 2444c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2445c0b746e5SOllivier Robert } 2446c0b746e5SOllivier Robert 2447c0b746e5SOllivier Robert 2448c0b746e5SOllivier Robert 2449c0b746e5SOllivier Robert /* 2450c0b746e5SOllivier Robert * set_control_keyid - set the keyid used to authenticate requests 2451c0b746e5SOllivier Robert */ 2452c0b746e5SOllivier Robert static void 2453c0b746e5SOllivier Robert set_control_keyid( 24549c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2455c0b746e5SOllivier Robert struct interface *inter, 2456c0b746e5SOllivier Robert struct req_pkt *inpkt 2457c0b746e5SOllivier Robert ) 2458c0b746e5SOllivier Robert { 2459224ba2bdSOllivier Robert keyid_t keyid; 2460224ba2bdSOllivier Robert extern keyid_t ctl_auth_keyid; 2461c0b746e5SOllivier Robert 2462c0b746e5SOllivier Robert /* 2463c0b746e5SOllivier Robert * Restrict ourselves to one item only. 2464c0b746e5SOllivier Robert */ 2465c0b746e5SOllivier Robert if (INFO_NITEMS(inpkt->err_nitems) > 1) { 2466224ba2bdSOllivier Robert msyslog(LOG_ERR, "set_control_keyid: err_nitems > 1"); 2467c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2468c0b746e5SOllivier Robert return; 2469c0b746e5SOllivier Robert } 2470c0b746e5SOllivier Robert 2471c0b746e5SOllivier Robert keyid = ntohl(*((u_int32 *)(inpkt->data))); 2472c0b746e5SOllivier Robert ctl_auth_keyid = keyid; 2473c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2474c0b746e5SOllivier Robert } 2475c0b746e5SOllivier Robert 2476c0b746e5SOllivier Robert 2477c0b746e5SOllivier Robert 2478c0b746e5SOllivier Robert /* 2479c0b746e5SOllivier Robert * get_ctl_stats - return some stats concerning the control message module 2480c0b746e5SOllivier Robert */ 2481c0b746e5SOllivier Robert static void 2482c0b746e5SOllivier Robert get_ctl_stats( 24839c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2484c0b746e5SOllivier Robert struct interface *inter, 2485c0b746e5SOllivier Robert struct req_pkt *inpkt 2486c0b746e5SOllivier Robert ) 2487c0b746e5SOllivier Robert { 2488c0b746e5SOllivier Robert register struct info_control *ic; 2489c0b746e5SOllivier Robert 2490c0b746e5SOllivier Robert /* 2491c0b746e5SOllivier Robert * Importations from the control module 2492c0b746e5SOllivier Robert */ 2493c0b746e5SOllivier Robert extern u_long ctltimereset; 2494c0b746e5SOllivier Robert extern u_long numctlreq; 2495c0b746e5SOllivier Robert extern u_long numctlbadpkts; 2496c0b746e5SOllivier Robert extern u_long numctlresponses; 2497c0b746e5SOllivier Robert extern u_long numctlfrags; 2498c0b746e5SOllivier Robert extern u_long numctlerrors; 2499c0b746e5SOllivier Robert extern u_long numctltooshort; 2500c0b746e5SOllivier Robert extern u_long numctlinputresp; 2501c0b746e5SOllivier Robert extern u_long numctlinputfrag; 2502c0b746e5SOllivier Robert extern u_long numctlinputerr; 2503c0b746e5SOllivier Robert extern u_long numctlbadoffset; 2504c0b746e5SOllivier Robert extern u_long numctlbadversion; 2505c0b746e5SOllivier Robert extern u_long numctldatatooshort; 2506c0b746e5SOllivier Robert extern u_long numctlbadop; 2507c0b746e5SOllivier Robert extern u_long numasyncmsgs; 2508c0b746e5SOllivier Robert 2509c0b746e5SOllivier Robert ic = (struct info_control *)prepare_pkt(srcadr, inter, inpkt, 2510c0b746e5SOllivier Robert sizeof(struct info_control)); 2511c0b746e5SOllivier Robert 2512c0b746e5SOllivier Robert ic->ctltimereset = htonl((u_int32)(current_time - ctltimereset)); 2513c0b746e5SOllivier Robert ic->numctlreq = htonl((u_int32)numctlreq); 2514c0b746e5SOllivier Robert ic->numctlbadpkts = htonl((u_int32)numctlbadpkts); 2515c0b746e5SOllivier Robert ic->numctlresponses = htonl((u_int32)numctlresponses); 2516c0b746e5SOllivier Robert ic->numctlfrags = htonl((u_int32)numctlfrags); 2517c0b746e5SOllivier Robert ic->numctlerrors = htonl((u_int32)numctlerrors); 2518c0b746e5SOllivier Robert ic->numctltooshort = htonl((u_int32)numctltooshort); 2519c0b746e5SOllivier Robert ic->numctlinputresp = htonl((u_int32)numctlinputresp); 2520c0b746e5SOllivier Robert ic->numctlinputfrag = htonl((u_int32)numctlinputfrag); 2521c0b746e5SOllivier Robert ic->numctlinputerr = htonl((u_int32)numctlinputerr); 2522c0b746e5SOllivier Robert ic->numctlbadoffset = htonl((u_int32)numctlbadoffset); 2523c0b746e5SOllivier Robert ic->numctlbadversion = htonl((u_int32)numctlbadversion); 2524c0b746e5SOllivier Robert ic->numctldatatooshort = htonl((u_int32)numctldatatooshort); 2525c0b746e5SOllivier Robert ic->numctlbadop = htonl((u_int32)numctlbadop); 2526c0b746e5SOllivier Robert ic->numasyncmsgs = htonl((u_int32)numasyncmsgs); 2527c0b746e5SOllivier Robert 2528c0b746e5SOllivier Robert (void) more_pkt(); 2529c0b746e5SOllivier Robert flush_pkt(); 2530c0b746e5SOllivier Robert } 2531c0b746e5SOllivier Robert 2532c0b746e5SOllivier Robert 2533c0b746e5SOllivier Robert #ifdef KERNEL_PLL 2534c0b746e5SOllivier Robert /* 2535c0b746e5SOllivier Robert * get_kernel_info - get kernel pll/pps information 2536c0b746e5SOllivier Robert */ 2537c0b746e5SOllivier Robert static void 2538c0b746e5SOllivier Robert get_kernel_info( 25399c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2540c0b746e5SOllivier Robert struct interface *inter, 2541c0b746e5SOllivier Robert struct req_pkt *inpkt 2542c0b746e5SOllivier Robert ) 2543c0b746e5SOllivier Robert { 2544c0b746e5SOllivier Robert register struct info_kernel *ik; 2545c0b746e5SOllivier Robert struct timex ntx; 2546c0b746e5SOllivier Robert 2547c0b746e5SOllivier Robert if (!pll_control) { 2548c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2549c0b746e5SOllivier Robert return; 2550c0b746e5SOllivier Robert } 2551c0b746e5SOllivier Robert 2552c0b746e5SOllivier Robert memset((char *)&ntx, 0, sizeof(ntx)); 2553c0b746e5SOllivier Robert if (ntp_adjtime(&ntx) < 0) 2554c0b746e5SOllivier Robert msyslog(LOG_ERR, "get_kernel_info: ntp_adjtime() failed: %m"); 2555c0b746e5SOllivier Robert ik = (struct info_kernel *)prepare_pkt(srcadr, inter, inpkt, 2556c0b746e5SOllivier Robert sizeof(struct info_kernel)); 2557c0b746e5SOllivier Robert 2558c0b746e5SOllivier Robert /* 2559c0b746e5SOllivier Robert * pll variables 2560c0b746e5SOllivier Robert */ 2561c0b746e5SOllivier Robert ik->offset = htonl((u_int32)ntx.offset); 2562c0b746e5SOllivier Robert ik->freq = htonl((u_int32)ntx.freq); 2563c0b746e5SOllivier Robert ik->maxerror = htonl((u_int32)ntx.maxerror); 2564c0b746e5SOllivier Robert ik->esterror = htonl((u_int32)ntx.esterror); 2565c0b746e5SOllivier Robert ik->status = htons(ntx.status); 2566c0b746e5SOllivier Robert ik->constant = htonl((u_int32)ntx.constant); 2567c0b746e5SOllivier Robert ik->precision = htonl((u_int32)ntx.precision); 2568c0b746e5SOllivier Robert ik->tolerance = htonl((u_int32)ntx.tolerance); 2569c0b746e5SOllivier Robert 2570c0b746e5SOllivier Robert /* 2571c0b746e5SOllivier Robert * pps variables 2572c0b746e5SOllivier Robert */ 2573c0b746e5SOllivier Robert ik->ppsfreq = htonl((u_int32)ntx.ppsfreq); 2574c0b746e5SOllivier Robert ik->jitter = htonl((u_int32)ntx.jitter); 2575c0b746e5SOllivier Robert ik->shift = htons(ntx.shift); 2576c0b746e5SOllivier Robert ik->stabil = htonl((u_int32)ntx.stabil); 2577c0b746e5SOllivier Robert ik->jitcnt = htonl((u_int32)ntx.jitcnt); 2578c0b746e5SOllivier Robert ik->calcnt = htonl((u_int32)ntx.calcnt); 2579c0b746e5SOllivier Robert ik->errcnt = htonl((u_int32)ntx.errcnt); 2580c0b746e5SOllivier Robert ik->stbcnt = htonl((u_int32)ntx.stbcnt); 2581c0b746e5SOllivier Robert 2582c0b746e5SOllivier Robert (void) more_pkt(); 2583c0b746e5SOllivier Robert flush_pkt(); 2584c0b746e5SOllivier Robert } 2585c0b746e5SOllivier Robert #endif /* KERNEL_PLL */ 2586c0b746e5SOllivier Robert 2587c0b746e5SOllivier Robert 2588c0b746e5SOllivier Robert #ifdef REFCLOCK 2589c0b746e5SOllivier Robert /* 2590c0b746e5SOllivier Robert * get_clock_info - get info about a clock 2591c0b746e5SOllivier Robert */ 2592c0b746e5SOllivier Robert static void 2593c0b746e5SOllivier Robert get_clock_info( 25949c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2595c0b746e5SOllivier Robert struct interface *inter, 2596c0b746e5SOllivier Robert struct req_pkt *inpkt 2597c0b746e5SOllivier Robert ) 2598c0b746e5SOllivier Robert { 2599c0b746e5SOllivier Robert register struct info_clock *ic; 2600c0b746e5SOllivier Robert register u_int32 *clkaddr; 2601c0b746e5SOllivier Robert register int items; 2602c0b746e5SOllivier Robert struct refclockstat clock_stat; 26039c2daa00SOllivier Robert struct sockaddr_storage addr; 26049c2daa00SOllivier Robert struct sockaddr_in tmp_clock; 2605c0b746e5SOllivier Robert l_fp ltmp; 2606c0b746e5SOllivier Robert 2607c0b746e5SOllivier Robert memset((char *)&addr, 0, sizeof addr); 26089c2daa00SOllivier Robert addr.ss_family = AF_INET; 26099c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 26109c2daa00SOllivier Robert addr.ss_len = SOCKLEN(&addr); 26119c2daa00SOllivier Robert #endif 26129c2daa00SOllivier Robert NSRCPORT(&addr) = htons(NTP_PORT); 2613c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2614c0b746e5SOllivier Robert clkaddr = (u_int32 *) inpkt->data; 2615c0b746e5SOllivier Robert 2616c0b746e5SOllivier Robert ic = (struct info_clock *)prepare_pkt(srcadr, inter, inpkt, 2617c0b746e5SOllivier Robert sizeof(struct info_clock)); 2618c0b746e5SOllivier Robert 2619c0b746e5SOllivier Robert while (items-- > 0) { 26209c2daa00SOllivier Robert tmp_clock.sin_addr.s_addr = *clkaddr++; 26219c2daa00SOllivier Robert CAST_V4(addr)->sin_addr = tmp_clock.sin_addr; 26229c2daa00SOllivier Robert if (!ISREFCLOCKADR(&tmp_clock) || 2623c0b746e5SOllivier Robert findexistingpeer(&addr, (struct peer *)0, -1) == 0) { 2624c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2625c0b746e5SOllivier Robert return; 2626c0b746e5SOllivier Robert } 2627c0b746e5SOllivier Robert 2628c0b746e5SOllivier Robert clock_stat.kv_list = (struct ctl_var *)0; 2629c0b746e5SOllivier Robert 2630c0b746e5SOllivier Robert refclock_control(&addr, (struct refclockstat *)0, &clock_stat); 2631c0b746e5SOllivier Robert 26329c2daa00SOllivier Robert ic->clockadr = tmp_clock.sin_addr.s_addr; 2633c0b746e5SOllivier Robert ic->type = clock_stat.type; 2634c0b746e5SOllivier Robert ic->flags = clock_stat.flags; 2635c0b746e5SOllivier Robert ic->lastevent = clock_stat.lastevent; 2636c0b746e5SOllivier Robert ic->currentstatus = clock_stat.currentstatus; 2637c0b746e5SOllivier Robert ic->polls = htonl((u_int32)clock_stat.polls); 2638c0b746e5SOllivier Robert ic->noresponse = htonl((u_int32)clock_stat.noresponse); 2639c0b746e5SOllivier Robert ic->badformat = htonl((u_int32)clock_stat.badformat); 2640c0b746e5SOllivier Robert ic->baddata = htonl((u_int32)clock_stat.baddata); 2641c0b746e5SOllivier Robert ic->timestarted = htonl((u_int32)clock_stat.timereset); 2642c0b746e5SOllivier Robert DTOLFP(clock_stat.fudgetime1, <mp); 2643c0b746e5SOllivier Robert HTONL_FP(<mp, &ic->fudgetime1); 26449c2daa00SOllivier Robert DTOLFP(clock_stat.fudgetime2, <mp); 2645c0b746e5SOllivier Robert HTONL_FP(<mp, &ic->fudgetime2); 2646c0b746e5SOllivier Robert ic->fudgeval1 = htonl((u_int32)clock_stat.fudgeval1); 2647c0b746e5SOllivier Robert ic->fudgeval2 = htonl((u_int32)clock_stat.fudgeval2); 2648c0b746e5SOllivier Robert 2649c0b746e5SOllivier Robert free_varlist(clock_stat.kv_list); 2650c0b746e5SOllivier Robert 2651c0b746e5SOllivier Robert ic = (struct info_clock *)more_pkt(); 2652c0b746e5SOllivier Robert } 2653c0b746e5SOllivier Robert flush_pkt(); 2654c0b746e5SOllivier Robert } 2655c0b746e5SOllivier Robert 2656c0b746e5SOllivier Robert 2657c0b746e5SOllivier Robert 2658c0b746e5SOllivier Robert /* 2659c0b746e5SOllivier Robert * set_clock_fudge - get a clock's fudge factors 2660c0b746e5SOllivier Robert */ 2661c0b746e5SOllivier Robert static void 2662c0b746e5SOllivier Robert set_clock_fudge( 26639c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2664c0b746e5SOllivier Robert struct interface *inter, 2665c0b746e5SOllivier Robert struct req_pkt *inpkt 2666c0b746e5SOllivier Robert ) 2667c0b746e5SOllivier Robert { 2668c0b746e5SOllivier Robert register struct conf_fudge *cf; 2669c0b746e5SOllivier Robert register int items; 2670c0b746e5SOllivier Robert struct refclockstat clock_stat; 26719c2daa00SOllivier Robert struct sockaddr_storage addr; 26729c2daa00SOllivier Robert struct sockaddr_in tmp_clock; 2673c0b746e5SOllivier Robert l_fp ltmp; 2674c0b746e5SOllivier Robert 2675c0b746e5SOllivier Robert memset((char *)&addr, 0, sizeof addr); 2676c0b746e5SOllivier Robert memset((char *)&clock_stat, 0, sizeof clock_stat); 2677c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2678c0b746e5SOllivier Robert cf = (struct conf_fudge *) inpkt->data; 2679c0b746e5SOllivier Robert 2680c0b746e5SOllivier Robert while (items-- > 0) { 26819c2daa00SOllivier Robert tmp_clock.sin_addr.s_addr = cf->clockadr; 26829c2daa00SOllivier Robert *CAST_V4(addr) = tmp_clock; 26839c2daa00SOllivier Robert addr.ss_family = AF_INET; 26849c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 26859c2daa00SOllivier Robert addr.ss_len = SOCKLEN(&addr); 26869c2daa00SOllivier Robert #endif 26879c2daa00SOllivier Robert NSRCPORT(&addr) = htons(NTP_PORT); 26889c2daa00SOllivier Robert if (!ISREFCLOCKADR(&tmp_clock) || 2689c0b746e5SOllivier Robert findexistingpeer(&addr, (struct peer *)0, -1) == 0) { 2690c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2691c0b746e5SOllivier Robert return; 2692c0b746e5SOllivier Robert } 2693c0b746e5SOllivier Robert 2694c0b746e5SOllivier Robert switch(ntohl(cf->which)) { 2695c0b746e5SOllivier Robert case FUDGE_TIME1: 2696c0b746e5SOllivier Robert NTOHL_FP(&cf->fudgetime, <mp); 2697c0b746e5SOllivier Robert LFPTOD(<mp, clock_stat.fudgetime1); 2698c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVETIME1; 2699c0b746e5SOllivier Robert break; 2700c0b746e5SOllivier Robert case FUDGE_TIME2: 2701c0b746e5SOllivier Robert NTOHL_FP(&cf->fudgetime, <mp); 2702c0b746e5SOllivier Robert LFPTOD(<mp, clock_stat.fudgetime2); 2703c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVETIME2; 2704c0b746e5SOllivier Robert break; 2705c0b746e5SOllivier Robert case FUDGE_VAL1: 2706c0b746e5SOllivier Robert clock_stat.fudgeval1 = ntohl(cf->fudgeval_flags); 2707c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVEVAL1; 2708c0b746e5SOllivier Robert break; 2709c0b746e5SOllivier Robert case FUDGE_VAL2: 2710c0b746e5SOllivier Robert clock_stat.fudgeval2 = ntohl(cf->fudgeval_flags); 2711c0b746e5SOllivier Robert clock_stat.haveflags = CLK_HAVEVAL2; 2712c0b746e5SOllivier Robert break; 2713c0b746e5SOllivier Robert case FUDGE_FLAGS: 27149c2daa00SOllivier Robert clock_stat.flags = (u_char) (ntohl(cf->fudgeval_flags) & 0xf); 2715c0b746e5SOllivier Robert clock_stat.haveflags = 2716c0b746e5SOllivier Robert (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4); 2717c0b746e5SOllivier Robert break; 2718c0b746e5SOllivier Robert default: 2719224ba2bdSOllivier Robert msyslog(LOG_ERR, "set_clock_fudge: default!"); 2720c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 2721c0b746e5SOllivier Robert return; 2722c0b746e5SOllivier Robert } 2723c0b746e5SOllivier Robert 2724c0b746e5SOllivier Robert refclock_control(&addr, &clock_stat, (struct refclockstat *)0); 2725c0b746e5SOllivier Robert } 2726c0b746e5SOllivier Robert 2727c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_OKAY); 2728c0b746e5SOllivier Robert } 2729c0b746e5SOllivier Robert #endif 2730c0b746e5SOllivier Robert 2731c0b746e5SOllivier Robert #ifdef REFCLOCK 2732c0b746e5SOllivier Robert /* 2733c0b746e5SOllivier Robert * get_clkbug_info - get debugging info about a clock 2734c0b746e5SOllivier Robert */ 2735c0b746e5SOllivier Robert static void 2736c0b746e5SOllivier Robert get_clkbug_info( 27379c2daa00SOllivier Robert struct sockaddr_storage *srcadr, 2738c0b746e5SOllivier Robert struct interface *inter, 2739c0b746e5SOllivier Robert struct req_pkt *inpkt 2740c0b746e5SOllivier Robert ) 2741c0b746e5SOllivier Robert { 2742c0b746e5SOllivier Robert register int i; 2743c0b746e5SOllivier Robert register struct info_clkbug *ic; 2744c0b746e5SOllivier Robert register u_int32 *clkaddr; 2745c0b746e5SOllivier Robert register int items; 2746c0b746e5SOllivier Robert struct refclockbug bug; 27479c2daa00SOllivier Robert struct sockaddr_storage addr; 27489c2daa00SOllivier Robert struct sockaddr_in tmp_clock; 2749c0b746e5SOllivier Robert 2750c0b746e5SOllivier Robert memset((char *)&addr, 0, sizeof addr); 27519c2daa00SOllivier Robert addr.ss_family = AF_INET; 27529c2daa00SOllivier Robert #ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 27539c2daa00SOllivier Robert addr.ss_len = SOCKLEN(&addr); 27549c2daa00SOllivier Robert #endif 27559c2daa00SOllivier Robert NSRCPORT(&addr) = htons(NTP_PORT); 2756c0b746e5SOllivier Robert items = INFO_NITEMS(inpkt->err_nitems); 2757c0b746e5SOllivier Robert clkaddr = (u_int32 *) inpkt->data; 2758c0b746e5SOllivier Robert 2759c0b746e5SOllivier Robert ic = (struct info_clkbug *)prepare_pkt(srcadr, inter, inpkt, 2760c0b746e5SOllivier Robert sizeof(struct info_clkbug)); 2761c0b746e5SOllivier Robert 2762c0b746e5SOllivier Robert while (items-- > 0) { 27639c2daa00SOllivier Robert tmp_clock.sin_addr.s_addr = *clkaddr++; 27649c2daa00SOllivier Robert GET_INADDR(addr) = tmp_clock.sin_addr.s_addr; 27659c2daa00SOllivier Robert if (!ISREFCLOCKADR(&tmp_clock) || 2766c0b746e5SOllivier Robert findexistingpeer(&addr, (struct peer *)0, -1) == 0) { 2767c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2768c0b746e5SOllivier Robert return; 2769c0b746e5SOllivier Robert } 2770c0b746e5SOllivier Robert 2771c0b746e5SOllivier Robert memset((char *)&bug, 0, sizeof bug); 2772c0b746e5SOllivier Robert refclock_buginfo(&addr, &bug); 2773c0b746e5SOllivier Robert if (bug.nvalues == 0 && bug.ntimes == 0) { 2774c0b746e5SOllivier Robert req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 2775c0b746e5SOllivier Robert return; 2776c0b746e5SOllivier Robert } 2777c0b746e5SOllivier Robert 27789c2daa00SOllivier Robert ic->clockadr = tmp_clock.sin_addr.s_addr; 2779c0b746e5SOllivier Robert i = bug.nvalues; 2780c0b746e5SOllivier Robert if (i > NUMCBUGVALUES) 2781c0b746e5SOllivier Robert i = NUMCBUGVALUES; 2782c0b746e5SOllivier Robert ic->nvalues = (u_char)i; 2783c0b746e5SOllivier Robert ic->svalues = htons((u_short) (bug.svalues & ((1<<i)-1))); 2784c0b746e5SOllivier Robert while (--i >= 0) 2785c0b746e5SOllivier Robert ic->values[i] = htonl(bug.values[i]); 2786c0b746e5SOllivier Robert 2787c0b746e5SOllivier Robert i = bug.ntimes; 2788c0b746e5SOllivier Robert if (i > NUMCBUGTIMES) 2789c0b746e5SOllivier Robert i = NUMCBUGTIMES; 2790c0b746e5SOllivier Robert ic->ntimes = (u_char)i; 2791c0b746e5SOllivier Robert ic->stimes = htonl(bug.stimes); 2792c0b746e5SOllivier Robert while (--i >= 0) { 2793c0b746e5SOllivier Robert HTONL_FP(&bug.times[i], &ic->times[i]); 2794c0b746e5SOllivier Robert } 2795c0b746e5SOllivier Robert 2796c0b746e5SOllivier Robert ic = (struct info_clkbug *)more_pkt(); 2797c0b746e5SOllivier Robert } 2798c0b746e5SOllivier Robert flush_pkt(); 2799c0b746e5SOllivier Robert } 2800c0b746e5SOllivier Robert #endif 2801ea906c41SOllivier Robert 2802ea906c41SOllivier Robert /* 2803ea906c41SOllivier Robert * receiver of interface structures 2804ea906c41SOllivier Robert */ 2805ea906c41SOllivier Robert static void 2806ea906c41SOllivier Robert fill_info_if_stats(void *data, interface_info_t *interface_info) 2807ea906c41SOllivier Robert { 2808ea906c41SOllivier Robert struct info_if_stats **ifsp = (struct info_if_stats **)data; 2809ea906c41SOllivier Robert struct info_if_stats *ifs = *ifsp; 2810ea906c41SOllivier Robert struct interface *interface = interface_info->interface; 2811ea906c41SOllivier Robert 2812ea906c41SOllivier Robert memset((char*)ifs, 0, sizeof(*ifs)); 2813ea906c41SOllivier Robert 2814ea906c41SOllivier Robert if (interface->sin.ss_family == AF_INET6) { 2815ea906c41SOllivier Robert if (!client_v6_capable) { 2816ea906c41SOllivier Robert return; 2817ea906c41SOllivier Robert } 2818ea906c41SOllivier Robert ifs->v6_flag = 1; 2819ea906c41SOllivier Robert memcpy((char *)&ifs->unaddr.addr6, (char *)&CAST_V6(interface->sin)->sin6_addr, sizeof(struct in6_addr)); 2820ea906c41SOllivier Robert memcpy((char *)&ifs->unbcast.addr6, (char *)&CAST_V6(interface->bcast)->sin6_addr, sizeof(struct in6_addr)); 2821ea906c41SOllivier Robert memcpy((char *)&ifs->unmask.addr6, (char *)&CAST_V6(interface->mask)->sin6_addr, sizeof(struct in6_addr)); 2822ea906c41SOllivier Robert } else { 2823ea906c41SOllivier Robert ifs->v6_flag = 0; 2824ea906c41SOllivier Robert memcpy((char *)&ifs->unaddr.addr, (char *)&CAST_V4(interface->sin)->sin_addr, sizeof(struct in_addr)); 2825ea906c41SOllivier Robert memcpy((char *)&ifs->unbcast.addr, (char *)&CAST_V4(interface->bcast)->sin_addr, sizeof(struct in_addr)); 2826ea906c41SOllivier Robert memcpy((char *)&ifs->unmask.addr, (char *)&CAST_V4(interface->mask)->sin_addr, sizeof(struct in_addr)); 2827ea906c41SOllivier Robert } 2828ea906c41SOllivier Robert ifs->v6_flag = htonl(ifs->v6_flag); 2829ea906c41SOllivier Robert strcpy(ifs->name, interface->name); 2830ea906c41SOllivier Robert ifs->family = htons(interface->family); 2831ea906c41SOllivier Robert ifs->flags = htonl(interface->flags); 2832ea906c41SOllivier Robert ifs->last_ttl = htonl(interface->last_ttl); 2833ea906c41SOllivier Robert ifs->num_mcast = htonl(interface->num_mcast); 2834ea906c41SOllivier Robert ifs->received = htonl(interface->received); 2835ea906c41SOllivier Robert ifs->sent = htonl(interface->sent); 2836ea906c41SOllivier Robert ifs->notsent = htonl(interface->notsent); 2837ea906c41SOllivier Robert ifs->scopeid = htonl(interface->scopeid); 2838ea906c41SOllivier Robert ifs->ifindex = htonl(interface->ifindex); 2839ea906c41SOllivier Robert ifs->ifnum = htonl(interface->ifnum); 2840ea906c41SOllivier Robert ifs->uptime = htonl(current_time - interface->starttime); 2841ea906c41SOllivier Robert ifs->ignore_packets = interface->ignore_packets; 2842ea906c41SOllivier Robert ifs->peercnt = htonl(interface->peercnt); 2843ea906c41SOllivier Robert ifs->action = interface_info->action; 2844ea906c41SOllivier Robert 2845ea906c41SOllivier Robert *ifsp = (struct info_if_stats *)more_pkt(); 2846ea906c41SOllivier Robert } 2847ea906c41SOllivier Robert 2848ea906c41SOllivier Robert /* 2849ea906c41SOllivier Robert * get_if_stats - get interface statistics 2850ea906c41SOllivier Robert */ 2851ea906c41SOllivier Robert static void 2852ea906c41SOllivier Robert get_if_stats( 2853ea906c41SOllivier Robert struct sockaddr_storage *srcadr, 2854ea906c41SOllivier Robert struct interface *inter, 2855ea906c41SOllivier Robert struct req_pkt *inpkt 2856ea906c41SOllivier Robert ) 2857ea906c41SOllivier Robert { 2858ea906c41SOllivier Robert struct info_if_stats *ifs; 2859ea906c41SOllivier Robert 2860ea906c41SOllivier Robert DPRINTF(3, ("wants interface statistics\n")); 2861ea906c41SOllivier Robert 2862ea906c41SOllivier Robert ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt, 2863ea906c41SOllivier Robert v6sizeof(struct info_if_stats)); 2864ea906c41SOllivier Robert 2865ea906c41SOllivier Robert interface_enumerate(fill_info_if_stats, &ifs); 2866ea906c41SOllivier Robert 2867ea906c41SOllivier Robert flush_pkt(); 2868ea906c41SOllivier Robert } 2869ea906c41SOllivier Robert 2870ea906c41SOllivier Robert static void 2871ea906c41SOllivier Robert do_if_reload( 2872ea906c41SOllivier Robert struct sockaddr_storage *srcadr, 2873ea906c41SOllivier Robert struct interface *inter, 2874ea906c41SOllivier Robert struct req_pkt *inpkt 2875ea906c41SOllivier Robert ) 2876ea906c41SOllivier Robert { 2877ea906c41SOllivier Robert struct info_if_stats *ifs; 2878ea906c41SOllivier Robert 2879ea906c41SOllivier Robert DPRINTF(3, ("wants interface reload\n")); 2880ea906c41SOllivier Robert 2881ea906c41SOllivier Robert ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt, 2882ea906c41SOllivier Robert v6sizeof(struct info_if_stats)); 2883ea906c41SOllivier Robert 2884ea906c41SOllivier Robert interface_update(fill_info_if_stats, &ifs); 2885ea906c41SOllivier Robert 2886ea906c41SOllivier Robert flush_pkt(); 2887ea906c41SOllivier Robert } 2888ea906c41SOllivier Robert 2889