1c0b746e5SOllivier Robert /* 29c2daa00SOllivier Robert * ntp_restrict.c - determine host restrictions 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" 132b15cb3dSCy Schubert #include "ntp_lists.h" 14c0b746e5SOllivier Robert #include "ntp_stdlib.h" 152b15cb3dSCy Schubert #include "ntp_assert.h" 16c0b746e5SOllivier Robert 17c0b746e5SOllivier Robert /* 18*f5f40dd6SCy Schubert * This code keeps a simple address-and-mask list of addressses we want 19*f5f40dd6SCy Schubert * to place restrictions on (or remove them from). The restrictions are 20*f5f40dd6SCy Schubert * implemented as a set of flags which tell you what matching addresses 21*f5f40dd6SCy Schubert * can't do. The list is sorted retrieve the restrictions most specific 22*f5f40dd6SCy Schubert * to the address. 23c0b746e5SOllivier Robert * 24c0b746e5SOllivier Robert * This was originally intended to restrict you from sync'ing to your 259c2daa00SOllivier Robert * own broadcasts when you are doing that, by restricting yourself from 269c2daa00SOllivier Robert * your own interfaces. It was also thought it would sometimes be useful 279c2daa00SOllivier Robert * to keep a misbehaving host or two from abusing your primary clock. It 289c2daa00SOllivier Robert * has been expanded, however, to suit the needs of those with more 299c2daa00SOllivier Robert * restrictive access policies. 30c0b746e5SOllivier Robert */ 312b15cb3dSCy Schubert #define MASK_IPV6_ADDR(dst, src, msk) \ 329c2daa00SOllivier Robert do { \ 33*f5f40dd6SCy Schubert int x; \ 34*f5f40dd6SCy Schubert \ 35*f5f40dd6SCy Schubert for (x = 0; x < (int)COUNTOF((dst)->s6_addr); x++) { \ 36*f5f40dd6SCy Schubert (dst)->s6_addr[x] = (src)->s6_addr[x] \ 37*f5f40dd6SCy Schubert & (msk)->s6_addr[x]; \ 389c2daa00SOllivier Robert } \ 39*f5f40dd6SCy Schubert } while (FALSE) 40c0b746e5SOllivier Robert 41c0b746e5SOllivier Robert /* 422b15cb3dSCy Schubert * We allocate INC_RESLIST{4|6} entries to the free list whenever empty. 43*f5f40dd6SCy Schubert * Auto-tune these to be just less than 1KB (leaving at least 32 bytes 442b15cb3dSCy Schubert * for allocator overhead). 45c0b746e5SOllivier Robert */ 46*f5f40dd6SCy Schubert #define INC_RESLIST4 ((1024 - 32) / V4_SIZEOF_RESTRICT_U) 47*f5f40dd6SCy Schubert #define INC_RESLIST6 ((1024 - 32) / V6_SIZEOF_RESTRICT_U) 489c2daa00SOllivier Robert 49c0b746e5SOllivier Robert /* 50c0b746e5SOllivier Robert * The restriction list 51c0b746e5SOllivier Robert */ 522b15cb3dSCy Schubert restrict_u *restrictlist4; 532b15cb3dSCy Schubert restrict_u *restrictlist6; 542b15cb3dSCy Schubert static int restrictcount; /* count in the restrict lists */ 55c0b746e5SOllivier Robert 56c0b746e5SOllivier Robert /* 57c0b746e5SOllivier Robert * The free list and associated counters. Also some uninteresting 58c0b746e5SOllivier Robert * stat counters. 59c0b746e5SOllivier Robert */ 602b15cb3dSCy Schubert static restrict_u *resfree4; /* available entries (free list) */ 612b15cb3dSCy Schubert static restrict_u *resfree6; 62c0b746e5SOllivier Robert 63c0b746e5SOllivier Robert static u_long res_calls; 64c0b746e5SOllivier Robert static u_long res_found; 65c0b746e5SOllivier Robert static u_long res_not_found; 66c0b746e5SOllivier Robert 67c0b746e5SOllivier Robert /* 682b15cb3dSCy Schubert * Count number of restriction entries referring to RES_LIMITED, to 692b15cb3dSCy Schubert * control implicit activation/deactivation of the MRU monlist. 709c2daa00SOllivier Robert */ 719c2daa00SOllivier Robert static u_long res_limited_refcnt; 729c2daa00SOllivier Robert 739c2daa00SOllivier Robert /* 742b15cb3dSCy Schubert * Our default entries. 7509100258SXin LI * 7609100258SXin LI * We can make this cleaner with c99 support: see init_restrict(). 77c0b746e5SOllivier Robert */ 782b15cb3dSCy Schubert static restrict_u restrict_def4; 792b15cb3dSCy Schubert static restrict_u restrict_def6; 802b15cb3dSCy Schubert 812b15cb3dSCy Schubert /* 822b15cb3dSCy Schubert * "restrict source ..." enabled knob and restriction bits. 832b15cb3dSCy Schubert */ 842b15cb3dSCy Schubert static int restrict_source_enabled; 852d4e511cSCy Schubert static u_int32 restrict_source_rflags; 862b15cb3dSCy Schubert static u_short restrict_source_mflags; 8709100258SXin LI static short restrict_source_ippeerlimit; 882b15cb3dSCy Schubert 892b15cb3dSCy Schubert /* 902b15cb3dSCy Schubert * private functions 912b15cb3dSCy Schubert */ 922b15cb3dSCy Schubert static restrict_u * alloc_res4(void); 932b15cb3dSCy Schubert static restrict_u * alloc_res6(void); 942b15cb3dSCy Schubert static void free_res(restrict_u *, int); 95*f5f40dd6SCy Schubert static inline void inc_res_limited(void); 96*f5f40dd6SCy Schubert static inline void dec_res_limited(void); 972b15cb3dSCy Schubert static restrict_u * match_restrict4_addr(u_int32, u_short); 982b15cb3dSCy Schubert static restrict_u * match_restrict6_addr(const struct in6_addr *, 992b15cb3dSCy Schubert u_short); 1002b15cb3dSCy Schubert static restrict_u * match_restrict_entry(const restrict_u *, int); 101*f5f40dd6SCy Schubert static inline int/*BOOL*/ mflags_sorts_before(u_short, u_short); 102*f5f40dd6SCy Schubert static int/*BOOL*/ res_sorts_before4(restrict_u *, restrict_u *); 103*f5f40dd6SCy Schubert static int/*BOOL*/ res_sorts_before6(restrict_u *, restrict_u *); 104*f5f40dd6SCy Schubert 105*f5f40dd6SCy Schubert typedef int (*res_sort_fn)(restrict_u *, restrict_u *); 1062b15cb3dSCy Schubert 107c0b746e5SOllivier Robert 108*f5f40dd6SCy Schubert /* dump_restrict() & dump_restricts() are DEBUG-only */ 109*f5f40dd6SCy Schubert #ifdef DEBUG 110*f5f40dd6SCy Schubert static void dump_restrict(restrict_u *, int); 111*f5f40dd6SCy Schubert 11209100258SXin LI 11309100258SXin LI /* 114*f5f40dd6SCy Schubert * dump_restrict - spit out a single restriction entry 11509100258SXin LI */ 11609100258SXin LI static void 11709100258SXin LI dump_restrict( 11809100258SXin LI restrict_u * res, 11909100258SXin LI int is_ipv6 12009100258SXin LI ) 12109100258SXin LI { 12209100258SXin LI char as[INET6_ADDRSTRLEN]; 12309100258SXin LI char ms[INET6_ADDRSTRLEN]; 12409100258SXin LI 12509100258SXin LI if (is_ipv6) { 12609100258SXin LI inet_ntop(AF_INET6, &res->u.v6.addr, as, sizeof as); 12709100258SXin LI inet_ntop(AF_INET6, &res->u.v6.mask, ms, sizeof ms); 12809100258SXin LI } else { 129*f5f40dd6SCy Schubert struct in_addr sia, sim; 13009100258SXin LI 131*f5f40dd6SCy Schubert sia.s_addr = htonl(res->u.v4.addr); 132*f5f40dd6SCy Schubert sim.s_addr = htonl(res->u.v4.addr); 13309100258SXin LI inet_ntop(AF_INET, &sia, as, sizeof as); 13409100258SXin LI inet_ntop(AF_INET, &sim, ms, sizeof ms); 13509100258SXin LI } 136*f5f40dd6SCy Schubert printf("%s/%s: hits %u ippeerlimit %hd mflags %s rflags %s", 137*f5f40dd6SCy Schubert as, ms, res->count, res->ippeerlimit, 138*f5f40dd6SCy Schubert mflags_str(res->mflags), 139*f5f40dd6SCy Schubert rflags_str(res->rflags)); 140*f5f40dd6SCy Schubert if (res->expire > 0) { 141*f5f40dd6SCy Schubert printf(" expire %u\n", res->expire); 142*f5f40dd6SCy Schubert } else { 143*f5f40dd6SCy Schubert printf("\n"); 144*f5f40dd6SCy Schubert } 14509100258SXin LI } 14609100258SXin LI 14709100258SXin LI 14809100258SXin LI /* 149*f5f40dd6SCy Schubert * dump_restricts - spit out the 'restrict' entries 15009100258SXin LI */ 15109100258SXin LI void 15209100258SXin LI dump_restricts(void) 15309100258SXin LI { 15409100258SXin LI restrict_u * res; 15509100258SXin LI 15609100258SXin LI /* Spit out the IPv4 list */ 157*f5f40dd6SCy Schubert printf("dump_restricts: restrictlist4: %p\n", restrictlist4); 158*f5f40dd6SCy Schubert for (res = restrictlist4; res != NULL; res = res->link) { 15909100258SXin LI dump_restrict(res, 0); 16009100258SXin LI } 16109100258SXin LI 16209100258SXin LI /* Spit out the IPv6 list */ 163*f5f40dd6SCy Schubert printf("dump_restricts: restrictlist6: %p\n", restrictlist6); 164*f5f40dd6SCy Schubert for (res = restrictlist6; res != NULL; res = res->link) { 16509100258SXin LI dump_restrict(res, 1); 16609100258SXin LI } 167*f5f40dd6SCy Schubert } 168*f5f40dd6SCy Schubert #endif /* DEBUG - dump_restrict() / dump_restricts() */ 16909100258SXin LI 17009100258SXin LI 171c0b746e5SOllivier Robert /* 172c0b746e5SOllivier Robert * init_restrict - initialize the restriction data structures 173c0b746e5SOllivier Robert */ 174c0b746e5SOllivier Robert void 175c0b746e5SOllivier Robert init_restrict(void) 176c0b746e5SOllivier Robert { 177c0b746e5SOllivier Robert /* 178*f5f40dd6SCy Schubert * The restriction lists end with a default entry with address 1792b15cb3dSCy Schubert * and mask 0, which will match any entry. The lists are kept 1802b15cb3dSCy Schubert * sorted by descending address followed by descending mask: 1812b15cb3dSCy Schubert * 1822b15cb3dSCy Schubert * address mask 1832b15cb3dSCy Schubert * 192.168.0.0 255.255.255.0 kod limited noquery nopeer 1842b15cb3dSCy Schubert * 192.168.0.0 255.255.0.0 kod limited 1852b15cb3dSCy Schubert * 0.0.0.0 0.0.0.0 kod limited noquery 1862b15cb3dSCy Schubert * 1872b15cb3dSCy Schubert * The first entry which matches an address is used. With the 1882b15cb3dSCy Schubert * example restrictions above, 192.168.0.0/24 matches the first 1892b15cb3dSCy Schubert * entry, the rest of 192.168.0.0/16 matches the second, and 1902b15cb3dSCy Schubert * everything else matches the third (default). 1912b15cb3dSCy Schubert * 1922b15cb3dSCy Schubert * Note this achieves the same result a little more efficiently 1932b15cb3dSCy Schubert * than the documented behavior, which is to keep the lists 1942b15cb3dSCy Schubert * sorted by ascending address followed by ascending mask, with 1952b15cb3dSCy Schubert * the _last_ matching entry used. 1962b15cb3dSCy Schubert * 1972b15cb3dSCy Schubert * An additional wrinkle is we may have multiple entries with 1982b15cb3dSCy Schubert * the same address and mask but differing match flags (mflags). 199*f5f40dd6SCy Schubert * We want to never talk to ourself, so RES_IGNORE entries for 200*f5f40dd6SCy Schubert * each local address are added by ntp_io.c with a host mask and 201*f5f40dd6SCy Schubert * both RESM_INTERFACE and RESM_NTPONLY set. We sort those 202*f5f40dd6SCy Schubert * entries before entries without those flags to achieve this. 203*f5f40dd6SCy Schubert * The remaining match flag is RESM_SOURCE, used to dynamically 204*f5f40dd6SCy Schubert * set restrictions for each peer based on the prototype set by 205*f5f40dd6SCy Schubert * "restrict source" in the configuration. We want those entries 206*f5f40dd6SCy Schubert * to be considered only when there is not a static host 207*f5f40dd6SCy Schubert * restriction for the address in the configuration, to allow 208*f5f40dd6SCy Schubert * operators to blacklist pool and manycast servers at runtime as 209*f5f40dd6SCy Schubert * desired using ntpq runtime configuration. Such static entries 210*f5f40dd6SCy Schubert * have no RESM_ bits set, so the sort order for mflags is first 211*f5f40dd6SCy Schubert * RESM_INTERFACE, then entries without RESM_SOURCE, finally the 212*f5f40dd6SCy Schubert * remaining. 213c0b746e5SOllivier Robert */ 21409100258SXin LI 21509100258SXin LI restrict_def4.ippeerlimit = -1; /* Cleaner if we have C99 */ 21609100258SXin LI restrict_def6.ippeerlimit = -1; /* Cleaner if we have C99 */ 21709100258SXin LI 2182b15cb3dSCy Schubert LINK_SLIST(restrictlist4, &restrict_def4, link); 2192b15cb3dSCy Schubert LINK_SLIST(restrictlist6, &restrict_def6, link); 2209c2daa00SOllivier Robert restrictcount = 2; 2212b15cb3dSCy Schubert } 2222b15cb3dSCy Schubert 2232b15cb3dSCy Schubert 2242b15cb3dSCy Schubert static restrict_u * 2252b15cb3dSCy Schubert alloc_res4(void) 2262b15cb3dSCy Schubert { 2272b15cb3dSCy Schubert const size_t cb = V4_SIZEOF_RESTRICT_U; 2282b15cb3dSCy Schubert const size_t count = INC_RESLIST4; 2292b15cb3dSCy Schubert restrict_u* rl; 2302b15cb3dSCy Schubert restrict_u* res; 2313311ff84SXin LI size_t i; 2322b15cb3dSCy Schubert 2332b15cb3dSCy Schubert UNLINK_HEAD_SLIST(res, resfree4, link); 234*f5f40dd6SCy Schubert if (res != NULL) { 2352b15cb3dSCy Schubert return res; 236*f5f40dd6SCy Schubert } 237f0574f5cSXin LI rl = eallocarray(count, cb); 2382b15cb3dSCy Schubert /* link all but the first onto free list */ 2392b15cb3dSCy Schubert res = (void *)((char *)rl + (count - 1) * cb); 2402b15cb3dSCy Schubert for (i = count - 1; i > 0; i--) { 2412b15cb3dSCy Schubert LINK_SLIST(resfree4, res, link); 2422b15cb3dSCy Schubert res = (void *)((char *)res - cb); 2432b15cb3dSCy Schubert } 244*f5f40dd6SCy Schubert DEBUG_INSIST(rl == res); 2452b15cb3dSCy Schubert /* allocate the first */ 2462b15cb3dSCy Schubert return res; 2472b15cb3dSCy Schubert } 2482b15cb3dSCy Schubert 2492b15cb3dSCy Schubert 2502b15cb3dSCy Schubert static restrict_u * 2512b15cb3dSCy Schubert alloc_res6(void) 2522b15cb3dSCy Schubert { 2532b15cb3dSCy Schubert const size_t cb = V6_SIZEOF_RESTRICT_U; 2542b15cb3dSCy Schubert const size_t count = INC_RESLIST6; 2552b15cb3dSCy Schubert restrict_u * rl; 2562b15cb3dSCy Schubert restrict_u * res; 2573311ff84SXin LI size_t i; 2582b15cb3dSCy Schubert 2592b15cb3dSCy Schubert UNLINK_HEAD_SLIST(res, resfree6, link); 260*f5f40dd6SCy Schubert if (res != NULL) { 2612b15cb3dSCy Schubert return res; 262*f5f40dd6SCy Schubert } 263f0574f5cSXin LI rl = eallocarray(count, cb); 2642b15cb3dSCy Schubert /* link all but the first onto free list */ 2652b15cb3dSCy Schubert res = (void *)((char *)rl + (count - 1) * cb); 2662b15cb3dSCy Schubert for (i = count - 1; i > 0; i--) { 2672b15cb3dSCy Schubert LINK_SLIST(resfree6, res, link); 2682b15cb3dSCy Schubert res = (void *)((char *)res - cb); 2692b15cb3dSCy Schubert } 270*f5f40dd6SCy Schubert DEBUG_INSIST(rl == res); 2712b15cb3dSCy Schubert /* allocate the first */ 2722b15cb3dSCy Schubert return res; 2732b15cb3dSCy Schubert } 2742b15cb3dSCy Schubert 2752b15cb3dSCy Schubert 2762b15cb3dSCy Schubert static void 2772b15cb3dSCy Schubert free_res( 2782b15cb3dSCy Schubert restrict_u * res, 2792b15cb3dSCy Schubert int v6 2802b15cb3dSCy Schubert ) 2812b15cb3dSCy Schubert { 282*f5f40dd6SCy Schubert restrict_u ** rlisthead_ptr; 283*f5f40dd6SCy Schubert restrict_u ** flisthead_ptr; 2842b15cb3dSCy Schubert restrict_u * unlinked; 285*f5f40dd6SCy Schubert size_t sz; 2862b15cb3dSCy Schubert 2872b15cb3dSCy Schubert restrictcount--; 288*f5f40dd6SCy Schubert if (RES_LIMITED & res->rflags) { 2892b15cb3dSCy Schubert dec_res_limited(); 290*f5f40dd6SCy Schubert } 2912b15cb3dSCy Schubert if (v6) { 292*f5f40dd6SCy Schubert rlisthead_ptr = &restrictlist6; 293*f5f40dd6SCy Schubert flisthead_ptr = &resfree6; 294*f5f40dd6SCy Schubert sz = V6_SIZEOF_RESTRICT_U; 2952b15cb3dSCy Schubert } else { 296*f5f40dd6SCy Schubert rlisthead_ptr = &restrictlist4; 297*f5f40dd6SCy Schubert flisthead_ptr = &resfree4; 298*f5f40dd6SCy Schubert sz = V4_SIZEOF_RESTRICT_U; 2992b15cb3dSCy Schubert } 300*f5f40dd6SCy Schubert UNLINK_SLIST(unlinked, *rlisthead_ptr, res, link, restrict_u); 301*f5f40dd6SCy Schubert INSIST(unlinked == res); 302*f5f40dd6SCy Schubert zero_mem(res, sz); 303*f5f40dd6SCy Schubert LINK_SLIST(*flisthead_ptr, res, link); 3042b15cb3dSCy Schubert } 3052b15cb3dSCy Schubert 3062b15cb3dSCy Schubert 307*f5f40dd6SCy Schubert static inline void 3082b15cb3dSCy Schubert inc_res_limited(void) 3092b15cb3dSCy Schubert { 310*f5f40dd6SCy Schubert if (0 == res_limited_refcnt) { 3112b15cb3dSCy Schubert mon_start(MON_RES); 312*f5f40dd6SCy Schubert } 3132b15cb3dSCy Schubert res_limited_refcnt++; 3142b15cb3dSCy Schubert } 3152b15cb3dSCy Schubert 3162b15cb3dSCy Schubert 317*f5f40dd6SCy Schubert static inline void 3182b15cb3dSCy Schubert dec_res_limited(void) 3192b15cb3dSCy Schubert { 3202b15cb3dSCy Schubert res_limited_refcnt--; 321*f5f40dd6SCy Schubert if (0 == res_limited_refcnt) { 3222b15cb3dSCy Schubert mon_stop(MON_RES); 3232b15cb3dSCy Schubert } 324*f5f40dd6SCy Schubert } 3252b15cb3dSCy Schubert 3262b15cb3dSCy Schubert 3272b15cb3dSCy Schubert static restrict_u * 3282b15cb3dSCy Schubert match_restrict4_addr( 3292b15cb3dSCy Schubert u_int32 addr, 3302b15cb3dSCy Schubert u_short port 3312b15cb3dSCy Schubert ) 3322b15cb3dSCy Schubert { 333*f5f40dd6SCy Schubert const int v6 = FALSE; 3342b15cb3dSCy Schubert restrict_u * res; 3352b15cb3dSCy Schubert restrict_u * next; 3362b15cb3dSCy Schubert 3372b15cb3dSCy Schubert for (res = restrictlist4; res != NULL; res = next) { 3382b15cb3dSCy Schubert next = res->link; 339*f5f40dd6SCy Schubert if (res->expire && res->expire <= current_time) { 34009100258SXin LI free_res(res, v6); /* zeroes the contents */ 341*f5f40dd6SCy Schubert } 3422b15cb3dSCy Schubert if ( res->u.v4.addr == (addr & res->u.v4.mask) 3432b15cb3dSCy Schubert && ( !(RESM_NTPONLY & res->mflags) 34409100258SXin LI || NTP_PORT == port)) { 345*f5f40dd6SCy Schubert 3462b15cb3dSCy Schubert break; 3472b15cb3dSCy Schubert } 34809100258SXin LI } 3492b15cb3dSCy Schubert return res; 3502b15cb3dSCy Schubert } 3512b15cb3dSCy Schubert 3522b15cb3dSCy Schubert 3532b15cb3dSCy Schubert static restrict_u * 3542b15cb3dSCy Schubert match_restrict6_addr( 3552b15cb3dSCy Schubert const struct in6_addr * addr, 3562b15cb3dSCy Schubert u_short port 3572b15cb3dSCy Schubert ) 3582b15cb3dSCy Schubert { 359*f5f40dd6SCy Schubert const int v6 = TRUE; 3602b15cb3dSCy Schubert restrict_u * res; 3612b15cb3dSCy Schubert restrict_u * next; 3622b15cb3dSCy Schubert struct in6_addr masked; 3632b15cb3dSCy Schubert 3642b15cb3dSCy Schubert for (res = restrictlist6; res != NULL; res = next) { 3652b15cb3dSCy Schubert next = res->link; 366*f5f40dd6SCy Schubert if (res->expire && res->expire <= current_time) { 3672b15cb3dSCy Schubert free_res(res, v6); 368*f5f40dd6SCy Schubert } 3692b15cb3dSCy Schubert MASK_IPV6_ADDR(&masked, addr, &res->u.v6.mask); 3702b15cb3dSCy Schubert if (ADDR6_EQ(&masked, &res->u.v6.addr) 3712b15cb3dSCy Schubert && ( !(RESM_NTPONLY & res->mflags) 372*f5f40dd6SCy Schubert || NTP_PORT == (int)port)) { 373*f5f40dd6SCy Schubert 3742b15cb3dSCy Schubert break; 3752b15cb3dSCy Schubert } 376*f5f40dd6SCy Schubert } 3772b15cb3dSCy Schubert return res; 3782b15cb3dSCy Schubert } 3792b15cb3dSCy Schubert 380c0b746e5SOllivier Robert 381c0b746e5SOllivier Robert /* 3822b15cb3dSCy Schubert * match_restrict_entry - find an exact match on a restrict list. 3832b15cb3dSCy Schubert * 3842b15cb3dSCy Schubert * Exact match is addr, mask, and mflags all equal. 3852b15cb3dSCy Schubert * In order to use more common code for IPv4 and IPv6, this routine 3862b15cb3dSCy Schubert * requires the caller to populate a restrict_u with mflags and either 3872b15cb3dSCy Schubert * the v4 or v6 address and mask as appropriate. Other fields in the 3882b15cb3dSCy Schubert * input restrict_u are ignored. 389c0b746e5SOllivier Robert */ 3902b15cb3dSCy Schubert static restrict_u * 3912b15cb3dSCy Schubert match_restrict_entry( 3922b15cb3dSCy Schubert const restrict_u * pmatch, 3932b15cb3dSCy Schubert int v6 3942b15cb3dSCy Schubert ) 3952b15cb3dSCy Schubert { 3962b15cb3dSCy Schubert restrict_u *res; 3972b15cb3dSCy Schubert restrict_u *rlist; 3982b15cb3dSCy Schubert size_t cb; 3992b15cb3dSCy Schubert 4002b15cb3dSCy Schubert if (v6) { 4012b15cb3dSCy Schubert rlist = restrictlist6; 4022b15cb3dSCy Schubert cb = sizeof(pmatch->u.v6); 4032b15cb3dSCy Schubert } else { 4042b15cb3dSCy Schubert rlist = restrictlist4; 4052b15cb3dSCy Schubert cb = sizeof(pmatch->u.v4); 4062b15cb3dSCy Schubert } 4072b15cb3dSCy Schubert 408*f5f40dd6SCy Schubert for (res = rlist; res != NULL; res = res->link) { 4092b15cb3dSCy Schubert if (res->mflags == pmatch->mflags && 410*f5f40dd6SCy Schubert !memcmp(&res->u, &pmatch->u, cb)) { 4112b15cb3dSCy Schubert break; 412*f5f40dd6SCy Schubert } 413*f5f40dd6SCy Schubert } 4142b15cb3dSCy Schubert return res; 4152b15cb3dSCy Schubert } 4162b15cb3dSCy Schubert 417c0b746e5SOllivier Robert 418c0b746e5SOllivier Robert /* 419*f5f40dd6SCy Schubert * mflags_sorts_before - common mflags sorting code 420*f5f40dd6SCy Schubert * 421*f5f40dd6SCy Schubert * See block comment in init_restrict() above for rationale. 422*f5f40dd6SCy Schubert */ 423*f5f40dd6SCy Schubert static inline int/*BOOL*/ 424*f5f40dd6SCy Schubert mflags_sorts_before( 425*f5f40dd6SCy Schubert u_short m1, 426*f5f40dd6SCy Schubert u_short m2 427*f5f40dd6SCy Schubert ) 428*f5f40dd6SCy Schubert { 429*f5f40dd6SCy Schubert if ( (RESM_INTERFACE & m1) 430*f5f40dd6SCy Schubert && !(RESM_INTERFACE & m2)) { 431*f5f40dd6SCy Schubert return TRUE; 432*f5f40dd6SCy Schubert } else if ( !(RESM_SOURCE & m1) 433*f5f40dd6SCy Schubert && (RESM_SOURCE & m2)) { 434*f5f40dd6SCy Schubert return TRUE; 435*f5f40dd6SCy Schubert } else { 436*f5f40dd6SCy Schubert return FALSE; 437*f5f40dd6SCy Schubert } 438*f5f40dd6SCy Schubert } 439*f5f40dd6SCy Schubert 440*f5f40dd6SCy Schubert 441*f5f40dd6SCy Schubert /* 442*f5f40dd6SCy Schubert * res_sorts_before4 - compare IPv4 restriction entries 4432b15cb3dSCy Schubert * 4442b15cb3dSCy Schubert * Returns nonzero if r1 sorts before r2. We sort by descending 445*f5f40dd6SCy Schubert * address, then descending mask, then an intricate mflags sort 446*f5f40dd6SCy Schubert * order explained in a block comment near the top of this file. 447c0b746e5SOllivier Robert */ 448*f5f40dd6SCy Schubert static int/*BOOL*/ 4492b15cb3dSCy Schubert res_sorts_before4( 4502b15cb3dSCy Schubert restrict_u *r1, 4512b15cb3dSCy Schubert restrict_u *r2 4522b15cb3dSCy Schubert ) 4532b15cb3dSCy Schubert { 4542b15cb3dSCy Schubert int r1_before_r2; 4552b15cb3dSCy Schubert 456*f5f40dd6SCy Schubert if (r1->u.v4.addr > r2->u.v4.addr) { 457*f5f40dd6SCy Schubert r1_before_r2 = TRUE; 458*f5f40dd6SCy Schubert } else if (r1->u.v4.addr < r2->u.v4.addr) { 459*f5f40dd6SCy Schubert r1_before_r2 = FALSE; 460*f5f40dd6SCy Schubert } else if (r1->u.v4.mask > r2->u.v4.mask) { 461*f5f40dd6SCy Schubert r1_before_r2 = TRUE; 462*f5f40dd6SCy Schubert } else if (r1->u.v4.mask < r2->u.v4.mask) { 463*f5f40dd6SCy Schubert r1_before_r2 = FALSE; 464*f5f40dd6SCy Schubert } else { 465*f5f40dd6SCy Schubert r1_before_r2 = mflags_sorts_before(r1->mflags, r2->mflags); 466*f5f40dd6SCy Schubert } 4672b15cb3dSCy Schubert 4682b15cb3dSCy Schubert return r1_before_r2; 4692b15cb3dSCy Schubert } 4702b15cb3dSCy Schubert 4712b15cb3dSCy Schubert 4722b15cb3dSCy Schubert /* 473*f5f40dd6SCy Schubert * res_sorts_before6 - compare IPv6 restriction entries 4742b15cb3dSCy Schubert * 4752b15cb3dSCy Schubert * Returns nonzero if r1 sorts before r2. We sort by descending 476*f5f40dd6SCy Schubert * address, then descending mask, then an intricate mflags sort 477*f5f40dd6SCy Schubert * order explained in a block comment near the top of this file. 4782b15cb3dSCy Schubert */ 479*f5f40dd6SCy Schubert static int/*BOOL*/ 4802b15cb3dSCy Schubert res_sorts_before6( 4812b15cb3dSCy Schubert restrict_u* r1, 4822b15cb3dSCy Schubert restrict_u* r2 4832b15cb3dSCy Schubert ) 4842b15cb3dSCy Schubert { 4852b15cb3dSCy Schubert int r1_before_r2; 4862b15cb3dSCy Schubert int cmp; 4872b15cb3dSCy Schubert 4882b15cb3dSCy Schubert cmp = ADDR6_CMP(&r1->u.v6.addr, &r2->u.v6.addr); 489*f5f40dd6SCy Schubert if (cmp > 0) { /* r1->addr > r2->addr */ 490*f5f40dd6SCy Schubert r1_before_r2 = TRUE; 491*f5f40dd6SCy Schubert } else if (cmp < 0) { /* r2->addr > r1->addr */ 492*f5f40dd6SCy Schubert r1_before_r2 = FALSE; 493*f5f40dd6SCy Schubert } else { 4942b15cb3dSCy Schubert cmp = ADDR6_CMP(&r1->u.v6.mask, &r2->u.v6.mask); 495*f5f40dd6SCy Schubert if (cmp > 0) { /* r1->mask > r2->mask*/ 496*f5f40dd6SCy Schubert r1_before_r2 = TRUE; 497*f5f40dd6SCy Schubert } else if (cmp < 0) { /* r2->mask > r1->mask */ 498*f5f40dd6SCy Schubert r1_before_r2 = FALSE; 499*f5f40dd6SCy Schubert } else { 500*f5f40dd6SCy Schubert r1_before_r2 = mflags_sorts_before(r1->mflags, 501*f5f40dd6SCy Schubert r2->mflags); 502*f5f40dd6SCy Schubert } 5032b15cb3dSCy Schubert } 5042b15cb3dSCy Schubert 5052b15cb3dSCy Schubert return r1_before_r2; 506c0b746e5SOllivier Robert } 507c0b746e5SOllivier Robert 508c0b746e5SOllivier Robert 509c0b746e5SOllivier Robert /* 51009100258SXin LI * restrictions - return restrictions for this host in *r4a 511c0b746e5SOllivier Robert */ 51209100258SXin LI void 513c0b746e5SOllivier Robert restrictions( 51409100258SXin LI sockaddr_u *srcadr, 51509100258SXin LI r4addr *r4a 516c0b746e5SOllivier Robert ) 517c0b746e5SOllivier Robert { 5182b15cb3dSCy Schubert restrict_u *match; 5192b15cb3dSCy Schubert struct in6_addr *pin6; 52009100258SXin LI 521*f5f40dd6SCy Schubert DEBUG_REQUIRE(NULL != r4a); 522c0b746e5SOllivier Robert 523c0b746e5SOllivier Robert res_calls++; 52409100258SXin LI 5252b15cb3dSCy Schubert if (IS_IPV4(srcadr)) { 526c0b746e5SOllivier Robert /* 527c0b746e5SOllivier Robert * Ignore any packets with a multicast source address 5289c2daa00SOllivier Robert * (this should be done early in the receive process, 5292b15cb3dSCy Schubert * not later!) 530c0b746e5SOllivier Robert */ 53109100258SXin LI if (IN_CLASSD(SRCADR(srcadr))) { 532*f5f40dd6SCy Schubert goto multicast; 53309100258SXin LI } 534c0b746e5SOllivier Robert 5352b15cb3dSCy Schubert match = match_restrict4_addr(SRCADR(srcadr), 5362b15cb3dSCy Schubert SRCPORT(srcadr)); 537*f5f40dd6SCy Schubert DEBUG_INSIST(match != NULL); 538c0b746e5SOllivier Robert match->count++; 5392b15cb3dSCy Schubert /* 5402b15cb3dSCy Schubert * res_not_found counts only use of the final default 5412b15cb3dSCy Schubert * entry, not any "restrict default ntpport ...", which 5422b15cb3dSCy Schubert * would be just before the final default. 5432b15cb3dSCy Schubert */ 5442b15cb3dSCy Schubert if (&restrict_def4 == match) 545c0b746e5SOllivier Robert res_not_found++; 546c0b746e5SOllivier Robert else 547c0b746e5SOllivier Robert res_found++; 54809100258SXin LI r4a->rflags = match->rflags; 54909100258SXin LI r4a->ippeerlimit = match->ippeerlimit; 550*f5f40dd6SCy Schubert } else { 551*f5f40dd6SCy Schubert DEBUG_REQUIRE(IS_IPV6(srcadr)); 5529c2daa00SOllivier Robert 5532b15cb3dSCy Schubert pin6 = PSOCK_ADDR6(srcadr); 554c0b746e5SOllivier Robert 555c0b746e5SOllivier Robert /* 5569c2daa00SOllivier Robert * Ignore any packets with a multicast source address 5579c2daa00SOllivier Robert * (this should be done early in the receive process, 5582b15cb3dSCy Schubert * not later!) 559c0b746e5SOllivier Robert */ 560*f5f40dd6SCy Schubert if (IN6_IS_ADDR_MULTICAST(pin6)) { 561*f5f40dd6SCy Schubert goto multicast; 562*f5f40dd6SCy Schubert } 5632b15cb3dSCy Schubert match = match_restrict6_addr(pin6, SRCPORT(srcadr)); 564*f5f40dd6SCy Schubert DEBUG_INSIST(match != NULL); 5652b15cb3dSCy Schubert match->count++; 5662b15cb3dSCy Schubert if (&restrict_def6 == match) 5679c2daa00SOllivier Robert res_not_found++; 5689c2daa00SOllivier Robert else 5699c2daa00SOllivier Robert res_found++; 57009100258SXin LI r4a->rflags = match->rflags; 57109100258SXin LI r4a->ippeerlimit = match->ippeerlimit; 572c0b746e5SOllivier Robert } 5732d4e511cSCy Schubert 57409100258SXin LI return; 575*f5f40dd6SCy Schubert 576*f5f40dd6SCy Schubert multicast: 577*f5f40dd6SCy Schubert r4a->rflags = RES_IGNORE; 578*f5f40dd6SCy Schubert r4a->ippeerlimit = 0; 57909100258SXin LI } 58009100258SXin LI 58109100258SXin LI 582*f5f40dd6SCy Schubert #ifdef DEBUG 583*f5f40dd6SCy Schubert /* display string for restrict_op */ 584*f5f40dd6SCy Schubert const char * 585*f5f40dd6SCy Schubert resop_str(restrict_op op) 586*f5f40dd6SCy Schubert { 58709100258SXin LI switch (op) { 58809100258SXin LI case RESTRICT_FLAGS: return "RESTRICT_FLAGS"; 589*f5f40dd6SCy Schubert case RESTRICT_UNFLAG: return "RESTRICT_UNFLAG"; 59009100258SXin LI case RESTRICT_REMOVE: return "RESTRICT_REMOVE"; 59109100258SXin LI case RESTRICT_REMOVEIF: return "RESTRICT_REMOVEIF"; 59209100258SXin LI } 593*f5f40dd6SCy Schubert DEBUG_INVARIANT(!"bad restrict_op in resop_str"); 594*f5f40dd6SCy Schubert return ""; /* silence not all paths return value warning */ 595c0b746e5SOllivier Robert } 596*f5f40dd6SCy Schubert #endif /* DEBUG */ 597c0b746e5SOllivier Robert 598c0b746e5SOllivier Robert 599c0b746e5SOllivier Robert /* 600c0b746e5SOllivier Robert * hack_restrict - add/subtract/manipulate entries on the restrict list 601c0b746e5SOllivier Robert */ 602*f5f40dd6SCy Schubert int/*BOOL*/ 603c0b746e5SOllivier Robert hack_restrict( 60409100258SXin LI restrict_op op, 6052b15cb3dSCy Schubert sockaddr_u * resaddr, 6062b15cb3dSCy Schubert sockaddr_u * resmask, 60709100258SXin LI short ippeerlimit, 6082b15cb3dSCy Schubert u_short mflags, 60909100258SXin LI u_short rflags, 610*f5f40dd6SCy Schubert u_int32 expire 611c0b746e5SOllivier Robert ) 612c0b746e5SOllivier Robert { 6132b15cb3dSCy Schubert int v6; 614*f5f40dd6SCy Schubert int bump_res_limited = FALSE; 6152b15cb3dSCy Schubert restrict_u match; 6162b15cb3dSCy Schubert restrict_u * res; 6172b15cb3dSCy Schubert restrict_u ** plisthead; 618*f5f40dd6SCy Schubert res_sort_fn pfn_sort; 619c0b746e5SOllivier Robert 620*f5f40dd6SCy Schubert #ifdef DEBUG 621*f5f40dd6SCy Schubert if (debug > 0) { 622*f5f40dd6SCy Schubert printf("hack_restrict: op %s addr %s mask %s", 623*f5f40dd6SCy Schubert resop_str(op), stoa(resaddr), stoa(resmask)); 624*f5f40dd6SCy Schubert if (ippeerlimit >= 0) { 625*f5f40dd6SCy Schubert printf(" ippeerlimit %d", ippeerlimit); 626*f5f40dd6SCy Schubert } 627*f5f40dd6SCy Schubert printf(" mflags %s rflags %s", mflags_str(mflags), 628*f5f40dd6SCy Schubert rflags_str(rflags)); 629*f5f40dd6SCy Schubert if (expire) { 630*f5f40dd6SCy Schubert printf("lifetime %u\n", 631*f5f40dd6SCy Schubert expire - (u_int32)current_time); 632*f5f40dd6SCy Schubert } else { 633*f5f40dd6SCy Schubert printf("\n"); 634*f5f40dd6SCy Schubert } 635*f5f40dd6SCy Schubert } 636*f5f40dd6SCy Schubert #endif 6372b15cb3dSCy Schubert 6382b15cb3dSCy Schubert if (NULL == resaddr) { 639*f5f40dd6SCy Schubert DEBUG_REQUIRE(NULL == resmask); 640*f5f40dd6SCy Schubert DEBUG_REQUIRE(RESTRICT_FLAGS == op); 641*f5f40dd6SCy Schubert DEBUG_REQUIRE(RESM_SOURCE & mflags); 64209100258SXin LI restrict_source_rflags = rflags; 6432b15cb3dSCy Schubert restrict_source_mflags = mflags; 64409100258SXin LI restrict_source_ippeerlimit = ippeerlimit; 645*f5f40dd6SCy Schubert restrict_source_enabled = TRUE; 646*f5f40dd6SCy Schubert DPRINTF(1, ("restrict source template saved\n")); 647*f5f40dd6SCy Schubert return TRUE; 6482b15cb3dSCy Schubert } 6492b15cb3dSCy Schubert 6502b15cb3dSCy Schubert ZERO(match); 6519034852cSGleb Smirnoff 6522b15cb3dSCy Schubert if (IS_IPV4(resaddr)) { 653*f5f40dd6SCy Schubert DEBUG_INVARIANT(IS_IPV4(resmask)); 654*f5f40dd6SCy Schubert v6 = FALSE; 655c0b746e5SOllivier Robert /* 6562b15cb3dSCy Schubert * Get address and mask in host byte order for easy 6572b15cb3dSCy Schubert * comparison as u_int32 658c0b746e5SOllivier Robert */ 6592b15cb3dSCy Schubert match.u.v4.addr = SRCADR(resaddr); 6602b15cb3dSCy Schubert match.u.v4.mask = SRCADR(resmask); 6612b15cb3dSCy Schubert match.u.v4.addr &= match.u.v4.mask; 662*f5f40dd6SCy Schubert } else { 663*f5f40dd6SCy Schubert DEBUG_INVARIANT(IS_IPV6(resaddr)); 664*f5f40dd6SCy Schubert DEBUG_INVARIANT(IS_IPV6(resmask)); 665*f5f40dd6SCy Schubert v6 = TRUE; 666c0b746e5SOllivier Robert /* 6672b15cb3dSCy Schubert * Get address and mask in network byte order for easy 6682b15cb3dSCy Schubert * comparison as byte sequences (e.g. memcmp()) 669c0b746e5SOllivier Robert */ 6702b15cb3dSCy Schubert match.u.v6.mask = SOCK_ADDR6(resmask); 6712b15cb3dSCy Schubert MASK_IPV6_ADDR(&match.u.v6.addr, PSOCK_ADDR6(resaddr), 6722b15cb3dSCy Schubert &match.u.v6.mask); 673*f5f40dd6SCy Schubert } 6749c2daa00SOllivier Robert 6752b15cb3dSCy Schubert match.mflags = mflags; 6762b15cb3dSCy Schubert res = match_restrict_entry(&match, v6); 6779c2daa00SOllivier Robert 678c0b746e5SOllivier Robert switch (op) { 6792b15cb3dSCy Schubert 680c0b746e5SOllivier Robert case RESTRICT_FLAGS: 681c0b746e5SOllivier Robert /* 682*f5f40dd6SCy Schubert * Here we add bits to the rflags. If we already have 683*f5f40dd6SCy Schubert * this restriction modify it. 684c0b746e5SOllivier Robert */ 685*f5f40dd6SCy Schubert if (NULL != res) { 686*f5f40dd6SCy Schubert if ( (RES_LIMITED & rflags) 687*f5f40dd6SCy Schubert && !(RES_LIMITED & res->rflags)) { 688*f5f40dd6SCy Schubert 689*f5f40dd6SCy Schubert bump_res_limited = TRUE; 690*f5f40dd6SCy Schubert } 691*f5f40dd6SCy Schubert res->rflags |= rflags; 692*f5f40dd6SCy Schubert res->expire = expire; 693*f5f40dd6SCy Schubert } else { 694*f5f40dd6SCy Schubert match.rflags = rflags; 695*f5f40dd6SCy Schubert match.expire = expire; 696*f5f40dd6SCy Schubert match.ippeerlimit = ippeerlimit; 6972b15cb3dSCy Schubert if (v6) { 6982b15cb3dSCy Schubert res = alloc_res6(); 699*f5f40dd6SCy Schubert memcpy(res, &match, V6_SIZEOF_RESTRICT_U); 7002b15cb3dSCy Schubert plisthead = &restrictlist6; 701*f5f40dd6SCy Schubert pfn_sort = &res_sorts_before6; 702ea906c41SOllivier Robert } else { 7032b15cb3dSCy Schubert res = alloc_res4(); 704*f5f40dd6SCy Schubert memcpy(res, &match, V4_SIZEOF_RESTRICT_U); 7052b15cb3dSCy Schubert plisthead = &restrictlist4; 706*f5f40dd6SCy Schubert pfn_sort = &res_sorts_before4; 707ea906c41SOllivier Robert } 7082b15cb3dSCy Schubert LINK_SORT_SLIST( 7092b15cb3dSCy Schubert *plisthead, res, 710*f5f40dd6SCy Schubert (*pfn_sort)(res, L_S_S_CUR()), 7112b15cb3dSCy Schubert link, restrict_u); 712c0b746e5SOllivier Robert restrictcount++; 713*f5f40dd6SCy Schubert if (RES_LIMITED & rflags) { 714*f5f40dd6SCy Schubert bump_res_limited = TRUE; 715c0b746e5SOllivier Robert } 716*f5f40dd6SCy Schubert } 717*f5f40dd6SCy Schubert if (bump_res_limited) { 718*f5f40dd6SCy Schubert inc_res_limited(); 719*f5f40dd6SCy Schubert } 720*f5f40dd6SCy Schubert return TRUE; 721c0b746e5SOllivier Robert 722c0b746e5SOllivier Robert case RESTRICT_UNFLAG: 723c0b746e5SOllivier Robert /* 72409100258SXin LI * Remove some bits from the rflags. If we didn't 725c0b746e5SOllivier Robert * find this one, just return. 726c0b746e5SOllivier Robert */ 727*f5f40dd6SCy Schubert if (NULL == res) { 728*f5f40dd6SCy Schubert DPRINTF(1, ("No match for %s %s removing rflags %s\n", 729*f5f40dd6SCy Schubert stoa(resaddr), stoa(resmask), 730*f5f40dd6SCy Schubert rflags_str(rflags))); 731*f5f40dd6SCy Schubert return FALSE; 732c0b746e5SOllivier Robert } 733*f5f40dd6SCy Schubert if ( (RES_LIMITED & res->rflags) 734*f5f40dd6SCy Schubert && (RES_LIMITED & rflags)) { 735*f5f40dd6SCy Schubert dec_res_limited(); 736*f5f40dd6SCy Schubert } 737*f5f40dd6SCy Schubert res->rflags &= ~rflags; 738*f5f40dd6SCy Schubert return TRUE; 739c0b746e5SOllivier Robert 740c0b746e5SOllivier Robert case RESTRICT_REMOVE: 741ea906c41SOllivier Robert case RESTRICT_REMOVEIF: 742c0b746e5SOllivier Robert /* 7439c2daa00SOllivier Robert * Remove an entry from the table entirely if we 7449c2daa00SOllivier Robert * found one. Don't remove the default entry and 745*f5f40dd6SCy Schubert * don't remove an interface entry unless asked. 746c0b746e5SOllivier Robert */ 7472b15cb3dSCy Schubert if ( res != NULL 7482b15cb3dSCy Schubert && ( RESTRICT_REMOVEIF == op 7492b15cb3dSCy Schubert || !(RESM_INTERFACE & res->mflags)) 7502b15cb3dSCy Schubert && res != &restrict_def4 751*f5f40dd6SCy Schubert && res != &restrict_def6) { 752*f5f40dd6SCy Schubert 7532b15cb3dSCy Schubert free_res(res, v6); 754*f5f40dd6SCy Schubert return TRUE; 755c0b746e5SOllivier Robert } 756*f5f40dd6SCy Schubert DPRINTF(1, ("No match removing %s %s restriction\n", 757*f5f40dd6SCy Schubert stoa(resaddr), stoa(resmask))); 758*f5f40dd6SCy Schubert return FALSE; 759*f5f40dd6SCy Schubert } 760*f5f40dd6SCy Schubert /* notreached */ 761*f5f40dd6SCy Schubert return FALSE; 7622b15cb3dSCy Schubert } 7632b15cb3dSCy Schubert 7642b15cb3dSCy Schubert 7659c2daa00SOllivier Robert /* 7662b15cb3dSCy Schubert * restrict_source - maintains dynamic "restrict source ..." entries as 7672b15cb3dSCy Schubert * peers come and go. 7689c2daa00SOllivier Robert */ 7692b15cb3dSCy Schubert void 7702b15cb3dSCy Schubert restrict_source( 7712b15cb3dSCy Schubert sockaddr_u * addr, 772*f5f40dd6SCy Schubert int farewell, /* TRUE to remove */ 773*f5f40dd6SCy Schubert u_int32 lifetime /* seconds, 0 forever */ 7742b15cb3dSCy Schubert ) 7752b15cb3dSCy Schubert { 7762b15cb3dSCy Schubert sockaddr_u onesmask; 777*f5f40dd6SCy Schubert int/*BOOL*/ success; 778c0b746e5SOllivier Robert 779*f5f40dd6SCy Schubert if ( !restrict_source_enabled || SOCK_UNSPEC(addr) 780*f5f40dd6SCy Schubert || IS_MCAST(addr) || ISREFCLOCKADR(addr)) { 7812b15cb3dSCy Schubert return; 782*f5f40dd6SCy Schubert } 7839c2daa00SOllivier Robert 7849034852cSGleb Smirnoff REQUIRE(AF_INET == AF(addr) || AF_INET6 == AF(addr)); 7852b15cb3dSCy Schubert 7862b15cb3dSCy Schubert SET_HOSTMASK(&onesmask, AF(addr)); 7872b15cb3dSCy Schubert if (farewell) { 788*f5f40dd6SCy Schubert success = hack_restrict(RESTRICT_REMOVE, addr, &onesmask, 789*f5f40dd6SCy Schubert 0, RESM_SOURCE, 0, 0); 790*f5f40dd6SCy Schubert if (success) { 791*f5f40dd6SCy Schubert DPRINTF(1, ("%s %s removed", __func__, 7922b15cb3dSCy Schubert stoa(addr))); 793*f5f40dd6SCy Schubert } else { 794*f5f40dd6SCy Schubert msyslog(LOG_ERR, "%s remove %s failed", 795*f5f40dd6SCy Schubert __func__, stoa(addr)); 796c0b746e5SOllivier Robert } 797*f5f40dd6SCy Schubert return; 798*f5f40dd6SCy Schubert } 799*f5f40dd6SCy Schubert 800*f5f40dd6SCy Schubert success = hack_restrict(RESTRICT_FLAGS, addr, &onesmask, 801*f5f40dd6SCy Schubert restrict_source_ippeerlimit, 802*f5f40dd6SCy Schubert restrict_source_mflags, 803*f5f40dd6SCy Schubert restrict_source_rflags, 804*f5f40dd6SCy Schubert lifetime > 0 805*f5f40dd6SCy Schubert ? lifetime + current_time 806*f5f40dd6SCy Schubert : 0); 807*f5f40dd6SCy Schubert if (success) { 808*f5f40dd6SCy Schubert DPRINTF(1, ("%s %s add/upd\n", __func__, 809*f5f40dd6SCy Schubert stoa(addr))); 810*f5f40dd6SCy Schubert } else { 811*f5f40dd6SCy Schubert msyslog(LOG_ERR, "%s %s failed", __func__, stoa(addr)); 812*f5f40dd6SCy Schubert } 813*f5f40dd6SCy Schubert } 814*f5f40dd6SCy Schubert 815*f5f40dd6SCy Schubert 816*f5f40dd6SCy Schubert #ifdef DEBUG 817*f5f40dd6SCy Schubert /* Convert restriction RES_ flag bits into a display string */ 818*f5f40dd6SCy Schubert const char * 819*f5f40dd6SCy Schubert rflags_str( 820*f5f40dd6SCy Schubert u_short rflags 821*f5f40dd6SCy Schubert ) 822*f5f40dd6SCy Schubert { 823*f5f40dd6SCy Schubert const size_t sz = LIB_BUFLENGTH; 824*f5f40dd6SCy Schubert char * rfs; 825*f5f40dd6SCy Schubert 826*f5f40dd6SCy Schubert LIB_GETBUF(rfs); 827*f5f40dd6SCy Schubert rfs[0] = '\0'; 828*f5f40dd6SCy Schubert 829*f5f40dd6SCy Schubert if (rflags & RES_FLAKE) { 830*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RES_FLAKE, rflags); 831*f5f40dd6SCy Schubert append_flagstr(rfs, sz, "flake"); 832*f5f40dd6SCy Schubert } 833*f5f40dd6SCy Schubert 834*f5f40dd6SCy Schubert if (rflags & RES_IGNORE) { 835*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RES_IGNORE, rflags); 836*f5f40dd6SCy Schubert append_flagstr(rfs, sz, "ignore"); 837*f5f40dd6SCy Schubert } 838*f5f40dd6SCy Schubert 839*f5f40dd6SCy Schubert if (rflags & RES_KOD) { 840*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RES_KOD, rflags); 841*f5f40dd6SCy Schubert append_flagstr(rfs, sz, "kod"); 842*f5f40dd6SCy Schubert } 843*f5f40dd6SCy Schubert 844*f5f40dd6SCy Schubert if (rflags & RES_MSSNTP) { 845*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RES_MSSNTP, rflags); 846*f5f40dd6SCy Schubert append_flagstr(rfs, sz, "mssntp"); 847*f5f40dd6SCy Schubert } 848*f5f40dd6SCy Schubert 849*f5f40dd6SCy Schubert if (rflags & RES_LIMITED) { 850*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RES_LIMITED, rflags); 851*f5f40dd6SCy Schubert append_flagstr(rfs, sz, "limited"); 852*f5f40dd6SCy Schubert } 853*f5f40dd6SCy Schubert 854*f5f40dd6SCy Schubert if (rflags & RES_LPTRAP) { 855*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RES_LPTRAP, rflags); 856*f5f40dd6SCy Schubert append_flagstr(rfs, sz, "lptrap"); 857*f5f40dd6SCy Schubert } 858*f5f40dd6SCy Schubert 859*f5f40dd6SCy Schubert if (rflags & RES_NOMODIFY) { 860*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RES_NOMODIFY, rflags); 861*f5f40dd6SCy Schubert append_flagstr(rfs, sz, "nomodify"); 862*f5f40dd6SCy Schubert } 863*f5f40dd6SCy Schubert 864*f5f40dd6SCy Schubert if (rflags & RES_NOMRULIST) { 865*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RES_NOMRULIST, rflags); 866*f5f40dd6SCy Schubert append_flagstr(rfs, sz, "nomrulist"); 867*f5f40dd6SCy Schubert } 868*f5f40dd6SCy Schubert 869*f5f40dd6SCy Schubert if (rflags & RES_NOEPEER) { 870*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RES_NOEPEER, rflags); 871*f5f40dd6SCy Schubert append_flagstr(rfs, sz, "noepeer"); 872*f5f40dd6SCy Schubert } 873*f5f40dd6SCy Schubert 874*f5f40dd6SCy Schubert if (rflags & RES_NOPEER) { 875*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RES_NOPEER, rflags); 876*f5f40dd6SCy Schubert append_flagstr(rfs, sz, "nopeer"); 877*f5f40dd6SCy Schubert } 878*f5f40dd6SCy Schubert 879*f5f40dd6SCy Schubert if (rflags & RES_NOQUERY) { 880*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RES_NOQUERY, rflags); 881*f5f40dd6SCy Schubert append_flagstr(rfs, sz, "noquery"); 882*f5f40dd6SCy Schubert } 883*f5f40dd6SCy Schubert 884*f5f40dd6SCy Schubert if (rflags & RES_DONTSERVE) { 885*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RES_DONTSERVE, rflags); 886*f5f40dd6SCy Schubert append_flagstr(rfs, sz, "dontserve"); 887*f5f40dd6SCy Schubert } 888*f5f40dd6SCy Schubert 889*f5f40dd6SCy Schubert if (rflags & RES_NOTRAP) { 890*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RES_NOTRAP, rflags); 891*f5f40dd6SCy Schubert append_flagstr(rfs, sz, "notrap"); 892*f5f40dd6SCy Schubert } 893*f5f40dd6SCy Schubert 894*f5f40dd6SCy Schubert if (rflags & RES_DONTTRUST) { 895*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RES_DONTTRUST, rflags); 896*f5f40dd6SCy Schubert append_flagstr(rfs, sz, "notrust"); 897*f5f40dd6SCy Schubert } 898*f5f40dd6SCy Schubert 899*f5f40dd6SCy Schubert if (rflags & RES_SRVRSPFUZ) { 900*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RES_SRVRSPFUZ, rflags); 901*f5f40dd6SCy Schubert append_flagstr(rfs, sz, "srvrspfuz"); 902*f5f40dd6SCy Schubert } 903*f5f40dd6SCy Schubert 904*f5f40dd6SCy Schubert if (rflags & RES_VERSION) { 905*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RES_VERSION, rflags); 906*f5f40dd6SCy Schubert append_flagstr(rfs, sz, "version"); 907*f5f40dd6SCy Schubert } 908*f5f40dd6SCy Schubert 909*f5f40dd6SCy Schubert DEBUG_INVARIANT(!rflags); 910*f5f40dd6SCy Schubert 911*f5f40dd6SCy Schubert if ('\0' == rfs[0]) { 912*f5f40dd6SCy Schubert append_flagstr(rfs, sz, "(none)"); 913*f5f40dd6SCy Schubert } 914*f5f40dd6SCy Schubert 915*f5f40dd6SCy Schubert return rfs; 916*f5f40dd6SCy Schubert } 917*f5f40dd6SCy Schubert 918*f5f40dd6SCy Schubert 919*f5f40dd6SCy Schubert /* Convert restriction match RESM_ flag bits into a display string */ 920*f5f40dd6SCy Schubert const char * 921*f5f40dd6SCy Schubert mflags_str( 922*f5f40dd6SCy Schubert u_short mflags 923*f5f40dd6SCy Schubert ) 924*f5f40dd6SCy Schubert { 925*f5f40dd6SCy Schubert const size_t sz = LIB_BUFLENGTH; 926*f5f40dd6SCy Schubert char * mfs; 927*f5f40dd6SCy Schubert 928*f5f40dd6SCy Schubert LIB_GETBUF(mfs); 929*f5f40dd6SCy Schubert mfs[0] = '\0'; 930*f5f40dd6SCy Schubert 931*f5f40dd6SCy Schubert if (mflags & RESM_NTPONLY) { 932*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RESM_NTPONLY, mflags); 933*f5f40dd6SCy Schubert append_flagstr(mfs, sz, "ntponly"); 934*f5f40dd6SCy Schubert } 935*f5f40dd6SCy Schubert 936*f5f40dd6SCy Schubert if (mflags & RESM_SOURCE) { 937*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RESM_SOURCE, mflags); 938*f5f40dd6SCy Schubert append_flagstr(mfs, sz, "source"); 939*f5f40dd6SCy Schubert } 940*f5f40dd6SCy Schubert 941*f5f40dd6SCy Schubert if (mflags & RESM_INTERFACE) { 942*f5f40dd6SCy Schubert CLEAR_BIT_IF_DEBUG(RESM_INTERFACE, mflags); 943*f5f40dd6SCy Schubert append_flagstr(mfs, sz, "interface"); 944*f5f40dd6SCy Schubert } 945*f5f40dd6SCy Schubert 946*f5f40dd6SCy Schubert DEBUG_INVARIANT(!mflags); 947*f5f40dd6SCy Schubert 948*f5f40dd6SCy Schubert return mfs; 949*f5f40dd6SCy Schubert } 950*f5f40dd6SCy Schubert #endif /* DEBUG */ 951