Coverage Report

Created: 2023-05-19 06:16

/src/ntp-dev/ntpd/ntp_peer.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * ntp_peer.c - management of data maintained for peer associations
3
 */
4
#ifdef HAVE_CONFIG_H
5
#include <config.h>
6
#endif
7
8
#include <stdio.h>
9
#include <sys/types.h>
10
11
#include "ntpd.h"
12
#include "ntp_lists.h"
13
#include "ntp_stdlib.h"
14
#include "ntp_control.h"
15
#include <ntp_random.h>
16
17
/*
18
 *        Table of valid association combinations
19
 *        ---------------------------------------
20
 *
21
 *                             packet->mode
22
 * peer->mode      | UNSPEC  ACTIVE PASSIVE  CLIENT  SERVER  BCAST
23
 * ----------      | ---------------------------------------------
24
 * NO_PEER         |   e       1       0       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       0
28
 * SERVER          |   e       0       0       0       0       0
29
 * BCAST           |   e       0       0       0       0       0
30
 * BCLIENT         |   e       0       0       0       e       1
31
 *
32
 * One point to note here: a packet in BCAST mode can potentially match
33
 * a peer in CLIENT mode, but we that is a special case and we check for
34
 * that early in the decision process.  This avoids having to keep track
35
 * of what kind of associations are possible etc...  We actually
36
 * circumvent that problem by requiring that the first b(m)roadcast
37
 * received after the change back to BCLIENT mode sets the clock.
38
 */
39
#define AM_MODES  7 /* number of rows and columns */
40
#define NO_PEER   0 /* action when no peer is found */
41
42
int AM[AM_MODES][AM_MODES] = {
43
/*      packet->mode              */
44
/* peer { UNSPEC,   ACTIVE,     PASSIVE,    CLIENT,     SERVER,     BCAST } */
45
/* mode */
46
/*NONE*/{ AM_ERR, AM_NEWPASS, AM_NOMATCH, AM_FXMIT,   AM_MANYCAST, AM_NEWBCL},
47
48
/*A*/ { AM_ERR, AM_PROCPKT, AM_PROCPKT, AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
49
50
/*P*/ { AM_ERR, AM_PROCPKT, AM_ERR,     AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
51
52
/*C*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT,  AM_NOMATCH},
53
54
/*S*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
55
56
/*BCST*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH,  AM_NOMATCH},
57
58
/*BCL*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH,  AM_PROCPKT},
59
};
60
61
249
#define MATCH_ASSOC(x, y) AM[(x)][(y)]
62
63
/*
64
 * These routines manage the allocation of memory to peer structures
65
 * and the maintenance of three data structures involving all peers:
66
 *
67
 * - peer_list is a single list with all peers, suitable for scanning
68
 *   operations over all peers.
69
 * - peer_adr_hash is an array of lists indexed by hashed peer address.
70
 * - peer_aid_hash is an array of lists indexed by hashed associd.
71
 *
72
 * They also maintain a free list of peer structures, peer_free.
73
 *
74
 * The three main entry points are findpeer(), which looks for matching
75
 * peer structures in the peer list, newpeer(), which allocates a new
76
 * peer structure and adds it to the list, and unpeer(), which
77
 * demobilizes the association and deallocates the structure.
78
 */
79
/*
80
 * Peer hash tables
81
 */
82
struct peer *peer_hash[NTP_HASH_SIZE];  /* peer hash table */
83
int peer_hash_count[NTP_HASH_SIZE]; /* peers in each bucket */
84
struct peer *assoc_hash[NTP_HASH_SIZE]; /* association ID hash table */
85
int assoc_hash_count[NTP_HASH_SIZE];/* peers in each bucket */
86
struct peer *peer_list;     /* peer structures list */
87
static struct peer *peer_free;    /* peer structures free list */
88
int peer_free_count;    /* count of free structures */
89
90
/*
91
 * Association ID.  We initialize this value randomly, then assign a new
92
 * value every time an association is mobilized.
93
 */
94
static associd_t current_association_ID; /* association ID */
95
static associd_t initial_association_ID; /* association ID */
96
97
/*
98
 * Memory allocation watermarks.
99
 */
100
#define INIT_PEER_ALLOC   8 /* static preallocation */
101
0
#define INC_PEER_ALLOC    4  /* add N more when empty */
102
103
/*
104
 * Miscellaneous statistic counters which may be queried.
105
 */
106
u_long  peer_timereset;     /* time stat counters zeroed */
107
u_long  findpeer_calls;     /* calls to findpeer */
108
u_long  assocpeer_calls;    /* calls to findpeerbyassoc */
109
u_long  peer_allocations;   /* allocations from free list */
110
u_long  peer_demobilizations;   /* structs freed to free list */
111
int total_peer_structs;   /* peer structs */
112
int peer_associations;    /* mobilized associations */
113
int peer_preempt;     /* preemptable associations */
114
static struct peer init_peer_alloc[INIT_PEER_ALLOC]; /* init alloc */
115
116
static struct peer *  findexistingpeer_name(const char *, u_short,
117
                struct peer *, int);
118
static struct peer *  findexistingpeer_addr(sockaddr_u *,
119
                struct peer *, int,
120
                u_char, int *);
121
static void   free_peer(struct peer *, int);
122
static void   getmorepeermem(void);
123
static int    score(struct peer *);
124
125
126
/*
127
 * init_peer - initialize peer data structures and counters
128
 *
129
 * N.B. We use the random number routine in here. It had better be
130
 * initialized prior to getting here.
131
 */
132
void
133
init_peer(void)
134
1
{
135
1
  int i;
136
137
  /*
138
   * Initialize peer free list from static allocation.
139
   */
140
9
  for (i = COUNTOF(init_peer_alloc) - 1; i >= 0; i--)
141
8
    LINK_SLIST(peer_free, &init_peer_alloc[i], p_link);
142
1
  total_peer_structs = COUNTOF(init_peer_alloc);
143
1
  peer_free_count = COUNTOF(init_peer_alloc);
144
145
  /*
146
   * Initialize our first association ID
147
   */
148
1
  do
149
1
    current_association_ID = ntp_random() & ASSOCID_MAX;
150
1
  while (!current_association_ID);
151
1
  initial_association_ID = current_association_ID;
152
1
}
153
154
155
/*
156
 * getmorepeermem - add more peer structures to the free list
157
 */
158
static void
159
getmorepeermem(void)
160
0
{
161
0
  int i;
162
0
  struct peer *peers;
163
164
0
  peers = eallocarray(INC_PEER_ALLOC, sizeof(*peers));
165
166
0
  for (i = INC_PEER_ALLOC - 1; i >= 0; i--)
167
0
    LINK_SLIST(peer_free, &peers[i], p_link);
168
169
0
  total_peer_structs += INC_PEER_ALLOC;
170
0
  peer_free_count += INC_PEER_ALLOC;
171
0
}
172
173
174
static struct peer *
175
findexistingpeer_name(
176
  const char *  hostname,
177
  u_short   hname_fam,
178
  struct peer * start_peer,
179
  int   mode
180
  )
181
0
{
182
0
  struct peer *p;
183
184
0
  if (NULL == start_peer)
185
0
    p = peer_list;
186
0
  else
187
0
    p = start_peer->p_link;
188
0
  for (; p != NULL; p = p->p_link)
189
0
    if (p->hostname != NULL
190
0
        && (-1 == mode || p->hmode == mode)
191
0
        && (AF_UNSPEC == hname_fam
192
0
      || AF_UNSPEC == AF(&p->srcadr)
193
0
      || hname_fam == AF(&p->srcadr))
194
0
        && !strcasecmp(p->hostname, hostname))
195
0
      break;
196
0
  return p;
197
0
}
198
199
200
static
201
struct peer *   
202
findexistingpeer_addr(
203
  sockaddr_u *  addr,
204
  struct peer * start_peer,
205
  int   mode,
206
  u_char    cast_flags,
207
  int *   ip_count
208
  )
209
0
{
210
0
  struct peer *peer;
211
212
0
  DPRINTF(2, ("findexistingpeer_addr(%s, %s, %d, 0x%x, %p)\n",
213
0
    sptoa(addr),
214
0
    (start_peer)
215
0
        ? sptoa(&start_peer->srcadr)
216
0
        : "NULL",
217
0
    mode, (u_int)cast_flags, ip_count));
218
219
  /*
220
   * start_peer is included so we can locate instances of the
221
   * same peer through different interfaces in the hash table.
222
   * Without MDF_BCLNT, a match requires the same mode and remote
223
   * address.  MDF_BCLNT associations start out as MODE_CLIENT
224
   * if broadcastdelay is not specified, and switch to
225
   * MODE_BCLIENT after estimating the one-way delay.  Duplicate
226
   * associations are expanded in definition to match any other
227
   * MDF_BCLNT with the same srcadr (remote, unicast address).
228
   */
229
0
  if (NULL == start_peer)
230
0
    peer = peer_hash[NTP_HASH_ADDR(addr)];
231
0
  else
232
0
    peer = start_peer->adr_link;
233
  
234
0
  while (peer != NULL) {
235
0
    DPRINTF(3, ("%s %s %d %d 0x%x 0x%x ", sptoa(addr),
236
0
      sptoa(&peer->srcadr), mode, peer->hmode,
237
0
      (u_int)cast_flags, (u_int)peer->cast_flags));
238
0
    if (ip_count) {
239
0
      if (SOCK_EQ(addr, &peer->srcadr)) {
240
0
        (*ip_count)++;
241
0
      }
242
0
    }
243
0
    if ((-1 == mode || peer->hmode == mode ||
244
0
         ((MDF_BCLNT & peer->cast_flags) &&
245
0
          (MDF_BCLNT & cast_flags))) &&
246
0
        ADDR_PORT_EQ(addr, &peer->srcadr)) {
247
0
      DPRINTF(3, ("found.\n"));
248
0
      break;
249
0
    }
250
0
    DPRINTF(3, ("\n"));
251
0
    peer = peer->adr_link;
252
0
  }
253
254
0
  return peer;
255
0
}
256
257
258
/*
259
 * findexistingpeer - search by address and return a pointer to a peer.
260
 */
261
struct peer *
262
findexistingpeer(
263
  sockaddr_u *  addr,
264
  const char *  hostname,
265
  struct peer * start_peer,
266
  int   mode,
267
  u_char    cast_flags,
268
  int *   ip_count
269
  )
270
0
{
271
0
  if (hostname != NULL)
272
0
    return findexistingpeer_name(hostname, AF(addr),
273
0
               start_peer, mode);
274
0
  else
275
0
    return findexistingpeer_addr(addr, start_peer, mode,
276
0
               cast_flags, ip_count);
277
0
}
278
279
280
/*
281
 * findpeer - find and return a peer match for a received datagram in
282
 *        the peer_hash table.
283
 *
284
 * [Bug 3072] To faciliate a faster reorganisation after routing changes
285
 * the original code re-assigned the peer address to be the destination
286
 * of the received packet and initiated another round on a mismatch.
287
 * Unfortunately this leaves us wide open for a DoS attack where the
288
 * attacker directs a packet with forged destination address to us --
289
 * this results in a wrong interface assignment, actually creating a DoS
290
 * situation.
291
 *
292
 * This condition would persist until the next update of the interface
293
 * list, but a continued attack would put us out of business again soon
294
 * enough. Authentication alone does not help here, since it does not
295
 * protect the UDP layer and leaves us open for a replay attack.
296
 *
297
 * So we do not update the adresses and wait until the next interface
298
 * list update does the right thing for us.
299
 */
300
struct peer *
301
findpeer(
302
  struct recvbuf *rbufp,
303
  int   pkt_mode,
304
  int *   action
305
  )
306
249
{
307
249
  struct peer * p;
308
249
  sockaddr_u *  srcadr;
309
249
  u_int   hash;
310
249
  struct pkt *  pkt;
311
249
  l_fp    pkt_org;
312
313
249
  findpeer_calls++;
314
249
  srcadr = &rbufp->recv_srcadr;
315
249
  hash = NTP_HASH_ADDR(srcadr);
316
249
  for (p = peer_hash[hash]; p != NULL; p = p->adr_link) {
317
318
    /* [Bug 3072] ensure interface of peer matches */
319
    /* [Bug 3356] ... if NOT a broadcast peer!     */
320
0
    if (p->hmode != MODE_BCLIENT && p->dstadr != rbufp->dstadr)
321
0
      continue;
322
323
    /* ensure peer source address matches */
324
0
    if ( ! ADDR_PORT_EQ(srcadr, &p->srcadr))
325
0
      continue;
326
    
327
    /* If the association matching rules determine that this
328
     * is not a valid combination, then look for the next
329
     * valid peer association.
330
     */
331
0
    *action = MATCH_ASSOC(p->hmode, pkt_mode);
332
333
    /* A response to our manycastclient solicitation might
334
     * be misassociated with an ephemeral peer already spun
335
     * for the server.  If the packet's org timestamp
336
     * doesn't match the peer's, check if it matches the
337
     * ACST prototype peer's.  If so it is a redundant
338
     * solicitation response, return AM_ERR to discard it.
339
     * [Bug 1762]
340
     */
341
0
    if (MODE_SERVER == pkt_mode && AM_PROCPKT == *action) {
342
0
      pkt = &rbufp->recv_pkt;
343
0
      NTOHL_FP(&pkt->org, &pkt_org);
344
0
      if (!L_ISEQU(&p->aorg, &pkt_org) &&
345
0
          findmanycastpeer(rbufp))
346
0
        *action = AM_ERR;
347
0
    }
348
349
    /* if an error was returned, exit back right here. */
350
0
    if (*action == AM_ERR)
351
0
      return NULL;
352
353
    /* if a match is found, we stop our search. */
354
0
    if (*action != AM_NOMATCH)
355
0
      break;
356
0
  }
357
358
  /* If no matching association is found... */
359
249
  if (NULL == p)
360
249
    *action = MATCH_ASSOC(NO_PEER, pkt_mode);
361
362
249
  return p;
363
249
}
364
365
/*
366
 * findpeerbyassoc - find and return a peer using his association ID
367
 */
368
struct peer *
369
findpeerbyassoc(
370
  associd_t assoc
371
  )
372
154
{
373
154
  struct peer *p;
374
154
  u_int hash;
375
376
154
  assocpeer_calls++;
377
154
  hash = assoc & NTP_HASH_MASK;
378
154
  for (p = assoc_hash[hash]; p != NULL; p = p->aid_link)
379
0
    if (assoc == p->associd)
380
0
      break;
381
154
  return p;
382
154
}
383
384
385
/*
386
 * clear_all - flush all time values for all associations
387
 */
388
void
389
clear_all(void)
390
0
{
391
0
  struct peer *p;
392
393
  /*
394
   * This routine is called when the clock is stepped, and so all
395
   * previously saved time values are untrusted.
396
   */
397
0
  for (p = peer_list; p != NULL; p = p->p_link)
398
0
    if (!(MDF_TXONLY_MASK & p->cast_flags))
399
0
      peer_clear(p, "STEP");
400
401
0
  DPRINTF(1, ("clear_all: at %lu\n", current_time));
402
0
}
403
404
405
/*
406
 * score_all() - determine if an association can be demobilized
407
 */
408
int
409
score_all(
410
  struct peer *peer /* peer structure pointer */
411
  )
412
0
{
413
0
  struct peer *speer;
414
0
  int temp, tamp;
415
0
  int x;
416
417
  /*
418
   * This routine finds the minimum score for all preemptible
419
   * associations and returns > 0 if the association can be
420
   * demobilized.
421
   */
422
0
  tamp = score(peer);
423
0
  temp = 100;
424
0
  for (speer = peer_list; speer != NULL; speer = speer->p_link)
425
0
    if (speer->flags & FLAG_PREEMPT) {
426
0
      x = score(speer);
427
0
      if (x < temp)
428
0
        temp = x;
429
0
    }
430
0
  DPRINTF(1, ("score_all: at %lu score %d min %d\n",
431
0
        current_time, tamp, temp));
432
433
0
  if (tamp != temp)
434
0
    temp = 0;
435
436
0
  return temp;
437
0
}
438
439
440
/*
441
 * score() - calculate preemption score
442
 */
443
static int
444
score(
445
  struct peer *peer /* peer structure pointer */
446
  )
447
0
{
448
0
  int temp;
449
450
  /*
451
   * This routine calculates the premption score from the peer
452
   * error bits and status. Increasing values are more cherished.
453
   */
454
0
  temp = 0;
455
0
  if (!(peer->flash & TEST10))
456
0
    temp++;     /* 1 good synch and stratum */
457
0
  if (!(peer->flash & TEST13))
458
0
    temp++;     /* 2 reachable */
459
0
  if (!(peer->flash & TEST12))
460
0
    temp++;     /* 3 no loop */
461
0
  if (!(peer->flash & TEST11))
462
0
    temp++;     /* 4 good distance */
463
0
  if (peer->status >= CTL_PST_SEL_SELCAND)
464
0
    temp++;     /* 5 in the hunt */
465
0
  if (peer->status != CTL_PST_SEL_EXCESS)
466
0
    temp++;     /* 6 not spare tire */
467
0
  return (temp);      /* selection status */
468
0
}
469
470
471
/*
472
 * free_peer - internal routine to free memory referred to by a struct
473
 *         peer and return it to the peer free list.  If unlink is
474
 *         nonzero, unlink from the various lists.
475
 */
476
static void
477
free_peer(
478
  struct peer * p,
479
  int   unlink_peer
480
  )
481
0
{
482
0
  struct peer * unlinked;
483
0
  int   hash;
484
485
0
  if (unlink_peer) {
486
0
    hash = NTP_HASH_ADDR(&p->srcadr);
487
0
    peer_hash_count[hash]--;
488
489
0
    UNLINK_SLIST(unlinked, peer_hash[hash], p, adr_link,
490
0
           struct peer);
491
0
    if (NULL == unlinked) {
492
0
      peer_hash_count[hash]++;
493
0
      msyslog(LOG_ERR, "peer %s not in address table!",
494
0
        stoa(&p->srcadr));
495
0
    }
496
497
    /*
498
     * Remove him from the association hash as well.
499
     */
500
0
    hash = p->associd & NTP_HASH_MASK;
501
0
    assoc_hash_count[hash]--;
502
503
0
    UNLINK_SLIST(unlinked, assoc_hash[hash], p, aid_link,
504
0
           struct peer);
505
0
    if (NULL == unlinked) {
506
0
      assoc_hash_count[hash]++;
507
0
      msyslog(LOG_ERR,
508
0
        "peer %s not in association ID table!",
509
0
        stoa(&p->srcadr));
510
0
    }
511
512
    /* Remove him from the overall list. */
513
0
    UNLINK_SLIST(unlinked, peer_list, p, p_link,
514
0
           struct peer);
515
0
    if (NULL == unlinked)
516
0
      msyslog(LOG_ERR, "%s not in peer list!",
517
0
        stoa(&p->srcadr));
518
0
  }
519
520
0
  if (p->hostname != NULL)
521
0
    free(p->hostname);
522
523
0
  if (p->ident != NULL)
524
0
    free(p->ident);
525
526
0
  if (p->addrs != NULL)
527
0
    free(p->addrs);   /* from copy_addrinfo_list() */
528
529
  /* Add his corporeal form to peer free list */
530
0
  ZERO(*p);
531
0
  LINK_SLIST(peer_free, p, p_link);
532
0
  peer_free_count++;
533
0
}
534
535
536
/*
537
 * unpeer - remove peer structure from hash table and free structure
538
 */
539
void
540
unpeer(
541
  struct peer *peer
542
  )
543
0
{
544
0
  mprintf_event(PEVNT_DEMOBIL, peer, "assoc %u", peer->associd);
545
0
  restrict_source(&peer->srcadr, 1, 0);
546
0
  set_peerdstadr(peer, NULL);
547
0
  peer_demobilizations++;
548
0
  peer_associations--;
549
0
  if (FLAG_PREEMPT & peer->flags)
550
0
    peer_preempt--;
551
0
#ifdef REFCLOCK
552
  /*
553
   * If this peer is actually a clock, shut it down first
554
   */
555
0
  if (FLAG_REFCLOCK & peer->flags)
556
0
    refclock_unpeer(peer);
557
0
#endif
558
559
0
  free_peer(peer, TRUE);
560
0
}
561
562
563
/*
564
 * peer_config - configure a new association
565
 */
566
struct peer *
567
peer_config(
568
  sockaddr_u *  srcadr,
569
  const char *  hostname,
570
  endpt *   dstadr,
571
  int   ippeerlimit,
572
  u_char    hmode,
573
  u_char    version,
574
  u_char    minpoll,
575
  u_char    maxpoll,
576
  u_int   flags,
577
  u_int32   ttl,
578
  keyid_t   key,
579
  const char *  ident   /* autokey group */
580
  )
581
0
{
582
0
  u_char cast_flags;
583
584
  /*
585
   * We do a dirty little jig to figure the cast flags. This is
586
   * probably not the best place to do this, at least until the
587
   * configure code is rebuilt. Note only one flag can be set.
588
   */
589
0
  switch (hmode) {
590
0
  case MODE_BROADCAST:
591
0
    if (IS_MCAST(srcadr))
592
0
      cast_flags = MDF_MCAST;
593
0
    else
594
0
      cast_flags = MDF_BCAST;
595
0
    break;
596
597
0
  case MODE_CLIENT:
598
0
    if (hostname != NULL && SOCK_UNSPEC(srcadr))
599
0
      cast_flags = MDF_POOL;
600
0
    else if (IS_MCAST(srcadr))
601
0
      cast_flags = MDF_ACAST;
602
0
    else
603
0
      cast_flags = MDF_UCAST;
604
0
    break;
605
606
0
  default:
607
0
    cast_flags = MDF_UCAST;
608
0
  }
609
610
  /*
611
   * Mobilize the association and initialize its variables. If
612
   * emulating ntpdate, force iburst.  For pool and manycastclient
613
   * strip FLAG_PREEMPT as the prototype associations are not
614
   * themselves preemptible, though the resulting associations
615
   * are.
616
   */
617
0
  flags |= FLAG_CONFIG;
618
0
  if (mode_ntpdate)
619
0
    flags |= FLAG_IBURST;
620
0
  if ((MDF_ACAST | MDF_POOL) & cast_flags)
621
0
    flags &= ~FLAG_PREEMPT;
622
0
  return newpeer(srcadr, hostname, dstadr, ippeerlimit, hmode, version,
623
0
      minpoll, maxpoll, flags, cast_flags, ttl, key, ident);
624
0
}
625
626
/*
627
 * setup peer dstadr field keeping it in sync with the interface
628
 * structures
629
 */
630
void
631
set_peerdstadr(
632
  struct peer * p,
633
  endpt *   dstadr
634
  )
635
0
{
636
0
  struct peer * unlinked;
637
638
0
  DEBUG_INSIST(p != NULL);
639
640
0
  if (p == NULL)
641
0
    return;
642
643
  /* check for impossible or identical assignment */
644
0
  if (p->dstadr == dstadr)
645
0
    return;
646
647
  /*
648
   * Don't accept updates to a separate multicast receive-only
649
   * endpt while a BCLNT peer is running its unicast protocol.
650
   */
651
0
  if (dstadr != NULL && (FLAG_BC_VOL & p->flags) &&
652
0
      (INT_MCASTIF & dstadr->flags) && MODE_CLIENT == p->hmode) {
653
0
    return;
654
0
  }
655
656
  /* unlink from list if we have an address prior to assignment */
657
0
  if (p->dstadr != NULL) {
658
0
    p->dstadr->peercnt--;
659
0
    UNLINK_SLIST(unlinked, p->dstadr->peers, p, ilink,
660
0
           struct peer);
661
0
    msyslog(LOG_INFO, "%s local addr %s -> %s",
662
0
      stoa(&p->srcadr), latoa(p->dstadr),
663
0
      latoa(dstadr));
664
0
  }
665
  
666
0
  p->dstadr = dstadr;
667
668
  /* link to list if we have an address after assignment */
669
0
  if (p->dstadr != NULL) {
670
0
    LINK_SLIST(dstadr->peers, p, ilink);
671
0
    dstadr->peercnt++;
672
0
  }
673
0
}
674
675
/*
676
 * attempt to re-rebind interface if necessary
677
 */
678
static void
679
peer_refresh_interface(
680
  struct peer *p
681
  )
682
0
{
683
0
  endpt * niface;
684
0
  endpt * piface;
685
686
0
  niface = select_peerinterface(p, &p->srcadr, NULL);
687
688
0
  DPRINTF(4, (
689
0
      "peer_refresh_interface: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %u key %08x: new interface: ",
690
0
      p->dstadr == NULL ? "<null>" :
691
0
      stoa(&p->dstadr->sin), stoa(&p->srcadr), p->hmode,
692
0
      p->version, p->minpoll, p->maxpoll, p->flags, p->cast_flags,
693
0
      p->ttl, p->keyid));
694
0
  if (niface != NULL) {
695
0
    DPRINTF(4, (
696
0
        "fd=%d, bfd=%d, name=%.16s, flags=0x%x, ifindex=%u, sin=%s",
697
0
        niface->fd,  niface->bfd, niface->name,
698
0
        niface->flags, niface->ifindex,
699
0
        stoa(&niface->sin)));
700
0
    if (niface->flags & INT_BROADCAST)
701
0
      DPRINTF(4, (", bcast=%s",
702
0
        stoa(&niface->bcast)));
703
0
    DPRINTF(4, (", mask=%s\n", stoa(&niface->mask)));
704
0
  } else {
705
0
    DPRINTF(4, ("<NONE>\n"));
706
0
  }
707
708
0
  piface = p->dstadr;
709
0
  set_peerdstadr(p, niface);
710
0
  if (p->dstadr != NULL) {
711
    /*
712
     * clear crypto if we change the local address
713
     */
714
0
    if (p->dstadr != piface && !(MDF_ACAST & p->cast_flags)
715
0
        && MODE_BROADCAST != p->pmode)
716
0
      peer_clear(p, "XFAC");
717
718
    /*
719
     * Broadcast needs the socket enabled for broadcast
720
     */
721
0
    if (MDF_BCAST & p->cast_flags)
722
0
      enable_broadcast(p->dstadr, &p->srcadr);
723
724
    /*
725
     * Multicast needs the socket interface enabled for
726
     * multicast
727
     */
728
0
    if (MDF_MCAST & p->cast_flags)
729
0
      enable_multicast_if(p->dstadr, &p->srcadr);
730
0
  }
731
0
}
732
733
734
/*
735
 * refresh_all_peerinterfaces - see that all interface bindings are up
736
 * to date
737
 */
738
void
739
refresh_all_peerinterfaces(void)
740
1
{
741
1
  struct peer *p;
742
743
  /*
744
   * this is called when the interface list has changed
745
   * give all peers a chance to find a better interface
746
   * but only if either they don't have an address already
747
   * or if the one they have hasn't worked for a while.
748
   */
749
1
  for (p = peer_list; p != NULL; p = p->p_link) {
750
0
    if (!(p->dstadr && (p->reach & 0x3)))  // Bug 2849 XOR 2043
751
0
      peer_refresh_interface(p);
752
0
  }
753
1
}
754
755
756
/*
757
 * newpeer - initialize a new peer association
758
 */
759
struct peer *
760
newpeer(
761
  sockaddr_u *  srcadr,
762
  const char *  hostname,
763
  endpt *   dstadr,
764
  int   ippeerlimit,
765
  u_char    hmode,
766
  u_char    version,
767
  u_char    minpoll,
768
  u_char    maxpoll,
769
  u_int   flags,
770
  u_char    cast_flags,
771
  u_int32   ttl,
772
  keyid_t   key,
773
  const char *  ident
774
  )
775
0
{
776
0
  struct peer * peer;
777
0
  u_int   hash;
778
0
  int   ip_count = 0;
779
780
781
0
  DEBUG_REQUIRE(srcadr);
782
783
#ifdef AUTOKEY
784
  /*
785
   * If Autokey is requested but not configured, complain loudly.
786
   */
787
  if (!crypto_flags) {
788
    if (key > NTP_MAXKEY) {
789
      return (NULL);
790
791
    } else if (flags & FLAG_SKEY) {
792
      msyslog(LOG_ERR, "Autokey not configured");
793
      return (NULL);
794
    } 
795
  }
796
#endif  /* AUTOKEY */
797
798
  /*
799
   * For now only pool associations have a hostname.
800
   */
801
0
  INSIST(NULL == hostname || (MDF_POOL & cast_flags));
802
803
  /*
804
   * First search from the beginning for an association with given
805
   * remote address and mode. If an interface is given, search
806
   * from there to find the association which matches that
807
   * destination. If the given interface is "any", track down the
808
   * actual interface, because that's what gets put into the peer
809
   * structure.
810
   */
811
0
  if (dstadr != NULL) {
812
0
    peer = findexistingpeer(srcadr, hostname, NULL, hmode,
813
0
          cast_flags, &ip_count);
814
0
    while (peer != NULL) {
815
0
      if (   peer->dstadr == dstadr
816
0
          || (   (MDF_BCLNT & cast_flags)
817
0
        && (MDF_BCLNT & peer->cast_flags)))
818
0
        break;
819
820
0
      if (dstadr == ANY_INTERFACE_CHOOSE(srcadr) &&
821
0
          peer->dstadr == findinterface(srcadr))
822
0
        break;
823
824
0
      peer = findexistingpeer(srcadr, hostname, peer,
825
0
            hmode, cast_flags, &ip_count);
826
0
    }
827
0
  } else {
828
    /* no endpt address given */
829
0
    peer = findexistingpeer(srcadr, hostname, NULL, hmode,
830
0
          cast_flags, &ip_count);
831
0
  }
832
833
  /*
834
   * If a peer is found, this would be a duplicate and we don't
835
   * allow that. This avoids duplicate ephemeral (broadcast/
836
   * multicast) and preemptible (manycast and pool) client
837
   * associations.
838
   */
839
0
  if (peer != NULL) {
840
0
    DPRINTF(2, ("newpeer(%s) found existing association\n",
841
0
      (hostname)
842
0
          ? hostname
843
0
          : stoa(srcadr)));
844
0
    return NULL;
845
0
  }
846
847
0
DPRINTF(1, ("newpeer(%s) found no existing and %d other associations\n",
848
0
    (hostname)
849
0
        ? hostname
850
0
        : stoa(srcadr),
851
0
    ip_count));
852
853
  /* Check ippeerlimit wrt ip_count */
854
0
  if (ippeerlimit > -1) {
855
0
    if (ip_count + 1 > ippeerlimit) {
856
0
      DPRINTF(2, ("newpeer(%s) denied - ippeerlimit %d\n",
857
0
        (hostname)
858
0
            ? hostname
859
0
            : stoa(srcadr),
860
0
        ippeerlimit));
861
0
      return NULL;
862
0
    }
863
0
  } else {
864
0
    DPRINTF(1, ("newpeer(%s) - ippeerlimit %d ignored\n",
865
0
      (hostname)
866
0
          ? hostname
867
0
          : stoa(srcadr),
868
0
      ippeerlimit));
869
0
  }
870
871
  /*
872
   * Allocate a new peer structure. Some dirt here, since some of
873
   * the initialization requires knowlege of our system state.
874
   */
875
0
  if (peer_free_count == 0)
876
0
    getmorepeermem();
877
0
  UNLINK_HEAD_SLIST(peer, peer_free, p_link);
878
0
  INSIST(peer != NULL);
879
0
  peer_free_count--;
880
0
  peer_associations++;
881
0
  if (FLAG_PREEMPT & flags)
882
0
    peer_preempt++;
883
884
  /*
885
   * Assign an association ID and increment the system variable.
886
   */
887
0
  peer->associd = current_association_ID;
888
0
  if (++current_association_ID == 0)
889
0
    ++current_association_ID;
890
891
0
  peer->srcadr = *srcadr;
892
0
  if (hostname != NULL)
893
0
    peer->hostname = estrdup(hostname);
894
0
  peer->hmode = hmode;
895
0
  peer->version = version;
896
0
  peer->flags = flags;
897
0
  peer->cast_flags = cast_flags;
898
0
  set_peerdstadr(peer, 
899
0
           select_peerinterface(peer, srcadr, dstadr));
900
901
  /*
902
   * It is an error to set minpoll less than NTP_MINPOLL or to
903
   * set maxpoll greater than NTP_MAXPOLL. However, minpoll is
904
   * clamped not greater than NTP_MAXPOLL and maxpoll is clamped
905
   * not less than NTP_MINPOLL without complaint. Finally,
906
   * minpoll is clamped not greater than maxpoll.
907
   */
908
0
  if (minpoll == 0)
909
0
    peer->minpoll = NTP_MINDPOLL;
910
0
  else
911
0
    peer->minpoll = min(minpoll, NTP_MAXPOLL);
912
0
  if (maxpoll == 0)
913
0
    peer->maxpoll = NTP_MAXDPOLL;
914
0
  else
915
0
    peer->maxpoll = max(maxpoll, NTP_MINPOLL);
916
0
  if (peer->minpoll > peer->maxpoll)
917
0
    peer->minpoll = peer->maxpoll;
918
919
0
  if (peer->dstadr != NULL)
920
0
    DPRINTF(3, ("newpeer(%s): using fd %d and our addr %s\n",
921
0
      stoa(srcadr), peer->dstadr->fd,
922
0
      stoa(&peer->dstadr->sin)));
923
0
  else
924
0
    DPRINTF(3, ("newpeer(%s): local interface currently not bound\n",
925
0
      stoa(srcadr))); 
926
927
  /*
928
   * Broadcast needs the socket enabled for broadcast
929
   */
930
0
  if ((MDF_BCAST & cast_flags) && peer->dstadr != NULL)
931
0
    enable_broadcast(peer->dstadr, srcadr);
932
933
  /*
934
   * Multicast needs the socket interface enabled for multicast
935
   */
936
0
  if ((MDF_MCAST & cast_flags) && peer->dstadr != NULL)
937
0
    enable_multicast_if(peer->dstadr, srcadr);
938
939
#ifdef AUTOKEY
940
  if (key > NTP_MAXKEY)
941
    peer->flags |= FLAG_SKEY;
942
#endif  /* AUTOKEY */
943
0
  peer->ttl = ttl;
944
0
  peer->keyid = key;
945
0
  if (ident != NULL)
946
0
    peer->ident = estrdup(ident);
947
0
  peer->precision = sys_precision;
948
0
  peer->hpoll = peer->minpoll;
949
0
  if (cast_flags & MDF_ACAST)
950
0
    peer_clear(peer, "ACST");
951
0
  else if (cast_flags & MDF_POOL)
952
0
    peer_clear(peer, "POOL");
953
0
  else if (cast_flags & MDF_MCAST)
954
0
    peer_clear(peer, "MCST");
955
0
  else if (cast_flags & MDF_BCAST)
956
0
    peer_clear(peer, "BCST");
957
0
  else
958
0
    peer_clear(peer, "INIT");
959
0
  if (mode_ntpdate)
960
0
    peer_ntpdate++;
961
962
  /*
963
   * Note time on statistics timers.
964
   */
965
0
  peer->timereset = current_time;
966
0
  peer->timereachable = current_time;
967
0
  peer->timereceived = current_time;
968
969
0
  if (ISREFCLOCKADR(&peer->srcadr)) {
970
0
#ifdef REFCLOCK
971
    /*
972
     * We let the reference clock support do clock
973
     * dependent initialization.  This includes setting
974
     * the peer timer, since the clock may have requirements
975
     * for this.
976
     */
977
0
    if (maxpoll == 0)
978
0
      peer->maxpoll = peer->minpoll;
979
0
    if (!refclock_newpeer(peer)) {
980
      /*
981
       * Dump it, something screwed up
982
       */
983
0
      set_peerdstadr(peer, NULL);
984
0
      free_peer(peer, 0);
985
0
      return NULL;
986
0
    }
987
#else /* REFCLOCK */
988
    msyslog(LOG_ERR, "refclock %s isn't supported. ntpd was compiled without refclock support.",
989
      stoa(&peer->srcadr));
990
    set_peerdstadr(peer, NULL);
991
    free_peer(peer, 0);
992
    return NULL;
993
#endif /* REFCLOCK */
994
0
  }
995
996
  /*
997
   * Put the new peer in the hash tables.
998
   */
999
0
  hash = NTP_HASH_ADDR(&peer->srcadr);
1000
0
  LINK_SLIST(peer_hash[hash], peer, adr_link);
1001
0
  peer_hash_count[hash]++;
1002
0
  hash = peer->associd & NTP_HASH_MASK;
1003
0
  LINK_SLIST(assoc_hash[hash], peer, aid_link);
1004
0
  assoc_hash_count[hash]++;
1005
0
  LINK_SLIST(peer_list, peer, p_link);
1006
1007
0
  restrict_source(&peer->srcadr, 0, 0);
1008
0
  mprintf_event(PEVNT_MOBIL, peer, "assoc %d", peer->associd);
1009
0
  DPRINTF(1, ("newpeer: %s->%s mode %u vers %u poll %u %u flags 0x%x 0x%x ttl %u key %08x\n",
1010
0
      latoa(peer->dstadr), stoa(&peer->srcadr), peer->hmode,
1011
0
      peer->version, peer->minpoll, peer->maxpoll, peer->flags,
1012
0
      peer->cast_flags, peer->ttl, peer->keyid));
1013
0
  return peer;
1014
0
}
1015
1016
1017
/*
1018
 * peer_clr_stats - clear peer module statistics counters
1019
 */
1020
void
1021
peer_clr_stats(void)
1022
0
{
1023
0
  findpeer_calls = 0;
1024
0
  assocpeer_calls = 0;
1025
0
  peer_allocations = 0;
1026
0
  peer_demobilizations = 0;
1027
0
  peer_timereset = current_time;
1028
0
}
1029
1030
1031
/*
1032
 * peer_reset - reset statistics counters
1033
 */
1034
void
1035
peer_reset(
1036
  struct peer *peer
1037
  )
1038
0
{
1039
0
  if (peer == NULL)
1040
0
    return;
1041
1042
0
  peer->timereset = current_time;
1043
0
  peer->sent = 0;
1044
0
  peer->received = 0;
1045
0
  peer->processed = 0;
1046
0
  peer->badauth = 0;
1047
0
  peer->bogusorg = 0;
1048
0
  peer->oldpkt = 0;
1049
0
  peer->seldisptoolarge = 0;
1050
0
  peer->selbroken = 0;
1051
0
}
1052
1053
1054
/*
1055
 * peer_all_reset - reset all peer statistics counters
1056
 */
1057
void
1058
peer_all_reset(void)
1059
0
{
1060
0
  struct peer *peer;
1061
1062
0
  for (peer = peer_list; peer != NULL; peer = peer->p_link)
1063
0
    peer_reset(peer);
1064
0
}
1065
1066
1067
/*
1068
 * findmanycastpeer - find and return a manycastclient or pool
1069
 *          association matching a received response.
1070
 */
1071
struct peer *
1072
findmanycastpeer(
1073
  struct recvbuf *rbufp /* receive buffer pointer */
1074
  )
1075
3
{
1076
3
  struct peer *peer;
1077
3
  struct pkt *pkt;
1078
3
  l_fp p_org;
1079
1080
  /*
1081
   * This routine is called upon arrival of a server-mode response
1082
   * to a manycastclient multicast solicitation, or to a pool
1083
   * server unicast solicitation.  Search the peer list for a
1084
   * manycastclient association where the last transmit timestamp
1085
   * matches the response packet's originate timestamp.  There can
1086
   * be multiple manycastclient associations, or multiple pool
1087
   * solicitation assocations, so this assumes the transmit
1088
   * timestamps are unique for such.
1089
   */
1090
3
  pkt = &rbufp->recv_pkt;
1091
3
  for (peer = peer_list; peer != NULL; peer = peer->p_link)
1092
0
    if (MDF_SOLICIT_MASK & peer->cast_flags) {
1093
0
      NTOHL_FP(&pkt->org, &p_org);
1094
0
      if (L_ISEQU(&p_org, &peer->aorg))
1095
0
        break;
1096
0
    }
1097
1098
3
  return peer;
1099
3
}
1100
1101
/* peer_cleanup - clean peer list prior to shutdown */
1102
void peer_cleanup(void)
1103
0
{
1104
0
        struct peer *peer;
1105
0
        associd_t assoc;
1106
1107
0
        for (assoc = initial_association_ID; assoc != current_association_ID; assoc++) {
1108
0
            if (assoc != 0U) {
1109
0
                peer = findpeerbyassoc(assoc);
1110
0
                if (peer != NULL)
1111
0
                    unpeer(peer);
1112
0
            }
1113
0
        }
1114
0
        peer = findpeerbyassoc(current_association_ID);
1115
0
        if (peer != NULL)
1116
0
            unpeer(peer);
1117
0
}