1 /* 2 * ntp_restrict.c - find out what restrictions this host is running under 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 match's 27 * flags instead. When you hit the point where the sorted address is 28 * greater than the target, you return with the last set of flags you 29 * found. Because of the ordering of the list, the most specific match 30 * 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 34 * from your own interfaces. It was also thought it would sometimes 35 * be useful to keep a misbehaving host or two from abusing your primary 36 * clock. It has been expanded, however, to suit the needs of those 37 * with more restrictive access policies. 38 */ 39 40 /* 41 * Memory allocation parameters. We allocate INITRESLIST entries 42 * initially, and add INCRESLIST entries to the free list whenever 43 * we run out. 44 */ 45 #define INITRESLIST 10 46 #define INCRESLIST 5 47 48 /* 49 * The restriction list 50 */ 51 struct restrictlist *restrictlist; 52 static int restrictcount; /* count of entries in the restriction list */ 53 54 /* 55 * The free list and associated counters. Also some uninteresting 56 * stat counters. 57 */ 58 static struct restrictlist *resfree; 59 static int numresfree; /* number of structures on free list */ 60 61 static u_long res_calls; 62 static u_long res_found; 63 static u_long res_not_found; 64 /* static u_long res_timereset; */ 65 66 /* 67 * Parameters of the RES_LIMITED restriction option. 68 * client_limit is the number of hosts allowed per source net 69 * client_limit_period is the number of seconds after which an entry 70 * is no longer considered for client limit determination 71 */ 72 u_long client_limit; 73 u_long client_limit_period; 74 /* 75 * count number of restriction entries referring to RES_LIMITED 76 * controls activation/deactivation of monitoring 77 * (with respect to RES_LIMITED control) 78 */ 79 static u_long res_limited_refcnt; 80 81 /* 82 * Our initial allocation of list entries. 83 */ 84 static struct restrictlist resinit[INITRESLIST]; 85 86 /* 87 * init_restrict - initialize the restriction data structures 88 */ 89 void 90 init_restrict(void) 91 { 92 register int i; 93 char bp[80]; 94 95 /* 96 * Zero the list and put all but one on the free list 97 */ 98 resfree = 0; 99 memset((char *)resinit, 0, sizeof resinit); 100 101 for (i = 1; i < INITRESLIST; i++) { 102 resinit[i].next = resfree; 103 resfree = &resinit[i]; 104 } 105 106 numresfree = INITRESLIST-1; 107 108 /* 109 * Put the remaining item at the head of the 110 * list as our default entry. Everything in here 111 * should be zero for now. 112 */ 113 resinit[0].addr = htonl(INADDR_ANY); 114 resinit[0].mask = 0; 115 restrictlist = &resinit[0]; 116 restrictcount = 1; 117 118 119 /* 120 * fix up stat counters 121 */ 122 res_calls = 0; 123 res_found = 0; 124 res_not_found = 0; 125 /* res_timereset = 0; */ 126 127 /* 128 * set default values for RES_LIMIT functionality 129 */ 130 client_limit = 3; 131 client_limit_period = 3600; 132 res_limited_refcnt = 0; 133 134 sprintf(bp, "client_limit=%ld", client_limit); 135 set_sys_var(bp, strlen(bp)+1, RO); 136 sprintf(bp, "client_limit_period=%ld", client_limit_period); 137 set_sys_var(bp, strlen(bp)+1, RO); 138 } 139 140 141 /* 142 * restrictions - return restrictions for this host 143 */ 144 int 145 restrictions( 146 struct sockaddr_in *srcadr 147 ) 148 { 149 register struct restrictlist *rl; 150 register struct restrictlist *match; 151 register u_int32 hostaddr; 152 register int isntpport; 153 154 res_calls++; 155 /* 156 * We need the host address in host order. Also need to know 157 * whether this is from the ntp port or not. 158 */ 159 hostaddr = SRCADR(srcadr); 160 isntpport = (SRCPORT(srcadr) == NTP_PORT); 161 162 /* 163 * Ignore any packets with a multicast source address 164 * (this should be done early in the receive process, later!) 165 */ 166 if (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr))) 167 return (int)RES_IGNORE; 168 169 /* 170 * Set match to first entry, which is default entry. Work our 171 * way down from there. 172 */ 173 match = restrictlist; 174 175 for (rl = match->next; rl != 0 && rl->addr <= hostaddr; rl = rl->next) 176 if ((hostaddr & rl->mask) == rl->addr) { 177 if ((rl->mflags & RESM_NTPONLY) && !isntpport) 178 continue; 179 match = rl; 180 } 181 182 match->count++; 183 if (match == restrictlist) 184 res_not_found++; 185 else 186 res_found++; 187 188 /* 189 * The following implements limiting the number of clients 190 * accepted from a given network. The notion of "same network" 191 * is determined by the mask and addr fields of the restrict 192 * list entry. The monitor mechanism has to be enabled for 193 * collecting info on current clients. 194 * 195 * The policy is as follows: 196 * - take the list of clients recorded 197 * from the given "network" seen within the last 198 * client_limit_period seconds 199 * - if there are at most client_limit entries: 200 * --> access allowed 201 * - otherwise sort by time first seen 202 * - current client among the first client_limit seen 203 * hosts? 204 * if yes: access allowed 205 * else: eccess denied 206 */ 207 if (match->flags & RES_LIMITED) { 208 int lcnt; 209 struct mon_data *md, *this_client; 210 211 #ifdef DEBUG 212 if (debug > 2) 213 printf("limited clients check: %ld clients, period %ld seconds, net is 0x%lX\n", 214 client_limit, client_limit_period, 215 (u_long)netof(hostaddr)); 216 #endif /*DEBUG*/ 217 if (mon_enabled == MON_OFF) { 218 #ifdef DEBUG 219 if (debug > 4) 220 printf("no limit - monitoring is off\n"); 221 #endif 222 return (int)(match->flags & ~RES_LIMITED); 223 } 224 225 /* 226 * How nice, MRU list provides our current client as the 227 * first entry in the list. 228 * Monitoring was verified to be active above, thus we 229 * know an entry for our client must exist, or some 230 * brain dead set the memory limit for mon entries to ZERO!!! 231 */ 232 this_client = mon_mru_list.mru_next; 233 234 for (md = mon_fifo_list.fifo_next,lcnt = 0; 235 md != &mon_fifo_list; 236 md = md->fifo_next) { 237 if ((current_time - md->lasttime) 238 > client_limit_period) { 239 #ifdef DEBUG 240 if (debug > 5) 241 printf("checking: %s: ignore: too old: %ld\n", 242 numtoa(md->rmtadr), 243 current_time - md->lasttime); 244 #endif 245 continue; 246 } 247 if (md->mode == MODE_BROADCAST || 248 md->mode == MODE_CONTROL || 249 md->mode == MODE_PRIVATE) { 250 #ifdef DEBUG 251 if (debug > 5) 252 printf("checking: %s: ignore mode %d\n", 253 numtoa(md->rmtadr), 254 md->mode); 255 #endif 256 continue; 257 } 258 if (netof(md->rmtadr) != 259 netof(hostaddr)) { 260 #ifdef DEBUG 261 if (debug > 5) 262 printf("checking: %s: different net 0x%lX\n", 263 numtoa(md->rmtadr), 264 (u_long)netof(md->rmtadr)); 265 #endif 266 continue; 267 } 268 lcnt++; 269 if (lcnt > (int) client_limit || 270 md->rmtadr == hostaddr) { 271 #ifdef DEBUG 272 if (debug > 5) 273 printf("considering %s: found host\n", 274 numtoa(md->rmtadr)); 275 #endif 276 break; 277 } 278 #ifdef DEBUG 279 else { 280 if (debug > 5) 281 printf("considering %s: same net\n", 282 numtoa(md->rmtadr)); 283 } 284 #endif 285 286 } 287 #ifdef DEBUG 288 if (debug > 4) 289 printf("this one is rank %d in list, limit is %lu: %s\n", 290 lcnt, client_limit, 291 (lcnt <= (int) client_limit) ? "ALLOW" : "REJECT"); 292 #endif 293 if (lcnt <= (int) client_limit) { 294 this_client->lastdrop = 0; 295 return (int)(match->flags & ~RES_LIMITED); 296 } else { 297 this_client->lastdrop = current_time; 298 } 299 } 300 return (int)match->flags; 301 } 302 303 304 /* 305 * hack_restrict - add/subtract/manipulate entries on the restrict list 306 */ 307 void 308 hack_restrict( 309 int op, 310 struct sockaddr_in *resaddr, 311 struct sockaddr_in *resmask, 312 int mflags, 313 int flags 314 ) 315 { 316 register u_int32 addr; 317 register u_int32 mask; 318 register struct restrictlist *rl; 319 register struct restrictlist *rlprev; 320 int i; 321 322 /* 323 * Get address and mask in host byte order 324 */ 325 addr = SRCADR(resaddr); 326 mask = SRCADR(resmask); 327 addr &= mask; /* make sure low bits are zero */ 328 329 /* 330 * If this is the default address, point at first on list. Else 331 * go searching for it. 332 */ 333 if (addr == htonl(INADDR_ANY)) { 334 rlprev = 0; 335 rl = restrictlist; 336 } else { 337 rlprev = restrictlist; 338 rl = rlprev->next; 339 while (rl != 0) { 340 if (rl->addr > addr) { 341 rl = 0; 342 break; 343 } else if (rl->addr == addr) { 344 if (rl->mask == mask) { 345 if ((mflags & RESM_NTPONLY) 346 == (rl->mflags & RESM_NTPONLY)) 347 break; /* exact match */ 348 if (!(mflags & RESM_NTPONLY)) { 349 /* 350 * No flag fits before flag 351 */ 352 rl = 0; 353 break; 354 } 355 /* continue on */ 356 } else if (rl->mask > mask) { 357 rl = 0; 358 break; 359 } 360 } 361 rlprev = rl; 362 rl = rl->next; 363 } 364 } 365 /* 366 * In case the above wasn't clear :-), either rl now points 367 * at the entry this call refers to, or rl is zero and rlprev 368 * points to the entry prior to where this one should go in 369 * the sort. 370 */ 371 372 /* 373 * Switch based on operation 374 */ 375 switch (op) { 376 case RESTRICT_FLAGS: 377 /* 378 * Here we add bits to the flags. If this is a new 379 * restriction add it. 380 */ 381 if (rl == 0) { 382 if (numresfree == 0) { 383 rl = (struct restrictlist *) emalloc( 384 INCRESLIST*sizeof(struct restrictlist)); 385 memset((char *)rl, 0, 386 INCRESLIST*sizeof(struct restrictlist)); 387 388 for (i = 0; i < INCRESLIST; i++) { 389 rl->next = resfree; 390 resfree = rl; 391 rl++; 392 } 393 numresfree = INCRESLIST; 394 } 395 396 rl = resfree; 397 resfree = rl->next; 398 numresfree--; 399 400 rl->addr = addr; 401 rl->mask = mask; 402 rl->mflags = (u_short)mflags; 403 404 rl->next = rlprev->next; 405 rlprev->next = rl; 406 restrictcount++; 407 } 408 if ((rl->flags ^ (u_short)flags) & RES_LIMITED) { 409 res_limited_refcnt++; 410 mon_start(MON_RES); /* ensure data gets collected */ 411 } 412 rl->flags |= (u_short)flags; 413 break; 414 415 case RESTRICT_UNFLAG: 416 /* 417 * Remove some bits from the flags. If we didn't 418 * find this one, just return. 419 */ 420 if (rl != 0) { 421 if ((rl->flags ^ (u_short)flags) & RES_LIMITED) { 422 res_limited_refcnt--; 423 if (res_limited_refcnt == 0) 424 mon_stop(MON_RES); 425 } 426 rl->flags &= (u_short)~flags; 427 } 428 break; 429 430 case RESTRICT_REMOVE: 431 /* 432 * Remove an entry from the table entirely if we found one. 433 * Don't remove the default entry and don't remove an 434 * interface entry. 435 */ 436 if (rl != 0 437 && rl->addr != htonl(INADDR_ANY) 438 && !(rl->mflags & RESM_INTERFACE)) { 439 rlprev->next = rl->next; 440 restrictcount--; 441 if (rl->flags & RES_LIMITED) { 442 res_limited_refcnt--; 443 if (res_limited_refcnt == 0) 444 mon_stop(MON_RES); 445 } 446 memset((char *)rl, 0, sizeof(struct restrictlist)); 447 448 rl->next = resfree; 449 resfree = rl; 450 numresfree++; 451 } 452 break; 453 454 default: 455 /* Oh, well */ 456 break; 457 } 458 459 /* done! */ 460 } 461