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