Annotation of embedaddon/ntp/ntpd/ntp_request.c, revision 1.1
1.1 ! misho 1: /*
! 2: * ntp_request.c - respond to information requests
! 3: */
! 4:
! 5: #ifdef HAVE_CONFIG_H
! 6: # include <config.h>
! 7: #endif
! 8:
! 9: #include "ntpd.h"
! 10: #include "ntp_io.h"
! 11: #include "ntp_request.h"
! 12: #include "ntp_control.h"
! 13: #include "ntp_refclock.h"
! 14: #include "ntp_if.h"
! 15: #include "ntp_stdlib.h"
! 16: #include "ntp_assert.h"
! 17:
! 18: #include <stdio.h>
! 19: #include <stddef.h>
! 20: #include <signal.h>
! 21: #ifdef HAVE_NETINET_IN_H
! 22: #include <netinet/in.h>
! 23: #endif
! 24: #include <arpa/inet.h>
! 25:
! 26: #include "recvbuff.h"
! 27:
! 28: #ifdef KERNEL_PLL
! 29: #include "ntp_syscall.h"
! 30: #endif /* KERNEL_PLL */
! 31:
! 32: /*
! 33: * Structure to hold request procedure information
! 34: */
! 35: #define NOAUTH 0
! 36: #define AUTH 1
! 37:
! 38: #define NO_REQUEST (-1)
! 39: /*
! 40: * Because we now have v6 addresses in the messages, we need to compensate
! 41: * for the larger size. Therefore, we introduce the alternate size to
! 42: * keep us friendly with older implementations. A little ugly.
! 43: */
! 44: static int client_v6_capable = 0; /* the client can handle longer messages */
! 45:
! 46: #define v6sizeof(type) (client_v6_capable ? sizeof(type) : v4sizeof(type))
! 47:
! 48: struct req_proc {
! 49: short request_code; /* defined request code */
! 50: short needs_auth; /* true when authentication needed */
! 51: short sizeofitem; /* size of request data item (older size)*/
! 52: short v6_sizeofitem; /* size of request data item (new size)*/
! 53: void (*handler) (sockaddr_u *, struct interface *,
! 54: struct req_pkt *); /* routine to handle request */
! 55: };
! 56:
! 57: /*
! 58: * Universal request codes
! 59: */
! 60: static struct req_proc univ_codes[] = {
! 61: { NO_REQUEST, NOAUTH, 0, 0 }
! 62: };
! 63:
! 64: static void req_ack (sockaddr_u *, struct interface *, struct req_pkt *, int);
! 65: static char * prepare_pkt (sockaddr_u *, struct interface *,
! 66: struct req_pkt *, size_t);
! 67: static char * more_pkt (void);
! 68: static void flush_pkt (void);
! 69: static void peer_list (sockaddr_u *, struct interface *, struct req_pkt *);
! 70: static void peer_list_sum (sockaddr_u *, struct interface *, struct req_pkt *);
! 71: static void peer_info (sockaddr_u *, struct interface *, struct req_pkt *);
! 72: static void peer_stats (sockaddr_u *, struct interface *, struct req_pkt *);
! 73: static void sys_info (sockaddr_u *, struct interface *, struct req_pkt *);
! 74: static void sys_stats (sockaddr_u *, struct interface *, struct req_pkt *);
! 75: static void mem_stats (sockaddr_u *, struct interface *, struct req_pkt *);
! 76: static void io_stats (sockaddr_u *, struct interface *, struct req_pkt *);
! 77: static void timer_stats (sockaddr_u *, struct interface *, struct req_pkt *);
! 78: static void loop_info (sockaddr_u *, struct interface *, struct req_pkt *);
! 79: static void do_conf (sockaddr_u *, struct interface *, struct req_pkt *);
! 80: static void do_unconf (sockaddr_u *, struct interface *, struct req_pkt *);
! 81: static void set_sys_flag (sockaddr_u *, struct interface *, struct req_pkt *);
! 82: static void clr_sys_flag (sockaddr_u *, struct interface *, struct req_pkt *);
! 83: static void setclr_flags (sockaddr_u *, struct interface *, struct req_pkt *, u_long);
! 84: static void list_restrict (sockaddr_u *, struct interface *, struct req_pkt *);
! 85: static void do_resaddflags (sockaddr_u *, struct interface *, struct req_pkt *);
! 86: static void do_ressubflags (sockaddr_u *, struct interface *, struct req_pkt *);
! 87: static void do_unrestrict (sockaddr_u *, struct interface *, struct req_pkt *);
! 88: static void do_restrict (sockaddr_u *, struct interface *, struct req_pkt *, int);
! 89: static void mon_getlist_0 (sockaddr_u *, struct interface *, struct req_pkt *);
! 90: static void mon_getlist_1 (sockaddr_u *, struct interface *, struct req_pkt *);
! 91: static void reset_stats (sockaddr_u *, struct interface *, struct req_pkt *);
! 92: static void reset_peer (sockaddr_u *, struct interface *, struct req_pkt *);
! 93: static void do_key_reread (sockaddr_u *, struct interface *, struct req_pkt *);
! 94: static void trust_key (sockaddr_u *, struct interface *, struct req_pkt *);
! 95: static void untrust_key (sockaddr_u *, struct interface *, struct req_pkt *);
! 96: static void do_trustkey (sockaddr_u *, struct interface *, struct req_pkt *, u_long);
! 97: static void get_auth_info (sockaddr_u *, struct interface *, struct req_pkt *);
! 98: static void reset_auth_stats (void);
! 99: static void req_get_traps (sockaddr_u *, struct interface *, struct req_pkt *);
! 100: static void req_set_trap (sockaddr_u *, struct interface *, struct req_pkt *);
! 101: static void req_clr_trap (sockaddr_u *, struct interface *, struct req_pkt *);
! 102: static void do_setclr_trap (sockaddr_u *, struct interface *, struct req_pkt *, int);
! 103: static void set_request_keyid (sockaddr_u *, struct interface *, struct req_pkt *);
! 104: static void set_control_keyid (sockaddr_u *, struct interface *, struct req_pkt *);
! 105: static void get_ctl_stats (sockaddr_u *, struct interface *, struct req_pkt *);
! 106: static void get_if_stats (sockaddr_u *, struct interface *, struct req_pkt *);
! 107: static void do_if_reload (sockaddr_u *, struct interface *, struct req_pkt *);
! 108: #ifdef KERNEL_PLL
! 109: static void get_kernel_info (sockaddr_u *, struct interface *, struct req_pkt *);
! 110: #endif /* KERNEL_PLL */
! 111: #ifdef REFCLOCK
! 112: static void get_clock_info (sockaddr_u *, struct interface *, struct req_pkt *);
! 113: static void set_clock_fudge (sockaddr_u *, struct interface *, struct req_pkt *);
! 114: #endif /* REFCLOCK */
! 115: #ifdef REFCLOCK
! 116: static void get_clkbug_info (sockaddr_u *, struct interface *, struct req_pkt *);
! 117: #endif /* REFCLOCK */
! 118:
! 119: /*
! 120: * ntpd request codes
! 121: */
! 122: static struct req_proc ntp_codes[] = {
! 123: { REQ_PEER_LIST, NOAUTH, 0, 0, peer_list },
! 124: { REQ_PEER_LIST_SUM, NOAUTH, 0, 0, peer_list_sum },
! 125: { REQ_PEER_INFO, NOAUTH, v4sizeof(struct info_peer_list),
! 126: sizeof(struct info_peer_list), peer_info},
! 127: { REQ_PEER_STATS, NOAUTH, v4sizeof(struct info_peer_list),
! 128: sizeof(struct info_peer_list), peer_stats},
! 129: { REQ_SYS_INFO, NOAUTH, 0, 0, sys_info },
! 130: { REQ_SYS_STATS, NOAUTH, 0, 0, sys_stats },
! 131: { REQ_IO_STATS, NOAUTH, 0, 0, io_stats },
! 132: { REQ_MEM_STATS, NOAUTH, 0, 0, mem_stats },
! 133: { REQ_LOOP_INFO, NOAUTH, 0, 0, loop_info },
! 134: { REQ_TIMER_STATS, NOAUTH, 0, 0, timer_stats },
! 135: { REQ_CONFIG, AUTH, v4sizeof(struct conf_peer),
! 136: sizeof(struct conf_peer), do_conf },
! 137: { REQ_UNCONFIG, AUTH, v4sizeof(struct conf_unpeer),
! 138: sizeof(struct conf_unpeer), do_unconf },
! 139: { REQ_SET_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags),
! 140: sizeof(struct conf_sys_flags), set_sys_flag },
! 141: { REQ_CLR_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags),
! 142: sizeof(struct conf_sys_flags), clr_sys_flag },
! 143: { REQ_GET_RESTRICT, NOAUTH, 0, 0, list_restrict },
! 144: { REQ_RESADDFLAGS, AUTH, v4sizeof(struct conf_restrict),
! 145: sizeof(struct conf_restrict), do_resaddflags },
! 146: { REQ_RESSUBFLAGS, AUTH, v4sizeof(struct conf_restrict),
! 147: sizeof(struct conf_restrict), do_ressubflags },
! 148: { REQ_UNRESTRICT, AUTH, v4sizeof(struct conf_restrict),
! 149: sizeof(struct conf_restrict), do_unrestrict },
! 150: { REQ_MON_GETLIST, NOAUTH, 0, 0, mon_getlist_0 },
! 151: { REQ_MON_GETLIST_1, NOAUTH, 0, 0, mon_getlist_1 },
! 152: { REQ_RESET_STATS, AUTH, sizeof(struct reset_flags), 0, reset_stats },
! 153: { REQ_RESET_PEER, AUTH, v4sizeof(struct conf_unpeer),
! 154: sizeof(struct conf_unpeer), reset_peer },
! 155: { REQ_REREAD_KEYS, AUTH, 0, 0, do_key_reread },
! 156: { REQ_TRUSTKEY, AUTH, sizeof(u_long), sizeof(u_long), trust_key },
! 157: { REQ_UNTRUSTKEY, AUTH, sizeof(u_long), sizeof(u_long), untrust_key },
! 158: { REQ_AUTHINFO, NOAUTH, 0, 0, get_auth_info },
! 159: { REQ_TRAPS, NOAUTH, 0, 0, req_get_traps },
! 160: { REQ_ADD_TRAP, AUTH, v4sizeof(struct conf_trap),
! 161: sizeof(struct conf_trap), req_set_trap },
! 162: { REQ_CLR_TRAP, AUTH, v4sizeof(struct conf_trap),
! 163: sizeof(struct conf_trap), req_clr_trap },
! 164: { REQ_REQUEST_KEY, AUTH, sizeof(u_long), sizeof(u_long),
! 165: set_request_keyid },
! 166: { REQ_CONTROL_KEY, AUTH, sizeof(u_long), sizeof(u_long),
! 167: set_control_keyid },
! 168: { REQ_GET_CTLSTATS, NOAUTH, 0, 0, get_ctl_stats },
! 169: #ifdef KERNEL_PLL
! 170: { REQ_GET_KERNEL, NOAUTH, 0, 0, get_kernel_info },
! 171: #endif
! 172: #ifdef REFCLOCK
! 173: { REQ_GET_CLOCKINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32),
! 174: get_clock_info },
! 175: { REQ_SET_CLKFUDGE, AUTH, sizeof(struct conf_fudge),
! 176: sizeof(struct conf_fudge), set_clock_fudge },
! 177: { REQ_GET_CLKBUGINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32),
! 178: get_clkbug_info },
! 179: #endif
! 180: { REQ_IF_STATS, AUTH, 0, 0, get_if_stats },
! 181: { REQ_IF_RELOAD, AUTH, 0, 0, do_if_reload },
! 182:
! 183: { NO_REQUEST, NOAUTH, 0, 0, 0 }
! 184: };
! 185:
! 186:
! 187: /*
! 188: * Authentication keyid used to authenticate requests. Zero means we
! 189: * don't allow writing anything.
! 190: */
! 191: keyid_t info_auth_keyid;
! 192:
! 193: /*
! 194: * Statistic counters to keep track of requests and responses.
! 195: */
! 196: u_long numrequests; /* number of requests we've received */
! 197: u_long numresppkts; /* number of resp packets sent with data */
! 198:
! 199: u_long errorcounter[INFO_ERR_AUTH+1]; /* lazy way to count errors, indexed */
! 200: /* by the error code */
! 201:
! 202: /*
! 203: * A hack. To keep the authentication module clear of ntp-ism's, we
! 204: * include a time reset variable for its stats here.
! 205: */
! 206: static u_long auth_timereset;
! 207:
! 208: /*
! 209: * Response packet used by these routines. Also some state information
! 210: * so that we can handle packet formatting within a common set of
! 211: * subroutines. Note we try to enter data in place whenever possible,
! 212: * but the need to set the more bit correctly means we occasionally
! 213: * use the extra buffer and copy.
! 214: */
! 215: static struct resp_pkt rpkt;
! 216: static int reqver;
! 217: static int seqno;
! 218: static int nitems;
! 219: static int itemsize;
! 220: static int databytes;
! 221: static char exbuf[RESP_DATA_SIZE];
! 222: static int usingexbuf;
! 223: static sockaddr_u *toaddr;
! 224: static struct interface *frominter;
! 225:
! 226: /*
! 227: * init_request - initialize request data
! 228: */
! 229: void
! 230: init_request (void)
! 231: {
! 232: int i;
! 233:
! 234: numrequests = 0;
! 235: numresppkts = 0;
! 236: auth_timereset = 0;
! 237: info_auth_keyid = 0; /* by default, can't do this */
! 238:
! 239: for (i = 0; i < sizeof(errorcounter)/sizeof(errorcounter[0]); i++)
! 240: errorcounter[i] = 0;
! 241: }
! 242:
! 243:
! 244: /*
! 245: * req_ack - acknowledge request with no data
! 246: */
! 247: static void
! 248: req_ack(
! 249: sockaddr_u *srcadr,
! 250: struct interface *inter,
! 251: struct req_pkt *inpkt,
! 252: int errcode
! 253: )
! 254: {
! 255: /*
! 256: * fill in the fields
! 257: */
! 258: rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver);
! 259: rpkt.auth_seq = AUTH_SEQ(0, 0);
! 260: rpkt.implementation = inpkt->implementation;
! 261: rpkt.request = inpkt->request;
! 262: rpkt.err_nitems = ERR_NITEMS(errcode, 0);
! 263: rpkt.mbz_itemsize = MBZ_ITEMSIZE(0);
! 264:
! 265: /*
! 266: * send packet and bump counters
! 267: */
! 268: sendpkt(srcadr, inter, -1, (struct pkt *)&rpkt, RESP_HEADER_SIZE);
! 269: errorcounter[errcode]++;
! 270: }
! 271:
! 272:
! 273: /*
! 274: * prepare_pkt - prepare response packet for transmission, return pointer
! 275: * to storage for data item.
! 276: */
! 277: static char *
! 278: prepare_pkt(
! 279: sockaddr_u *srcadr,
! 280: struct interface *inter,
! 281: struct req_pkt *pkt,
! 282: size_t structsize
! 283: )
! 284: {
! 285: DPRINTF(4, ("request: preparing pkt\n"));
! 286:
! 287: /*
! 288: * Fill in the implementation, request and itemsize fields
! 289: * since these won't change.
! 290: */
! 291: rpkt.implementation = pkt->implementation;
! 292: rpkt.request = pkt->request;
! 293: rpkt.mbz_itemsize = MBZ_ITEMSIZE(structsize);
! 294:
! 295: /*
! 296: * Compute the static data needed to carry on.
! 297: */
! 298: toaddr = srcadr;
! 299: frominter = inter;
! 300: seqno = 0;
! 301: nitems = 0;
! 302: itemsize = structsize;
! 303: databytes = 0;
! 304: usingexbuf = 0;
! 305:
! 306: /*
! 307: * return the beginning of the packet buffer.
! 308: */
! 309: return &rpkt.data[0];
! 310: }
! 311:
! 312:
! 313: /*
! 314: * more_pkt - return a data pointer for a new item.
! 315: */
! 316: static char *
! 317: more_pkt(void)
! 318: {
! 319: /*
! 320: * If we were using the extra buffer, send the packet.
! 321: */
! 322: if (usingexbuf) {
! 323: DPRINTF(3, ("request: sending pkt\n"));
! 324: rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, MORE_BIT, reqver);
! 325: rpkt.auth_seq = AUTH_SEQ(0, seqno);
! 326: rpkt.err_nitems = htons((u_short)nitems);
! 327: sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt,
! 328: RESP_HEADER_SIZE + databytes);
! 329: numresppkts++;
! 330:
! 331: /*
! 332: * Copy data out of exbuf into the packet.
! 333: */
! 334: memcpy(&rpkt.data[0], exbuf, (unsigned)itemsize);
! 335: seqno++;
! 336: databytes = 0;
! 337: nitems = 0;
! 338: usingexbuf = 0;
! 339: }
! 340:
! 341: databytes += itemsize;
! 342: nitems++;
! 343: if (databytes + itemsize <= RESP_DATA_SIZE) {
! 344: DPRINTF(4, ("request: giving him more data\n"));
! 345: /*
! 346: * More room in packet. Give him the
! 347: * next address.
! 348: */
! 349: return &rpkt.data[databytes];
! 350: } else {
! 351: /*
! 352: * No room in packet. Give him the extra
! 353: * buffer unless this was the last in the sequence.
! 354: */
! 355: DPRINTF(4, ("request: into extra buffer\n"));
! 356: if (seqno == MAXSEQ)
! 357: return NULL;
! 358: else {
! 359: usingexbuf = 1;
! 360: return exbuf;
! 361: }
! 362: }
! 363: }
! 364:
! 365:
! 366: /*
! 367: * flush_pkt - we're done, return remaining information.
! 368: */
! 369: static void
! 370: flush_pkt(void)
! 371: {
! 372: DPRINTF(3, ("request: flushing packet, %d items\n", nitems));
! 373: /*
! 374: * Must send the last packet. If nothing in here and nothing
! 375: * has been sent, send an error saying no data to be found.
! 376: */
! 377: if (seqno == 0 && nitems == 0)
! 378: req_ack(toaddr, frominter, (struct req_pkt *)&rpkt,
! 379: INFO_ERR_NODATA);
! 380: else {
! 381: rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver);
! 382: rpkt.auth_seq = AUTH_SEQ(0, seqno);
! 383: rpkt.err_nitems = htons((u_short)nitems);
! 384: sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt,
! 385: RESP_HEADER_SIZE+databytes);
! 386: numresppkts++;
! 387: }
! 388: }
! 389:
! 390:
! 391:
! 392: /*
! 393: * Given a buffer, return the packet mode
! 394: */
! 395: int
! 396: get_packet_mode(struct recvbuf *rbufp)
! 397: {
! 398: struct req_pkt *inpkt = (struct req_pkt *)&rbufp->recv_pkt;
! 399: return (INFO_MODE(inpkt->rm_vn_mode));
! 400: }
! 401:
! 402:
! 403: /*
! 404: * process_private - process private mode (7) packets
! 405: */
! 406: void
! 407: process_private(
! 408: struct recvbuf *rbufp,
! 409: int mod_okay
! 410: )
! 411: {
! 412: static u_long quiet_until;
! 413: struct req_pkt *inpkt;
! 414: struct req_pkt_tail *tailinpkt;
! 415: sockaddr_u *srcadr;
! 416: struct interface *inter;
! 417: struct req_proc *proc;
! 418: int ec;
! 419: short temp_size;
! 420: l_fp ftmp;
! 421: double dtemp;
! 422: size_t recv_len;
! 423: size_t noslop_len;
! 424: size_t mac_len;
! 425:
! 426: /*
! 427: * Initialize pointers, for convenience
! 428: */
! 429: recv_len = rbufp->recv_length;
! 430: inpkt = (struct req_pkt *)&rbufp->recv_pkt;
! 431: srcadr = &rbufp->recv_srcadr;
! 432: inter = rbufp->dstadr;
! 433:
! 434: DPRINTF(3, ("process_private: impl %d req %d\n",
! 435: inpkt->implementation, inpkt->request));
! 436:
! 437: /*
! 438: * Do some sanity checks on the packet. Return a format
! 439: * error if it fails.
! 440: */
! 441: ec = 0;
! 442: if ( (++ec, ISRESPONSE(inpkt->rm_vn_mode))
! 443: || (++ec, ISMORE(inpkt->rm_vn_mode))
! 444: || (++ec, INFO_VERSION(inpkt->rm_vn_mode) > NTP_VERSION)
! 445: || (++ec, INFO_VERSION(inpkt->rm_vn_mode) < NTP_OLDVERSION)
! 446: || (++ec, INFO_SEQ(inpkt->auth_seq) != 0)
! 447: || (++ec, INFO_ERR(inpkt->err_nitems) != 0)
! 448: || (++ec, INFO_MBZ(inpkt->mbz_itemsize) != 0)
! 449: || (++ec, rbufp->recv_length < REQ_LEN_HDR)
! 450: ) {
! 451: NLOG(NLOG_SYSEVENT)
! 452: if (current_time >= quiet_until) {
! 453: msyslog(LOG_ERR,
! 454: "process_private: drop test %d"
! 455: " failed, pkt from %s",
! 456: ec, stoa(srcadr));
! 457: quiet_until = current_time + 60;
! 458: }
! 459: return;
! 460: }
! 461:
! 462: reqver = INFO_VERSION(inpkt->rm_vn_mode);
! 463:
! 464: /*
! 465: * Get the appropriate procedure list to search.
! 466: */
! 467: if (inpkt->implementation == IMPL_UNIV)
! 468: proc = univ_codes;
! 469: else if ((inpkt->implementation == IMPL_XNTPD) ||
! 470: (inpkt->implementation == IMPL_XNTPD_OLD))
! 471: proc = ntp_codes;
! 472: else {
! 473: req_ack(srcadr, inter, inpkt, INFO_ERR_IMPL);
! 474: return;
! 475: }
! 476:
! 477: /*
! 478: * Search the list for the request codes. If it isn't one
! 479: * we know, return an error.
! 480: */
! 481: while (proc->request_code != NO_REQUEST) {
! 482: if (proc->request_code == (short) inpkt->request)
! 483: break;
! 484: proc++;
! 485: }
! 486: if (proc->request_code == NO_REQUEST) {
! 487: req_ack(srcadr, inter, inpkt, INFO_ERR_REQ);
! 488: return;
! 489: }
! 490:
! 491: DPRINTF(4, ("found request in tables\n"));
! 492:
! 493: /*
! 494: * If we need data, check to see if we have some. If we
! 495: * don't, check to see that there is none (picky, picky).
! 496: */
! 497:
! 498: /* This part is a bit tricky, we want to be sure that the size
! 499: * returned is either the old or the new size. We also can find
! 500: * out if the client can accept both types of messages this way.
! 501: *
! 502: * Handle the exception of REQ_CONFIG. It can have two data sizes.
! 503: */
! 504: temp_size = INFO_ITEMSIZE(inpkt->mbz_itemsize);
! 505: if ((temp_size != proc->sizeofitem &&
! 506: temp_size != proc->v6_sizeofitem) &&
! 507: !(inpkt->implementation == IMPL_XNTPD &&
! 508: inpkt->request == REQ_CONFIG &&
! 509: temp_size == sizeof(struct old_conf_peer))) {
! 510: DPRINTF(3, ("process_private: wrong item size, received %d, should be %d or %d\n",
! 511: temp_size, proc->sizeofitem, proc->v6_sizeofitem));
! 512: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
! 513: return;
! 514: }
! 515: if ((proc->sizeofitem != 0) &&
! 516: ((size_t)(temp_size * INFO_NITEMS(inpkt->err_nitems)) >
! 517: (recv_len - REQ_LEN_HDR))) {
! 518: DPRINTF(3, ("process_private: not enough data\n"));
! 519: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
! 520: return;
! 521: }
! 522:
! 523: switch (inpkt->implementation) {
! 524: case IMPL_XNTPD:
! 525: client_v6_capable = 1;
! 526: break;
! 527: case IMPL_XNTPD_OLD:
! 528: client_v6_capable = 0;
! 529: break;
! 530: default:
! 531: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
! 532: return;
! 533: }
! 534:
! 535: /*
! 536: * If we need to authenticate, do so. Note that an
! 537: * authenticatable packet must include a mac field, must
! 538: * have used key info_auth_keyid and must have included
! 539: * a time stamp in the appropriate field. The time stamp
! 540: * must be within INFO_TS_MAXSKEW of the receive
! 541: * time stamp.
! 542: */
! 543: if (proc->needs_auth && sys_authenticate) {
! 544:
! 545: if (recv_len < (REQ_LEN_HDR +
! 546: (INFO_ITEMSIZE(inpkt->mbz_itemsize) *
! 547: INFO_NITEMS(inpkt->err_nitems)) +
! 548: REQ_TAIL_MIN)) {
! 549: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
! 550: return;
! 551: }
! 552:
! 553: /*
! 554: * For 16-octet digests, regardless of itemsize and
! 555: * nitems, authenticated requests are a fixed size
! 556: * with the timestamp, key ID, and digest located
! 557: * at the end of the packet. Because the key ID
! 558: * determining the digest size precedes the digest,
! 559: * for larger digests the fixed size request scheme
! 560: * is abandoned and the timestamp, key ID, and digest
! 561: * are located relative to the start of the packet,
! 562: * with the digest size determined by the packet size.
! 563: */
! 564: noslop_len = REQ_LEN_HDR
! 565: + INFO_ITEMSIZE(inpkt->mbz_itemsize) *
! 566: INFO_NITEMS(inpkt->err_nitems)
! 567: + sizeof(inpkt->tstamp);
! 568: /* 32-bit alignment */
! 569: noslop_len = (noslop_len + 3) & ~3;
! 570: if (recv_len > (noslop_len + MAX_MAC_LEN))
! 571: mac_len = 20;
! 572: else
! 573: mac_len = recv_len - noslop_len;
! 574:
! 575: tailinpkt = (void *)((char *)inpkt + recv_len -
! 576: (mac_len + sizeof(inpkt->tstamp)));
! 577:
! 578: /*
! 579: * If this guy is restricted from doing this, don't let
! 580: * him. If the wrong key was used, or packet doesn't
! 581: * have mac, return.
! 582: */
! 583: if (!INFO_IS_AUTH(inpkt->auth_seq) || !info_auth_keyid
! 584: || ntohl(tailinpkt->keyid) != info_auth_keyid) {
! 585: DPRINTF(5, ("failed auth %d info_auth_keyid %u pkt keyid %u maclen %lu\n",
! 586: INFO_IS_AUTH(inpkt->auth_seq),
! 587: info_auth_keyid,
! 588: ntohl(tailinpkt->keyid), (u_long)mac_len));
! 589: #ifdef DEBUG
! 590: msyslog(LOG_DEBUG,
! 591: "process_private: failed auth %d info_auth_keyid %u pkt keyid %u maclen %lu\n",
! 592: INFO_IS_AUTH(inpkt->auth_seq),
! 593: info_auth_keyid,
! 594: ntohl(tailinpkt->keyid), (u_long)mac_len);
! 595: #endif
! 596: req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
! 597: return;
! 598: }
! 599: if (recv_len > REQ_LEN_NOMAC + MAX_MAC_LEN) {
! 600: DPRINTF(5, ("bad pkt length %lu\n",
! 601: (u_long)recv_len));
! 602: msyslog(LOG_ERR,
! 603: "process_private: bad pkt length %lu",
! 604: (u_long)recv_len);
! 605: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
! 606: return;
! 607: }
! 608: if (!mod_okay || !authhavekey(info_auth_keyid)) {
! 609: DPRINTF(5, ("failed auth mod_okay %d\n",
! 610: mod_okay));
! 611: #ifdef DEBUG
! 612: msyslog(LOG_DEBUG,
! 613: "process_private: failed auth mod_okay %d\n",
! 614: mod_okay);
! 615: #endif
! 616: req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
! 617: return;
! 618: }
! 619:
! 620: /*
! 621: * calculate absolute time difference between xmit time stamp
! 622: * and receive time stamp. If too large, too bad.
! 623: */
! 624: NTOHL_FP(&tailinpkt->tstamp, &ftmp);
! 625: L_SUB(&ftmp, &rbufp->recv_time);
! 626: LFPTOD(&ftmp, dtemp);
! 627: if (fabs(dtemp) > INFO_TS_MAXSKEW) {
! 628: /*
! 629: * He's a loser. Tell him.
! 630: */
! 631: DPRINTF(5, ("xmit/rcv timestamp delta %g > INFO_TS_MAXSKEW %g\n",
! 632: dtemp, INFO_TS_MAXSKEW));
! 633: req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
! 634: return;
! 635: }
! 636:
! 637: /*
! 638: * So far so good. See if decryption works out okay.
! 639: */
! 640: if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt,
! 641: recv_len - mac_len, mac_len)) {
! 642: DPRINTF(5, ("authdecrypt failed\n"));
! 643: req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
! 644: return;
! 645: }
! 646: }
! 647:
! 648: DPRINTF(3, ("process_private: all okay, into handler\n"));
! 649: /*
! 650: * Packet is okay. Call the handler to send him data.
! 651: */
! 652: (proc->handler)(srcadr, inter, inpkt);
! 653: }
! 654:
! 655:
! 656: /*
! 657: * peer_list - send a list of the peers
! 658: */
! 659: static void
! 660: peer_list(
! 661: sockaddr_u *srcadr,
! 662: struct interface *inter,
! 663: struct req_pkt *inpkt
! 664: )
! 665: {
! 666: register struct info_peer_list *ip;
! 667: register struct peer *pp;
! 668: register int i;
! 669: register int skip = 0;
! 670:
! 671: ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt,
! 672: v6sizeof(struct info_peer_list));
! 673: for (i = 0; i < NTP_HASH_SIZE && ip != 0; i++) {
! 674: pp = peer_hash[i];
! 675: while (pp != 0 && ip != 0) {
! 676: if (IS_IPV6(&pp->srcadr)) {
! 677: if (client_v6_capable) {
! 678: ip->addr6 = SOCK_ADDR6(&pp->srcadr);
! 679: ip->v6_flag = 1;
! 680: skip = 0;
! 681: } else {
! 682: skip = 1;
! 683: break;
! 684: }
! 685: } else {
! 686: ip->addr = NSRCADR(&pp->srcadr);
! 687: if (client_v6_capable)
! 688: ip->v6_flag = 0;
! 689: skip = 0;
! 690: }
! 691:
! 692: if(!skip) {
! 693: ip->port = NSRCPORT(&pp->srcadr);
! 694: ip->hmode = pp->hmode;
! 695: ip->flags = 0;
! 696: if (pp->flags & FLAG_CONFIG)
! 697: ip->flags |= INFO_FLAG_CONFIG;
! 698: if (pp == sys_peer)
! 699: ip->flags |= INFO_FLAG_SYSPEER;
! 700: if (pp->status == CTL_PST_SEL_SYNCCAND)
! 701: ip->flags |= INFO_FLAG_SEL_CANDIDATE;
! 702: if (pp->status >= CTL_PST_SEL_SYSPEER)
! 703: ip->flags |= INFO_FLAG_SHORTLIST;
! 704: ip = (struct info_peer_list *)more_pkt();
! 705: }
! 706: pp = pp->next;
! 707: }
! 708: }
! 709: flush_pkt();
! 710: }
! 711:
! 712:
! 713: /*
! 714: * peer_list_sum - return extended peer list
! 715: */
! 716: static void
! 717: peer_list_sum(
! 718: sockaddr_u *srcadr,
! 719: struct interface *inter,
! 720: struct req_pkt *inpkt
! 721: )
! 722: {
! 723: register struct info_peer_summary *ips;
! 724: register struct peer *pp;
! 725: register int i;
! 726: l_fp ltmp;
! 727: register int skip;
! 728:
! 729: #ifdef DEBUG
! 730: if (debug > 2)
! 731: printf("wants peer list summary\n");
! 732: #endif
! 733: ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt,
! 734: v6sizeof(struct info_peer_summary));
! 735: for (i = 0; i < NTP_HASH_SIZE && ips != 0; i++) {
! 736: pp = peer_hash[i];
! 737: while (pp != 0 && ips != 0) {
! 738: #ifdef DEBUG
! 739: if (debug > 3)
! 740: printf("sum: got one\n");
! 741: #endif
! 742: /*
! 743: * Be careful here not to return v6 peers when we
! 744: * want only v4.
! 745: */
! 746: if (IS_IPV6(&pp->srcadr)) {
! 747: if (client_v6_capable) {
! 748: ips->srcadr6 = SOCK_ADDR6(&pp->srcadr);
! 749: ips->v6_flag = 1;
! 750: if (pp->dstadr)
! 751: ips->dstadr6 = SOCK_ADDR6(&pp->dstadr->sin);
! 752: else
! 753: memset(&ips->dstadr6, 0, sizeof(ips->dstadr6));
! 754: skip = 0;
! 755: } else {
! 756: skip = 1;
! 757: break;
! 758: }
! 759: } else {
! 760: ips->srcadr = NSRCADR(&pp->srcadr);
! 761: if (client_v6_capable)
! 762: ips->v6_flag = 0;
! 763:
! 764: if (pp->dstadr) {
! 765: if (!pp->processed)
! 766: ips->dstadr = NSRCADR(&pp->dstadr->sin);
! 767: else {
! 768: if (MDF_BCAST == pp->cast_flags)
! 769: ips->dstadr = NSRCADR(&pp->dstadr->bcast);
! 770: else if (pp->cast_flags) {
! 771: ips->dstadr = NSRCADR(&pp->dstadr->sin);
! 772: if (!ips->dstadr)
! 773: ips->dstadr = NSRCADR(&pp->dstadr->bcast);
! 774: }
! 775: }
! 776: } else
! 777: ips->dstadr = 0;
! 778:
! 779: skip = 0;
! 780: }
! 781:
! 782: if (!skip){
! 783: ips->srcport = NSRCPORT(&pp->srcadr);
! 784: ips->stratum = pp->stratum;
! 785: ips->hpoll = pp->hpoll;
! 786: ips->ppoll = pp->ppoll;
! 787: ips->reach = pp->reach;
! 788: ips->flags = 0;
! 789: if (pp == sys_peer)
! 790: ips->flags |= INFO_FLAG_SYSPEER;
! 791: if (pp->flags & FLAG_CONFIG)
! 792: ips->flags |= INFO_FLAG_CONFIG;
! 793: if (pp->flags & FLAG_REFCLOCK)
! 794: ips->flags |= INFO_FLAG_REFCLOCK;
! 795: if (pp->flags & FLAG_PREFER)
! 796: ips->flags |= INFO_FLAG_PREFER;
! 797: if (pp->flags & FLAG_BURST)
! 798: ips->flags |= INFO_FLAG_BURST;
! 799: if (pp->status == CTL_PST_SEL_SYNCCAND)
! 800: ips->flags |= INFO_FLAG_SEL_CANDIDATE;
! 801: if (pp->status >= CTL_PST_SEL_SYSPEER)
! 802: ips->flags |= INFO_FLAG_SHORTLIST;
! 803: ips->hmode = pp->hmode;
! 804: ips->delay = HTONS_FP(DTOFP(pp->delay));
! 805: DTOLFP(pp->offset, <mp);
! 806: HTONL_FP(<mp, &ips->offset);
! 807: ips->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp)));
! 808: }
! 809: pp = pp->next;
! 810: ips = (struct info_peer_summary *)more_pkt();
! 811: }
! 812: }
! 813: flush_pkt();
! 814: }
! 815:
! 816:
! 817: /*
! 818: * peer_info - send information for one or more peers
! 819: */
! 820: static void
! 821: peer_info (
! 822: sockaddr_u *srcadr,
! 823: struct interface *inter,
! 824: struct req_pkt *inpkt
! 825: )
! 826: {
! 827: register struct info_peer_list *ipl;
! 828: register struct peer *pp;
! 829: register struct info_peer *ip;
! 830: register int items;
! 831: register int i, j;
! 832: sockaddr_u addr;
! 833: extern struct peer *sys_peer;
! 834: l_fp ltmp;
! 835:
! 836: items = INFO_NITEMS(inpkt->err_nitems);
! 837: ipl = (struct info_peer_list *) inpkt->data;
! 838:
! 839: ip = (struct info_peer *)prepare_pkt(srcadr, inter, inpkt,
! 840: v6sizeof(struct info_peer));
! 841: while (items-- > 0 && ip != 0) {
! 842: ZERO_SOCK(&addr);
! 843: NSRCPORT(&addr) = ipl->port;
! 844: if (client_v6_capable && ipl->v6_flag) {
! 845: AF(&addr) = AF_INET6;
! 846: SOCK_ADDR6(&addr) = ipl->addr6;
! 847: } else {
! 848: AF(&addr) = AF_INET;
! 849: NSRCADR(&addr) = ipl->addr;
! 850: }
! 851: #ifdef ISC_PLATFORM_HAVESALEN
! 852: addr.sa.sa_len = SOCKLEN(&addr);
! 853: #endif
! 854: ipl++;
! 855: pp = findexistingpeer(&addr, NULL, -1, 0);
! 856: if (NULL == pp)
! 857: continue;
! 858: if (IS_IPV6(srcadr)) {
! 859: if (pp->dstadr)
! 860: ip->dstadr6 =
! 861: (MDF_BCAST == pp->cast_flags)
! 862: ? SOCK_ADDR6(&pp->dstadr->bcast)
! 863: : SOCK_ADDR6(&pp->dstadr->sin);
! 864: else
! 865: memset(&ip->dstadr6, 0, sizeof(ip->dstadr6));
! 866:
! 867: ip->srcadr6 = SOCK_ADDR6(&pp->srcadr);
! 868: ip->v6_flag = 1;
! 869: } else {
! 870: if (pp->dstadr) {
! 871: if (!pp->processed)
! 872: ip->dstadr = NSRCADR(&pp->dstadr->sin);
! 873: else {
! 874: if (MDF_BCAST == pp->cast_flags)
! 875: ip->dstadr = NSRCADR(&pp->dstadr->bcast);
! 876: else if (pp->cast_flags) {
! 877: ip->dstadr = NSRCADR(&pp->dstadr->sin);
! 878: if (!ip->dstadr)
! 879: ip->dstadr = NSRCADR(&pp->dstadr->bcast);
! 880: }
! 881: }
! 882: } else
! 883: ip->dstadr = 0;
! 884:
! 885: ip->srcadr = NSRCADR(&pp->srcadr);
! 886: if (client_v6_capable)
! 887: ip->v6_flag = 0;
! 888: }
! 889: ip->srcport = NSRCPORT(&pp->srcadr);
! 890: ip->flags = 0;
! 891: if (pp == sys_peer)
! 892: ip->flags |= INFO_FLAG_SYSPEER;
! 893: if (pp->flags & FLAG_CONFIG)
! 894: ip->flags |= INFO_FLAG_CONFIG;
! 895: if (pp->flags & FLAG_REFCLOCK)
! 896: ip->flags |= INFO_FLAG_REFCLOCK;
! 897: if (pp->flags & FLAG_PREFER)
! 898: ip->flags |= INFO_FLAG_PREFER;
! 899: if (pp->flags & FLAG_BURST)
! 900: ip->flags |= INFO_FLAG_BURST;
! 901: if (pp->status == CTL_PST_SEL_SYNCCAND)
! 902: ip->flags |= INFO_FLAG_SEL_CANDIDATE;
! 903: if (pp->status >= CTL_PST_SEL_SYSPEER)
! 904: ip->flags |= INFO_FLAG_SHORTLIST;
! 905: ip->leap = pp->leap;
! 906: ip->hmode = pp->hmode;
! 907: ip->keyid = pp->keyid;
! 908: ip->stratum = pp->stratum;
! 909: ip->ppoll = pp->ppoll;
! 910: ip->hpoll = pp->hpoll;
! 911: ip->precision = pp->precision;
! 912: ip->version = pp->version;
! 913: ip->reach = pp->reach;
! 914: ip->unreach = (u_char) pp->unreach;
! 915: ip->flash = (u_char)pp->flash;
! 916: ip->flash2 = (u_short) pp->flash;
! 917: ip->estbdelay = HTONS_FP(DTOFP(pp->delay));
! 918: ip->ttl = pp->ttl;
! 919: ip->associd = htons(pp->associd);
! 920: ip->rootdelay = HTONS_FP(DTOUFP(pp->rootdelay));
! 921: ip->rootdispersion = HTONS_FP(DTOUFP(pp->rootdisp));
! 922: ip->refid = pp->refid;
! 923: HTONL_FP(&pp->reftime, &ip->reftime);
! 924: HTONL_FP(&pp->aorg, &ip->org);
! 925: HTONL_FP(&pp->rec, &ip->rec);
! 926: HTONL_FP(&pp->xmt, &ip->xmt);
! 927: j = pp->filter_nextpt - 1;
! 928: for (i = 0; i < NTP_SHIFT; i++, j--) {
! 929: if (j < 0)
! 930: j = NTP_SHIFT-1;
! 931: ip->filtdelay[i] = HTONS_FP(DTOFP(pp->filter_delay[j]));
! 932: DTOLFP(pp->filter_offset[j], <mp);
! 933: HTONL_FP(<mp, &ip->filtoffset[i]);
! 934: ip->order[i] = (u_char)((pp->filter_nextpt+NTP_SHIFT-1)
! 935: - pp->filter_order[i]);
! 936: if (ip->order[i] >= NTP_SHIFT)
! 937: ip->order[i] -= NTP_SHIFT;
! 938: }
! 939: DTOLFP(pp->offset, <mp);
! 940: HTONL_FP(<mp, &ip->offset);
! 941: ip->delay = HTONS_FP(DTOFP(pp->delay));
! 942: ip->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp)));
! 943: ip->selectdisp = HTONS_FP(DTOUFP(SQRT(pp->jitter)));
! 944: ip = (struct info_peer *)more_pkt();
! 945: }
! 946: flush_pkt();
! 947: }
! 948:
! 949:
! 950: /*
! 951: * peer_stats - send statistics for one or more peers
! 952: */
! 953: static void
! 954: peer_stats (
! 955: sockaddr_u *srcadr,
! 956: struct interface *inter,
! 957: struct req_pkt *inpkt
! 958: )
! 959: {
! 960: register struct info_peer_list *ipl;
! 961: register struct peer *pp;
! 962: register struct info_peer_stats *ip;
! 963: register int items;
! 964: sockaddr_u addr;
! 965: extern struct peer *sys_peer;
! 966:
! 967: #ifdef DEBUG
! 968: if (debug)
! 969: printf("peer_stats: called\n");
! 970: #endif
! 971: items = INFO_NITEMS(inpkt->err_nitems);
! 972: ipl = (struct info_peer_list *) inpkt->data;
! 973: ip = (struct info_peer_stats *)prepare_pkt(srcadr, inter, inpkt,
! 974: v6sizeof(struct info_peer_stats));
! 975: while (items-- > 0 && ip != 0) {
! 976: memset((char *)&addr, 0, sizeof(addr));
! 977: NSRCPORT(&addr) = ipl->port;
! 978: if (client_v6_capable && ipl->v6_flag) {
! 979: AF(&addr) = AF_INET6;
! 980: SOCK_ADDR6(&addr) = ipl->addr6;
! 981: } else {
! 982: AF(&addr) = AF_INET;
! 983: NSRCADR(&addr) = ipl->addr;
! 984: }
! 985: #ifdef ISC_PLATFORM_HAVESALEN
! 986: addr.sa.sa_len = SOCKLEN(&addr);
! 987: #endif
! 988: DPRINTF(1, ("peer_stats: looking for %s, %d, %d\n",
! 989: stoa(&addr), ipl->port, NSRCPORT(&addr)));
! 990:
! 991: ipl = (struct info_peer_list *)((char *)ipl +
! 992: INFO_ITEMSIZE(inpkt->mbz_itemsize));
! 993:
! 994: pp = findexistingpeer(&addr, NULL, -1, 0);
! 995: if (NULL == pp)
! 996: continue;
! 997:
! 998: DPRINTF(1, ("peer_stats: found %s\n", stoa(&addr)));
! 999:
! 1000: if (IS_IPV4(&pp->srcadr)) {
! 1001: if (pp->dstadr) {
! 1002: if (!pp->processed)
! 1003: ip->dstadr = NSRCADR(&pp->dstadr->sin);
! 1004: else {
! 1005: if (MDF_BCAST == pp->cast_flags)
! 1006: ip->dstadr = NSRCADR(&pp->dstadr->bcast);
! 1007: else if (pp->cast_flags) {
! 1008: ip->dstadr = NSRCADR(&pp->dstadr->sin);
! 1009: if (!ip->dstadr)
! 1010: ip->dstadr = NSRCADR(&pp->dstadr->bcast);
! 1011: }
! 1012: }
! 1013: } else
! 1014: ip->dstadr = 0;
! 1015:
! 1016: ip->srcadr = NSRCADR(&pp->srcadr);
! 1017: if (client_v6_capable)
! 1018: ip->v6_flag = 0;
! 1019: } else {
! 1020: if (pp->dstadr)
! 1021: ip->dstadr6 =
! 1022: (MDF_BCAST == pp->cast_flags)
! 1023: ? SOCK_ADDR6(&pp->dstadr->bcast)
! 1024: : SOCK_ADDR6(&pp->dstadr->sin);
! 1025: else
! 1026: memset(&ip->dstadr6, 0, sizeof(ip->dstadr6));
! 1027:
! 1028: ip->srcadr6 = SOCK_ADDR6(&pp->srcadr);
! 1029: ip->v6_flag = 1;
! 1030: }
! 1031: ip->srcport = NSRCPORT(&pp->srcadr);
! 1032: ip->flags = 0;
! 1033: if (pp == sys_peer)
! 1034: ip->flags |= INFO_FLAG_SYSPEER;
! 1035: if (pp->flags & FLAG_CONFIG)
! 1036: ip->flags |= INFO_FLAG_CONFIG;
! 1037: if (pp->flags & FLAG_REFCLOCK)
! 1038: ip->flags |= INFO_FLAG_REFCLOCK;
! 1039: if (pp->flags & FLAG_PREFER)
! 1040: ip->flags |= INFO_FLAG_PREFER;
! 1041: if (pp->flags & FLAG_BURST)
! 1042: ip->flags |= INFO_FLAG_BURST;
! 1043: if (pp->flags & FLAG_IBURST)
! 1044: ip->flags |= INFO_FLAG_IBURST;
! 1045: if (pp->status == CTL_PST_SEL_SYNCCAND)
! 1046: ip->flags |= INFO_FLAG_SEL_CANDIDATE;
! 1047: if (pp->status >= CTL_PST_SEL_SYSPEER)
! 1048: ip->flags |= INFO_FLAG_SHORTLIST;
! 1049: ip->flags = htons(ip->flags);
! 1050: ip->timereceived = htonl((u_int32)(current_time - pp->timereceived));
! 1051: ip->timetosend = htonl(pp->nextdate - current_time);
! 1052: ip->timereachable = htonl((u_int32)(current_time - pp->timereachable));
! 1053: ip->sent = htonl((u_int32)(pp->sent));
! 1054: ip->processed = htonl((u_int32)(pp->processed));
! 1055: ip->badauth = htonl((u_int32)(pp->badauth));
! 1056: ip->bogusorg = htonl((u_int32)(pp->bogusorg));
! 1057: ip->oldpkt = htonl((u_int32)(pp->oldpkt));
! 1058: ip->seldisp = htonl((u_int32)(pp->seldisptoolarge));
! 1059: ip->selbroken = htonl((u_int32)(pp->selbroken));
! 1060: ip->candidate = pp->status;
! 1061: ip = (struct info_peer_stats *)more_pkt();
! 1062: }
! 1063: flush_pkt();
! 1064: }
! 1065:
! 1066:
! 1067: /*
! 1068: * sys_info - return system info
! 1069: */
! 1070: static void
! 1071: sys_info(
! 1072: sockaddr_u *srcadr,
! 1073: struct interface *inter,
! 1074: struct req_pkt *inpkt
! 1075: )
! 1076: {
! 1077: register struct info_sys *is;
! 1078:
! 1079: is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt,
! 1080: v6sizeof(struct info_sys));
! 1081:
! 1082: if (sys_peer) {
! 1083: if (IS_IPV4(&sys_peer->srcadr)) {
! 1084: is->peer = NSRCADR(&sys_peer->srcadr);
! 1085: if (client_v6_capable)
! 1086: is->v6_flag = 0;
! 1087: } else if (client_v6_capable) {
! 1088: is->peer6 = SOCK_ADDR6(&sys_peer->srcadr);
! 1089: is->v6_flag = 1;
! 1090: }
! 1091: is->peer_mode = sys_peer->hmode;
! 1092: } else {
! 1093: is->peer = 0;
! 1094: if (client_v6_capable) {
! 1095: is->v6_flag = 0;
! 1096: }
! 1097: is->peer_mode = 0;
! 1098: }
! 1099:
! 1100: is->leap = sys_leap;
! 1101: is->stratum = sys_stratum;
! 1102: is->precision = sys_precision;
! 1103: is->rootdelay = htonl(DTOFP(sys_rootdelay));
! 1104: is->rootdispersion = htonl(DTOUFP(sys_rootdisp));
! 1105: is->frequency = htonl(DTOFP(sys_jitter));
! 1106: is->stability = htonl(DTOUFP(clock_stability));
! 1107: is->refid = sys_refid;
! 1108: HTONL_FP(&sys_reftime, &is->reftime);
! 1109:
! 1110: is->poll = sys_poll;
! 1111:
! 1112: is->flags = 0;
! 1113: if (sys_authenticate)
! 1114: is->flags |= INFO_FLAG_AUTHENTICATE;
! 1115: if (sys_bclient)
! 1116: is->flags |= INFO_FLAG_BCLIENT;
! 1117: #ifdef REFCLOCK
! 1118: if (cal_enable)
! 1119: is->flags |= INFO_FLAG_CAL;
! 1120: #endif /* REFCLOCK */
! 1121: if (kern_enable)
! 1122: is->flags |= INFO_FLAG_KERNEL;
! 1123: if (mon_enabled != MON_OFF)
! 1124: is->flags |= INFO_FLAG_MONITOR;
! 1125: if (ntp_enable)
! 1126: is->flags |= INFO_FLAG_NTP;
! 1127: if (pps_enable)
! 1128: is->flags |= INFO_FLAG_PPS_SYNC;
! 1129: if (stats_control)
! 1130: is->flags |= INFO_FLAG_FILEGEN;
! 1131: is->bdelay = HTONS_FP(DTOFP(sys_bdelay));
! 1132: HTONL_UF(sys_authdelay.l_f, &is->authdelay);
! 1133: (void) more_pkt();
! 1134: flush_pkt();
! 1135: }
! 1136:
! 1137:
! 1138: /*
! 1139: * sys_stats - return system statistics
! 1140: */
! 1141: static void
! 1142: sys_stats(
! 1143: sockaddr_u *srcadr,
! 1144: struct interface *inter,
! 1145: struct req_pkt *inpkt
! 1146: )
! 1147: {
! 1148: register struct info_sys_stats *ss;
! 1149:
! 1150: /*
! 1151: * Importations from the protocol module
! 1152: */
! 1153: ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt,
! 1154: sizeof(struct info_sys_stats));
! 1155: ss->timeup = htonl((u_int32)current_time);
! 1156: ss->timereset = htonl((u_int32)(current_time - sys_stattime));
! 1157: ss->denied = htonl((u_int32)sys_restricted);
! 1158: ss->oldversionpkt = htonl((u_int32)sys_oldversion);
! 1159: ss->newversionpkt = htonl((u_int32)sys_newversion);
! 1160: ss->unknownversion = htonl((u_int32)sys_declined);
! 1161: ss->badlength = htonl((u_int32)sys_badlength);
! 1162: ss->processed = htonl((u_int32)sys_processed);
! 1163: ss->badauth = htonl((u_int32)sys_badauth);
! 1164: ss->limitrejected = htonl((u_int32)sys_limitrejected);
! 1165: ss->received = htonl((u_int32)sys_received);
! 1166: (void) more_pkt();
! 1167: flush_pkt();
! 1168: }
! 1169:
! 1170:
! 1171: /*
! 1172: * mem_stats - return memory statistics
! 1173: */
! 1174: static void
! 1175: mem_stats(
! 1176: sockaddr_u *srcadr,
! 1177: struct interface *inter,
! 1178: struct req_pkt *inpkt
! 1179: )
! 1180: {
! 1181: register struct info_mem_stats *ms;
! 1182: register int i;
! 1183:
! 1184: /*
! 1185: * Importations from the peer module
! 1186: */
! 1187: extern int peer_hash_count[NTP_HASH_SIZE];
! 1188: extern int peer_free_count;
! 1189: extern u_long peer_timereset;
! 1190: extern u_long findpeer_calls;
! 1191: extern u_long peer_allocations;
! 1192: extern u_long peer_demobilizations;
! 1193: extern int total_peer_structs;
! 1194:
! 1195: ms = (struct info_mem_stats *)prepare_pkt(srcadr, inter, inpkt,
! 1196: sizeof(struct info_mem_stats));
! 1197:
! 1198: ms->timereset = htonl((u_int32)(current_time - peer_timereset));
! 1199: ms->totalpeermem = htons((u_short)total_peer_structs);
! 1200: ms->freepeermem = htons((u_short)peer_free_count);
! 1201: ms->findpeer_calls = htonl((u_int32)findpeer_calls);
! 1202: ms->allocations = htonl((u_int32)peer_allocations);
! 1203: ms->demobilizations = htonl((u_int32)peer_demobilizations);
! 1204:
! 1205: for (i = 0; i < NTP_HASH_SIZE; i++) {
! 1206: if (peer_hash_count[i] > 255)
! 1207: ms->hashcount[i] = 255;
! 1208: else
! 1209: ms->hashcount[i] = (u_char)peer_hash_count[i];
! 1210: }
! 1211:
! 1212: (void) more_pkt();
! 1213: flush_pkt();
! 1214: }
! 1215:
! 1216:
! 1217: /*
! 1218: * io_stats - return io statistics
! 1219: */
! 1220: static void
! 1221: io_stats(
! 1222: sockaddr_u *srcadr,
! 1223: struct interface *inter,
! 1224: struct req_pkt *inpkt
! 1225: )
! 1226: {
! 1227: register struct info_io_stats *io;
! 1228:
! 1229: /*
! 1230: * Importations from the io module
! 1231: */
! 1232: extern u_long io_timereset;
! 1233:
! 1234: io = (struct info_io_stats *)prepare_pkt(srcadr, inter, inpkt,
! 1235: sizeof(struct info_io_stats));
! 1236:
! 1237: io->timereset = htonl((u_int32)(current_time - io_timereset));
! 1238: io->totalrecvbufs = htons((u_short) total_recvbuffs());
! 1239: io->freerecvbufs = htons((u_short) free_recvbuffs());
! 1240: io->fullrecvbufs = htons((u_short) full_recvbuffs());
! 1241: io->lowwater = htons((u_short) lowater_additions());
! 1242: io->dropped = htonl((u_int32)packets_dropped);
! 1243: io->ignored = htonl((u_int32)packets_ignored);
! 1244: io->received = htonl((u_int32)packets_received);
! 1245: io->sent = htonl((u_int32)packets_sent);
! 1246: io->notsent = htonl((u_int32)packets_notsent);
! 1247: io->interrupts = htonl((u_int32)handler_calls);
! 1248: io->int_received = htonl((u_int32)handler_pkts);
! 1249:
! 1250: (void) more_pkt();
! 1251: flush_pkt();
! 1252: }
! 1253:
! 1254:
! 1255: /*
! 1256: * timer_stats - return timer statistics
! 1257: */
! 1258: static void
! 1259: timer_stats(
! 1260: sockaddr_u * srcadr,
! 1261: struct interface * inter,
! 1262: struct req_pkt * inpkt
! 1263: )
! 1264: {
! 1265: struct info_timer_stats * ts;
! 1266: u_long sincereset;
! 1267:
! 1268: ts = (struct info_timer_stats *)prepare_pkt(srcadr, inter,
! 1269: inpkt, sizeof(*ts));
! 1270:
! 1271: sincereset = current_time - timer_timereset;
! 1272: ts->timereset = htonl((u_int32)sincereset);
! 1273: ts->alarms = ts->timereset;
! 1274: ts->overflows = htonl((u_int32)alarm_overflow);
! 1275: ts->xmtcalls = htonl((u_int32)timer_xmtcalls);
! 1276:
! 1277: (void) more_pkt();
! 1278: flush_pkt();
! 1279: }
! 1280:
! 1281:
! 1282: /*
! 1283: * loop_info - return the current state of the loop filter
! 1284: */
! 1285: static void
! 1286: loop_info(
! 1287: sockaddr_u *srcadr,
! 1288: struct interface *inter,
! 1289: struct req_pkt *inpkt
! 1290: )
! 1291: {
! 1292: register struct info_loop *li;
! 1293: l_fp ltmp;
! 1294:
! 1295: /*
! 1296: * Importations from the loop filter module
! 1297: */
! 1298: extern double last_offset;
! 1299: extern double drift_comp;
! 1300: extern int tc_counter;
! 1301: extern u_long sys_epoch;
! 1302:
! 1303: li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt,
! 1304: sizeof(struct info_loop));
! 1305:
! 1306: DTOLFP(last_offset, <mp);
! 1307: HTONL_FP(<mp, &li->last_offset);
! 1308: DTOLFP(drift_comp * 1e6, <mp);
! 1309: HTONL_FP(<mp, &li->drift_comp);
! 1310: li->compliance = htonl((u_int32)(tc_counter));
! 1311: li->watchdog_timer = htonl((u_int32)(current_time - sys_epoch));
! 1312:
! 1313: (void) more_pkt();
! 1314: flush_pkt();
! 1315: }
! 1316:
! 1317:
! 1318: /*
! 1319: * do_conf - add a peer to the configuration list
! 1320: */
! 1321: static void
! 1322: do_conf(
! 1323: sockaddr_u *srcadr,
! 1324: struct interface *inter,
! 1325: struct req_pkt *inpkt
! 1326: )
! 1327: {
! 1328: static u_long soonest_ifrescan_time = 0;
! 1329: int items;
! 1330: u_int fl;
! 1331: struct conf_peer *cp;
! 1332: struct conf_peer temp_cp;
! 1333: sockaddr_u peeraddr;
! 1334:
! 1335: /*
! 1336: * Do a check of everything to see that it looks
! 1337: * okay. If not, complain about it. Note we are
! 1338: * very picky here.
! 1339: */
! 1340: items = INFO_NITEMS(inpkt->err_nitems);
! 1341: cp = (struct conf_peer *)inpkt->data;
! 1342: memset(&temp_cp, 0, sizeof(struct conf_peer));
! 1343: memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
! 1344:
! 1345: #if 0 /* paranoid checking - these are done in newpeer() */
! 1346: fl = 0;
! 1347: while (items-- > 0 && !fl) {
! 1348: if (((temp_cp.version) > NTP_VERSION)
! 1349: || ((temp_cp.version) < NTP_OLDVERSION))
! 1350: fl = 1;
! 1351: if (temp_cp.hmode != MODE_ACTIVE
! 1352: && temp_cp.hmode != MODE_CLIENT
! 1353: && temp_cp.hmode != MODE_BROADCAST)
! 1354: fl = 1;
! 1355: if (temp_cp.flags & ~(CONF_FLAG_PREFER | CONF_FLAG_BURST |
! 1356: CONF_FLAG_IBURST | CONF_FLAG_SKEY))
! 1357: fl = 1;
! 1358: cp = (struct conf_peer *)
! 1359: ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
! 1360: }
! 1361:
! 1362: if (fl) {
! 1363: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
! 1364: return;
! 1365: }
! 1366: #endif /* end paranoid checking */
! 1367:
! 1368: /*
! 1369: * Looks okay, try it out
! 1370: */
! 1371: items = INFO_NITEMS(inpkt->err_nitems);
! 1372: cp = (struct conf_peer *)inpkt->data;
! 1373:
! 1374: while (items-- > 0) {
! 1375: memset(&temp_cp, 0, sizeof(struct conf_peer));
! 1376: memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
! 1377: ZERO_SOCK(&peeraddr);
! 1378:
! 1379: fl = 0;
! 1380: if (temp_cp.flags & CONF_FLAG_PREFER)
! 1381: fl |= FLAG_PREFER;
! 1382: if (temp_cp.flags & CONF_FLAG_BURST)
! 1383: fl |= FLAG_BURST;
! 1384: if (temp_cp.flags & CONF_FLAG_IBURST)
! 1385: fl |= FLAG_IBURST;
! 1386: #ifdef OPENSSL
! 1387: if (temp_cp.flags & CONF_FLAG_SKEY)
! 1388: fl |= FLAG_SKEY;
! 1389: #endif /* OPENSSL */
! 1390: if (client_v6_capable && temp_cp.v6_flag != 0) {
! 1391: AF(&peeraddr) = AF_INET6;
! 1392: SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6;
! 1393: } else {
! 1394: AF(&peeraddr) = AF_INET;
! 1395: NSRCADR(&peeraddr) = temp_cp.peeraddr;
! 1396: /*
! 1397: * Make sure the address is valid
! 1398: */
! 1399: if (!ISREFCLOCKADR(&peeraddr) &&
! 1400: ISBADADR(&peeraddr)) {
! 1401: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
! 1402: return;
! 1403: }
! 1404:
! 1405: }
! 1406: NSRCPORT(&peeraddr) = htons(NTP_PORT);
! 1407: #ifdef ISC_PLATFORM_HAVESALEN
! 1408: peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
! 1409: #endif
! 1410:
! 1411: /* XXX W2DO? minpoll/maxpoll arguments ??? */
! 1412: if (peer_config(&peeraddr, (struct interface *)0,
! 1413: temp_cp.hmode, temp_cp.version, temp_cp.minpoll,
! 1414: temp_cp.maxpoll, fl, temp_cp.ttl, temp_cp.keyid,
! 1415: NULL) == 0) {
! 1416: req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
! 1417: return;
! 1418: }
! 1419:
! 1420: /*
! 1421: * ntp_intres.c uses REQ_CONFIG/doconf() to add each
! 1422: * server after its name is resolved. If we have been
! 1423: * disconnected from the network, it may notice the
! 1424: * network has returned and add the first server while
! 1425: * the relevant interface is still disabled, awaiting
! 1426: * the next interface rescan. To get things moving
! 1427: * more quickly, trigger an interface scan now, except
! 1428: * if we have done so in the last half minute.
! 1429: */
! 1430: if (soonest_ifrescan_time < current_time) {
! 1431: soonest_ifrescan_time = current_time + 30;
! 1432: timer_interfacetimeout(current_time);
! 1433: DPRINTF(1, ("do_conf triggering interface rescan\n"));
! 1434: }
! 1435:
! 1436: cp = (struct conf_peer *)
! 1437: ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
! 1438: }
! 1439:
! 1440: req_ack(srcadr, inter, inpkt, INFO_OKAY);
! 1441: }
! 1442:
! 1443: #if 0
! 1444: /* XXX */
! 1445: /*
! 1446: * dns_a - Snarf DNS info for an association ID
! 1447: */
! 1448: static void
! 1449: dns_a(
! 1450: sockaddr_u *srcadr,
! 1451: struct interface *inter,
! 1452: struct req_pkt *inpkt
! 1453: )
! 1454: {
! 1455: register struct info_dns_assoc *dp;
! 1456: register int items;
! 1457: struct sockaddr_in peeraddr;
! 1458:
! 1459: /*
! 1460: * Do a check of everything to see that it looks
! 1461: * okay. If not, complain about it. Note we are
! 1462: * very picky here.
! 1463: */
! 1464: items = INFO_NITEMS(inpkt->err_nitems);
! 1465: dp = (struct info_dns_assoc *)inpkt->data;
! 1466:
! 1467: /*
! 1468: * Looks okay, try it out
! 1469: */
! 1470: items = INFO_NITEMS(inpkt->err_nitems);
! 1471: dp = (struct info_dns_assoc *)inpkt->data;
! 1472: memset((char *)&peeraddr, 0, sizeof(struct sockaddr_in));
! 1473: peeraddr.sin_family = AF_INET;
! 1474: peeraddr.sin_port = htons(NTP_PORT);
! 1475:
! 1476: /*
! 1477: * Make sure the address is valid
! 1478: */
! 1479: if (!ISREFCLOCKADR(&peeraddr) && ISBADADR(&peeraddr)) {
! 1480: msyslog(LOG_ERR, "dns_a: !ISREFCLOCKADR && ISBADADR");
! 1481: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
! 1482: return;
! 1483: }
! 1484:
! 1485: while (items-- > 0) {
! 1486: associd_t associd;
! 1487: size_t hnl;
! 1488: struct peer *peer;
! 1489: int bogon = 0;
! 1490:
! 1491: associd = dp->associd;
! 1492: peer = findpeerbyassoc(associd);
! 1493: if (peer == 0 || peer->flags & FLAG_REFCLOCK) {
! 1494: msyslog(LOG_ERR, "dns_a: %s",
! 1495: (peer == 0)
! 1496: ? "peer == 0"
! 1497: : "peer->flags & FLAG_REFCLOCK");
! 1498: ++bogon;
! 1499: }
! 1500: peeraddr.sin_addr.s_addr = dp->peeraddr;
! 1501: for (hnl = 0; dp->hostname[hnl] && hnl < sizeof dp->hostname; ++hnl) ;
! 1502: if (hnl >= sizeof dp->hostname) {
! 1503: msyslog(LOG_ERR, "dns_a: hnl (%ld) >= %ld",
! 1504: (long)hnl, (long)sizeof dp->hostname);
! 1505: ++bogon;
! 1506: }
! 1507:
! 1508: msyslog(LOG_INFO, "dns_a: <%s> for %s, AssocID %d, bogon %d",
! 1509: dp->hostname,
! 1510: stoa((sockaddr_u *)&peeraddr), associd,
! 1511: bogon);
! 1512:
! 1513: if (bogon) {
! 1514: /* If it didn't work */
! 1515: req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
! 1516: return;
! 1517: } else {
! 1518: #if 0
! 1519: #ifdef PUBKEY
! 1520: crypto_public(peer, dp->hostname);
! 1521: #endif /* PUBKEY */
! 1522: #endif
! 1523: }
! 1524:
! 1525: dp++;
! 1526: }
! 1527:
! 1528: req_ack(srcadr, inter, inpkt, INFO_OKAY);
! 1529: }
! 1530: #endif /* 0 */
! 1531:
! 1532: /*
! 1533: * do_unconf - remove a peer from the configuration list
! 1534: */
! 1535: static void
! 1536: do_unconf(
! 1537: sockaddr_u *srcadr,
! 1538: struct interface *inter,
! 1539: struct req_pkt *inpkt
! 1540: )
! 1541: {
! 1542: register struct conf_unpeer *cp;
! 1543: struct conf_unpeer temp_cp;
! 1544: register int items;
! 1545: register struct peer *peer;
! 1546: sockaddr_u peeraddr;
! 1547: int bad, found;
! 1548:
! 1549: /*
! 1550: * This is a bit unstructured, but I like to be careful.
! 1551: * We check to see that every peer exists and is actually
! 1552: * configured. If so, we remove them. If not, we return
! 1553: * an error.
! 1554: */
! 1555: items = INFO_NITEMS(inpkt->err_nitems);
! 1556: cp = (struct conf_unpeer *)inpkt->data;
! 1557:
! 1558: bad = 0;
! 1559: while (items-- > 0 && !bad) {
! 1560: memset(&temp_cp, 0, sizeof(temp_cp));
! 1561: ZERO_SOCK(&peeraddr);
! 1562: memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
! 1563: if (client_v6_capable && temp_cp.v6_flag) {
! 1564: AF(&peeraddr) = AF_INET6;
! 1565: SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6;
! 1566: } else {
! 1567: AF(&peeraddr) = AF_INET;
! 1568: NSRCADR(&peeraddr) = temp_cp.peeraddr;
! 1569: }
! 1570: SET_PORT(&peeraddr, NTP_PORT);
! 1571: #ifdef ISC_PLATFORM_HAVESALEN
! 1572: peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
! 1573: #endif
! 1574: found = 0;
! 1575: peer = NULL;
! 1576:
! 1577: DPRINTF(1, ("searching for %s\n", stoa(&peeraddr)));
! 1578:
! 1579: while (!found) {
! 1580: peer = findexistingpeer(&peeraddr, peer, -1, 0);
! 1581: if (!peer)
! 1582: break;
! 1583: if (peer->flags & FLAG_CONFIG)
! 1584: found = 1;
! 1585: }
! 1586: if (!found)
! 1587: bad = 1;
! 1588: cp = (struct conf_unpeer *)
! 1589: ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
! 1590: }
! 1591:
! 1592: if (bad) {
! 1593: req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
! 1594: return;
! 1595: }
! 1596:
! 1597: /*
! 1598: * Now do it in earnest.
! 1599: */
! 1600:
! 1601: items = INFO_NITEMS(inpkt->err_nitems);
! 1602: cp = (struct conf_unpeer *)inpkt->data;
! 1603:
! 1604: while (items-- > 0) {
! 1605: memset(&temp_cp, 0, sizeof(temp_cp));
! 1606: memset(&peeraddr, 0, sizeof(peeraddr));
! 1607: memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
! 1608: if (client_v6_capable && temp_cp.v6_flag) {
! 1609: AF(&peeraddr) = AF_INET6;
! 1610: SOCK_ADDR6(&peeraddr) = temp_cp.peeraddr6;
! 1611: } else {
! 1612: AF(&peeraddr) = AF_INET;
! 1613: NSRCADR(&peeraddr) = temp_cp.peeraddr;
! 1614: }
! 1615: SET_PORT(&peeraddr, NTP_PORT);
! 1616: #ifdef ISC_PLATFORM_HAVESALEN
! 1617: peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
! 1618: #endif
! 1619: found = 0;
! 1620: peer = NULL;
! 1621:
! 1622: while (!found) {
! 1623: peer = findexistingpeer(&peeraddr, peer, -1, 0);
! 1624: if (!peer)
! 1625: break;
! 1626: if (peer->flags & FLAG_CONFIG)
! 1627: found = 1;
! 1628: }
! 1629: NTP_INSIST(found);
! 1630: NTP_INSIST(peer);
! 1631:
! 1632: peer_clear(peer, "GONE");
! 1633: unpeer(peer);
! 1634:
! 1635: cp = (struct conf_unpeer *)
! 1636: ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
! 1637: }
! 1638:
! 1639: req_ack(srcadr, inter, inpkt, INFO_OKAY);
! 1640: }
! 1641:
! 1642:
! 1643: /*
! 1644: * set_sys_flag - set system flags
! 1645: */
! 1646: static void
! 1647: set_sys_flag(
! 1648: sockaddr_u *srcadr,
! 1649: struct interface *inter,
! 1650: struct req_pkt *inpkt
! 1651: )
! 1652: {
! 1653: setclr_flags(srcadr, inter, inpkt, 1);
! 1654: }
! 1655:
! 1656:
! 1657: /*
! 1658: * clr_sys_flag - clear system flags
! 1659: */
! 1660: static void
! 1661: clr_sys_flag(
! 1662: sockaddr_u *srcadr,
! 1663: struct interface *inter,
! 1664: struct req_pkt *inpkt
! 1665: )
! 1666: {
! 1667: setclr_flags(srcadr, inter, inpkt, 0);
! 1668: }
! 1669:
! 1670:
! 1671: /*
! 1672: * setclr_flags - do the grunge work of flag setting/clearing
! 1673: */
! 1674: static void
! 1675: setclr_flags(
! 1676: sockaddr_u *srcadr,
! 1677: struct interface *inter,
! 1678: struct req_pkt *inpkt,
! 1679: u_long set
! 1680: )
! 1681: {
! 1682: struct conf_sys_flags *sf;
! 1683: u_int32 flags;
! 1684: int prev_kern_enable;
! 1685:
! 1686: prev_kern_enable = kern_enable;
! 1687: if (INFO_NITEMS(inpkt->err_nitems) > 1) {
! 1688: msyslog(LOG_ERR, "setclr_flags: err_nitems > 1");
! 1689: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
! 1690: return;
! 1691: }
! 1692:
! 1693: sf = (struct conf_sys_flags *)inpkt->data;
! 1694: flags = ntohl(sf->flags);
! 1695:
! 1696: if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
! 1697: SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR |
! 1698: SYS_FLAG_FILEGEN | SYS_FLAG_AUTH | SYS_FLAG_CAL)) {
! 1699: msyslog(LOG_ERR, "setclr_flags: extra flags: %#x",
! 1700: flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
! 1701: SYS_FLAG_NTP | SYS_FLAG_KERNEL |
! 1702: SYS_FLAG_MONITOR | SYS_FLAG_FILEGEN |
! 1703: SYS_FLAG_AUTH | SYS_FLAG_CAL));
! 1704: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
! 1705: return;
! 1706: }
! 1707:
! 1708: if (flags & SYS_FLAG_BCLIENT)
! 1709: proto_config(PROTO_BROADCLIENT, set, 0., NULL);
! 1710: if (flags & SYS_FLAG_PPS)
! 1711: proto_config(PROTO_PPS, set, 0., NULL);
! 1712: if (flags & SYS_FLAG_NTP)
! 1713: proto_config(PROTO_NTP, set, 0., NULL);
! 1714: if (flags & SYS_FLAG_KERNEL)
! 1715: proto_config(PROTO_KERNEL, set, 0., NULL);
! 1716: if (flags & SYS_FLAG_MONITOR)
! 1717: proto_config(PROTO_MONITOR, set, 0., NULL);
! 1718: if (flags & SYS_FLAG_FILEGEN)
! 1719: proto_config(PROTO_FILEGEN, set, 0., NULL);
! 1720: if (flags & SYS_FLAG_AUTH)
! 1721: proto_config(PROTO_AUTHENTICATE, set, 0., NULL);
! 1722: if (flags & SYS_FLAG_CAL)
! 1723: proto_config(PROTO_CAL, set, 0., NULL);
! 1724: req_ack(srcadr, inter, inpkt, INFO_OKAY);
! 1725:
! 1726: /* Reset the kernel ntp parameters if the kernel flag changed. */
! 1727: if (prev_kern_enable && !kern_enable)
! 1728: loop_config(LOOP_KERN_CLEAR, 0.0);
! 1729: if (!prev_kern_enable && kern_enable)
! 1730: loop_config(LOOP_DRIFTCOMP, drift_comp);
! 1731: }
! 1732:
! 1733: /*
! 1734: * list_restrict4 - recursive helper for list_restrict dumps IPv4
! 1735: * restriction list in reverse order.
! 1736: */
! 1737: static void
! 1738: list_restrict4(
! 1739: restrict_u * res,
! 1740: struct info_restrict ** ppir
! 1741: )
! 1742: {
! 1743: struct info_restrict * pir;
! 1744:
! 1745: if (res->link != NULL)
! 1746: list_restrict4(res->link, ppir);
! 1747:
! 1748: pir = *ppir;
! 1749: pir->addr = htonl(res->u.v4.addr);
! 1750: if (client_v6_capable)
! 1751: pir->v6_flag = 0;
! 1752: pir->mask = htonl(res->u.v4.mask);
! 1753: pir->count = htonl(res->count);
! 1754: pir->flags = htons(res->flags);
! 1755: pir->mflags = htons(res->mflags);
! 1756: *ppir = (struct info_restrict *)more_pkt();
! 1757: }
! 1758:
! 1759:
! 1760: /*
! 1761: * list_restrict6 - recursive helper for list_restrict dumps IPv6
! 1762: * restriction list in reverse order.
! 1763: */
! 1764: static void
! 1765: list_restrict6(
! 1766: restrict_u * res,
! 1767: struct info_restrict ** ppir
! 1768: )
! 1769: {
! 1770: struct info_restrict * pir;
! 1771:
! 1772: if (res->link != NULL)
! 1773: list_restrict6(res->link, ppir);
! 1774:
! 1775: pir = *ppir;
! 1776: pir->addr6 = res->u.v6.addr;
! 1777: pir->mask6 = res->u.v6.mask;
! 1778: pir->v6_flag = 1;
! 1779: pir->count = htonl(res->count);
! 1780: pir->flags = htons(res->flags);
! 1781: pir->mflags = htons(res->mflags);
! 1782: *ppir = (struct info_restrict *)more_pkt();
! 1783: }
! 1784:
! 1785:
! 1786: /*
! 1787: * list_restrict - return the restrict list
! 1788: */
! 1789: static void
! 1790: list_restrict(
! 1791: sockaddr_u *srcadr,
! 1792: struct interface *inter,
! 1793: struct req_pkt *inpkt
! 1794: )
! 1795: {
! 1796: struct info_restrict *ir;
! 1797:
! 1798: DPRINTF(3, ("wants restrict list summary\n"));
! 1799:
! 1800: ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt,
! 1801: v6sizeof(struct info_restrict));
! 1802:
! 1803: /*
! 1804: * The restriction lists are kept sorted in the reverse order
! 1805: * than they were originally. To preserve the output semantics,
! 1806: * dump each list in reverse order. A recursive helper function
! 1807: * achieves that.
! 1808: */
! 1809: list_restrict4(restrictlist4, &ir);
! 1810: if (client_v6_capable)
! 1811: list_restrict6(restrictlist6, &ir);
! 1812: flush_pkt();
! 1813: }
! 1814:
! 1815:
! 1816: /*
! 1817: * do_resaddflags - add flags to a restrict entry (or create one)
! 1818: */
! 1819: static void
! 1820: do_resaddflags(
! 1821: sockaddr_u *srcadr,
! 1822: struct interface *inter,
! 1823: struct req_pkt *inpkt
! 1824: )
! 1825: {
! 1826: do_restrict(srcadr, inter, inpkt, RESTRICT_FLAGS);
! 1827: }
! 1828:
! 1829:
! 1830:
! 1831: /*
! 1832: * do_ressubflags - remove flags from a restrict entry
! 1833: */
! 1834: static void
! 1835: do_ressubflags(
! 1836: sockaddr_u *srcadr,
! 1837: struct interface *inter,
! 1838: struct req_pkt *inpkt
! 1839: )
! 1840: {
! 1841: do_restrict(srcadr, inter, inpkt, RESTRICT_UNFLAG);
! 1842: }
! 1843:
! 1844:
! 1845: /*
! 1846: * do_unrestrict - remove a restrict entry from the list
! 1847: */
! 1848: static void
! 1849: do_unrestrict(
! 1850: sockaddr_u *srcadr,
! 1851: struct interface *inter,
! 1852: struct req_pkt *inpkt
! 1853: )
! 1854: {
! 1855: do_restrict(srcadr, inter, inpkt, RESTRICT_REMOVE);
! 1856: }
! 1857:
! 1858:
! 1859: /*
! 1860: * do_restrict - do the dirty stuff of dealing with restrictions
! 1861: */
! 1862: static void
! 1863: do_restrict(
! 1864: sockaddr_u *srcadr,
! 1865: struct interface *inter,
! 1866: struct req_pkt *inpkt,
! 1867: int op
! 1868: )
! 1869: {
! 1870: register struct conf_restrict *cr;
! 1871: register int items;
! 1872: sockaddr_u matchaddr;
! 1873: sockaddr_u matchmask;
! 1874: int bad;
! 1875:
! 1876: /*
! 1877: * Do a check of the flags to make sure that only
! 1878: * the NTPPORT flag is set, if any. If not, complain
! 1879: * about it. Note we are very picky here.
! 1880: */
! 1881: items = INFO_NITEMS(inpkt->err_nitems);
! 1882: cr = (struct conf_restrict *)inpkt->data;
! 1883:
! 1884: bad = 0;
! 1885: cr->flags = ntohs(cr->flags);
! 1886: cr->mflags = ntohs(cr->mflags);
! 1887: while (items-- > 0 && !bad) {
! 1888: if (cr->mflags & ~(RESM_NTPONLY))
! 1889: bad |= 1;
! 1890: if (cr->flags & ~(RES_ALLFLAGS))
! 1891: bad |= 2;
! 1892: if (cr->mask != htonl(INADDR_ANY)) {
! 1893: if (client_v6_capable && cr->v6_flag != 0) {
! 1894: if (IN6_IS_ADDR_UNSPECIFIED(&cr->addr6))
! 1895: bad |= 4;
! 1896: } else
! 1897: if (cr->addr == htonl(INADDR_ANY))
! 1898: bad |= 8;
! 1899: }
! 1900: cr = (struct conf_restrict *)((char *)cr +
! 1901: INFO_ITEMSIZE(inpkt->mbz_itemsize));
! 1902: }
! 1903:
! 1904: if (bad) {
! 1905: msyslog(LOG_ERR, "do_restrict: bad = %#x", bad);
! 1906: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
! 1907: return;
! 1908: }
! 1909:
! 1910: /*
! 1911: * Looks okay, try it out
! 1912: */
! 1913: items = INFO_NITEMS(inpkt->err_nitems);
! 1914: cr = (struct conf_restrict *)inpkt->data;
! 1915: ZERO_SOCK(&matchaddr);
! 1916: ZERO_SOCK(&matchmask);
! 1917:
! 1918: while (items-- > 0) {
! 1919: if (client_v6_capable && cr->v6_flag) {
! 1920: AF(&matchaddr) = AF_INET6;
! 1921: AF(&matchmask) = AF_INET6;
! 1922: SOCK_ADDR6(&matchaddr) = cr->addr6;
! 1923: SOCK_ADDR6(&matchmask) = cr->mask6;
! 1924: } else {
! 1925: AF(&matchaddr) = AF_INET;
! 1926: AF(&matchmask) = AF_INET;
! 1927: NSRCADR(&matchaddr) = cr->addr;
! 1928: NSRCADR(&matchmask) = cr->mask;
! 1929: }
! 1930: hack_restrict(op, &matchaddr, &matchmask, cr->mflags,
! 1931: cr->flags);
! 1932: cr++;
! 1933: }
! 1934:
! 1935: req_ack(srcadr, inter, inpkt, INFO_OKAY);
! 1936: }
! 1937:
! 1938:
! 1939: /*
! 1940: * mon_getlist - return monitor data
! 1941: */
! 1942: static void
! 1943: mon_getlist_0(
! 1944: sockaddr_u *srcadr,
! 1945: struct interface *inter,
! 1946: struct req_pkt *inpkt
! 1947: )
! 1948: {
! 1949: register struct info_monitor *im;
! 1950: register struct mon_data *md;
! 1951: extern struct mon_data mon_mru_list;
! 1952: extern int mon_enabled;
! 1953:
! 1954: #ifdef DEBUG
! 1955: if (debug > 2)
! 1956: printf("wants monitor 0 list\n");
! 1957: #endif
! 1958: if (!mon_enabled) {
! 1959: req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
! 1960: return;
! 1961: }
! 1962: im = (struct info_monitor *)prepare_pkt(srcadr, inter, inpkt,
! 1963: v6sizeof(struct info_monitor));
! 1964: for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0;
! 1965: md = md->mru_next) {
! 1966: im->lasttime = htonl((u_int32)((current_time -
! 1967: md->firsttime) / md->count));
! 1968: im->firsttime = htonl((u_int32)(current_time - md->lasttime));
! 1969: im->restr = htonl((u_int32)md->flags);
! 1970: im->count = htonl((u_int32)(md->count));
! 1971: if (IS_IPV6(&md->rmtadr)) {
! 1972: if (!client_v6_capable)
! 1973: continue;
! 1974: im->addr6 = SOCK_ADDR6(&md->rmtadr);
! 1975: im->v6_flag = 1;
! 1976: } else {
! 1977: im->addr = NSRCADR(&md->rmtadr);
! 1978: if (client_v6_capable)
! 1979: im->v6_flag = 0;
! 1980: }
! 1981: im->port = md->rmtport;
! 1982: im->mode = md->mode;
! 1983: im->version = md->version;
! 1984: im = (struct info_monitor *)more_pkt();
! 1985: }
! 1986: flush_pkt();
! 1987: }
! 1988:
! 1989: /*
! 1990: * mon_getlist - return monitor data
! 1991: */
! 1992: static void
! 1993: mon_getlist_1(
! 1994: sockaddr_u *srcadr,
! 1995: struct interface *inter,
! 1996: struct req_pkt *inpkt
! 1997: )
! 1998: {
! 1999: register struct info_monitor_1 *im;
! 2000: register struct mon_data *md;
! 2001: extern struct mon_data mon_mru_list;
! 2002: extern int mon_enabled;
! 2003:
! 2004: if (!mon_enabled) {
! 2005: req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
! 2006: return;
! 2007: }
! 2008: im = (struct info_monitor_1 *)prepare_pkt(srcadr, inter, inpkt,
! 2009: v6sizeof(struct info_monitor_1));
! 2010: for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0;
! 2011: md = md->mru_next) {
! 2012: im->lasttime = htonl((u_int32)((current_time -
! 2013: md->firsttime) / md->count));
! 2014: im->firsttime = htonl((u_int32)(current_time - md->lasttime));
! 2015: im->restr = htonl((u_int32)md->flags);
! 2016: im->count = htonl((u_int32)md->count);
! 2017: if (IS_IPV6(&md->rmtadr)) {
! 2018: if (!client_v6_capable)
! 2019: continue;
! 2020: im->addr6 = SOCK_ADDR6(&md->rmtadr);
! 2021: im->v6_flag = 1;
! 2022: im->daddr6 = SOCK_ADDR6(&md->interface->sin);
! 2023: } else {
! 2024: im->addr = NSRCADR(&md->rmtadr);
! 2025: if (client_v6_capable)
! 2026: im->v6_flag = 0;
! 2027: if (MDF_BCAST == md->cast_flags)
! 2028: im->daddr = NSRCADR(&md->interface->bcast);
! 2029: else if (md->cast_flags) {
! 2030: im->daddr = NSRCADR(&md->interface->sin);
! 2031: if (!im->daddr)
! 2032: im->daddr = NSRCADR(&md->interface->bcast);
! 2033: } else
! 2034: im->daddr = 4;
! 2035: }
! 2036: im->flags = htonl(md->cast_flags);
! 2037: im->port = md->rmtport;
! 2038: im->mode = md->mode;
! 2039: im->version = md->version;
! 2040: im = (struct info_monitor_1 *)more_pkt();
! 2041: }
! 2042: flush_pkt();
! 2043: }
! 2044:
! 2045: /*
! 2046: * Module entry points and the flags they correspond with
! 2047: */
! 2048: struct reset_entry {
! 2049: int flag; /* flag this corresponds to */
! 2050: void (*handler) (void); /* routine to handle request */
! 2051: };
! 2052:
! 2053: struct reset_entry reset_entries[] = {
! 2054: { RESET_FLAG_ALLPEERS, peer_all_reset },
! 2055: { RESET_FLAG_IO, io_clr_stats },
! 2056: { RESET_FLAG_SYS, proto_clr_stats },
! 2057: { RESET_FLAG_MEM, peer_clr_stats },
! 2058: { RESET_FLAG_TIMER, timer_clr_stats },
! 2059: { RESET_FLAG_AUTH, reset_auth_stats },
! 2060: { RESET_FLAG_CTL, ctl_clr_stats },
! 2061: { 0, 0 }
! 2062: };
! 2063:
! 2064: /*
! 2065: * reset_stats - reset statistic counters here and there
! 2066: */
! 2067: static void
! 2068: reset_stats(
! 2069: sockaddr_u *srcadr,
! 2070: struct interface *inter,
! 2071: struct req_pkt *inpkt
! 2072: )
! 2073: {
! 2074: struct reset_flags *rflags;
! 2075: u_long flags;
! 2076: struct reset_entry *rent;
! 2077:
! 2078: if (INFO_NITEMS(inpkt->err_nitems) > 1) {
! 2079: msyslog(LOG_ERR, "reset_stats: err_nitems > 1");
! 2080: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
! 2081: return;
! 2082: }
! 2083:
! 2084: rflags = (struct reset_flags *)inpkt->data;
! 2085: flags = ntohl(rflags->flags);
! 2086:
! 2087: if (flags & ~RESET_ALLFLAGS) {
! 2088: msyslog(LOG_ERR, "reset_stats: reset leaves %#lx",
! 2089: flags & ~RESET_ALLFLAGS);
! 2090: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
! 2091: return;
! 2092: }
! 2093:
! 2094: for (rent = reset_entries; rent->flag != 0; rent++) {
! 2095: if (flags & rent->flag)
! 2096: (*rent->handler)();
! 2097: }
! 2098: req_ack(srcadr, inter, inpkt, INFO_OKAY);
! 2099: }
! 2100:
! 2101:
! 2102: /*
! 2103: * reset_peer - clear a peer's statistics
! 2104: */
! 2105: static void
! 2106: reset_peer(
! 2107: sockaddr_u *srcadr,
! 2108: struct interface *inter,
! 2109: struct req_pkt *inpkt
! 2110: )
! 2111: {
! 2112: struct conf_unpeer *cp;
! 2113: int items;
! 2114: struct peer *peer;
! 2115: sockaddr_u peeraddr;
! 2116: int bad;
! 2117:
! 2118: /*
! 2119: * We check first to see that every peer exists. If not,
! 2120: * we return an error.
! 2121: */
! 2122:
! 2123: items = INFO_NITEMS(inpkt->err_nitems);
! 2124: cp = (struct conf_unpeer *)inpkt->data;
! 2125:
! 2126: bad = 0;
! 2127: while (items-- > 0 && !bad) {
! 2128: ZERO_SOCK(&peeraddr);
! 2129: if (client_v6_capable && cp->v6_flag) {
! 2130: AF(&peeraddr) = AF_INET6;
! 2131: SOCK_ADDR6(&peeraddr) = cp->peeraddr6;
! 2132: } else {
! 2133: AF(&peeraddr) = AF_INET;
! 2134: NSRCADR(&peeraddr) = cp->peeraddr;
! 2135: }
! 2136:
! 2137: #ifdef ISC_PLATFORM_HAVESALEN
! 2138: peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
! 2139: #endif
! 2140: peer = findexistingpeer(&peeraddr, NULL, -1, 0);
! 2141: if (NULL == peer)
! 2142: bad++;
! 2143: cp = (struct conf_unpeer *)((char *)cp +
! 2144: INFO_ITEMSIZE(inpkt->mbz_itemsize));
! 2145: }
! 2146:
! 2147: if (bad) {
! 2148: req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
! 2149: return;
! 2150: }
! 2151:
! 2152: /*
! 2153: * Now do it in earnest.
! 2154: */
! 2155:
! 2156: items = INFO_NITEMS(inpkt->err_nitems);
! 2157: cp = (struct conf_unpeer *)inpkt->data;
! 2158: while (items-- > 0) {
! 2159: ZERO_SOCK(&peeraddr);
! 2160: if (client_v6_capable && cp->v6_flag) {
! 2161: AF(&peeraddr) = AF_INET6;
! 2162: SOCK_ADDR6(&peeraddr) = cp->peeraddr6;
! 2163: } else {
! 2164: AF(&peeraddr) = AF_INET;
! 2165: NSRCADR(&peeraddr) = cp->peeraddr;
! 2166: }
! 2167: SET_PORT(&peeraddr, 123);
! 2168: #ifdef ISC_PLATFORM_HAVESALEN
! 2169: peeraddr.sa.sa_len = SOCKLEN(&peeraddr);
! 2170: #endif
! 2171: peer = findexistingpeer(&peeraddr, NULL, -1, 0);
! 2172: while (peer != NULL) {
! 2173: peer_reset(peer);
! 2174: peer = findexistingpeer(&peeraddr, peer, -1, 0);
! 2175: }
! 2176: cp = (struct conf_unpeer *)((char *)cp +
! 2177: INFO_ITEMSIZE(inpkt->mbz_itemsize));
! 2178: }
! 2179:
! 2180: req_ack(srcadr, inter, inpkt, INFO_OKAY);
! 2181: }
! 2182:
! 2183:
! 2184: /*
! 2185: * do_key_reread - reread the encryption key file
! 2186: */
! 2187: static void
! 2188: do_key_reread(
! 2189: sockaddr_u *srcadr,
! 2190: struct interface *inter,
! 2191: struct req_pkt *inpkt
! 2192: )
! 2193: {
! 2194: rereadkeys();
! 2195: req_ack(srcadr, inter, inpkt, INFO_OKAY);
! 2196: }
! 2197:
! 2198:
! 2199: /*
! 2200: * trust_key - make one or more keys trusted
! 2201: */
! 2202: static void
! 2203: trust_key(
! 2204: sockaddr_u *srcadr,
! 2205: struct interface *inter,
! 2206: struct req_pkt *inpkt
! 2207: )
! 2208: {
! 2209: do_trustkey(srcadr, inter, inpkt, 1);
! 2210: }
! 2211:
! 2212:
! 2213: /*
! 2214: * untrust_key - make one or more keys untrusted
! 2215: */
! 2216: static void
! 2217: untrust_key(
! 2218: sockaddr_u *srcadr,
! 2219: struct interface *inter,
! 2220: struct req_pkt *inpkt
! 2221: )
! 2222: {
! 2223: do_trustkey(srcadr, inter, inpkt, 0);
! 2224: }
! 2225:
! 2226:
! 2227: /*
! 2228: * do_trustkey - make keys either trustable or untrustable
! 2229: */
! 2230: static void
! 2231: do_trustkey(
! 2232: sockaddr_u *srcadr,
! 2233: struct interface *inter,
! 2234: struct req_pkt *inpkt,
! 2235: u_long trust
! 2236: )
! 2237: {
! 2238: register u_long *kp;
! 2239: register int items;
! 2240:
! 2241: items = INFO_NITEMS(inpkt->err_nitems);
! 2242: kp = (u_long *)inpkt->data;
! 2243: while (items-- > 0) {
! 2244: authtrust(*kp, trust);
! 2245: kp++;
! 2246: }
! 2247:
! 2248: req_ack(srcadr, inter, inpkt, INFO_OKAY);
! 2249: }
! 2250:
! 2251:
! 2252: /*
! 2253: * get_auth_info - return some stats concerning the authentication module
! 2254: */
! 2255: static void
! 2256: get_auth_info(
! 2257: sockaddr_u *srcadr,
! 2258: struct interface *inter,
! 2259: struct req_pkt *inpkt
! 2260: )
! 2261: {
! 2262: register struct info_auth *ia;
! 2263:
! 2264: /*
! 2265: * Importations from the authentication module
! 2266: */
! 2267: extern u_long authnumkeys;
! 2268: extern int authnumfreekeys;
! 2269: extern u_long authkeylookups;
! 2270: extern u_long authkeynotfound;
! 2271: extern u_long authencryptions;
! 2272: extern u_long authdecryptions;
! 2273: extern u_long authkeyuncached;
! 2274: extern u_long authkeyexpired;
! 2275:
! 2276: ia = (struct info_auth *)prepare_pkt(srcadr, inter, inpkt,
! 2277: sizeof(struct info_auth));
! 2278:
! 2279: ia->numkeys = htonl((u_int32)authnumkeys);
! 2280: ia->numfreekeys = htonl((u_int32)authnumfreekeys);
! 2281: ia->keylookups = htonl((u_int32)authkeylookups);
! 2282: ia->keynotfound = htonl((u_int32)authkeynotfound);
! 2283: ia->encryptions = htonl((u_int32)authencryptions);
! 2284: ia->decryptions = htonl((u_int32)authdecryptions);
! 2285: ia->keyuncached = htonl((u_int32)authkeyuncached);
! 2286: ia->expired = htonl((u_int32)authkeyexpired);
! 2287: ia->timereset = htonl((u_int32)(current_time - auth_timereset));
! 2288:
! 2289: (void) more_pkt();
! 2290: flush_pkt();
! 2291: }
! 2292:
! 2293:
! 2294:
! 2295: /*
! 2296: * reset_auth_stats - reset the authentication stat counters. Done here
! 2297: * to keep ntp-isms out of the authentication module
! 2298: */
! 2299: static void
! 2300: reset_auth_stats(void)
! 2301: {
! 2302: /*
! 2303: * Importations from the authentication module
! 2304: */
! 2305: extern u_long authkeylookups;
! 2306: extern u_long authkeynotfound;
! 2307: extern u_long authencryptions;
! 2308: extern u_long authdecryptions;
! 2309: extern u_long authkeyuncached;
! 2310:
! 2311: authkeylookups = 0;
! 2312: authkeynotfound = 0;
! 2313: authencryptions = 0;
! 2314: authdecryptions = 0;
! 2315: authkeyuncached = 0;
! 2316: auth_timereset = current_time;
! 2317: }
! 2318:
! 2319:
! 2320: /*
! 2321: * req_get_traps - return information about current trap holders
! 2322: */
! 2323: static void
! 2324: req_get_traps(
! 2325: sockaddr_u *srcadr,
! 2326: struct interface *inter,
! 2327: struct req_pkt *inpkt
! 2328: )
! 2329: {
! 2330: register struct info_trap *it;
! 2331: register struct ctl_trap *tr;
! 2332: register int i;
! 2333:
! 2334: /*
! 2335: * Imported from the control module
! 2336: */
! 2337: extern struct ctl_trap ctl_trap[];
! 2338: extern int num_ctl_traps;
! 2339:
! 2340: if (num_ctl_traps == 0) {
! 2341: req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
! 2342: return;
! 2343: }
! 2344:
! 2345: it = (struct info_trap *)prepare_pkt(srcadr, inter, inpkt,
! 2346: v6sizeof(struct info_trap));
! 2347:
! 2348: for (i = 0, tr = ctl_trap; i < CTL_MAXTRAPS; i++, tr++) {
! 2349: if (tr->tr_flags & TRAP_INUSE) {
! 2350: if (IS_IPV4(&tr->tr_addr)) {
! 2351: if (tr->tr_localaddr == any_interface)
! 2352: it->local_address = 0;
! 2353: else
! 2354: it->local_address
! 2355: = NSRCADR(&tr->tr_localaddr->sin);
! 2356: it->trap_address = NSRCADR(&tr->tr_addr);
! 2357: if (client_v6_capable)
! 2358: it->v6_flag = 0;
! 2359: } else {
! 2360: if (!client_v6_capable)
! 2361: continue;
! 2362: it->local_address6
! 2363: = SOCK_ADDR6(&tr->tr_localaddr->sin);
! 2364: it->trap_address6 = SOCK_ADDR6(&tr->tr_addr);
! 2365: it->v6_flag = 1;
! 2366: }
! 2367: it->trap_port = NSRCPORT(&tr->tr_addr);
! 2368: it->sequence = htons(tr->tr_sequence);
! 2369: it->settime = htonl((u_int32)(current_time - tr->tr_settime));
! 2370: it->origtime = htonl((u_int32)(current_time - tr->tr_origtime));
! 2371: it->resets = htonl((u_int32)tr->tr_resets);
! 2372: it->flags = htonl((u_int32)tr->tr_flags);
! 2373: it = (struct info_trap *)more_pkt();
! 2374: }
! 2375: }
! 2376: flush_pkt();
! 2377: }
! 2378:
! 2379:
! 2380: /*
! 2381: * req_set_trap - configure a trap
! 2382: */
! 2383: static void
! 2384: req_set_trap(
! 2385: sockaddr_u *srcadr,
! 2386: struct interface *inter,
! 2387: struct req_pkt *inpkt
! 2388: )
! 2389: {
! 2390: do_setclr_trap(srcadr, inter, inpkt, 1);
! 2391: }
! 2392:
! 2393:
! 2394:
! 2395: /*
! 2396: * req_clr_trap - unconfigure a trap
! 2397: */
! 2398: static void
! 2399: req_clr_trap(
! 2400: sockaddr_u *srcadr,
! 2401: struct interface *inter,
! 2402: struct req_pkt *inpkt
! 2403: )
! 2404: {
! 2405: do_setclr_trap(srcadr, inter, inpkt, 0);
! 2406: }
! 2407:
! 2408:
! 2409:
! 2410: /*
! 2411: * do_setclr_trap - do the grunge work of (un)configuring a trap
! 2412: */
! 2413: static void
! 2414: do_setclr_trap(
! 2415: sockaddr_u *srcadr,
! 2416: struct interface *inter,
! 2417: struct req_pkt *inpkt,
! 2418: int set
! 2419: )
! 2420: {
! 2421: register struct conf_trap *ct;
! 2422: register struct interface *linter;
! 2423: int res;
! 2424: sockaddr_u laddr;
! 2425:
! 2426: /*
! 2427: * Prepare sockaddr
! 2428: */
! 2429: ZERO_SOCK(&laddr);
! 2430: AF(&laddr) = AF(srcadr);
! 2431: SET_PORT(&laddr, NTP_PORT);
! 2432:
! 2433: /*
! 2434: * Restrict ourselves to one item only. This eliminates
! 2435: * the error reporting problem.
! 2436: */
! 2437: if (INFO_NITEMS(inpkt->err_nitems) > 1) {
! 2438: msyslog(LOG_ERR, "do_setclr_trap: err_nitems > 1");
! 2439: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
! 2440: return;
! 2441: }
! 2442: ct = (struct conf_trap *)inpkt->data;
! 2443:
! 2444: /*
! 2445: * Look for the local interface. If none, use the default.
! 2446: */
! 2447: if (ct->local_address == 0) {
! 2448: linter = any_interface;
! 2449: } else {
! 2450: if (IS_IPV4(&laddr))
! 2451: NSRCADR(&laddr) = ct->local_address;
! 2452: else
! 2453: SOCK_ADDR6(&laddr) = ct->local_address6;
! 2454: linter = findinterface(&laddr);
! 2455: if (NULL == linter) {
! 2456: req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
! 2457: return;
! 2458: }
! 2459: }
! 2460:
! 2461: if (IS_IPV4(&laddr))
! 2462: NSRCADR(&laddr) = ct->trap_address;
! 2463: else
! 2464: SOCK_ADDR6(&laddr) = ct->trap_address6;
! 2465: if (ct->trap_port)
! 2466: NSRCPORT(&laddr) = ct->trap_port;
! 2467: else
! 2468: SET_PORT(&laddr, TRAPPORT);
! 2469:
! 2470: if (set) {
! 2471: res = ctlsettrap(&laddr, linter, 0,
! 2472: INFO_VERSION(inpkt->rm_vn_mode));
! 2473: } else {
! 2474: res = ctlclrtrap(&laddr, linter, 0);
! 2475: }
! 2476:
! 2477: if (!res) {
! 2478: req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
! 2479: } else {
! 2480: req_ack(srcadr, inter, inpkt, INFO_OKAY);
! 2481: }
! 2482: return;
! 2483: }
! 2484:
! 2485:
! 2486:
! 2487: /*
! 2488: * set_request_keyid - set the keyid used to authenticate requests
! 2489: */
! 2490: static void
! 2491: set_request_keyid(
! 2492: sockaddr_u *srcadr,
! 2493: struct interface *inter,
! 2494: struct req_pkt *inpkt
! 2495: )
! 2496: {
! 2497: keyid_t *pkeyid;
! 2498:
! 2499: /*
! 2500: * Restrict ourselves to one item only.
! 2501: */
! 2502: if (INFO_NITEMS(inpkt->err_nitems) > 1) {
! 2503: msyslog(LOG_ERR, "set_request_keyid: err_nitems > 1");
! 2504: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
! 2505: return;
! 2506: }
! 2507:
! 2508: pkeyid = (keyid_t *)inpkt->data;
! 2509: info_auth_keyid = ntohl(*pkeyid);
! 2510: req_ack(srcadr, inter, inpkt, INFO_OKAY);
! 2511: }
! 2512:
! 2513:
! 2514:
! 2515: /*
! 2516: * set_control_keyid - set the keyid used to authenticate requests
! 2517: */
! 2518: static void
! 2519: set_control_keyid(
! 2520: sockaddr_u *srcadr,
! 2521: struct interface *inter,
! 2522: struct req_pkt *inpkt
! 2523: )
! 2524: {
! 2525: keyid_t *pkeyid;
! 2526: extern keyid_t ctl_auth_keyid;
! 2527:
! 2528: /*
! 2529: * Restrict ourselves to one item only.
! 2530: */
! 2531: if (INFO_NITEMS(inpkt->err_nitems) > 1) {
! 2532: msyslog(LOG_ERR, "set_control_keyid: err_nitems > 1");
! 2533: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
! 2534: return;
! 2535: }
! 2536:
! 2537: pkeyid = (keyid_t *)inpkt->data;
! 2538: ctl_auth_keyid = ntohl(*pkeyid);
! 2539: req_ack(srcadr, inter, inpkt, INFO_OKAY);
! 2540: }
! 2541:
! 2542:
! 2543:
! 2544: /*
! 2545: * get_ctl_stats - return some stats concerning the control message module
! 2546: */
! 2547: static void
! 2548: get_ctl_stats(
! 2549: sockaddr_u *srcadr,
! 2550: struct interface *inter,
! 2551: struct req_pkt *inpkt
! 2552: )
! 2553: {
! 2554: register struct info_control *ic;
! 2555:
! 2556: /*
! 2557: * Importations from the control module
! 2558: */
! 2559: extern u_long ctltimereset;
! 2560: extern u_long numctlreq;
! 2561: extern u_long numctlbadpkts;
! 2562: extern u_long numctlresponses;
! 2563: extern u_long numctlfrags;
! 2564: extern u_long numctlerrors;
! 2565: extern u_long numctltooshort;
! 2566: extern u_long numctlinputresp;
! 2567: extern u_long numctlinputfrag;
! 2568: extern u_long numctlinputerr;
! 2569: extern u_long numctlbadoffset;
! 2570: extern u_long numctlbadversion;
! 2571: extern u_long numctldatatooshort;
! 2572: extern u_long numctlbadop;
! 2573: extern u_long numasyncmsgs;
! 2574:
! 2575: ic = (struct info_control *)prepare_pkt(srcadr, inter, inpkt,
! 2576: sizeof(struct info_control));
! 2577:
! 2578: ic->ctltimereset = htonl((u_int32)(current_time - ctltimereset));
! 2579: ic->numctlreq = htonl((u_int32)numctlreq);
! 2580: ic->numctlbadpkts = htonl((u_int32)numctlbadpkts);
! 2581: ic->numctlresponses = htonl((u_int32)numctlresponses);
! 2582: ic->numctlfrags = htonl((u_int32)numctlfrags);
! 2583: ic->numctlerrors = htonl((u_int32)numctlerrors);
! 2584: ic->numctltooshort = htonl((u_int32)numctltooshort);
! 2585: ic->numctlinputresp = htonl((u_int32)numctlinputresp);
! 2586: ic->numctlinputfrag = htonl((u_int32)numctlinputfrag);
! 2587: ic->numctlinputerr = htonl((u_int32)numctlinputerr);
! 2588: ic->numctlbadoffset = htonl((u_int32)numctlbadoffset);
! 2589: ic->numctlbadversion = htonl((u_int32)numctlbadversion);
! 2590: ic->numctldatatooshort = htonl((u_int32)numctldatatooshort);
! 2591: ic->numctlbadop = htonl((u_int32)numctlbadop);
! 2592: ic->numasyncmsgs = htonl((u_int32)numasyncmsgs);
! 2593:
! 2594: (void) more_pkt();
! 2595: flush_pkt();
! 2596: }
! 2597:
! 2598:
! 2599: #ifdef KERNEL_PLL
! 2600: /*
! 2601: * get_kernel_info - get kernel pll/pps information
! 2602: */
! 2603: static void
! 2604: get_kernel_info(
! 2605: sockaddr_u *srcadr,
! 2606: struct interface *inter,
! 2607: struct req_pkt *inpkt
! 2608: )
! 2609: {
! 2610: register struct info_kernel *ik;
! 2611: struct timex ntx;
! 2612:
! 2613: if (!pll_control) {
! 2614: req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
! 2615: return;
! 2616: }
! 2617:
! 2618: memset((char *)&ntx, 0, sizeof(ntx));
! 2619: if (ntp_adjtime(&ntx) < 0)
! 2620: msyslog(LOG_ERR, "get_kernel_info: ntp_adjtime() failed: %m");
! 2621: ik = (struct info_kernel *)prepare_pkt(srcadr, inter, inpkt,
! 2622: sizeof(struct info_kernel));
! 2623:
! 2624: /*
! 2625: * pll variables
! 2626: */
! 2627: ik->offset = htonl((u_int32)ntx.offset);
! 2628: ik->freq = htonl((u_int32)ntx.freq);
! 2629: ik->maxerror = htonl((u_int32)ntx.maxerror);
! 2630: ik->esterror = htonl((u_int32)ntx.esterror);
! 2631: ik->status = htons(ntx.status);
! 2632: ik->constant = htonl((u_int32)ntx.constant);
! 2633: ik->precision = htonl((u_int32)ntx.precision);
! 2634: ik->tolerance = htonl((u_int32)ntx.tolerance);
! 2635:
! 2636: /*
! 2637: * pps variables
! 2638: */
! 2639: ik->ppsfreq = htonl((u_int32)ntx.ppsfreq);
! 2640: ik->jitter = htonl((u_int32)ntx.jitter);
! 2641: ik->shift = htons(ntx.shift);
! 2642: ik->stabil = htonl((u_int32)ntx.stabil);
! 2643: ik->jitcnt = htonl((u_int32)ntx.jitcnt);
! 2644: ik->calcnt = htonl((u_int32)ntx.calcnt);
! 2645: ik->errcnt = htonl((u_int32)ntx.errcnt);
! 2646: ik->stbcnt = htonl((u_int32)ntx.stbcnt);
! 2647:
! 2648: (void) more_pkt();
! 2649: flush_pkt();
! 2650: }
! 2651: #endif /* KERNEL_PLL */
! 2652:
! 2653:
! 2654: #ifdef REFCLOCK
! 2655: /*
! 2656: * get_clock_info - get info about a clock
! 2657: */
! 2658: static void
! 2659: get_clock_info(
! 2660: sockaddr_u *srcadr,
! 2661: struct interface *inter,
! 2662: struct req_pkt *inpkt
! 2663: )
! 2664: {
! 2665: register struct info_clock *ic;
! 2666: register u_int32 *clkaddr;
! 2667: register int items;
! 2668: struct refclockstat clock_stat;
! 2669: sockaddr_u addr;
! 2670: l_fp ltmp;
! 2671:
! 2672: ZERO_SOCK(&addr);
! 2673: AF(&addr) = AF_INET;
! 2674: #ifdef ISC_PLATFORM_HAVESALEN
! 2675: addr.sa.sa_len = SOCKLEN(&addr);
! 2676: #endif
! 2677: SET_PORT(&addr, NTP_PORT);
! 2678: items = INFO_NITEMS(inpkt->err_nitems);
! 2679: clkaddr = (u_int32 *) inpkt->data;
! 2680:
! 2681: ic = (struct info_clock *)prepare_pkt(srcadr, inter, inpkt,
! 2682: sizeof(struct info_clock));
! 2683:
! 2684: while (items-- > 0) {
! 2685: NSRCADR(&addr) = *clkaddr++;
! 2686: if (!ISREFCLOCKADR(&addr) ||
! 2687: findexistingpeer(&addr, NULL, -1, 0) == NULL) {
! 2688: req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
! 2689: return;
! 2690: }
! 2691:
! 2692: clock_stat.kv_list = (struct ctl_var *)0;
! 2693:
! 2694: refclock_control(&addr, NULL, &clock_stat);
! 2695:
! 2696: ic->clockadr = NSRCADR(&addr);
! 2697: ic->type = clock_stat.type;
! 2698: ic->flags = clock_stat.flags;
! 2699: ic->lastevent = clock_stat.lastevent;
! 2700: ic->currentstatus = clock_stat.currentstatus;
! 2701: ic->polls = htonl((u_int32)clock_stat.polls);
! 2702: ic->noresponse = htonl((u_int32)clock_stat.noresponse);
! 2703: ic->badformat = htonl((u_int32)clock_stat.badformat);
! 2704: ic->baddata = htonl((u_int32)clock_stat.baddata);
! 2705: ic->timestarted = htonl((u_int32)clock_stat.timereset);
! 2706: DTOLFP(clock_stat.fudgetime1, <mp);
! 2707: HTONL_FP(<mp, &ic->fudgetime1);
! 2708: DTOLFP(clock_stat.fudgetime2, <mp);
! 2709: HTONL_FP(<mp, &ic->fudgetime2);
! 2710: ic->fudgeval1 = htonl((u_int32)clock_stat.fudgeval1);
! 2711: ic->fudgeval2 = htonl(clock_stat.fudgeval2);
! 2712:
! 2713: free_varlist(clock_stat.kv_list);
! 2714:
! 2715: ic = (struct info_clock *)more_pkt();
! 2716: }
! 2717: flush_pkt();
! 2718: }
! 2719:
! 2720:
! 2721:
! 2722: /*
! 2723: * set_clock_fudge - get a clock's fudge factors
! 2724: */
! 2725: static void
! 2726: set_clock_fudge(
! 2727: sockaddr_u *srcadr,
! 2728: struct interface *inter,
! 2729: struct req_pkt *inpkt
! 2730: )
! 2731: {
! 2732: register struct conf_fudge *cf;
! 2733: register int items;
! 2734: struct refclockstat clock_stat;
! 2735: sockaddr_u addr;
! 2736: l_fp ltmp;
! 2737:
! 2738: ZERO_SOCK(&addr);
! 2739: memset((char *)&clock_stat, 0, sizeof clock_stat);
! 2740: items = INFO_NITEMS(inpkt->err_nitems);
! 2741: cf = (struct conf_fudge *) inpkt->data;
! 2742:
! 2743: while (items-- > 0) {
! 2744: AF(&addr) = AF_INET;
! 2745: NSRCADR(&addr) = cf->clockadr;
! 2746: #ifdef ISC_PLATFORM_HAVESALEN
! 2747: addr.sa.sa_len = SOCKLEN(&addr);
! 2748: #endif
! 2749: SET_PORT(&addr, NTP_PORT);
! 2750: if (!ISREFCLOCKADR(&addr) ||
! 2751: findexistingpeer(&addr, NULL, -1, 0) == 0) {
! 2752: req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
! 2753: return;
! 2754: }
! 2755:
! 2756: switch(ntohl(cf->which)) {
! 2757: case FUDGE_TIME1:
! 2758: NTOHL_FP(&cf->fudgetime, <mp);
! 2759: LFPTOD(<mp, clock_stat.fudgetime1);
! 2760: clock_stat.haveflags = CLK_HAVETIME1;
! 2761: break;
! 2762: case FUDGE_TIME2:
! 2763: NTOHL_FP(&cf->fudgetime, <mp);
! 2764: LFPTOD(<mp, clock_stat.fudgetime2);
! 2765: clock_stat.haveflags = CLK_HAVETIME2;
! 2766: break;
! 2767: case FUDGE_VAL1:
! 2768: clock_stat.fudgeval1 = ntohl(cf->fudgeval_flags);
! 2769: clock_stat.haveflags = CLK_HAVEVAL1;
! 2770: break;
! 2771: case FUDGE_VAL2:
! 2772: clock_stat.fudgeval2 = ntohl(cf->fudgeval_flags);
! 2773: clock_stat.haveflags = CLK_HAVEVAL2;
! 2774: break;
! 2775: case FUDGE_FLAGS:
! 2776: clock_stat.flags = (u_char) (ntohl(cf->fudgeval_flags) & 0xf);
! 2777: clock_stat.haveflags =
! 2778: (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4);
! 2779: break;
! 2780: default:
! 2781: msyslog(LOG_ERR, "set_clock_fudge: default!");
! 2782: req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
! 2783: return;
! 2784: }
! 2785:
! 2786: refclock_control(&addr, &clock_stat, (struct refclockstat *)0);
! 2787: }
! 2788:
! 2789: req_ack(srcadr, inter, inpkt, INFO_OKAY);
! 2790: }
! 2791: #endif
! 2792:
! 2793: #ifdef REFCLOCK
! 2794: /*
! 2795: * get_clkbug_info - get debugging info about a clock
! 2796: */
! 2797: static void
! 2798: get_clkbug_info(
! 2799: sockaddr_u *srcadr,
! 2800: struct interface *inter,
! 2801: struct req_pkt *inpkt
! 2802: )
! 2803: {
! 2804: register int i;
! 2805: register struct info_clkbug *ic;
! 2806: register u_int32 *clkaddr;
! 2807: register int items;
! 2808: struct refclockbug bug;
! 2809: sockaddr_u addr;
! 2810:
! 2811: ZERO_SOCK(&addr);
! 2812: AF(&addr) = AF_INET;
! 2813: #ifdef ISC_PLATFORM_HAVESALEN
! 2814: addr.sa.sa_len = SOCKLEN(&addr);
! 2815: #endif
! 2816: SET_PORT(&addr, NTP_PORT);
! 2817: items = INFO_NITEMS(inpkt->err_nitems);
! 2818: clkaddr = (u_int32 *) inpkt->data;
! 2819:
! 2820: ic = (struct info_clkbug *)prepare_pkt(srcadr, inter, inpkt,
! 2821: sizeof(struct info_clkbug));
! 2822:
! 2823: while (items-- > 0) {
! 2824: NSRCADR(&addr) = *clkaddr++;
! 2825: if (!ISREFCLOCKADR(&addr) ||
! 2826: findexistingpeer(&addr, NULL, -1, 0) == 0) {
! 2827: req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
! 2828: return;
! 2829: }
! 2830:
! 2831: memset((char *)&bug, 0, sizeof bug);
! 2832: refclock_buginfo(&addr, &bug);
! 2833: if (bug.nvalues == 0 && bug.ntimes == 0) {
! 2834: req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
! 2835: return;
! 2836: }
! 2837:
! 2838: ic->clockadr = NSRCADR(&addr);
! 2839: i = bug.nvalues;
! 2840: if (i > NUMCBUGVALUES)
! 2841: i = NUMCBUGVALUES;
! 2842: ic->nvalues = (u_char)i;
! 2843: ic->svalues = htons((u_short) (bug.svalues & ((1<<i)-1)));
! 2844: while (--i >= 0)
! 2845: ic->values[i] = htonl(bug.values[i]);
! 2846:
! 2847: i = bug.ntimes;
! 2848: if (i > NUMCBUGTIMES)
! 2849: i = NUMCBUGTIMES;
! 2850: ic->ntimes = (u_char)i;
! 2851: ic->stimes = htonl(bug.stimes);
! 2852: while (--i >= 0) {
! 2853: HTONL_FP(&bug.times[i], &ic->times[i]);
! 2854: }
! 2855:
! 2856: ic = (struct info_clkbug *)more_pkt();
! 2857: }
! 2858: flush_pkt();
! 2859: }
! 2860: #endif
! 2861:
! 2862: /*
! 2863: * receiver of interface structures
! 2864: */
! 2865: static void
! 2866: fill_info_if_stats(void *data, interface_info_t *interface_info)
! 2867: {
! 2868: struct info_if_stats **ifsp = (struct info_if_stats **)data;
! 2869: struct info_if_stats *ifs = *ifsp;
! 2870: endpt *ep = interface_info->ep;
! 2871:
! 2872: memset(ifs, 0, sizeof(*ifs));
! 2873:
! 2874: if (IS_IPV6(&ep->sin)) {
! 2875: if (!client_v6_capable) {
! 2876: return;
! 2877: }
! 2878: ifs->v6_flag = 1;
! 2879: ifs->unaddr.addr6 = SOCK_ADDR6(&ep->sin);
! 2880: ifs->unbcast.addr6 = SOCK_ADDR6(&ep->bcast);
! 2881: ifs->unmask.addr6 = SOCK_ADDR6(&ep->mask);
! 2882: } else {
! 2883: ifs->v6_flag = 0;
! 2884: ifs->unaddr.addr = SOCK_ADDR4(&ep->sin);
! 2885: ifs->unbcast.addr = SOCK_ADDR4(&ep->bcast);
! 2886: ifs->unmask.addr = SOCK_ADDR4(&ep->mask);
! 2887: }
! 2888: ifs->v6_flag = htonl(ifs->v6_flag);
! 2889: strncpy(ifs->name, ep->name, sizeof(ifs->name));
! 2890: ifs->family = htons(ep->family);
! 2891: ifs->flags = htonl(ep->flags);
! 2892: ifs->last_ttl = htonl(ep->last_ttl);
! 2893: ifs->num_mcast = htonl(ep->num_mcast);
! 2894: ifs->received = htonl(ep->received);
! 2895: ifs->sent = htonl(ep->sent);
! 2896: ifs->notsent = htonl(ep->notsent);
! 2897: ifs->ifindex = htonl(ep->ifindex);
! 2898: /* scope no longer in struct interface, in in6_addr typically */
! 2899: ifs->scopeid = ifs->ifindex;
! 2900: ifs->ifnum = htonl(ep->ifnum);
! 2901: ifs->uptime = htonl(current_time - ep->starttime);
! 2902: ifs->ignore_packets = ep->ignore_packets;
! 2903: ifs->peercnt = htonl(ep->peercnt);
! 2904: ifs->action = interface_info->action;
! 2905:
! 2906: *ifsp = (struct info_if_stats *)more_pkt();
! 2907: }
! 2908:
! 2909: /*
! 2910: * get_if_stats - get interface statistics
! 2911: */
! 2912: static void
! 2913: get_if_stats(
! 2914: sockaddr_u *srcadr,
! 2915: struct interface *inter,
! 2916: struct req_pkt *inpkt
! 2917: )
! 2918: {
! 2919: struct info_if_stats *ifs;
! 2920:
! 2921: DPRINTF(3, ("wants interface statistics\n"));
! 2922:
! 2923: ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt,
! 2924: v6sizeof(struct info_if_stats));
! 2925:
! 2926: interface_enumerate(fill_info_if_stats, &ifs);
! 2927:
! 2928: flush_pkt();
! 2929: }
! 2930:
! 2931: static void
! 2932: do_if_reload(
! 2933: sockaddr_u *srcadr,
! 2934: struct interface *inter,
! 2935: struct req_pkt *inpkt
! 2936: )
! 2937: {
! 2938: struct info_if_stats *ifs;
! 2939:
! 2940: DPRINTF(3, ("wants interface reload\n"));
! 2941:
! 2942: ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt,
! 2943: v6sizeof(struct info_if_stats));
! 2944:
! 2945: interface_update(fill_info_if_stats, &ifs);
! 2946:
! 2947: flush_pkt();
! 2948: }
! 2949:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>