PageRenderTime 1259ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/ntp/ntpd/ntp_restrict.c

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