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