2 * ntp_peer.c - management of data maintained for peer associations
12 #include "ntp_stdlib.h"
14 #include "ntp_crypto.h"
18 * Table of valid association combinations
19 * ---------------------------------------
22 * peer->mode | UNSPEC ACTIVE PASSIVE CLIENT SERVER BCAST
23 * ---------- | ---------------------------------------------
24 * NO_PEER | e 1 e 1 1 1
25 * ACTIVE | e 1 1 0 0 0
26 * PASSIVE | e 1 e 0 0 0
27 * CLIENT | e 0 0 0 1 1
28 * SERVER | e 0 0 0 0 0
30 * CONTROL | e 0 0 0 0 0
31 * PRIVATE | e 0 0 0 0 0
32 * BCLIENT | e 0 0 0 e 1
34 * One point to note here: a packet in BCAST mode can potentially match
35 * a peer in CLIENT mode, but we that is a special case and we check for
36 * that early in the decision process. This avoids having to keep track
37 * of what kind of associations are possible etc... We actually
38 * circumvent that problem by requiring that the first b(m)roadcast
39 * received after the change back to BCLIENT mode sets the clock.
42 int AM[AM_MODES][AM_MODES] = {
43 /* { UNSPEC, ACTIVE, PASSIVE, CLIENT, SERVER, BCAST } */
45 /*NONE*/{ AM_ERR, AM_NEWPASS, AM_ERR, AM_FXMIT, AM_MANYCAST, AM_NEWBCL},
47 /*A*/ { AM_ERR, AM_PROCPKT, AM_PROCPKT, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
49 /*P*/ { AM_ERR, AM_PROCPKT, AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
51 /*C*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT, AM_POSSBCL},
53 /*S*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
55 /*BCST*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
57 /*CNTL*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
59 /*PRIV*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
61 /*BCL*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_ERR, AM_PROCPKT},
64 #define MATCH_ASSOC(x,y) AM[(x)][(y)]
67 * These routines manage the allocation of memory to peer structures
68 * and the maintenance of the peer hash table. The two main entry
69 * points are findpeer(), which looks for matching peer sturctures in
70 * the peer list, newpeer(), which allocates a new peer structure and
71 * adds it to the list, and unpeer(), which demobilizes the association
72 * and deallocates the structure.
77 struct peer *peer_hash[HASH_SIZE]; /* peer hash table */
78 int peer_hash_count[HASH_SIZE]; /* peers in each bucket */
79 struct peer *assoc_hash[HASH_SIZE]; /* association ID hash table */
80 int assoc_hash_count[HASH_SIZE]; /* peers in each bucket */
81 static struct peer *peer_free; /* peer structures free list */
82 int peer_free_count; /* count of free structures */
85 * Association ID. We initialize this value randomly, then assign a new
86 * value every time the peer structure is incremented.
88 static associd_t current_association_ID; /* association ID */
91 * Memory allocation watermarks.
93 #define INIT_PEER_ALLOC 15 /* initialize for 15 peers */
94 #define INC_PEER_ALLOC 5 /* when run out, add 5 more */
97 * Miscellaneous statistic counters which may be queried.
99 u_long peer_timereset; /* time stat counters zeroed */
100 u_long findpeer_calls; /* calls to findpeer */
101 u_long assocpeer_calls; /* calls to findpeerbyassoc */
102 u_long peer_allocations; /* allocations from free list */
103 u_long peer_demobilizations; /* structs freed to free list */
104 int total_peer_structs; /* peer structs */
105 int peer_associations; /* active associations */
106 static struct peer init_peer_alloc[INIT_PEER_ALLOC]; /* init alloc */
108 static void getmorepeermem P((void));
111 * init_peer - initialize peer data structures and counters
113 * N.B. We use the random number routine in here. It had better be
114 * initialized prior to getting here.
122 * Clear hash table and counters.
124 for (i = 0; i < HASH_SIZE; i++) {
126 peer_hash_count[i] = 0;
128 assoc_hash_count[i] = 0;
132 * Clear stat counters
134 findpeer_calls = peer_allocations = 0;
135 assocpeer_calls = peer_demobilizations = 0;
138 * Initialize peer memory.
141 for (i = 0; i < INIT_PEER_ALLOC; i++) {
142 init_peer_alloc[i].next = peer_free;
143 peer_free = &init_peer_alloc[i];
145 total_peer_structs = INIT_PEER_ALLOC;
146 peer_free_count = INIT_PEER_ALLOC;
149 * Initialize our first association ID
151 current_association_ID = (associd_t)ranp2(16);
152 if (current_association_ID == 0)
153 current_association_ID = 1;
158 * getmorepeermem - add more peer structures to the free list
164 register struct peer *peer;
166 peer = (struct peer *)emalloc(INC_PEER_ALLOC *
167 sizeof(struct peer));
168 for (i = 0; i < INC_PEER_ALLOC; i++) {
169 peer->next = peer_free;
174 total_peer_structs += INC_PEER_ALLOC;
175 peer_free_count += INC_PEER_ALLOC;
180 * findexistingpeer - return a pointer to a peer in the hash table
184 struct sockaddr_in *addr,
185 struct peer *start_peer,
189 register struct peer *peer;
192 * start_peer is included so we can locate instances of the
193 * same peer through different interfaces in the hash table.
196 peer = peer_hash[HASH_ADDR(addr)];
198 peer = start_peer->next;
201 if (NSRCADR(addr) == NSRCADR(&peer->srcadr)
202 && NSRCPORT(addr) == NSRCPORT(&peer->srcadr)) {
205 else if (peer->hmode == mode)
215 * findpeer - find and return a peer in the hash table.
219 struct sockaddr_in *srcadr,
220 struct interface *dstadr,
226 register struct peer *peer;
230 hash = HASH_ADDR(srcadr);
231 for (peer = peer_hash[hash]; peer != 0; peer = peer->next) {
232 if (NSRCADR(srcadr) == NSRCADR(&peer->srcadr)
233 && NSRCPORT(srcadr) == NSRCPORT(&peer->srcadr)) {
236 * if the association matching rules determine
237 * that this is not a valid combination, then
238 * look for the next valid peer association.
240 *action = MATCH_ASSOC(peer->hmode, pkt_mode);
243 * Sigh! Check if BCLIENT peer in client
244 * server mode, else return error.
246 if ((*action == AM_POSSBCL) && !(peer->flags &
251 * if an error was returned, exit back right
254 if (*action == AM_ERR)
255 return ((struct peer *)0);
258 * if a match is found, we stop our search.
260 if (*action != AM_NOMATCH)
266 * If no matching association is found
269 *action = MATCH_ASSOC(NO_PEER, pkt_mode);
270 return ((struct peer *)0);
272 peer->dstadr = dstadr;
277 * findpeerbyassocid - find and return a peer using his association ID
284 register struct peer *peer;
289 hash = assoc & HASH_MASK;
290 for (peer = assoc_hash[hash]; peer != 0; peer =
292 if (assoc == peer->associd)
300 * clear_all - flush all time values for all associations
305 struct peer *peer, *next_peer;
309 * This routine is called when the clock is stepped, and so all
310 * previously saved time values are untrusted.
312 for (n = 0; n < HASH_SIZE; n++) {
313 for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
314 next_peer = peer->next;
320 printf("clear_all: at %lu\n", current_time);
326 * unpeer - remove peer structure from hash table and free structure
330 struct peer *peer_to_remove
338 printf("demobilize %u %d\n", peer_to_remove->associd,
341 peer_clear(peer_to_remove);
342 hash = HASH_ADDR(&peer_to_remove->srcadr);
343 peer_hash_count[hash]--;
344 peer_demobilizations++;
347 * If this peer is actually a clock, shut it down first
349 if (peer_to_remove->flags & FLAG_REFCLOCK)
350 refclock_unpeer(peer_to_remove);
352 peer_to_remove->action = 0; /* disable timeout actions */
353 if (peer_hash[hash] == peer_to_remove)
354 peer_hash[hash] = peer_to_remove->next;
356 register struct peer *peer;
358 peer = peer_hash[hash];
359 while (peer != 0 && peer->next != peer_to_remove)
363 peer_hash_count[hash]++;
364 msyslog(LOG_ERR, "peer struct for %s not in table!",
365 ntoa(&peer->srcadr));
367 peer->next = peer_to_remove->next;
372 * Remove him from the association hash as well.
374 hash = peer_to_remove->associd & HASH_MASK;
375 assoc_hash_count[hash]--;
376 if (assoc_hash[hash] == peer_to_remove)
377 assoc_hash[hash] = peer_to_remove->ass_next;
379 register struct peer *peer;
381 peer = assoc_hash[hash];
382 while (peer != 0 && peer->ass_next != peer_to_remove)
383 peer = peer->ass_next;
386 assoc_hash_count[hash]++;
388 "peer struct for %s not in association table!",
389 ntoa(&peer->srcadr));
391 peer->ass_next = peer_to_remove->ass_next;
394 peer_to_remove->next = peer_free;
395 peer_free = peer_to_remove;
401 * peer_config - configure a new association
405 struct sockaddr_in *srcadr,
406 struct interface *dstadr,
417 register struct peer *peer;
421 * First search from the beginning for an association with given
422 * remote address and mode. If an interface is given, search
423 * from there to find the association which matches that
426 peer = findexistingpeer(srcadr, (struct peer *)0, hmode);
429 if (peer->dstadr == dstadr)
431 peer = findexistingpeer(srcadr, peer, hmode);
436 * We do a dirty little jig to figure the cast flags. This is
437 * probably not the best place to do this, at least until the
438 * configure code is rebuilt. Note only one flag can be set.
443 if (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr)))
444 cast_flags = MDF_MCAST;
446 cast_flags = MDF_BCAST;
450 if (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr)))
451 cast_flags = MDF_ACAST;
453 cast_flags = MDF_UCAST;
457 cast_flags = MDF_UCAST;
462 * If the peer is already configured, some dope has a duplicate
463 * configureation entry or another dope is wiggling from afar.
466 peer->hmode = (u_char)hmode;
467 peer->version = (u_char)version;
468 peer->minpoll = (u_char)minpoll;
469 peer->maxpoll = (u_char)maxpoll;
470 peer->hpoll = peer->kpoll = peer->minpoll;
471 peer->ppoll = peer->maxpoll;
472 peer->flags = flags | FLAG_CONFIG |
473 (peer->flags & FLAG_REFCLOCK);
474 peer->cast_flags = cast_flags;
481 * Here no match has been found, so presumably this is a new
482 * persistent association. Mobilize the thing and initialize its
485 peer = newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll,
486 flags | FLAG_CONFIG, cast_flags, ttl, key);
492 * newpeer - initialize a new peer association
496 struct sockaddr_in *srcadr,
497 struct interface *dstadr,
508 register struct peer *peer;
512 * Allocate a new peer structure. Some dirt here, since some of
513 * the initialization requires knowlege of our system state.
515 if (peer_free_count == 0)
518 peer_free = peer->next;
521 memset((char *)peer, 0, sizeof(struct peer));
524 * Initialize the peer structure and dance the interface jig.
525 * Reference clocks step the loopback waltz, the others
526 * squaredance around the interface list looking for a buddy. If
527 * the dance peters out, there is always the wildcard interface.
528 * This might happen in some systems and would preclude proper
529 * operation with public key cryptography.
531 if (ISREFCLOCKADR(srcadr))
532 peer->dstadr = loopback_interface;
533 else if (cast_flags & MDF_BCLNT)
534 peer->dstadr = findbcastinter(srcadr);
535 else if (dstadr != any_interface)
536 peer->dstadr = dstadr;
538 peer->dstadr = findinterface(srcadr);
539 peer->srcadr = *srcadr;
540 peer->hmode = (u_char)hmode;
541 peer->version = (u_char)version;
542 peer->minpoll = (u_char)max(NTP_MINPOLL, minpoll);
543 peer->maxpoll = (u_char)min(NTP_MAXPOLL, maxpoll);
544 peer->flags = flags | (key > NTP_MAXKEY ? FLAG_SKEY : 0);
545 peer->cast_flags = cast_flags;
548 peer->precision = sys_precision;
554 * Assign an association ID and increment the system variable.
556 peer->associd = current_association_ID;
557 if (++current_association_ID == 0)
558 ++current_association_ID;
561 * Note time on statistics timers.
563 peer->timereset = current_time;
564 peer->timereachable = current_time;
565 peer->timereceived = current_time;
567 if (ISREFCLOCKADR(&peer->srcadr)) {
569 * We let the reference clock support do clock
570 * dependent initialization. This includes setting
571 * the peer timer, since the clock may have requirements
574 if (!refclock_newpeer(peer)) {
576 * Dump it, something screwed up
578 peer->next = peer_free;
587 * Put the new peer in the hash tables.
589 i = HASH_ADDR(&peer->srcadr);
590 peer->next = peer_hash[i];
592 peer_hash_count[i]++;
593 i = peer->associd & HASH_MASK;
594 peer->ass_next = assoc_hash[i];
595 assoc_hash[i] = peer;
596 assoc_hash_count[i]++;
600 "newpeer: %s->%s mode %d vers %d poll %d %d flags %x %x ttl %d key %08x\n",
601 ntoa(&peer->dstadr->sin), ntoa(&peer->srcadr),
602 peer->hmode, peer->version, peer->minpoll,
603 peer->maxpoll, peer->flags, peer->cast_flags,
604 peer->ttlmax, peer->keyid);
611 * peer_unconfig - remove the configuration bit from a peer
615 struct sockaddr_in *srcadr,
616 struct interface *dstadr,
620 register struct peer *peer;
624 peer = findexistingpeer(srcadr, (struct peer *)0, mode);
626 if (peer->flags & FLAG_CONFIG
627 && (dstadr == 0 || peer->dstadr == dstadr)) {
631 * Tricky stuff here. If the peer is polling us
632 * in active mode, turn off the configuration
633 * bit and make the mode passive. This allows us
634 * to avoid dumping a lot of history for peers
635 * we might choose to keep track of in passive
636 * mode. The protocol will eventually terminate
637 * undesirables on its own.
639 if (peer->hmode == MODE_ACTIVE
640 && peer->pmode == MODE_ACTIVE) {
641 peer->hmode = MODE_PASSIVE;
642 peer->flags &= ~FLAG_CONFIG;
648 peer = findexistingpeer(srcadr, peer, mode);
654 * peer_clr_stats - clear peer module stat counters
661 peer_allocations = 0;
662 peer_demobilizations = 0;
663 peer_timereset = current_time;
667 * peer_reset - reset stat counters in a peer structure
682 peer->seldisptoolarge = 0;
684 peer->timereset = current_time;
689 * peer_all_reset - reset all peer stat counters
697 for (hash = 0; hash < HASH_SIZE; hash++)
698 for (peer = peer_hash[hash]; peer != 0; peer = peer->next)
705 * expire_all - flush all crypto data and update timestamps.
710 struct peer *peer, *next_peer;
714 * This routine is called about once per day from the timer
715 * routine and when the client is first synchronized. Search the
716 * peer list for all associations and flush only the key list
717 * and cookie. If a manycast client association, flush
718 * everything. Then, recompute and sign the agreement public
721 for (n = 0; n < HASH_SIZE; n++) {
722 for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
723 next_peer = peer->next;
724 if (peer->cast_flags & MDF_ACAST) {
729 peer->pcookie.tstamp = 0;
735 sys_private = (u_int32)RANDOM & 0xffffffff;
741 printf("expire_all: at %lu\n", current_time);
748 * findmanycastpeer - find and return a manycast peer
752 struct recvbuf *rbufp
755 register struct peer *peer;
761 * This routine is called upon arrival of a client-mode message
762 * from a manycast server. Search the peer list for a manycast
763 * client association where the last transmit timestamp matches
764 * the originate timestamp. This assumes the transmit timestamps
765 * for possibly more than one manycast association are unique.
767 pkt = &rbufp->recv_pkt;
768 for (i = 0; i < HASH_SIZE; i++) {
769 if (peer_hash_count[i] == 0)
772 for (peer = peer_hash[i]; peer != 0; peer =
774 if (peer->cast_flags & MDF_ACAST) {
775 NTOHL_FP(&pkt->org, &p_org);
776 if (L_ISEQU(&peer->xmt, &p_org))
786 * resetmanycast - reset all manycast clients
791 register struct peer *peer;
795 * This routine is called when the number of client associations
796 * falls below the minimum. Search the peer list for manycast
797 * client associations and reset the ttl and poll interval.
799 for (i = 0; i < HASH_SIZE; i++) {
800 if (peer_hash_count[i] == 0)
803 for (peer = peer_hash[i]; peer != 0; peer =
805 if (peer->cast_flags & MDF_ACAST) {
807 poll_update(peer, peer->hpoll);