File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / ntpd / ntp_peer.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 1 month ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    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>