1 /* 2 * ntp_restrict.c - determine host restrictions 3 */ 4 #ifdef HAVE_CONFIG_H 5 #include <config.h> 6 #endif 7 8 #include <stdio.h> 9 #include <sys/types.h> 10 11 #include "ntpd.h" 12 #include "ntp_if.h" 13 #include "ntp_stdlib.h" 14 15 /* 16 * This code keeps a simple address-and-mask list of hosts we want 17 * to place restrictions on (or remove them from). The restrictions 18 * are implemented as a set of flags which tell you what the host 19 * can't do. There is a subroutine entry to return the flags. The 20 * list is kept sorted to reduce the average number of comparisons 21 * and make sure you get the set of restrictions most specific to 22 * the address. 23 * 24 * The algorithm is that, when looking up a host, it is first assumed 25 * that the default set of restrictions will apply. It then searches 26 * down through the list. Whenever it finds a match it adopts the 27 * match's flags instead. When you hit the point where the sorted 28 * address is greater than the target, you return with the last set of 29 * flags you found. Because of the ordering of the list, the most 30 * specific match will provide the final set of flags. 31 * 32 * This was originally intended to restrict you from sync'ing to your 33 * own broadcasts when you are doing that, by restricting yourself from 34 * your own interfaces. It was also thought it would sometimes be useful 35 * to keep a misbehaving host or two from abusing your primary clock. It 36 * has been expanded, however, to suit the needs of those with more 37 * restrictive access policies. 38 */ 39 /* 40 * We will use two lists, one for IPv4 addresses and one for IPv6 41 * addresses. This is not protocol-independant but for now I can't 42 * find a way to respect this. We'll check this later... JFB 07/2001 43 */ 44 #define SET_IPV6_ADDR_MASK(dst, src, msk) \ 45 do { \ 46 int idx; \ 47 for (idx = 0; idx < 16; idx++) { \ 48 (dst)->s6_addr[idx] = \ 49 (u_char) ((src)->s6_addr[idx] & (msk)->s6_addr[idx]); \ 50 } \ 51 } while (0) 52 53 /* 54 * Memory allocation parameters. We allocate INITRESLIST entries 55 * initially, and add INCRESLIST entries to the free list whenever 56 * we run out. 57 */ 58 #define INITRESLIST 10 59 #define INCRESLIST 5 60 61 #define RES_AVG 8. /* interpacket averaging factor */ 62 63 /* 64 * The restriction list 65 */ 66 struct restrictlist *restrictlist; 67 struct restrictlist6 *restrictlist6; 68 static int restrictcount; /* count of entries in the res list */ 69 static int restrictcount6; /* count of entries in the res list 2*/ 70 71 /* 72 * The free list and associated counters. Also some uninteresting 73 * stat counters. 74 */ 75 static struct restrictlist *resfree; 76 static struct restrictlist6 *resfree6; 77 static int numresfree; /* number of structures on free list */ 78 static int numresfree6; /* number of structures on free list 2 */ 79 80 static u_long res_calls; 81 static u_long res_found; 82 static u_long res_not_found; 83 84 /* 85 * Parameters of the RES_LIMITED restriction option. 86 */ 87 u_long res_avg_interval = 5; /* min average interpacket interval */ 88 u_long res_min_interval = 1; /* min interpacket interval */ 89 90 /* 91 * Count number of restriction entries referring to RES_LIMITED controls 92 * activation/deactivation of monitoring (with respect to RES_LIMITED 93 * control) 94 */ 95 static u_long res_limited_refcnt; 96 static u_long res_limited_refcnt6; 97 98 /* 99 * Our initial allocation of lists entries. 100 */ 101 static struct restrictlist resinit[INITRESLIST]; 102 static struct restrictlist6 resinit6[INITRESLIST]; 103 104 /* 105 * init_restrict - initialize the restriction data structures 106 */ 107 void 108 init_restrict(void) 109 { 110 register int i; 111 112 /* 113 * Zero the list and put all but one on the free list 114 */ 115 resfree = NULL; 116 memset((char *)resinit, 0, sizeof resinit); 117 resfree6 = NULL; 118 memset((char *)resinit6, 0, sizeof resinit6); 119 for (i = 1; i < INITRESLIST; i++) { 120 resinit[i].next = resfree; 121 resinit6[i].next = resfree6; 122 resfree = &resinit[i]; 123 resfree6 = &resinit6[i]; 124 } 125 numresfree = INITRESLIST-1; 126 numresfree6 = INITRESLIST-1; 127 128 /* 129 * Put the remaining item at the head of the list as our default 130 * entry. Everything in here should be zero for now. 131 */ 132 resinit[0].addr = htonl(INADDR_ANY); 133 resinit[0].mask = 0; 134 memset(&resinit6[0].addr6, 0, sizeof(struct in6_addr)); 135 memset(&resinit6[0].mask6, 0, sizeof(struct in6_addr)); 136 restrictlist = &resinit[0]; 137 restrictlist6 = &resinit6[0]; 138 restrictcount = 1; 139 restrictcount = 2; 140 141 /* 142 * fix up stat counters 143 */ 144 res_calls = 0; 145 res_found = 0; 146 res_not_found = 0; 147 148 /* 149 * set default values for RES_LIMIT functionality 150 */ 151 res_limited_refcnt = 0; 152 res_limited_refcnt6 = 0; 153 } 154 155 156 /* 157 * restrictions - return restrictions for this host 158 */ 159 int 160 restrictions( 161 struct sockaddr_storage *srcadr, 162 int at_listhead 163 ) 164 { 165 struct restrictlist *rl; 166 struct restrictlist *match = NULL; 167 struct restrictlist6 *rl6; 168 struct restrictlist6 *match6 = NULL; 169 struct in6_addr hostaddr6; 170 struct in6_addr hostservaddr6; 171 u_int32 hostaddr; 172 int flags = 0; 173 int isntpport; 174 175 res_calls++; 176 if (srcadr->ss_family == AF_INET) { 177 /* 178 * We need the host address in host order. Also need to 179 * know whether this is from the ntp port or not. 180 */ 181 hostaddr = SRCADR(srcadr); 182 isntpport = (SRCPORT(srcadr) == NTP_PORT); 183 184 /* 185 * Ignore any packets with a multicast source address 186 * (this should be done early in the receive process, 187 * later!) 188 */ 189 if (IN_CLASSD(SRCADR(srcadr))) 190 return (int)RES_IGNORE; 191 192 /* 193 * Set match to first entry, which is default entry. 194 * Work our way down from there. 195 */ 196 match = restrictlist; 197 for (rl = match->next; rl != NULL && rl->addr <= hostaddr; 198 rl = rl->next) 199 if ((hostaddr & rl->mask) == rl->addr) { 200 if ((rl->mflags & RESM_NTPONLY) && 201 !isntpport) 202 continue; 203 match = rl; 204 } 205 match->count++; 206 if (match == restrictlist) 207 res_not_found++; 208 else 209 res_found++; 210 flags = match->flags; 211 } 212 213 /* IPv6 source address */ 214 if (srcadr->ss_family == AF_INET6) { 215 /* 216 * Need to know whether this is from the ntp port or 217 * not. 218 */ 219 hostaddr6 = GET_INADDR6(*srcadr); 220 isntpport = (ntohs(( 221 (struct sockaddr_in6 *)srcadr)->sin6_port) == 222 NTP_PORT); 223 224 /* 225 * Ignore any packets with a multicast source address 226 * (this should be done early in the receive process, 227 * later!) 228 */ 229 if (IN6_IS_ADDR_MULTICAST(&hostaddr6)) 230 return (int)RES_IGNORE; 231 232 /* 233 * Set match to first entry, which is default entry. 234 * Work our way down from there. 235 */ 236 match6 = restrictlist6; 237 for (rl6 = match6->next; rl6 != NULL && 238 (memcmp(&(rl6->addr6), &hostaddr6, 239 sizeof(hostaddr6)) <= 0); rl6 = rl6->next) { 240 SET_IPV6_ADDR_MASK(&hostservaddr6, &hostaddr6, 241 &rl6->mask6); 242 if (memcmp(&hostservaddr6, &(rl6->addr6), 243 sizeof(hostservaddr6)) == 0) { 244 if ((rl6->mflags & RESM_NTPONLY) && 245 !isntpport) 246 continue; 247 match6 = rl6; 248 } 249 } 250 match6->count++; 251 if (match6 == restrictlist6) 252 res_not_found++; 253 else 254 res_found++; 255 flags = match6->flags; 256 } 257 258 /* 259 * The following implements a generalized call gap facility. 260 * Douse the RES_LIMITED bit only if the interval since the last 261 * packet is greater than res_min_interval and the average is 262 * greater thatn res_avg_interval. 263 */ 264 if (!at_listhead || mon_enabled == MON_OFF) { 265 flags &= ~RES_LIMITED; 266 } else { 267 struct mon_data *md; 268 269 /* 270 * At this poin the most recent arrival is first in the 271 * MRU list. Let the first 10 packets in for free until 272 * the average stabilizes. 273 */ 274 md = mon_mru_list.mru_next; 275 if (md->avg_interval == 0) 276 md->avg_interval = md->drop_count; 277 else 278 md->avg_interval += (md->drop_count - 279 md->avg_interval) / RES_AVG; 280 if (md->count < 10 || (md->drop_count > 281 res_min_interval && md->avg_interval > 282 res_avg_interval)) 283 flags &= ~RES_LIMITED; 284 md->drop_count = flags; 285 } 286 return (flags); 287 } 288 289 290 /* 291 * hack_restrict - add/subtract/manipulate entries on the restrict list 292 */ 293 void 294 hack_restrict( 295 int op, 296 struct sockaddr_storage *resaddr, 297 struct sockaddr_storage *resmask, 298 int mflags, 299 int flags 300 ) 301 { 302 register u_int32 addr = 0; 303 register u_int32 mask = 0; 304 struct in6_addr addr6; 305 struct in6_addr mask6; 306 register struct restrictlist *rl = NULL; 307 register struct restrictlist *rlprev = NULL; 308 register struct restrictlist6 *rl6 = NULL; 309 register struct restrictlist6 *rlprev6 = NULL; 310 int i, addr_cmp, mask_cmp; 311 memset(&addr6, 0, sizeof(struct in6_addr)); 312 memset(&mask6, 0, sizeof(struct in6_addr)); 313 314 if (resaddr->ss_family == AF_INET) { 315 /* 316 * Get address and mask in host byte order 317 */ 318 addr = SRCADR(resaddr); 319 mask = SRCADR(resmask); 320 addr &= mask; /* make sure low bits zero */ 321 322 /* 323 * If this is the default address, point at first on 324 * list. Else go searching for it. 325 */ 326 if (addr == 0) { 327 rlprev = NULL; 328 rl = restrictlist; 329 } else { 330 rlprev = restrictlist; 331 rl = rlprev->next; 332 while (rl != NULL) { 333 if (rl->addr > addr) { 334 rl = NULL; 335 break; 336 } else if (rl->addr == addr) { 337 if (rl->mask == mask) { 338 if ((mflags & 339 RESM_NTPONLY) == 340 (rl->mflags & 341 RESM_NTPONLY)) 342 break; 343 344 if (!(mflags & 345 RESM_NTPONLY)) { 346 rl = NULL; 347 break; 348 } 349 } else if (rl->mask > mask) { 350 rl = NULL; 351 break; 352 } 353 } 354 rlprev = rl; 355 rl = rl->next; 356 } 357 } 358 } 359 360 if (resaddr->ss_family == AF_INET6) { 361 mask6 = GET_INADDR6(*resmask); 362 SET_IPV6_ADDR_MASK(&addr6, 363 &GET_INADDR6(*resaddr), &mask6); 364 if (IN6_IS_ADDR_UNSPECIFIED(&addr6)) { 365 rlprev6 = NULL; 366 rl6 = restrictlist6; 367 } else { 368 rlprev6 = restrictlist6; 369 rl6 = rlprev6->next; 370 while (rl6 != NULL) { 371 addr_cmp = memcmp(&rl6->addr6, &addr6, 372 sizeof(addr6)); 373 if (addr_cmp > 0) { 374 rl6 = NULL; 375 break; 376 } else if (addr_cmp == 0) { 377 mask_cmp = memcmp(&rl6->mask6, 378 &mask6, sizeof(mask6)); 379 if (mask_cmp == 0) { 380 if ((mflags & 381 RESM_NTPONLY) == 382 (rl6->mflags & 383 RESM_NTPONLY)) 384 break; 385 386 if (!(mflags & 387 RESM_NTPONLY)) { 388 rl6 = NULL; 389 break; 390 } 391 } else if (mask_cmp > 0) { 392 rl6 = NULL; 393 break; 394 } 395 } 396 rlprev6 = rl6; 397 rl6 = rl6->next; 398 } 399 } 400 } 401 402 /* 403 * In case the above wasn't clear :-), either rl now points 404 * at the entry this call refers to, or rl is zero and rlprev 405 * points to the entry prior to where this one should go in 406 * the sort. 407 */ 408 409 /* 410 * Switch based on operation 411 */ 412 if (resaddr->ss_family == AF_INET) { 413 switch (op) { 414 case RESTRICT_FLAGS: 415 /* 416 * Here we add bits to the flags. If this is a 417 * new restriction add it. 418 */ 419 if (rl == NULL) { 420 if (resfree == NULL) { 421 rl = (struct restrictlist *) 422 emalloc(INCRESLIST * 423 sizeof(struct 424 restrictlist)); 425 memset((char *)rl, 0, 426 INCRESLIST * sizeof(struct 427 restrictlist)); 428 for (i = 0; i < INCRESLIST; i++) { 429 rl->next = resfree; 430 resfree = rl; 431 rl++; 432 } 433 numresfree = INCRESLIST; 434 } 435 436 rl = resfree; 437 resfree = rl->next; 438 numresfree--; 439 440 rl->addr = addr; 441 rl->mask = mask; 442 rl->mflags = (u_short)mflags; 443 444 if (rlprev == NULL) { 445 rl->next = restrictlist; 446 restrictlist = rl; 447 } else { 448 rl->next = rlprev->next; 449 rlprev->next = rl; 450 } 451 restrictcount++; 452 } 453 if ((rl->flags ^ (u_short)flags) & 454 RES_LIMITED) { 455 res_limited_refcnt++; 456 mon_start(MON_RES); 457 } 458 rl->flags |= (u_short)flags; 459 break; 460 461 case RESTRICT_UNFLAG: 462 /* 463 * Remove some bits from the flags. If we didn't 464 * find this one, just return. 465 */ 466 if (rl != NULL) { 467 if ((rl->flags ^ (u_short)flags) & 468 RES_LIMITED) { 469 res_limited_refcnt--; 470 if (res_limited_refcnt == 0) 471 mon_stop(MON_RES); 472 } 473 rl->flags &= (u_short)~flags; 474 } 475 break; 476 477 case RESTRICT_REMOVE: 478 case RESTRICT_REMOVEIF: 479 /* 480 * Remove an entry from the table entirely if we 481 * found one. Don't remove the default entry and 482 * don't remove an interface entry. 483 */ 484 if (rl != NULL 485 && rl->addr != htonl(INADDR_ANY) 486 && !(rl->mflags & RESM_INTERFACE && op != RESTRICT_REMOVEIF)) { 487 if (rlprev != NULL) { 488 rlprev->next = rl->next; 489 } else { 490 restrictlist = rl->next; 491 } 492 restrictcount--; 493 if (rl->flags & RES_LIMITED) { 494 res_limited_refcnt--; 495 if (res_limited_refcnt == 0) 496 mon_stop(MON_RES); 497 } 498 memset((char *)rl, 0, 499 sizeof(struct restrictlist)); 500 501 rl->next = resfree; 502 resfree = rl; 503 numresfree++; 504 } 505 break; 506 507 default: 508 break; 509 } 510 } else if (resaddr->ss_family == AF_INET6) { 511 switch (op) { 512 case RESTRICT_FLAGS: 513 /* 514 * Here we add bits to the flags. If this is a 515 * new restriction add it. 516 */ 517 if (rl6 == NULL) { 518 if (resfree6 == NULL) { 519 rl6 = (struct 520 restrictlist6 *)emalloc( 521 INCRESLIST * sizeof(struct 522 restrictlist6)); 523 memset((char *)rl6, 0, 524 INCRESLIST * sizeof(struct 525 restrictlist6)); 526 527 for (i = 0; i < INCRESLIST; 528 i++) { 529 rl6->next = resfree6; 530 resfree6 = rl6; 531 rl6++; 532 } 533 numresfree6 = INCRESLIST; 534 } 535 rl6 = resfree6; 536 resfree6 = rl6->next; 537 numresfree6--; 538 rl6->addr6 = addr6; 539 rl6->mask6 = mask6; 540 rl6->mflags = (u_short)mflags; 541 if (rlprev6 != NULL) { 542 rl6->next = rlprev6->next; 543 rlprev6->next = rl6; 544 } else { 545 rl6->next = restrictlist6; 546 restrictlist6 = rl6; 547 } 548 restrictcount6++; 549 } 550 if ((rl6->flags ^ (u_short)flags) & 551 RES_LIMITED) { 552 res_limited_refcnt6++; 553 mon_start(MON_RES); 554 } 555 rl6->flags |= (u_short)flags; 556 break; 557 558 case RESTRICT_UNFLAG: 559 /* 560 * Remove some bits from the flags. If we didn't 561 * find this one, just return. 562 */ 563 if (rl6 != NULL) { 564 if ((rl6->flags ^ (u_short)flags) & 565 RES_LIMITED) { 566 res_limited_refcnt6--; 567 if (res_limited_refcnt6 == 0) 568 mon_stop(MON_RES); 569 } 570 rl6->flags &= (u_short)~flags; 571 } 572 break; 573 574 case RESTRICT_REMOVE: 575 case RESTRICT_REMOVEIF: 576 /* 577 * Remove an entry from the table entirely if we 578 * found one. Don't remove the default entry and 579 * don't remove an interface entry. 580 */ 581 if (rl6 != NULL && 582 !IN6_IS_ADDR_UNSPECIFIED(&rl6->addr6) 583 && !(rl6->mflags & RESM_INTERFACE && op != RESTRICT_REMOVEIF)) { 584 if (rlprev6 != NULL) { 585 rlprev6->next = rl6->next; 586 } else { 587 restrictlist6 = rl6->next; 588 } 589 restrictcount6--; 590 if (rl6->flags & RES_LIMITED) { 591 res_limited_refcnt6--; 592 if (res_limited_refcnt6 == 0) 593 mon_stop(MON_RES); 594 } 595 memset((char *)rl6, 0, 596 sizeof(struct restrictlist6)); 597 rl6->next = resfree6; 598 resfree6 = rl6; 599 numresfree6++; 600 } 601 break; 602 603 default: 604 break; 605 } 606 } 607 } 608