#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#include "ntpd.h"
#include "ntp_lists.h"
#include "ntp_stdlib.h"
#include "ntp_control.h"
#include <ntp_random.h>
#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_NOMATCH},
{ 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];
struct peer *peer_list;
static struct peer *peer_free;
int peer_free_count;
static associd_t current_association_ID;
static associd_t initial_association_ID;
#define INIT_PEER_ALLOC 8
#define INC_PEER_ALLOC 4
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 struct peer * findexistingpeer_name(const char *, u_short,
struct peer *, int);
static struct peer * findexistingpeer_addr(sockaddr_u *,
struct peer *, int,
u_char);
static void free_peer(struct peer *, int);
static void getmorepeermem(void);
static int score(struct peer *);
void
init_peer(void)
{
int i;
for (i = COUNTOF(init_peer_alloc) - 1; i >= 0; i--)
LINK_SLIST(peer_free, &init_peer_alloc[i], p_link);
total_peer_structs = COUNTOF(init_peer_alloc);
peer_free_count = COUNTOF(init_peer_alloc);
do
current_association_ID = ntp_random() & ASSOCID_MAX;
while (!current_association_ID);
initial_association_ID = current_association_ID;
}
static void
getmorepeermem(void)
{
int i;
struct peer *peers;
peers = eallocarray(INC_PEER_ALLOC, sizeof(*peers));
for (i = INC_PEER_ALLOC - 1; i >= 0; i--)
LINK_SLIST(peer_free, &peers[i], p_link);
total_peer_structs += INC_PEER_ALLOC;
peer_free_count += INC_PEER_ALLOC;
}
static struct peer *
findexistingpeer_name(
const char * hostname,
u_short hname_fam,
struct peer * start_peer,
int mode
)
{
struct peer *p;
if (NULL == start_peer)
p = peer_list;
else
p = start_peer->p_link;
for (; p != NULL; p = p->p_link)
if (p->hostname != NULL
&& (-1 == mode || p->hmode == mode)
&& (AF_UNSPEC == hname_fam
|| AF_UNSPEC == AF(&p->srcadr)
|| hname_fam == AF(&p->srcadr))
&& !strcasecmp(p->hostname, hostname))
break;
return p;
}
static
struct peer *
findexistingpeer_addr(
sockaddr_u * addr,
struct peer * start_peer,
int mode,
u_char cast_flags
)
{
struct peer *peer;
DPRINTF(2, ("findexistingpeer_addr(%s, %s, %d, 0x%x)\n",
sptoa(addr),
(start_peer)
? sptoa(&start_peer->srcadr)
: "NULL",
mode, (u_int)cast_flags));
if (NULL == start_peer)
peer = peer_hash[NTP_HASH_ADDR(addr)];
else
peer = start_peer->adr_link;
while (peer != NULL) {
DPRINTF(3, ("%s %s %d %d 0x%x 0x%x ", sptoa(addr),
sptoa(&peer->srcadr), mode, peer->hmode,
(u_int)cast_flags, (u_int)peer->cast_flags));
if ((-1 == mode || peer->hmode == mode ||
((MDF_BCLNT & peer->cast_flags) &&
(MDF_BCLNT & cast_flags))) &&
ADDR_PORT_EQ(addr, &peer->srcadr)) {
DPRINTF(3, ("found.\n"));
break;
}
DPRINTF(3, ("\n"));
peer = peer->adr_link;
}
return peer;
}
struct peer *
findexistingpeer(
sockaddr_u * addr,
const char * hostname,
struct peer * start_peer,
int mode,
u_char cast_flags
)
{
if (hostname != NULL)
return findexistingpeer_name(hostname, AF(addr),
start_peer, mode);
else
return findexistingpeer_addr(addr, start_peer, mode,
cast_flags);
}
struct peer *
findpeer(
struct recvbuf *rbufp,
int pkt_mode,
int * action
)
{
struct peer * p;
sockaddr_u * srcadr;
u_int hash;
struct pkt * pkt;
l_fp pkt_org;
findpeer_calls++;
srcadr = &rbufp->recv_srcadr;
hash = NTP_HASH_ADDR(srcadr);
for (p = peer_hash[hash]; p != NULL; p = p->adr_link) {
if (p->hmode != MODE_BCLIENT && p->dstadr != rbufp->dstadr)
continue;
if ( ! ADDR_PORT_EQ(srcadr, &p->srcadr))
continue;
*action = MATCH_ASSOC(p->hmode, pkt_mode);
if (MODE_SERVER == pkt_mode && AM_PROCPKT == *action) {
pkt = &rbufp->recv_pkt;
NTOHL_FP(&pkt->org, &pkt_org);
if (!L_ISEQU(&p->aorg, &pkt_org) &&
findmanycastpeer(rbufp))
*action = AM_ERR;
}
if (*action == AM_ERR)
return NULL;
if (*action != AM_NOMATCH)
break;
}
if (NULL == p)
*action = MATCH_ASSOC(NO_PEER, pkt_mode);
return p;
}
struct peer *
findpeerbyassoc(
associd_t assoc
)
{
struct peer *p;
u_int hash;
assocpeer_calls++;
hash = assoc & NTP_HASH_MASK;
for (p = assoc_hash[hash]; p != NULL; p = p->aid_link)
if (assoc == p->associd)
break;
return p;
}
void
clear_all(void)
{
struct peer *p;
for (p = peer_list; p != NULL; p = p->p_link)
if (!(MDF_TXONLY_MASK & p->cast_flags))
peer_clear(p, "STEP");
DPRINTF(1, ("clear_all: at %lu\n", current_time));
}
int
score_all(
struct peer *peer
)
{
struct peer *speer;
int temp, tamp;
int x;
tamp = score(peer);
temp = 100;
for (speer = peer_list; speer != NULL; speer = speer->p_link)
if (speer->flags & FLAG_PREEMPT) {
x = score(speer);
if (x < temp)
temp = x;
}
DPRINTF(1, ("score_all: at %lu score %d min %d\n",
current_time, tamp, temp));
if (tamp != temp)
temp = 0;
return temp;
}
static int
score(
struct peer *peer
)
{
int temp;
temp = 0;
if (!(peer->flash & TEST10))
temp++;
if (!(peer->flash & TEST13))
temp++;
if (!(peer->flash & TEST12))
temp++;
if (!(peer->flash & TEST11))
temp++;
if (peer->status >= CTL_PST_SEL_SELCAND)
temp++;
if (peer->status != CTL_PST_SEL_EXCESS)
temp++;
return (temp);
}
static void
free_peer(
struct peer * p,
int unlink_peer
)
{
struct peer * unlinked;
int hash;
if (unlink_peer) {
hash = NTP_HASH_ADDR(&p->srcadr);
peer_hash_count[hash]--;
UNLINK_SLIST(unlinked, peer_hash[hash], p, adr_link,
struct peer);
if (NULL == unlinked) {
peer_hash_count[hash]++;
msyslog(LOG_ERR, "peer %s not in address table!",
stoa(&p->srcadr));
}
hash = p->associd & NTP_HASH_MASK;
assoc_hash_count[hash]--;
UNLINK_SLIST(unlinked, assoc_hash[hash], p, aid_link,
struct peer);
if (NULL == unlinked) {
assoc_hash_count[hash]++;
msyslog(LOG_ERR,
"peer %s not in association ID table!",
stoa(&p->srcadr));
}
UNLINK_SLIST(unlinked, peer_list, p, p_link,
struct peer);
if (NULL == unlinked)
msyslog(LOG_ERR, "%s not in peer list!",
stoa(&p->srcadr));
}
if (p->hostname != NULL)
free(p->hostname);
if (p->ident != NULL)
free(p->ident);
if (p->addrs != NULL)
free(p->addrs);
free(p->dns_name);
ZERO(*p);
LINK_SLIST(peer_free, p, p_link);
peer_free_count++;
}
void
unpeer(
struct peer *peer
)
{
mprintf_event(PEVNT_DEMOBIL, peer, "assoc %u", peer->associd);
restrict_source(&peer->srcadr, 1, 0);
set_peerdstadr(peer, NULL);
peer_demobilizations++;
peer_associations--;
if (FLAG_PREEMPT & peer->flags)
peer_preempt--;
#ifdef REFCLOCK
if (FLAG_REFCLOCK & peer->flags)
refclock_unpeer(peer);
#endif
free_peer(peer, TRUE);
}
struct peer *
peer_config(
sockaddr_u * srcadr,
const char * hostname,
endpt * dstadr,
u_char hmode,
u_char version,
u_char minpoll,
u_char maxpoll,
u_int flags,
u_int32 ttl,
keyid_t key,
const char * ident,
const char * dns_name
)
{
u_char cast_flags;
u_long next_update;
struct peer *peer = NULL;
switch (hmode) {
case MODE_BROADCAST:
if (IS_MCAST(srcadr))
cast_flags = MDF_MCAST;
else
cast_flags = MDF_BCAST;
break;
case MODE_CLIENT:
if (hostname != NULL && SOCK_UNSPEC(srcadr))
cast_flags = MDF_POOL;
else if (IS_MCAST(srcadr))
cast_flags = MDF_ACAST;
else
cast_flags = MDF_UCAST;
break;
default:
cast_flags = MDF_UCAST;
}
flags |= FLAG_CONFIG;
if (mode_ntpdate)
flags |= FLAG_IBURST;
if ((MDF_ACAST | MDF_POOL) & cast_flags)
flags &= ~FLAG_PREEMPT;
peer = newpeer(srcadr, hostname, dstadr, hmode, version, minpoll, maxpoll,
flags | FLAG_CONFIG, cast_flags, ttl, key, ident);
if (peer) {
peer->dns_name = strdup(dns_name);
msyslog(LOG_NOTICE, "peer %s @ %s", dns_name, stoa(&peer->srcadr));
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 * p,
endpt * dstadr
)
{
struct peer * unlinked;
DEBUG_INSIST(p != NULL);
if (p == NULL)
return;
if (p->dstadr == dstadr)
return;
if (dstadr != NULL && (FLAG_BC_VOL & p->flags) &&
(INT_MCASTIF & dstadr->flags) && MODE_CLIENT == p->hmode) {
return;
}
if (p->dstadr != NULL) {
p->dstadr->peercnt--;
UNLINK_SLIST(unlinked, p->dstadr->peers, p, ilink,
struct peer);
msyslog(LOG_INFO, "%s local addr %s -> %s",
stoa(&p->srcadr), latoa(p->dstadr),
latoa(dstadr));
}
p->dstadr = dstadr;
if (p->dstadr != NULL) {
LINK_SLIST(dstadr->peers, p, ilink);
dstadr->peercnt++;
}
}
static void
peer_refresh_interface(
struct peer *p
)
{
endpt * niface;
endpt * piface;
niface = select_peerinterface(p, &p->srcadr, NULL);
DPRINTF(4, (
"peer_refresh_interface: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %u key %08x: new interface: ",
p->dstadr == NULL ? "<null>" :
stoa(&p->dstadr->sin), stoa(&p->srcadr), p->hmode,
p->version, p->minpoll, p->maxpoll, p->flags, p->cast_flags,
p->ttl, p->keyid));
if (niface != NULL) {
DPRINTF(4, (
"fd=%d, bfd=%d, name=%.16s, flags=0x%x, ifindex=%u, sin=%s",
niface->fd, niface->bfd, niface->name,
niface->flags, niface->ifindex,
stoa(&niface->sin)));
if (niface->flags & INT_BROADCAST)
DPRINTF(4, (", bcast=%s",
stoa(&niface->bcast)));
DPRINTF(4, (", mask=%s\n", stoa(&niface->mask)));
} else {
DPRINTF(4, ("<NONE>\n"));
}
piface = p->dstadr;
set_peerdstadr(p, niface);
if (p->dstadr != NULL) {
if (p->dstadr != piface && !(MDF_ACAST & p->cast_flags)
&& MODE_BROADCAST != p->pmode)
peer_clear(p, "XFAC");
if (MDF_BCAST & p->cast_flags)
enable_broadcast(p->dstadr, &p->srcadr);
if (MDF_MCAST & p->cast_flags)
enable_multicast_if(p->dstadr, &p->srcadr);
}
}
void
refresh_all_peerinterfaces(void)
{
struct peer *p;
for (p = peer_list; p != NULL; p = p->p_link) {
if (!(p->dstadr && (p->reach & 0x3))) peer_refresh_interface(p);
}
}
struct peer *
newpeer(
sockaddr_u * srcadr,
const char * hostname,
endpt * dstadr,
u_char hmode,
u_char version,
u_char minpoll,
u_char maxpoll,
u_int flags,
u_char cast_flags,
u_int32 ttl,
keyid_t key,
const char * ident
)
{
struct peer * peer;
u_int hash;
DEBUG_REQUIRE(srcadr);
#ifdef AUTOKEY
if (!crypto_flags) {
if (key > NTP_MAXKEY) {
return (NULL);
} else if (flags & FLAG_SKEY) {
msyslog(LOG_ERR, "Autokey not configured");
return (NULL);
}
}
#endif
INSIST(NULL == hostname || (MDF_POOL & cast_flags));
if (dstadr != NULL) {
peer = findexistingpeer(srcadr, hostname, NULL, hmode,
cast_flags);
while (peer != NULL) {
if (peer->dstadr == dstadr ||
((MDF_BCLNT & cast_flags) &&
(MDF_BCLNT & peer->cast_flags)))
break;
if (dstadr == ANY_INTERFACE_CHOOSE(srcadr) &&
peer->dstadr == findinterface(srcadr))
break;
peer = findexistingpeer(srcadr, hostname, peer,
hmode, cast_flags);
}
} else {
peer = findexistingpeer(srcadr, hostname, NULL, hmode,
cast_flags);
}
if (peer != NULL) {
DPRINTF(2, ("newpeer(%s) found existing association\n",
(hostname)
? hostname
: stoa(srcadr)));
return NULL;
}
if (peer_free_count == 0)
getmorepeermem();
UNLINK_HEAD_SLIST(peer, peer_free, p_link);
INSIST(peer != NULL);
peer_free_count--;
peer_associations++;
if (FLAG_PREEMPT & flags)
peer_preempt++;
peer->associd = current_association_ID;
if (++current_association_ID == 0)
++current_association_ID;
peer->srcadr = *srcadr;
if (hostname != NULL)
peer->hostname = estrdup(hostname);
peer->hmode = hmode;
peer->version = version;
peer->flags = flags;
peer->cast_flags = cast_flags;
set_peerdstadr(peer,
select_peerinterface(peer, srcadr, dstadr));
if (minpoll == 0)
peer->minpoll = NTP_MINDPOLL;
else {
peer->flags |= FLAG_UMINPOLL;
peer->minpoll = min(minpoll, NTP_MAXPOLL);
}
if (maxpoll == 0)
peer->maxpoll = NTP_MAXDPOLL;
else {
peer->flags |= FLAG_UMAXPOLL;
peer->maxpoll = max(maxpoll, NTP_MINPOLL);
}
if (peer->minpoll > peer->maxpoll)
peer->minpoll = peer->maxpoll;
if (peer->dstadr != NULL)
DPRINTF(3, ("newpeer(%s): using fd %d and our addr %s\n",
stoa(srcadr), peer->dstadr->fd,
stoa(&peer->dstadr->sin)));
else
DPRINTF(3, ("newpeer(%s): local interface currently not bound\n",
stoa(srcadr)));
if ((MDF_BCAST & cast_flags) && peer->dstadr != NULL)
enable_broadcast(peer->dstadr, srcadr);
if ((MDF_MCAST & cast_flags) && peer->dstadr != NULL)
enable_multicast_if(peer->dstadr, srcadr);
#ifdef AUTOKEY
if (key > NTP_MAXKEY)
peer->flags |= FLAG_SKEY;
#endif
peer->ttl = ttl;
peer->keyid = key;
if (ident != NULL)
peer->ident = estrdup(ident);
peer->precision = sys_precision;
peer->hpoll = peer->minpoll;
if (cast_flags & MDF_ACAST)
peer_clear(peer, "ACST");
else if (cast_flags & MDF_POOL)
peer_clear(peer, "POOL");
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;
if (ISREFCLOCKADR(&peer->srcadr)) {
#ifdef REFCLOCK
if (maxpoll == 0)
peer->maxpoll = peer->minpoll;
if (!refclock_newpeer(peer)) {
set_peerdstadr(peer, NULL);
free_peer(peer, 0);
return NULL;
}
#else
msyslog(LOG_ERR, "refclock %s isn't supported. ntpd was compiled without refclock support.",
stoa(&peer->srcadr));
set_peerdstadr(peer, NULL);
free_peer(peer, 0);
return NULL;
#endif
}
hash = NTP_HASH_ADDR(&peer->srcadr);
LINK_SLIST(peer_hash[hash], peer, adr_link);
peer_hash_count[hash]++;
hash = peer->associd & NTP_HASH_MASK;
LINK_SLIST(assoc_hash[hash], peer, aid_link);
assoc_hash_count[hash]++;
LINK_SLIST(peer_list, peer, p_link);
restrict_source(&peer->srcadr, 0, 0);
mprintf_event(PEVNT_MOBIL, peer, "assoc %d", peer->associd);
DPRINTF(1, ("newpeer: %s->%s mode %u vers %u poll %u %u flags 0x%x 0x%x ttl %u key %08x\n",
latoa(peer->dstadr), stoa(&peer->srcadr), peer->hmode,
peer->version, peer->minpoll, peer->maxpoll, peer->flags,
peer->cast_flags, peer->ttl, peer->keyid));
return peer;
}
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 == NULL)
return;
peer->timereset = current_time;
peer->sent = 0;
peer->received = 0;
peer->processed = 0;
peer->badauth = 0;
peer->bogusorg = 0;
peer->oldpkt = 0;
peer->seldisptoolarge = 0;
peer->selbroken = 0;
}
void
peer_all_reset(void)
{
struct peer *peer;
for (peer = peer_list; peer != NULL; peer = peer->p_link)
peer_reset(peer);
}
struct peer *
findmanycastpeer(
struct recvbuf *rbufp
)
{
struct peer *peer;
struct pkt *pkt;
l_fp p_org;
pkt = &rbufp->recv_pkt;
for (peer = peer_list; peer != NULL; peer = peer->p_link)
if (MDF_SOLICIT_MASK & peer->cast_flags) {
NTOHL_FP(&pkt->org, &p_org);
if (L_ISEQU(&p_org, &peer->aorg))
break;
}
return peer;
}
void peer_cleanup(void)
{
struct peer *peer;
associd_t assoc;
for (assoc = initial_association_ID; assoc != current_association_ID; assoc++) {
if (assoc != 0U) {
peer = findpeerbyassoc(assoc);
if (peer != NULL)
unpeer(peer);
}
}
peer = findpeerbyassoc(current_association_ID);
if (peer != NULL)
unpeer(peer);
}
#include <dns_util.h>
u_long get_dns_flags(
const 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;
}