#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#include "ntpd.h"
#include "ntp_stdlib.h"
#include <ntp_random.h>
#ifdef OPENSSL
#include "openssl/rand.h"
#endif
#define AM_MODES 7
#define NO_PEER 0
int AM[AM_MODES][AM_MODES] = {
{ AM_ERR, AM_NEWPASS, AM_NOMATCH, AM_FXMIT, AM_MANYCAST, AM_NEWBCL},
{ AM_ERR, AM_PROCPKT, AM_PROCPKT, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
{ AM_ERR, AM_PROCPKT, AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT, AM_POSSBCL},
{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT},
};
#define MATCH_ASSOC(x,y) AM[(x)][(y)]
struct peer *peer_hash[NTP_HASH_SIZE];
int peer_hash_count[NTP_HASH_SIZE];
struct peer *assoc_hash[NTP_HASH_SIZE];
int assoc_hash_count[NTP_HASH_SIZE];
static struct peer *peer_free;
int peer_free_count;
static associd_t current_association_ID;
#define INIT_PEER_ALLOC 15
#define INC_PEER_ALLOC 5
u_long peer_timereset;
u_long findpeer_calls;
u_long assocpeer_calls;
u_long peer_allocations;
u_long peer_demobilizations;
int total_peer_structs;
int peer_associations;
int peer_preempt;
static struct peer init_peer_alloc[INIT_PEER_ALLOC];
static void getmorepeermem P((void));
static struct interface *select_peerinterface P((struct peer *, struct sockaddr_storage *, struct interface *, u_char));
void
init_peer(void)
{
register int i;
for (i = 0; i < NTP_HASH_SIZE; i++) {
peer_hash[i] = 0;
peer_hash_count[i] = 0;
assoc_hash[i] = 0;
assoc_hash_count[i] = 0;
}
findpeer_calls = peer_allocations = 0;
assocpeer_calls = peer_demobilizations = 0;
peer_free = 0;
for (i = 0; i < INIT_PEER_ALLOC; i++) {
init_peer_alloc[i].next = peer_free;
peer_free = &init_peer_alloc[i];
}
total_peer_structs = INIT_PEER_ALLOC;
peer_free_count = INIT_PEER_ALLOC;
while ((current_association_ID = ntp_random() & 0xffff) == 0);
}
static void
getmorepeermem(void)
{
register int i;
register struct peer *peer;
peer = (struct peer *)emalloc(INC_PEER_ALLOC *
sizeof(struct peer));
for (i = 0; i < INC_PEER_ALLOC; i++) {
peer->next = peer_free;
peer_free = peer;
peer++;
}
total_peer_structs += INC_PEER_ALLOC;
peer_free_count += INC_PEER_ALLOC;
}
struct peer *
findexistingpeer(
struct sockaddr_storage *addr,
struct peer *start_peer,
int mode
)
{
register struct peer *peer;
if (start_peer == 0)
peer = peer_hash[NTP_HASH_ADDR(addr)];
else
peer = start_peer->next;
while (peer != 0) {
if (SOCKCMP(addr, &peer->srcadr)
&& NSRCPORT(addr) == NSRCPORT(&peer->srcadr)) {
if (mode == -1)
return (peer);
else if (peer->hmode == mode)
break;
}
peer = peer->next;
}
return (peer);
}
struct peer *
findpeer(
struct sockaddr_storage *srcadr,
struct interface *dstadr,
int pkt_mode,
int *action
)
{
register struct peer *peer;
int hash;
findpeer_calls++;
hash = NTP_HASH_ADDR(srcadr);
for (peer = peer_hash[hash]; peer != NULL; peer = peer->next) {
if (SOCKCMP(srcadr, &peer->srcadr) &&
NSRCPORT(srcadr) == NSRCPORT(&peer->srcadr)) {
*action = MATCH_ASSOC(peer->hmode, pkt_mode);
if (*action == AM_ERR)
return ((struct peer *)0);
if (*action != AM_NOMATCH)
break;
}
}
if (peer == 0) {
*action = MATCH_ASSOC(NO_PEER, pkt_mode);
return ((struct peer *)0);
}
set_peerdstadr(peer, dstadr);
return (peer);
}
struct peer *
findpeerbyassoc(
u_int assoc
)
{
register struct peer *peer;
int hash;
assocpeer_calls++;
hash = assoc & NTP_HASH_MASK;
for (peer = assoc_hash[hash]; peer != 0; peer =
peer->ass_next) {
if (assoc == peer->associd)
return (peer);
}
return (NULL);
}
void
clear_all(void)
{
struct peer *peer, *next_peer;
int n;
for (n = 0; n < NTP_HASH_SIZE; n++) {
for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
next_peer = peer->next;
if (!(peer->cast_flags & (MDF_ACAST | MDF_MCAST |
MDF_BCAST))) {
peer->hpoll = peer->minpoll;
peer_clear(peer, "STEP");
}
}
}
#ifdef DEBUG
if (debug)
printf("clear_all: at %lu\n", current_time);
#endif
}
void
unpeer(
struct peer *peer_to_remove
)
{
int hash;
#ifdef OPENSSL
char statstr[NTP_MAXSTRLEN];
if (peer_to_remove->flags & FLAG_SKEY) {
sprintf(statstr, "unpeer %d flash %x reach %03o flags %04x",
peer_to_remove->associd, peer_to_remove->flash,
peer_to_remove->reach, peer_to_remove->flags);
record_crypto_stats(&peer_to_remove->srcadr, statstr);
#ifdef DEBUG
if (debug)
printf("peer: %s\n", statstr);
#endif
}
#endif
#ifdef DEBUG
if (debug)
printf("demobilize %u %d %d\n", peer_to_remove->associd,
peer_associations, peer_preempt);
#endif
set_peerdstadr(peer_to_remove, NULL);
hash = NTP_HASH_ADDR(&peer_to_remove->srcadr);
peer_hash_count[hash]--;
peer_demobilizations++;
peer_associations--;
if (peer_to_remove->flags & FLAG_PREEMPT)
peer_preempt--;
#ifdef REFCLOCK
if (peer_to_remove->flags & FLAG_REFCLOCK)
refclock_unpeer(peer_to_remove);
#endif
peer_to_remove->action = 0;
if (peer_hash[hash] == peer_to_remove)
peer_hash[hash] = peer_to_remove->next;
else {
register struct peer *peer;
peer = peer_hash[hash];
while (peer != 0 && peer->next != peer_to_remove)
peer = peer->next;
if (peer == 0) {
peer_hash_count[hash]++;
msyslog(LOG_ERR, "peer struct for %s not in table!",
stoa(&peer->srcadr));
} else {
peer->next = peer_to_remove->next;
}
}
hash = peer_to_remove->associd & NTP_HASH_MASK;
assoc_hash_count[hash]--;
if (assoc_hash[hash] == peer_to_remove)
assoc_hash[hash] = peer_to_remove->ass_next;
else {
register struct peer *peer;
peer = assoc_hash[hash];
while (peer != 0 && peer->ass_next != peer_to_remove)
peer = peer->ass_next;
if (peer == 0) {
assoc_hash_count[hash]++;
msyslog(LOG_ERR,
"peer struct for %s not in association table!",
stoa(&peer->srcadr));
} else {
peer->ass_next = peer_to_remove->ass_next;
}
}
peer_to_remove->next = peer_free;
peer_free = peer_to_remove;
peer_free_count++;
}
struct peer *
peer_config(
struct sockaddr_storage *srcadr,
struct interface *dstadr,
int hmode,
int version,
int minpoll,
int maxpoll,
u_int flags,
int ttl,
keyid_t key,
u_char *keystr,
char *dns_name
)
{
register struct peer *peer;
u_char cast_flags;
u_long next_update;
peer = findexistingpeer(srcadr, (struct peer *)0, hmode);
if (dstadr != 0) {
while (peer != 0) {
if (peer->dstadr == dstadr)
break;
if (dstadr == ANY_INTERFACE_CHOOSE(srcadr) &&
peer->dstadr == findinterface(srcadr))
break;
peer = findexistingpeer(srcadr, peer, hmode);
}
}
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 (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);
}
if (mode_ntpdate)
flags |= FLAG_IBURST;
peer = newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll,
flags | FLAG_CONFIG, cast_flags, ttl, key);
if (peer) {
peer->dns_name = strdup(dns_name);
next_update = get_dns_flags(dns_name, peer);
if (dns_timer == 0 || (dns_timer > next_update))
dns_timer = next_update;
}
return (peer);
}
void
set_peerdstadr(struct peer *peer, struct interface *interface)
{
if (peer->dstadr != interface) {
if (interface != NULL &&
(peer->cast_flags & MDF_BCLNT) &&
(interface->flags & INT_MCASTIF) &&
peer->burst) {
return;
}
if (peer->dstadr != NULL)
{
peer->dstadr->peercnt--;
ISC_LIST_UNLINK_TYPE(peer->dstadr->peers, peer, ilink, struct peer);
}
DPRINTF(4, ("set_peerdstadr(%s): change interface from %s to %s\n",
stoa(&peer->srcadr),
(peer->dstadr != NULL) ? stoa(&peer->dstadr->sin) : "<null>",
(interface != NULL) ? stoa(&interface->sin) : "<null>"));
peer->dstadr = interface;
if (peer->dstadr != NULL)
{
ISC_LIST_APPEND(peer->dstadr->peers, peer, ilink);
peer->dstadr->peercnt++;
}
}
}
static void
peer_refresh_interface(struct peer *peer)
{
struct interface *niface, *piface;
niface = select_peerinterface(peer, &peer->srcadr, NULL, peer->cast_flags);
#ifdef DEBUG
if (debug > 3)
{
printf(
"peer_refresh_interface: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %d key %08x: new interface: ",
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);
if (niface != NULL)
{
printf("fd=%d, bfd=%d, name=%.16s, flags=0x%x, scope=%d, ",
niface->fd,
niface->bfd,
niface->name,
niface->flags,
niface->scopeid);
printf(", sin=%s",
stoa((&niface->sin)));
if (niface->flags & INT_BROADCAST)
printf(", bcast=%s,",
stoa((&niface->bcast)));
printf(", mask=%s\n",
stoa((&niface->mask)));
}
else
{
printf("<NONE>\n");
}
}
#endif
piface = peer->dstadr;
set_peerdstadr(peer, niface);
if (peer->dstadr) {
if (peer->dstadr != piface && !(peer->cast_flags & MDF_BCLNT)) {
peer_crypto_clear(peer);
}
if (peer->cast_flags & MDF_BCAST) {
enable_broadcast(peer->dstadr, &peer->srcadr);
}
if (peer->cast_flags & MDF_MCAST) {
enable_multicast_if(peer->dstadr, &peer->srcadr);
}
}
}
void
refresh_all_peerinterfaces(void)
{
struct peer *peer, *next_peer;
int n;
for (n = 0; n < NTP_HASH_SIZE; n++) {
for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
next_peer = peer->next;
peer_refresh_interface(peer);
}
}
}
static struct interface *
select_peerinterface(struct peer *peer, struct sockaddr_storage *srcadr, struct interface *dstadr, u_char cast_flags)
{
struct interface *interface;
if (ISREFCLOCKADR(srcadr))
interface = loopback_interface;
else
if (cast_flags & (MDF_BCLNT | MDF_ACAST | MDF_MCAST | MDF_BCAST)) {
interface = findbcastinter(srcadr);
#ifdef DEBUG
if (debug > 3) {
if (interface != NULL)
printf("Found *-cast interface address %s, for address %s\n",
stoa(&(interface)->sin), stoa(srcadr));
else
printf("No *-cast local address found for address %s\n",
stoa(srcadr));
}
#endif
if (interface == ANY_INTERFACE_CHOOSE(srcadr))
interface = findinterface(srcadr);
}
else if (dstadr != NULL && dstadr != ANY_INTERFACE_CHOOSE(srcadr))
interface = dstadr;
else
interface = findinterface(srcadr);
if (interface != NULL && interface->flags & INT_WILDCARD)
interface = NULL;
return interface;
}
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];
#endif
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));
peer->associd = current_association_ID;
if (++current_association_ID == 0)
++current_association_ID;
DPRINTF(3, ("newpeer: cast flags: 0x%x for address: %s\n",
cast_flags, stoa(srcadr)));
ISC_LINK_INIT(peer, ilink);
dstadr = select_peerinterface(peer, srcadr, dstadr, cast_flags);
if (dstadr == NULL && !(flags & FLAG_DYNAMIC))
{
msyslog(LOG_ERR, "Cannot find existing interface for address %s", stoa(srcadr));
peer->next = peer_free;
peer_free = peer;
peer_associations--;
peer_free_count++;
return (NULL);
}
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;
set_peerdstadr(peer, dstadr);
#ifdef DEBUG
if (debug > 2) {
if (peer->dstadr)
printf("newpeer: using fd %d and our addr %s\n",
peer->dstadr->fd, stoa(&peer->dstadr->sin));
else
printf("newpeer: local interface currently not bound\n");
}
#endif
if (cast_flags & MDF_BCAST && peer->dstadr) {
enable_broadcast(peer->dstadr, srcadr);
}
if (cast_flags & MDF_MCAST && peer->dstadr) {
enable_multicast_if(peer->dstadr, srcadr);
}
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++;
peer->timereset = current_time;
peer->timereachable = current_time;
peer->timereceived = current_time;
#ifdef REFCLOCK
if (ISREFCLOCKADR(&peer->srcadr)) {
if (!refclock_newpeer(peer)) {
set_peerdstadr(peer, NULL);
peer->next = peer_free;
peer_free = peer;
peer_free_count++;
return (NULL);
}
}
#endif
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);
DPRINTF(1, ("peer: %s\n", statstr));
}
#endif
DPRINTF(1, ("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));
return (peer);
}
int
peer_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++;
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);
}
void
peer_clr_stats(void)
{
findpeer_calls = 0;
assocpeer_calls = 0;
peer_allocations = 0;
peer_demobilizations = 0;
peer_timereset = current_time;
}
void
peer_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;
}
void
peer_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
void
expire_all(void)
{
struct peer *peer, *next_peer;
int n;
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
struct peer *
findmanycastpeer(
struct recvbuf *rbufp
)
{
register struct peer *peer;
struct pkt *pkt;
l_fp p_org;
int i;
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);
}
#include <dns_util.h>
u_long get_dns_flags(
char *dns_name,
struct peer* peer)
{
dns_handle_t handle;
dns_reply_t *reply;
dns_TXT_record_t *txt;
uint16_t klass, type;
handle = dns_open(NULL);
if (!handle) {
return 0;
}
dns_class_number("IN", &klass);
dns_type_number("TXT", &type);
reply = dns_lookup(handle, dns_name, klass, type);
if (reply) {
int a;
#if DEBUG
if (debug > 1) {
dns_print_reply(reply, stdout, 0xffff);
printf("status: %d\n", reply->status);
printf("answer count: %d\n", reply->header->ancount);
}
#endif
for (a = 0; a < reply->header->ancount; a++) {
if ((reply->answer[a]->dnstype != type) ||
(reply->answer[a]->dnsclass != klass))
continue;
txt = reply->answer[a]->data.TXT;
if (txt) {
int s;
u_int old_flags = peer->flags & (FLAG_BURST | FLAG_IBURST);
u_int new_flags = 0;
u_char minpoll = NTP_MINDPOLL;
u_char maxpoll = NTP_MAXDPOLL;
for (s = 0; s < txt->string_count; s++) {
#if DEBUG
if (debug > 1)
printf("%d: %s\n", s, txt->strings[s]);
#endif
if (0 == strncmp(txt->strings[s], "ntp ", 4)) {
char *next = txt->strings[s]+4;
char *arg, *p;
long arg_val;
if (peer->dns_ttl != reply->answer[a]->ttl) {
peer->dns_ttl = reply->answer[a]->ttl;
msyslog(LOG_INFO, "DNS %s ttl %d",
dns_name, peer->dns_ttl);
}
if (peer->dns_ttl != 0)
peer->dns_update = current_time + peer->dns_ttl;
while (NULL != (p = strsep(&next, " \t"))) {
switch (*p) {
case 'b':
if (strcmp(p, "burst") == 0) {
new_flags |= FLAG_BURST;
} else {
msyslog(LOG_WARNING, "DNS %s unknown configuration [%s]", dns_name, p);
}
break;
case 'i':
if (0 == strcmp(p, "iburst")) {
new_flags |= FLAG_IBURST;
} else {
msyslog(LOG_WARNING, "DNS %s unknown configuration [%s]", dns_name, p);
}
break;
case 'm':
if ((0 == (strcmp(p, "minpoll"))) || (0 == strcmp(p, "maxpoll"))) {
if (next) {
arg = strsep(&next, " \t");
arg_val = strtol(arg, NULL, 10);
if (p[1] == 'i') {
minpoll = (u_char)max(NTP_MINPOLL, arg_val);
} else {
maxpoll = (u_char)min(NTP_MAXPOLL, arg_val);
}
} else {
msyslog(LOG_WARNING, "DNS %s option %s missing numeric argument", dns_name, p);
}
} else {
msyslog(LOG_WARNING, "DNS %s unknown configuration [%s]", dns_name, p);
}
break;
default:
msyslog(LOG_WARNING, "DNS %s unknown configuration [%s]", dns_name, p);
break;
}
}
}
}
if (0 == (peer->flags & FLAG_UMINPOLL) && (minpoll != peer->minpoll)) {
peer->minpoll = minpoll;
msyslog(LOG_INFO, "DNS %s minpoll %d",
dns_name, peer->minpoll);
}
if (0 == (peer->flags & FLAG_UMAXPOLL) && (maxpoll != peer->maxpoll)) {
peer->maxpoll = maxpoll;
msyslog(LOG_INFO, "DNS %s maxpoll %d",
dns_name, peer->maxpoll);
}
if (new_flags != old_flags) {
u_int changes;
if (peer->flags & FLAG_UIBURST)
new_flags |= FLAG_IBURST;
if (peer->flags & FLAG_IBURST)
new_flags |= FLAG_IBURST;
changes = new_flags ^ old_flags;
if (changes & FLAG_IBURST) {
if (new_flags & FLAG_IBURST)
peer->flags |= FLAG_IBURST;
else
peer->flags &= ~FLAG_IBURST;
msyslog(LOG_INFO, "DNS %s %ciburst",
dns_name,
(new_flags & FLAG_IBURST) ? '+' : '-');
}
if (changes & FLAG_BURST) {
if (new_flags & FLAG_BURST)
peer->flags |= FLAG_BURST;
else
peer->flags &= ~FLAG_BURST;
msyslog(LOG_INFO, "DNS %s %cburst",
dns_name,
(new_flags & FLAG_BURST) ? '+' : '-');
}
}
}
}
dns_free_reply(reply);
}
dns_free(handle);
return peer->dns_update;
}