1 1.13 christos /* $NetBSD: ntp_peer.c,v 1.14 2024/08/18 20:47:17 christos Exp $ */ 2 1.1 kardel 3 1.1 kardel /* 4 1.1 kardel * ntp_peer.c - management of data maintained for peer associations 5 1.1 kardel */ 6 1.1 kardel #ifdef HAVE_CONFIG_H 7 1.1 kardel #include <config.h> 8 1.1 kardel #endif 9 1.1 kardel 10 1.1 kardel #include <stdio.h> 11 1.1 kardel #include <sys/types.h> 12 1.1 kardel 13 1.1 kardel #include "ntpd.h" 14 1.1 kardel #include "ntp_lists.h" 15 1.1 kardel #include "ntp_stdlib.h" 16 1.1 kardel #include "ntp_control.h" 17 1.1 kardel #include <ntp_random.h> 18 1.1 kardel 19 1.1 kardel /* 20 1.4 christos * Table of valid association combinations 21 1.4 christos * --------------------------------------- 22 1.1 kardel * 23 1.1 kardel * packet->mode 24 1.1 kardel * peer->mode | UNSPEC ACTIVE PASSIVE CLIENT SERVER BCAST 25 1.1 kardel * ---------- | --------------------------------------------- 26 1.1 kardel * NO_PEER | e 1 0 1 1 1 27 1.1 kardel * ACTIVE | e 1 1 0 0 0 28 1.1 kardel * PASSIVE | e 1 e 0 0 0 29 1.1 kardel * CLIENT | e 0 0 0 1 0 30 1.1 kardel * SERVER | e 0 0 0 0 0 31 1.1 kardel * BCAST | e 0 0 0 0 0 32 1.1 kardel * BCLIENT | e 0 0 0 e 1 33 1.1 kardel * 34 1.1 kardel * One point to note here: a packet in BCAST mode can potentially match 35 1.1 kardel * a peer in CLIENT mode, but we that is a special case and we check for 36 1.1 kardel * that early in the decision process. This avoids having to keep track 37 1.1 kardel * of what kind of associations are possible etc... We actually 38 1.1 kardel * circumvent that problem by requiring that the first b(m)roadcast 39 1.1 kardel * received after the change back to BCLIENT mode sets the clock. 40 1.1 kardel */ 41 1.1 kardel #define AM_MODES 7 /* number of rows and columns */ 42 1.1 kardel #define NO_PEER 0 /* action when no peer is found */ 43 1.1 kardel 44 1.14 christos const s_char AM[AM_MODES][AM_MODES] = { 45 1.4 christos /* packet->mode */ 46 1.4 christos /* peer { UNSPEC, ACTIVE, PASSIVE, CLIENT, SERVER, BCAST } */ 47 1.4 christos /* mode */ 48 1.1 kardel /*NONE*/{ AM_ERR, AM_NEWPASS, AM_NOMATCH, AM_FXMIT, AM_MANYCAST, AM_NEWBCL}, 49 1.1 kardel 50 1.1 kardel /*A*/ { AM_ERR, AM_PROCPKT, AM_PROCPKT, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH}, 51 1.1 kardel 52 1.1 kardel /*P*/ { AM_ERR, AM_PROCPKT, AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH}, 53 1.1 kardel 54 1.1 kardel /*C*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT, AM_NOMATCH}, 55 1.1 kardel 56 1.1 kardel /*S*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH}, 57 1.1 kardel 58 1.1 kardel /*BCST*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH}, 59 1.1 kardel 60 1.1 kardel /*BCL*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT}, 61 1.1 kardel }; 62 1.1 kardel 63 1.14 christos #define MATCH_ASSOC(x, y) (AM[CLAMP((x), 0, AM_MODES)][CLAMP((y), 0, AM_MODES)]) 64 1.1 kardel 65 1.1 kardel /* 66 1.1 kardel * These routines manage the allocation of memory to peer structures 67 1.4 christos * and the maintenance of three data structures involving all peers: 68 1.4 christos * 69 1.4 christos * - peer_list is a single list with all peers, suitable for scanning 70 1.4 christos * operations over all peers. 71 1.4 christos * - peer_adr_hash is an array of lists indexed by hashed peer address. 72 1.4 christos * - peer_aid_hash is an array of lists indexed by hashed associd. 73 1.4 christos * 74 1.4 christos * They also maintain a free list of peer structures, peer_free. 75 1.4 christos * 76 1.4 christos * The three main entry points are findpeer(), which looks for matching 77 1.4 christos * peer structures in the peer list, newpeer(), which allocates a new 78 1.4 christos * peer structure and adds it to the list, and unpeer(), which 79 1.4 christos * demobilizes the association and deallocates the structure. 80 1.1 kardel */ 81 1.1 kardel /* 82 1.1 kardel * Peer hash tables 83 1.1 kardel */ 84 1.1 kardel struct peer *peer_hash[NTP_HASH_SIZE]; /* peer hash table */ 85 1.1 kardel int peer_hash_count[NTP_HASH_SIZE]; /* peers in each bucket */ 86 1.1 kardel struct peer *assoc_hash[NTP_HASH_SIZE]; /* association ID hash table */ 87 1.4 christos int assoc_hash_count[NTP_HASH_SIZE];/* peers in each bucket */ 88 1.4 christos struct peer *peer_list; /* peer structures list */ 89 1.1 kardel static struct peer *peer_free; /* peer structures free list */ 90 1.1 kardel int peer_free_count; /* count of free structures */ 91 1.1 kardel 92 1.1 kardel /* 93 1.1 kardel * Association ID. We initialize this value randomly, then assign a new 94 1.4 christos * value every time an association is mobilized. 95 1.1 kardel */ 96 1.14 christos static associd_t current_association_ID; /* actually next poss. ID */ 97 1.14 christos static associd_t initial_association_ID; 98 1.1 kardel 99 1.1 kardel /* 100 1.1 kardel * Memory allocation watermarks. 101 1.1 kardel */ 102 1.4 christos #define INIT_PEER_ALLOC 8 /* static preallocation */ 103 1.4 christos #define INC_PEER_ALLOC 4 /* add N more when empty */ 104 1.1 kardel 105 1.1 kardel /* 106 1.1 kardel * Miscellaneous statistic counters which may be queried. 107 1.1 kardel */ 108 1.1 kardel u_long peer_timereset; /* time stat counters zeroed */ 109 1.1 kardel u_long findpeer_calls; /* calls to findpeer */ 110 1.1 kardel u_long assocpeer_calls; /* calls to findpeerbyassoc */ 111 1.1 kardel u_long peer_allocations; /* allocations from free list */ 112 1.1 kardel u_long peer_demobilizations; /* structs freed to free list */ 113 1.1 kardel int total_peer_structs; /* peer structs */ 114 1.1 kardel int peer_associations; /* mobilized associations */ 115 1.1 kardel int peer_preempt; /* preemptable associations */ 116 1.1 kardel static struct peer init_peer_alloc[INIT_PEER_ALLOC]; /* init alloc */ 117 1.1 kardel 118 1.4 christos static struct peer * findexistingpeer_name(const char *, u_short, 119 1.4 christos struct peer *, int); 120 1.4 christos static struct peer * findexistingpeer_addr(sockaddr_u *, 121 1.4 christos struct peer *, int, 122 1.12 christos u_char, int *); 123 1.4 christos static void free_peer(struct peer *, int); 124 1.4 christos static void getmorepeermem(void); 125 1.4 christos static int score(struct peer *); 126 1.1 kardel 127 1.1 kardel 128 1.1 kardel /* 129 1.1 kardel * init_peer - initialize peer data structures and counters 130 1.1 kardel * 131 1.1 kardel * N.B. We use the random number routine in here. It had better be 132 1.1 kardel * initialized prior to getting here. 133 1.1 kardel */ 134 1.1 kardel void 135 1.1 kardel init_peer(void) 136 1.1 kardel { 137 1.4 christos int i; 138 1.1 kardel 139 1.1 kardel /* 140 1.4 christos * Initialize peer free list from static allocation. 141 1.1 kardel */ 142 1.4 christos for (i = COUNTOF(init_peer_alloc) - 1; i >= 0; i--) 143 1.4 christos LINK_SLIST(peer_free, &init_peer_alloc[i], p_link); 144 1.4 christos total_peer_structs = COUNTOF(init_peer_alloc); 145 1.4 christos peer_free_count = COUNTOF(init_peer_alloc); 146 1.1 kardel 147 1.1 kardel /* 148 1.1 kardel * Initialize our first association ID 149 1.1 kardel */ 150 1.4 christos do 151 1.4 christos current_association_ID = ntp_random() & ASSOCID_MAX; 152 1.4 christos while (!current_association_ID); 153 1.6 christos initial_association_ID = current_association_ID; 154 1.1 kardel } 155 1.1 kardel 156 1.1 kardel 157 1.1 kardel /* 158 1.1 kardel * getmorepeermem - add more peer structures to the free list 159 1.1 kardel */ 160 1.1 kardel static void 161 1.1 kardel getmorepeermem(void) 162 1.1 kardel { 163 1.4 christos int i; 164 1.4 christos struct peer *peers; 165 1.1 kardel 166 1.11 christos peers = eallocarray(INC_PEER_ALLOC, sizeof(*peers)); 167 1.4 christos 168 1.4 christos for (i = INC_PEER_ALLOC - 1; i >= 0; i--) 169 1.4 christos LINK_SLIST(peer_free, &peers[i], p_link); 170 1.1 kardel 171 1.1 kardel total_peer_structs += INC_PEER_ALLOC; 172 1.1 kardel peer_free_count += INC_PEER_ALLOC; 173 1.1 kardel } 174 1.1 kardel 175 1.1 kardel 176 1.4 christos static struct peer * 177 1.4 christos findexistingpeer_name( 178 1.4 christos const char * hostname, 179 1.4 christos u_short hname_fam, 180 1.4 christos struct peer * start_peer, 181 1.4 christos int mode 182 1.4 christos ) 183 1.4 christos { 184 1.4 christos struct peer *p; 185 1.4 christos 186 1.4 christos if (NULL == start_peer) 187 1.4 christos p = peer_list; 188 1.4 christos else 189 1.4 christos p = start_peer->p_link; 190 1.4 christos for (; p != NULL; p = p->p_link) 191 1.4 christos if (p->hostname != NULL 192 1.4 christos && (-1 == mode || p->hmode == mode) 193 1.4 christos && (AF_UNSPEC == hname_fam 194 1.4 christos || AF_UNSPEC == AF(&p->srcadr) 195 1.4 christos || hname_fam == AF(&p->srcadr)) 196 1.4 christos && !strcasecmp(p->hostname, hostname)) 197 1.4 christos break; 198 1.4 christos return p; 199 1.4 christos } 200 1.4 christos 201 1.4 christos 202 1.4 christos static 203 1.4 christos struct peer * 204 1.4 christos findexistingpeer_addr( 205 1.3 kardel sockaddr_u * addr, 206 1.3 kardel struct peer * start_peer, 207 1.3 kardel int mode, 208 1.12 christos u_char cast_flags, 209 1.12 christos int * ip_count 210 1.1 kardel ) 211 1.1 kardel { 212 1.4 christos struct peer *peer; 213 1.4 christos 214 1.12 christos DPRINTF(2, ("findexistingpeer_addr(%s, %s, %d, 0x%x, %p)\n", 215 1.4 christos sptoa(addr), 216 1.4 christos (start_peer) 217 1.4 christos ? sptoa(&start_peer->srcadr) 218 1.4 christos : "NULL", 219 1.12 christos mode, (u_int)cast_flags, ip_count)); 220 1.1 kardel 221 1.1 kardel /* 222 1.1 kardel * start_peer is included so we can locate instances of the 223 1.1 kardel * same peer through different interfaces in the hash table. 224 1.3 kardel * Without MDF_BCLNT, a match requires the same mode and remote 225 1.3 kardel * address. MDF_BCLNT associations start out as MODE_CLIENT 226 1.3 kardel * if broadcastdelay is not specified, and switch to 227 1.3 kardel * MODE_BCLIENT after estimating the one-way delay. Duplicate 228 1.3 kardel * associations are expanded in definition to match any other 229 1.3 kardel * MDF_BCLNT with the same srcadr (remote, unicast address). 230 1.1 kardel */ 231 1.1 kardel if (NULL == start_peer) 232 1.1 kardel peer = peer_hash[NTP_HASH_ADDR(addr)]; 233 1.1 kardel else 234 1.4 christos peer = start_peer->adr_link; 235 1.1 kardel 236 1.1 kardel while (peer != NULL) { 237 1.4 christos DPRINTF(3, ("%s %s %d %d 0x%x 0x%x ", sptoa(addr), 238 1.4 christos sptoa(&peer->srcadr), mode, peer->hmode, 239 1.4 christos (u_int)cast_flags, (u_int)peer->cast_flags)); 240 1.12 christos if (ip_count) { 241 1.12 christos if (SOCK_EQ(addr, &peer->srcadr)) { 242 1.12 christos (*ip_count)++; 243 1.12 christos } 244 1.12 christos } 245 1.4 christos if ((-1 == mode || peer->hmode == mode || 246 1.4 christos ((MDF_BCLNT & peer->cast_flags) && 247 1.4 christos (MDF_BCLNT & cast_flags))) && 248 1.4 christos ADDR_PORT_EQ(addr, &peer->srcadr)) { 249 1.4 christos DPRINTF(3, ("found.\n")); 250 1.1 kardel break; 251 1.4 christos } 252 1.4 christos DPRINTF(3, ("\n")); 253 1.4 christos peer = peer->adr_link; 254 1.1 kardel } 255 1.3 kardel 256 1.3 kardel return peer; 257 1.1 kardel } 258 1.1 kardel 259 1.1 kardel 260 1.1 kardel /* 261 1.14 christos * findexistingpeer - search by name+family or address. 262 1.4 christos */ 263 1.4 christos struct peer * 264 1.4 christos findexistingpeer( 265 1.4 christos sockaddr_u * addr, 266 1.4 christos const char * hostname, 267 1.4 christos struct peer * start_peer, 268 1.4 christos int mode, 269 1.12 christos u_char cast_flags, 270 1.12 christos int * ip_count 271 1.4 christos ) 272 1.4 christos { 273 1.4 christos if (hostname != NULL) 274 1.4 christos return findexistingpeer_name(hostname, AF(addr), 275 1.4 christos start_peer, mode); 276 1.4 christos else 277 1.4 christos return findexistingpeer_addr(addr, start_peer, mode, 278 1.12 christos cast_flags, ip_count); 279 1.4 christos } 280 1.4 christos 281 1.4 christos 282 1.4 christos /* 283 1.3 kardel * findpeer - find and return a peer match for a received datagram in 284 1.3 kardel * the peer_hash table. 285 1.10 christos * 286 1.10 christos * [Bug 3072] To faciliate a faster reorganisation after routing changes 287 1.10 christos * the original code re-assigned the peer address to be the destination 288 1.10 christos * of the received packet and initiated another round on a mismatch. 289 1.10 christos * Unfortunately this leaves us wide open for a DoS attack where the 290 1.10 christos * attacker directs a packet with forged destination address to us -- 291 1.10 christos * this results in a wrong interface assignment, actually creating a DoS 292 1.10 christos * situation. 293 1.10 christos * 294 1.10 christos * This condition would persist until the next update of the interface 295 1.10 christos * list, but a continued attack would put us out of business again soon 296 1.10 christos * enough. Authentication alone does not help here, since it does not 297 1.10 christos * protect the UDP layer and leaves us open for a replay attack. 298 1.10 christos * 299 1.14 christos * So we do not update the addresses and wait until the next interface 300 1.10 christos * list update does the right thing for us. 301 1.1 kardel */ 302 1.1 kardel struct peer * 303 1.1 kardel findpeer( 304 1.3 kardel struct recvbuf *rbufp, 305 1.3 kardel int pkt_mode, 306 1.3 kardel int * action 307 1.1 kardel ) 308 1.1 kardel { 309 1.3 kardel struct peer * p; 310 1.3 kardel sockaddr_u * srcadr; 311 1.3 kardel u_int hash; 312 1.3 kardel struct pkt * pkt; 313 1.3 kardel l_fp pkt_org; 314 1.1 kardel 315 1.1 kardel findpeer_calls++; 316 1.3 kardel srcadr = &rbufp->recv_srcadr; 317 1.1 kardel hash = NTP_HASH_ADDR(srcadr); 318 1.4 christos for (p = peer_hash[hash]; p != NULL; p = p->adr_link) { 319 1.1 kardel 320 1.10 christos /* [Bug 3072] ensure interface of peer matches */ 321 1.11 christos /* [Bug 3356] ... if NOT a broadcast peer! */ 322 1.11 christos if (p->hmode != MODE_BCLIENT && p->dstadr != rbufp->dstadr) 323 1.10 christos continue; 324 1.10 christos 325 1.10 christos /* ensure peer source address matches */ 326 1.10 christos if ( ! ADDR_PORT_EQ(srcadr, &p->srcadr)) 327 1.10 christos continue; 328 1.10 christos 329 1.10 christos /* If the association matching rules determine that this 330 1.10 christos * is not a valid combination, then look for the next 331 1.10 christos * valid peer association. 332 1.10 christos */ 333 1.10 christos *action = MATCH_ASSOC(p->hmode, pkt_mode); 334 1.3 kardel 335 1.10 christos /* A response to our manycastclient solicitation might 336 1.10 christos * be misassociated with an ephemeral peer already spun 337 1.10 christos * for the server. If the packet's org timestamp 338 1.10 christos * doesn't match the peer's, check if it matches the 339 1.10 christos * ACST prototype peer's. If so it is a redundant 340 1.10 christos * solicitation response, return AM_ERR to discard it. 341 1.10 christos * [Bug 1762] 342 1.10 christos */ 343 1.10 christos if (MODE_SERVER == pkt_mode && AM_PROCPKT == *action) { 344 1.10 christos pkt = &rbufp->recv_pkt; 345 1.10 christos NTOHL_FP(&pkt->org, &pkt_org); 346 1.10 christos if (!L_ISEQU(&p->aorg, &pkt_org) && 347 1.10 christos findmanycastpeer(rbufp)) 348 1.10 christos *action = AM_ERR; 349 1.10 christos } 350 1.1 kardel 351 1.10 christos /* if an error was returned, exit back right here. */ 352 1.14 christos if (*action == AM_ERR) { 353 1.10 christos return NULL; 354 1.14 christos } 355 1.1 kardel 356 1.10 christos /* if a match is found, we stop our search. */ 357 1.14 christos if (*action != AM_NOMATCH) { 358 1.10 christos break; 359 1.14 christos } 360 1.1 kardel } 361 1.1 kardel 362 1.10 christos /* If no matching association is found... */ 363 1.14 christos if (NULL == p) { 364 1.1 kardel *action = MATCH_ASSOC(NO_PEER, pkt_mode); 365 1.14 christos } 366 1.3 kardel return p; 367 1.1 kardel } 368 1.1 kardel 369 1.1 kardel /* 370 1.4 christos * findpeerbyassoc - find and return a peer using his association ID 371 1.1 kardel */ 372 1.1 kardel struct peer * 373 1.1 kardel findpeerbyassoc( 374 1.4 christos associd_t assoc 375 1.1 kardel ) 376 1.1 kardel { 377 1.3 kardel struct peer *p; 378 1.1 kardel u_int hash; 379 1.1 kardel 380 1.1 kardel assocpeer_calls++; 381 1.1 kardel hash = assoc & NTP_HASH_MASK; 382 1.4 christos for (p = assoc_hash[hash]; p != NULL; p = p->aid_link) 383 1.3 kardel if (assoc == p->associd) 384 1.4 christos break; 385 1.4 christos return p; 386 1.1 kardel } 387 1.1 kardel 388 1.1 kardel 389 1.1 kardel /* 390 1.1 kardel * clear_all - flush all time values for all associations 391 1.1 kardel */ 392 1.1 kardel void 393 1.1 kardel clear_all(void) 394 1.1 kardel { 395 1.4 christos struct peer *p; 396 1.1 kardel 397 1.1 kardel /* 398 1.1 kardel * This routine is called when the clock is stepped, and so all 399 1.1 kardel * previously saved time values are untrusted. 400 1.1 kardel */ 401 1.4 christos for (p = peer_list; p != NULL; p = p->p_link) 402 1.4 christos if (!(MDF_TXONLY_MASK & p->cast_flags)) 403 1.4 christos peer_clear(p, "STEP"); 404 1.4 christos 405 1.4 christos DPRINTF(1, ("clear_all: at %lu\n", current_time)); 406 1.1 kardel } 407 1.1 kardel 408 1.1 kardel 409 1.1 kardel /* 410 1.1 kardel * score_all() - determine if an association can be demobilized 411 1.1 kardel */ 412 1.1 kardel int 413 1.1 kardel score_all( 414 1.1 kardel struct peer *peer /* peer structure pointer */ 415 1.1 kardel ) 416 1.1 kardel { 417 1.4 christos struct peer *speer; 418 1.1 kardel int temp, tamp; 419 1.4 christos int x; 420 1.1 kardel 421 1.1 kardel /* 422 1.4 christos * This routine finds the minimum score for all preemptible 423 1.4 christos * associations and returns > 0 if the association can be 424 1.1 kardel * demobilized. 425 1.1 kardel */ 426 1.1 kardel tamp = score(peer); 427 1.1 kardel temp = 100; 428 1.4 christos for (speer = peer_list; speer != NULL; speer = speer->p_link) 429 1.4 christos if (speer->flags & FLAG_PREEMPT) { 430 1.4 christos x = score(speer); 431 1.4 christos if (x < temp) 432 1.1 kardel temp = x; 433 1.1 kardel } 434 1.4 christos DPRINTF(1, ("score_all: at %lu score %d min %d\n", 435 1.4 christos current_time, tamp, temp)); 436 1.4 christos 437 1.1 kardel if (tamp != temp) 438 1.1 kardel temp = 0; 439 1.4 christos 440 1.4 christos return temp; 441 1.1 kardel } 442 1.1 kardel 443 1.1 kardel 444 1.1 kardel /* 445 1.1 kardel * score() - calculate preemption score 446 1.1 kardel */ 447 1.1 kardel static int 448 1.1 kardel score( 449 1.1 kardel struct peer *peer /* peer structure pointer */ 450 1.1 kardel ) 451 1.1 kardel { 452 1.1 kardel int temp; 453 1.1 kardel 454 1.1 kardel /* 455 1.1 kardel * This routine calculates the premption score from the peer 456 1.1 kardel * error bits and status. Increasing values are more cherished. 457 1.1 kardel */ 458 1.1 kardel temp = 0; 459 1.1 kardel if (!(peer->flash & TEST10)) 460 1.1 kardel temp++; /* 1 good synch and stratum */ 461 1.1 kardel if (!(peer->flash & TEST13)) 462 1.1 kardel temp++; /* 2 reachable */ 463 1.1 kardel if (!(peer->flash & TEST12)) 464 1.1 kardel temp++; /* 3 no loop */ 465 1.1 kardel if (!(peer->flash & TEST11)) 466 1.1 kardel temp++; /* 4 good distance */ 467 1.1 kardel if (peer->status >= CTL_PST_SEL_SELCAND) 468 1.1 kardel temp++; /* 5 in the hunt */ 469 1.1 kardel if (peer->status != CTL_PST_SEL_EXCESS) 470 1.1 kardel temp++; /* 6 not spare tire */ 471 1.1 kardel return (temp); /* selection status */ 472 1.1 kardel } 473 1.1 kardel 474 1.1 kardel 475 1.1 kardel /* 476 1.4 christos * free_peer - internal routine to free memory referred to by a struct 477 1.4 christos * peer and return it to the peer free list. If unlink is 478 1.4 christos * nonzero, unlink from the various lists. 479 1.4 christos */ 480 1.4 christos static void 481 1.4 christos free_peer( 482 1.4 christos struct peer * p, 483 1.4 christos int unlink_peer 484 1.4 christos ) 485 1.4 christos { 486 1.4 christos struct peer * unlinked; 487 1.4 christos int hash; 488 1.4 christos 489 1.4 christos if (unlink_peer) { 490 1.4 christos hash = NTP_HASH_ADDR(&p->srcadr); 491 1.4 christos peer_hash_count[hash]--; 492 1.4 christos 493 1.4 christos UNLINK_SLIST(unlinked, peer_hash[hash], p, adr_link, 494 1.4 christos struct peer); 495 1.4 christos if (NULL == unlinked) { 496 1.4 christos peer_hash_count[hash]++; 497 1.4 christos msyslog(LOG_ERR, "peer %s not in address table!", 498 1.4 christos stoa(&p->srcadr)); 499 1.4 christos } 500 1.4 christos 501 1.4 christos /* 502 1.4 christos * Remove him from the association hash as well. 503 1.4 christos */ 504 1.4 christos hash = p->associd & NTP_HASH_MASK; 505 1.4 christos assoc_hash_count[hash]--; 506 1.4 christos 507 1.4 christos UNLINK_SLIST(unlinked, assoc_hash[hash], p, aid_link, 508 1.4 christos struct peer); 509 1.4 christos if (NULL == unlinked) { 510 1.4 christos assoc_hash_count[hash]++; 511 1.4 christos msyslog(LOG_ERR, 512 1.4 christos "peer %s not in association ID table!", 513 1.4 christos stoa(&p->srcadr)); 514 1.4 christos } 515 1.4 christos 516 1.4 christos /* Remove him from the overall list. */ 517 1.4 christos UNLINK_SLIST(unlinked, peer_list, p, p_link, 518 1.4 christos struct peer); 519 1.4 christos if (NULL == unlinked) 520 1.4 christos msyslog(LOG_ERR, "%s not in peer list!", 521 1.4 christos stoa(&p->srcadr)); 522 1.4 christos } 523 1.4 christos 524 1.4 christos if (p->hostname != NULL) 525 1.4 christos free(p->hostname); 526 1.4 christos 527 1.4 christos if (p->ident != NULL) 528 1.4 christos free(p->ident); 529 1.4 christos 530 1.4 christos if (p->addrs != NULL) 531 1.4 christos free(p->addrs); /* from copy_addrinfo_list() */ 532 1.4 christos 533 1.4 christos /* Add his corporeal form to peer free list */ 534 1.4 christos ZERO(*p); 535 1.4 christos LINK_SLIST(peer_free, p, p_link); 536 1.4 christos peer_free_count++; 537 1.4 christos } 538 1.4 christos 539 1.4 christos 540 1.4 christos /* 541 1.1 kardel * unpeer - remove peer structure from hash table and free structure 542 1.1 kardel */ 543 1.1 kardel void 544 1.1 kardel unpeer( 545 1.4 christos struct peer *peer 546 1.1 kardel ) 547 1.1 kardel { 548 1.4 christos mprintf_event(PEVNT_DEMOBIL, peer, "assoc %u", peer->associd); 549 1.14 christos restrict_source(&peer->srcadr, TRUE, 0); 550 1.14 christos peer->flags |= FLAG_DISABLED; 551 1.4 christos set_peerdstadr(peer, NULL); 552 1.1 kardel peer_demobilizations++; 553 1.1 kardel peer_associations--; 554 1.4 christos if (FLAG_PREEMPT & peer->flags) 555 1.1 kardel peer_preempt--; 556 1.1 kardel #ifdef REFCLOCK 557 1.1 kardel /* 558 1.1 kardel * If this peer is actually a clock, shut it down first 559 1.1 kardel */ 560 1.4 christos if (FLAG_REFCLOCK & peer->flags) 561 1.4 christos refclock_unpeer(peer); 562 1.1 kardel #endif 563 1.1 kardel 564 1.4 christos free_peer(peer, TRUE); 565 1.1 kardel } 566 1.1 kardel 567 1.1 kardel 568 1.1 kardel /* 569 1.1 kardel * peer_config - configure a new association 570 1.1 kardel */ 571 1.1 kardel struct peer * 572 1.1 kardel peer_config( 573 1.4 christos sockaddr_u * srcadr, 574 1.4 christos const char * hostname, 575 1.4 christos endpt * dstadr, 576 1.12 christos int ippeerlimit, 577 1.4 christos u_char hmode, 578 1.4 christos u_char version, 579 1.4 christos u_char minpoll, 580 1.4 christos u_char maxpoll, 581 1.4 christos u_int flags, 582 1.4 christos u_int32 ttl, 583 1.4 christos keyid_t key, 584 1.4 christos const char * ident /* autokey group */ 585 1.1 kardel ) 586 1.1 kardel { 587 1.1 kardel u_char cast_flags; 588 1.1 kardel 589 1.1 kardel /* 590 1.1 kardel * We do a dirty little jig to figure the cast flags. This is 591 1.1 kardel * probably not the best place to do this, at least until the 592 1.1 kardel * configure code is rebuilt. Note only one flag can be set. 593 1.1 kardel */ 594 1.1 kardel switch (hmode) { 595 1.1 kardel case MODE_BROADCAST: 596 1.1 kardel if (IS_MCAST(srcadr)) 597 1.1 kardel cast_flags = MDF_MCAST; 598 1.1 kardel else 599 1.1 kardel cast_flags = MDF_BCAST; 600 1.1 kardel break; 601 1.1 kardel 602 1.1 kardel case MODE_CLIENT: 603 1.4 christos if (hostname != NULL && SOCK_UNSPEC(srcadr)) 604 1.4 christos cast_flags = MDF_POOL; 605 1.4 christos else if (IS_MCAST(srcadr)) 606 1.1 kardel cast_flags = MDF_ACAST; 607 1.1 kardel else 608 1.1 kardel cast_flags = MDF_UCAST; 609 1.1 kardel break; 610 1.1 kardel 611 1.1 kardel default: 612 1.1 kardel cast_flags = MDF_UCAST; 613 1.1 kardel } 614 1.1 kardel 615 1.1 kardel /* 616 1.1 kardel * Mobilize the association and initialize its variables. If 617 1.4 christos * emulating ntpdate, force iburst. For pool and manycastclient 618 1.4 christos * strip FLAG_PREEMPT as the prototype associations are not 619 1.4 christos * themselves preemptible, though the resulting associations 620 1.4 christos * are. 621 1.1 kardel */ 622 1.4 christos flags |= FLAG_CONFIG; 623 1.1 kardel if (mode_ntpdate) 624 1.1 kardel flags |= FLAG_IBURST; 625 1.4 christos if ((MDF_ACAST | MDF_POOL) & cast_flags) 626 1.4 christos flags &= ~FLAG_PREEMPT; 627 1.12 christos return newpeer(srcadr, hostname, dstadr, ippeerlimit, hmode, version, 628 1.4 christos minpoll, maxpoll, flags, cast_flags, ttl, key, ident); 629 1.1 kardel } 630 1.1 kardel 631 1.1 kardel /* 632 1.1 kardel * setup peer dstadr field keeping it in sync with the interface 633 1.1 kardel * structures 634 1.1 kardel */ 635 1.1 kardel void 636 1.1 kardel set_peerdstadr( 637 1.3 kardel struct peer * p, 638 1.3 kardel endpt * dstadr 639 1.1 kardel ) 640 1.1 kardel { 641 1.3 kardel struct peer * unlinked; 642 1.1 kardel 643 1.10 christos DEBUG_INSIST(p != NULL); 644 1.10 christos 645 1.10 christos if (p == NULL) 646 1.10 christos return; 647 1.10 christos 648 1.10 christos /* check for impossible or identical assignment */ 649 1.3 kardel if (p->dstadr == dstadr) 650 1.3 kardel return; 651 1.1 kardel 652 1.3 kardel /* 653 1.14 christos * Do not change the local address of a link-local 654 1.14 christos * peer address. 655 1.14 christos */ 656 1.14 christos if ( p->dstadr != NULL && is_linklocal(&p->dstadr->sin) 657 1.14 christos && dstadr != NULL) { 658 1.14 christos return; 659 1.14 christos } 660 1.14 christos 661 1.14 christos /* 662 1.14 christos * Do not set the local address for a link-local IPv6 peer 663 1.14 christos * to one with a different scope ID. 664 1.14 christos */ 665 1.14 christos if ( dstadr != NULL && IS_IPV6(&p->srcadr) 666 1.14 christos && SCOPE(&dstadr->sin) != SCOPE(&p->srcadr)) { 667 1.14 christos return; 668 1.14 christos } 669 1.14 christos 670 1.14 christos /* 671 1.3 kardel * Don't accept updates to a separate multicast receive-only 672 1.3 kardel * endpt while a BCLNT peer is running its unicast protocol. 673 1.3 kardel */ 674 1.3 kardel if (dstadr != NULL && (FLAG_BC_VOL & p->flags) && 675 1.3 kardel (INT_MCASTIF & dstadr->flags) && MODE_CLIENT == p->hmode) { 676 1.3 kardel return; 677 1.3 kardel } 678 1.10 christos 679 1.10 christos /* unlink from list if we have an address prior to assignment */ 680 1.3 kardel if (p->dstadr != NULL) { 681 1.3 kardel p->dstadr->peercnt--; 682 1.3 kardel UNLINK_SLIST(unlinked, p->dstadr->peers, p, ilink, 683 1.3 kardel struct peer); 684 1.14 christos } 685 1.14 christos if ( !IS_MCAST(&p->srcadr) && !(FLAG_DISABLED & p->flags) 686 1.14 christos && !initializing) { 687 1.4 christos msyslog(LOG_INFO, "%s local addr %s -> %s", 688 1.14 christos stoa(&p->srcadr), eptoa(p->dstadr), 689 1.14 christos eptoa(dstadr)); 690 1.3 kardel } 691 1.14 christos 692 1.3 kardel p->dstadr = dstadr; 693 1.10 christos 694 1.10 christos /* link to list if we have an address after assignment */ 695 1.10 christos if (p->dstadr != NULL) { 696 1.3 kardel LINK_SLIST(dstadr->peers, p, ilink); 697 1.3 kardel dstadr->peercnt++; 698 1.1 kardel } 699 1.1 kardel } 700 1.1 kardel 701 1.1 kardel /* 702 1.1 kardel * attempt to re-rebind interface if necessary 703 1.1 kardel */ 704 1.1 kardel static void 705 1.1 kardel peer_refresh_interface( 706 1.4 christos struct peer *p 707 1.1 kardel ) 708 1.1 kardel { 709 1.3 kardel endpt * niface; 710 1.3 kardel endpt * piface; 711 1.1 kardel 712 1.4 christos niface = select_peerinterface(p, &p->srcadr, NULL); 713 1.1 kardel 714 1.3 kardel DPRINTF(4, ( 715 1.4 christos "peer_refresh_interface: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %u key %08x: new interface: ", 716 1.4 christos p->dstadr == NULL ? "<null>" : 717 1.4 christos stoa(&p->dstadr->sin), stoa(&p->srcadr), p->hmode, 718 1.4 christos p->version, p->minpoll, p->maxpoll, p->flags, p->cast_flags, 719 1.4 christos p->ttl, p->keyid)); 720 1.3 kardel if (niface != NULL) { 721 1.3 kardel DPRINTF(4, ( 722 1.3 kardel "fd=%d, bfd=%d, name=%.16s, flags=0x%x, ifindex=%u, sin=%s", 723 1.3 kardel niface->fd, niface->bfd, niface->name, 724 1.3 kardel niface->flags, niface->ifindex, 725 1.3 kardel stoa(&niface->sin))); 726 1.3 kardel if (niface->flags & INT_BROADCAST) 727 1.3 kardel DPRINTF(4, (", bcast=%s", 728 1.3 kardel stoa(&niface->bcast))); 729 1.3 kardel DPRINTF(4, (", mask=%s\n", stoa(&niface->mask))); 730 1.3 kardel } else { 731 1.3 kardel DPRINTF(4, ("<NONE>\n")); 732 1.1 kardel } 733 1.1 kardel 734 1.4 christos piface = p->dstadr; 735 1.4 christos set_peerdstadr(p, niface); 736 1.4 christos if (p->dstadr != NULL) { 737 1.1 kardel /* 738 1.1 kardel * clear crypto if we change the local address 739 1.1 kardel */ 740 1.4 christos if (p->dstadr != piface && !(MDF_ACAST & p->cast_flags) 741 1.4 christos && MODE_BROADCAST != p->pmode) 742 1.4 christos peer_clear(p, "XFAC"); 743 1.1 kardel 744 1.1 kardel /* 745 1.1 kardel * Broadcast needs the socket enabled for broadcast 746 1.1 kardel */ 747 1.4 christos if (MDF_BCAST & p->cast_flags) 748 1.4 christos enable_broadcast(p->dstadr, &p->srcadr); 749 1.1 kardel 750 1.1 kardel /* 751 1.1 kardel * Multicast needs the socket interface enabled for 752 1.1 kardel * multicast 753 1.1 kardel */ 754 1.4 christos if (MDF_MCAST & p->cast_flags) 755 1.4 christos enable_multicast_if(p->dstadr, &p->srcadr); 756 1.1 kardel } 757 1.1 kardel } 758 1.1 kardel 759 1.4 christos 760 1.1 kardel /* 761 1.1 kardel * refresh_all_peerinterfaces - see that all interface bindings are up 762 1.1 kardel * to date 763 1.1 kardel */ 764 1.1 kardel void 765 1.1 kardel refresh_all_peerinterfaces(void) 766 1.1 kardel { 767 1.4 christos struct peer *p; 768 1.1 kardel 769 1.1 kardel /* 770 1.14 christos * This is called when the interface list has changed. 771 1.14 christos * Give peers a chance to find a better interface. 772 1.1 kardel */ 773 1.8 christos for (p = peer_list; p != NULL; p = p->p_link) { 774 1.14 christos /* 775 1.14 christos * Bug 2849 XOR 2043 776 1.14 christos * Change local address only if the peer doesn't 777 1.14 christos * have a local address already or if the one 778 1.14 christos * they have hasn't worked for a while. 779 1.14 christos */ 780 1.14 christos if (p->dstadr != NULL && (p->reach & 0x3)) { 781 1.14 christos continue; 782 1.14 christos } 783 1.14 christos peer_refresh_interface(p); 784 1.8 christos } 785 1.1 kardel } 786 1.1 kardel 787 1.1 kardel 788 1.1 kardel /* 789 1.1 kardel * newpeer - initialize a new peer association 790 1.1 kardel */ 791 1.1 kardel struct peer * 792 1.1 kardel newpeer( 793 1.4 christos sockaddr_u * srcadr, 794 1.4 christos const char * hostname, 795 1.4 christos endpt * dstadr, 796 1.12 christos int ippeerlimit, 797 1.4 christos u_char hmode, 798 1.4 christos u_char version, 799 1.4 christos u_char minpoll, 800 1.4 christos u_char maxpoll, 801 1.4 christos u_int flags, 802 1.4 christos u_char cast_flags, 803 1.4 christos u_int32 ttl, 804 1.4 christos keyid_t key, 805 1.4 christos const char * ident 806 1.1 kardel ) 807 1.1 kardel { 808 1.4 christos struct peer * peer; 809 1.4 christos u_int hash; 810 1.12 christos int ip_count = 0; 811 1.12 christos 812 1.8 christos DEBUG_REQUIRE(srcadr); 813 1.8 christos 814 1.4 christos #ifdef AUTOKEY 815 1.1 kardel /* 816 1.1 kardel * If Autokey is requested but not configured, complain loudly. 817 1.1 kardel */ 818 1.1 kardel if (!crypto_flags) { 819 1.1 kardel if (key > NTP_MAXKEY) { 820 1.1 kardel return (NULL); 821 1.1 kardel 822 1.1 kardel } else if (flags & FLAG_SKEY) { 823 1.14 christos msyslog(LOG_ERR, "Rejecting Autokey with %s," 824 1.14 christos " built without support.", 825 1.14 christos stoa(srcadr)); 826 1.1 kardel return (NULL); 827 1.1 kardel } 828 1.1 kardel } 829 1.4 christos #endif /* AUTOKEY */ 830 1.4 christos 831 1.4 christos /* 832 1.4 christos * For now only pool associations have a hostname. 833 1.4 christos */ 834 1.8 christos INSIST(NULL == hostname || (MDF_POOL & cast_flags)); 835 1.1 kardel 836 1.1 kardel /* 837 1.1 kardel * First search from the beginning for an association with given 838 1.1 kardel * remote address and mode. If an interface is given, search 839 1.1 kardel * from there to find the association which matches that 840 1.1 kardel * destination. If the given interface is "any", track down the 841 1.1 kardel * actual interface, because that's what gets put into the peer 842 1.1 kardel * structure. 843 1.1 kardel */ 844 1.1 kardel if (dstadr != NULL) { 845 1.4 christos peer = findexistingpeer(srcadr, hostname, NULL, hmode, 846 1.12 christos cast_flags, &ip_count); 847 1.1 kardel while (peer != NULL) { 848 1.12 christos if ( peer->dstadr == dstadr 849 1.12 christos || ( (MDF_BCLNT & cast_flags) 850 1.12 christos && (MDF_BCLNT & peer->cast_flags))) 851 1.1 kardel break; 852 1.1 kardel 853 1.1 kardel if (dstadr == ANY_INTERFACE_CHOOSE(srcadr) && 854 1.1 kardel peer->dstadr == findinterface(srcadr)) 855 1.1 kardel break; 856 1.1 kardel 857 1.4 christos peer = findexistingpeer(srcadr, hostname, peer, 858 1.12 christos hmode, cast_flags, &ip_count); 859 1.1 kardel } 860 1.3 kardel } else { 861 1.3 kardel /* no endpt address given */ 862 1.4 christos peer = findexistingpeer(srcadr, hostname, NULL, hmode, 863 1.12 christos cast_flags, &ip_count); 864 1.1 kardel } 865 1.1 kardel 866 1.1 kardel /* 867 1.14 christos * In any case, do not create an association with a duplicate 868 1.14 christos * remote address (srcadr) except for undefined (zero) address. 869 1.14 christos * Arguably this should be part of the logic above but 870 1.14 christos * [Bug 3888] exposed a situation with manycastclient where 871 1.14 christos * duplicate associations happened. 872 1.14 christos */ 873 1.14 christos if (NULL == peer) { 874 1.14 christos for (peer = peer_list; 875 1.14 christos peer != NULL; 876 1.14 christos peer = peer->p_link) { 877 1.14 christos if ( SOCK_EQ(srcadr, &peer->srcadr) 878 1.14 christos && !SOCK_UNSPEC(srcadr) 879 1.14 christos && !SOCK_UNSPEC(&peer->srcadr)) { 880 1.14 christos /* leave peer non-NULL */ 881 1.14 christos break; 882 1.14 christos } 883 1.14 christos } 884 1.14 christos } 885 1.14 christos 886 1.14 christos /* 887 1.1 kardel * If a peer is found, this would be a duplicate and we don't 888 1.3 kardel * allow that. This avoids duplicate ephemeral (broadcast/ 889 1.3 kardel * multicast) and preemptible (manycast and pool) client 890 1.1 kardel * associations. 891 1.1 kardel */ 892 1.4 christos if (peer != NULL) { 893 1.14 christos DPRINTF(2, ("%s(%s) found existing association\n", 894 1.14 christos __func__, 895 1.4 christos (hostname) 896 1.4 christos ? hostname 897 1.4 christos : stoa(srcadr))); 898 1.4 christos return NULL; 899 1.4 christos } 900 1.1 kardel 901 1.13 christos #if 0 902 1.14 christos DPRINTF(1, ("newpeer(%s) found no existing and %d other associations\n", 903 1.12 christos (hostname) 904 1.12 christos ? hostname 905 1.12 christos : stoa(srcadr), 906 1.12 christos ip_count)); 907 1.13 christos #endif 908 1.12 christos 909 1.12 christos /* Check ippeerlimit wrt ip_count */ 910 1.12 christos if (ippeerlimit > -1) { 911 1.12 christos if (ip_count + 1 > ippeerlimit) { 912 1.12 christos DPRINTF(2, ("newpeer(%s) denied - ippeerlimit %d\n", 913 1.12 christos (hostname) 914 1.12 christos ? hostname 915 1.12 christos : stoa(srcadr), 916 1.12 christos ippeerlimit)); 917 1.12 christos return NULL; 918 1.12 christos } 919 1.12 christos } else { 920 1.12 christos DPRINTF(1, ("newpeer(%s) - ippeerlimit %d ignored\n", 921 1.12 christos (hostname) 922 1.12 christos ? hostname 923 1.12 christos : stoa(srcadr), 924 1.12 christos ippeerlimit)); 925 1.12 christos } 926 1.12 christos 927 1.1 kardel /* 928 1.1 kardel * Allocate a new peer structure. Some dirt here, since some of 929 1.1 kardel * the initialization requires knowlege of our system state. 930 1.1 kardel */ 931 1.1 kardel if (peer_free_count == 0) 932 1.1 kardel getmorepeermem(); 933 1.4 christos UNLINK_HEAD_SLIST(peer, peer_free, p_link); 934 1.8 christos INSIST(peer != NULL); 935 1.1 kardel peer_free_count--; 936 1.1 kardel peer_associations++; 937 1.4 christos if (FLAG_PREEMPT & flags) 938 1.1 kardel peer_preempt++; 939 1.1 kardel 940 1.1 kardel /* 941 1.14 christos * Assign an available association ID. Zero is reserved. 942 1.1 kardel */ 943 1.14 christos do { 944 1.14 christos while (0 == ++current_association_ID) { 945 1.14 christos /* EMPTY */ 946 1.14 christos } 947 1.14 christos } while (NULL != findpeerbyassoc(current_association_ID)); 948 1.1 kardel peer->associd = current_association_ID; 949 1.1 kardel 950 1.1 kardel peer->srcadr = *srcadr; 951 1.14 christos if (hostname != NULL) { 952 1.4 christos peer->hostname = estrdup(hostname); 953 1.14 christos } 954 1.4 christos peer->hmode = hmode; 955 1.4 christos peer->version = version; 956 1.1 kardel peer->flags = flags; 957 1.4 christos peer->cast_flags = cast_flags; 958 1.4 christos set_peerdstadr(peer, 959 1.4 christos select_peerinterface(peer, srcadr, dstadr)); 960 1.1 kardel 961 1.1 kardel /* 962 1.14 christos * Zero for minpoll or maxpoll means use defaults. 963 1.1 kardel */ 964 1.14 christos peer->maxpoll = (0 == maxpoll) 965 1.14 christos ? NTP_MAXDPOLL 966 1.14 christos : maxpoll; 967 1.14 christos peer->minpoll = (0 == minpoll) 968 1.14 christos ? NTP_MINDPOLL 969 1.14 christos : minpoll; 970 1.14 christos 971 1.14 christos /* 972 1.14 christos * Clamp maxpoll and minpoll within NTP_MINPOLL and NTP_MAXPOLL, 973 1.14 christos * and further clamp minpoll less than or equal maxpoll. 974 1.14 christos */ 975 1.14 christos peer->maxpoll = CLAMP(peer->maxpoll, NTP_MINPOLL, NTP_MAXPOLL); 976 1.14 christos peer->minpoll = CLAMP(peer->minpoll, NTP_MINPOLL, peer->maxpoll); 977 1.1 kardel 978 1.14 christos if (peer->dstadr != NULL) { 979 1.4 christos DPRINTF(3, ("newpeer(%s): using fd %d and our addr %s\n", 980 1.4 christos stoa(srcadr), peer->dstadr->fd, 981 1.4 christos stoa(&peer->dstadr->sin))); 982 1.14 christos } else { 983 1.14 christos DPRINTF(3, ("newpeer(%s): local addr unavailable\n", 984 1.4 christos stoa(srcadr))); 985 1.14 christos } 986 1.1 kardel /* 987 1.1 kardel * Broadcast needs the socket enabled for broadcast 988 1.1 kardel */ 989 1.14 christos if ((MDF_BCAST & cast_flags) && peer->dstadr != NULL) { 990 1.1 kardel enable_broadcast(peer->dstadr, srcadr); 991 1.14 christos } 992 1.1 kardel /* 993 1.1 kardel * Multicast needs the socket interface enabled for multicast 994 1.1 kardel */ 995 1.14 christos if ((MDF_MCAST & cast_flags) && peer->dstadr != NULL) { 996 1.1 kardel enable_multicast_if(peer->dstadr, srcadr); 997 1.14 christos } 998 1.4 christos #ifdef AUTOKEY 999 1.1 kardel if (key > NTP_MAXKEY) 1000 1.1 kardel peer->flags |= FLAG_SKEY; 1001 1.4 christos #endif /* AUTOKEY */ 1002 1.4 christos peer->ttl = ttl; 1003 1.1 kardel peer->keyid = key; 1004 1.14 christos if (ident != NULL) { 1005 1.4 christos peer->ident = estrdup(ident); 1006 1.14 christos } 1007 1.1 kardel peer->precision = sys_precision; 1008 1.1 kardel peer->hpoll = peer->minpoll; 1009 1.14 christos if (cast_flags & MDF_ACAST) { 1010 1.1 kardel peer_clear(peer, "ACST"); 1011 1.14 christos } else if (cast_flags & MDF_POOL) { 1012 1.4 christos peer_clear(peer, "POOL"); 1013 1.14 christos } else if (cast_flags & MDF_MCAST) { 1014 1.1 kardel peer_clear(peer, "MCST"); 1015 1.14 christos } else if (cast_flags & MDF_BCAST) { 1016 1.1 kardel peer_clear(peer, "BCST"); 1017 1.14 christos } else { 1018 1.1 kardel peer_clear(peer, "INIT"); 1019 1.14 christos } 1020 1.14 christos if (mode_ntpdate) { 1021 1.1 kardel peer_ntpdate++; 1022 1.14 christos } 1023 1.1 kardel /* 1024 1.1 kardel * Note time on statistics timers. 1025 1.1 kardel */ 1026 1.1 kardel peer->timereset = current_time; 1027 1.1 kardel peer->timereachable = current_time; 1028 1.1 kardel peer->timereceived = current_time; 1029 1.1 kardel 1030 1.4 christos if (ISREFCLOCKADR(&peer->srcadr)) { 1031 1.1 kardel #ifdef REFCLOCK 1032 1.1 kardel /* 1033 1.1 kardel * We let the reference clock support do clock 1034 1.1 kardel * dependent initialization. This includes setting 1035 1.1 kardel * the peer timer, since the clock may have requirements 1036 1.1 kardel * for this. 1037 1.1 kardel */ 1038 1.1 kardel if (!refclock_newpeer(peer)) { 1039 1.1 kardel /* 1040 1.1 kardel * Dump it, something screwed up 1041 1.1 kardel */ 1042 1.1 kardel set_peerdstadr(peer, NULL); 1043 1.4 christos free_peer(peer, 0); 1044 1.4 christos return NULL; 1045 1.1 kardel } 1046 1.4 christos #else /* REFCLOCK */ 1047 1.4 christos msyslog(LOG_ERR, "refclock %s isn't supported. ntpd was compiled without refclock support.", 1048 1.4 christos stoa(&peer->srcadr)); 1049 1.4 christos set_peerdstadr(peer, NULL); 1050 1.4 christos free_peer(peer, 0); 1051 1.4 christos return NULL; 1052 1.4 christos #endif /* REFCLOCK */ 1053 1.1 kardel } 1054 1.1 kardel 1055 1.1 kardel /* 1056 1.1 kardel * Put the new peer in the hash tables. 1057 1.1 kardel */ 1058 1.1 kardel hash = NTP_HASH_ADDR(&peer->srcadr); 1059 1.4 christos LINK_SLIST(peer_hash[hash], peer, adr_link); 1060 1.1 kardel peer_hash_count[hash]++; 1061 1.1 kardel hash = peer->associd & NTP_HASH_MASK; 1062 1.4 christos LINK_SLIST(assoc_hash[hash], peer, aid_link); 1063 1.1 kardel assoc_hash_count[hash]++; 1064 1.4 christos LINK_SLIST(peer_list, peer, p_link); 1065 1.4 christos 1066 1.14 christos restrict_source(&peer->srcadr, FALSE, 0); 1067 1.4 christos mprintf_event(PEVNT_MOBIL, peer, "assoc %d", peer->associd); 1068 1.4 christos DPRINTF(1, ("newpeer: %s->%s mode %u vers %u poll %u %u flags 0x%x 0x%x ttl %u key %08x\n", 1069 1.4 christos latoa(peer->dstadr), stoa(&peer->srcadr), peer->hmode, 1070 1.4 christos peer->version, peer->minpoll, peer->maxpoll, peer->flags, 1071 1.4 christos peer->cast_flags, peer->ttl, peer->keyid)); 1072 1.4 christos return peer; 1073 1.1 kardel } 1074 1.1 kardel 1075 1.1 kardel 1076 1.1 kardel /* 1077 1.4 christos * peer_clr_stats - clear peer module statistics counters 1078 1.1 kardel */ 1079 1.1 kardel void 1080 1.1 kardel peer_clr_stats(void) 1081 1.1 kardel { 1082 1.1 kardel findpeer_calls = 0; 1083 1.1 kardel assocpeer_calls = 0; 1084 1.1 kardel peer_allocations = 0; 1085 1.1 kardel peer_demobilizations = 0; 1086 1.1 kardel peer_timereset = current_time; 1087 1.1 kardel } 1088 1.1 kardel 1089 1.4 christos 1090 1.1 kardel /* 1091 1.1 kardel * peer_reset - reset statistics counters 1092 1.1 kardel */ 1093 1.1 kardel void 1094 1.1 kardel peer_reset( 1095 1.1 kardel struct peer *peer 1096 1.1 kardel ) 1097 1.1 kardel { 1098 1.1 kardel if (peer == NULL) 1099 1.3 kardel return; 1100 1.1 kardel 1101 1.1 kardel peer->timereset = current_time; 1102 1.1 kardel peer->sent = 0; 1103 1.1 kardel peer->received = 0; 1104 1.1 kardel peer->processed = 0; 1105 1.1 kardel peer->badauth = 0; 1106 1.1 kardel peer->bogusorg = 0; 1107 1.1 kardel peer->oldpkt = 0; 1108 1.1 kardel peer->seldisptoolarge = 0; 1109 1.1 kardel peer->selbroken = 0; 1110 1.1 kardel } 1111 1.1 kardel 1112 1.1 kardel 1113 1.1 kardel /* 1114 1.1 kardel * peer_all_reset - reset all peer statistics counters 1115 1.1 kardel */ 1116 1.1 kardel void 1117 1.1 kardel peer_all_reset(void) 1118 1.1 kardel { 1119 1.1 kardel struct peer *peer; 1120 1.1 kardel 1121 1.4 christos for (peer = peer_list; peer != NULL; peer = peer->p_link) 1122 1.1 kardel peer_reset(peer); 1123 1.1 kardel } 1124 1.1 kardel 1125 1.1 kardel 1126 1.1 kardel /* 1127 1.4 christos * findmanycastpeer - find and return a manycastclient or pool 1128 1.4 christos * association matching a received response. 1129 1.1 kardel */ 1130 1.1 kardel struct peer * 1131 1.1 kardel findmanycastpeer( 1132 1.1 kardel struct recvbuf *rbufp /* receive buffer pointer */ 1133 1.1 kardel ) 1134 1.1 kardel { 1135 1.4 christos struct peer *peer; 1136 1.1 kardel struct pkt *pkt; 1137 1.1 kardel l_fp p_org; 1138 1.1 kardel 1139 1.1 kardel /* 1140 1.4 christos * This routine is called upon arrival of a server-mode response 1141 1.4 christos * to a manycastclient multicast solicitation, or to a pool 1142 1.4 christos * server unicast solicitation. Search the peer list for a 1143 1.4 christos * manycastclient association where the last transmit timestamp 1144 1.4 christos * matches the response packet's originate timestamp. There can 1145 1.4 christos * be multiple manycastclient associations, or multiple pool 1146 1.4 christos * solicitation assocations, so this assumes the transmit 1147 1.4 christos * timestamps are unique for such. 1148 1.1 kardel */ 1149 1.1 kardel pkt = &rbufp->recv_pkt; 1150 1.4 christos for (peer = peer_list; peer != NULL; peer = peer->p_link) 1151 1.4 christos if (MDF_SOLICIT_MASK & peer->cast_flags) { 1152 1.4 christos NTOHL_FP(&pkt->org, &p_org); 1153 1.14 christos if (L_ISEQU(&p_org, &peer->aorg)) { 1154 1.4 christos break; 1155 1.14 christos } 1156 1.1 kardel } 1157 1.4 christos 1158 1.4 christos return peer; 1159 1.1 kardel } 1160 1.6 christos 1161 1.6 christos /* peer_cleanup - clean peer list prior to shutdown */ 1162 1.6 christos void peer_cleanup(void) 1163 1.6 christos { 1164 1.14 christos struct peer *peer; 1165 1.14 christos struct peer *nextpeer; 1166 1.6 christos 1167 1.14 christos for (peer = peer_list; peer != NULL; peer = nextpeer) { 1168 1.14 christos nextpeer = peer->p_link; 1169 1.14 christos unpeer(peer); 1170 1.14 christos } 1171 1.6 christos } 1172