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/* 62 * The restriction list 63 */ 64struct restrictlist *restrictlist; 65struct restrictlist6 *restrictlist6; 66static int restrictcount; /* count of entries in the res list */ 67static int restrictcount6; /* count of entries in the res list 2*/ 68 69/* 70 * The free list and associated counters. Also some uninteresting 71 * stat counters. 72 */ 73static struct restrictlist *resfree; 74static struct restrictlist6 *resfree6; 75static int numresfree; /* number of struct on free list */ 76static int numresfree6; /* number of struct on free list 2 */ 77 78static u_long res_calls; 79static u_long res_found; 80static u_long res_not_found; 81 82/* 83 * Count number of restriction entries referring to RES_LIMITED controls 84 * activation/deactivation of monitoring (with respect to RES_LIMITED 85 * control) 86 */ 87static u_long res_limited_refcnt; 88static u_long res_limited_refcnt6; 89 90/* 91 * Our initial allocation of lists entries. 92 */ 93static struct restrictlist resinit[INITRESLIST]; 94static struct restrictlist6 resinit6[INITRESLIST]; 95 96 97/* 98 * init_restrict - initialize the restriction data structures 99 */ 100void 101init_restrict(void) 102{ 103 register int i; 104 105 /* 106 * Zero the list and put all but one on the free list 107 */ 108 resfree = 0; 109 memset((char *)resinit, 0, sizeof resinit); 110 resfree6 = 0; 111 memset((char *)resinit6, 0, sizeof resinit6); 112 for (i = 1; i < INITRESLIST; i++) { 113 resinit[i].next = resfree; 114 resinit6[i].next = resfree6; 115 resfree = &resinit[i]; 116 resfree6 = &resinit6[i]; 117 } 118 numresfree = INITRESLIST-1; 119 numresfree6 = INITRESLIST-1; 120 121 /* 122 * Put the remaining item at the head of the list as our default 123 * entry. Everything in here should be zero for now. 124 */ 125 resinit[0].addr = htonl(INADDR_ANY); 126 resinit[0].mask = 0; 127 memset(&resinit6[0].addr6, 0, sizeof(struct in6_addr)); 128 memset(&resinit6[0].mask6, 0, sizeof(struct in6_addr)); 129 restrictlist = &resinit[0]; 130 restrictlist6 = &resinit6[0]; 131 restrictcount = 1; 132 restrictcount = 2; 133 134 /* 135 * fix up stat counters 136 */ 137 res_calls = 0; 138 res_found = 0; 139 res_not_found = 0; 140 141 /* 142 * set default values for RES_LIMIT functionality 143 */ 144 res_limited_refcnt = 0; 145 res_limited_refcnt6 = 0; 146} 147 148 149/* 150 * restrictions - return restrictions for this host 151 */ 152int 153restrictions( 154 sockaddr_u *srcadr 155 ) 156{ 157 struct restrictlist *rl; 158 struct restrictlist *match = NULL; 159 struct restrictlist6 *rl6; 160 struct restrictlist6 *match6 = NULL; 161 struct in6_addr hostaddr6; 162 struct in6_addr hostservaddr6; 163 u_int32 hostaddr; 164 int flags = 0; 165 int isntpport; 166 167 res_calls++; 168 /* IPv4 source address */ 169 if (IS_IPV4(srcadr)) { 170 171 /* 172 * We need the host address in host order. Also need to 173 * know whether this is from the ntp port or not. 174 */ 175 hostaddr = SRCADR(srcadr); 176 isntpport = (NTP_PORT == SRCPORT(srcadr)); 177 178 /* 179 * Ignore any packets with a multicast source address 180 * (this should be done early in the receive process, 181 * not later!) 182 */ 183 if (IN_CLASSD(SRCADR(srcadr))) 184 return (int)RES_IGNORE; 185 186 /* 187 * Set match to first entry, which is default entry. 188 * Work our way down from there. 189 */ 190 match = restrictlist; 191 for (rl = match->next; rl != 0 && rl->addr <= hostaddr; 192 rl = rl->next) 193 if ((hostaddr & rl->mask) == rl->addr) { 194 if ((rl->mflags & RESM_NTPONLY) && 195 !isntpport) 196 continue; 197 match = rl; 198 } 199 match->count++; 200 if (match == restrictlist) 201 res_not_found++; 202 else 203 res_found++; 204 flags = match->flags; 205 } 206 207 /* IPv6 source address */ 208 if (IS_IPV6(srcadr)) { 209 210 /* 211 * We need the host address in network order. Also need 212 * to know whether this is from the ntp port or not. 213 */ 214 hostaddr6 = SOCK_ADDR6(srcadr); 215 isntpport = (NTP_PORT == SRCPORT(srcadr)); 216 217 /* 218 * Ignore any packets with a multicast source address 219 * (this should be done early in the receive process, 220 * not later!) 221 */ 222 if (IN6_IS_ADDR_MULTICAST(&hostaddr6)) 223 return (int)RES_IGNORE; 224 225 /* 226 * Set match to first entry, which is default entry. 227 * Work our way down from there. 228 */ 229 match6 = restrictlist6; 230 for (rl6 = match6->next; rl6 != 0 && 231 (memcmp(&(rl6->addr6), &hostaddr6, 232 sizeof(hostaddr6)) <= 0); rl6 = rl6->next) { 233 SET_IPV6_ADDR_MASK(&hostservaddr6, &hostaddr6, 234 &rl6->mask6); 235 if (memcmp(&hostservaddr6, &(rl6->addr6), 236 sizeof(hostservaddr6)) == 0) { 237 if ((rl6->mflags & RESM_NTPONLY) && 238 !isntpport) 239 continue; 240 match6 = rl6; 241 } 242 } 243 match6->count++; 244 if (match6 == restrictlist6) 245 res_not_found++; 246 else 247 res_found++; 248 flags = match6->flags; 249 } 250 return (flags); 251} 252 253 254/* 255 * hack_restrict - add/subtract/manipulate entries on the restrict list 256 */ 257void 258hack_restrict( 259 int op, 260 sockaddr_u *resaddr, 261 sockaddr_u *resmask, 262 int mflags, 263 int flags 264 ) 265{ 266 register u_int32 addr = 0; 267 register u_int32 mask = 0; 268 struct in6_addr addr6; 269 struct in6_addr mask6; 270 register struct restrictlist *rl = NULL; 271 register struct restrictlist *rlprev = NULL; 272 register struct restrictlist6 *rl6 = NULL; 273 register struct restrictlist6 *rlprev6 = NULL; 274 int i, addr_cmp, mask_cmp; 275 memset(&addr6, 0, sizeof(struct in6_addr)); 276 memset(&mask6, 0, sizeof(struct in6_addr)); 277 278 if (IS_IPV4(resaddr)) { 279 280 DPRINTF(1, ("restrict: addr %08x mask %08x mflags %08x flags %08x\n", 281 SRCADR(resaddr), SRCADR(resmask), mflags, flags)); 282 283 /* 284 * Get address and mask in host byte order 285 */ 286 addr = SRCADR(resaddr); 287 mask = SRCADR(resmask); 288 addr &= mask; /* make sure low bits zero */ 289 290 /* 291 * If this is the default address, point at first on 292 * list. Else go searching for it. 293 */ 294 if (addr == 0) { 295 rlprev = 0; 296 rl = restrictlist; 297 } else { 298 rlprev = restrictlist; 299 rl = rlprev->next; 300 while (rl != 0) { 301 if (rl->addr > addr) { 302 rl = 0; 303 break; 304 } else if (rl->addr == addr) { 305 if (rl->mask == mask) { 306 if ((mflags & 307 RESM_NTPONLY) == 308 (rl->mflags & 309 RESM_NTPONLY)) 310 break; 311 312 if (!(mflags & 313 RESM_NTPONLY)) { 314 rl = 0; 315 break; 316 } 317 } else if (rl->mask > mask) { 318 rl = 0; 319 break; 320 } 321 } 322 rlprev = rl; 323 rl = rl->next; 324 } 325 } 326 } 327 328 if (IS_IPV6(resaddr)) { 329 mask6 = SOCK_ADDR6(resmask); 330 SET_IPV6_ADDR_MASK(&addr6, 331 PSOCK_ADDR6(resaddr), &mask6); 332 if (IN6_IS_ADDR_UNSPECIFIED(&addr6)) { 333 rlprev6 = NULL; 334 rl6 = restrictlist6; 335 } else { 336 rlprev6 = restrictlist6; 337 rl6 = rlprev6->next; 338 while (rl6 != 0) { 339 addr_cmp = memcmp(&rl6->addr6, &addr6, 340 sizeof(addr6)); 341 if (addr_cmp > 0) { 342 rl6 = 0; 343 break; 344 345 } else if (addr_cmp == 0) { 346 mask_cmp = memcmp(&rl6->mask6, 347 &mask6, sizeof(mask6)); 348 if (mask_cmp == 0) { 349 if ((mflags & 350 RESM_NTPONLY) == 351 (rl6->mflags & 352 RESM_NTPONLY)) 353 break; 354 355 if (!(mflags & 356 RESM_NTPONLY)) { 357 rl6 = 0; 358 break; 359 } 360 } else if (mask_cmp > 0) { 361 rl6 = 0; 362 break; 363 } 364 } 365 rlprev6 = rl6; 366 rl6 = rl6->next; 367 } 368 } 369 } 370 371 /* 372 * In case the above wasn't clear :-), either rl now points 373 * at the entry this call refers to, or rl is zero and rlprev 374 * points to the entry prior to where this one should go in 375 * the sort. 376 */ 377 /* 378 * Switch based on operation 379 */ 380 if (IS_IPV4(resaddr)) { 381 switch (op) { 382 case RESTRICT_FLAGS: 383 384 /* 385 * Here we add bits to the flags. If this is a 386 * new restriction add it. 387 */ 388 if (rl == 0) { 389 if (numresfree == 0) { 390 rl = (struct restrictlist *) 391 emalloc(INCRESLIST * 392 sizeof(struct 393 restrictlist)); 394 memset((char *)rl, 0, 395 INCRESLIST * sizeof(struct 396 restrictlist)); 397 for (i = 0; i < INCRESLIST; 398 i++) { 399 rl->next = resfree; 400 resfree = rl; 401 rl++; 402 } 403 numresfree = INCRESLIST; 404 } 405 rl = resfree; 406 resfree = rl->next; 407 numresfree--; 408 rl->addr = addr; 409 rl->mask = mask; 410 rl->mflags = (u_short)mflags; 411 if (rlprev == NULL) { 412 rl->next = restrictlist; 413 restrictlist = rl; 414 } else { 415 rl->next = rlprev->next; 416 rlprev->next = rl; 417 } 418 restrictcount++; 419 } 420 if ((rl->flags ^ (u_short)flags) & 421 RES_LIMITED) { 422 res_limited_refcnt++; 423 mon_start(MON_RES); 424 } 425 rl->flags |= (u_short)flags; 426 break; 427 428 case RESTRICT_UNFLAG: 429 430 /* 431 * Remove some bits from the flags. If we didn't 432 * find this one, just return. 433 */ 434 if (rl != 0) { 435 if ((rl->flags ^ (u_short)flags) & 436 RES_LIMITED) { 437 res_limited_refcnt--; 438 if (res_limited_refcnt == 0) 439 mon_stop(MON_RES); 440 } 441 rl->flags &= (u_short)~flags; 442 } 443 break; 444 445 case RESTRICT_REMOVE: 446 case RESTRICT_REMOVEIF: 447 448 /* 449 * Remove an entry from the table entirely if we 450 * found one. Don't remove the default entry and 451 * don't remove an interface entry. 452 */ 453 if (rl != 0 454 && rl->addr != htonl(INADDR_ANY) 455 && !(rl->mflags & RESM_INTERFACE && op != 456 RESTRICT_REMOVEIF)) { 457 if (rlprev != NULL) { 458 rlprev->next = rl->next; 459 } else { 460 restrictlist = rl->next; 461 } 462 restrictcount--; 463 if (rl->flags & RES_LIMITED) { 464 res_limited_refcnt--; 465 if (res_limited_refcnt == 0) 466 mon_stop(MON_RES); 467 } 468 memset((char *)rl, 0, 469 sizeof(struct restrictlist)); 470 471 rl->next = resfree; 472 resfree = rl; 473 numresfree++; 474 } 475 break; 476 477 default: 478 break; 479 } 480 } else if (IS_IPV6(resaddr)) { 481 switch (op) { 482 case RESTRICT_FLAGS: 483 484 /* 485 * Here we add bits to the flags. If this is a 486 * new restriction add it. 487 */ 488 if (rl6 == 0) { 489 if (numresfree6 == 0) { 490 rl6 = (struct 491 restrictlist6 *)emalloc( 492 INCRESLIST * sizeof(struct 493 restrictlist6)); 494 memset((char *)rl6, 0, 495 INCRESLIST * sizeof(struct 496 restrictlist6)); 497 498 for (i = 0; i < INCRESLIST; 499 i++) { 500 rl6->next = resfree6; 501 resfree6 = rl6; 502 rl6++; 503 } 504 numresfree6 = INCRESLIST; 505 } 506 rl6 = resfree6; 507 resfree6 = rl6->next; 508 numresfree6--; 509 rl6->addr6 = addr6; 510 rl6->mask6 = mask6; 511 rl6->mflags = (u_short)mflags; 512 if (rlprev6 != NULL) { 513 rl6->next = rlprev6->next; 514 rlprev6->next = rl6; 515 } else { 516 rl6->next = restrictlist6; 517 restrictlist6 = rl6; 518 } 519 restrictcount6++; 520 } 521 if ((rl6->flags ^ (u_short)flags) & 522 RES_LIMITED) { 523 res_limited_refcnt6++; 524 mon_start(MON_RES); 525 } 526 rl6->flags |= (u_short)flags; 527 break; 528 529 case RESTRICT_UNFLAG: 530 531 /* 532 * Remove some bits from the flags. If we didn't 533 * find this one, just return. 534 */ 535 if (rl6 != 0) { 536 if ((rl6->flags ^ (u_short)flags) & 537 RES_LIMITED) { 538 res_limited_refcnt6--; 539 if (res_limited_refcnt6 == 0) 540 mon_stop(MON_RES); 541 } 542 rl6->flags &= (u_short)~flags; 543 } 544 break; 545 546 case RESTRICT_REMOVE: 547 case RESTRICT_REMOVEIF: 548 549 /* 550 * Remove an entry from the table entirely if we 551 * found one. Don't remove the default entry and 552 * don't remove an interface entry. 553 */ 554 if (rl6 != 0 && 555 !IN6_IS_ADDR_UNSPECIFIED(&rl6->addr6) 556 && !(rl6->mflags & RESM_INTERFACE && op != 557 RESTRICT_REMOVEIF)) { 558 if (rlprev6 != NULL) { 559 rlprev6->next = rl6->next; 560 } else { 561 restrictlist6 = rl6->next; 562 } 563 restrictcount6--; 564 if (rl6->flags & RES_LIMITED) { 565 res_limited_refcnt6--; 566 if (res_limited_refcnt6 == 0) 567 mon_stop(MON_RES); 568 } 569 memset((char *)rl6, 0, 570 sizeof(struct restrictlist6)); 571 rl6->next = resfree6; 572 resfree6 = rl6; 573 numresfree6++; 574 } 575 break; 576 577 default: 578 break; 579 } 580 } 581} 582