📄 ntp_peer.c
字号:
* We do a dirty little jig to figure the cast flags. This is * probably not the best place to do this, at least until the * configure code is rebuilt. Note only one flag can be set. */ switch (hmode) { case MODE_BROADCAST: if(srcadr->ss_family == AF_INET) { if (IN_CLASSD(ntohl(((struct sockaddr_in*)srcadr)->sin_addr.s_addr))) cast_flags = MDF_MCAST; else cast_flags = MDF_BCAST; break; } else { if (IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)srcadr)->sin6_addr)) cast_flags = MDF_MCAST; else cast_flags = MDF_BCAST; break; } case MODE_CLIENT: if(srcadr->ss_family == AF_INET) { if (IN_CLASSD(ntohl(((struct sockaddr_in*)srcadr)->sin_addr.s_addr))) cast_flags = MDF_ACAST; else cast_flags = MDF_UCAST; break; } else { if (IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)srcadr)->sin6_addr)) cast_flags = MDF_ACAST; else cast_flags = MDF_UCAST; break; } default: cast_flags = MDF_UCAST; } /* * If the peer is already configured, some dope has a duplicate * configureation entry or another dope is wiggling from afar. */ if (peer != 0) { peer->hmode = (u_char)hmode; peer->version = (u_char) version; peer->minpoll = (u_char) minpoll; peer->maxpoll = (u_char) maxpoll; peer->flags = flags | FLAG_CONFIG | (peer->flags & FLAG_REFCLOCK); peer->cast_flags = cast_flags; peer->ttl = (u_char) ttl; peer->keyid = key; peer->precision = sys_precision; peer_clear(peer, "RMOT"); return (peer); } /* * Here no match has been found, so presumably this is a new * persistent association. Mobilize the thing and initialize its * variables. If emulating ntpdate, force iburst. */ if (mode_ntpdate) flags |= FLAG_IBURST; peer = newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll, flags | FLAG_CONFIG, cast_flags, ttl, key); return (peer);}/* * newpeer - initialize a new peer association */struct peer *newpeer( struct sockaddr_storage *srcadr, struct interface *dstadr, int hmode, int version, int minpoll, int maxpoll, u_int flags, u_char cast_flags, int ttl, keyid_t key ){ register struct peer *peer; register int i;#ifdef OPENSSL char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */#endif /* OPENSSL */ /* * Allocate a new peer structure. Some dirt here, since some of * the initialization requires knowlege of our system state. */ if (peer_free_count == 0) getmorepeermem(); peer = peer_free; peer_free = peer->next; peer_free_count--; peer_associations++; if (flags & FLAG_PREEMPT) peer_preempt++; memset((char *)peer, 0, sizeof(struct peer)); /* * Assign an association ID and increment the system variable. */ peer->associd = current_association_ID; if (++current_association_ID == 0) ++current_association_ID;#ifdef DEBUG if (debug >2) printf("newpeer: cast flags: 0x%x for address: %s\n", cast_flags, stoa(srcadr));#endif /* * Initialize the peer structure and dance the interface jig. * Reference clocks step the loopback waltz, the others * squaredance around the interface list looking for a buddy. If * the dance peters out, there is always the wildcard interface. * This might happen in some systems and would preclude proper * operation with public key cryptography. */ if (ISREFCLOCKADR(srcadr)) peer->dstadr = loopback_interface; else if (cast_flags & (MDF_BCLNT | MDF_ACAST | MDF_MCAST | MDF_BCAST)) { peer->dstadr = findbcastinter(srcadr);#ifdef DEBUG if (debug > 1) { if (peer->dstadr != NULL) printf("Found broadcast interface address %s, for address %s\n", stoa(&(peer->dstadr)->sin), stoa(srcadr)); else printf("No broadcast local address found for address %s\n", stoa(srcadr)); }#endif /* * If it was a multicast packet, findbcastinter() may not * find it, so try a little harder. */ if (peer->dstadr == ANY_INTERFACE_CHOOSE(srcadr)) peer->dstadr = findinterface(srcadr); } else if (dstadr != NULL && dstadr != ANY_INTERFACE_CHOOSE(srcadr)) peer->dstadr = dstadr; else peer->dstadr = findinterface(srcadr); /* * If we can't find an interface to use we return a NULL */ if (peer->dstadr == NULL) { msyslog(LOG_ERR, "Cannot find suitable interface for address %s", stoa(srcadr)); return (NULL); } /* * Broadcast needs the socket enabled for broadcast */ if (cast_flags & MDF_BCAST) { enable_broadcast(peer->dstadr, srcadr); } /* * Multicast needs the socket interface enabled for multicast */ if (cast_flags & MDF_MCAST) { enable_multicast_if(peer->dstadr, srcadr); }#ifdef DEBUG if (debug>2) printf("newpeer: using fd %d and our addr %s\n", peer->dstadr->fd, stoa(&peer->dstadr->sin));#endif peer->srcadr = *srcadr; peer->hmode = (u_char)hmode; peer->version = (u_char)version; peer->minpoll = (u_char)max(NTP_MINPOLL, minpoll); peer->maxpoll = (u_char)min(NTP_MAXPOLL, maxpoll); peer->flags = flags; if (key != 0) peer->flags |= FLAG_AUTHENABLE; if (key > NTP_MAXKEY) peer->flags |= FLAG_SKEY; peer->cast_flags = cast_flags; peer->ttl = (u_char)ttl; peer->keyid = key; peer->precision = sys_precision; peer->hpoll = peer->minpoll; if (cast_flags & MDF_ACAST) peer_clear(peer, "ACST"); else if (cast_flags & MDF_MCAST) peer_clear(peer, "MCST"); else if (cast_flags & MDF_BCAST) peer_clear(peer, "BCST"); else peer_clear(peer, "INIT"); if (mode_ntpdate) peer_ntpdate++; /* * Note time on statistics timers. */ peer->timereset = current_time; peer->timereachable = current_time; peer->timereceived = current_time;#ifdef REFCLOCK if (ISREFCLOCKADR(&peer->srcadr)) { /* * We let the reference clock support do clock * dependent initialization. This includes setting * the peer timer, since the clock may have requirements * for this. */ if (!refclock_newpeer(peer)) { /* * Dump it, something screwed up */ peer->next = peer_free; peer_free = peer; peer_free_count++; return (NULL); } }#endif /* * Put the new peer in the hash tables. */ i = NTP_HASH_ADDR(&peer->srcadr); peer->next = peer_hash[i]; peer_hash[i] = peer; peer_hash_count[i]++; i = peer->associd & NTP_HASH_MASK; peer->ass_next = assoc_hash[i]; assoc_hash[i] = peer; assoc_hash_count[i]++;#ifdef OPENSSL if (peer->flags & FLAG_SKEY) { sprintf(statstr, "newpeer %d", peer->associd); record_crypto_stats(&peer->srcadr, statstr);#ifdef DEBUG if (debug) printf("peer: %s\n", statstr);#endif }#endif /* OPENSSL */#ifdef DEBUG if (debug) printf( "newpeer: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %d key %08x\n", peer->dstadr == NULL ? "null" : stoa(&peer->dstadr->sin), stoa(&peer->srcadr), peer->hmode, peer->version, peer->minpoll, peer->maxpoll, peer->flags, peer->cast_flags, peer->ttl, peer->keyid);#endif return (peer);}/* * peer_unconfig - remove the configuration bit from a peer */intpeer_unconfig( struct sockaddr_storage *srcadr, struct interface *dstadr, int mode ){ register struct peer *peer; int num_found; num_found = 0; peer = findexistingpeer(srcadr, (struct peer *)0, mode); while (peer != 0) { if (peer->flags & FLAG_CONFIG && (dstadr == 0 || peer->dstadr == dstadr)) { num_found++; /* * Tricky stuff here. If the peer is polling us * in active mode, turn off the configuration * bit and make the mode passive. This allows us * to avoid dumping a lot of history for peers * we might choose to keep track of in passive * mode. The protocol will eventually terminate * undesirables on its own. */ if (peer->hmode == MODE_ACTIVE && peer->pmode == MODE_ACTIVE) { peer->hmode = MODE_PASSIVE; peer->flags &= ~FLAG_CONFIG; } else { unpeer(peer); peer = 0; } } peer = findexistingpeer(srcadr, peer, mode); } return (num_found);}/* * peer_clr_stats - clear peer module stat counters */voidpeer_clr_stats(void){ findpeer_calls = 0; assocpeer_calls = 0; peer_allocations = 0; peer_demobilizations = 0; peer_timereset = current_time;}/* * peer_reset - reset stat counters in a peer structure */voidpeer_reset( struct peer *peer ){ if (peer == 0) return; peer->sent = 0; peer->received = 0; peer->processed = 0; peer->badauth = 0; peer->bogusorg = 0; peer->oldpkt = 0; peer->seldisptoolarge = 0; peer->timereset = current_time;}/* * peer_all_reset - reset all peer stat counters */voidpeer_all_reset(void){ struct peer *peer; int hash; for (hash = 0; hash < NTP_HASH_SIZE; hash++) for (peer = peer_hash[hash]; peer != 0; peer = peer->next) peer_reset(peer);}#ifdef OPENSSL/* * expire_all - flush all crypto data and update timestamps. */voidexpire_all(void){ struct peer *peer, *next_peer; int n; /* * This routine is called about once per day from the timer * routine and when the client is first synchronized. Search the * peer list for all associations and flush only the key list * and cookie. If a manycast client association, flush * everything. Then, recompute and sign the agreement public * value, if present. */ if (!crypto_flags) return; for (n = 0; n < NTP_HASH_SIZE; n++) { for (peer = peer_hash[n]; peer != 0; peer = next_peer) { next_peer = peer->next; if (!(peer->flags & FLAG_SKEY)) { continue; } else if (peer->hmode == MODE_ACTIVE || peer->hmode == MODE_PASSIVE) { key_expire(peer); peer->crypto &= ~(CRYPTO_FLAG_AUTO | CRYPTO_FLAG_AGREE); } } } RAND_bytes((u_char *)&sys_private, 4); crypto_update();}#endif /* OPENSSL *//* * findmanycastpeer - find and return a manycast peer */struct peer *findmanycastpeer( struct recvbuf *rbufp ){ register struct peer *peer; struct pkt *pkt; l_fp p_org; int i; /* * This routine is called upon arrival of a server-mode message * from a manycast client. Search the peer list for a manycast * client association where the last transmit timestamp matches * the originate timestamp. This assumes the transmit timestamps * for possibly more than one manycast association are unique. */ pkt = &rbufp->recv_pkt; for (i = 0; i < NTP_HASH_SIZE; i++) { if (peer_hash_count[i] == 0) continue; for (peer = peer_hash[i]; peer != 0; peer = peer->next) { if (peer->cast_flags & MDF_ACAST) { NTOHL_FP(&pkt->org, &p_org); if (L_ISEQU(&peer->xmt, &p_org)) return (peer); } } } return (NULL);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -