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