ntp_request.c revision 200576
154359Sroberto/* 254359Sroberto * ntp_request.c - respond to information requests 354359Sroberto */ 4132451Sroberto 554359Sroberto#ifdef HAVE_CONFIG_H 682498Sroberto# include <config.h> 754359Sroberto#endif 854359Sroberto 954359Sroberto#include "ntpd.h" 1054359Sroberto#include "ntp_io.h" 1154359Sroberto#include "ntp_request.h" 1254359Sroberto#include "ntp_control.h" 1354359Sroberto#include "ntp_refclock.h" 1454359Sroberto#include "ntp_if.h" 1554359Sroberto#include "ntp_stdlib.h" 1682498Sroberto 1782498Sroberto#include <stdio.h> 18132451Sroberto#include <stddef.h> 1982498Sroberto#include <signal.h> 2082498Sroberto#include <netinet/in.h> 2182498Sroberto#include <arpa/inet.h> 2282498Sroberto 2354359Sroberto#include "recvbuff.h" 2454359Sroberto 2554359Sroberto#ifdef KERNEL_PLL 2654359Sroberto#include "ntp_syscall.h" 2754359Sroberto#endif /* KERNEL_PLL */ 2854359Sroberto 2954359Sroberto/* 3054359Sroberto * Structure to hold request procedure information 3154359Sroberto */ 3254359Sroberto#define NOAUTH 0 3354359Sroberto#define AUTH 1 3454359Sroberto 3554359Sroberto#define NO_REQUEST (-1) 36132451Sroberto/* 37132451Sroberto * Because we now have v6 addresses in the messages, we need to compensate 38132451Sroberto * for the larger size. Therefore, we introduce the alternate size to 39132451Sroberto * keep us friendly with older implementations. A little ugly. 40132451Sroberto */ 41132451Srobertostatic int client_v6_capable = 0; /* the client can handle longer messages */ 4254359Sroberto 43132451Sroberto#define v6sizeof(type) (client_v6_capable ? sizeof(type) : v4sizeof(type)) 44132451Sroberto 4554359Srobertostruct req_proc { 4654359Sroberto short request_code; /* defined request code */ 4754359Sroberto short needs_auth; /* true when authentication needed */ 48132451Sroberto short sizeofitem; /* size of request data item (older size)*/ 49132451Sroberto short v6_sizeofitem; /* size of request data item (new size)*/ 50132451Sroberto void (*handler) P((struct sockaddr_storage *, struct interface *, 5154359Sroberto struct req_pkt *)); /* routine to handle request */ 5254359Sroberto}; 5354359Sroberto 5454359Sroberto/* 5554359Sroberto * Universal request codes 5654359Sroberto */ 5754359Srobertostatic struct req_proc univ_codes[] = { 5854359Sroberto { NO_REQUEST, NOAUTH, 0, 0 } 5954359Sroberto}; 6054359Sroberto 61132451Srobertostatic void req_ack P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int)); 62132451Srobertostatic char * prepare_pkt P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_int)); 6354359Srobertostatic char * more_pkt P((void)); 6454359Srobertostatic void flush_pkt P((void)); 65132451Srobertostatic void peer_list P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 66132451Srobertostatic void peer_list_sum P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 67132451Srobertostatic void peer_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 68132451Srobertostatic void peer_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 69132451Srobertostatic void sys_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 70132451Srobertostatic void sys_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 71132451Srobertostatic void mem_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 72132451Srobertostatic void io_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 73132451Srobertostatic void timer_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 74132451Srobertostatic void loop_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 75132451Srobertostatic void do_conf P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 76132451Srobertostatic void do_unconf P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 77132451Srobertostatic void set_sys_flag P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 78132451Srobertostatic void clr_sys_flag P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 79132451Srobertostatic void setclr_flags P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_long)); 80132451Srobertostatic void list_restrict P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 81132451Srobertostatic void do_resaddflags P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 82132451Srobertostatic void do_ressubflags P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 83132451Srobertostatic void do_unrestrict P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 84132451Srobertostatic void do_restrict P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int)); 85132451Srobertostatic void mon_getlist_0 P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 86132451Srobertostatic void mon_getlist_1 P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 87132451Srobertostatic void reset_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 88132451Srobertostatic void reset_peer P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 89132451Srobertostatic void do_key_reread P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 90132451Srobertostatic void trust_key P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 91132451Srobertostatic void untrust_key P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 92132451Srobertostatic void do_trustkey P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_long)); 93132451Srobertostatic void get_auth_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 9454359Srobertostatic void reset_auth_stats P((void)); 95132451Srobertostatic void req_get_traps P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 96132451Srobertostatic void req_set_trap P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 97132451Srobertostatic void req_clr_trap P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 98132451Srobertostatic void do_setclr_trap P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int)); 99132451Srobertostatic void set_request_keyid P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 100132451Srobertostatic void set_control_keyid P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 101182007Srobertostatic void get_ctl_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 102182007Srobertostatic void get_if_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 103182007Srobertostatic void do_if_reload P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 10454359Sroberto#ifdef KERNEL_PLL 105132451Srobertostatic void get_kernel_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 10654359Sroberto#endif /* KERNEL_PLL */ 10754359Sroberto#ifdef REFCLOCK 108132451Srobertostatic void get_clock_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 109132451Srobertostatic void set_clock_fudge P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 11054359Sroberto#endif /* REFCLOCK */ 11154359Sroberto#ifdef REFCLOCK 112132451Srobertostatic void get_clkbug_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *)); 11354359Sroberto#endif /* REFCLOCK */ 11454359Sroberto 11554359Sroberto/* 11654359Sroberto * ntpd request codes 11754359Sroberto */ 11854359Srobertostatic struct req_proc ntp_codes[] = { 119132451Sroberto { REQ_PEER_LIST, NOAUTH, 0, 0, peer_list }, 120132451Sroberto { REQ_PEER_LIST_SUM, NOAUTH, 0, 0, peer_list_sum }, 121132451Sroberto { REQ_PEER_INFO, NOAUTH, v4sizeof(struct info_peer_list), 122132451Sroberto sizeof(struct info_peer_list), peer_info}, 123132451Sroberto { REQ_PEER_STATS, NOAUTH, v4sizeof(struct info_peer_list), 124132451Sroberto sizeof(struct info_peer_list), peer_stats}, 125132451Sroberto { REQ_SYS_INFO, NOAUTH, 0, 0, sys_info }, 126132451Sroberto { REQ_SYS_STATS, NOAUTH, 0, 0, sys_stats }, 127132451Sroberto { REQ_IO_STATS, NOAUTH, 0, 0, io_stats }, 128132451Sroberto { REQ_MEM_STATS, NOAUTH, 0, 0, mem_stats }, 129132451Sroberto { REQ_LOOP_INFO, NOAUTH, 0, 0, loop_info }, 130132451Sroberto { REQ_TIMER_STATS, NOAUTH, 0, 0, timer_stats }, 131132451Sroberto { REQ_CONFIG, AUTH, v4sizeof(struct conf_peer), 132132451Sroberto sizeof(struct conf_peer), do_conf }, 133132451Sroberto { REQ_UNCONFIG, AUTH, v4sizeof(struct conf_unpeer), 134132451Sroberto sizeof(struct conf_unpeer), do_unconf }, 135132451Sroberto { REQ_SET_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), 136132451Sroberto sizeof(struct conf_sys_flags), set_sys_flag }, 137132451Sroberto { REQ_CLR_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), 138132451Sroberto sizeof(struct conf_sys_flags), clr_sys_flag }, 139132451Sroberto { REQ_GET_RESTRICT, NOAUTH, 0, 0, list_restrict }, 140132451Sroberto { REQ_RESADDFLAGS, AUTH, v4sizeof(struct conf_restrict), 141132451Sroberto sizeof(struct conf_restrict), do_resaddflags }, 142132451Sroberto { REQ_RESSUBFLAGS, AUTH, v4sizeof(struct conf_restrict), 143132451Sroberto sizeof(struct conf_restrict), do_ressubflags }, 144132451Sroberto { REQ_UNRESTRICT, AUTH, v4sizeof(struct conf_restrict), 145132451Sroberto sizeof(struct conf_restrict), do_unrestrict }, 146132451Sroberto { REQ_MON_GETLIST, NOAUTH, 0, 0, mon_getlist_0 }, 147132451Sroberto { REQ_MON_GETLIST_1, NOAUTH, 0, 0, mon_getlist_1 }, 148132451Sroberto { REQ_RESET_STATS, AUTH, sizeof(struct reset_flags), 0, reset_stats }, 149132451Sroberto { REQ_RESET_PEER, AUTH, v4sizeof(struct conf_unpeer), 150132451Sroberto sizeof(struct conf_unpeer), reset_peer }, 151132451Sroberto { REQ_REREAD_KEYS, AUTH, 0, 0, do_key_reread }, 152132451Sroberto { REQ_TRUSTKEY, AUTH, sizeof(u_long), sizeof(u_long), trust_key }, 153132451Sroberto { REQ_UNTRUSTKEY, AUTH, sizeof(u_long), sizeof(u_long), untrust_key }, 154132451Sroberto { REQ_AUTHINFO, NOAUTH, 0, 0, get_auth_info }, 155132451Sroberto { REQ_TRAPS, NOAUTH, 0, 0, req_get_traps }, 156132451Sroberto { REQ_ADD_TRAP, AUTH, v4sizeof(struct conf_trap), 157132451Sroberto sizeof(struct conf_trap), req_set_trap }, 158132451Sroberto { REQ_CLR_TRAP, AUTH, v4sizeof(struct conf_trap), 159132451Sroberto sizeof(struct conf_trap), req_clr_trap }, 160132451Sroberto { REQ_REQUEST_KEY, AUTH, sizeof(u_long), sizeof(u_long), 161132451Sroberto set_request_keyid }, 162132451Sroberto { REQ_CONTROL_KEY, AUTH, sizeof(u_long), sizeof(u_long), 163132451Sroberto set_control_keyid }, 164132451Sroberto { REQ_GET_CTLSTATS, NOAUTH, 0, 0, get_ctl_stats }, 16554359Sroberto#ifdef KERNEL_PLL 166132451Sroberto { REQ_GET_KERNEL, NOAUTH, 0, 0, get_kernel_info }, 16754359Sroberto#endif 16854359Sroberto#ifdef REFCLOCK 169132451Sroberto { REQ_GET_CLOCKINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32), 170132451Sroberto get_clock_info }, 171132451Sroberto { REQ_SET_CLKFUDGE, AUTH, sizeof(struct conf_fudge), 172132451Sroberto sizeof(struct conf_fudge), set_clock_fudge }, 173132451Sroberto { REQ_GET_CLKBUGINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32), 174132451Sroberto get_clkbug_info }, 17554359Sroberto#endif 176182007Sroberto { REQ_IF_STATS, AUTH, 0, 0, get_if_stats }, 177182007Sroberto { REQ_IF_RELOAD, AUTH, 0, 0, do_if_reload }, 178182007Sroberto 179132451Sroberto { NO_REQUEST, NOAUTH, 0, 0, 0 } 18054359Sroberto}; 18154359Sroberto 18254359Sroberto 18354359Sroberto/* 18454359Sroberto * Authentication keyid used to authenticate requests. Zero means we 18554359Sroberto * don't allow writing anything. 18654359Sroberto */ 18782498Srobertokeyid_t info_auth_keyid; 18854359Sroberto 18954359Sroberto/* 19054359Sroberto * Statistic counters to keep track of requests and responses. 19154359Sroberto */ 19254359Srobertou_long numrequests; /* number of requests we've received */ 19354359Srobertou_long numresppkts; /* number of resp packets sent with data */ 19454359Sroberto 19554359Srobertou_long errorcounter[INFO_ERR_AUTH+1]; /* lazy way to count errors, indexed */ 19654359Sroberto/* by the error code */ 19754359Sroberto 19854359Sroberto/* 19954359Sroberto * A hack. To keep the authentication module clear of ntp-ism's, we 20054359Sroberto * include a time reset variable for its stats here. 20154359Sroberto */ 20254359Srobertostatic u_long auth_timereset; 20354359Sroberto 20454359Sroberto/* 20554359Sroberto * Response packet used by these routines. Also some state information 20654359Sroberto * so that we can handle packet formatting within a common set of 20754359Sroberto * subroutines. Note we try to enter data in place whenever possible, 20854359Sroberto * but the need to set the more bit correctly means we occasionally 20954359Sroberto * use the extra buffer and copy. 21054359Sroberto */ 21154359Srobertostatic struct resp_pkt rpkt; 21254359Srobertostatic int reqver; 21354359Srobertostatic int seqno; 21454359Srobertostatic int nitems; 21554359Srobertostatic int itemsize; 21654359Srobertostatic int databytes; 21754359Srobertostatic char exbuf[RESP_DATA_SIZE]; 21854359Srobertostatic int usingexbuf; 219132451Srobertostatic struct sockaddr_storage *toaddr; 22054359Srobertostatic struct interface *frominter; 22154359Sroberto 22254359Sroberto/* 22354359Sroberto * init_request - initialize request data 22454359Sroberto */ 22554359Srobertovoid 22654359Srobertoinit_request (void) 22754359Sroberto{ 22854359Sroberto int i; 22954359Sroberto 23054359Sroberto numrequests = 0; 23154359Sroberto numresppkts = 0; 23254359Sroberto auth_timereset = 0; 23354359Sroberto info_auth_keyid = 0; /* by default, can't do this */ 23454359Sroberto 23554359Sroberto for (i = 0; i < sizeof(errorcounter)/sizeof(errorcounter[0]); i++) 23654359Sroberto errorcounter[i] = 0; 23754359Sroberto} 23854359Sroberto 23954359Sroberto 24054359Sroberto/* 24154359Sroberto * req_ack - acknowledge request with no data 24254359Sroberto */ 24354359Srobertostatic void 24454359Srobertoreq_ack( 245132451Sroberto struct sockaddr_storage *srcadr, 24654359Sroberto struct interface *inter, 24754359Sroberto struct req_pkt *inpkt, 24854359Sroberto int errcode 24954359Sroberto ) 25054359Sroberto{ 25154359Sroberto /* 25254359Sroberto * fill in the fields 25354359Sroberto */ 25454359Sroberto rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver); 25554359Sroberto rpkt.auth_seq = AUTH_SEQ(0, 0); 25654359Sroberto rpkt.implementation = inpkt->implementation; 25754359Sroberto rpkt.request = inpkt->request; 25854359Sroberto rpkt.err_nitems = ERR_NITEMS(errcode, 0); 25954359Sroberto rpkt.mbz_itemsize = MBZ_ITEMSIZE(0); 26054359Sroberto 26154359Sroberto /* 26254359Sroberto * send packet and bump counters 26354359Sroberto */ 26454359Sroberto sendpkt(srcadr, inter, -1, (struct pkt *)&rpkt, RESP_HEADER_SIZE); 26554359Sroberto errorcounter[errcode]++; 26654359Sroberto} 26754359Sroberto 26854359Sroberto 26954359Sroberto/* 27054359Sroberto * prepare_pkt - prepare response packet for transmission, return pointer 27154359Sroberto * to storage for data item. 27254359Sroberto */ 27354359Srobertostatic char * 27454359Srobertoprepare_pkt( 275132451Sroberto struct sockaddr_storage *srcadr, 27654359Sroberto struct interface *inter, 27754359Sroberto struct req_pkt *pkt, 27854359Sroberto u_int structsize 27954359Sroberto ) 28054359Sroberto{ 28154359Sroberto#ifdef DEBUG 28254359Sroberto if (debug > 3) 28354359Sroberto printf("request: preparing pkt\n"); 28454359Sroberto#endif 28554359Sroberto 28654359Sroberto /* 287132451Sroberto * Fill in the implementation, request and itemsize fields 28854359Sroberto * since these won't change. 28954359Sroberto */ 29054359Sroberto rpkt.implementation = pkt->implementation; 29154359Sroberto rpkt.request = pkt->request; 29254359Sroberto rpkt.mbz_itemsize = MBZ_ITEMSIZE(structsize); 29354359Sroberto 29454359Sroberto /* 29554359Sroberto * Compute the static data needed to carry on. 29654359Sroberto */ 29754359Sroberto toaddr = srcadr; 29854359Sroberto frominter = inter; 29954359Sroberto seqno = 0; 30054359Sroberto nitems = 0; 30154359Sroberto itemsize = structsize; 30254359Sroberto databytes = 0; 30354359Sroberto usingexbuf = 0; 30454359Sroberto 30554359Sroberto /* 30654359Sroberto * return the beginning of the packet buffer. 30754359Sroberto */ 30854359Sroberto return &rpkt.data[0]; 30954359Sroberto} 31054359Sroberto 31154359Sroberto 31254359Sroberto/* 31354359Sroberto * more_pkt - return a data pointer for a new item. 31454359Sroberto */ 31554359Srobertostatic char * 31654359Srobertomore_pkt(void) 31754359Sroberto{ 31854359Sroberto /* 31954359Sroberto * If we were using the extra buffer, send the packet. 32054359Sroberto */ 32154359Sroberto if (usingexbuf) { 32254359Sroberto#ifdef DEBUG 32354359Sroberto if (debug > 2) 32454359Sroberto printf("request: sending pkt\n"); 32554359Sroberto#endif 32654359Sroberto rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, MORE_BIT, reqver); 32754359Sroberto rpkt.auth_seq = AUTH_SEQ(0, seqno); 32854359Sroberto rpkt.err_nitems = htons((u_short)nitems); 32954359Sroberto sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt, 33054359Sroberto RESP_HEADER_SIZE+databytes); 33154359Sroberto numresppkts++; 33254359Sroberto 33354359Sroberto /* 33454359Sroberto * Copy data out of exbuf into the packet. 33554359Sroberto */ 33654359Sroberto memmove(&rpkt.data[0], exbuf, (unsigned)itemsize); 33754359Sroberto seqno++; 33854359Sroberto databytes = 0; 33954359Sroberto nitems = 0; 34054359Sroberto usingexbuf = 0; 34154359Sroberto } 34254359Sroberto 34354359Sroberto databytes += itemsize; 34454359Sroberto nitems++; 34554359Sroberto if (databytes + itemsize <= RESP_DATA_SIZE) { 34654359Sroberto#ifdef DEBUG 34754359Sroberto if (debug > 3) 34854359Sroberto printf("request: giving him more data\n"); 34954359Sroberto#endif 35054359Sroberto /* 35154359Sroberto * More room in packet. Give him the 35254359Sroberto * next address. 35354359Sroberto */ 35454359Sroberto return &rpkt.data[databytes]; 35554359Sroberto } else { 35654359Sroberto /* 35754359Sroberto * No room in packet. Give him the extra 35854359Sroberto * buffer unless this was the last in the sequence. 35954359Sroberto */ 36054359Sroberto#ifdef DEBUG 36154359Sroberto if (debug > 3) 36254359Sroberto printf("request: into extra buffer\n"); 36354359Sroberto#endif 36454359Sroberto if (seqno == MAXSEQ) 36554359Sroberto return (char *)0; 36654359Sroberto else { 36754359Sroberto usingexbuf = 1; 36854359Sroberto return exbuf; 36954359Sroberto } 37054359Sroberto } 37154359Sroberto} 37254359Sroberto 37354359Sroberto 37454359Sroberto/* 37554359Sroberto * flush_pkt - we're done, return remaining information. 37654359Sroberto */ 37754359Srobertostatic void 37854359Srobertoflush_pkt(void) 37954359Sroberto{ 38054359Sroberto#ifdef DEBUG 38154359Sroberto if (debug > 2) 38254359Sroberto printf("request: flushing packet, %d items\n", nitems); 38354359Sroberto#endif 38454359Sroberto /* 38554359Sroberto * Must send the last packet. If nothing in here and nothing 38654359Sroberto * has been sent, send an error saying no data to be found. 38754359Sroberto */ 38854359Sroberto if (seqno == 0 && nitems == 0) 38954359Sroberto req_ack(toaddr, frominter, (struct req_pkt *)&rpkt, 39054359Sroberto INFO_ERR_NODATA); 39154359Sroberto else { 39254359Sroberto rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver); 39354359Sroberto rpkt.auth_seq = AUTH_SEQ(0, seqno); 39454359Sroberto rpkt.err_nitems = htons((u_short)nitems); 39554359Sroberto sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt, 39654359Sroberto RESP_HEADER_SIZE+databytes); 39754359Sroberto numresppkts++; 39854359Sroberto } 39954359Sroberto} 40054359Sroberto 40154359Sroberto 40254359Sroberto 40354359Sroberto/* 40454359Sroberto * process_private - process private mode (7) packets 40554359Sroberto */ 40654359Srobertovoid 40754359Srobertoprocess_private( 40854359Sroberto struct recvbuf *rbufp, 40954359Sroberto int mod_okay 41054359Sroberto ) 41154359Sroberto{ 412200576Sroberto static u_long quiet_until; 41354359Sroberto struct req_pkt *inpkt; 414106163Sroberto struct req_pkt_tail *tailinpkt; 415132451Sroberto struct sockaddr_storage *srcadr; 41654359Sroberto struct interface *inter; 41754359Sroberto struct req_proc *proc; 41882498Sroberto int ec; 419132451Sroberto short temp_size; 42054359Sroberto 42154359Sroberto /* 42254359Sroberto * Initialize pointers, for convenience 42354359Sroberto */ 42454359Sroberto inpkt = (struct req_pkt *)&rbufp->recv_pkt; 42554359Sroberto srcadr = &rbufp->recv_srcadr; 42654359Sroberto inter = rbufp->dstadr; 42754359Sroberto 42854359Sroberto#ifdef DEBUG 42954359Sroberto if (debug > 2) 43082498Sroberto printf("process_private: impl %d req %d\n", 43154359Sroberto inpkt->implementation, inpkt->request); 43254359Sroberto#endif 43354359Sroberto 43454359Sroberto /* 43554359Sroberto * Do some sanity checks on the packet. Return a format 43654359Sroberto * error if it fails. 43754359Sroberto */ 43882498Sroberto ec = 0; 43982498Sroberto if ( (++ec, ISRESPONSE(inpkt->rm_vn_mode)) 44082498Sroberto || (++ec, ISMORE(inpkt->rm_vn_mode)) 44182498Sroberto || (++ec, INFO_VERSION(inpkt->rm_vn_mode) > NTP_VERSION) 44282498Sroberto || (++ec, INFO_VERSION(inpkt->rm_vn_mode) < NTP_OLDVERSION) 44382498Sroberto || (++ec, INFO_SEQ(inpkt->auth_seq) != 0) 44482498Sroberto || (++ec, INFO_ERR(inpkt->err_nitems) != 0) 44582498Sroberto || (++ec, INFO_MBZ(inpkt->mbz_itemsize) != 0) 446106163Sroberto || (++ec, rbufp->recv_length < REQ_LEN_HDR) 44782498Sroberto ) { 448200576Sroberto NLOG(NLOG_SYSEVENT) 449200576Sroberto if (current_time >= quiet_until) { 450200576Sroberto msyslog(LOG_ERR, 451200576Sroberto "process_private: drop test %d" 452200576Sroberto " failed, pkt from %s", 453200576Sroberto ec, stoa(srcadr)); 454200576Sroberto quiet_until = current_time + 60; 455200576Sroberto } 45654359Sroberto return; 45754359Sroberto } 45854359Sroberto 45954359Sroberto reqver = INFO_VERSION(inpkt->rm_vn_mode); 46054359Sroberto 46154359Sroberto /* 46254359Sroberto * Get the appropriate procedure list to search. 46354359Sroberto */ 46454359Sroberto if (inpkt->implementation == IMPL_UNIV) 46554359Sroberto proc = univ_codes; 466132451Sroberto else if ((inpkt->implementation == IMPL_XNTPD) || 467132451Sroberto (inpkt->implementation == IMPL_XNTPD_OLD)) 46854359Sroberto proc = ntp_codes; 46954359Sroberto else { 47054359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_IMPL); 47154359Sroberto return; 47254359Sroberto } 47354359Sroberto 47454359Sroberto /* 47554359Sroberto * Search the list for the request codes. If it isn't one 47654359Sroberto * we know, return an error. 47754359Sroberto */ 47854359Sroberto while (proc->request_code != NO_REQUEST) { 47954359Sroberto if (proc->request_code == (short) inpkt->request) 48054359Sroberto break; 48154359Sroberto proc++; 48254359Sroberto } 48354359Sroberto if (proc->request_code == NO_REQUEST) { 48454359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_REQ); 48554359Sroberto return; 48654359Sroberto } 48754359Sroberto 48854359Sroberto#ifdef DEBUG 48954359Sroberto if (debug > 3) 49054359Sroberto printf("found request in tables\n"); 49154359Sroberto#endif 49254359Sroberto 49354359Sroberto /* 494132451Sroberto * If we need data, check to see if we have some. If we 495132451Sroberto * don't, check to see that there is none (picky, picky). 496132451Sroberto */ 497132451Sroberto 498132451Sroberto /* This part is a bit tricky, we want to be sure that the size 499132451Sroberto * returned is either the old or the new size. We also can find 500132451Sroberto * out if the client can accept both types of messages this way. 501132451Sroberto * 502132451Sroberto * Handle the exception of REQ_CONFIG. It can have two data sizes. 503132451Sroberto */ 504132451Sroberto temp_size = INFO_ITEMSIZE(inpkt->mbz_itemsize); 505132451Sroberto if ((temp_size != proc->sizeofitem && 506200576Sroberto temp_size != proc->v6_sizeofitem) && 507132451Sroberto !(inpkt->implementation == IMPL_XNTPD && 508200576Sroberto inpkt->request == REQ_CONFIG && 509200576Sroberto temp_size == sizeof(struct old_conf_peer))) { 510182007Sroberto#ifdef DEBUG 511132451Sroberto if (debug > 2) 512132451Sroberto printf("process_private: wrong item size, received %d, should be %d or %d\n", 513132451Sroberto temp_size, proc->sizeofitem, proc->v6_sizeofitem); 514182007Sroberto#endif 515132451Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 516132451Sroberto return; 517132451Sroberto } 518132451Sroberto if ((proc->sizeofitem != 0) && 519132451Sroberto ((temp_size * INFO_NITEMS(inpkt->err_nitems)) > 520132451Sroberto (rbufp->recv_length - REQ_LEN_HDR))) { 521182007Sroberto#ifdef DEBUG 522132451Sroberto if (debug > 2) 523132451Sroberto printf("process_private: not enough data\n"); 524182007Sroberto#endif 525132451Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 526132451Sroberto return; 527132451Sroberto } 528132451Sroberto 529132451Sroberto switch (inpkt->implementation) { 530132451Sroberto case IMPL_XNTPD: 531132451Sroberto client_v6_capable = 1; 532132451Sroberto break; 533132451Sroberto case IMPL_XNTPD_OLD: 534132451Sroberto client_v6_capable = 0; 535132451Sroberto break; 536132451Sroberto default: 537132451Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 538132451Sroberto return; 539132451Sroberto } 540132451Sroberto 541132451Sroberto /* 54254359Sroberto * If we need to authenticate, do so. Note that an 54354359Sroberto * authenticatable packet must include a mac field, must 54454359Sroberto * have used key info_auth_keyid and must have included 54554359Sroberto * a time stamp in the appropriate field. The time stamp 54654359Sroberto * must be within INFO_TS_MAXSKEW of the receive 54754359Sroberto * time stamp. 54854359Sroberto */ 54954359Sroberto if (proc->needs_auth && sys_authenticate) { 55054359Sroberto l_fp ftmp; 55154359Sroberto double dtemp; 55254359Sroberto 553132451Sroberto if (rbufp->recv_length < (int)((REQ_LEN_HDR + 554106163Sroberto (INFO_ITEMSIZE(inpkt->mbz_itemsize) * 555106163Sroberto INFO_NITEMS(inpkt->err_nitems)) 556132451Sroberto + sizeof(struct req_pkt_tail)))) { 557106163Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 558106163Sroberto } 559106163Sroberto tailinpkt = (struct req_pkt_tail *)((char *)&rbufp->recv_pkt + 560106163Sroberto rbufp->recv_length - sizeof(struct req_pkt_tail)); 561106163Sroberto 56254359Sroberto /* 56354359Sroberto * If this guy is restricted from doing this, don't let him 56454359Sroberto * If wrong key was used, or packet doesn't have mac, return. 56554359Sroberto */ 56654359Sroberto if (!INFO_IS_AUTH(inpkt->auth_seq) || info_auth_keyid == 0 567106163Sroberto || ntohl(tailinpkt->keyid) != info_auth_keyid) { 56854359Sroberto#ifdef DEBUG 56954359Sroberto if (debug > 4) 57054359Sroberto printf("failed auth %d info_auth_keyid %lu pkt keyid %lu\n", 571132451Sroberto INFO_IS_AUTH(inpkt->auth_seq), 572132451Sroberto (u_long)info_auth_keyid, 573132451Sroberto (u_long)ntohl(tailinpkt->keyid)); 574132451Sroberto msyslog(LOG_DEBUG, 575132451Sroberto "process_private: failed auth %d info_auth_keyid %lu pkt keyid %lu\n", 576132451Sroberto INFO_IS_AUTH(inpkt->auth_seq), 577132451Sroberto (u_long)info_auth_keyid, 578132451Sroberto (u_long)ntohl(tailinpkt->keyid)); 57954359Sroberto#endif 58054359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 58154359Sroberto return; 58254359Sroberto } 58354359Sroberto if (rbufp->recv_length > REQ_LEN_MAC) { 58454359Sroberto#ifdef DEBUG 58554359Sroberto if (debug > 4) 58654359Sroberto printf("bad pkt length %d\n", 58754359Sroberto rbufp->recv_length); 58854359Sroberto#endif 589132451Sroberto msyslog(LOG_ERR, "process_private: bad pkt length %d", 590132451Sroberto rbufp->recv_length); 59154359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 59254359Sroberto return; 59354359Sroberto } 59454359Sroberto if (!mod_okay || !authhavekey(info_auth_keyid)) { 59554359Sroberto#ifdef DEBUG 59654359Sroberto if (debug > 4) 59754359Sroberto printf("failed auth mod_okay %d\n", mod_okay); 598132451Sroberto msyslog(LOG_DEBUG, 599132451Sroberto "process_private: failed auth mod_okay %d\n", 600132451Sroberto mod_okay); 60154359Sroberto#endif 60254359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 60354359Sroberto return; 60454359Sroberto } 60554359Sroberto 60654359Sroberto /* 60754359Sroberto * calculate absolute time difference between xmit time stamp 60854359Sroberto * and receive time stamp. If too large, too bad. 60954359Sroberto */ 610106163Sroberto NTOHL_FP(&tailinpkt->tstamp, &ftmp); 61154359Sroberto L_SUB(&ftmp, &rbufp->recv_time); 61254359Sroberto LFPTOD(&ftmp, dtemp); 61354359Sroberto if (fabs(dtemp) >= INFO_TS_MAXSKEW) { 61454359Sroberto /* 61554359Sroberto * He's a loser. Tell him. 61654359Sroberto */ 617132451Sroberto#ifdef DEBUG 618132451Sroberto if (debug > 4) 619132451Sroberto printf("xmit/rcv timestamp delta > INFO_TS_MAXSKEW\n"); 620132451Sroberto#endif 62154359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 62254359Sroberto return; 62354359Sroberto } 62454359Sroberto 62554359Sroberto /* 62654359Sroberto * So far so good. See if decryption works out okay. 62754359Sroberto */ 62854359Sroberto if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt, 629106163Sroberto rbufp->recv_length - sizeof(struct req_pkt_tail) + 630106163Sroberto REQ_LEN_HDR, sizeof(struct req_pkt_tail) - REQ_LEN_HDR)) { 631132451Sroberto#ifdef DEBUG 632132451Sroberto if (debug > 4) 633132451Sroberto printf("authdecrypt failed\n"); 634132451Sroberto#endif 63554359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); 63654359Sroberto return; 63754359Sroberto } 63854359Sroberto } 63954359Sroberto 64054359Sroberto#ifdef DEBUG 64154359Sroberto if (debug > 3) 64254359Sroberto printf("process_private: all okay, into handler\n"); 64354359Sroberto#endif 64454359Sroberto 64554359Sroberto /* 64654359Sroberto * Packet is okay. Call the handler to send him data. 64754359Sroberto */ 64854359Sroberto (proc->handler)(srcadr, inter, inpkt); 64954359Sroberto} 65054359Sroberto 65154359Sroberto 65254359Sroberto/* 65354359Sroberto * peer_list - send a list of the peers 65454359Sroberto */ 65554359Srobertostatic void 65654359Srobertopeer_list( 657132451Sroberto struct sockaddr_storage *srcadr, 65854359Sroberto struct interface *inter, 65954359Sroberto struct req_pkt *inpkt 66054359Sroberto ) 66154359Sroberto{ 66254359Sroberto register struct info_peer_list *ip; 66354359Sroberto register struct peer *pp; 66454359Sroberto register int i; 665132451Sroberto register int skip = 0; 66654359Sroberto 66754359Sroberto ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt, 668132451Sroberto v6sizeof(struct info_peer_list)); 669182007Sroberto for (i = 0; i < NTP_HASH_SIZE && ip != 0; i++) { 67054359Sroberto pp = peer_hash[i]; 67154359Sroberto while (pp != 0 && ip != 0) { 672132451Sroberto if (pp->srcadr.ss_family == AF_INET6) { 673132451Sroberto if (client_v6_capable) { 674132451Sroberto ip->addr6 = GET_INADDR6(pp->srcadr); 675132451Sroberto ip->v6_flag = 1; 676132451Sroberto skip = 0; 677132451Sroberto } else { 678132451Sroberto skip = 1; 679132451Sroberto break; 680132451Sroberto } 681132451Sroberto } else { 682132451Sroberto ip->addr = GET_INADDR(pp->srcadr); 683132451Sroberto if (client_v6_capable) 684132451Sroberto ip->v6_flag = 0; 685132451Sroberto skip = 0; 686132451Sroberto } 687132451Sroberto 688132451Sroberto if(!skip) { 689132451Sroberto ip->port = NSRCPORT(&pp->srcadr); 690132451Sroberto ip->hmode = pp->hmode; 691132451Sroberto ip->flags = 0; 692132451Sroberto if (pp->flags & FLAG_CONFIG) 693132451Sroberto ip->flags |= INFO_FLAG_CONFIG; 694132451Sroberto if (pp == sys_peer) 695132451Sroberto ip->flags |= INFO_FLAG_SYSPEER; 696132451Sroberto if (pp->status == CTL_PST_SEL_SYNCCAND) 697132451Sroberto ip->flags |= INFO_FLAG_SEL_CANDIDATE; 698132451Sroberto if (pp->status >= CTL_PST_SEL_SYSPEER) 699132451Sroberto ip->flags |= INFO_FLAG_SHORTLIST; 700132451Sroberto ip = (struct info_peer_list *)more_pkt(); 701132451Sroberto } 702132451Sroberto pp = pp->next; 70354359Sroberto } 70454359Sroberto } 70554359Sroberto flush_pkt(); 70654359Sroberto} 70754359Sroberto 70854359Sroberto 70954359Sroberto/* 71054359Sroberto * peer_list_sum - return extended peer list 71154359Sroberto */ 71254359Srobertostatic void 71354359Srobertopeer_list_sum( 714132451Sroberto struct sockaddr_storage *srcadr, 71554359Sroberto struct interface *inter, 71654359Sroberto struct req_pkt *inpkt 71754359Sroberto ) 71854359Sroberto{ 71954359Sroberto register struct info_peer_summary *ips; 72054359Sroberto register struct peer *pp; 72154359Sroberto register int i; 72254359Sroberto l_fp ltmp; 723132451Sroberto register int skip; 72454359Sroberto 72554359Sroberto#ifdef DEBUG 72654359Sroberto if (debug > 2) 72754359Sroberto printf("wants peer list summary\n"); 72854359Sroberto#endif 72954359Sroberto ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt, 730132451Sroberto v6sizeof(struct info_peer_summary)); 731182007Sroberto for (i = 0; i < NTP_HASH_SIZE && ips != 0; i++) { 73254359Sroberto pp = peer_hash[i]; 73354359Sroberto while (pp != 0 && ips != 0) { 73454359Sroberto#ifdef DEBUG 73554359Sroberto if (debug > 3) 73654359Sroberto printf("sum: got one\n"); 73754359Sroberto#endif 738132451Sroberto /* 739132451Sroberto * Be careful here not to return v6 peers when we 740132451Sroberto * want only v4. 741132451Sroberto */ 742132451Sroberto if (pp->srcadr.ss_family == AF_INET6) { 743132451Sroberto if (client_v6_capable) { 744132451Sroberto ips->srcadr6 = GET_INADDR6(pp->srcadr); 745132451Sroberto ips->v6_flag = 1; 746182007Sroberto if (pp->dstadr) 747182007Sroberto ips->dstadr6 = GET_INADDR6(pp->dstadr->sin); 748182007Sroberto else 749182007Sroberto memset(&ips->dstadr6, 0, sizeof(ips->dstadr6)); 750132451Sroberto skip = 0; 751132451Sroberto } else { 752132451Sroberto skip = 1; 753132451Sroberto break; 754132451Sroberto } 755132451Sroberto } else { 756132451Sroberto ips->srcadr = GET_INADDR(pp->srcadr); 757132451Sroberto if (client_v6_capable) 758132451Sroberto ips->v6_flag = 0; 759132451Sroberto/* XXX PDM This code is buggy. Need to replace with a straightforward assignment */ 760182007Sroberto 761182007Sroberto if (pp->dstadr) 762182007Sroberto ips->dstadr = (pp->processed) ? 763182007Sroberto pp->cast_flags == MDF_BCAST ? 764182007Sroberto GET_INADDR(pp->dstadr->bcast): 765182007Sroberto pp->cast_flags ? 766182007Sroberto GET_INADDR(pp->dstadr->sin) ? 767182007Sroberto GET_INADDR(pp->dstadr->sin): 768182007Sroberto GET_INADDR(pp->dstadr->bcast): 769182007Sroberto 1 : GET_INADDR(pp->dstadr->sin); 770182007Sroberto else 771182007Sroberto memset(&ips->dstadr, 0, sizeof(ips->dstadr)); 77254359Sroberto 773132451Sroberto skip = 0; 774132451Sroberto } 775182007Sroberto 776132451Sroberto if (!skip){ 777132451Sroberto ips->srcport = NSRCPORT(&pp->srcadr); 778132451Sroberto ips->stratum = pp->stratum; 779132451Sroberto ips->hpoll = pp->hpoll; 780132451Sroberto ips->ppoll = pp->ppoll; 781132451Sroberto ips->reach = pp->reach; 782132451Sroberto ips->flags = 0; 783132451Sroberto if (pp == sys_peer) 784132451Sroberto ips->flags |= INFO_FLAG_SYSPEER; 785132451Sroberto if (pp->flags & FLAG_CONFIG) 786132451Sroberto ips->flags |= INFO_FLAG_CONFIG; 787132451Sroberto if (pp->flags & FLAG_REFCLOCK) 788132451Sroberto ips->flags |= INFO_FLAG_REFCLOCK; 789132451Sroberto if (pp->flags & FLAG_AUTHENABLE) 790132451Sroberto ips->flags |= INFO_FLAG_AUTHENABLE; 791132451Sroberto if (pp->flags & FLAG_PREFER) 792132451Sroberto ips->flags |= INFO_FLAG_PREFER; 793132451Sroberto if (pp->flags & FLAG_BURST) 794132451Sroberto ips->flags |= INFO_FLAG_BURST; 795132451Sroberto if (pp->status == CTL_PST_SEL_SYNCCAND) 796132451Sroberto ips->flags |= INFO_FLAG_SEL_CANDIDATE; 797132451Sroberto if (pp->status >= CTL_PST_SEL_SYSPEER) 798132451Sroberto ips->flags |= INFO_FLAG_SHORTLIST; 799132451Sroberto ips->hmode = pp->hmode; 800132451Sroberto ips->delay = HTONS_FP(DTOFP(pp->delay)); 801132451Sroberto DTOLFP(pp->offset, <mp); 802132451Sroberto HTONL_FP(<mp, &ips->offset); 803182007Sroberto ips->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); 804132451Sroberto } 805132451Sroberto pp = pp->next; 80654359Sroberto ips = (struct info_peer_summary *)more_pkt(); 80754359Sroberto } 80854359Sroberto } 80954359Sroberto flush_pkt(); 81054359Sroberto} 81154359Sroberto 81254359Sroberto 81354359Sroberto/* 81454359Sroberto * peer_info - send information for one or more peers 81554359Sroberto */ 81654359Srobertostatic void 81754359Srobertopeer_info ( 818132451Sroberto struct sockaddr_storage *srcadr, 81954359Sroberto struct interface *inter, 82054359Sroberto struct req_pkt *inpkt 82154359Sroberto ) 82254359Sroberto{ 82354359Sroberto register struct info_peer_list *ipl; 82454359Sroberto register struct peer *pp; 82554359Sroberto register struct info_peer *ip; 82654359Sroberto register int items; 82754359Sroberto register int i, j; 828132451Sroberto struct sockaddr_storage addr; 82954359Sroberto extern struct peer *sys_peer; 83054359Sroberto l_fp ltmp; 83154359Sroberto 83254359Sroberto memset((char *)&addr, 0, sizeof addr); 83354359Sroberto items = INFO_NITEMS(inpkt->err_nitems); 83454359Sroberto ipl = (struct info_peer_list *) inpkt->data; 835132451Sroberto 83654359Sroberto ip = (struct info_peer *)prepare_pkt(srcadr, inter, inpkt, 837132451Sroberto v6sizeof(struct info_peer)); 83854359Sroberto while (items-- > 0 && ip != 0) { 839132451Sroberto memset((char *)&addr, 0, sizeof(addr)); 840132451Sroberto NSRCPORT(&addr) = ipl->port; 841132451Sroberto if (client_v6_capable && ipl->v6_flag != 0) { 842132451Sroberto addr.ss_family = AF_INET6; 843132451Sroberto GET_INADDR6(addr) = ipl->addr6; 844132451Sroberto } else { 845132451Sroberto addr.ss_family = AF_INET; 846132451Sroberto GET_INADDR(addr) = ipl->addr; 847132451Sroberto } 848132451Sroberto#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 849132451Sroberto addr.ss_len = SOCKLEN(&addr); 850132451Sroberto#endif 85154359Sroberto ipl++; 85254359Sroberto if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0) 85354359Sroberto continue; 854132451Sroberto if (pp->srcadr.ss_family == AF_INET6) { 855182007Sroberto if (pp->dstadr) 856182007Sroberto ip->dstadr6 = pp->cast_flags == MDF_BCAST ? 857182007Sroberto GET_INADDR6(pp->dstadr->bcast) : 858182007Sroberto GET_INADDR6(pp->dstadr->sin); 859182007Sroberto else 860182007Sroberto memset(&ip->dstadr6, 0, sizeof(ip->dstadr6)); 861182007Sroberto 862132451Sroberto ip->srcadr6 = GET_INADDR6(pp->srcadr); 863132451Sroberto ip->v6_flag = 1; 864132451Sroberto } else { 865132451Sroberto/* XXX PDM This code is buggy. Need to replace with a straightforward assignment */ 866182007Sroberto if (pp->dstadr) 867182007Sroberto ip->dstadr = (pp->processed) ? 868182007Sroberto pp->cast_flags == MDF_BCAST ? 869182007Sroberto GET_INADDR(pp->dstadr->bcast): 870182007Sroberto pp->cast_flags ? 871182007Sroberto GET_INADDR(pp->dstadr->sin) ? 872182007Sroberto GET_INADDR(pp->dstadr->sin): 873182007Sroberto GET_INADDR(pp->dstadr->bcast): 874182007Sroberto 2 : GET_INADDR(pp->dstadr->sin); 875182007Sroberto else 876182007Sroberto memset(&ip->dstadr, 0, sizeof(ip->dstadr)); 877132451Sroberto 878132451Sroberto ip->srcadr = GET_INADDR(pp->srcadr); 879132451Sroberto if (client_v6_capable) 880132451Sroberto ip->v6_flag = 0; 881132451Sroberto } 88254359Sroberto ip->srcport = NSRCPORT(&pp->srcadr); 88354359Sroberto ip->flags = 0; 88454359Sroberto if (pp == sys_peer) 88554359Sroberto ip->flags |= INFO_FLAG_SYSPEER; 88654359Sroberto if (pp->flags & FLAG_CONFIG) 88754359Sroberto ip->flags |= INFO_FLAG_CONFIG; 88854359Sroberto if (pp->flags & FLAG_REFCLOCK) 88954359Sroberto ip->flags |= INFO_FLAG_REFCLOCK; 89054359Sroberto if (pp->flags & FLAG_AUTHENABLE) 89154359Sroberto ip->flags |= INFO_FLAG_AUTHENABLE; 89254359Sroberto if (pp->flags & FLAG_PREFER) 89354359Sroberto ip->flags |= INFO_FLAG_PREFER; 89454359Sroberto if (pp->flags & FLAG_BURST) 89554359Sroberto ip->flags |= INFO_FLAG_BURST; 89654359Sroberto if (pp->status == CTL_PST_SEL_SYNCCAND) 89754359Sroberto ip->flags |= INFO_FLAG_SEL_CANDIDATE; 89854359Sroberto if (pp->status >= CTL_PST_SEL_SYSPEER) 89954359Sroberto ip->flags |= INFO_FLAG_SHORTLIST; 90054359Sroberto ip->leap = pp->leap; 90154359Sroberto ip->hmode = pp->hmode; 90254359Sroberto ip->keyid = pp->keyid; 90354359Sroberto ip->stratum = pp->stratum; 90454359Sroberto ip->ppoll = pp->ppoll; 90554359Sroberto ip->hpoll = pp->hpoll; 90654359Sroberto ip->precision = pp->precision; 90754359Sroberto ip->version = pp->version; 90854359Sroberto ip->reach = pp->reach; 909132451Sroberto ip->unreach = (u_char) pp->unreach; 91054359Sroberto ip->flash = (u_char)pp->flash; 911132451Sroberto ip->flash2 = (u_short) pp->flash; 91254359Sroberto ip->estbdelay = HTONS_FP(DTOFP(pp->estbdelay)); 91354359Sroberto ip->ttl = pp->ttl; 91454359Sroberto ip->associd = htons(pp->associd); 91554359Sroberto ip->rootdelay = HTONS_FP(DTOUFP(pp->rootdelay)); 91654359Sroberto ip->rootdispersion = HTONS_FP(DTOUFP(pp->rootdispersion)); 91754359Sroberto ip->refid = pp->refid; 91854359Sroberto HTONL_FP(&pp->reftime, &ip->reftime); 91954359Sroberto HTONL_FP(&pp->org, &ip->org); 92054359Sroberto HTONL_FP(&pp->rec, &ip->rec); 92154359Sroberto HTONL_FP(&pp->xmt, &ip->xmt); 92254359Sroberto j = pp->filter_nextpt - 1; 92354359Sroberto for (i = 0; i < NTP_SHIFT; i++, j--) { 92454359Sroberto if (j < 0) 92554359Sroberto j = NTP_SHIFT-1; 92654359Sroberto ip->filtdelay[i] = HTONS_FP(DTOFP(pp->filter_delay[j])); 92754359Sroberto DTOLFP(pp->filter_offset[j], <mp); 92854359Sroberto HTONL_FP(<mp, &ip->filtoffset[i]); 929132451Sroberto ip->order[i] = (u_char)((pp->filter_nextpt+NTP_SHIFT-1) 930132451Sroberto - pp->filter_order[i]); 93154359Sroberto if (ip->order[i] >= NTP_SHIFT) 93254359Sroberto ip->order[i] -= NTP_SHIFT; 93354359Sroberto } 93454359Sroberto DTOLFP(pp->offset, <mp); 93554359Sroberto HTONL_FP(<mp, &ip->offset); 93654359Sroberto ip->delay = HTONS_FP(DTOFP(pp->delay)); 93754359Sroberto ip->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp))); 93882498Sroberto ip->selectdisp = HTONS_FP(DTOUFP(SQRT(pp->jitter))); 93954359Sroberto ip = (struct info_peer *)more_pkt(); 94054359Sroberto } 94154359Sroberto flush_pkt(); 94254359Sroberto} 94354359Sroberto 94454359Sroberto 94554359Sroberto/* 94654359Sroberto * peer_stats - send statistics for one or more peers 94754359Sroberto */ 94854359Srobertostatic void 94954359Srobertopeer_stats ( 950132451Sroberto struct sockaddr_storage *srcadr, 95154359Sroberto struct interface *inter, 95254359Sroberto struct req_pkt *inpkt 95354359Sroberto ) 95454359Sroberto{ 95554359Sroberto register struct info_peer_list *ipl; 95654359Sroberto register struct peer *pp; 95754359Sroberto register struct info_peer_stats *ip; 95854359Sroberto register int items; 959132451Sroberto struct sockaddr_storage addr; 96054359Sroberto extern struct peer *sys_peer; 96154359Sroberto 962182007Sroberto#ifdef DEBUG 963182007Sroberto if (debug) 964182007Sroberto printf("peer_stats: called\n"); 965182007Sroberto#endif 96654359Sroberto items = INFO_NITEMS(inpkt->err_nitems); 96754359Sroberto ipl = (struct info_peer_list *) inpkt->data; 96854359Sroberto ip = (struct info_peer_stats *)prepare_pkt(srcadr, inter, inpkt, 969132451Sroberto v6sizeof(struct info_peer_stats)); 97054359Sroberto while (items-- > 0 && ip != 0) { 971132451Sroberto memset((char *)&addr, 0, sizeof(addr)); 972132451Sroberto NSRCPORT(&addr) = ipl->port; 973132451Sroberto if (client_v6_capable && ipl->v6_flag) { 974132451Sroberto addr.ss_family = AF_INET6; 975132451Sroberto GET_INADDR6(addr) = ipl->addr6; 976132451Sroberto } else { 977132451Sroberto addr.ss_family = AF_INET; 978132451Sroberto GET_INADDR(addr) = ipl->addr; 979132451Sroberto } 980132451Sroberto#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 981132451Sroberto addr.ss_len = SOCKLEN(&addr); 982132451Sroberto#endif 983182007Sroberto#ifdef DEBUG 984182007Sroberto if (debug) 985182007Sroberto printf("peer_stats: looking for %s, %d, %d\n", stoa(&addr), 986132451Sroberto ipl->port, ((struct sockaddr_in6 *)&addr)->sin6_port); 987182007Sroberto#endif 988132451Sroberto ipl = (struct info_peer_list *)((char *)ipl + 989132451Sroberto INFO_ITEMSIZE(inpkt->mbz_itemsize)); 990132451Sroberto 99154359Sroberto if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0) 99254359Sroberto continue; 993182007Sroberto#ifdef DEBUG 994182007Sroberto if (debug) 995182007Sroberto printf("peer_stats: found %s\n", stoa(&addr)); 996182007Sroberto#endif 997132451Sroberto if (pp->srcadr.ss_family == AF_INET) { 998182007Sroberto if (pp->dstadr) 999182007Sroberto ip->dstadr = (pp->processed) ? 1000182007Sroberto pp->cast_flags == MDF_BCAST ? 1001182007Sroberto GET_INADDR(pp->dstadr->bcast): 1002182007Sroberto pp->cast_flags ? 1003182007Sroberto GET_INADDR(pp->dstadr->sin) ? 1004182007Sroberto GET_INADDR(pp->dstadr->sin): 1005182007Sroberto GET_INADDR(pp->dstadr->bcast): 1006182007Sroberto 3 : 7; 1007182007Sroberto else 1008182007Sroberto memset(&ip->dstadr, 0, sizeof(ip->dstadr)); 1009182007Sroberto 1010132451Sroberto ip->srcadr = GET_INADDR(pp->srcadr); 1011132451Sroberto if (client_v6_capable) 1012132451Sroberto ip->v6_flag = 0; 1013132451Sroberto } else { 1014182007Sroberto if (pp->dstadr) 1015182007Sroberto ip->dstadr6 = pp->cast_flags == MDF_BCAST ? 1016182007Sroberto GET_INADDR6(pp->dstadr->bcast): 1017182007Sroberto GET_INADDR6(pp->dstadr->sin); 1018182007Sroberto else 1019182007Sroberto memset(&ip->dstadr6, 0, sizeof(ip->dstadr6)); 1020182007Sroberto 1021132451Sroberto ip->srcadr6 = GET_INADDR6(pp->srcadr); 1022132451Sroberto ip->v6_flag = 1; 1023132451Sroberto } 102454359Sroberto ip->srcport = NSRCPORT(&pp->srcadr); 102554359Sroberto ip->flags = 0; 102654359Sroberto if (pp == sys_peer) 102754359Sroberto ip->flags |= INFO_FLAG_SYSPEER; 102854359Sroberto if (pp->flags & FLAG_CONFIG) 102954359Sroberto ip->flags |= INFO_FLAG_CONFIG; 103054359Sroberto if (pp->flags & FLAG_REFCLOCK) 103154359Sroberto ip->flags |= INFO_FLAG_REFCLOCK; 103254359Sroberto if (pp->flags & FLAG_AUTHENABLE) 103354359Sroberto ip->flags |= INFO_FLAG_AUTHENABLE; 103454359Sroberto if (pp->flags & FLAG_PREFER) 103554359Sroberto ip->flags |= INFO_FLAG_PREFER; 103654359Sroberto if (pp->flags & FLAG_BURST) 103754359Sroberto ip->flags |= INFO_FLAG_BURST; 1038182007Sroberto if (pp->flags & FLAG_IBURST) 1039182007Sroberto ip->flags |= INFO_FLAG_IBURST; 104054359Sroberto if (pp->status == CTL_PST_SEL_SYNCCAND) 104154359Sroberto ip->flags |= INFO_FLAG_SEL_CANDIDATE; 104254359Sroberto if (pp->status >= CTL_PST_SEL_SYSPEER) 104354359Sroberto ip->flags |= INFO_FLAG_SHORTLIST; 1044182007Sroberto ip->flags = htons(ip->flags); 104554359Sroberto ip->timereceived = htonl((u_int32)(current_time - pp->timereceived)); 104654359Sroberto ip->timetosend = htonl(pp->nextdate - current_time); 104754359Sroberto ip->timereachable = htonl((u_int32)(current_time - pp->timereachable)); 104854359Sroberto ip->sent = htonl((u_int32)(pp->sent)); 104954359Sroberto ip->processed = htonl((u_int32)(pp->processed)); 105054359Sroberto ip->badauth = htonl((u_int32)(pp->badauth)); 105154359Sroberto ip->bogusorg = htonl((u_int32)(pp->bogusorg)); 105254359Sroberto ip->oldpkt = htonl((u_int32)(pp->oldpkt)); 105354359Sroberto ip->seldisp = htonl((u_int32)(pp->seldisptoolarge)); 105454359Sroberto ip->selbroken = htonl((u_int32)(pp->selbroken)); 105554359Sroberto ip->candidate = pp->status; 105654359Sroberto ip = (struct info_peer_stats *)more_pkt(); 105754359Sroberto } 105854359Sroberto flush_pkt(); 105954359Sroberto} 106054359Sroberto 106154359Sroberto 106254359Sroberto/* 106354359Sroberto * sys_info - return system info 106454359Sroberto */ 106554359Srobertostatic void 106654359Srobertosys_info( 1067132451Sroberto struct sockaddr_storage *srcadr, 106854359Sroberto struct interface *inter, 106954359Sroberto struct req_pkt *inpkt 107054359Sroberto ) 107154359Sroberto{ 107254359Sroberto register struct info_sys *is; 107354359Sroberto 107454359Sroberto is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt, 1075132451Sroberto v6sizeof(struct info_sys)); 107654359Sroberto 107754359Sroberto if (sys_peer != 0) { 1078132451Sroberto if (sys_peer->srcadr.ss_family == AF_INET) { 1079132451Sroberto is->peer = GET_INADDR(sys_peer->srcadr); 1080132451Sroberto if (client_v6_capable) 1081132451Sroberto is->v6_flag = 0; 1082132451Sroberto } else if (client_v6_capable) { 1083132451Sroberto is->peer6 = GET_INADDR6(sys_peer->srcadr); 1084132451Sroberto is->v6_flag = 1; 1085132451Sroberto } 108654359Sroberto is->peer_mode = sys_peer->hmode; 108754359Sroberto } else { 108854359Sroberto is->peer = 0; 1089132451Sroberto if (client_v6_capable) { 1090132451Sroberto is->v6_flag = 0; 1091132451Sroberto } 109254359Sroberto is->peer_mode = 0; 109354359Sroberto } 1094132451Sroberto 109554359Sroberto is->leap = sys_leap; 109654359Sroberto is->stratum = sys_stratum; 109754359Sroberto is->precision = sys_precision; 109854359Sroberto is->rootdelay = htonl(DTOFP(sys_rootdelay)); 109954359Sroberto is->rootdispersion = htonl(DTOUFP(sys_rootdispersion)); 110082498Sroberto is->frequency = htonl(DTOFP(sys_jitter)); 1101182007Sroberto is->stability = htonl(DTOUFP(clock_stability)); 110254359Sroberto is->refid = sys_refid; 110354359Sroberto HTONL_FP(&sys_reftime, &is->reftime); 110454359Sroberto 110554359Sroberto is->poll = sys_poll; 110654359Sroberto 110754359Sroberto is->flags = 0; 1108106163Sroberto if (sys_authenticate) 1109106163Sroberto is->flags |= INFO_FLAG_AUTHENTICATE; 111054359Sroberto if (sys_bclient) 1111106163Sroberto is->flags |= INFO_FLAG_BCLIENT; 1112106163Sroberto#ifdef REFCLOCK 1113106163Sroberto if (cal_enable) 1114106163Sroberto is->flags |= INFO_FLAG_CAL; 1115106163Sroberto#endif /* REFCLOCK */ 111654359Sroberto if (kern_enable) 1117106163Sroberto is->flags |= INFO_FLAG_KERNEL; 1118106163Sroberto if (mon_enabled != MON_OFF) 1119106163Sroberto is->flags |= INFO_FLAG_MONITOR; 112054359Sroberto if (ntp_enable) 1121106163Sroberto is->flags |= INFO_FLAG_NTP; 1122106163Sroberto if (pps_enable) 1123106163Sroberto is->flags |= INFO_FLAG_PPS_SYNC; 112454359Sroberto if (stats_control) 1125106163Sroberto is->flags |= INFO_FLAG_FILEGEN; 112654359Sroberto is->bdelay = HTONS_FP(DTOFP(sys_bdelay)); 112754359Sroberto HTONL_UF(sys_authdelay.l_f, &is->authdelay); 112854359Sroberto 112954359Sroberto (void) more_pkt(); 113054359Sroberto flush_pkt(); 113154359Sroberto} 113254359Sroberto 113354359Sroberto 113454359Sroberto/* 113554359Sroberto * sys_stats - return system statistics 113654359Sroberto */ 113754359Srobertostatic void 113854359Srobertosys_stats( 1139132451Sroberto struct sockaddr_storage *srcadr, 114054359Sroberto struct interface *inter, 114154359Sroberto struct req_pkt *inpkt 114254359Sroberto ) 114354359Sroberto{ 114454359Sroberto register struct info_sys_stats *ss; 114554359Sroberto 114654359Sroberto /* 114754359Sroberto * Importations from the protocol module 114854359Sroberto */ 114954359Sroberto ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt, 1150132451Sroberto sizeof(struct info_sys_stats)); 115154359Sroberto ss->timeup = htonl((u_int32)current_time); 115254359Sroberto ss->timereset = htonl((u_int32)(current_time - sys_stattime)); 1153132451Sroberto ss->denied = htonl((u_int32)sys_restricted); 115454359Sroberto ss->oldversionpkt = htonl((u_int32)sys_oldversionpkt); 115554359Sroberto ss->newversionpkt = htonl((u_int32)sys_newversionpkt); 115654359Sroberto ss->unknownversion = htonl((u_int32)sys_unknownversion); 115754359Sroberto ss->badlength = htonl((u_int32)sys_badlength); 115854359Sroberto ss->processed = htonl((u_int32)sys_processed); 115954359Sroberto ss->badauth = htonl((u_int32)sys_badauth); 116054359Sroberto ss->limitrejected = htonl((u_int32)sys_limitrejected); 1161132451Sroberto ss->received = htonl((u_int32)sys_received); 116254359Sroberto (void) more_pkt(); 116354359Sroberto flush_pkt(); 116454359Sroberto} 116554359Sroberto 116654359Sroberto 116754359Sroberto/* 116854359Sroberto * mem_stats - return memory statistics 116954359Sroberto */ 117054359Srobertostatic void 117154359Srobertomem_stats( 1172132451Sroberto struct sockaddr_storage *srcadr, 117354359Sroberto struct interface *inter, 117454359Sroberto struct req_pkt *inpkt 117554359Sroberto ) 117654359Sroberto{ 117754359Sroberto register struct info_mem_stats *ms; 117854359Sroberto register int i; 117954359Sroberto 118054359Sroberto /* 118154359Sroberto * Importations from the peer module 118254359Sroberto */ 1183182007Sroberto extern int peer_hash_count[NTP_HASH_SIZE]; 118454359Sroberto extern int peer_free_count; 118554359Sroberto extern u_long peer_timereset; 118654359Sroberto extern u_long findpeer_calls; 118754359Sroberto extern u_long peer_allocations; 118854359Sroberto extern u_long peer_demobilizations; 118954359Sroberto extern int total_peer_structs; 119054359Sroberto 119154359Sroberto ms = (struct info_mem_stats *)prepare_pkt(srcadr, inter, inpkt, 119254359Sroberto sizeof(struct info_mem_stats)); 119354359Sroberto 119454359Sroberto ms->timereset = htonl((u_int32)(current_time - peer_timereset)); 119554359Sroberto ms->totalpeermem = htons((u_short)total_peer_structs); 119654359Sroberto ms->freepeermem = htons((u_short)peer_free_count); 119754359Sroberto ms->findpeer_calls = htonl((u_int32)findpeer_calls); 119854359Sroberto ms->allocations = htonl((u_int32)peer_allocations); 119954359Sroberto ms->demobilizations = htonl((u_int32)peer_demobilizations); 120054359Sroberto 1201182007Sroberto for (i = 0; i < NTP_HASH_SIZE; i++) { 120254359Sroberto if (peer_hash_count[i] > 255) 120354359Sroberto ms->hashcount[i] = 255; 120454359Sroberto else 120554359Sroberto ms->hashcount[i] = (u_char)peer_hash_count[i]; 120654359Sroberto } 120754359Sroberto 120854359Sroberto (void) more_pkt(); 120954359Sroberto flush_pkt(); 121054359Sroberto} 121154359Sroberto 121254359Sroberto 121354359Sroberto/* 121454359Sroberto * io_stats - return io statistics 121554359Sroberto */ 121654359Srobertostatic void 121754359Srobertoio_stats( 1218132451Sroberto struct sockaddr_storage *srcadr, 121954359Sroberto struct interface *inter, 122054359Sroberto struct req_pkt *inpkt 122154359Sroberto ) 122254359Sroberto{ 122354359Sroberto register struct info_io_stats *io; 122454359Sroberto 122554359Sroberto /* 122654359Sroberto * Importations from the io module 122754359Sroberto */ 122854359Sroberto extern u_long io_timereset; 122954359Sroberto 123054359Sroberto io = (struct info_io_stats *)prepare_pkt(srcadr, inter, inpkt, 123154359Sroberto sizeof(struct info_io_stats)); 123254359Sroberto 123354359Sroberto io->timereset = htonl((u_int32)(current_time - io_timereset)); 123454359Sroberto io->totalrecvbufs = htons((u_short) total_recvbuffs()); 123554359Sroberto io->freerecvbufs = htons((u_short) free_recvbuffs()); 123654359Sroberto io->fullrecvbufs = htons((u_short) full_recvbuffs()); 123754359Sroberto io->lowwater = htons((u_short) lowater_additions()); 123854359Sroberto io->dropped = htonl((u_int32)packets_dropped); 123954359Sroberto io->ignored = htonl((u_int32)packets_ignored); 124054359Sroberto io->received = htonl((u_int32)packets_received); 124154359Sroberto io->sent = htonl((u_int32)packets_sent); 124254359Sroberto io->notsent = htonl((u_int32)packets_notsent); 124354359Sroberto io->interrupts = htonl((u_int32)handler_calls); 124454359Sroberto io->int_received = htonl((u_int32)handler_pkts); 124554359Sroberto 124654359Sroberto (void) more_pkt(); 124754359Sroberto flush_pkt(); 124854359Sroberto} 124954359Sroberto 125054359Sroberto 125154359Sroberto/* 125254359Sroberto * timer_stats - return timer statistics 125354359Sroberto */ 125454359Srobertostatic void 125554359Srobertotimer_stats( 1256132451Sroberto struct sockaddr_storage *srcadr, 125754359Sroberto struct interface *inter, 125854359Sroberto struct req_pkt *inpkt 125954359Sroberto ) 126054359Sroberto{ 126154359Sroberto register struct info_timer_stats *ts; 126254359Sroberto 126354359Sroberto /* 126454359Sroberto * Importations from the timer module 126554359Sroberto */ 126654359Sroberto extern u_long timer_timereset; 126754359Sroberto extern u_long timer_overflows; 126854359Sroberto extern u_long timer_xmtcalls; 126954359Sroberto 127054359Sroberto ts = (struct info_timer_stats *)prepare_pkt(srcadr, inter, inpkt, 127154359Sroberto sizeof(struct info_timer_stats)); 127254359Sroberto 127354359Sroberto ts->timereset = htonl((u_int32)(current_time - timer_timereset)); 127454359Sroberto ts->alarms = htonl((u_int32)alarm_overflow); 127554359Sroberto ts->overflows = htonl((u_int32)timer_overflows); 127654359Sroberto ts->xmtcalls = htonl((u_int32)timer_xmtcalls); 127754359Sroberto 127854359Sroberto (void) more_pkt(); 127954359Sroberto flush_pkt(); 128054359Sroberto} 128154359Sroberto 128254359Sroberto 128354359Sroberto/* 128454359Sroberto * loop_info - return the current state of the loop filter 128554359Sroberto */ 128654359Srobertostatic void 128754359Srobertoloop_info( 1288132451Sroberto struct sockaddr_storage *srcadr, 128954359Sroberto struct interface *inter, 129054359Sroberto struct req_pkt *inpkt 129154359Sroberto ) 129254359Sroberto{ 129354359Sroberto register struct info_loop *li; 129454359Sroberto l_fp ltmp; 129554359Sroberto 129654359Sroberto /* 129754359Sroberto * Importations from the loop filter module 129854359Sroberto */ 129954359Sroberto extern double last_offset; 130054359Sroberto extern double drift_comp; 130154359Sroberto extern int tc_counter; 1302182007Sroberto extern u_long sys_clocktime; 130354359Sroberto 130454359Sroberto li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt, 130554359Sroberto sizeof(struct info_loop)); 130654359Sroberto 130754359Sroberto DTOLFP(last_offset, <mp); 130854359Sroberto HTONL_FP(<mp, &li->last_offset); 130954359Sroberto DTOLFP(drift_comp * 1e6, <mp); 131054359Sroberto HTONL_FP(<mp, &li->drift_comp); 131154359Sroberto li->compliance = htonl((u_int32)(tc_counter)); 1312182007Sroberto li->watchdog_timer = htonl((u_int32)(current_time - sys_clocktime)); 131354359Sroberto 131454359Sroberto (void) more_pkt(); 131554359Sroberto flush_pkt(); 131654359Sroberto} 131754359Sroberto 131854359Sroberto 131954359Sroberto/* 132054359Sroberto * do_conf - add a peer to the configuration list 132154359Sroberto */ 132254359Srobertostatic void 132354359Srobertodo_conf( 1324132451Sroberto struct sockaddr_storage *srcadr, 132554359Sroberto struct interface *inter, 132654359Sroberto struct req_pkt *inpkt 132754359Sroberto ) 132854359Sroberto{ 1329200576Sroberto static u_long soonest_ifrescan_time = 0; 1330132451Sroberto int items; 133182498Sroberto u_int fl; 1332132451Sroberto struct conf_peer *cp; 1333132451Sroberto struct conf_peer temp_cp; 1334132451Sroberto struct sockaddr_storage peeraddr; 1335132451Sroberto struct sockaddr_in tmp_clock; 133654359Sroberto 133754359Sroberto /* 133854359Sroberto * Do a check of everything to see that it looks 133954359Sroberto * okay. If not, complain about it. Note we are 134054359Sroberto * very picky here. 134154359Sroberto */ 134254359Sroberto items = INFO_NITEMS(inpkt->err_nitems); 134354359Sroberto cp = (struct conf_peer *)inpkt->data; 1344132451Sroberto memset(&temp_cp, 0, sizeof(struct conf_peer)); 1345132451Sroberto memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize)); 134654359Sroberto fl = 0; 134754359Sroberto while (items-- > 0 && !fl) { 1348132451Sroberto if (((temp_cp.version) > NTP_VERSION) 1349132451Sroberto || ((temp_cp.version) < NTP_OLDVERSION)) 135054359Sroberto fl = 1; 1351132451Sroberto if (temp_cp.hmode != MODE_ACTIVE 1352132451Sroberto && temp_cp.hmode != MODE_CLIENT 1353132451Sroberto && temp_cp.hmode != MODE_BROADCAST) 135454359Sroberto fl = 1; 1355132451Sroberto if (temp_cp.flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER 1356182007Sroberto | CONF_FLAG_BURST | CONF_FLAG_IBURST | CONF_FLAG_SKEY)) 135754359Sroberto fl = 1; 1358132451Sroberto cp = (struct conf_peer *) 1359132451Sroberto ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize)); 136054359Sroberto } 136154359Sroberto 136254359Sroberto if (fl) { 136354359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 136454359Sroberto return; 136554359Sroberto } 136654359Sroberto 136754359Sroberto /* 136854359Sroberto * Looks okay, try it out 136954359Sroberto */ 137054359Sroberto items = INFO_NITEMS(inpkt->err_nitems); 1371132451Sroberto cp = (struct conf_peer *)inpkt->data; 137254359Sroberto 1373132451Sroberto while (items-- > 0) { 1374132451Sroberto memset(&temp_cp, 0, sizeof(struct conf_peer)); 1375132451Sroberto memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize)); 1376132451Sroberto memset((char *)&peeraddr, 0, sizeof(struct sockaddr_storage)); 1377132451Sroberto 1378132451Sroberto fl = 0; 1379132451Sroberto if (temp_cp.flags & CONF_FLAG_AUTHENABLE) 1380182007Sroberto fl |= FLAG_AUTHENABLE; 1381132451Sroberto if (temp_cp.flags & CONF_FLAG_PREFER) 1382182007Sroberto fl |= FLAG_PREFER; 1383132451Sroberto if (temp_cp.flags & CONF_FLAG_BURST) 1384132451Sroberto fl |= FLAG_BURST; 1385182007Sroberto if (temp_cp.flags & CONF_FLAG_IBURST) 1386182007Sroberto fl |= FLAG_IBURST; 1387132451Sroberto if (temp_cp.flags & CONF_FLAG_SKEY) 1388132451Sroberto fl |= FLAG_SKEY; 1389182007Sroberto 1390132451Sroberto if (client_v6_capable && temp_cp.v6_flag != 0) { 1391132451Sroberto peeraddr.ss_family = AF_INET6; 1392132451Sroberto GET_INADDR6(peeraddr) = temp_cp.peeraddr6; 1393132451Sroberto } else { 1394132451Sroberto peeraddr.ss_family = AF_INET; 1395132451Sroberto GET_INADDR(peeraddr) = temp_cp.peeraddr; 1396132451Sroberto /* 1397132451Sroberto * Make sure the address is valid 1398132451Sroberto */ 1399132451Sroberto tmp_clock = *CAST_V4(peeraddr); 1400132451Sroberto if ( 140154359Sroberto#ifdef REFCLOCK 1402132451Sroberto !ISREFCLOCKADR(&tmp_clock) && 140354359Sroberto#endif 1404132451Sroberto ISBADADR(&tmp_clock)) { 1405132451Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 1406132451Sroberto return; 1407132451Sroberto } 1408132451Sroberto 1409132451Sroberto } 1410132451Sroberto NSRCPORT(&peeraddr) = htons(NTP_PORT); 1411132451Sroberto#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 1412132451Sroberto peeraddr.ss_len = SOCKLEN(&peeraddr); 141382498Sroberto#endif 141454359Sroberto 141554359Sroberto /* XXX W2DO? minpoll/maxpoll arguments ??? */ 1416132451Sroberto if (peer_config(&peeraddr, (struct interface *)0, 1417132451Sroberto temp_cp.hmode, temp_cp.version, temp_cp.minpoll, 1418132451Sroberto temp_cp.maxpoll, fl, temp_cp.ttl, temp_cp.keyid, 1419132451Sroberto NULL) == 0) { 142054359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 142154359Sroberto return; 142254359Sroberto } 1423200576Sroberto 1424200576Sroberto /* 1425200576Sroberto * ntp_intres.c uses REQ_CONFIG/doconf() to add each 1426200576Sroberto * server after its name is resolved. If we have been 1427200576Sroberto * disconnected from the network, it may notice the 1428200576Sroberto * network has returned and add the first server while 1429200576Sroberto * the relevant interface is still disabled, awaiting 1430200576Sroberto * the next interface rescan. To get things moving 1431200576Sroberto * more quickly, trigger an interface scan now, except 1432200576Sroberto * if we have done so in the last half minute. 1433200576Sroberto */ 1434200576Sroberto if (soonest_ifrescan_time < current_time) { 1435200576Sroberto soonest_ifrescan_time = current_time + 30; 1436200576Sroberto timer_interfacetimeout(current_time); 1437200576Sroberto DPRINTF(1, ("do_conf triggering interface rescan\n")); 1438200576Sroberto } 1439200576Sroberto 1440132451Sroberto cp = (struct conf_peer *) 1441132451Sroberto ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize)); 144254359Sroberto } 144354359Sroberto 144454359Sroberto req_ack(srcadr, inter, inpkt, INFO_OKAY); 144554359Sroberto} 144654359Sroberto 1447132451Sroberto#if 0 1448132451Sroberto/* XXX */ 144954359Sroberto/* 145082498Sroberto * dns_a - Snarf DNS info for an association ID 145182498Sroberto */ 145282498Srobertostatic void 145382498Srobertodns_a( 1454132451Sroberto struct sockaddr_storage *srcadr, 145582498Sroberto struct interface *inter, 145682498Sroberto struct req_pkt *inpkt 145782498Sroberto ) 145882498Sroberto{ 145982498Sroberto register struct info_dns_assoc *dp; 146082498Sroberto register int items; 146182498Sroberto struct sockaddr_in peeraddr; 146282498Sroberto 146382498Sroberto /* 146482498Sroberto * Do a check of everything to see that it looks 146582498Sroberto * okay. If not, complain about it. Note we are 146682498Sroberto * very picky here. 146782498Sroberto */ 146882498Sroberto items = INFO_NITEMS(inpkt->err_nitems); 146982498Sroberto dp = (struct info_dns_assoc *)inpkt->data; 147082498Sroberto 147182498Sroberto /* 147282498Sroberto * Looks okay, try it out 147382498Sroberto */ 147482498Sroberto items = INFO_NITEMS(inpkt->err_nitems); 147582498Sroberto dp = (struct info_dns_assoc *)inpkt->data; 147682498Sroberto memset((char *)&peeraddr, 0, sizeof(struct sockaddr_in)); 147782498Sroberto peeraddr.sin_family = AF_INET; 147882498Sroberto peeraddr.sin_port = htons(NTP_PORT); 147982498Sroberto 148082498Sroberto /* 148182498Sroberto * Make sure the address is valid 148282498Sroberto */ 148382498Sroberto if ( 148482498Sroberto#ifdef REFCLOCK 148582498Sroberto !ISREFCLOCKADR(&peeraddr) && 148682498Sroberto#endif 148782498Sroberto ISBADADR(&peeraddr)) { 148882498Sroberto#ifdef REFCLOCK 148982498Sroberto msyslog(LOG_ERR, "dns_a: !ISREFCLOCK && ISBADADR"); 149082498Sroberto#else 149182498Sroberto msyslog(LOG_ERR, "dns_a: ISBADADR"); 149282498Sroberto#endif 149382498Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 149482498Sroberto return; 149582498Sroberto } 149682498Sroberto 149782498Sroberto while (items-- > 0) { 149882498Sroberto associd_t associd; 149982498Sroberto size_t hnl; 150082498Sroberto struct peer *peer; 150182498Sroberto int bogon = 0; 150282498Sroberto 150382498Sroberto associd = dp->associd; 150482498Sroberto peer = findpeerbyassoc(associd); 150582498Sroberto if (peer == 0 || peer->flags & FLAG_REFCLOCK) { 150682498Sroberto msyslog(LOG_ERR, "dns_a: %s", 150782498Sroberto (peer == 0) 150882498Sroberto ? "peer == 0" 150982498Sroberto : "peer->flags & FLAG_REFCLOCK"); 151082498Sroberto ++bogon; 151182498Sroberto } 151282498Sroberto peeraddr.sin_addr.s_addr = dp->peeraddr; 151382498Sroberto for (hnl = 0; dp->hostname[hnl] && hnl < sizeof dp->hostname; ++hnl) ; 151482498Sroberto if (hnl >= sizeof dp->hostname) { 151582498Sroberto msyslog(LOG_ERR, "dns_a: hnl (%ld) >= %ld", 151682498Sroberto (long)hnl, (long)sizeof dp->hostname); 151782498Sroberto ++bogon; 151882498Sroberto } 151982498Sroberto 152082498Sroberto msyslog(LOG_INFO, "dns_a: <%s> for %s, AssocID %d, bogon %d", 1521132451Sroberto dp->hostname, 1522132451Sroberto stoa((struct sockaddr_storage *)&peeraddr), associd, 152382498Sroberto bogon); 1524132451Sroberto 152582498Sroberto if (bogon) { 152682498Sroberto /* If it didn't work */ 152782498Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 152882498Sroberto return; 152982498Sroberto } else { 153082498Sroberto#if 0 153182498Sroberto#ifdef PUBKEY 153282498Sroberto crypto_public(peer, dp->hostname); 153382498Sroberto#endif /* PUBKEY */ 153482498Sroberto#endif 153582498Sroberto } 1536132451Sroberto 153782498Sroberto dp++; 153882498Sroberto } 153982498Sroberto 154082498Sroberto req_ack(srcadr, inter, inpkt, INFO_OKAY); 154182498Sroberto} 1542132451Sroberto#endif /* 0 */ 154382498Sroberto 154482498Sroberto/* 154554359Sroberto * do_unconf - remove a peer from the configuration list 154654359Sroberto */ 154754359Srobertostatic void 154854359Srobertodo_unconf( 1549132451Sroberto struct sockaddr_storage *srcadr, 155054359Sroberto struct interface *inter, 155154359Sroberto struct req_pkt *inpkt 155254359Sroberto ) 155354359Sroberto{ 155454359Sroberto register struct conf_unpeer *cp; 1555132451Sroberto struct conf_unpeer temp_cp; 155654359Sroberto register int items; 155754359Sroberto register struct peer *peer; 1558132451Sroberto struct sockaddr_storage peeraddr; 155954359Sroberto int bad, found; 156054359Sroberto 156154359Sroberto /* 156254359Sroberto * This is a bit unstructured, but I like to be careful. 156354359Sroberto * We check to see that every peer exists and is actually 156454359Sroberto * configured. If so, we remove them. If not, we return 156554359Sroberto * an error. 156654359Sroberto */ 156754359Sroberto items = INFO_NITEMS(inpkt->err_nitems); 156854359Sroberto cp = (struct conf_unpeer *)inpkt->data; 156954359Sroberto 157054359Sroberto bad = 0; 157154359Sroberto while (items-- > 0 && !bad) { 1572132451Sroberto memset(&temp_cp, 0, sizeof(temp_cp)); 1573132451Sroberto memset(&peeraddr, 0, sizeof(peeraddr)); 1574132451Sroberto memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize)); 1575132451Sroberto if (client_v6_capable && temp_cp.v6_flag != 0) { 1576132451Sroberto peeraddr.ss_family = AF_INET6; 1577132451Sroberto GET_INADDR6(peeraddr) = temp_cp.peeraddr6; 1578132451Sroberto } else { 1579132451Sroberto peeraddr.ss_family = AF_INET; 1580132451Sroberto GET_INADDR(peeraddr) = temp_cp.peeraddr; 1581132451Sroberto } 1582132451Sroberto NSRCPORT(&peeraddr) = htons(NTP_PORT); 1583132451Sroberto#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 1584132451Sroberto peeraddr.ss_len = SOCKLEN(&peeraddr); 1585132451Sroberto#endif 158654359Sroberto found = 0; 158754359Sroberto peer = (struct peer *)0; 1588182007Sroberto#ifdef DEBUG 1589182007Sroberto if (debug) 1590182007Sroberto printf("searching for %s\n", stoa(&peeraddr)); 1591182007Sroberto#endif 159254359Sroberto while (!found) { 159354359Sroberto peer = findexistingpeer(&peeraddr, peer, -1); 159454359Sroberto if (peer == (struct peer *)0) 159554359Sroberto break; 159654359Sroberto if (peer->flags & FLAG_CONFIG) 159754359Sroberto found = 1; 159854359Sroberto } 159954359Sroberto if (!found) 160054359Sroberto bad = 1; 1601132451Sroberto cp = (struct conf_unpeer *) 1602132451Sroberto ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize)); 160354359Sroberto } 160454359Sroberto 160554359Sroberto if (bad) { 160654359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 160754359Sroberto return; 160854359Sroberto } 160954359Sroberto 161054359Sroberto /* 161154359Sroberto * Now do it in earnest. 161254359Sroberto */ 161354359Sroberto 161454359Sroberto items = INFO_NITEMS(inpkt->err_nitems); 161554359Sroberto cp = (struct conf_unpeer *)inpkt->data; 161654359Sroberto while (items-- > 0) { 1617132451Sroberto memset(&temp_cp, 0, sizeof(temp_cp)); 1618132451Sroberto memset(&peeraddr, 0, sizeof(peeraddr)); 1619132451Sroberto memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize)); 1620132451Sroberto if (client_v6_capable && temp_cp.v6_flag != 0) { 1621132451Sroberto peeraddr.ss_family = AF_INET6; 1622132451Sroberto GET_INADDR6(peeraddr) = temp_cp.peeraddr6; 1623132451Sroberto } else { 1624132451Sroberto peeraddr.ss_family = AF_INET; 1625132451Sroberto GET_INADDR(peeraddr) = temp_cp.peeraddr; 1626132451Sroberto } 1627132451Sroberto NSRCPORT(&peeraddr) = htons(NTP_PORT); 1628132451Sroberto#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 1629132451Sroberto peeraddr.ss_len = SOCKLEN(&peeraddr); 1630132451Sroberto#endif 163154359Sroberto peer_unconfig(&peeraddr, (struct interface *)0, -1); 1632132451Sroberto cp = (struct conf_unpeer *) 1633132451Sroberto ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize)); 163454359Sroberto } 163554359Sroberto 163654359Sroberto req_ack(srcadr, inter, inpkt, INFO_OKAY); 163754359Sroberto} 163854359Sroberto 163954359Sroberto 164054359Sroberto/* 164154359Sroberto * set_sys_flag - set system flags 164254359Sroberto */ 164354359Srobertostatic void 164454359Srobertoset_sys_flag( 1645132451Sroberto struct sockaddr_storage *srcadr, 164654359Sroberto struct interface *inter, 164754359Sroberto struct req_pkt *inpkt 164854359Sroberto ) 164954359Sroberto{ 165054359Sroberto setclr_flags(srcadr, inter, inpkt, 1); 165154359Sroberto} 165254359Sroberto 165354359Sroberto 165454359Sroberto/* 165554359Sroberto * clr_sys_flag - clear system flags 165654359Sroberto */ 165754359Srobertostatic void 165854359Srobertoclr_sys_flag( 1659132451Sroberto struct sockaddr_storage *srcadr, 166054359Sroberto struct interface *inter, 166154359Sroberto struct req_pkt *inpkt 166254359Sroberto ) 166354359Sroberto{ 166454359Sroberto setclr_flags(srcadr, inter, inpkt, 0); 166554359Sroberto} 166654359Sroberto 166754359Sroberto 166854359Sroberto/* 166954359Sroberto * setclr_flags - do the grunge work of flag setting/clearing 167054359Sroberto */ 167154359Srobertostatic void 167254359Srobertosetclr_flags( 1673132451Sroberto struct sockaddr_storage *srcadr, 167454359Sroberto struct interface *inter, 167554359Sroberto struct req_pkt *inpkt, 167654359Sroberto u_long set 167754359Sroberto ) 167854359Sroberto{ 167982498Sroberto register u_int flags; 1680182007Sroberto int prev_kern_enable; 168154359Sroberto 1682182007Sroberto prev_kern_enable = kern_enable; 168354359Sroberto if (INFO_NITEMS(inpkt->err_nitems) > 1) { 168482498Sroberto msyslog(LOG_ERR, "setclr_flags: err_nitems > 1"); 168554359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 168654359Sroberto return; 168754359Sroberto } 168854359Sroberto 168954359Sroberto flags = ((struct conf_sys_flags *)inpkt->data)->flags; 1690182007Sroberto flags = ntohl(flags); 1691182007Sroberto 169282498Sroberto if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS | 169354359Sroberto SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR | 1694106163Sroberto SYS_FLAG_FILEGEN | SYS_FLAG_AUTH | SYS_FLAG_CAL)) { 169582498Sroberto msyslog(LOG_ERR, "setclr_flags: extra flags: %#x", 1696132451Sroberto flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS | 169782498Sroberto SYS_FLAG_NTP | SYS_FLAG_KERNEL | 1698106163Sroberto SYS_FLAG_MONITOR | SYS_FLAG_FILEGEN | 1699106163Sroberto SYS_FLAG_AUTH | SYS_FLAG_CAL)); 170054359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 170154359Sroberto return; 170254359Sroberto } 170354359Sroberto 170454359Sroberto if (flags & SYS_FLAG_BCLIENT) 1705132451Sroberto proto_config(PROTO_BROADCLIENT, set, 0., NULL); 170682498Sroberto if (flags & SYS_FLAG_PPS) 1707132451Sroberto proto_config(PROTO_PPS, set, 0., NULL); 170854359Sroberto if (flags & SYS_FLAG_NTP) 1709132451Sroberto proto_config(PROTO_NTP, set, 0., NULL); 171054359Sroberto if (flags & SYS_FLAG_KERNEL) 1711132451Sroberto proto_config(PROTO_KERNEL, set, 0., NULL); 171254359Sroberto if (flags & SYS_FLAG_MONITOR) 1713132451Sroberto proto_config(PROTO_MONITOR, set, 0., NULL); 171454359Sroberto if (flags & SYS_FLAG_FILEGEN) 1715132451Sroberto proto_config(PROTO_FILEGEN, set, 0., NULL); 1716106163Sroberto if (flags & SYS_FLAG_AUTH) 1717132451Sroberto proto_config(PROTO_AUTHENTICATE, set, 0., NULL); 1718106163Sroberto if (flags & SYS_FLAG_CAL) 1719132451Sroberto proto_config(PROTO_CAL, set, 0., NULL); 172054359Sroberto req_ack(srcadr, inter, inpkt, INFO_OKAY); 1721182007Sroberto 1722182007Sroberto /* Reset the kernel ntp parameters if the kernel flag changed. */ 1723182007Sroberto if (prev_kern_enable && !kern_enable) 1724182007Sroberto loop_config(LOOP_KERN_CLEAR, 0.0); 1725182007Sroberto if (!prev_kern_enable && kern_enable) 1726182007Sroberto loop_config(LOOP_DRIFTCOMP, drift_comp); 172754359Sroberto} 172854359Sroberto 172954359Sroberto 173054359Sroberto/* 173154359Sroberto * list_restrict - return the restrict list 173254359Sroberto */ 173354359Srobertostatic void 173454359Srobertolist_restrict( 1735132451Sroberto struct sockaddr_storage *srcadr, 173654359Sroberto struct interface *inter, 173754359Sroberto struct req_pkt *inpkt 173854359Sroberto ) 173954359Sroberto{ 174054359Sroberto register struct info_restrict *ir; 174154359Sroberto register struct restrictlist *rl; 1742132451Sroberto register struct restrictlist6 *rl6; 174354359Sroberto 174454359Sroberto#ifdef DEBUG 174554359Sroberto if (debug > 2) 1746132451Sroberto printf("wants restrict list summary\n"); 174754359Sroberto#endif 174854359Sroberto 174954359Sroberto ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt, 1750132451Sroberto v6sizeof(struct info_restrict)); 1751132451Sroberto 175254359Sroberto for (rl = restrictlist; rl != 0 && ir != 0; rl = rl->next) { 175354359Sroberto ir->addr = htonl(rl->addr); 1754132451Sroberto if (client_v6_capable) 1755132451Sroberto ir->v6_flag = 0; 175654359Sroberto ir->mask = htonl(rl->mask); 175754359Sroberto ir->count = htonl((u_int32)rl->count); 175854359Sroberto ir->flags = htons(rl->flags); 175954359Sroberto ir->mflags = htons(rl->mflags); 176054359Sroberto ir = (struct info_restrict *)more_pkt(); 176154359Sroberto } 1762132451Sroberto if (client_v6_capable) 1763132451Sroberto for (rl6 = restrictlist6; rl6 != 0 && ir != 0; rl6 = rl6->next) { 1764132451Sroberto ir->addr6 = rl6->addr6; 1765132451Sroberto ir->mask6 = rl6->mask6; 1766132451Sroberto ir->v6_flag = 1; 1767132451Sroberto ir->count = htonl((u_int32)rl6->count); 1768132451Sroberto ir->flags = htons(rl6->flags); 1769132451Sroberto ir->mflags = htons(rl6->mflags); 1770132451Sroberto ir = (struct info_restrict *)more_pkt(); 1771132451Sroberto } 177254359Sroberto flush_pkt(); 177354359Sroberto} 177454359Sroberto 177554359Sroberto 177654359Sroberto 177754359Sroberto/* 177854359Sroberto * do_resaddflags - add flags to a restrict entry (or create one) 177954359Sroberto */ 178054359Srobertostatic void 178154359Srobertodo_resaddflags( 1782132451Sroberto struct sockaddr_storage *srcadr, 178354359Sroberto struct interface *inter, 178454359Sroberto struct req_pkt *inpkt 178554359Sroberto ) 178654359Sroberto{ 178754359Sroberto do_restrict(srcadr, inter, inpkt, RESTRICT_FLAGS); 178854359Sroberto} 178954359Sroberto 179054359Sroberto 179154359Sroberto 179254359Sroberto/* 179354359Sroberto * do_ressubflags - remove flags from a restrict entry 179454359Sroberto */ 179554359Srobertostatic void 179654359Srobertodo_ressubflags( 1797132451Sroberto struct sockaddr_storage *srcadr, 179854359Sroberto struct interface *inter, 179954359Sroberto struct req_pkt *inpkt 180054359Sroberto ) 180154359Sroberto{ 180254359Sroberto do_restrict(srcadr, inter, inpkt, RESTRICT_UNFLAG); 180354359Sroberto} 180454359Sroberto 180554359Sroberto 180654359Sroberto/* 180754359Sroberto * do_unrestrict - remove a restrict entry from the list 180854359Sroberto */ 180954359Srobertostatic void 181054359Srobertodo_unrestrict( 1811132451Sroberto struct sockaddr_storage *srcadr, 181254359Sroberto struct interface *inter, 181354359Sroberto struct req_pkt *inpkt 181454359Sroberto ) 181554359Sroberto{ 181654359Sroberto do_restrict(srcadr, inter, inpkt, RESTRICT_REMOVE); 181754359Sroberto} 181854359Sroberto 181954359Sroberto 182054359Sroberto 182154359Sroberto 182254359Sroberto 182354359Sroberto/* 182454359Sroberto * do_restrict - do the dirty stuff of dealing with restrictions 182554359Sroberto */ 182654359Srobertostatic void 182754359Srobertodo_restrict( 1828132451Sroberto struct sockaddr_storage *srcadr, 182954359Sroberto struct interface *inter, 183054359Sroberto struct req_pkt *inpkt, 183154359Sroberto int op 183254359Sroberto ) 183354359Sroberto{ 183454359Sroberto register struct conf_restrict *cr; 183554359Sroberto register int items; 1836132451Sroberto struct sockaddr_storage matchaddr; 1837132451Sroberto struct sockaddr_storage matchmask; 183854359Sroberto int bad; 183954359Sroberto 184054359Sroberto /* 184154359Sroberto * Do a check of the flags to make sure that only 184254359Sroberto * the NTPPORT flag is set, if any. If not, complain 184354359Sroberto * about it. Note we are very picky here. 184454359Sroberto */ 184554359Sroberto items = INFO_NITEMS(inpkt->err_nitems); 184654359Sroberto cr = (struct conf_restrict *)inpkt->data; 184754359Sroberto 184854359Sroberto bad = 0; 1849182007Sroberto cr->flags = ntohs(cr->flags); 1850182007Sroberto cr->mflags = ntohs(cr->mflags); 185154359Sroberto while (items-- > 0 && !bad) { 185254359Sroberto if (cr->mflags & ~(RESM_NTPONLY)) 185382498Sroberto bad |= 1; 185454359Sroberto if (cr->flags & ~(RES_ALLFLAGS)) 185582498Sroberto bad |= 2; 1856132451Sroberto if (cr->mask != htonl(INADDR_ANY)) { 1857132451Sroberto if (client_v6_capable && cr->v6_flag != 0) { 1858132451Sroberto if (IN6_IS_ADDR_UNSPECIFIED(&cr->addr6)) 1859132451Sroberto bad |= 4; 1860132451Sroberto } else 1861132451Sroberto if (cr->addr == htonl(INADDR_ANY)) 1862132451Sroberto bad |= 8; 1863132451Sroberto } 1864132451Sroberto cr = (struct conf_restrict *)((char *)cr + 1865132451Sroberto INFO_ITEMSIZE(inpkt->mbz_itemsize)); 186654359Sroberto } 186754359Sroberto 186854359Sroberto if (bad) { 186982498Sroberto msyslog(LOG_ERR, "do_restrict: bad = %#x", bad); 187054359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 187154359Sroberto return; 187254359Sroberto } 187354359Sroberto 187454359Sroberto /* 187554359Sroberto * Looks okay, try it out 187654359Sroberto */ 187754359Sroberto items = INFO_NITEMS(inpkt->err_nitems); 187854359Sroberto cr = (struct conf_restrict *)inpkt->data; 1879132451Sroberto memset((char *)&matchaddr, 0, sizeof(struct sockaddr_storage)); 1880132451Sroberto memset((char *)&matchmask, 0, sizeof(struct sockaddr_storage)); 188154359Sroberto 188254359Sroberto while (items-- > 0) { 1883132451Sroberto if (client_v6_capable && cr->v6_flag != 0) { 1884132451Sroberto GET_INADDR6(matchaddr) = cr->addr6; 1885132451Sroberto GET_INADDR6(matchmask) = cr->mask6; 1886132451Sroberto matchaddr.ss_family = AF_INET6; 1887132451Sroberto matchmask.ss_family = AF_INET6; 1888132451Sroberto } else { 1889132451Sroberto GET_INADDR(matchaddr) = cr->addr; 1890132451Sroberto GET_INADDR(matchmask) = cr->mask; 1891132451Sroberto matchaddr.ss_family = AF_INET; 1892132451Sroberto matchmask.ss_family = AF_INET; 1893132451Sroberto } 189454359Sroberto hack_restrict(op, &matchaddr, &matchmask, cr->mflags, 189554359Sroberto cr->flags); 189654359Sroberto cr++; 189754359Sroberto } 189854359Sroberto 189954359Sroberto req_ack(srcadr, inter, inpkt, INFO_OKAY); 190054359Sroberto} 190154359Sroberto 190254359Sroberto 190354359Sroberto/* 190454359Sroberto * mon_getlist - return monitor data 190554359Sroberto */ 190654359Srobertostatic void 190754359Srobertomon_getlist_0( 1908132451Sroberto struct sockaddr_storage *srcadr, 190954359Sroberto struct interface *inter, 191054359Sroberto struct req_pkt *inpkt 191154359Sroberto ) 191254359Sroberto{ 191354359Sroberto register struct info_monitor *im; 191454359Sroberto register struct mon_data *md; 191554359Sroberto extern struct mon_data mon_mru_list; 191654359Sroberto extern int mon_enabled; 191754359Sroberto 191854359Sroberto#ifdef DEBUG 191954359Sroberto if (debug > 2) 192054359Sroberto printf("wants monitor 0 list\n"); 192154359Sroberto#endif 192254359Sroberto if (!mon_enabled) { 192354359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 192454359Sroberto return; 192554359Sroberto } 192654359Sroberto im = (struct info_monitor *)prepare_pkt(srcadr, inter, inpkt, 1927132451Sroberto v6sizeof(struct info_monitor)); 192854359Sroberto for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0; 192954359Sroberto md = md->mru_next) { 1930132451Sroberto im->lasttime = htonl((u_int32)md->avg_interval); 1931132451Sroberto im->firsttime = htonl((u_int32)(current_time - md->lasttime)); 1932132451Sroberto im->lastdrop = htonl((u_int32)md->drop_count); 193354359Sroberto im->count = htonl((u_int32)(md->count)); 1934132451Sroberto if (md->rmtadr.ss_family == AF_INET6) { 1935132451Sroberto if (!client_v6_capable) 1936132451Sroberto continue; 1937132451Sroberto im->addr6 = GET_INADDR6(md->rmtadr); 1938132451Sroberto im->v6_flag = 1; 1939132451Sroberto } else { 1940132451Sroberto im->addr = GET_INADDR(md->rmtadr); 1941132451Sroberto if (client_v6_capable) 1942132451Sroberto im->v6_flag = 0; 1943132451Sroberto } 194454359Sroberto im->port = md->rmtport; 194554359Sroberto im->mode = md->mode; 194654359Sroberto im->version = md->version; 194754359Sroberto im = (struct info_monitor *)more_pkt(); 194854359Sroberto } 194954359Sroberto flush_pkt(); 195054359Sroberto} 195154359Sroberto 195254359Sroberto/* 195354359Sroberto * mon_getlist - return monitor data 195454359Sroberto */ 195554359Srobertostatic void 195654359Srobertomon_getlist_1( 1957132451Sroberto struct sockaddr_storage *srcadr, 195854359Sroberto struct interface *inter, 195954359Sroberto struct req_pkt *inpkt 196054359Sroberto ) 196154359Sroberto{ 196254359Sroberto register struct info_monitor_1 *im; 196354359Sroberto register struct mon_data *md; 196454359Sroberto extern struct mon_data mon_mru_list; 196554359Sroberto extern int mon_enabled; 196654359Sroberto 196754359Sroberto if (!mon_enabled) { 196854359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 196954359Sroberto return; 197054359Sroberto } 197154359Sroberto im = (struct info_monitor_1 *)prepare_pkt(srcadr, inter, inpkt, 1972132451Sroberto v6sizeof(struct info_monitor_1)); 197354359Sroberto for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0; 197454359Sroberto md = md->mru_next) { 1975132451Sroberto im->lasttime = htonl((u_int32)md->avg_interval); 1976132451Sroberto im->firsttime = htonl((u_int32)(current_time - md->lasttime)); 1977132451Sroberto im->lastdrop = htonl((u_int32)md->drop_count); 197854359Sroberto im->count = htonl((u_int32)md->count); 1979132451Sroberto if (md->rmtadr.ss_family == AF_INET6) { 1980132451Sroberto if (!client_v6_capable) 1981132451Sroberto continue; 1982132451Sroberto im->addr6 = GET_INADDR6(md->rmtadr); 1983132451Sroberto im->v6_flag = 1; 1984132451Sroberto im->daddr6 = GET_INADDR6(md->interface->sin); 1985132451Sroberto } else { 1986132451Sroberto im->addr = GET_INADDR(md->rmtadr); 1987132451Sroberto if (client_v6_capable) 1988132451Sroberto im->v6_flag = 0; 1989132451Sroberto im->daddr = (md->cast_flags == MDF_BCAST) 1990132451Sroberto ? GET_INADDR(md->interface->bcast) 1991132451Sroberto : (md->cast_flags 1992132451Sroberto ? (GET_INADDR(md->interface->sin) 1993132451Sroberto ? GET_INADDR(md->interface->sin) 1994132451Sroberto : GET_INADDR(md->interface->bcast)) 1995132451Sroberto : 4); 1996132451Sroberto } 1997182007Sroberto im->flags = htonl(md->cast_flags); 199854359Sroberto im->port = md->rmtport; 199954359Sroberto im->mode = md->mode; 200054359Sroberto im->version = md->version; 200154359Sroberto im = (struct info_monitor_1 *)more_pkt(); 200254359Sroberto } 200354359Sroberto flush_pkt(); 200454359Sroberto} 200554359Sroberto 200654359Sroberto/* 200754359Sroberto * Module entry points and the flags they correspond with 200854359Sroberto */ 200954359Srobertostruct reset_entry { 201054359Sroberto int flag; /* flag this corresponds to */ 201154359Sroberto void (*handler) P((void)); /* routine to handle request */ 201254359Sroberto}; 201354359Sroberto 201454359Srobertostruct reset_entry reset_entries[] = { 201554359Sroberto { RESET_FLAG_ALLPEERS, peer_all_reset }, 201654359Sroberto { RESET_FLAG_IO, io_clr_stats }, 201754359Sroberto { RESET_FLAG_SYS, proto_clr_stats }, 201854359Sroberto { RESET_FLAG_MEM, peer_clr_stats }, 201954359Sroberto { RESET_FLAG_TIMER, timer_clr_stats }, 202054359Sroberto { RESET_FLAG_AUTH, reset_auth_stats }, 202154359Sroberto { RESET_FLAG_CTL, ctl_clr_stats }, 202254359Sroberto { 0, 0 } 202354359Sroberto}; 202454359Sroberto 202554359Sroberto/* 202654359Sroberto * reset_stats - reset statistic counters here and there 202754359Sroberto */ 202854359Srobertostatic void 202954359Srobertoreset_stats( 2030132451Sroberto struct sockaddr_storage *srcadr, 203154359Sroberto struct interface *inter, 203254359Sroberto struct req_pkt *inpkt 203354359Sroberto ) 203454359Sroberto{ 203554359Sroberto u_long flags; 203654359Sroberto struct reset_entry *rent; 203754359Sroberto 203854359Sroberto if (INFO_NITEMS(inpkt->err_nitems) > 1) { 203982498Sroberto msyslog(LOG_ERR, "reset_stats: err_nitems > 1"); 204054359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 204154359Sroberto return; 204254359Sroberto } 204354359Sroberto 204454359Sroberto flags = ((struct reset_flags *)inpkt->data)->flags; 2045182007Sroberto flags = ntohl(flags); 2046182007Sroberto 204754359Sroberto if (flags & ~RESET_ALLFLAGS) { 204882498Sroberto msyslog(LOG_ERR, "reset_stats: reset leaves %#lx", 204982498Sroberto flags & ~RESET_ALLFLAGS); 205054359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 205154359Sroberto return; 205254359Sroberto } 205354359Sroberto 205454359Sroberto for (rent = reset_entries; rent->flag != 0; rent++) { 205554359Sroberto if (flags & rent->flag) 205654359Sroberto (rent->handler)(); 205754359Sroberto } 205854359Sroberto req_ack(srcadr, inter, inpkt, INFO_OKAY); 205954359Sroberto} 206054359Sroberto 206154359Sroberto 206254359Sroberto/* 206354359Sroberto * reset_peer - clear a peer's statistics 206454359Sroberto */ 206554359Srobertostatic void 206654359Srobertoreset_peer( 2067132451Sroberto struct sockaddr_storage *srcadr, 206854359Sroberto struct interface *inter, 206954359Sroberto struct req_pkt *inpkt 207054359Sroberto ) 207154359Sroberto{ 207254359Sroberto register struct conf_unpeer *cp; 207354359Sroberto register int items; 207454359Sroberto register struct peer *peer; 2075132451Sroberto struct sockaddr_storage peeraddr; 207654359Sroberto int bad; 207754359Sroberto 207854359Sroberto /* 207954359Sroberto * We check first to see that every peer exists. If not, 208054359Sroberto * we return an error. 208154359Sroberto */ 208254359Sroberto 208354359Sroberto items = INFO_NITEMS(inpkt->err_nitems); 208454359Sroberto cp = (struct conf_unpeer *)inpkt->data; 208554359Sroberto 208654359Sroberto bad = 0; 208754359Sroberto while (items-- > 0 && !bad) { 2088132451Sroberto memset((char *)&peeraddr, 0, sizeof(peeraddr)); 2089132451Sroberto if (client_v6_capable && cp->v6_flag != 0) { 2090132451Sroberto GET_INADDR6(peeraddr) = cp->peeraddr6; 2091132451Sroberto peeraddr.ss_family = AF_INET6; 2092132451Sroberto } else { 2093132451Sroberto GET_INADDR(peeraddr) = cp->peeraddr; 2094132451Sroberto peeraddr.ss_family = AF_INET; 2095132451Sroberto } 2096132451Sroberto NSRCPORT(&peeraddr) = htons(NTP_PORT); 2097132451Sroberto#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 2098132451Sroberto peeraddr.ss_len = SOCKLEN(&peeraddr); 2099132451Sroberto#endif 210054359Sroberto peer = findexistingpeer(&peeraddr, (struct peer *)0, -1); 210154359Sroberto if (peer == (struct peer *)0) 210254359Sroberto bad++; 2103132451Sroberto cp = (struct conf_unpeer *)((char *)cp + 2104132451Sroberto INFO_ITEMSIZE(inpkt->mbz_itemsize)); 210554359Sroberto } 210654359Sroberto 210754359Sroberto if (bad) { 210854359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 210954359Sroberto return; 211054359Sroberto } 211154359Sroberto 211254359Sroberto /* 211354359Sroberto * Now do it in earnest. 211454359Sroberto */ 211554359Sroberto 211654359Sroberto items = INFO_NITEMS(inpkt->err_nitems); 211754359Sroberto cp = (struct conf_unpeer *)inpkt->data; 211854359Sroberto while (items-- > 0) { 2119132451Sroberto memset((char *)&peeraddr, 0, sizeof(peeraddr)); 2120132451Sroberto if (client_v6_capable && cp->v6_flag != 0) { 2121132451Sroberto GET_INADDR6(peeraddr) = cp->peeraddr6; 2122132451Sroberto peeraddr.ss_family = AF_INET6; 2123132451Sroberto } else { 2124132451Sroberto GET_INADDR(peeraddr) = cp->peeraddr; 2125132451Sroberto peeraddr.ss_family = AF_INET; 2126132451Sroberto } 2127132451Sroberto#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 2128132451Sroberto peeraddr.ss_len = SOCKLEN(&peeraddr); 2129132451Sroberto#endif 213054359Sroberto peer = findexistingpeer(&peeraddr, (struct peer *)0, -1); 213154359Sroberto while (peer != 0) { 213254359Sroberto peer_reset(peer); 213354359Sroberto peer = findexistingpeer(&peeraddr, (struct peer *)peer, -1); 213454359Sroberto } 2135132451Sroberto cp = (struct conf_unpeer *)((char *)cp + 2136132451Sroberto INFO_ITEMSIZE(inpkt->mbz_itemsize)); 213754359Sroberto } 213854359Sroberto 213954359Sroberto req_ack(srcadr, inter, inpkt, INFO_OKAY); 214054359Sroberto} 214154359Sroberto 214254359Sroberto 214354359Sroberto/* 214454359Sroberto * do_key_reread - reread the encryption key file 214554359Sroberto */ 214654359Srobertostatic void 214754359Srobertodo_key_reread( 2148132451Sroberto struct sockaddr_storage *srcadr, 214954359Sroberto struct interface *inter, 215054359Sroberto struct req_pkt *inpkt 215154359Sroberto ) 215254359Sroberto{ 215354359Sroberto rereadkeys(); 215454359Sroberto req_ack(srcadr, inter, inpkt, INFO_OKAY); 215554359Sroberto} 215654359Sroberto 215754359Sroberto 215854359Sroberto/* 215954359Sroberto * trust_key - make one or more keys trusted 216054359Sroberto */ 216154359Srobertostatic void 216254359Srobertotrust_key( 2163132451Sroberto struct sockaddr_storage *srcadr, 216454359Sroberto struct interface *inter, 216554359Sroberto struct req_pkt *inpkt 216654359Sroberto ) 216754359Sroberto{ 216854359Sroberto do_trustkey(srcadr, inter, inpkt, 1); 216954359Sroberto} 217054359Sroberto 217154359Sroberto 217254359Sroberto/* 217354359Sroberto * untrust_key - make one or more keys untrusted 217454359Sroberto */ 217554359Srobertostatic void 217654359Srobertountrust_key( 2177132451Sroberto struct sockaddr_storage *srcadr, 217854359Sroberto struct interface *inter, 217954359Sroberto struct req_pkt *inpkt 218054359Sroberto ) 218154359Sroberto{ 218254359Sroberto do_trustkey(srcadr, inter, inpkt, 0); 218354359Sroberto} 218454359Sroberto 218554359Sroberto 218654359Sroberto/* 218754359Sroberto * do_trustkey - make keys either trustable or untrustable 218854359Sroberto */ 218954359Srobertostatic void 219054359Srobertodo_trustkey( 2191132451Sroberto struct sockaddr_storage *srcadr, 219254359Sroberto struct interface *inter, 219354359Sroberto struct req_pkt *inpkt, 219482498Sroberto u_long trust 219554359Sroberto ) 219654359Sroberto{ 219754359Sroberto register u_long *kp; 219854359Sroberto register int items; 219954359Sroberto 220054359Sroberto items = INFO_NITEMS(inpkt->err_nitems); 220154359Sroberto kp = (u_long *)inpkt->data; 220254359Sroberto while (items-- > 0) { 220354359Sroberto authtrust(*kp, trust); 220454359Sroberto kp++; 220554359Sroberto } 220654359Sroberto 220754359Sroberto req_ack(srcadr, inter, inpkt, INFO_OKAY); 220854359Sroberto} 220954359Sroberto 221054359Sroberto 221154359Sroberto/* 221254359Sroberto * get_auth_info - return some stats concerning the authentication module 221354359Sroberto */ 221454359Srobertostatic void 221554359Srobertoget_auth_info( 2216132451Sroberto struct sockaddr_storage *srcadr, 221754359Sroberto struct interface *inter, 221854359Sroberto struct req_pkt *inpkt 221954359Sroberto ) 222054359Sroberto{ 222154359Sroberto register struct info_auth *ia; 222254359Sroberto 222354359Sroberto /* 222454359Sroberto * Importations from the authentication module 222554359Sroberto */ 222654359Sroberto extern u_long authnumkeys; 222754359Sroberto extern int authnumfreekeys; 222854359Sroberto extern u_long authkeylookups; 222954359Sroberto extern u_long authkeynotfound; 223054359Sroberto extern u_long authencryptions; 223154359Sroberto extern u_long authdecryptions; 223254359Sroberto extern u_long authkeyuncached; 223354359Sroberto extern u_long authkeyexpired; 223454359Sroberto 223554359Sroberto ia = (struct info_auth *)prepare_pkt(srcadr, inter, inpkt, 223654359Sroberto sizeof(struct info_auth)); 223754359Sroberto 223854359Sroberto ia->numkeys = htonl((u_int32)authnumkeys); 223954359Sroberto ia->numfreekeys = htonl((u_int32)authnumfreekeys); 224054359Sroberto ia->keylookups = htonl((u_int32)authkeylookups); 224154359Sroberto ia->keynotfound = htonl((u_int32)authkeynotfound); 224254359Sroberto ia->encryptions = htonl((u_int32)authencryptions); 224354359Sroberto ia->decryptions = htonl((u_int32)authdecryptions); 224454359Sroberto ia->keyuncached = htonl((u_int32)authkeyuncached); 224554359Sroberto ia->expired = htonl((u_int32)authkeyexpired); 224654359Sroberto ia->timereset = htonl((u_int32)(current_time - auth_timereset)); 224754359Sroberto 224854359Sroberto (void) more_pkt(); 224954359Sroberto flush_pkt(); 225054359Sroberto} 225154359Sroberto 225254359Sroberto 225354359Sroberto 225454359Sroberto/* 225554359Sroberto * reset_auth_stats - reset the authentication stat counters. Done here 225654359Sroberto * to keep ntp-isms out of the authentication module 225754359Sroberto */ 225854359Srobertostatic void 225954359Srobertoreset_auth_stats(void) 226054359Sroberto{ 226154359Sroberto /* 226254359Sroberto * Importations from the authentication module 226354359Sroberto */ 226454359Sroberto extern u_long authkeylookups; 226554359Sroberto extern u_long authkeynotfound; 226654359Sroberto extern u_long authencryptions; 226754359Sroberto extern u_long authdecryptions; 226854359Sroberto extern u_long authkeyuncached; 226954359Sroberto 227054359Sroberto authkeylookups = 0; 227154359Sroberto authkeynotfound = 0; 227254359Sroberto authencryptions = 0; 227354359Sroberto authdecryptions = 0; 227454359Sroberto authkeyuncached = 0; 227554359Sroberto auth_timereset = current_time; 227654359Sroberto} 227754359Sroberto 227854359Sroberto 227954359Sroberto/* 228054359Sroberto * req_get_traps - return information about current trap holders 228154359Sroberto */ 228254359Srobertostatic void 228354359Srobertoreq_get_traps( 2284132451Sroberto struct sockaddr_storage *srcadr, 228554359Sroberto struct interface *inter, 228654359Sroberto struct req_pkt *inpkt 228754359Sroberto ) 228854359Sroberto{ 228954359Sroberto register struct info_trap *it; 229054359Sroberto register struct ctl_trap *tr; 229154359Sroberto register int i; 229254359Sroberto 229354359Sroberto /* 229454359Sroberto * Imported from the control module 229554359Sroberto */ 229654359Sroberto extern struct ctl_trap ctl_trap[]; 229754359Sroberto extern int num_ctl_traps; 229854359Sroberto 229954359Sroberto if (num_ctl_traps == 0) { 230054359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 230154359Sroberto return; 230254359Sroberto } 230354359Sroberto 230454359Sroberto it = (struct info_trap *)prepare_pkt(srcadr, inter, inpkt, 2305132451Sroberto v6sizeof(struct info_trap)); 230654359Sroberto 230754359Sroberto for (i = 0, tr = ctl_trap; i < CTL_MAXTRAPS; i++, tr++) { 230854359Sroberto if (tr->tr_flags & TRAP_INUSE) { 2309132451Sroberto if (tr->tr_addr.ss_family == AF_INET) { 2310132451Sroberto if (tr->tr_localaddr == any_interface) 2311132451Sroberto it->local_address = 0; 2312132451Sroberto else 2313132451Sroberto it->local_address 2314132451Sroberto = GET_INADDR(tr->tr_localaddr->sin); 2315132451Sroberto it->trap_address = GET_INADDR(tr->tr_addr); 2316132451Sroberto if (client_v6_capable) 2317132451Sroberto it->v6_flag = 0; 2318132451Sroberto } else { 2319132451Sroberto if (!client_v6_capable) 2320132451Sroberto continue; 2321132451Sroberto it->local_address6 2322132451Sroberto = GET_INADDR6(tr->tr_localaddr->sin); 2323132451Sroberto it->trap_address6 = GET_INADDR6(tr->tr_addr); 2324132451Sroberto it->v6_flag = 1; 2325132451Sroberto } 232654359Sroberto it->trap_port = NSRCPORT(&tr->tr_addr); 232754359Sroberto it->sequence = htons(tr->tr_sequence); 232854359Sroberto it->settime = htonl((u_int32)(current_time - tr->tr_settime)); 232954359Sroberto it->origtime = htonl((u_int32)(current_time - tr->tr_origtime)); 233054359Sroberto it->resets = htonl((u_int32)tr->tr_resets); 233154359Sroberto it->flags = htonl((u_int32)tr->tr_flags); 233254359Sroberto it = (struct info_trap *)more_pkt(); 233354359Sroberto } 233454359Sroberto } 233554359Sroberto flush_pkt(); 233654359Sroberto} 233754359Sroberto 233854359Sroberto 233954359Sroberto/* 234054359Sroberto * req_set_trap - configure a trap 234154359Sroberto */ 234254359Srobertostatic void 234354359Srobertoreq_set_trap( 2344132451Sroberto struct sockaddr_storage *srcadr, 234554359Sroberto struct interface *inter, 234654359Sroberto struct req_pkt *inpkt 234754359Sroberto ) 234854359Sroberto{ 234954359Sroberto do_setclr_trap(srcadr, inter, inpkt, 1); 235054359Sroberto} 235154359Sroberto 235254359Sroberto 235354359Sroberto 235454359Sroberto/* 235554359Sroberto * req_clr_trap - unconfigure a trap 235654359Sroberto */ 235754359Srobertostatic void 235854359Srobertoreq_clr_trap( 2359132451Sroberto struct sockaddr_storage *srcadr, 236054359Sroberto struct interface *inter, 236154359Sroberto struct req_pkt *inpkt 236254359Sroberto ) 236354359Sroberto{ 236454359Sroberto do_setclr_trap(srcadr, inter, inpkt, 0); 236554359Sroberto} 236654359Sroberto 236754359Sroberto 236854359Sroberto 236954359Sroberto/* 237054359Sroberto * do_setclr_trap - do the grunge work of (un)configuring a trap 237154359Sroberto */ 237254359Srobertostatic void 237354359Srobertodo_setclr_trap( 2374132451Sroberto struct sockaddr_storage *srcadr, 237554359Sroberto struct interface *inter, 237654359Sroberto struct req_pkt *inpkt, 237754359Sroberto int set 237854359Sroberto ) 237954359Sroberto{ 238054359Sroberto register struct conf_trap *ct; 238154359Sroberto register struct interface *linter; 238254359Sroberto int res; 2383132451Sroberto struct sockaddr_storage laddr; 238454359Sroberto 238554359Sroberto /* 2386132451Sroberto * Prepare sockaddr_storage structure 238754359Sroberto */ 238854359Sroberto memset((char *)&laddr, 0, sizeof laddr); 2389132451Sroberto laddr.ss_family = srcadr->ss_family; 2390132451Sroberto NSRCPORT(&laddr) = ntohs(NTP_PORT); 239154359Sroberto 239254359Sroberto /* 239354359Sroberto * Restrict ourselves to one item only. This eliminates 239454359Sroberto * the error reporting problem. 239554359Sroberto */ 239654359Sroberto if (INFO_NITEMS(inpkt->err_nitems) > 1) { 239782498Sroberto msyslog(LOG_ERR, "do_setclr_trap: err_nitems > 1"); 239854359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 239954359Sroberto return; 240054359Sroberto } 240154359Sroberto ct = (struct conf_trap *)inpkt->data; 240254359Sroberto 240354359Sroberto /* 240454359Sroberto * Look for the local interface. If none, use the default. 240554359Sroberto */ 240654359Sroberto if (ct->local_address == 0) { 240754359Sroberto linter = any_interface; 240854359Sroberto } else { 2409132451Sroberto if (laddr.ss_family == AF_INET) 2410132451Sroberto GET_INADDR(laddr) = ct->local_address; 2411132451Sroberto else 2412132451Sroberto GET_INADDR6(laddr) = ct->local_address6; 241354359Sroberto linter = findinterface(&laddr); 241454359Sroberto if (linter == NULL) { 241554359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 241654359Sroberto return; 241754359Sroberto } 241854359Sroberto } 241954359Sroberto 2420132451Sroberto if (laddr.ss_family == AF_INET) 2421132451Sroberto GET_INADDR(laddr) = ct->trap_address; 2422132451Sroberto else 2423132451Sroberto GET_INADDR6(laddr) = ct->trap_address6; 242454359Sroberto if (ct->trap_port != 0) 2425132451Sroberto NSRCPORT(&laddr) = ct->trap_port; 242654359Sroberto else 2427132451Sroberto NSRCPORT(&laddr) = htons(TRAPPORT); 242854359Sroberto 242954359Sroberto if (set) { 243054359Sroberto res = ctlsettrap(&laddr, linter, 0, 243154359Sroberto INFO_VERSION(inpkt->rm_vn_mode)); 243254359Sroberto } else { 243354359Sroberto res = ctlclrtrap(&laddr, linter, 0); 243454359Sroberto } 243554359Sroberto 243654359Sroberto if (!res) { 243754359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 243854359Sroberto } else { 243954359Sroberto req_ack(srcadr, inter, inpkt, INFO_OKAY); 244054359Sroberto } 244154359Sroberto return; 244254359Sroberto} 244354359Sroberto 244454359Sroberto 244554359Sroberto 244654359Sroberto/* 244754359Sroberto * set_request_keyid - set the keyid used to authenticate requests 244854359Sroberto */ 244954359Srobertostatic void 245054359Srobertoset_request_keyid( 2451132451Sroberto struct sockaddr_storage *srcadr, 245254359Sroberto struct interface *inter, 245354359Sroberto struct req_pkt *inpkt 245454359Sroberto ) 245554359Sroberto{ 245682498Sroberto keyid_t keyid; 245754359Sroberto 245854359Sroberto /* 245954359Sroberto * Restrict ourselves to one item only. 246054359Sroberto */ 246154359Sroberto if (INFO_NITEMS(inpkt->err_nitems) > 1) { 246282498Sroberto msyslog(LOG_ERR, "set_request_keyid: err_nitems > 1"); 246354359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 246454359Sroberto return; 246554359Sroberto } 246654359Sroberto 246754359Sroberto keyid = ntohl(*((u_int32 *)(inpkt->data))); 246854359Sroberto info_auth_keyid = keyid; 246954359Sroberto req_ack(srcadr, inter, inpkt, INFO_OKAY); 247054359Sroberto} 247154359Sroberto 247254359Sroberto 247354359Sroberto 247454359Sroberto/* 247554359Sroberto * set_control_keyid - set the keyid used to authenticate requests 247654359Sroberto */ 247754359Srobertostatic void 247854359Srobertoset_control_keyid( 2479132451Sroberto struct sockaddr_storage *srcadr, 248054359Sroberto struct interface *inter, 248154359Sroberto struct req_pkt *inpkt 248254359Sroberto ) 248354359Sroberto{ 248482498Sroberto keyid_t keyid; 248582498Sroberto extern keyid_t ctl_auth_keyid; 248654359Sroberto 248754359Sroberto /* 248854359Sroberto * Restrict ourselves to one item only. 248954359Sroberto */ 249054359Sroberto if (INFO_NITEMS(inpkt->err_nitems) > 1) { 249182498Sroberto msyslog(LOG_ERR, "set_control_keyid: err_nitems > 1"); 249254359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 249354359Sroberto return; 249454359Sroberto } 249554359Sroberto 249654359Sroberto keyid = ntohl(*((u_int32 *)(inpkt->data))); 249754359Sroberto ctl_auth_keyid = keyid; 249854359Sroberto req_ack(srcadr, inter, inpkt, INFO_OKAY); 249954359Sroberto} 250054359Sroberto 250154359Sroberto 250254359Sroberto 250354359Sroberto/* 250454359Sroberto * get_ctl_stats - return some stats concerning the control message module 250554359Sroberto */ 250654359Srobertostatic void 250754359Srobertoget_ctl_stats( 2508132451Sroberto struct sockaddr_storage *srcadr, 250954359Sroberto struct interface *inter, 251054359Sroberto struct req_pkt *inpkt 251154359Sroberto ) 251254359Sroberto{ 251354359Sroberto register struct info_control *ic; 251454359Sroberto 251554359Sroberto /* 251654359Sroberto * Importations from the control module 251754359Sroberto */ 251854359Sroberto extern u_long ctltimereset; 251954359Sroberto extern u_long numctlreq; 252054359Sroberto extern u_long numctlbadpkts; 252154359Sroberto extern u_long numctlresponses; 252254359Sroberto extern u_long numctlfrags; 252354359Sroberto extern u_long numctlerrors; 252454359Sroberto extern u_long numctltooshort; 252554359Sroberto extern u_long numctlinputresp; 252654359Sroberto extern u_long numctlinputfrag; 252754359Sroberto extern u_long numctlinputerr; 252854359Sroberto extern u_long numctlbadoffset; 252954359Sroberto extern u_long numctlbadversion; 253054359Sroberto extern u_long numctldatatooshort; 253154359Sroberto extern u_long numctlbadop; 253254359Sroberto extern u_long numasyncmsgs; 253354359Sroberto 253454359Sroberto ic = (struct info_control *)prepare_pkt(srcadr, inter, inpkt, 253554359Sroberto sizeof(struct info_control)); 253654359Sroberto 253754359Sroberto ic->ctltimereset = htonl((u_int32)(current_time - ctltimereset)); 253854359Sroberto ic->numctlreq = htonl((u_int32)numctlreq); 253954359Sroberto ic->numctlbadpkts = htonl((u_int32)numctlbadpkts); 254054359Sroberto ic->numctlresponses = htonl((u_int32)numctlresponses); 254154359Sroberto ic->numctlfrags = htonl((u_int32)numctlfrags); 254254359Sroberto ic->numctlerrors = htonl((u_int32)numctlerrors); 254354359Sroberto ic->numctltooshort = htonl((u_int32)numctltooshort); 254454359Sroberto ic->numctlinputresp = htonl((u_int32)numctlinputresp); 254554359Sroberto ic->numctlinputfrag = htonl((u_int32)numctlinputfrag); 254654359Sroberto ic->numctlinputerr = htonl((u_int32)numctlinputerr); 254754359Sroberto ic->numctlbadoffset = htonl((u_int32)numctlbadoffset); 254854359Sroberto ic->numctlbadversion = htonl((u_int32)numctlbadversion); 254954359Sroberto ic->numctldatatooshort = htonl((u_int32)numctldatatooshort); 255054359Sroberto ic->numctlbadop = htonl((u_int32)numctlbadop); 255154359Sroberto ic->numasyncmsgs = htonl((u_int32)numasyncmsgs); 255254359Sroberto 255354359Sroberto (void) more_pkt(); 255454359Sroberto flush_pkt(); 255554359Sroberto} 255654359Sroberto 255754359Sroberto 255854359Sroberto#ifdef KERNEL_PLL 255954359Sroberto/* 256054359Sroberto * get_kernel_info - get kernel pll/pps information 256154359Sroberto */ 256254359Srobertostatic void 256354359Srobertoget_kernel_info( 2564132451Sroberto struct sockaddr_storage *srcadr, 256554359Sroberto struct interface *inter, 256654359Sroberto struct req_pkt *inpkt 256754359Sroberto ) 256854359Sroberto{ 256954359Sroberto register struct info_kernel *ik; 257054359Sroberto struct timex ntx; 257154359Sroberto 257254359Sroberto if (!pll_control) { 257354359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 257454359Sroberto return; 257554359Sroberto } 257654359Sroberto 257754359Sroberto memset((char *)&ntx, 0, sizeof(ntx)); 257854359Sroberto if (ntp_adjtime(&ntx) < 0) 257954359Sroberto msyslog(LOG_ERR, "get_kernel_info: ntp_adjtime() failed: %m"); 258054359Sroberto ik = (struct info_kernel *)prepare_pkt(srcadr, inter, inpkt, 258154359Sroberto sizeof(struct info_kernel)); 258254359Sroberto 258354359Sroberto /* 258454359Sroberto * pll variables 258554359Sroberto */ 258654359Sroberto ik->offset = htonl((u_int32)ntx.offset); 258754359Sroberto ik->freq = htonl((u_int32)ntx.freq); 258854359Sroberto ik->maxerror = htonl((u_int32)ntx.maxerror); 258954359Sroberto ik->esterror = htonl((u_int32)ntx.esterror); 259054359Sroberto ik->status = htons(ntx.status); 259154359Sroberto ik->constant = htonl((u_int32)ntx.constant); 259254359Sroberto ik->precision = htonl((u_int32)ntx.precision); 259354359Sroberto ik->tolerance = htonl((u_int32)ntx.tolerance); 259454359Sroberto 259554359Sroberto /* 259654359Sroberto * pps variables 259754359Sroberto */ 259854359Sroberto ik->ppsfreq = htonl((u_int32)ntx.ppsfreq); 259954359Sroberto ik->jitter = htonl((u_int32)ntx.jitter); 260054359Sroberto ik->shift = htons(ntx.shift); 260154359Sroberto ik->stabil = htonl((u_int32)ntx.stabil); 260254359Sroberto ik->jitcnt = htonl((u_int32)ntx.jitcnt); 260354359Sroberto ik->calcnt = htonl((u_int32)ntx.calcnt); 260454359Sroberto ik->errcnt = htonl((u_int32)ntx.errcnt); 260554359Sroberto ik->stbcnt = htonl((u_int32)ntx.stbcnt); 260654359Sroberto 260754359Sroberto (void) more_pkt(); 260854359Sroberto flush_pkt(); 260954359Sroberto} 261054359Sroberto#endif /* KERNEL_PLL */ 261154359Sroberto 261254359Sroberto 261354359Sroberto#ifdef REFCLOCK 261454359Sroberto/* 261554359Sroberto * get_clock_info - get info about a clock 261654359Sroberto */ 261754359Srobertostatic void 261854359Srobertoget_clock_info( 2619132451Sroberto struct sockaddr_storage *srcadr, 262054359Sroberto struct interface *inter, 262154359Sroberto struct req_pkt *inpkt 262254359Sroberto ) 262354359Sroberto{ 262454359Sroberto register struct info_clock *ic; 262554359Sroberto register u_int32 *clkaddr; 262654359Sroberto register int items; 262754359Sroberto struct refclockstat clock_stat; 2628132451Sroberto struct sockaddr_storage addr; 2629132451Sroberto struct sockaddr_in tmp_clock; 263054359Sroberto l_fp ltmp; 263154359Sroberto 263254359Sroberto memset((char *)&addr, 0, sizeof addr); 2633132451Sroberto addr.ss_family = AF_INET; 2634132451Sroberto#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 2635132451Sroberto addr.ss_len = SOCKLEN(&addr); 2636132451Sroberto#endif 2637132451Sroberto NSRCPORT(&addr) = htons(NTP_PORT); 263854359Sroberto items = INFO_NITEMS(inpkt->err_nitems); 263954359Sroberto clkaddr = (u_int32 *) inpkt->data; 264054359Sroberto 264154359Sroberto ic = (struct info_clock *)prepare_pkt(srcadr, inter, inpkt, 264254359Sroberto sizeof(struct info_clock)); 264354359Sroberto 264454359Sroberto while (items-- > 0) { 2645132451Sroberto tmp_clock.sin_addr.s_addr = *clkaddr++; 2646132451Sroberto CAST_V4(addr)->sin_addr = tmp_clock.sin_addr; 2647132451Sroberto if (!ISREFCLOCKADR(&tmp_clock) || 264854359Sroberto findexistingpeer(&addr, (struct peer *)0, -1) == 0) { 264954359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 265054359Sroberto return; 265154359Sroberto } 265254359Sroberto 265354359Sroberto clock_stat.kv_list = (struct ctl_var *)0; 265454359Sroberto 265554359Sroberto refclock_control(&addr, (struct refclockstat *)0, &clock_stat); 265654359Sroberto 2657132451Sroberto ic->clockadr = tmp_clock.sin_addr.s_addr; 265854359Sroberto ic->type = clock_stat.type; 265954359Sroberto ic->flags = clock_stat.flags; 266054359Sroberto ic->lastevent = clock_stat.lastevent; 266154359Sroberto ic->currentstatus = clock_stat.currentstatus; 266254359Sroberto ic->polls = htonl((u_int32)clock_stat.polls); 266354359Sroberto ic->noresponse = htonl((u_int32)clock_stat.noresponse); 266454359Sroberto ic->badformat = htonl((u_int32)clock_stat.badformat); 266554359Sroberto ic->baddata = htonl((u_int32)clock_stat.baddata); 266654359Sroberto ic->timestarted = htonl((u_int32)clock_stat.timereset); 266754359Sroberto DTOLFP(clock_stat.fudgetime1, <mp); 266854359Sroberto HTONL_FP(<mp, &ic->fudgetime1); 2669132451Sroberto DTOLFP(clock_stat.fudgetime2, <mp); 267054359Sroberto HTONL_FP(<mp, &ic->fudgetime2); 267154359Sroberto ic->fudgeval1 = htonl((u_int32)clock_stat.fudgeval1); 267254359Sroberto ic->fudgeval2 = htonl((u_int32)clock_stat.fudgeval2); 267354359Sroberto 267454359Sroberto free_varlist(clock_stat.kv_list); 267554359Sroberto 267654359Sroberto ic = (struct info_clock *)more_pkt(); 267754359Sroberto } 267854359Sroberto flush_pkt(); 267954359Sroberto} 268054359Sroberto 268154359Sroberto 268254359Sroberto 268354359Sroberto/* 268454359Sroberto * set_clock_fudge - get a clock's fudge factors 268554359Sroberto */ 268654359Srobertostatic void 268754359Srobertoset_clock_fudge( 2688132451Sroberto struct sockaddr_storage *srcadr, 268954359Sroberto struct interface *inter, 269054359Sroberto struct req_pkt *inpkt 269154359Sroberto ) 269254359Sroberto{ 269354359Sroberto register struct conf_fudge *cf; 269454359Sroberto register int items; 269554359Sroberto struct refclockstat clock_stat; 2696132451Sroberto struct sockaddr_storage addr; 2697132451Sroberto struct sockaddr_in tmp_clock; 269854359Sroberto l_fp ltmp; 269954359Sroberto 270054359Sroberto memset((char *)&addr, 0, sizeof addr); 270154359Sroberto memset((char *)&clock_stat, 0, sizeof clock_stat); 270254359Sroberto items = INFO_NITEMS(inpkt->err_nitems); 270354359Sroberto cf = (struct conf_fudge *) inpkt->data; 270454359Sroberto 270554359Sroberto while (items-- > 0) { 2706132451Sroberto tmp_clock.sin_addr.s_addr = cf->clockadr; 2707132451Sroberto *CAST_V4(addr) = tmp_clock; 2708132451Sroberto addr.ss_family = AF_INET; 2709132451Sroberto#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 2710132451Sroberto addr.ss_len = SOCKLEN(&addr); 2711132451Sroberto#endif 2712132451Sroberto NSRCPORT(&addr) = htons(NTP_PORT); 2713132451Sroberto if (!ISREFCLOCKADR(&tmp_clock) || 271454359Sroberto findexistingpeer(&addr, (struct peer *)0, -1) == 0) { 271554359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 271654359Sroberto return; 271754359Sroberto } 271854359Sroberto 271954359Sroberto switch(ntohl(cf->which)) { 272054359Sroberto case FUDGE_TIME1: 272154359Sroberto NTOHL_FP(&cf->fudgetime, <mp); 272254359Sroberto LFPTOD(<mp, clock_stat.fudgetime1); 272354359Sroberto clock_stat.haveflags = CLK_HAVETIME1; 272454359Sroberto break; 272554359Sroberto case FUDGE_TIME2: 272654359Sroberto NTOHL_FP(&cf->fudgetime, <mp); 272754359Sroberto LFPTOD(<mp, clock_stat.fudgetime2); 272854359Sroberto clock_stat.haveflags = CLK_HAVETIME2; 272954359Sroberto break; 273054359Sroberto case FUDGE_VAL1: 273154359Sroberto clock_stat.fudgeval1 = ntohl(cf->fudgeval_flags); 273254359Sroberto clock_stat.haveflags = CLK_HAVEVAL1; 273354359Sroberto break; 273454359Sroberto case FUDGE_VAL2: 273554359Sroberto clock_stat.fudgeval2 = ntohl(cf->fudgeval_flags); 273654359Sroberto clock_stat.haveflags = CLK_HAVEVAL2; 273754359Sroberto break; 273854359Sroberto case FUDGE_FLAGS: 2739132451Sroberto clock_stat.flags = (u_char) (ntohl(cf->fudgeval_flags) & 0xf); 274054359Sroberto clock_stat.haveflags = 274154359Sroberto (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4); 274254359Sroberto break; 274354359Sroberto default: 274482498Sroberto msyslog(LOG_ERR, "set_clock_fudge: default!"); 274554359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); 274654359Sroberto return; 274754359Sroberto } 274854359Sroberto 274954359Sroberto refclock_control(&addr, &clock_stat, (struct refclockstat *)0); 275054359Sroberto } 275154359Sroberto 275254359Sroberto req_ack(srcadr, inter, inpkt, INFO_OKAY); 275354359Sroberto} 275454359Sroberto#endif 275554359Sroberto 275654359Sroberto#ifdef REFCLOCK 275754359Sroberto/* 275854359Sroberto * get_clkbug_info - get debugging info about a clock 275954359Sroberto */ 276054359Srobertostatic void 276154359Srobertoget_clkbug_info( 2762132451Sroberto struct sockaddr_storage *srcadr, 276354359Sroberto struct interface *inter, 276454359Sroberto struct req_pkt *inpkt 276554359Sroberto ) 276654359Sroberto{ 276754359Sroberto register int i; 276854359Sroberto register struct info_clkbug *ic; 276954359Sroberto register u_int32 *clkaddr; 277054359Sroberto register int items; 277154359Sroberto struct refclockbug bug; 2772132451Sroberto struct sockaddr_storage addr; 2773132451Sroberto struct sockaddr_in tmp_clock; 277454359Sroberto 277554359Sroberto memset((char *)&addr, 0, sizeof addr); 2776132451Sroberto addr.ss_family = AF_INET; 2777132451Sroberto#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR 2778132451Sroberto addr.ss_len = SOCKLEN(&addr); 2779132451Sroberto#endif 2780132451Sroberto NSRCPORT(&addr) = htons(NTP_PORT); 278154359Sroberto items = INFO_NITEMS(inpkt->err_nitems); 278254359Sroberto clkaddr = (u_int32 *) inpkt->data; 278354359Sroberto 278454359Sroberto ic = (struct info_clkbug *)prepare_pkt(srcadr, inter, inpkt, 278554359Sroberto sizeof(struct info_clkbug)); 278654359Sroberto 278754359Sroberto while (items-- > 0) { 2788132451Sroberto tmp_clock.sin_addr.s_addr = *clkaddr++; 2789132451Sroberto GET_INADDR(addr) = tmp_clock.sin_addr.s_addr; 2790132451Sroberto if (!ISREFCLOCKADR(&tmp_clock) || 279154359Sroberto findexistingpeer(&addr, (struct peer *)0, -1) == 0) { 279254359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 279354359Sroberto return; 279454359Sroberto } 279554359Sroberto 279654359Sroberto memset((char *)&bug, 0, sizeof bug); 279754359Sroberto refclock_buginfo(&addr, &bug); 279854359Sroberto if (bug.nvalues == 0 && bug.ntimes == 0) { 279954359Sroberto req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA); 280054359Sroberto return; 280154359Sroberto } 280254359Sroberto 2803132451Sroberto ic->clockadr = tmp_clock.sin_addr.s_addr; 280454359Sroberto i = bug.nvalues; 280554359Sroberto if (i > NUMCBUGVALUES) 280654359Sroberto i = NUMCBUGVALUES; 280754359Sroberto ic->nvalues = (u_char)i; 280854359Sroberto ic->svalues = htons((u_short) (bug.svalues & ((1<<i)-1))); 280954359Sroberto while (--i >= 0) 281054359Sroberto ic->values[i] = htonl(bug.values[i]); 281154359Sroberto 281254359Sroberto i = bug.ntimes; 281354359Sroberto if (i > NUMCBUGTIMES) 281454359Sroberto i = NUMCBUGTIMES; 281554359Sroberto ic->ntimes = (u_char)i; 281654359Sroberto ic->stimes = htonl(bug.stimes); 281754359Sroberto while (--i >= 0) { 281854359Sroberto HTONL_FP(&bug.times[i], &ic->times[i]); 281954359Sroberto } 282054359Sroberto 282154359Sroberto ic = (struct info_clkbug *)more_pkt(); 282254359Sroberto } 282354359Sroberto flush_pkt(); 282454359Sroberto} 282554359Sroberto#endif 2826182007Sroberto 2827182007Sroberto/* 2828182007Sroberto * receiver of interface structures 2829182007Sroberto */ 2830182007Srobertostatic void 2831182007Srobertofill_info_if_stats(void *data, interface_info_t *interface_info) 2832182007Sroberto{ 2833182007Sroberto struct info_if_stats **ifsp = (struct info_if_stats **)data; 2834182007Sroberto struct info_if_stats *ifs = *ifsp; 2835182007Sroberto struct interface *interface = interface_info->interface; 2836182007Sroberto 2837182007Sroberto memset((char*)ifs, 0, sizeof(*ifs)); 2838182007Sroberto 2839182007Sroberto if (interface->sin.ss_family == AF_INET6) { 2840182007Sroberto if (!client_v6_capable) { 2841182007Sroberto return; 2842182007Sroberto } 2843182007Sroberto ifs->v6_flag = 1; 2844182007Sroberto memcpy((char *)&ifs->unaddr.addr6, (char *)&CAST_V6(interface->sin)->sin6_addr, sizeof(struct in6_addr)); 2845182007Sroberto memcpy((char *)&ifs->unbcast.addr6, (char *)&CAST_V6(interface->bcast)->sin6_addr, sizeof(struct in6_addr)); 2846182007Sroberto memcpy((char *)&ifs->unmask.addr6, (char *)&CAST_V6(interface->mask)->sin6_addr, sizeof(struct in6_addr)); 2847182007Sroberto } else { 2848182007Sroberto ifs->v6_flag = 0; 2849182007Sroberto memcpy((char *)&ifs->unaddr.addr, (char *)&CAST_V4(interface->sin)->sin_addr, sizeof(struct in_addr)); 2850182007Sroberto memcpy((char *)&ifs->unbcast.addr, (char *)&CAST_V4(interface->bcast)->sin_addr, sizeof(struct in_addr)); 2851182007Sroberto memcpy((char *)&ifs->unmask.addr, (char *)&CAST_V4(interface->mask)->sin_addr, sizeof(struct in_addr)); 2852182007Sroberto } 2853182007Sroberto ifs->v6_flag = htonl(ifs->v6_flag); 2854182007Sroberto strcpy(ifs->name, interface->name); 2855182007Sroberto ifs->family = htons(interface->family); 2856182007Sroberto ifs->flags = htonl(interface->flags); 2857182007Sroberto ifs->last_ttl = htonl(interface->last_ttl); 2858182007Sroberto ifs->num_mcast = htonl(interface->num_mcast); 2859182007Sroberto ifs->received = htonl(interface->received); 2860182007Sroberto ifs->sent = htonl(interface->sent); 2861182007Sroberto ifs->notsent = htonl(interface->notsent); 2862182007Sroberto ifs->scopeid = htonl(interface->scopeid); 2863182007Sroberto ifs->ifindex = htonl(interface->ifindex); 2864182007Sroberto ifs->ifnum = htonl(interface->ifnum); 2865182007Sroberto ifs->uptime = htonl(current_time - interface->starttime); 2866182007Sroberto ifs->ignore_packets = interface->ignore_packets; 2867182007Sroberto ifs->peercnt = htonl(interface->peercnt); 2868182007Sroberto ifs->action = interface_info->action; 2869182007Sroberto 2870182007Sroberto *ifsp = (struct info_if_stats *)more_pkt(); 2871182007Sroberto} 2872182007Sroberto 2873182007Sroberto/* 2874182007Sroberto * get_if_stats - get interface statistics 2875182007Sroberto */ 2876182007Srobertostatic void 2877182007Srobertoget_if_stats( 2878182007Sroberto struct sockaddr_storage *srcadr, 2879182007Sroberto struct interface *inter, 2880182007Sroberto struct req_pkt *inpkt 2881182007Sroberto ) 2882182007Sroberto{ 2883182007Sroberto struct info_if_stats *ifs; 2884182007Sroberto 2885182007Sroberto DPRINTF(3, ("wants interface statistics\n")); 2886182007Sroberto 2887182007Sroberto ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt, 2888182007Sroberto v6sizeof(struct info_if_stats)); 2889182007Sroberto 2890182007Sroberto interface_enumerate(fill_info_if_stats, &ifs); 2891182007Sroberto 2892182007Sroberto flush_pkt(); 2893182007Sroberto} 2894182007Sroberto 2895182007Srobertostatic void 2896182007Srobertodo_if_reload( 2897182007Sroberto struct sockaddr_storage *srcadr, 2898182007Sroberto struct interface *inter, 2899182007Sroberto struct req_pkt *inpkt 2900182007Sroberto ) 2901182007Sroberto{ 2902182007Sroberto struct info_if_stats *ifs; 2903182007Sroberto 2904182007Sroberto DPRINTF(3, ("wants interface reload\n")); 2905182007Sroberto 2906182007Sroberto ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt, 2907182007Sroberto v6sizeof(struct info_if_stats)); 2908182007Sroberto 2909182007Sroberto interface_update(fill_info_if_stats, &ifs); 2910182007Sroberto 2911182007Sroberto flush_pkt(); 2912182007Sroberto} 2913182007Sroberto 2914