ntp_peer.c revision 1.1 1 1.1 kardel /* $NetBSD: ntp_peer.c,v 1.1 2009/12/13 16:55:35 kardel Exp $ */
2 1.1 kardel
3 1.1 kardel /*
4 1.1 kardel * ntp_peer.c - management of data maintained for peer associations
5 1.1 kardel */
6 1.1 kardel #ifdef HAVE_CONFIG_H
7 1.1 kardel #include <config.h>
8 1.1 kardel #endif
9 1.1 kardel
10 1.1 kardel #include <stdio.h>
11 1.1 kardel #include <sys/types.h>
12 1.1 kardel
13 1.1 kardel #include "ntpd.h"
14 1.1 kardel #include "ntp_lists.h"
15 1.1 kardel #include "ntp_stdlib.h"
16 1.1 kardel #include "ntp_control.h"
17 1.1 kardel #include <ntp_random.h>
18 1.1 kardel #ifdef OPENSSL
19 1.1 kardel #include "openssl/rand.h"
20 1.1 kardel #endif /* OPENSSL */
21 1.1 kardel
22 1.1 kardel #ifdef SYS_WINNT
23 1.1 kardel extern int accept_wildcard_if_for_winnt;
24 1.1 kardel #endif
25 1.1 kardel
26 1.1 kardel /*
27 1.1 kardel * Table of valid association combinations
28 1.1 kardel * ---------------------------------------
29 1.1 kardel *
30 1.1 kardel * packet->mode
31 1.1 kardel * peer->mode | UNSPEC ACTIVE PASSIVE CLIENT SERVER BCAST
32 1.1 kardel * ---------- | ---------------------------------------------
33 1.1 kardel * NO_PEER | e 1 0 1 1 1
34 1.1 kardel * ACTIVE | e 1 1 0 0 0
35 1.1 kardel * PASSIVE | e 1 e 0 0 0
36 1.1 kardel * CLIENT | e 0 0 0 1 0
37 1.1 kardel * SERVER | e 0 0 0 0 0
38 1.1 kardel * BCAST | e 0 0 0 0 0
39 1.1 kardel * BCLIENT | e 0 0 0 e 1
40 1.1 kardel *
41 1.1 kardel * One point to note here: a packet in BCAST mode can potentially match
42 1.1 kardel * a peer in CLIENT mode, but we that is a special case and we check for
43 1.1 kardel * that early in the decision process. This avoids having to keep track
44 1.1 kardel * of what kind of associations are possible etc... We actually
45 1.1 kardel * circumvent that problem by requiring that the first b(m)roadcast
46 1.1 kardel * received after the change back to BCLIENT mode sets the clock.
47 1.1 kardel */
48 1.1 kardel #define AM_MODES 7 /* number of rows and columns */
49 1.1 kardel #define NO_PEER 0 /* action when no peer is found */
50 1.1 kardel
51 1.1 kardel int AM[AM_MODES][AM_MODES] = {
52 1.1 kardel /* { UNSPEC, ACTIVE, PASSIVE, CLIENT, SERVER, BCAST } */
53 1.1 kardel
54 1.1 kardel /*NONE*/{ AM_ERR, AM_NEWPASS, AM_NOMATCH, AM_FXMIT, AM_MANYCAST, AM_NEWBCL},
55 1.1 kardel
56 1.1 kardel /*A*/ { AM_ERR, AM_PROCPKT, AM_PROCPKT, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
57 1.1 kardel
58 1.1 kardel /*P*/ { AM_ERR, AM_PROCPKT, AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
59 1.1 kardel
60 1.1 kardel /*C*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT, AM_NOMATCH},
61 1.1 kardel
62 1.1 kardel /*S*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
63 1.1 kardel
64 1.1 kardel /*BCST*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
65 1.1 kardel
66 1.1 kardel /*BCL*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT},
67 1.1 kardel };
68 1.1 kardel
69 1.1 kardel #define MATCH_ASSOC(x, y) AM[(x)][(y)]
70 1.1 kardel
71 1.1 kardel /*
72 1.1 kardel * These routines manage the allocation of memory to peer structures
73 1.1 kardel * and the maintenance of the peer hash table. The three main entry
74 1.1 kardel * points are findpeer(), which looks for matching peer structures in
75 1.1 kardel * the peer list, newpeer(), which allocates a new peer structure and
76 1.1 kardel * adds it to the list, and unpeer(), which demobilizes the association
77 1.1 kardel * and deallocates the structure.
78 1.1 kardel */
79 1.1 kardel /*
80 1.1 kardel * Peer hash tables
81 1.1 kardel */
82 1.1 kardel struct peer *peer_hash[NTP_HASH_SIZE]; /* peer hash table */
83 1.1 kardel int peer_hash_count[NTP_HASH_SIZE]; /* peers in each bucket */
84 1.1 kardel struct peer *assoc_hash[NTP_HASH_SIZE]; /* association ID hash table */
85 1.1 kardel int assoc_hash_count[NTP_HASH_SIZE]; /* peers in each bucket */
86 1.1 kardel static struct peer *peer_free; /* peer structures free list */
87 1.1 kardel int peer_free_count; /* count of free structures */
88 1.1 kardel
89 1.1 kardel /*
90 1.1 kardel * Association ID. We initialize this value randomly, then assign a new
91 1.1 kardel * value every time the peer structure is incremented.
92 1.1 kardel */
93 1.1 kardel static associd_t current_association_ID; /* association ID */
94 1.1 kardel
95 1.1 kardel /*
96 1.1 kardel * Memory allocation watermarks.
97 1.1 kardel */
98 1.1 kardel #define INIT_PEER_ALLOC 15 /* initialize for 15 peers */
99 1.1 kardel #define INC_PEER_ALLOC 5 /* when run out, add 5 more */
100 1.1 kardel
101 1.1 kardel /*
102 1.1 kardel * Miscellaneous statistic counters which may be queried.
103 1.1 kardel */
104 1.1 kardel u_long peer_timereset; /* time stat counters zeroed */
105 1.1 kardel u_long findpeer_calls; /* calls to findpeer */
106 1.1 kardel u_long assocpeer_calls; /* calls to findpeerbyassoc */
107 1.1 kardel u_long peer_allocations; /* allocations from free list */
108 1.1 kardel u_long peer_demobilizations; /* structs freed to free list */
109 1.1 kardel int total_peer_structs; /* peer structs */
110 1.1 kardel int peer_associations; /* mobilized associations */
111 1.1 kardel int peer_preempt; /* preemptable associations */
112 1.1 kardel static struct peer init_peer_alloc[INIT_PEER_ALLOC]; /* init alloc */
113 1.1 kardel
114 1.1 kardel static void getmorepeermem (void);
115 1.1 kardel static struct interface *select_peerinterface (struct peer *, sockaddr_u *, struct interface *, u_char);
116 1.1 kardel
117 1.1 kardel static int score(struct peer *);
118 1.1 kardel
119 1.1 kardel /*
120 1.1 kardel * init_peer - initialize peer data structures and counters
121 1.1 kardel *
122 1.1 kardel * N.B. We use the random number routine in here. It had better be
123 1.1 kardel * initialized prior to getting here.
124 1.1 kardel */
125 1.1 kardel void
126 1.1 kardel init_peer(void)
127 1.1 kardel {
128 1.1 kardel register int i;
129 1.1 kardel
130 1.1 kardel /*
131 1.1 kardel * Clear hash tables and counters.
132 1.1 kardel */
133 1.1 kardel memset(peer_hash, 0, sizeof(peer_hash));
134 1.1 kardel memset(peer_hash_count, 0, sizeof(peer_hash_count));
135 1.1 kardel memset(assoc_hash, 0, sizeof(assoc_hash));
136 1.1 kardel memset(assoc_hash_count, 0, sizeof(assoc_hash_count));
137 1.1 kardel
138 1.1 kardel /*
139 1.1 kardel * Clear stat counters
140 1.1 kardel */
141 1.1 kardel findpeer_calls = peer_allocations = 0;
142 1.1 kardel assocpeer_calls = peer_demobilizations = 0;
143 1.1 kardel
144 1.1 kardel /*
145 1.1 kardel * Initialize peer memory.
146 1.1 kardel */
147 1.1 kardel peer_free = NULL;
148 1.1 kardel for (i = 0; i < INIT_PEER_ALLOC; i++)
149 1.1 kardel LINK_SLIST(peer_free, &init_peer_alloc[i], next);
150 1.1 kardel total_peer_structs = INIT_PEER_ALLOC;
151 1.1 kardel peer_free_count = INIT_PEER_ALLOC;
152 1.1 kardel
153 1.1 kardel /*
154 1.1 kardel * Initialize our first association ID
155 1.1 kardel */
156 1.1 kardel while ((current_association_ID = ntp_random() & 0xffff) == 0);
157 1.1 kardel }
158 1.1 kardel
159 1.1 kardel
160 1.1 kardel /*
161 1.1 kardel * getmorepeermem - add more peer structures to the free list
162 1.1 kardel */
163 1.1 kardel static void
164 1.1 kardel getmorepeermem(void)
165 1.1 kardel {
166 1.1 kardel register int i;
167 1.1 kardel register struct peer *peer;
168 1.1 kardel
169 1.1 kardel peer = (struct peer *)emalloc(INC_PEER_ALLOC *
170 1.1 kardel sizeof(struct peer));
171 1.1 kardel for (i = 0; i < INC_PEER_ALLOC; i++) {
172 1.1 kardel LINK_SLIST(peer_free, peer, next);
173 1.1 kardel peer++;
174 1.1 kardel }
175 1.1 kardel
176 1.1 kardel total_peer_structs += INC_PEER_ALLOC;
177 1.1 kardel peer_free_count += INC_PEER_ALLOC;
178 1.1 kardel }
179 1.1 kardel
180 1.1 kardel
181 1.1 kardel /*
182 1.1 kardel * findexistingpeer - return a pointer to a peer in the hash table
183 1.1 kardel */
184 1.1 kardel struct peer *
185 1.1 kardel findexistingpeer(
186 1.1 kardel sockaddr_u *addr,
187 1.1 kardel struct peer *start_peer,
188 1.1 kardel int mode
189 1.1 kardel )
190 1.1 kardel {
191 1.1 kardel register struct peer *peer;
192 1.1 kardel
193 1.1 kardel /*
194 1.1 kardel * start_peer is included so we can locate instances of the
195 1.1 kardel * same peer through different interfaces in the hash table.
196 1.1 kardel */
197 1.1 kardel if (NULL == start_peer)
198 1.1 kardel peer = peer_hash[NTP_HASH_ADDR(addr)];
199 1.1 kardel else
200 1.1 kardel peer = start_peer->next;
201 1.1 kardel
202 1.1 kardel while (peer != NULL) {
203 1.1 kardel if (SOCK_EQ(addr, &peer->srcadr)
204 1.1 kardel && NSRCPORT(addr) == NSRCPORT(&peer->srcadr)
205 1.1 kardel && (-1 == mode || peer->hmode == mode))
206 1.1 kardel break;
207 1.1 kardel peer = peer->next;
208 1.1 kardel }
209 1.1 kardel return (peer);
210 1.1 kardel }
211 1.1 kardel
212 1.1 kardel
213 1.1 kardel /*
214 1.1 kardel * findpeer - find and return a peer in the hash table.
215 1.1 kardel */
216 1.1 kardel struct peer *
217 1.1 kardel findpeer(
218 1.1 kardel sockaddr_u *srcadr,
219 1.1 kardel struct interface *dstadr,
220 1.1 kardel int pkt_mode,
221 1.1 kardel int *action
222 1.1 kardel )
223 1.1 kardel {
224 1.1 kardel register struct peer *peer;
225 1.1 kardel u_int hash;
226 1.1 kardel
227 1.1 kardel findpeer_calls++;
228 1.1 kardel hash = NTP_HASH_ADDR(srcadr);
229 1.1 kardel for (peer = peer_hash[hash]; peer != NULL; peer = peer->next) {
230 1.1 kardel if (SOCK_EQ(srcadr, &peer->srcadr) &&
231 1.1 kardel NSRCPORT(srcadr) == NSRCPORT(&peer->srcadr)) {
232 1.1 kardel
233 1.1 kardel /*
234 1.1 kardel * if the association matching rules determine
235 1.1 kardel * that this is not a valid combination, then
236 1.1 kardel * look for the next valid peer association.
237 1.1 kardel */
238 1.1 kardel *action = MATCH_ASSOC(peer->hmode, pkt_mode);
239 1.1 kardel
240 1.1 kardel /*
241 1.1 kardel * if an error was returned, exit back right
242 1.1 kardel * here.
243 1.1 kardel */
244 1.1 kardel if (*action == AM_ERR)
245 1.1 kardel return ((struct peer *)0);
246 1.1 kardel
247 1.1 kardel /*
248 1.1 kardel * if a match is found, we stop our search.
249 1.1 kardel */
250 1.1 kardel if (*action != AM_NOMATCH)
251 1.1 kardel break;
252 1.1 kardel }
253 1.1 kardel }
254 1.1 kardel
255 1.1 kardel /*
256 1.1 kardel * If no matching association is found
257 1.1 kardel */
258 1.1 kardel if (peer == 0) {
259 1.1 kardel *action = MATCH_ASSOC(NO_PEER, pkt_mode);
260 1.1 kardel return ((struct peer *)0);
261 1.1 kardel }
262 1.1 kardel set_peerdstadr(peer, dstadr);
263 1.1 kardel return (peer);
264 1.1 kardel }
265 1.1 kardel
266 1.1 kardel /*
267 1.1 kardel * findpeerbyassocid - find and return a peer using his association ID
268 1.1 kardel */
269 1.1 kardel struct peer *
270 1.1 kardel findpeerbyassoc(
271 1.1 kardel u_int assoc
272 1.1 kardel )
273 1.1 kardel {
274 1.1 kardel register struct peer *peer;
275 1.1 kardel u_int hash;
276 1.1 kardel
277 1.1 kardel assocpeer_calls++;
278 1.1 kardel
279 1.1 kardel hash = assoc & NTP_HASH_MASK;
280 1.1 kardel for (peer = assoc_hash[hash]; peer != 0; peer =
281 1.1 kardel peer->ass_next) {
282 1.1 kardel if (assoc == peer->associd)
283 1.1 kardel return (peer);
284 1.1 kardel }
285 1.1 kardel return (NULL);
286 1.1 kardel }
287 1.1 kardel
288 1.1 kardel
289 1.1 kardel /*
290 1.1 kardel * clear_all - flush all time values for all associations
291 1.1 kardel */
292 1.1 kardel void
293 1.1 kardel clear_all(void)
294 1.1 kardel {
295 1.1 kardel struct peer *peer, *next_peer;
296 1.1 kardel int n;
297 1.1 kardel
298 1.1 kardel /*
299 1.1 kardel * This routine is called when the clock is stepped, and so all
300 1.1 kardel * previously saved time values are untrusted.
301 1.1 kardel */
302 1.1 kardel for (n = 0; n < NTP_HASH_SIZE; n++) {
303 1.1 kardel for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
304 1.1 kardel next_peer = peer->next;
305 1.1 kardel if (!(peer->cast_flags & (MDF_ACAST |
306 1.1 kardel MDF_MCAST | MDF_BCAST))) {
307 1.1 kardel peer_clear(peer, "STEP");
308 1.1 kardel }
309 1.1 kardel }
310 1.1 kardel }
311 1.1 kardel #ifdef DEBUG
312 1.1 kardel if (debug)
313 1.1 kardel printf("clear_all: at %lu\n", current_time);
314 1.1 kardel #endif
315 1.1 kardel }
316 1.1 kardel
317 1.1 kardel
318 1.1 kardel /*
319 1.1 kardel * score_all() - determine if an association can be demobilized
320 1.1 kardel */
321 1.1 kardel int
322 1.1 kardel score_all(
323 1.1 kardel struct peer *peer /* peer structure pointer */
324 1.1 kardel )
325 1.1 kardel {
326 1.1 kardel struct peer *speer, *next_peer;
327 1.1 kardel int n;
328 1.1 kardel int temp, tamp;
329 1.1 kardel
330 1.1 kardel /*
331 1.1 kardel * This routine finds the minimum score for all ephemeral
332 1.1 kardel * assocations and returns > 0 if the association can be
333 1.1 kardel * demobilized.
334 1.1 kardel */
335 1.1 kardel tamp = score(peer);
336 1.1 kardel temp = 100;
337 1.1 kardel for (n = 0; n < NTP_HASH_SIZE; n++) {
338 1.1 kardel for (speer = peer_hash[n]; speer != 0; speer =
339 1.1 kardel next_peer) {
340 1.1 kardel int x;
341 1.1 kardel
342 1.1 kardel next_peer = speer->next;
343 1.1 kardel if ((x = score(speer)) < temp && (peer->flags &
344 1.1 kardel FLAG_PREEMPT))
345 1.1 kardel temp = x;
346 1.1 kardel }
347 1.1 kardel }
348 1.1 kardel #ifdef DEBUG
349 1.1 kardel if (debug)
350 1.1 kardel printf("score_all: at %lu score %d min %d\n",
351 1.1 kardel current_time, tamp, temp);
352 1.1 kardel #endif
353 1.1 kardel if (tamp != temp)
354 1.1 kardel temp = 0;
355 1.1 kardel return (temp);
356 1.1 kardel }
357 1.1 kardel
358 1.1 kardel
359 1.1 kardel /*
360 1.1 kardel * score() - calculate preemption score
361 1.1 kardel */
362 1.1 kardel static int
363 1.1 kardel score(
364 1.1 kardel struct peer *peer /* peer structure pointer */
365 1.1 kardel )
366 1.1 kardel {
367 1.1 kardel int temp;
368 1.1 kardel
369 1.1 kardel /*
370 1.1 kardel * This routine calculates the premption score from the peer
371 1.1 kardel * error bits and status. Increasing values are more cherished.
372 1.1 kardel */
373 1.1 kardel temp = 0;
374 1.1 kardel if (!(peer->flash & TEST10))
375 1.1 kardel temp++; /* 1 good synch and stratum */
376 1.1 kardel if (!(peer->flash & TEST13))
377 1.1 kardel temp++; /* 2 reachable */
378 1.1 kardel if (!(peer->flash & TEST12))
379 1.1 kardel temp++; /* 3 no loop */
380 1.1 kardel if (!(peer->flash & TEST11))
381 1.1 kardel temp++; /* 4 good distance */
382 1.1 kardel if (peer->status >= CTL_PST_SEL_SELCAND)
383 1.1 kardel temp++; /* 5 in the hunt */
384 1.1 kardel if (peer->status != CTL_PST_SEL_EXCESS)
385 1.1 kardel temp++; /* 6 not spare tire */
386 1.1 kardel return (temp); /* selection status */
387 1.1 kardel }
388 1.1 kardel
389 1.1 kardel
390 1.1 kardel /*
391 1.1 kardel * unpeer - remove peer structure from hash table and free structure
392 1.1 kardel */
393 1.1 kardel void
394 1.1 kardel unpeer(
395 1.1 kardel struct peer *peer_to_remove
396 1.1 kardel )
397 1.1 kardel {
398 1.1 kardel register struct peer *unlinked;
399 1.1 kardel int hash;
400 1.1 kardel char tbuf[80];
401 1.1 kardel
402 1.1 kardel snprintf(tbuf, sizeof(tbuf), "assoc %d",
403 1.1 kardel peer_to_remove->associd);
404 1.1 kardel report_event(PEVNT_DEMOBIL, peer_to_remove, tbuf);
405 1.1 kardel set_peerdstadr(peer_to_remove, NULL);
406 1.1 kardel hash = NTP_HASH_ADDR(&peer_to_remove->srcadr);
407 1.1 kardel peer_hash_count[hash]--;
408 1.1 kardel peer_demobilizations++;
409 1.1 kardel peer_associations--;
410 1.1 kardel if (peer_to_remove->flags & FLAG_PREEMPT)
411 1.1 kardel peer_preempt--;
412 1.1 kardel #ifdef REFCLOCK
413 1.1 kardel /*
414 1.1 kardel * If this peer is actually a clock, shut it down first
415 1.1 kardel */
416 1.1 kardel if (peer_to_remove->flags & FLAG_REFCLOCK)
417 1.1 kardel refclock_unpeer(peer_to_remove);
418 1.1 kardel #endif
419 1.1 kardel peer_to_remove->action = 0; /* disable timeout actions */
420 1.1 kardel
421 1.1 kardel UNLINK_SLIST(unlinked, peer_hash[hash], peer_to_remove, next,
422 1.1 kardel struct peer);
423 1.1 kardel
424 1.1 kardel if (NULL == unlinked) {
425 1.1 kardel peer_hash_count[hash]++;
426 1.1 kardel msyslog(LOG_ERR, "peer struct for %s not in table!",
427 1.1 kardel stoa(&peer_to_remove->srcadr));
428 1.1 kardel }
429 1.1 kardel
430 1.1 kardel /*
431 1.1 kardel * Remove him from the association hash as well.
432 1.1 kardel */
433 1.1 kardel hash = peer_to_remove->associd & NTP_HASH_MASK;
434 1.1 kardel assoc_hash_count[hash]--;
435 1.1 kardel
436 1.1 kardel UNLINK_SLIST(unlinked, assoc_hash[hash], peer_to_remove,
437 1.1 kardel ass_next, struct peer);
438 1.1 kardel
439 1.1 kardel if (NULL == unlinked) {
440 1.1 kardel assoc_hash_count[hash]++;
441 1.1 kardel msyslog(LOG_ERR,
442 1.1 kardel "peer struct for %s not in association table!",
443 1.1 kardel stoa(&peer_to_remove->srcadr));
444 1.1 kardel }
445 1.1 kardel
446 1.1 kardel LINK_SLIST(peer_free, peer_to_remove, next);
447 1.1 kardel peer_free_count++;
448 1.1 kardel }
449 1.1 kardel
450 1.1 kardel
451 1.1 kardel /*
452 1.1 kardel * peer_config - configure a new association
453 1.1 kardel */
454 1.1 kardel struct peer *
455 1.1 kardel peer_config(
456 1.1 kardel sockaddr_u *srcadr,
457 1.1 kardel struct interface *dstadr,
458 1.1 kardel int hmode,
459 1.1 kardel int version,
460 1.1 kardel int minpoll,
461 1.1 kardel int maxpoll,
462 1.1 kardel u_int flags,
463 1.1 kardel int ttl,
464 1.1 kardel keyid_t key,
465 1.1 kardel u_char *keystr
466 1.1 kardel )
467 1.1 kardel {
468 1.1 kardel u_char cast_flags;
469 1.1 kardel
470 1.1 kardel /*
471 1.1 kardel * We do a dirty little jig to figure the cast flags. This is
472 1.1 kardel * probably not the best place to do this, at least until the
473 1.1 kardel * configure code is rebuilt. Note only one flag can be set.
474 1.1 kardel */
475 1.1 kardel switch (hmode) {
476 1.1 kardel case MODE_BROADCAST:
477 1.1 kardel if (IS_MCAST(srcadr))
478 1.1 kardel cast_flags = MDF_MCAST;
479 1.1 kardel else
480 1.1 kardel cast_flags = MDF_BCAST;
481 1.1 kardel break;
482 1.1 kardel
483 1.1 kardel case MODE_CLIENT:
484 1.1 kardel if (IS_MCAST(srcadr))
485 1.1 kardel cast_flags = MDF_ACAST;
486 1.1 kardel else
487 1.1 kardel cast_flags = MDF_UCAST;
488 1.1 kardel break;
489 1.1 kardel
490 1.1 kardel default:
491 1.1 kardel cast_flags = MDF_UCAST;
492 1.1 kardel }
493 1.1 kardel
494 1.1 kardel /*
495 1.1 kardel * Mobilize the association and initialize its variables. If
496 1.1 kardel * emulating ntpdate, force iburst.
497 1.1 kardel */
498 1.1 kardel if (mode_ntpdate)
499 1.1 kardel flags |= FLAG_IBURST;
500 1.1 kardel return(newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll,
501 1.1 kardel flags | FLAG_CONFIG, cast_flags, ttl, key));
502 1.1 kardel }
503 1.1 kardel
504 1.1 kardel /*
505 1.1 kardel * setup peer dstadr field keeping it in sync with the interface
506 1.1 kardel * structures
507 1.1 kardel */
508 1.1 kardel void
509 1.1 kardel set_peerdstadr(
510 1.1 kardel struct peer *peer,
511 1.1 kardel struct interface *interface
512 1.1 kardel )
513 1.1 kardel {
514 1.1 kardel struct peer *unlinked;
515 1.1 kardel
516 1.1 kardel if (peer->dstadr != interface) {
517 1.1 kardel if (interface != NULL && (peer->cast_flags &
518 1.1 kardel MDF_BCLNT) && (interface->flags & INT_MCASTIF) &&
519 1.1 kardel peer->burst) {
520 1.1 kardel
521 1.1 kardel /*
522 1.1 kardel * don't accept updates to a true multicast
523 1.1 kardel * reception interface while a BCLNT peer is
524 1.1 kardel * running it's unicast protocol
525 1.1 kardel */
526 1.1 kardel return;
527 1.1 kardel }
528 1.1 kardel if (peer->dstadr != NULL) {
529 1.1 kardel peer->dstadr->peercnt--;
530 1.1 kardel UNLINK_SLIST(unlinked, peer->dstadr->peers,
531 1.1 kardel peer, ilink, struct peer);
532 1.1 kardel msyslog(LOG_INFO,
533 1.1 kardel "%s interface %s -> %s",
534 1.1 kardel stoa(&peer->srcadr),
535 1.1 kardel stoa(&peer->dstadr->sin),
536 1.1 kardel (interface != NULL)
537 1.1 kardel ? stoa(&interface->sin)
538 1.1 kardel : "(null)");
539 1.1 kardel }
540 1.1 kardel peer->dstadr = interface;
541 1.1 kardel if (peer->dstadr != NULL) {
542 1.1 kardel LINK_SLIST(peer->dstadr->peers, peer, ilink);
543 1.1 kardel peer->dstadr->peercnt++;
544 1.1 kardel }
545 1.1 kardel }
546 1.1 kardel }
547 1.1 kardel
548 1.1 kardel /*
549 1.1 kardel * attempt to re-rebind interface if necessary
550 1.1 kardel */
551 1.1 kardel static void
552 1.1 kardel peer_refresh_interface(
553 1.1 kardel struct peer *peer
554 1.1 kardel )
555 1.1 kardel {
556 1.1 kardel struct interface *niface, *piface;
557 1.1 kardel
558 1.1 kardel niface = select_peerinterface(peer, &peer->srcadr, NULL,
559 1.1 kardel peer->cast_flags);
560 1.1 kardel
561 1.1 kardel #ifdef DEBUG
562 1.1 kardel if (debug > 3)
563 1.1 kardel {
564 1.1 kardel printf(
565 1.1 kardel "peer_refresh_interface: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %d key %08x: new interface: ",
566 1.1 kardel peer->dstadr == NULL ? "<null>" :
567 1.1 kardel stoa(&peer->dstadr->sin), stoa(&peer->srcadr),
568 1.1 kardel peer->hmode, peer->version, peer->minpoll,
569 1.1 kardel peer->maxpoll, peer->flags, peer->cast_flags,
570 1.1 kardel peer->ttl, peer->keyid);
571 1.1 kardel if (niface != NULL) {
572 1.1 kardel printf(
573 1.1 kardel "fd=%d, bfd=%d, name=%.16s, flags=0x%x, scope=%d, ",
574 1.1 kardel niface->fd, niface->bfd, niface->name,
575 1.1 kardel niface->flags, niface->scopeid);
576 1.1 kardel printf(", sin=%s", stoa((&niface->sin)));
577 1.1 kardel if (niface->flags & INT_BROADCAST)
578 1.1 kardel printf(", bcast=%s,",
579 1.1 kardel stoa((&niface->bcast)));
580 1.1 kardel printf(", mask=%s\n", stoa((&niface->mask)));
581 1.1 kardel } else {
582 1.1 kardel printf("<NONE>\n");
583 1.1 kardel }
584 1.1 kardel }
585 1.1 kardel #endif
586 1.1 kardel
587 1.1 kardel piface = peer->dstadr;
588 1.1 kardel set_peerdstadr(peer, niface);
589 1.1 kardel if (peer->dstadr) {
590 1.1 kardel /*
591 1.1 kardel * clear crypto if we change the local address
592 1.1 kardel */
593 1.1 kardel if (peer->dstadr != piface && !(peer->cast_flags &
594 1.1 kardel MDF_ACAST) && peer->pmode != MODE_BROADCAST)
595 1.1 kardel peer_clear(peer, "XFAC");
596 1.1 kardel
597 1.1 kardel /*
598 1.1 kardel * Broadcast needs the socket enabled for broadcast
599 1.1 kardel */
600 1.1 kardel if (peer->cast_flags & MDF_BCAST) {
601 1.1 kardel enable_broadcast(peer->dstadr, &peer->srcadr);
602 1.1 kardel }
603 1.1 kardel
604 1.1 kardel /*
605 1.1 kardel * Multicast needs the socket interface enabled for
606 1.1 kardel * multicast
607 1.1 kardel */
608 1.1 kardel if (peer->cast_flags & MDF_MCAST) {
609 1.1 kardel enable_multicast_if(peer->dstadr,
610 1.1 kardel &peer->srcadr);
611 1.1 kardel }
612 1.1 kardel }
613 1.1 kardel }
614 1.1 kardel
615 1.1 kardel /*
616 1.1 kardel * refresh_all_peerinterfaces - see that all interface bindings are up
617 1.1 kardel * to date
618 1.1 kardel */
619 1.1 kardel void
620 1.1 kardel refresh_all_peerinterfaces(void)
621 1.1 kardel {
622 1.1 kardel struct peer *peer, *next_peer;
623 1.1 kardel int n;
624 1.1 kardel
625 1.1 kardel /*
626 1.1 kardel * this is called when the interface list has changed
627 1.1 kardel * give all peers a chance to find a better interface
628 1.1 kardel */
629 1.1 kardel for (n = 0; n < NTP_HASH_SIZE; n++) {
630 1.1 kardel for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
631 1.1 kardel next_peer = peer->next;
632 1.1 kardel peer_refresh_interface(peer);
633 1.1 kardel }
634 1.1 kardel }
635 1.1 kardel }
636 1.1 kardel
637 1.1 kardel
638 1.1 kardel /*
639 1.1 kardel * find an interface suitable for the src address
640 1.1 kardel */
641 1.1 kardel static struct interface *
642 1.1 kardel select_peerinterface(
643 1.1 kardel struct peer * peer,
644 1.1 kardel sockaddr_u * srcadr,
645 1.1 kardel struct interface * dstadr,
646 1.1 kardel u_char cast_flags
647 1.1 kardel )
648 1.1 kardel {
649 1.1 kardel struct interface *interface;
650 1.1 kardel
651 1.1 kardel /*
652 1.1 kardel * Initialize the peer structure and dance the interface jig.
653 1.1 kardel * Reference clocks step the loopback waltz, the others
654 1.1 kardel * squaredance around the interface list looking for a buddy. If
655 1.1 kardel * the dance peters out, there is always the wildcard interface.
656 1.1 kardel * This might happen in some systems and would preclude proper
657 1.1 kardel * operation with public key cryptography.
658 1.1 kardel */
659 1.1 kardel if (ISREFCLOCKADR(srcadr))
660 1.1 kardel interface = loopback_interface;
661 1.1 kardel else
662 1.1 kardel if (cast_flags & (MDF_BCLNT | MDF_ACAST | MDF_MCAST | MDF_BCAST)) {
663 1.1 kardel interface = findbcastinter(srcadr);
664 1.1 kardel #ifdef DEBUG
665 1.1 kardel if (debug > 3) {
666 1.1 kardel if (interface != NULL)
667 1.1 kardel printf("Found *-cast interface address %s, for address %s\n",
668 1.1 kardel stoa(&(interface)->sin), stoa(srcadr));
669 1.1 kardel else
670 1.1 kardel printf("No *-cast local address found for address %s\n",
671 1.1 kardel stoa(srcadr));
672 1.1 kardel }
673 1.1 kardel #endif
674 1.1 kardel /*
675 1.1 kardel * If it was a multicast packet,
676 1.1 kardel * findbcastinter() may not find it, so try a
677 1.1 kardel * little harder.
678 1.1 kardel */
679 1.1 kardel if (interface == ANY_INTERFACE_CHOOSE(srcadr))
680 1.1 kardel interface = findinterface(srcadr);
681 1.1 kardel }
682 1.1 kardel else if (dstadr != NULL && dstadr !=
683 1.1 kardel ANY_INTERFACE_CHOOSE(srcadr))
684 1.1 kardel interface = dstadr;
685 1.1 kardel else
686 1.1 kardel interface = findinterface(srcadr);
687 1.1 kardel
688 1.1 kardel /*
689 1.1 kardel * we do not bind to the wildcard interfaces for output
690 1.1 kardel * as our (network) source address would be undefined and
691 1.1 kardel * crypto will not work without knowing the own transmit address
692 1.1 kardel */
693 1.1 kardel if (interface != NULL && interface->flags & INT_WILDCARD)
694 1.1 kardel #ifdef SYS_WINNT
695 1.1 kardel if ( !accept_wildcard_if_for_winnt )
696 1.1 kardel #endif
697 1.1 kardel interface = NULL;
698 1.1 kardel
699 1.1 kardel
700 1.1 kardel return interface;
701 1.1 kardel }
702 1.1 kardel
703 1.1 kardel /*
704 1.1 kardel * newpeer - initialize a new peer association
705 1.1 kardel */
706 1.1 kardel struct peer *
707 1.1 kardel newpeer(
708 1.1 kardel sockaddr_u *srcadr,
709 1.1 kardel struct interface *dstadr,
710 1.1 kardel int hmode,
711 1.1 kardel int version,
712 1.1 kardel int minpoll,
713 1.1 kardel int maxpoll,
714 1.1 kardel u_int flags,
715 1.1 kardel u_char cast_flags,
716 1.1 kardel int ttl,
717 1.1 kardel keyid_t key
718 1.1 kardel )
719 1.1 kardel {
720 1.1 kardel struct peer *peer;
721 1.1 kardel u_int hash;
722 1.1 kardel char tbuf[80];
723 1.1 kardel
724 1.1 kardel #ifdef OPENSSL
725 1.1 kardel /*
726 1.1 kardel * If Autokey is requested but not configured, complain loudly.
727 1.1 kardel */
728 1.1 kardel if (!crypto_flags) {
729 1.1 kardel if (key > NTP_MAXKEY) {
730 1.1 kardel return (NULL);
731 1.1 kardel
732 1.1 kardel } else if (flags & FLAG_SKEY) {
733 1.1 kardel msyslog(LOG_ERR, "Autokey not configured");
734 1.1 kardel return (NULL);
735 1.1 kardel }
736 1.1 kardel }
737 1.1 kardel #endif /* OPENSSL */
738 1.1 kardel
739 1.1 kardel /*
740 1.1 kardel * First search from the beginning for an association with given
741 1.1 kardel * remote address and mode. If an interface is given, search
742 1.1 kardel * from there to find the association which matches that
743 1.1 kardel * destination. If the given interface is "any", track down the
744 1.1 kardel * actual interface, because that's what gets put into the peer
745 1.1 kardel * structure.
746 1.1 kardel */
747 1.1 kardel peer = findexistingpeer(srcadr, NULL, hmode);
748 1.1 kardel if (dstadr != NULL) {
749 1.1 kardel while (peer != NULL) {
750 1.1 kardel if (peer->dstadr == dstadr)
751 1.1 kardel break;
752 1.1 kardel
753 1.1 kardel if (dstadr == ANY_INTERFACE_CHOOSE(srcadr) &&
754 1.1 kardel peer->dstadr == findinterface(srcadr))
755 1.1 kardel break;
756 1.1 kardel
757 1.1 kardel peer = findexistingpeer(srcadr, peer, hmode);
758 1.1 kardel }
759 1.1 kardel }
760 1.1 kardel
761 1.1 kardel /*
762 1.1 kardel * If a peer is found, this would be a duplicate and we don't
763 1.1 kardel * allow that. This is mostly to avoid duplicate pool
764 1.1 kardel * associations.
765 1.1 kardel */
766 1.1 kardel if (peer != NULL)
767 1.1 kardel return (NULL);
768 1.1 kardel
769 1.1 kardel /*
770 1.1 kardel * Allocate a new peer structure. Some dirt here, since some of
771 1.1 kardel * the initialization requires knowlege of our system state.
772 1.1 kardel */
773 1.1 kardel if (peer_free_count == 0)
774 1.1 kardel getmorepeermem();
775 1.1 kardel UNLINK_HEAD_SLIST(peer, peer_free, next);
776 1.1 kardel peer_free_count--;
777 1.1 kardel peer_associations++;
778 1.1 kardel if (flags & FLAG_PREEMPT)
779 1.1 kardel peer_preempt++;
780 1.1 kardel memset(peer, 0, sizeof(*peer));
781 1.1 kardel
782 1.1 kardel /*
783 1.1 kardel * Assign an association ID and increment the system variable.
784 1.1 kardel */
785 1.1 kardel peer->associd = current_association_ID;
786 1.1 kardel if (++current_association_ID == 0)
787 1.1 kardel ++current_association_ID;
788 1.1 kardel
789 1.1 kardel DPRINTF(3, ("newpeer: cast flags: 0x%x for address: %s\n",
790 1.1 kardel cast_flags, stoa(srcadr)));
791 1.1 kardel
792 1.1 kardel peer->srcadr = *srcadr;
793 1.1 kardel set_peerdstadr(peer, select_peerinterface(peer, srcadr, dstadr,
794 1.1 kardel cast_flags));
795 1.1 kardel peer->hmode = (u_char)hmode;
796 1.1 kardel peer->version = (u_char)version;
797 1.1 kardel peer->flags = flags;
798 1.1 kardel
799 1.1 kardel /*
800 1.1 kardel * It is an error to set minpoll less than NTP_MINPOLL or to
801 1.1 kardel * set maxpoll greater than NTP_MAXPOLL. However, minpoll is
802 1.1 kardel * clamped not greater than NTP_MAXPOLL and maxpoll is clamped
803 1.1 kardel * not less than NTP_MINPOLL without complaint. Finally,
804 1.1 kardel * minpoll is clamped not greater than maxpoll.
805 1.1 kardel */
806 1.1 kardel if (minpoll == 0)
807 1.1 kardel peer->minpoll = NTP_MINDPOLL;
808 1.1 kardel else
809 1.1 kardel peer->minpoll = (u_char)min(minpoll, NTP_MAXPOLL);
810 1.1 kardel if (maxpoll == 0)
811 1.1 kardel peer->maxpoll = NTP_MAXDPOLL;
812 1.1 kardel else
813 1.1 kardel peer->maxpoll = (u_char)max(maxpoll, NTP_MINPOLL);
814 1.1 kardel if (peer->minpoll > peer->maxpoll)
815 1.1 kardel peer->minpoll = peer->maxpoll;
816 1.1 kardel
817 1.1 kardel if (peer->dstadr)
818 1.1 kardel DPRINTF(3, ("newpeer: using fd %d and our addr %s\n",
819 1.1 kardel peer->dstadr->fd, stoa(&peer->dstadr->sin)));
820 1.1 kardel else
821 1.1 kardel DPRINTF(3, ("newpeer: local interface currently not bound\n"));
822 1.1 kardel
823 1.1 kardel /*
824 1.1 kardel * Broadcast needs the socket enabled for broadcast
825 1.1 kardel */
826 1.1 kardel if ((cast_flags & MDF_BCAST) && peer->dstadr)
827 1.1 kardel enable_broadcast(peer->dstadr, srcadr);
828 1.1 kardel
829 1.1 kardel /*
830 1.1 kardel * Multicast needs the socket interface enabled for multicast
831 1.1 kardel */
832 1.1 kardel if ((cast_flags & MDF_MCAST) && peer->dstadr)
833 1.1 kardel enable_multicast_if(peer->dstadr, srcadr);
834 1.1 kardel
835 1.1 kardel #ifdef OPENSSL
836 1.1 kardel if (key > NTP_MAXKEY)
837 1.1 kardel peer->flags |= FLAG_SKEY;
838 1.1 kardel #endif /* OPENSSL */
839 1.1 kardel peer->cast_flags = cast_flags;
840 1.1 kardel peer->ttl = (u_char)ttl;
841 1.1 kardel peer->keyid = key;
842 1.1 kardel peer->precision = sys_precision;
843 1.1 kardel peer->hpoll = peer->minpoll;
844 1.1 kardel if (cast_flags & MDF_ACAST)
845 1.1 kardel peer_clear(peer, "ACST");
846 1.1 kardel else if (cast_flags & MDF_MCAST)
847 1.1 kardel peer_clear(peer, "MCST");
848 1.1 kardel else if (cast_flags & MDF_BCAST)
849 1.1 kardel peer_clear(peer, "BCST");
850 1.1 kardel else
851 1.1 kardel peer_clear(peer, "INIT");
852 1.1 kardel if (mode_ntpdate)
853 1.1 kardel peer_ntpdate++;
854 1.1 kardel
855 1.1 kardel /*
856 1.1 kardel * Note time on statistics timers.
857 1.1 kardel */
858 1.1 kardel peer->timereset = current_time;
859 1.1 kardel peer->timereachable = current_time;
860 1.1 kardel peer->timereceived = current_time;
861 1.1 kardel
862 1.1 kardel #ifdef REFCLOCK
863 1.1 kardel if (ISREFCLOCKADR(&peer->srcadr)) {
864 1.1 kardel
865 1.1 kardel /*
866 1.1 kardel * We let the reference clock support do clock
867 1.1 kardel * dependent initialization. This includes setting
868 1.1 kardel * the peer timer, since the clock may have requirements
869 1.1 kardel * for this.
870 1.1 kardel */
871 1.1 kardel if (maxpoll == 0)
872 1.1 kardel peer->maxpoll = peer->minpoll;
873 1.1 kardel if (!refclock_newpeer(peer)) {
874 1.1 kardel /*
875 1.1 kardel * Dump it, something screwed up
876 1.1 kardel */
877 1.1 kardel set_peerdstadr(peer, NULL);
878 1.1 kardel LINK_SLIST(peer_free, peer, next);
879 1.1 kardel peer_free_count++;
880 1.1 kardel return (NULL);
881 1.1 kardel }
882 1.1 kardel }
883 1.1 kardel #endif
884 1.1 kardel
885 1.1 kardel /*
886 1.1 kardel * Put the new peer in the hash tables.
887 1.1 kardel */
888 1.1 kardel hash = NTP_HASH_ADDR(&peer->srcadr);
889 1.1 kardel LINK_SLIST(peer_hash[hash], peer, next);
890 1.1 kardel peer_hash_count[hash]++;
891 1.1 kardel hash = peer->associd & NTP_HASH_MASK;
892 1.1 kardel LINK_SLIST(assoc_hash[hash], peer, ass_next);
893 1.1 kardel assoc_hash_count[hash]++;
894 1.1 kardel snprintf(tbuf, sizeof(tbuf), "assoc %d", peer->associd);
895 1.1 kardel report_event(PEVNT_MOBIL, peer, tbuf);
896 1.1 kardel DPRINTF(1, ("newpeer: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %d key %08x\n",
897 1.1 kardel peer->dstadr == NULL ? "<null>" : stoa(&peer->dstadr->sin),
898 1.1 kardel stoa(&peer->srcadr), peer->hmode, peer->version,
899 1.1 kardel peer->minpoll, peer->maxpoll, peer->flags, peer->cast_flags,
900 1.1 kardel peer->ttl, peer->keyid));
901 1.1 kardel return (peer);
902 1.1 kardel }
903 1.1 kardel
904 1.1 kardel
905 1.1 kardel /*
906 1.1 kardel * peer_clr_stats - clear peer module statiistics counters
907 1.1 kardel */
908 1.1 kardel void
909 1.1 kardel peer_clr_stats(void)
910 1.1 kardel {
911 1.1 kardel findpeer_calls = 0;
912 1.1 kardel assocpeer_calls = 0;
913 1.1 kardel peer_allocations = 0;
914 1.1 kardel peer_demobilizations = 0;
915 1.1 kardel peer_timereset = current_time;
916 1.1 kardel }
917 1.1 kardel
918 1.1 kardel /*
919 1.1 kardel * peer_reset - reset statistics counters
920 1.1 kardel */
921 1.1 kardel void
922 1.1 kardel peer_reset(
923 1.1 kardel struct peer *peer
924 1.1 kardel )
925 1.1 kardel {
926 1.1 kardel if (peer == NULL)
927 1.1 kardel return;
928 1.1 kardel
929 1.1 kardel peer->timereset = current_time;
930 1.1 kardel peer->sent = 0;
931 1.1 kardel peer->received = 0;
932 1.1 kardel peer->processed = 0;
933 1.1 kardel peer->badauth = 0;
934 1.1 kardel peer->bogusorg = 0;
935 1.1 kardel peer->oldpkt = 0;
936 1.1 kardel peer->seldisptoolarge = 0;
937 1.1 kardel peer->selbroken = 0;
938 1.1 kardel }
939 1.1 kardel
940 1.1 kardel
941 1.1 kardel /*
942 1.1 kardel * peer_all_reset - reset all peer statistics counters
943 1.1 kardel */
944 1.1 kardel void
945 1.1 kardel peer_all_reset(void)
946 1.1 kardel {
947 1.1 kardel struct peer *peer;
948 1.1 kardel int hash;
949 1.1 kardel
950 1.1 kardel for (hash = 0; hash < NTP_HASH_SIZE; hash++)
951 1.1 kardel for (peer = peer_hash[hash]; peer != 0; peer = peer->next)
952 1.1 kardel peer_reset(peer);
953 1.1 kardel }
954 1.1 kardel
955 1.1 kardel
956 1.1 kardel /*
957 1.1 kardel * findmanycastpeer - find and return a manycast peer
958 1.1 kardel */
959 1.1 kardel struct peer *
960 1.1 kardel findmanycastpeer(
961 1.1 kardel struct recvbuf *rbufp /* receive buffer pointer */
962 1.1 kardel )
963 1.1 kardel {
964 1.1 kardel register struct peer *peer;
965 1.1 kardel struct pkt *pkt;
966 1.1 kardel l_fp p_org;
967 1.1 kardel int i;
968 1.1 kardel
969 1.1 kardel /*
970 1.1 kardel * This routine is called upon arrival of a server-mode message
971 1.1 kardel * from a manycast client. Search the peer list for a manycast
972 1.1 kardel * client association where the last transmit timestamp matches
973 1.1 kardel * the originate timestamp. This assumes the transmit timestamps
974 1.1 kardel * for possibly more than one manycast association are unique.
975 1.1 kardel */
976 1.1 kardel pkt = &rbufp->recv_pkt;
977 1.1 kardel for (i = 0; i < NTP_HASH_SIZE; i++) {
978 1.1 kardel if (peer_hash_count[i] == 0)
979 1.1 kardel continue;
980 1.1 kardel
981 1.1 kardel for (peer = peer_hash[i]; peer != 0; peer =
982 1.1 kardel peer->next) {
983 1.1 kardel if (peer->cast_flags & MDF_ACAST) {
984 1.1 kardel NTOHL_FP(&pkt->org, &p_org);
985 1.1 kardel if (L_ISEQU(&p_org, &peer->aorg))
986 1.1 kardel return (peer);
987 1.1 kardel }
988 1.1 kardel }
989 1.1 kardel }
990 1.1 kardel return (NULL);
991 1.1 kardel }
992