Compare commits
1384 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91421cb757 | ||
|
|
53792c934c | ||
|
|
df071825f2 | ||
|
|
e1791f36ea | ||
|
|
0fdf3c1f61 | ||
|
|
ee1df06aab | ||
|
|
1e87eba424 | ||
|
|
08933475ab | ||
|
|
7cbf497da4 | ||
|
|
3a610a007f | ||
|
|
48b090cb5c | ||
|
|
4139298d28 | ||
|
|
51cc10fa54 | ||
|
|
ea6cc33804 | ||
|
|
ad03967ee4 | ||
|
|
f4fd07d303 | ||
|
|
e3c08a34a7 | ||
|
|
118011fe2b | ||
|
|
af3bd07355 | ||
|
|
d68209978a | ||
|
|
47b45b2967 | ||
|
|
2b38e3823b | ||
|
|
282eab7952 | ||
|
|
c346f61535 | ||
|
|
03212e533b | ||
|
|
da8b6517de | ||
|
|
c5db8f93ec | ||
|
|
974a6d087a | ||
|
|
b758b67c37 | ||
|
|
9bafdc62b7 | ||
|
|
97f876b64c | ||
|
|
cbfbd173c4 | ||
|
|
b6f926fbef | ||
|
|
c822620967 | ||
|
|
397c0502e2 | ||
|
|
1682d15a74 | ||
|
|
dd33e98da0 | ||
|
|
c16d966ad3 | ||
|
|
1dfed16071 | ||
|
|
6f835ed6c8 | ||
|
|
9d6fd1727e | ||
|
|
8c1b6a5fd7 | ||
|
|
8dcdb33be9 | ||
|
|
aba8bbb6e3 | ||
|
|
caf4d571e6 | ||
|
|
3b6eb197a8 | ||
|
|
f3e57877ed | ||
|
|
c851c695db | ||
|
|
a3bd7e73d3 | ||
|
|
ab5ceaf74a | ||
|
|
1f2f69d4f6 | ||
|
|
f361b39dea | ||
|
|
eb1fe15ca8 | ||
|
|
45d8a2435e | ||
|
|
706d84fd10 | ||
|
|
a997ca0da0 | ||
|
|
9268b5d677 | ||
|
|
51e4eeeb04 | ||
|
|
05ff659a3c | ||
|
|
db0f488ea8 | ||
|
|
7dcca6c622 | ||
|
|
090856c7e6 | ||
|
|
cc5cc8f1e0 | ||
|
|
c488b68e75 | ||
|
|
1f1873aadd | ||
|
|
0a496f059c | ||
|
|
e27825b0ef | ||
|
|
1f60a18ea1 | ||
|
|
a0088e8364 | ||
|
|
34e26e14c5 | ||
|
|
6b17335209 | ||
|
|
07ed585c38 | ||
|
|
0669ee7a69 | ||
|
|
f84e674d8a | ||
|
|
7f0084316a | ||
|
|
a6918530ce | ||
|
|
4e72fec660 | ||
|
|
4441cf762c | ||
|
|
e83915d10d | ||
|
|
6d37924b86 | ||
|
|
f3d7974e86 | ||
|
|
734d53176f | ||
|
|
9a7be47614 | ||
|
|
26e27d0015 | ||
|
|
94b6878821 | ||
|
|
8b96552f0d | ||
|
|
ae290659de | ||
|
|
6b2b564ac3 | ||
|
|
4f7bb57e97 | ||
|
|
56f0623930 | ||
|
|
f3223fbff6 | ||
|
|
4c4f4c2649 | ||
|
|
773af304ea | ||
|
|
4cc944b0d6 | ||
|
|
87e00feb01 | ||
|
|
e7a4af8903 | ||
|
|
2d69d6146d | ||
|
|
30e4a9441e | ||
|
|
232a8f3569 | ||
|
|
1721453d51 | ||
|
|
499d8dde2b | ||
|
|
6f1cbfd000 | ||
|
|
55ecde7f1b | ||
|
|
6b54d69a85 | ||
|
|
246a31cd73 | ||
|
|
83e4b73596 | ||
|
|
6340ca734f | ||
|
|
baf553db0c | ||
|
|
486bcd5a7b | ||
|
|
be9a74d2f8 | ||
|
|
ffcbc0f011 | ||
|
|
a969ba6e2a | ||
|
|
f1781728af | ||
|
|
cd7df612b1 | ||
|
|
c1a4e257a3 | ||
|
|
4fe6744a22 | ||
|
|
3bd4c47f31 | ||
|
|
98196c4931 | ||
|
|
22cd860124 | ||
|
|
3c973ad92d | ||
|
|
faaf306a63 | ||
|
|
c7e6aea81b | ||
|
|
e541245987 | ||
|
|
84a01bee10 | ||
|
|
d1ced3ae38 | ||
|
|
a6cee69af4 | ||
|
|
0039920ab6 | ||
|
|
39d8550a80 | ||
|
|
ef3d137a64 | ||
|
|
8c707e1e37 | ||
|
|
373e917389 | ||
|
|
74f0f9a042 | ||
|
|
ed6bdb0967 | ||
|
|
c88af046b7 | ||
|
|
ae0187d454 | ||
|
|
0c50e3ddc8 | ||
|
|
075366ad6e | ||
|
|
8e8b2d6f63 | ||
|
|
087eb76140 | ||
|
|
ebedcbaeb8 | ||
|
|
0954a977c9 | ||
|
|
b77efc1948 | ||
|
|
3b0cb34710 | ||
|
|
aa6f832d61 | ||
|
|
ad9c6f06c5 | ||
|
|
a6004d7f17 | ||
|
|
c366717e66 | ||
|
|
22dee512f3 | ||
|
|
6fd5d79e73 | ||
|
|
9d6918d32c | ||
|
|
a49c5c2265 | ||
|
|
30858e3b9b | ||
|
|
30df7efc96 | ||
|
|
3e8c42cba5 | ||
|
|
62cb936cb7 | ||
|
|
39921d03ba | ||
|
|
6a0b00f0d6 | ||
|
|
51eadb692a | ||
|
|
897c113fda | ||
|
|
33e3f1029c | ||
|
|
3d4ff1ba84 | ||
|
|
24036ea507 | ||
|
|
0549c73b7e | ||
|
|
b697fbb7f1 | ||
|
|
96e063c43d | ||
|
|
4e841da1a6 | ||
|
|
09ce307bdb | ||
|
|
a3303e196e | ||
|
|
63437ffbb5 | ||
|
|
69a815aa8f | ||
|
|
1d224949cc | ||
|
|
391f708a09 | ||
|
|
cbd29e5da8 | ||
|
|
50a2841d34 | ||
|
|
9396752c11 | ||
|
|
712dadb287 | ||
|
|
32be32eab8 | ||
|
|
1649f709e7 | ||
|
|
50ca85504c | ||
|
|
4bb68866a8 | ||
|
|
2446514e71 | ||
|
|
109d0e74f1 | ||
|
|
74ea91531a | ||
|
|
9828ab115e | ||
|
|
f77700aa27 | ||
|
|
0fbd980639 | ||
|
|
43cdf1c3d0 | ||
|
|
ff19b1a97d | ||
|
|
1835343acd | ||
|
|
2aaea18f43 | ||
|
|
7ab78b937f | ||
|
|
c7be0164ce | ||
|
|
d203af4a02 | ||
|
|
05f76dab89 | ||
|
|
bf05f8ff20 | ||
|
|
09f3b2cd9c | ||
|
|
22827870fa | ||
|
|
4583dd9e42 | ||
|
|
561441320f | ||
|
|
b2a9c571eb | ||
|
|
efff74c1ae | ||
|
|
a9df0e30b0 | ||
|
|
5ce3e76fbf | ||
|
|
6ec5f5c427 | ||
|
|
5a7212c70e | ||
|
|
3a8b0f6fcc | ||
|
|
a24c31e023 | ||
|
|
f5a3679f1d | ||
|
|
5ac813cb86 | ||
|
|
a93b02e321 | ||
|
|
c77fb9d8f0 | ||
|
|
facc18f2a8 | ||
|
|
bc515b71ec | ||
|
|
7bfa26399b | ||
|
|
461b7b43b4 | ||
|
|
b1cefa57f1 | ||
|
|
ce9a9704c6 | ||
|
|
93a9a55055 | ||
|
|
44eb875a5a | ||
|
|
bc87e609c2 | ||
|
|
005c46d6f5 | ||
|
|
503c609149 | ||
|
|
60704f5e2e | ||
|
|
4e7694d710 | ||
|
|
e33b48700e | ||
|
|
ad59f278c6 | ||
|
|
16f03e7139 | ||
|
|
dc99058d83 | ||
|
|
916959c188 | ||
|
|
864913c0f3 | ||
|
|
13dee6f49e | ||
|
|
62f9c0d470 | ||
|
|
54bb3639d4 | ||
|
|
fca008d8d4 | ||
|
|
43517fcaf5 | ||
|
|
88a77a78ad | ||
|
|
3e2496fb16 | ||
|
|
05da782f8f | ||
|
|
361dfe5158 | ||
|
|
68f6312d4b | ||
|
|
730c6745f0 | ||
|
|
d42d4706bb | ||
|
|
0740e43e20 | ||
|
|
903df07bcb | ||
|
|
0ef1334d78 | ||
|
|
5eb9dde09c | ||
|
|
ae3154aca9 | ||
|
|
3ebe62d1b7 | ||
|
|
f89cae3ecf | ||
|
|
09b768efa4 | ||
|
|
a1d973f987 | ||
|
|
0682b7795c | ||
|
|
b637d7815d | ||
|
|
7ac9ae1125 | ||
|
|
c6af3a32f2 | ||
|
|
16800ea072 | ||
|
|
b5e33ae53a | ||
|
|
3c0c1111fe | ||
|
|
2675f20615 | ||
|
|
e94ad0fa01 | ||
|
|
396750cef5 | ||
|
|
6c45519e18 | ||
|
|
6d95099c56 | ||
|
|
c8328ecde8 | ||
|
|
094bfaeb4f | ||
|
|
bf4e62c19e | ||
|
|
6b1c464d6d | ||
|
|
fa78573778 | ||
|
|
cd2ddb9904 | ||
|
|
9bb3998da4 | ||
|
|
d6dce53e08 | ||
|
|
06093a9a84 | ||
|
|
1d07667ac7 | ||
|
|
591ed1e905 | ||
|
|
907efeb2dc | ||
|
|
beea62cb66 | ||
|
|
5874f3e922 | ||
|
|
04cb536f16 | ||
|
|
8ee8524016 | ||
|
|
ce7845bf54 | ||
|
|
d55f81f5fd | ||
|
|
294d36df47 | ||
|
|
f186bdcbc7 | ||
|
|
ed1bd54b5c | ||
|
|
da2cad4b14 | ||
|
|
0a4a04969d | ||
|
|
45cb8dd9be | ||
|
|
88b09aaddc | ||
|
|
fe71bba356 | ||
|
|
cbc100fc81 | ||
|
|
68bea10bbf | ||
|
|
8628cd603f | ||
|
|
ff325644c7 | ||
|
|
b97026035e | ||
|
|
69cbf78bb6 | ||
|
|
c6cdf6bbee | ||
|
|
09217a1a87 | ||
|
|
332c41e2ff | ||
|
|
2c0c36f54b | ||
|
|
d6b749af91 | ||
|
|
14ffa0770b | ||
|
|
87985855ad | ||
|
|
a2bc254bed | ||
|
|
a7b27e84fa | ||
|
|
529b030228 | ||
|
|
4caa86dd7d | ||
|
|
e1abeeeec2 | ||
|
|
40205a053e | ||
|
|
b8ac466209 | ||
|
|
d1377fa3c4 | ||
|
|
fa79466c2a | ||
|
|
a93bd4b016 | ||
|
|
407a1f3e95 | ||
|
|
4b6af5d53f | ||
|
|
7aa3f9af66 | ||
|
|
f7cf749943 | ||
|
|
aa300f7167 | ||
|
|
c7f3bd2ac8 | ||
|
|
22fe2fd038 | ||
|
|
7480aeffc8 | ||
|
|
bec366b404 | ||
|
|
e06e6e34bf | ||
|
|
832e47beab | ||
|
|
df3d54f776 | ||
|
|
22c0f4fe87 | ||
|
|
9e4cf47ee8 | ||
|
|
fdc97e1383 | ||
|
|
a18bf3149a | ||
|
|
1566bacb2c | ||
|
|
e6e751b066 | ||
|
|
8de875f0fb | ||
|
|
4ace25c5d6 | ||
|
|
1e5051228d | ||
|
|
926332a764 | ||
|
|
d05dd58de1 | ||
|
|
f7443d76f7 | ||
|
|
f344dbc622 | ||
|
|
f4d0c660ca | ||
|
|
1801a29226 | ||
|
|
92be34a407 | ||
|
|
bb58f63ce5 | ||
|
|
367341f745 | ||
|
|
eddf365284 | ||
|
|
a63b8b89e6 | ||
|
|
5757371d43 | ||
|
|
b633de9413 | ||
|
|
c49778df4a | ||
|
|
53a9173fc0 | ||
|
|
d917275e48 | ||
|
|
cc7cb0b893 | ||
|
|
ec0628c4b2 | ||
|
|
97b1d25764 | ||
|
|
33702ab1f8 | ||
|
|
11867dc28c | ||
|
|
d3a8b39c7d | ||
|
|
15379ea1f2 | ||
|
|
efef497b89 | ||
|
|
5aa5f0ff2f | ||
|
|
5bb88f0963 | ||
|
|
1d03016bbc | ||
|
|
ce5732e84f | ||
|
|
a86fdf437e | ||
|
|
3e86d316c4 | ||
|
|
d67ecac59d | ||
|
|
fa14bec83b | ||
|
|
14a4ae883d | ||
|
|
3b799c826d | ||
|
|
b40f26c019 | ||
|
|
dd4ad9ac7e | ||
|
|
2dbba34b2c | ||
|
|
c2bcd1e183 | ||
|
|
d64c81fff7 | ||
|
|
93be5b1e02 | ||
|
|
9a31b68b59 | ||
|
|
0007ee9064 | ||
|
|
67ab3285b5 | ||
|
|
41a8d9e99b | ||
|
|
90477fb794 | ||
|
|
98079ea898 | ||
|
|
4790115455 | ||
|
|
27b78d990b | ||
|
|
77607cbea0 | ||
|
|
102208df69 | ||
|
|
6de81f1250 | ||
|
|
20fd11e11a | ||
|
|
9cdcfe9f19 | ||
|
|
5e3e464ac4 | ||
|
|
3a3965ac21 | ||
|
|
a7369bef8a | ||
|
|
d2aa7dfbb6 | ||
|
|
63ec5d1264 | ||
|
|
f6381cf482 | ||
|
|
34b5d19488 | ||
|
|
d6cb7e4815 | ||
|
|
d389e0191b | ||
|
|
d3699bb6bc | ||
|
|
13480e8c2a | ||
|
|
5b3b93f80a | ||
|
|
b69e845b1c | ||
|
|
90c3822bfa | ||
|
|
c895a0626d | ||
|
|
b842bc97bb | ||
|
|
0f38fa05a6 | ||
|
|
45c5cb1f8f | ||
|
|
f6d6956261 | ||
|
|
60176c7bf4 | ||
|
|
362c9303da | ||
|
|
5e95a552ee | ||
|
|
90cb222551 | ||
|
|
850163288d | ||
|
|
e3ec6f0bd7 | ||
|
|
f7bfbdc872 | ||
|
|
4918bd5505 | ||
|
|
9bad339af8 | ||
|
|
ba4fc0f996 | ||
|
|
2fd5bc952d | ||
|
|
0ddb8769bb | ||
|
|
654f59e762 | ||
|
|
d91b1fd402 | ||
|
|
c6d82c9ba6 | ||
|
|
4d25cf89d5 | ||
|
|
24e9207e13 | ||
|
|
89130d91d6 | ||
|
|
d644b2a17d | ||
|
|
bd7bfa21c4 | ||
|
|
403de05925 | ||
|
|
46c89f2bd0 | ||
|
|
23facf0d77 | ||
|
|
549b1a478c | ||
|
|
7f8565b94c | ||
|
|
06568c6636 | ||
|
|
5d07d77e75 | ||
|
|
62018e1f72 | ||
|
|
7c0f2543a7 | ||
|
|
ca85a28241 | ||
|
|
585840b033 | ||
|
|
dec180ac00 | ||
|
|
86fa104692 | ||
|
|
b059c96dc6 | ||
|
|
a77cec8d58 | ||
|
|
64bcff1c7c | ||
|
|
2ed162ac20 | ||
|
|
e66b4dff3c | ||
|
|
8efd731cc4 | ||
|
|
a5ae1f8587 | ||
|
|
b8f16556d3 | ||
|
|
cbe379ad6b | ||
|
|
338b340be9 | ||
|
|
a006eb7e14 | ||
|
|
554b580e97 | ||
|
|
0df29f5e23 | ||
|
|
b4c0f092d8 | ||
|
|
78c6184752 | ||
|
|
38440b204d | ||
|
|
ad4a8ff7d9 | ||
|
|
04b0ac0537 | ||
|
|
982faf4024 | ||
|
|
fe3992f9fa | ||
|
|
7aa970e2c7 | ||
|
|
30d0879ed5 | ||
|
|
fd6ad9e481 | ||
|
|
794fccca7f | ||
|
|
394ff492da | ||
|
|
1e153945de | ||
|
|
0b8a5a30a7 | ||
|
|
150162bc37 | ||
|
|
8805283088 | ||
|
|
65c7212000 | ||
|
|
979fe86bc8 | ||
|
|
ff841ebf5a | ||
|
|
360f2513ab | ||
|
|
4c960fa90a | ||
|
|
9003b50b13 | ||
|
|
f6e62e2af9 | ||
|
|
47b9ac59c7 | ||
|
|
0705a7e2d5 | ||
|
|
28b879ac47 | ||
|
|
caeea190f1 | ||
|
|
8ff70de618 | ||
|
|
ee4d1cea92 | ||
|
|
f4f400776b | ||
|
|
b467a454b4 | ||
|
|
efb8b5566a | ||
|
|
f9c863708c | ||
|
|
2941d3ac89 | ||
|
|
d36b732c4c | ||
|
|
d2c5458e31 | ||
|
|
8d8a54ec79 | ||
|
|
1062667618 | ||
|
|
6ef15b34ca | ||
|
|
3d04f46334 | ||
|
|
aff3396280 | ||
|
|
70d1873dd9 | ||
|
|
0491805d2f | ||
|
|
61b838dd57 | ||
|
|
fbf01f7046 | ||
|
|
5f4dc5c6ca | ||
|
|
2ae195f5a7 | ||
|
|
393415597c | ||
|
|
ae4624bf46 | ||
|
|
5e321739db | ||
|
|
9f79ee4ae3 | ||
|
|
28de38768e | ||
|
|
25cf5e373e | ||
|
|
424c4a8a53 | ||
|
|
97e618a0e3 | ||
|
|
d8dbd903d0 | ||
|
|
81c538efce | ||
|
|
d310ab7ecb | ||
|
|
0b1008d367 | ||
|
|
32fc6dbe03 | ||
|
|
83d2ed09fc | ||
|
|
fbc5205702 | ||
|
|
cbc6524234 | ||
|
|
094b5c3d90 | ||
|
|
3267804598 | ||
|
|
476693678e | ||
|
|
bd9520b7ad | ||
|
|
3ad3f3bbd4 | ||
|
|
ad946d555d | ||
|
|
800c5cc1e7 | ||
|
|
857973e6f7 | ||
|
|
9c448c8018 | ||
|
|
193de4abf5 | ||
|
|
98906275a0 | ||
|
|
b9ff5c8f43 | ||
|
|
3d9d2dd001 | ||
|
|
17b475912f | ||
|
|
e9828b6f66 | ||
|
|
72eba2bffc | ||
|
|
6ac3bc0452 | ||
|
|
00cd9d5519 | ||
|
|
f2658275b2 | ||
|
|
25e27235dd | ||
|
|
bf2db4b084 | ||
|
|
5782649ad9 | ||
|
|
288df49c96 | ||
|
|
10cfc0ddb3 | ||
|
|
15b1b7e9c3 | ||
|
|
00c0f69aa5 | ||
|
|
51943369e3 | ||
|
|
2d75f2e4a5 | ||
|
|
976afc93e4 | ||
|
|
7f68f82146 | ||
|
|
85900a246c | ||
|
|
b4f971a081 | ||
|
|
3e1551a1de | ||
|
|
af292dae6d | ||
|
|
933878f2c8 | ||
|
|
d54409dcd3 | ||
|
|
5bf50af2d0 | ||
|
|
c43b8a6326 | ||
|
|
b06900d1a3 | ||
|
|
f2f02fc3fb | ||
|
|
aaeea9f6ed | ||
|
|
2bb6f7735f | ||
|
|
40766e55e8 | ||
|
|
b5ea1cc255 | ||
|
|
6d8e8ac0fa | ||
|
|
24b167ada8 | ||
|
|
993f8cbb1b | ||
|
|
47a9516980 | ||
|
|
dc8a1b1bcf | ||
|
|
cdb755c5f1 | ||
|
|
063efb330a | ||
|
|
70772c9091 | ||
|
|
10d8540f62 | ||
|
|
006c162382 | ||
|
|
6799a46605 | ||
|
|
c4638f9e66 | ||
|
|
4b34f5d22f | ||
|
|
a0358e5ddb | ||
|
|
a03f8d4c37 | ||
|
|
c4a0937683 | ||
|
|
2f4c4b6076 | ||
|
|
a008a843cf | ||
|
|
d92c53e700 | ||
|
|
a754e1d7b2 | ||
|
|
8e9ffba66e | ||
|
|
15a97ad6fb | ||
|
|
91f4a5e4b5 | ||
|
|
0fa7e62947 | ||
|
|
62f992f06c | ||
|
|
a23949d44d | ||
|
|
b692f23466 | ||
|
|
8aa999ef69 | ||
|
|
20b215f293 | ||
|
|
e6096e643a | ||
|
|
8938ae05ac | ||
|
|
9d1b22aac2 | ||
|
|
1fc02680af | ||
|
|
4872aa747b | ||
|
|
7ea3d3fdca | ||
|
|
50f86ce8e4 | ||
|
|
7e22cf28f8 | ||
|
|
3b1b3e9d50 | ||
|
|
ab72091de2 | ||
|
|
66f57867d8 | ||
|
|
6375838445 | ||
|
|
82a14af5e7 | ||
|
|
97dce08ed7 | ||
|
|
198d940af6 | ||
|
|
1d7e0a36e3 | ||
|
|
10068600f8 | ||
|
|
b7639d5815 | ||
|
|
49752b90d5 | ||
|
|
e98bd52e25 | ||
|
|
8a8bbad0cf | ||
|
|
fec216df32 | ||
|
|
4e1fe44428 | ||
|
|
51967f9807 | ||
|
|
b37f8b99ae | ||
|
|
fc2833f172 | ||
|
|
490f90758d | ||
|
|
56618c31f6 | ||
|
|
604f7598c2 | ||
|
|
2a7a2b84ec | ||
|
|
3e21a1a6fa | ||
|
|
2b29191e7c | ||
|
|
03431d6373 | ||
|
|
cc1a29e250 | ||
|
|
e62e9b6187 | ||
|
|
19c51cfa49 | ||
|
|
d5082158ee | ||
|
|
3f7483e816 | ||
|
|
0c8584eabc | ||
|
|
f00690f93e | ||
|
|
89b12ed35b | ||
|
|
1a9a3489ec | ||
|
|
c8a80487cd | ||
|
|
4ea8e80dd9 | ||
|
|
c07d30dcb1 | ||
|
|
d588ab54d4 | ||
|
|
f8b422a7b6 | ||
|
|
29fe922b14 | ||
|
|
8707019237 | ||
|
|
d1fbb77e0f | ||
|
|
1fbe4d2f5f | ||
|
|
0575610fa1 | ||
|
|
e3f1455850 | ||
|
|
bd9b3cf55b | ||
|
|
14db4212ab | ||
|
|
00a5b5d477 | ||
|
|
b8eac19177 | ||
|
|
b47b04c846 | ||
|
|
613ad15d02 | ||
|
|
24187530fb | ||
|
|
a857daa351 | ||
|
|
f01d7be6c6 | ||
|
|
d387380a25 | ||
|
|
f2e4c277c4 | ||
|
|
5107ace14a | ||
|
|
7b1eae4f50 | ||
|
|
c152dc8492 | ||
|
|
7bcca0060f | ||
|
|
d68c2ca2b7 | ||
|
|
de73a497ca | ||
|
|
e3ec15af10 | ||
|
|
dac74312da | ||
|
|
2ecd9bd5c0 | ||
|
|
a0ab18f6eb | ||
|
|
ebe95a831f | ||
|
|
ee4158678a | ||
|
|
83349b8aa4 | ||
|
|
7fa836e105 | ||
|
|
1633e30834 | ||
|
|
c8ca33f810 | ||
|
|
e243c072b5 | ||
|
|
da4f372271 | ||
|
|
610e782a29 | ||
|
|
854cf26907 | ||
|
|
bb201c211a | ||
|
|
12fae49fff | ||
|
|
fd372273bd | ||
|
|
b98d22c191 | ||
|
|
160f6507c3 | ||
|
|
613d6c5249 | ||
|
|
81a883fda3 | ||
|
|
40b695c1f1 | ||
|
|
5f938534a9 | ||
|
|
8d718cbb3e | ||
|
|
f6a2b79310 | ||
|
|
82e3f45a9f | ||
|
|
072e81b3c5 | ||
|
|
1d97ac4fd2 | ||
|
|
db73746620 | ||
|
|
97bc798b05 | ||
|
|
edc231bc58 | ||
|
|
b85e092e23 | ||
|
|
583043f527 | ||
|
|
8f6213cce9 | ||
|
|
00ec693db8 | ||
|
|
70b4a818ef | ||
|
|
7c28612a59 | ||
|
|
6f4681034e | ||
|
|
6938f3476e | ||
|
|
17fb9ea763 | ||
|
|
7d23a66ff0 | ||
|
|
703c7ff429 | ||
|
|
8a9be9e493 | ||
|
|
c92f0083a2 | ||
|
|
b5dbfd142a | ||
|
|
cbf13a2a6d | ||
|
|
5b3bf92101 | ||
|
|
0744ca66ad | ||
|
|
2d33bda2e6 | ||
|
|
32f90c0fad | ||
|
|
bce6e1bc6d | ||
|
|
824202ef54 | ||
|
|
9ebfca1e84 | ||
|
|
6429e421b3 | ||
|
|
c9bfa948c3 | ||
|
|
e7829aefd8 | ||
|
|
51ea3ca254 | ||
|
|
57ab36e77d | ||
|
|
dd0e0a3995 | ||
|
|
6fd6dacb39 | ||
|
|
39048ad10b | ||
|
|
979cdf9b64 | ||
|
|
dbf721235b | ||
|
|
c979fa04a4 | ||
|
|
c5f4ec7d23 | ||
|
|
5d3b87a484 | ||
|
|
72ae2f3d56 | ||
|
|
6c0cb858c1 | ||
|
|
e0c0ad3b5e | ||
|
|
4619d94622 | ||
|
|
0975a58e9b | ||
|
|
a25720a34a | ||
|
|
cc111e0bab | ||
|
|
86bec2d399 | ||
|
|
a59ff5f3df | ||
|
|
c3a04081ff | ||
|
|
ae76242fdf | ||
|
|
4f04476e3b | ||
|
|
1486a9c7f2 | ||
|
|
5ada888507 | ||
|
|
5f8e58f49b | ||
|
|
b8071a849a | ||
|
|
b6e9e7c32d | ||
|
|
0435d041ea | ||
|
|
795501bc86 | ||
|
|
c2207688c0 | ||
|
|
98c098bfc7 | ||
|
|
c47e3ba446 | ||
|
|
f1668d2786 | ||
|
|
7d7b7b31e5 | ||
|
|
3ddacb86e9 | ||
|
|
60b68069cf | ||
|
|
871417d45d | ||
|
|
65d1e3bb9b | ||
|
|
0fc2f31368 | ||
|
|
c3e0b9b6e7 | ||
|
|
6ea1f23b3f | ||
|
|
963c380d13 | ||
|
|
00238fb019 | ||
|
|
74e6b52011 | ||
|
|
875b8160f6 | ||
|
|
76ff440ebe | ||
|
|
8db957dfbf | ||
|
|
9d633048fe | ||
|
|
a9b55837dc | ||
|
|
c352dd8f1a | ||
|
|
3a2371527f | ||
|
|
1ee9be4c3f | ||
|
|
56ad6c9be1 | ||
|
|
fa04c83d86 | ||
|
|
4c82efc5ac | ||
|
|
5f45d6a715 | ||
|
|
2329bef5ba | ||
|
|
62ab3ccd3d | ||
|
|
71aaa5a791 | ||
|
|
08619211f8 | ||
|
|
3dffbc3ebf | ||
|
|
0d6eb134f5 | ||
|
|
50db3492e2 | ||
|
|
3b19596122 | ||
|
|
d082faf3e4 | ||
|
|
99e8891f85 | ||
|
|
532066ee2d | ||
|
|
254390644a | ||
|
|
241fa9c6c8 | ||
|
|
e142a83296 | ||
|
|
f7029f5c08 | ||
|
|
c50f25a3ea | ||
|
|
65c9b48921 | ||
|
|
f25e6c6d33 | ||
|
|
587ad4f271 | ||
|
|
4452292064 | ||
|
|
e597dba7ec | ||
|
|
dd9d9ce54c | ||
|
|
06e54b823e | ||
|
|
32b4e4cb7c | ||
|
|
376d48c7f1 | ||
|
|
6586e8352a | ||
|
|
3511a92869 | ||
|
|
44de649e5c | ||
|
|
29c122af83 | ||
|
|
6dbdc972c4 | ||
|
|
7b174c250d | ||
|
|
50d7f721ee | ||
|
|
5a4120dbfb | ||
|
|
eec5c1e21c | ||
|
|
1f776a4aa2 | ||
|
|
227ddad9b5 | ||
|
|
a9bf81ad91 | ||
|
|
6008bdbbc1 | ||
|
|
93bafe619d | ||
|
|
8ab91e9f7f | ||
|
|
5731050062 | ||
|
|
fb63dd1345 | ||
|
|
5f8002fcd7 | ||
|
|
19b1689161 | ||
|
|
b485ed97aa | ||
|
|
53c4c5c859 | ||
|
|
dc27e148a1 | ||
|
|
45cca58592 | ||
|
|
e136725c5b | ||
|
|
486479e943 | ||
|
|
3bb51da835 | ||
|
|
806cf78797 | ||
|
|
3b3f441189 | ||
|
|
24b5a5d50b | ||
|
|
d56a604a96 | ||
|
|
8c0b73d3a8 | ||
|
|
6bd3a09fb8 | ||
|
|
f65b0e546b | ||
|
|
8584c502d3 | ||
|
|
c3edf383ff | ||
|
|
c4cd95df68 | ||
|
|
ed4c0767b1 | ||
|
|
043c271f8a | ||
|
|
d4da20f064 | ||
|
|
903650af67 | ||
|
|
ef1d7425e3 | ||
|
|
1d1c795601 | ||
|
|
889d8a156f | ||
|
|
b7f666ff09 | ||
|
|
e4e9b342a7 | ||
|
|
d5c35a59b0 | ||
|
|
2f9fd1dcc5 | ||
|
|
8f3194f7ac | ||
|
|
10bd29265b | ||
|
|
42b44a591b | ||
|
|
a810559b24 | ||
|
|
861c89141a | ||
|
|
8939c95fd6 | ||
|
|
408c368fa5 | ||
|
|
b5d9a362b4 | ||
|
|
f1af2bb485 | ||
|
|
1b55190d3f | ||
|
|
f373a15b62 | ||
|
|
91543f4831 | ||
|
|
d81b42d067 | ||
|
|
724789de13 | ||
|
|
8f51a29137 | ||
|
|
c845f6eda5 | ||
|
|
89500e31f1 | ||
|
|
c8f2dd8b53 | ||
|
|
ceae52df15 | ||
|
|
c2d8d3ffc4 | ||
|
|
aa985beeef | ||
|
|
65e7912d31 | ||
|
|
02ed24d351 | ||
|
|
6acef73052 | ||
|
|
10ae7b50f2 | ||
|
|
831b5ba12b | ||
|
|
0932f9c08b | ||
|
|
397542b213 | ||
|
|
0c38719fe0 | ||
|
|
ff7eea27e7 | ||
|
|
687bac22db | ||
|
|
8d41ebd8a3 | ||
|
|
4631dbf68c | ||
|
|
4f9aefc753 | ||
|
|
4b5287005f | ||
|
|
5c32841934 | ||
|
|
ccd1d32c3a | ||
|
|
75ffc9bf15 | ||
|
|
3af1ea8cbc | ||
|
|
1f0dc5835b | ||
|
|
ed1fc98595 | ||
|
|
b58fb39f24 | ||
|
|
0304d28f7e | ||
|
|
f5adbb90a1 | ||
|
|
32b826e2a0 | ||
|
|
0937692dc6 | ||
|
|
785ee80b93 | ||
|
|
f119ed382e | ||
|
|
da23c4f960 | ||
|
|
4885d57c58 | ||
|
|
0db0e0c216 | ||
|
|
ec2962eacb | ||
|
|
0ca895f585 | ||
|
|
6299ffbe60 | ||
|
|
7f0485cf53 | ||
|
|
02bff4f109 | ||
|
|
d1ca25ca7e | ||
|
|
23c2176681 | ||
|
|
e83297d0f6 | ||
|
|
41de7442d2 | ||
|
|
0852d76b58 | ||
|
|
a55ce08cc0 | ||
|
|
dd090561bf | ||
|
|
28f04fd647 | ||
|
|
50a96b62f1 | ||
|
|
00b963ab72 | ||
|
|
79333a2498 | ||
|
|
32f82c62c8 | ||
|
|
4e076d746f | ||
|
|
13e435ebca | ||
|
|
4b0eecbb44 | ||
|
|
0360a524df | ||
|
|
262ac85107 | ||
|
|
4c70046d93 | ||
|
|
458824dcb4 | ||
|
|
a7338645d7 | ||
|
|
776fd04754 | ||
|
|
20bccd499f | ||
|
|
708bcd2dd3 | ||
|
|
d0edff7d6e | ||
|
|
ccca70cb33 | ||
|
|
0d829ebc69 | ||
|
|
4137b84e4e | ||
|
|
e6c2a670fe | ||
|
|
47f99dd2b3 | ||
|
|
6759b99e28 | ||
|
|
3471f18130 | ||
|
|
2ef843dd16 | ||
|
|
ce2a0f5a6a | ||
|
|
adca3e9c4b | ||
|
|
366dfcb907 | ||
|
|
28c625572b | ||
|
|
02f9b76418 | ||
|
|
ba8badd6df | ||
|
|
0decc869ae | ||
|
|
b573aebc09 | ||
|
|
d31d057aa3 | ||
|
|
6445c8ed73 | ||
|
|
382e38f494 | ||
|
|
9940aba9f6 | ||
|
|
7e846b9858 | ||
|
|
d322de0613 | ||
|
|
b98f771519 | ||
|
|
c7a93f6e4e | ||
|
|
970ce22b68 | ||
|
|
e292e93d35 | ||
|
|
fa164d459f | ||
|
|
f53c79c01b | ||
|
|
7dbe193bee | ||
|
|
a669f012dd | ||
|
|
237724c0c7 | ||
|
|
53f84c7f62 | ||
|
|
6692a1a53f | ||
|
|
a37cd7aaf5 | ||
|
|
e4cdbbf521 | ||
|
|
4568a6f842 | ||
|
|
5c72bb9e33 | ||
|
|
8c3bdb4ffc | ||
|
|
ffbad34b31 | ||
|
|
f086d39641 | ||
|
|
cc4baaab0d | ||
|
|
66409193dc | ||
|
|
2937f8a040 | ||
|
|
edf0bde0c6 | ||
|
|
8d03046269 | ||
|
|
9f48ffa1e8 | ||
|
|
871d4562f1 | ||
|
|
0f371f9e1a | ||
|
|
6bd109aa2f | ||
|
|
f7a40ec650 | ||
|
|
ff1b41dc57 | ||
|
|
fc4c4fda05 | ||
|
|
ef1a94abaa | ||
|
|
d9fb0be8c7 | ||
|
|
3f3adae6bc | ||
|
|
1ecbaaa382 | ||
|
|
d859ca2f9b | ||
|
|
3953dcc7f2 | ||
|
|
625ac28c61 | ||
|
|
b4b9308079 | ||
|
|
e2ba0df2d4 | ||
|
|
921360ce62 | ||
|
|
429805dbbc | ||
|
|
0da5e8979b | ||
|
|
baa80ae512 | ||
|
|
3e8ed78bf1 | ||
|
|
48493329d6 | ||
|
|
76dd75de77 | ||
|
|
63fd27e35f | ||
|
|
115ac3e4d7 | ||
|
|
cfcad42ff1 | ||
|
|
3f2873d42c | ||
|
|
ab915f837c | ||
|
|
ddd9a6b499 | ||
|
|
7abb69b5dc | ||
|
|
d5052fb24f | ||
|
|
b5a7ff42bb | ||
|
|
48fd1c4dd6 | ||
|
|
2bb73af7d1 | ||
|
|
86e92f9983 | ||
|
|
1c10b9de11 | ||
|
|
a66d36ea11 | ||
|
|
aa63a21ce0 | ||
|
|
797a7afba4 | ||
|
|
4b5ea12e90 | ||
|
|
2b6390fdc9 | ||
|
|
bd08ae67f9 | ||
|
|
4582c0efe7 | ||
|
|
834f36fe6d | ||
|
|
6f130def07 | ||
|
|
3931a7bd85 | ||
|
|
d9ee9c0872 | ||
|
|
0b0a73c1c9 | ||
|
|
81925ab73a | ||
|
|
9de1aa9b7f | ||
|
|
6f9aaa93e9 | ||
|
|
7e5664bdbc | ||
|
|
83f28bef6c | ||
|
|
96c727fda6 | ||
|
|
49dc570a72 | ||
|
|
cd1e04a234 | ||
|
|
27cb314e54 | ||
|
|
56a1142f03 | ||
|
|
5b37aa8c19 | ||
|
|
8ac9787350 | ||
|
|
9f9bd08af8 | ||
|
|
4c985dac39 | ||
|
|
3d77c0460d | ||
|
|
3ddad24608 | ||
|
|
6e37ab595c | ||
|
|
a1a79edaea | ||
|
|
49333cbdbe | ||
|
|
de92b479d9 | ||
|
|
0f128eb58c | ||
|
|
c630924d66 | ||
|
|
ff59fc82b3 | ||
|
|
52a1ae72f0 | ||
|
|
3a654c506f | ||
|
|
2763d4b51a | ||
|
|
e28836bf45 | ||
|
|
a6ebfacf7b | ||
|
|
c7961075c4 | ||
|
|
ab6ede7e04 | ||
|
|
b3538f1100 | ||
|
|
3b323bda58 | ||
|
|
13d86c7372 | ||
|
|
208fb610a6 | ||
|
|
4038ae2005 | ||
|
|
dd1721c799 | ||
|
|
a21e27bc99 | ||
|
|
b0ff858e78 | ||
|
|
54dae552b1 | ||
|
|
25c4198f7c | ||
|
|
4ead40cf67 | ||
|
|
04a0612e8a | ||
|
|
aa608c84b4 | ||
|
|
38365ff040 | ||
|
|
9c4270bcd9 | ||
|
|
46b066565e | ||
|
|
4dc9c657ad | ||
|
|
39595cfe31 | ||
|
|
ffa3d7d6a2 | ||
|
|
aa67fe7a8c | ||
|
|
bb2509fd2c | ||
|
|
61744359de | ||
|
|
095f62551f | ||
|
|
e25db1f273 | ||
|
|
79cb46c0e9 | ||
|
|
22ce550e53 | ||
|
|
30393100c1 | ||
|
|
459380965a | ||
|
|
21bac1bccd | ||
|
|
b1a1b6def5 | ||
|
|
baeb3adf21 | ||
|
|
39f6a04ca4 | ||
|
|
37c9ccebd1 | ||
|
|
71c73ac17c | ||
|
|
c6cb7407b3 | ||
|
|
333b2ceb97 | ||
|
|
b456b9fdfe | ||
|
|
34d0a36a1d | ||
|
|
355736f36f | ||
|
|
771287be11 | ||
|
|
dc9476b670 | ||
|
|
1e14cc0f48 | ||
|
|
55b548ae2b | ||
|
|
3b43646a08 | ||
|
|
3bc0d932d0 | ||
|
|
60225f4e75 | ||
|
|
1962446269 | ||
|
|
be37986a0f | ||
|
|
d7346a1e8c | ||
|
|
87d346f6a7 | ||
|
|
f0dd7f807d | ||
|
|
0c0502426f | ||
|
|
7f035f58c6 | ||
|
|
81e84f8dac | ||
|
|
55b42f6de3 | ||
|
|
ed8b68ad06 | ||
|
|
bad7b875eb | ||
|
|
5d162f20a9 | ||
|
|
9d29949440 | ||
|
|
1b75c1e61f | ||
|
|
293fd0f700 | ||
|
|
c1be917782 | ||
|
|
bb86e858b6 | ||
|
|
8445f5d2e2 | ||
|
|
72c9c3b11b | ||
|
|
6e3dba3fde | ||
|
|
7558ecd9ac | ||
|
|
1f776932a1 | ||
|
|
4820dce97a | ||
|
|
f8abe0c566 | ||
|
|
9def963c65 | ||
|
|
990123a937 | ||
|
|
1d6c639310 | ||
|
|
429798fd08 | ||
|
|
b5a8dd1dec | ||
|
|
95a0bd3701 | ||
|
|
8ff556739e | ||
|
|
496787677e | ||
|
|
e1ff419cf9 | ||
|
|
ee86ce68fc | ||
|
|
b75e936372 | ||
|
|
aa79235194 | ||
|
|
7c305be1bd | ||
|
|
f7fe362721 | ||
|
|
36bec089f7 | ||
|
|
45dd1fece4 | ||
|
|
29d28dda95 | ||
|
|
421594f83d | ||
|
|
d89fb4ed4f | ||
|
|
295a54eed3 | ||
|
|
5c0bd5b112 | ||
|
|
86e3b9a026 | ||
|
|
2f38141f43 | ||
|
|
8273ea5a19 | ||
|
|
4f7b304f53 | ||
|
|
8e4b87918f | ||
|
|
83b2198e86 | ||
|
|
d1a5975f9b | ||
|
|
52002051ad | ||
|
|
b191a77901 | ||
|
|
23780dd577 | ||
|
|
d1e9a582ad | ||
|
|
819ff4dd0f | ||
|
|
de604c18a0 | ||
|
|
be6cfb42ab | ||
|
|
2022310f95 | ||
|
|
657ed09693 | ||
|
|
c99df938d7 | ||
|
|
cf568a3726 | ||
|
|
e4807d8bb2 | ||
|
|
35239a302a | ||
|
|
db3946c358 | ||
|
|
0d28af84d0 | ||
|
|
42698cb7ab | ||
|
|
1d860415f2 | ||
|
|
289a253569 | ||
|
|
faafb3f7b7 | ||
|
|
2b127a1eab | ||
|
|
dfb23b3f77 | ||
|
|
b269221c00 | ||
|
|
8b46061e73 | ||
|
|
4d0f5b4c44 | ||
|
|
1dedeb87cc | ||
|
|
79cfefd856 | ||
|
|
0c0d4793ac | ||
|
|
12d71ed28c | ||
|
|
9fed0f71c2 | ||
|
|
2e34ac1403 | ||
|
|
bc54ae392b | ||
|
|
00acd06340 | ||
|
|
476e4a03c1 | ||
|
|
5f11b3e5e0 | ||
|
|
3169daad46 | ||
|
|
fd05f12790 | ||
|
|
ad094275b0 | ||
|
|
c740e4f342 | ||
|
|
132255b5da | ||
|
|
c4c0488ac6 | ||
|
|
a2ce6fcc91 | ||
|
|
12090548d2 | ||
|
|
8223cb15e7 | ||
|
|
4ba9b38cc5 | ||
|
|
42243214b5 | ||
|
|
23245c0cb2 | ||
|
|
b271446f82 | ||
|
|
611ebc5f1e | ||
|
|
be0f45cdbc | ||
|
|
9b40cbf587 | ||
|
|
c4a7f90ebb | ||
|
|
9609baee41 | ||
|
|
395eb71931 | ||
|
|
8bc4cecee6 | ||
|
|
6b617c0d15 | ||
|
|
55d290a3bf | ||
|
|
e17b4b3871 | ||
|
|
236e072cab | ||
|
|
05ff1ed7cc | ||
|
|
2b5bae9a8f | ||
|
|
39f1b8e73d | ||
|
|
af576b56c2 | ||
|
|
54dd393f39 | ||
|
|
4ce4f3779b | ||
|
|
8b3ae2fd43 | ||
|
|
ed55cb66e6 | ||
|
|
2cd9a0de1f | ||
|
|
c514ab9907 | ||
|
|
078a630bba | ||
|
|
43c271b07c | ||
|
|
24ce681e51 | ||
|
|
5ae34bf3c8 | ||
|
|
51931b888a | ||
|
|
9f7f3b1216 | ||
|
|
97c83bb05b | ||
|
|
8767ceecd4 | ||
|
|
18c63eff8f | ||
|
|
c64b7f6a78 | ||
|
|
068b4b51e3 | ||
|
|
919dd7cf14 | ||
|
|
f632e56793 | ||
|
|
2021c66251 | ||
|
|
8358e0f4b2 | ||
|
|
7f61b3ad59 | ||
|
|
a9ab732e35 | ||
|
|
11263a462c | ||
|
|
231d061b45 | ||
|
|
cdbee9a40b | ||
|
|
7b4ad2eb34 | ||
|
|
19d69be220 | ||
|
|
04363607aa | ||
|
|
dcffad2a86 | ||
|
|
6a69ab5ebd | ||
|
|
fc92ead0dd | ||
|
|
61ce600b20 | ||
|
|
7a14dfebbb | ||
|
|
42fb8153ba | ||
|
|
6f13e53886 | ||
|
|
d1c759c5c1 | ||
|
|
e46164e0bd | ||
|
|
7389ce7ff5 | ||
|
|
2f77797b17 | ||
|
|
9380ba70d6 | ||
|
|
1023dcbc9e | ||
|
|
83e854e359 | ||
|
|
50303b19d8 | ||
|
|
89382bacaa | ||
|
|
6c559c34df | ||
|
|
adaa6888dd | ||
|
|
a813111379 | ||
|
|
18f0fb050b | ||
|
|
05e92e5afe | ||
|
|
4723d49dad | ||
|
|
fbbc14541a | ||
|
|
5ef33279f2 | ||
|
|
1e02a85970 | ||
|
|
0e88d53faa | ||
|
|
01d1b8ddf2 | ||
|
|
c8257540bc | ||
|
|
2240704863 | ||
|
|
e8ca69ea16 | ||
|
|
da632e7cc1 | ||
|
|
30cd96663f | ||
|
|
7dbe98147d | ||
|
|
5d71d83420 | ||
|
|
38a59a9ff7 | ||
|
|
4b028ad612 | ||
|
|
442560beb4 | ||
|
|
7d2b5c9583 | ||
|
|
29689cfa5a | ||
|
|
52d4abf2f9 | ||
|
|
a953096485 | ||
|
|
884a6dfe6d | ||
|
|
0068301d24 | ||
|
|
353ae4d270 | ||
|
|
e759d426fa | ||
|
|
40ef23b547 | ||
|
|
f5e8562f96 | ||
|
|
1567feae3c | ||
|
|
daf061c9de | ||
|
|
d0e2c6c9ab | ||
|
|
8643ec7fea | ||
|
|
5cfea3d402 | ||
|
|
6c8f21e4a4 | ||
|
|
1d0f91c4a9 | ||
|
|
2a82db4caf | ||
|
|
dd88c17f15 | ||
|
|
8b37270410 | ||
|
|
760169fc43 | ||
|
|
7023e38294 | ||
|
|
a7cf58cc47 | ||
|
|
e25d1a2ea2 | ||
|
|
70969c1757 | ||
|
|
3803437dcc | ||
|
|
eabc6dd76a | ||
|
|
e28d2e2b77 | ||
|
|
96fafe2ed6 | ||
|
|
c81d390f84 | ||
|
|
08456c61f6 | ||
|
|
bc26f9a03f | ||
|
|
6ffeff86be | ||
|
|
f444cddbaf | ||
|
|
d13191a46c | ||
|
|
801ca9a7b7 | ||
|
|
df66e341de | ||
|
|
71ee7ee254 | ||
|
|
a156cae901 | ||
|
|
22b135a116 | ||
|
|
0f08983d85 | ||
|
|
e3e86343fc | ||
|
|
7b6dd880f7 | ||
|
|
b7f4020133 | ||
|
|
c46c7c7584 | ||
|
|
552af8b988 | ||
|
|
4f8ff361dc | ||
|
|
0010b47439 | ||
|
|
4b86b65d07 | ||
|
|
248489401a | ||
|
|
bc5992daf6 | ||
|
|
fdacfb0119 | ||
|
|
0d5d35d052 | ||
|
|
843c96b4b3 | ||
|
|
58dc02ebf2 | ||
|
|
c239f7de25 | ||
|
|
ac8540c3c5 | ||
|
|
22d904db95 | ||
|
|
741c2952d4 | ||
|
|
96f6979c4f | ||
|
|
c5379c1ab6 | ||
|
|
a4a5205fd7 | ||
|
|
c5ad4e7998 | ||
|
|
270dc2e199 | ||
|
|
948a0b6e81 | ||
|
|
87b8ecb13a | ||
|
|
e44ddcac63 | ||
|
|
00e9ad5217 | ||
|
|
96c3879bed | ||
|
|
57f460de2f | ||
|
|
6caacacf6d | ||
|
|
60ac5af682 | ||
|
|
caa94380ac | ||
|
|
0793380b40 | ||
|
|
1adadf585d | ||
|
|
e5ffdb9c77 | ||
|
|
6da5201092 | ||
|
|
b36ae19434 | ||
|
|
2307eac613 | ||
|
|
127ea40ae7 | ||
|
|
6aef600d48 | ||
|
|
98d76a0326 | ||
|
|
6ea6dcf05b | ||
|
|
627797800d | ||
|
|
c6cc03ed0c | ||
|
|
3d7b550f52 | ||
|
|
751d6f4ae6 | ||
|
|
a5c72ab51d | ||
|
|
9bbc88762b | ||
|
|
ceae00dddf | ||
|
|
3634c54e8d | ||
|
|
d74942a03d | ||
|
|
70c5e3e076 | ||
|
|
4cb1b32009 | ||
|
|
3268e90f5e | ||
|
|
e98170816a | ||
|
|
52b92f4db8 | ||
|
|
a2761754da | ||
|
|
805a11345c | ||
|
|
1ab62aec37 | ||
|
|
915363f976 | ||
|
|
205fafa577 | ||
|
|
be2daf4ad5 | ||
|
|
8ecfaa4adf | ||
|
|
03bfcf6462 | ||
|
|
39bec5ff32 | ||
|
|
246839d64a | ||
|
|
3862deb398 | ||
|
|
5954608577 | ||
|
|
984d2fded6 | ||
|
|
a4f04ed45a | ||
|
|
07736e8dcb | ||
|
|
00fc082d68 | ||
|
|
c72daea868 |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
VERSION export-subst
|
||||
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
src/*.o
|
||||
src/*.mo
|
||||
src/dnsmasq.pot
|
||||
src/dnsmasq
|
||||
src/dnsmasq_baseline
|
||||
src/.copts_*
|
||||
contrib/lease-tools/dhcp_lease_time
|
||||
contrib/lease-tools/dhcp_release
|
||||
contrib/lease-tools/dhcp_release6
|
||||
debian/files
|
||||
debian/substvars
|
||||
debian/utils-substvars
|
||||
debian/trees/
|
||||
debian/build/
|
||||
@@ -56,7 +56,7 @@ release 0.95 Major rewrite: remove calls to gethostbyname() and talk
|
||||
any more memory after start-up. The NAT-like forwarding was
|
||||
inspired by a suggestion from Eli Chen <eli@routefree.com>
|
||||
|
||||
release 0.96 Fixed embarrasing thinko in cache linked-list code.
|
||||
release 0.96 Fixed embarrassing thinko in cache linked-list code.
|
||||
|
||||
release 0.98 Some enhancements and bug-fixes.
|
||||
Thanks to "Denis Carre" <denis.carre@laposte.net> and Martin
|
||||
@@ -78,7 +78,7 @@ release 0.98 Some enhancements and bug-fixes.
|
||||
ids, to thwart DNS spoofers.
|
||||
(7) Dnsmasq no longer forwards queries when the
|
||||
"recursion desired" bit is not set in the header.
|
||||
(8) Fixed getopt code to work on compliers with unsigned char.
|
||||
(8) Fixed getopt code to work on compilers with unsigned char.
|
||||
|
||||
release 0.991 Added -b flag: when set causes dnsmasq to always answer
|
||||
reverse queries on the RFC 1918 private IP space itself and
|
||||
@@ -88,7 +88,7 @@ release 0.991 Added -b flag: when set causes dnsmasq to always answer
|
||||
Fixed a bug which stopped dnsmasq working on a box with
|
||||
two or more interfaces with the same IP address.
|
||||
|
||||
Fixed cacheing of CNAMEs. Previously, a CNAME which pointed
|
||||
Fixed caching of CNAMEs. Previously, a CNAME which pointed
|
||||
to a name with many A records would not have all the addresses
|
||||
returned when being answered from the cache.
|
||||
|
||||
@@ -191,7 +191,7 @@ release 1.1 Added --user argument to allow user to change to
|
||||
|
||||
release 1.2 Added IPv6 DNS record support. AAAA records are cached
|
||||
and read from /etc/hosts. Reverse-lookups in the
|
||||
ip6.int and ip6.arpa domains are suppored. Dnsmasq can
|
||||
ip6.int and ip6.arpa domains are supported. Dnsmasq can
|
||||
talk to upstream servers via IPv6 if it finds IP6 addresses
|
||||
in /etc/resolv.conf and it offers DNS service automatically
|
||||
if IPv6 support is present in the kernel.
|
||||
@@ -214,7 +214,7 @@ release 1.3 Some versions of the Linux kernel return EINVAL rather
|
||||
starting, rather than after the first query - principle
|
||||
of least surprise applies here.
|
||||
|
||||
release 1.4 Fix a bug with DHPC lease parsing which broke in
|
||||
release 1.4 Fix a bug with DHCP lease parsing which broke in
|
||||
non-UTC timezones. Thanks to Mark Wormgoor for
|
||||
spotting and diagnosing this. Fixed versions in
|
||||
the .spec files this time. Fixed bug in Suse startup
|
||||
@@ -258,7 +258,7 @@ release 1.7 Fix a problem with cache not clearing properly
|
||||
on receipt of SIGHUP. Bug spotted by Sat Deshpande.
|
||||
|
||||
In group-id changing code:
|
||||
1) Drop supplimentary groups.
|
||||
1) Drop supplementary groups.
|
||||
2) Change gid before dropping root (patch from Soewono Effendi.)
|
||||
3) Change group to "dip" if it exists, to allow access
|
||||
to /etc/ppp/resolv.conf (suggestion from Jorg Sommer.)
|
||||
@@ -297,7 +297,7 @@ release 1.9 Fixes to rpm .spec files.
|
||||
required. The difference is not really visible with
|
||||
bloated libcs like glibc, but should dramatically reduce
|
||||
memory requirements when linked against ulibc for use on
|
||||
embeded routers, and that's the point really. Thanks to
|
||||
embedded routers, and that's the point really. Thanks to
|
||||
Matthew Natalier for prompting this.
|
||||
|
||||
Changed debug mode (-d) so that all logging appears on
|
||||
@@ -319,12 +319,12 @@ release 1.9 Fixes to rpm .spec files.
|
||||
uClinux. Thanks to Matthew Natalier for uClinux stuff.
|
||||
|
||||
release 1.10 Log warnings if resolv.conf or dhcp.leases are not
|
||||
accessable for any reason, as suggested by Hinrich Eilts.
|
||||
accessible for any reason, as suggested by Hinrich Eilts.
|
||||
|
||||
Fixed wrong address printing in error message about
|
||||
no interface with address.
|
||||
|
||||
Updated docs and split installation instuctions into setup.html.
|
||||
Updated docs and split installation instructions into setup.html.
|
||||
|
||||
Fix bug in CNAME chasing code: One CNAME pointing
|
||||
to many A records would lose A records after the
|
||||
@@ -346,7 +346,7 @@ release 1.10 Log warnings if resolv.conf or dhcp.leases are not
|
||||
|
||||
Added -S option to directly specify upstream servers and
|
||||
added ability to direct queries for specific domains to
|
||||
specfic servers. Suggested by Jens Vonderheide.
|
||||
specific servers. Suggested by Jens Vonderheide.
|
||||
|
||||
Upgraded random ID generation - patch from Rob Funk.
|
||||
|
||||
@@ -386,13 +386,13 @@ release 1.11 Actually implement the -R flag promised in the 1.10 man page.
|
||||
names in /etc/hosts -suggestion from Phil Harman.
|
||||
|
||||
Always return a zero time-to-live for names derived from
|
||||
DHCP which stops anthing else caching these
|
||||
DHCP which stops anything else caching these
|
||||
names. Previously the TTL was derived from the lease
|
||||
time but that is incorrect since a lease can be given
|
||||
up early: dnsmasq would know this but anything with the
|
||||
name cached with long TTL would not be updated.
|
||||
|
||||
Extended HAVE_IPV6 config flag to allow compliation on
|
||||
Extended HAVE_IPV6 config flag to allow compilation on
|
||||
old systems which don't have modern library routines
|
||||
like inet_ntop(). Thanks to Phil Harman for the patch.
|
||||
|
||||
@@ -471,7 +471,7 @@ release 1.14 Fixed man page description of -b option which confused
|
||||
/etc/resolv.conf.
|
||||
(Thanks to Klaas Teschauer)
|
||||
|
||||
Check that recieved queries have only rfc1035-legal characters
|
||||
Check that received queries have only rfc1035-legal characters
|
||||
in them. This check is mainly to avoid bad strings being
|
||||
sent to syslog.
|
||||
|
||||
@@ -549,7 +549,7 @@ release 1.16 Allow "/" characters in domain names - this fixes
|
||||
|
||||
release 1.17 Fixed crash with DHCP hostnames > 40 characters.
|
||||
|
||||
Fixed name-comparision routines to not depend on Locale,
|
||||
Fixed name-comparison routines to not depend on Locale,
|
||||
in theory this versions since 1.15 could lock up or give
|
||||
wrong results when run with locale != 'C'.
|
||||
|
||||
@@ -574,7 +574,7 @@ release 1.18 Added round-robin DNS for names which have more than one
|
||||
forwarded because -D is in effect, return NXDOMAIN not
|
||||
an empty reply.
|
||||
|
||||
Add code to return the software version in repsonse to the
|
||||
Add code to return the software version in response to the
|
||||
correct magic query in the same way as BIND. Use
|
||||
"dig version.bind chaos txt" to make the query.
|
||||
|
||||
@@ -635,7 +635,7 @@ release 2.0
|
||||
dynamic allocation.
|
||||
|
||||
Allow dhcp-host options for the same host with different
|
||||
IP adresses where the correct one will be selected for
|
||||
IP addresses where the correct one will be selected for
|
||||
the network the host appears on.
|
||||
|
||||
Fix parsing of --dhcp-option to allow more than one
|
||||
@@ -674,7 +674,7 @@ release 2.1
|
||||
|
||||
Fix unaligned access warnings on BSD/Alpha.
|
||||
|
||||
Allow empty DHCP options, like so: dhpc-option=44
|
||||
Allow empty DHCP options, like so: dhcp-option=44
|
||||
|
||||
Allow single-byte DHCP options like so: dhcp-option=20,1
|
||||
|
||||
@@ -745,7 +745,7 @@ release 2.3
|
||||
around a bug in the DHCP client in HP Jetdirect printers.
|
||||
Thanks to Marko Stolle for finding this problem.
|
||||
|
||||
Return DHCP T1 and T2 times, with "fuzz" to desychronise lease
|
||||
Return DHCP T1 and T2 times, with "fuzz" to desynchronise lease
|
||||
renewals, as specified in the RFC.
|
||||
|
||||
Ensure that the END option is always present in DHCP
|
||||
@@ -838,7 +838,7 @@ release 2.4
|
||||
by Chad Skeeters.
|
||||
|
||||
Fixed bug in /etc/ethers parsing code triggered by tab
|
||||
characters. Qudos to Dag Wieers for hepling to nail that
|
||||
characters. Kudos to Dag Wieers for helping to nail that
|
||||
one.
|
||||
|
||||
Added "bind-interfaces" option correctly.
|
||||
@@ -975,7 +975,7 @@ release 2.8
|
||||
configuration. Specifically: (1) options are matched on
|
||||
the netids from dhcp-range, dhcp-host, vendor class and
|
||||
user class(es). Multiple net-ids are allowed and options
|
||||
are searched on them all. (2) matches agains vendor class
|
||||
are searched on them all. (2) matches against vendor class
|
||||
and user class are now on a substring, if the given
|
||||
string is a substring of the vendor/user class, then a
|
||||
match occurs. Thanks again to Richard Musil for prompting
|
||||
@@ -997,7 +997,7 @@ release 2.8
|
||||
|
||||
Add checks against DHCP clients which return zero-length
|
||||
hostnames. This avoids the potential lease-loss problems
|
||||
reffered to above. Also, if a client sends a hostname when
|
||||
referred to above. Also, if a client sends a hostname when
|
||||
it creates a lease but subsequently sends no or a
|
||||
zero-length hostname whilst renewing, continue to use the
|
||||
existing hostname, don't wipe it out.
|
||||
@@ -1010,7 +1010,7 @@ release 2.9
|
||||
but to the address of another interface were ignored
|
||||
unless the loopback interface was explicitly configured.
|
||||
2) on OpenBSD failure to configure one interface now
|
||||
causes a fatal error on startup rather than an huge
|
||||
causes a fatal error on startup rather than a huge
|
||||
stream of log messages. Thanks to Erik Jan Tromp for
|
||||
finding that bug.
|
||||
|
||||
@@ -1019,7 +1019,7 @@ release 2.9
|
||||
broken. The new algorithm is to pick as before for the
|
||||
first try, but if a query is retried, to send to all
|
||||
available servers in parallel. The first one to reply
|
||||
then becomes prefered for the next query. This should
|
||||
then becomes preferred for the next query. This should
|
||||
improve reliability without generating significant extra
|
||||
upstream load.
|
||||
|
||||
@@ -1027,7 +1027,7 @@ release 2.9
|
||||
unqualified domains introduced in version 2.8
|
||||
|
||||
Allow fallback to "bind-interfaces" at runtime: Some
|
||||
verions of *BSD seem to have enough stuff in the header
|
||||
versions of *BSD seem to have enough stuff in the header
|
||||
files to build but no kernel support. Also now log if
|
||||
"bind-interfaces" is forced on.
|
||||
|
||||
@@ -1049,7 +1049,7 @@ release 2.9
|
||||
first name found is now returned for reverse lookups,
|
||||
rather than all of them.
|
||||
|
||||
Add back fatal errors when nonexistant
|
||||
Add back fatal errors when nonexistent
|
||||
interfaces or interface addresses are given but only in
|
||||
"bind-interfaces" mode. Principle of least surprise applies.
|
||||
|
||||
@@ -1193,7 +1193,7 @@ version 2.14
|
||||
|
||||
version 2.15
|
||||
Fixed NXDOMAIN/NODATA confusion for locally known
|
||||
names. We now return a NODATA reponse for names which are
|
||||
names. We now return a NODATA response for names which are
|
||||
locally known. Now a query for (eg AAAA or MX) for a name
|
||||
with an IPv4 address in /etc/hosts which fails upstream
|
||||
will generate a NODATA response. Note that the query
|
||||
@@ -1229,7 +1229,7 @@ version 2.16
|
||||
|
||||
Set NONBLOCK on all listening sockets to workaround non-POSIX
|
||||
compliance in Linux 2.4 and 2.6. This fixes rare hangs which
|
||||
occured when corrupted packets were received. Thanks to
|
||||
occurred when corrupted packets were received. Thanks to
|
||||
Joris van Rantwijk for chasing that down.
|
||||
|
||||
Updated config.h for NetBSD. Thanks to Martin Lambers.
|
||||
@@ -1297,7 +1297,7 @@ version 2.18
|
||||
interfaces with more than one IPv6 address. Thanks to
|
||||
Martin Pels for help with that.
|
||||
|
||||
Fix problems which occured when more than one dhcp-range
|
||||
Fix problems which occurred when more than one dhcp-range
|
||||
was specified in the same subnet: sometimes parameters
|
||||
(lease time, network-id tag) from the wrong one would be
|
||||
used. Thanks to Rory Campbell-Lange for the bug report.
|
||||
@@ -1314,7 +1314,7 @@ version 2.19
|
||||
Thanks to Richard Atterer for the bug report.
|
||||
|
||||
Check for under-length option fields in DHCP packets, a
|
||||
zero length client-id, in particluar, could seriously
|
||||
zero length client-id, in particular, could seriously
|
||||
confuse dnsmasq 'till now. Thanks to Will Murname for help
|
||||
with that.
|
||||
|
||||
@@ -1389,7 +1389,7 @@ version 2.21
|
||||
recursive queries.
|
||||
|
||||
Fix DHCP address allocation problem when netid tags are in
|
||||
use. Thanks to Will Murnane for the bug report and
|
||||
use. Thanks to Will Murname for the bug report and
|
||||
subsequent testing.
|
||||
|
||||
Add an additional data section to the reply for MX and SRV
|
||||
@@ -1505,7 +1505,7 @@ version 2.23
|
||||
from dnsmasq --version. Thanks to Dirk Schenkewitz for
|
||||
the suggestion.
|
||||
|
||||
Fix pathalogical behaviour when a broken client keeps sending
|
||||
Fix pathological behaviour when a broken client keeps sending
|
||||
DHCPDISCOVER messages repeatedly and fast. Because dealing with
|
||||
each of these takes a few seconds, (because of the ping) then a
|
||||
queue of DHCP packets could build up. Now, the results of a ping
|
||||
@@ -1593,7 +1593,7 @@ version 2.24
|
||||
than one dhcp-range is available. Thanks to Sorin Panca
|
||||
for help chasing this down.
|
||||
|
||||
Added more explict error mesages to the hosts file and
|
||||
Added more explicit error messages to the hosts file and
|
||||
ethers file reading code. Markus Kaiserswerth suffered to
|
||||
make this happen.
|
||||
|
||||
@@ -1617,7 +1617,7 @@ version 2.25
|
||||
|
||||
Fixed Suse spec file - thanks to Steven Springl.
|
||||
|
||||
Fixed DHCP bug when two distict subnets are on the same
|
||||
Fixed DHCP bug when two distinct subnets are on the same
|
||||
physical interface. Thanks to Pawel Zawora for finding
|
||||
this and suggesting the fix.
|
||||
|
||||
@@ -1740,7 +1740,7 @@ version 2.28
|
||||
Fixed regression in netlink code under 2.2.x kernels which
|
||||
occurred in 2.27. Erik Jan Tromp is the vintage kernel fan
|
||||
who found this. P.S. It looks like this "netlink bind:
|
||||
permission denied" problem occured in kernels at least as
|
||||
permission denied" problem occurred in kernels at least as
|
||||
late a 2.4.18. Good information from Alain Richoux.
|
||||
|
||||
Added a warning when it's impossible to give a host its
|
||||
@@ -1761,7 +1761,7 @@ version 2.28
|
||||
Eric House and Eric Spakman for help in chasing this down.
|
||||
|
||||
Tolerate configuration screwups which lead to the DHCP
|
||||
server attemping to allocate its own address to a
|
||||
server attempting to allocate its own address to a
|
||||
client; eg setting the whole subnet range as a DHCP
|
||||
range. Addresses in use by the server are now excluded
|
||||
from use by clients.
|
||||
@@ -2067,7 +2067,7 @@ version 2.36
|
||||
kernel. Thanks to Philip Wall for the bug report.
|
||||
|
||||
Added --dhcp-bridge option, but only to the FreeBSD
|
||||
build. This fixes an oddity with a a particular bridged
|
||||
build. This fixes an oddity with a particular bridged
|
||||
network configuration on FreeBSD. Thanks to Luigi Rizzo
|
||||
for the patch.
|
||||
|
||||
@@ -2273,7 +2273,7 @@ version 2.40
|
||||
this.
|
||||
|
||||
Use client-id as hash-seed for DHCP address allocation
|
||||
with Firewire and Infiniband, as these don't supply an MAC
|
||||
with Firewire and InfiniBand, as these don't supply a MAC
|
||||
address.
|
||||
|
||||
Tweaked TFTP file-open code to make it behave sensibly
|
||||
@@ -2307,7 +2307,7 @@ version 2.40
|
||||
Continue to use unqualified hostnames provided by DHCP
|
||||
clients, even if the domain part is illegal. (The domain
|
||||
is ignored, and an error logged.) Previously in this
|
||||
situation, the whole name whould have been
|
||||
situation, the whole name would have been
|
||||
rejected. Thanks to Jima for the patch.
|
||||
|
||||
Handle EINTR returns from wait() correctly and reap
|
||||
@@ -2319,7 +2319,7 @@ version 2.40
|
||||
leases file and passed to the lease-change
|
||||
script. Suggestion from Ben Voigt.
|
||||
|
||||
Re-run the lease chamge script with an "old" event for
|
||||
Re-run the lease change script with an "old" event for
|
||||
each lease when dnsmasq receives a SIGHUP.
|
||||
|
||||
Added more useful exit codes, including passing on a
|
||||
@@ -2417,7 +2417,7 @@ version 2.41
|
||||
Changed behavior of DHCP server to always return total length of
|
||||
a new lease in DHCPOFFER, even if an existing lease
|
||||
exists. (It used to return the time remaining on the lease
|
||||
whne one existed.) This fixes problems with the Sony Ericsson
|
||||
when one existed.) This fixes problems with the Sony Ericsson
|
||||
K610i phone. Thanks to Hakon Stordahl for finding and
|
||||
fixing this.
|
||||
|
||||
@@ -2433,7 +2433,7 @@ version 2.41
|
||||
|
||||
Add --dhcp-match flag, to check for arbitrary options in
|
||||
DHCP messages from clients. This enables use of dnsmasq
|
||||
with gPXE. Thanks to Rance Hall for the suggestion.
|
||||
with iPXE. Thanks to Rance Hall for the suggestion.
|
||||
|
||||
Added --dhcp-broadcast, to force broadcast replies to DHCP
|
||||
clients which need them but are too dumb or too old to
|
||||
@@ -2476,7 +2476,7 @@ version 2.42
|
||||
|
||||
Fix OS detection logic to cope with GNU/FreeBSD.
|
||||
|
||||
Fix unitialised variable in DBus code - thanks to Roy
|
||||
Fix uninitialised variable in DBus code - thanks to Roy
|
||||
Marples.
|
||||
|
||||
Fix network enumeration code to work on later NetBSD -
|
||||
|
||||
199
FAQ
199
FAQ
@@ -9,7 +9,7 @@ A: The high ports that dnsmasq opens are for replies from the upstream
|
||||
from port 53 the replies would be _to_ port 53 and get blocked.
|
||||
|
||||
This is not a security hole since dnsmasq will only accept replies to that
|
||||
port: queries are dropped. The replies must be to oustanding queries
|
||||
port: queries are dropped. The replies must be to outstanding queries
|
||||
which dnsmasq has forwarded, otherwise they are dropped too.
|
||||
|
||||
Addendum: dnsmasq now has the option "query-port" (-Q), which allows
|
||||
@@ -22,7 +22,7 @@ A: The high ports that dnsmasq opens are for replies from the upstream
|
||||
now uses a new, randomly selected, port for each query. The old
|
||||
default behaviour (use one port allocated by the OS) is available by
|
||||
setting --query-port=0, and setting the query port to a positive
|
||||
value is still works. You should think hard and know what you are
|
||||
value still works. You should think hard and know what you are
|
||||
doing before using either of these options.
|
||||
|
||||
Q: Why doesn't dnsmasq support DNS queries over TCP? Don't the RFC's specify
|
||||
@@ -59,7 +59,7 @@ A: Yes, there is explicit support for *BSD and MacOS X and Solaris.
|
||||
|
||||
Q: My company's nameserver knows about some names which aren't in the
|
||||
public DNS. Even though I put it first in /etc/resolv.conf, it
|
||||
dosen't work: dnsmasq seems not to use the nameservers in the order
|
||||
doesn't work: dnsmasq seems not to use the nameservers in the order
|
||||
given. What am I doing wrong?
|
||||
|
||||
A: By default, dnsmasq treats all the nameservers it knows about as
|
||||
@@ -112,7 +112,7 @@ A: Resolver code sometime does strange things when given names without
|
||||
hostname will fix things. (ie "ping myhost" fails, but "ping
|
||||
myhost." works. The solution is to make sure that all your hosts
|
||||
have a domain set ("domain" in resolv.conf, or set a domain in
|
||||
your DHCP server, see below fr Windows XP and Mac OS X).
|
||||
your DHCP server, see below for Windows XP and Mac OS X).
|
||||
Any domain will do, but "localnet" is traditional. Now when you
|
||||
resolve "myhost" the resolver will attempt to look up
|
||||
"myhost.localnet" so you need to have dnsmasq reply to that name.
|
||||
@@ -144,19 +144,19 @@ Q: Who are Verisign, what do they have to do with the bogus-nxdomain
|
||||
option in dnsmasq and why should I wory about it?
|
||||
|
||||
A: [note: this was written in September 2003, things may well change.]
|
||||
Versign run the .com and .net top-level-domains. They have just
|
||||
Verisign run the .com and .net top-level-domains. They have just
|
||||
changed the configuration of their servers so that unknown .com and
|
||||
.net domains, instead of returning an error code NXDOMAIN, (no such
|
||||
domain) return the address of a host at Versign which runs a web
|
||||
domain) return the address of a host at Verisign which runs a web
|
||||
server showing a search page. Most right-thinking people regard
|
||||
this new behaviour as broken :-). You can test to see if you are
|
||||
suffering Versign brokeness by run a command like
|
||||
suffering Verisign brokenness by run a command like
|
||||
|
||||
host jlsdajkdalld.com
|
||||
|
||||
If you get "jlsdajkdalld.com" does not exist, then all is fine, if
|
||||
host returns an IP address, then the DNS is broken. (Try a few
|
||||
different unlikely domains, just in case you picked a wierd one
|
||||
different unlikely domains, just in case you picked a weird one
|
||||
which really _is_ registered.)
|
||||
|
||||
Assuming that your DNS is broken, and you want to fix it, simply
|
||||
@@ -180,7 +180,7 @@ A: There are a couple of configuration gotchas which have been
|
||||
whilst the ISC one works.
|
||||
|
||||
The first thing to check is the broadcast address set for the
|
||||
ethernet interface. This is normally the adddress on the connected
|
||||
ethernet interface. This is normally the address on the connected
|
||||
network with all ones in the host part. For instance if the
|
||||
address of the ethernet interface is 192.168.55.7 and the netmask
|
||||
is 255.255.255.0 then the broadcast address should be
|
||||
@@ -205,7 +205,7 @@ A: By default, none of the DHCP clients send the host-name when asking
|
||||
send with the "hostname" keyword in /etc/network/interfaces. (See
|
||||
"man interfaces" for details.) That doesn't work for dhclient, were
|
||||
you have to add something like "send host-name daisy" to
|
||||
/etc/dhclient.conf [Update: the lastest dhcpcd packages _do_ send
|
||||
/etc/dhclient.conf [Update: the latest dhcpcd packages _do_ send
|
||||
the hostname by default.
|
||||
|
||||
Q: I'm network booting my machines, and trying to give them static
|
||||
@@ -236,53 +236,70 @@ Q: What network types are supported by the DHCP server?
|
||||
A: Ethernet (and 802.11 wireless) are supported on all platforms. On
|
||||
Linux all network types (including FireWire) are supported.
|
||||
|
||||
Q: What is this strange "bind-interface" option?
|
||||
Q: What are these strange "bind-interface" and "bind-dynamic" options?
|
||||
|
||||
A: The DNS spec says that the reply to a DNS query must come from the
|
||||
same address it was sent to. The traditional way to write an UDP
|
||||
server to do this is to find all of the addresses belonging to the
|
||||
machine (ie all the interfaces on the machine) and then create a
|
||||
socket for each interface which is bound to the address of the
|
||||
interface. Then when a packet is sent to address A, it is received
|
||||
on the socket bound to address A and when the reply is also sent
|
||||
via that socket, the source address is set to A by the kernel and
|
||||
everything works. This is the how dnsmasq works when
|
||||
"bind-interfaces" is set, with the obvious extension that is misses
|
||||
out creating sockets for some interfaces depending on the
|
||||
--interface, --address and --except-interface flags. The
|
||||
disadvantage of this approach is that it breaks if interfaces don't
|
||||
exist or are not configured when the daemon starts and does the
|
||||
socket creation step. In a hotplug-aware world this is a real
|
||||
problem.
|
||||
A: Dnsmasq from v2.63 can operate in one of three different "networking
|
||||
modes". This is unfortunate as it requires users configuring dnsmasq
|
||||
to take into account some rather bizarre constraints and select the
|
||||
mode which best fits the requirements of a particular installation.
|
||||
The origin of these are deficiencies in the Unix networking
|
||||
model and APIs and each mode has different advantages and
|
||||
problems. Just to add to the confusion, not all modes are available on
|
||||
all platforms (due the to lack of supporting network APIs).To further
|
||||
add to the confusion, the rules for the DHCP subsystem on dnsmasq are
|
||||
different to the rules for the DNS and TFTP subsystems.
|
||||
|
||||
The alternative approach is to have only one socket, which is bound
|
||||
to the correct port and the wildcard IP address (0.0.0.0). That
|
||||
socket will receive _all_ packets sent to port 53, no matter what
|
||||
destination address they have. This solves the problem of
|
||||
interfaces which are created or reconfigured after daemon
|
||||
start-up. To make this work is more complicated because of the
|
||||
"reply source address" problem. When a UDP packet is sent by a
|
||||
socket bound to 0.0.0.0 its source address will be set to the
|
||||
address of one of the machine's interfaces, but which one is not
|
||||
determined and can vary depending on the OS being run. To get round
|
||||
this it is neccessary to use a scary advanced API to determine the
|
||||
address to which a query was sent, and force that to be the source
|
||||
address in the reply. For IPv4 this stuff in non-portable and quite
|
||||
often not even available (It's different between FreeBSD 5.x and
|
||||
Linux, for instance, and FreeBSD 4.x, Linux 2.0.x and OpenBSD don't
|
||||
have it at all.) Hence "bind-interfaces" has to always be available
|
||||
as a fall back. For IPv6 the API is standard and universally
|
||||
available.
|
||||
The three modes are "wildcard", "bind-interfaces" and "bind-dynamic".
|
||||
|
||||
It could be argued that if the --interface or --address flags are
|
||||
used then binding interfaces is more appropriate, but using
|
||||
wildcard binding means that dnsmasq will quite happily start up
|
||||
after being told to use interfaces which don't exist, but which are
|
||||
created later. Wildcard binding breaks the scenario when dnsmasq is
|
||||
listening on one interface and another server (most probably BIND)
|
||||
is listening on another. It's not possible for BIND to bind to an
|
||||
(address,port) pair when dnsmasq has bound (wildcard,port), hence
|
||||
the ability to explicitly turn off wildcard binding.
|
||||
In "wildcard" mode, dnsmasq binds the wildcard IP address (0.0.0.0 or
|
||||
::). This allows it to receive all the packets sent to the server on
|
||||
the relevant port. Access control (--interface, --except-interface,
|
||||
--listen-address, etc) is implemented by dnsmasq: it queries the
|
||||
kernel to determine the interface on which a packet was received and
|
||||
the address to which it was sent, and applies the configured
|
||||
rules. Wildcard mode is the default if neither of the other modes are
|
||||
specified.
|
||||
|
||||
In "bind-interfaces" mode, dnsmasq runs through all the network
|
||||
interfaces available when it starts, finds the set of IP addresses on
|
||||
those interfaces, filters that set using the access control
|
||||
configuration, and then binds the set of IP addresses. Only packets
|
||||
sent to the allowed addresses are delivered by the kernel to dnsmasq.
|
||||
|
||||
In "bind-dynamic" mode, access control filtering is done both by
|
||||
binding individual IP addresses, as for bind-interfaces, and by
|
||||
inspecting individual packets on arrival as for wildcard mode. In
|
||||
addition, dnsmasq notices when new interfaces appear or new addresses
|
||||
appear on existing interfaces, and the resulting IP addresses are
|
||||
bound automatically without having to restart dnsmasq.
|
||||
|
||||
The mode chosen has four different effects: co-existence with other
|
||||
servers, semantics of --interface access control, effect of new
|
||||
interfaces, and legality of --interface specifications for
|
||||
non-existent interfaces. We will deal with these in order.
|
||||
|
||||
A dnsmasq instance running in wildcard mode precludes a machine from
|
||||
running a second instance of dnsmasq or any other DNS, TFTP or DHCP
|
||||
server. Attempts to do so will fail with an "address in use" error.
|
||||
Dnsmasq running in --bind-interfaces or bind-dynamic mode allow other
|
||||
instances of dnsmasq or other servers, as long as no two servers are
|
||||
configured to listen on the same interface address.
|
||||
|
||||
The semantics of --interface varies subtly between wildcard or
|
||||
bind-dynamic mode and bind-interfaces mode. The situation where this
|
||||
matters is a request which arrives via one interface (A), but with a
|
||||
destination address of a second interface (B) and when dnsmasq is
|
||||
configured to listen only on B. In wildcard or bind-dynamic mode, such
|
||||
a request will be ignored, in bind-interfaces mode, it will be
|
||||
accepted.
|
||||
|
||||
The creation of new network interfaces after dnsmasq starts is ignored
|
||||
by dnsmasq when in --bind-interfaces mode. In wildcard or bind-dynamic
|
||||
mode, such interfaces are handled normally.
|
||||
|
||||
An --interface specification for a non-existent interface is a fatal
|
||||
error at start-up when in --bind-interfaces mode, by just generates a
|
||||
warning in wildcard or bind-dynamic mode.
|
||||
|
||||
Q: Why doesn't Kerberos work/why can't I get sensible answers to
|
||||
queries for SRV records.
|
||||
@@ -296,15 +313,25 @@ Q: Can I get email notification when a new version of dnsmasq is
|
||||
released?
|
||||
|
||||
A: Yes, new releases of dnsmasq are always announced through
|
||||
freshmeat.net, and they allow you to subcribe to email alerts when
|
||||
freshmeat.net, and they allow you to subscribe to email alerts when
|
||||
new versions of particular projects are released. New releases are
|
||||
also announced in the dnsmasq-discuss mailing list, subscribe at
|
||||
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss
|
||||
|
||||
Q: What does the dhcp-authoritative option do?
|
||||
|
||||
A: See http://www.isc.org/files/auth.html - that's
|
||||
for the ISC daemon, but the same applies to dnsmasq.
|
||||
A: The DHCP spec says that when a DHCP server receives a renewal request
|
||||
from a client it has no knowledge of, it should just ignore it.
|
||||
This is because it's supported to have more than one DHCP server
|
||||
on a network, and another DHCP server may be dealing with the client.
|
||||
This has the unfortunate effect that when _no_ DHCP replies to
|
||||
the client, it takes some time for the client to time-out and start
|
||||
to get a new lease. Setting this option makes dnsmasq violate the
|
||||
standard to the extent that it will send a NAK reply to the client,
|
||||
causing it to immediately start to get a new lease. This improves
|
||||
behaviour when machines move networks, and in the case that the DHCP
|
||||
lease database is lost. As long as there are not more tha one DHCP
|
||||
server on the network, it's safe to enable the option.
|
||||
|
||||
Q: Why does my Gentoo box pause for a minute before getting a new
|
||||
lease?
|
||||
@@ -332,18 +359,64 @@ A: By default, the identity of a machine is determined by using the
|
||||
method for setting the client-id varies with DHCP client software,
|
||||
dhcpcd uses the "-I" flag. Windows uses a registry setting,
|
||||
see http://www.jsiinc.com/SUBF/TIP2800/rh2845.htm
|
||||
|
||||
Addendum:
|
||||
From version 2.46, dnsmasq has a solution to this which doesn't
|
||||
involve setting client-IDs. It's possible to put more than one MAC
|
||||
address in a --dhcp-host configuration. This tells dnsmasq that it
|
||||
should use the specified IP for any of the specified MAC addresses,
|
||||
and furthermore it gives dnsmasq permission to sumarily abandon a
|
||||
and furthermore it gives dnsmasq permission to summarily abandon a
|
||||
lease to one of the MAC addresses if another one comes along. Note
|
||||
that this will work fine only as longer as only one interface is
|
||||
up at any time. There is no way for dnsmasq to enforce this
|
||||
constraint: if you configure multiple MAC addresses and violate
|
||||
this rule, bad things will happen.
|
||||
|
||||
Addendum-II: The link above is dead, the former contents of the link are:
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
How can I keep the same DHCP client reservation, if the MAC address changes?
|
||||
|
||||
When you reserve an IP address for a DHCP client, you provide the
|
||||
MAC address of the client's NIC.
|
||||
|
||||
It is possible to use a custom identifier, which is sent as
|
||||
option 61 in the client's DHCP Discover and Request packet.
|
||||
|
||||
The DhcpClientIdentifier is a REG_DWORD value that is located at:
|
||||
|
||||
Windows NT 4.0 SP2+
|
||||
|
||||
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<Adapter Name>'X'\Parameters\Tcpip
|
||||
|
||||
where <Adapter Name> is the NIC driver name and 'X' is the number of the NIC.
|
||||
|
||||
Windows 2000
|
||||
|
||||
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TcpIp\Parameters\Interfaces\<NIC GUID>
|
||||
|
||||
where <NIC GUID> is the GUID of the NIC.
|
||||
|
||||
The valid range of data is 0x0 - 0xFFFFFFFF. The custom identifier is send as 4 bytes,
|
||||
8 hexadecimal character, in groups of 2 hexadecimal characters, with the groups being
|
||||
sent in reverse order. If the custom identifier is less than 8 hexadeciaml characters,
|
||||
it is zero padded at the end. Examples:
|
||||
|
||||
Custom Client Client Reservation
|
||||
Identifier on DHCP Server
|
||||
12345678 78563412
|
||||
123456 56341200
|
||||
1234 34120000
|
||||
1234567 67452301
|
||||
12345 45230100
|
||||
123 23010000
|
||||
A18F42 428FA100
|
||||
CF432 32F40C00
|
||||
C32D1BE BED1320C
|
||||
|
||||
-------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Q: Can dnsmasq do DHCP on IP-alias interfaces?
|
||||
|
||||
A: Yes, from version-2.21. The support is only available running under
|
||||
@@ -467,8 +540,18 @@ A: The DHCP client on windows Vista (and possibly later versions)
|
||||
work).
|
||||
|
||||
|
||||
Q: DHCP doesn't work with windows 7 but everything else is fine.
|
||||
|
||||
A: There seems to be a problem if Windows 7 doesn't get a value for
|
||||
DHCP option 252 in DHCP packets it gets from the server. The
|
||||
symptoms have been variously reported as continual DHCPINFORM
|
||||
requests in an attempt to get an option-252, or even ignoring DHCP
|
||||
offers completely (and failing to get an IP address) if there is no
|
||||
option-252 supplied. DHCP option 252 is for WPAD, WWW Proxy
|
||||
Auto Detection and if you don't want or need to use that, then
|
||||
simplest fix seems to be to supply an empty option with:
|
||||
|
||||
dhcp-option=252,"\n"
|
||||
|
||||
|
||||
|
||||
|
||||
181
Makefile
181
Makefile
@@ -1,4 +1,4 @@
|
||||
# dnsmasq is Copyright (c) 2000-2011 Simon Kelley
|
||||
# dnsmasq is Copyright (c) 2000-2016 Simon Kelley
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -13,89 +13,160 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
PREFIX = /usr/local
|
||||
BINDIR = ${PREFIX}/sbin
|
||||
MANDIR = ${PREFIX}/share/man
|
||||
LOCALEDIR = ${PREFIX}/share/locale
|
||||
# NOTE: Building the i18n targets requires GNU-make
|
||||
|
||||
PKG_CONFIG = pkg-config
|
||||
INSTALL = install
|
||||
MSGMERGE = msgmerge
|
||||
MSGFMT = msgfmt
|
||||
XGETTEXT = xgettext
|
||||
|
||||
CFLAGS = -Wall -W -O2
|
||||
# Variables you may well want to override.
|
||||
|
||||
PREFIX = /usr/local
|
||||
BINDIR = $(PREFIX)/sbin
|
||||
MANDIR = $(PREFIX)/share/man
|
||||
LOCALEDIR = $(PREFIX)/share/locale
|
||||
BUILDDIR = $(SRC)
|
||||
DESTDIR =
|
||||
CFLAGS = -Wall -W -O2
|
||||
LDFLAGS =
|
||||
COPTS =
|
||||
RPM_OPT_FLAGS =
|
||||
LIBS =
|
||||
|
||||
#################################################################
|
||||
|
||||
# Variables you might want to override.
|
||||
|
||||
PKG_CONFIG = pkg-config
|
||||
INSTALL = install
|
||||
MSGMERGE = msgmerge
|
||||
MSGFMT = msgfmt
|
||||
XGETTEXT = xgettext
|
||||
|
||||
SRC = src
|
||||
PO = po
|
||||
PO = po
|
||||
MAN = man
|
||||
|
||||
DBUS_CFLAGS=`echo $(COPTS) | ../bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --cflags dbus-1`
|
||||
DBUS_LIBS= `echo $(COPTS) | ../bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --libs dbus-1`
|
||||
IDN_CFLAGS= `echo $(COPTS) | ../bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --cflags libidn`
|
||||
IDN_LIBS= `echo $(COPTS) | ../bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --libs libidn`
|
||||
CT_CFLAGS= `echo $(COPTS) | ../bld/pkg-wrapper HAVE_CONNTRACK $(PKG_CONFIG) --cflags libnetfilter_conntrack`
|
||||
CT_LIBS= `echo $(COPTS) | ../bld/pkg-wrapper HAVE_CONNTRACK $(PKG_CONFIG) --libs libnetfilter_conntrack`
|
||||
SUNOS_LIBS= `if uname | grep SunOS 2>&1 >/dev/null; then echo -lsocket -lnsl -lposix4; fi`
|
||||
#################################################################
|
||||
|
||||
OBJS = cache.o rfc1035.o util.o option.o forward.o network.o \
|
||||
# pmake way. (NB no spaces to keep gmake 3.82 happy)
|
||||
top!=pwd
|
||||
# GNU make way.
|
||||
top?=$(CURDIR)
|
||||
|
||||
dbus_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --cflags dbus-1`
|
||||
dbus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --libs dbus-1`
|
||||
ubus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_UBUS $(PKG_CONFIG) --copy -lubox -lubus`
|
||||
idn_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --cflags libidn`
|
||||
idn_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --libs libidn`
|
||||
idn2_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFIG) --cflags libidn2`
|
||||
idn2_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFIG) --libs libidn2`
|
||||
ct_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_CONNTRACK $(PKG_CONFIG) --cflags libnetfilter_conntrack`
|
||||
ct_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_CONNTRACK $(PKG_CONFIG) --libs libnetfilter_conntrack`
|
||||
lua_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --cflags lua5.2`
|
||||
lua_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --libs lua5.2`
|
||||
nettle_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --cflags nettle hogweed`
|
||||
nettle_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --libs nettle hogweed`
|
||||
gmp_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC NO_GMP --copy -lgmp`
|
||||
sunos_libs = `if uname | grep SunOS >/dev/null 2>&1; then echo -lsocket -lnsl -lposix4; fi`
|
||||
version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"'
|
||||
|
||||
sum?=$(shell $(CC) -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | ( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' ')
|
||||
sum!=$(CC) -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | ( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' '
|
||||
copts_conf = .copts_$(sum)
|
||||
|
||||
objs = cache.o rfc1035.o util.o option.o forward.o network.o \
|
||||
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
|
||||
helper.o tftp.o log.o conntrack.o
|
||||
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
|
||||
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
|
||||
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \
|
||||
poll.o rrfilter.o edns0.o arp.o crypto.o dump.o ubus.o metrics.o
|
||||
|
||||
all :
|
||||
@cd $(SRC) && $(MAKE) \
|
||||
BUILD_CFLAGS="$(DBUS_CFLAGS) $(IDN_CFLAGS) $(CT_CFLAGS)" \
|
||||
BUILD_LIBS="$(DBUS_LIBS) $(IDN_LIBS) $(CT_LIBS) $(SUNOS_LIBS)" \
|
||||
-f ../Makefile dnsmasq
|
||||
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
||||
dns-protocol.h radv-protocol.h ip6addr.h metrics.h
|
||||
|
||||
clean :
|
||||
rm -f *~ $(SRC)/*.mo contrib/*/*~ */*~ $(SRC)/*.pot
|
||||
rm -f $(SRC)/*.o $(SRC)/dnsmasq.a $(SRC)/dnsmasq core */core
|
||||
all : $(BUILDDIR)
|
||||
@cd $(BUILDDIR) && $(MAKE) \
|
||||
top="$(top)" \
|
||||
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
|
||||
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs)" \
|
||||
-f $(top)/Makefile dnsmasq
|
||||
|
||||
mostly_clean :
|
||||
rm -f $(BUILDDIR)/*.mo $(BUILDDIR)/*.pot
|
||||
rm -f $(BUILDDIR)/.copts_* $(BUILDDIR)/*.o $(BUILDDIR)/dnsmasq.a $(BUILDDIR)/dnsmasq
|
||||
|
||||
clean : mostly_clean
|
||||
rm -f $(BUILDDIR)/dnsmasq_baseline
|
||||
rm -f core */core
|
||||
rm -f *~ contrib/*/*~ */*~
|
||||
|
||||
install : all install-common
|
||||
|
||||
install-common :
|
||||
$(INSTALL) -d $(DESTDIR)$(BINDIR) -d $(DESTDIR)$(MANDIR)/man8
|
||||
$(INSTALL) -d $(DESTDIR)$(BINDIR)
|
||||
$(INSTALL) -d $(DESTDIR)$(MANDIR)/man8
|
||||
$(INSTALL) -m 644 $(MAN)/dnsmasq.8 $(DESTDIR)$(MANDIR)/man8
|
||||
$(INSTALL) -m 755 $(SRC)/dnsmasq $(DESTDIR)$(BINDIR)
|
||||
$(INSTALL) -m 755 $(BUILDDIR)/dnsmasq $(DESTDIR)$(BINDIR)
|
||||
|
||||
all-i18n :
|
||||
@cd $(SRC) && $(MAKE) \
|
||||
I18N=-DLOCALEDIR='\"$(LOCALEDIR)\"' \
|
||||
BUILD_CFLAGS="$(DBUS_CFLAGS) $(CT_CFLAGS) `$(PKG_CONFIG) --cflags libidn`" \
|
||||
BUILD_LIBS="$(DBUS_LIBS) $(CT_LIBS) $(SUNOS_LIBS) `$(PKG_CONFIG) --libs libidn`" \
|
||||
-f ../Makefile dnsmasq
|
||||
@cd $(PO); for f in *.po; do \
|
||||
cd ../$(SRC) && $(MAKE) \
|
||||
-f ../Makefile $${f%.po}.mo; \
|
||||
all-i18n : $(BUILDDIR)
|
||||
@cd $(BUILDDIR) && $(MAKE) \
|
||||
top="$(top)" \
|
||||
i18n=-DLOCALEDIR=\'\"$(LOCALEDIR)\"\' \
|
||||
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
|
||||
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \
|
||||
-f $(top)/Makefile dnsmasq
|
||||
for f in `cd $(PO); echo *.po`; do \
|
||||
cd $(top) && cd $(BUILDDIR) && $(MAKE) top="$(top)" -f $(top)/Makefile $${f%.po}.mo; \
|
||||
done
|
||||
|
||||
install-i18n : all-i18n install-common
|
||||
cd $(SRC); ../bld/install-mo $(DESTDIR)$(LOCALEDIR) $(INSTALL)
|
||||
cd $(BUILDDIR); $(top)/bld/install-mo $(DESTDIR)$(LOCALEDIR) $(INSTALL)
|
||||
cd $(MAN); ../bld/install-man $(DESTDIR)$(MANDIR) $(INSTALL)
|
||||
|
||||
merge :
|
||||
@cd $(SRC) && $(MAKE) -f ../Makefile dnsmasq.pot
|
||||
@cd $(PO); for f in *.po; do \
|
||||
echo -n msgmerge $$f && $(MSGMERGE) --no-wrap -U $$f ../$(SRC)/dnsmasq.pot; \
|
||||
merge :
|
||||
@cd $(BUILDDIR) && $(MAKE) top="$(top)" -f $(top)/Makefile dnsmasq.pot
|
||||
for f in `cd $(PO); echo *.po`; do \
|
||||
echo -n msgmerge $(PO)/$$f && $(MSGMERGE) --no-wrap -U $(PO)/$$f $(BUILDDIR)/dnsmasq.pot; \
|
||||
done
|
||||
|
||||
# Canonicalise .po file.
|
||||
%.po :
|
||||
@cd $(BUILDDIR) && $(MAKE) -f $(top)/Makefile dnsmasq.pot
|
||||
mv $(PO)/$*.po $(PO)/$*.po.orig && $(MSGMERGE) --no-wrap $(PO)/$*.po.orig $(BUILDDIR)/dnsmasq.pot >$(PO)/$*.po;
|
||||
|
||||
# rules below are targets in recusive makes with cwd=$(SRC)
|
||||
$(BUILDDIR):
|
||||
mkdir -p $(BUILDDIR)
|
||||
|
||||
# rules below are helpers for size tracking
|
||||
|
||||
baseline : mostly_clean all
|
||||
@cd $(BUILDDIR) && \
|
||||
mv dnsmasq dnsmasq_baseline
|
||||
|
||||
bloatcheck : $(BUILDDIR)/dnsmasq_baseline mostly_clean all
|
||||
@cd $(BUILDDIR) && \
|
||||
$(top)/bld/bloat-o-meter dnsmasq_baseline dnsmasq; \
|
||||
size dnsmasq_baseline dnsmasq
|
||||
|
||||
# rules below are targets in recursive makes with cwd=$(BUILDDIR)
|
||||
|
||||
$(copts_conf): $(hdrs)
|
||||
@rm -f *.o .copts_*
|
||||
@touch $@
|
||||
|
||||
$(objs:.o=.c) $(hdrs):
|
||||
ln -s $(top)/$(SRC)/$@ .
|
||||
|
||||
$(objs): $(copts_conf) $(hdrs)
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $(COPTS) $(I18N) $(BUILD_CFLAGS) $(RPM_OPT_FLAGS) -c $<
|
||||
$(CC) $(CFLAGS) $(COPTS) $(i18n) $(build_cflags) $(RPM_OPT_FLAGS) -c $<
|
||||
|
||||
dnsmasq : $(OBJS)
|
||||
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(BUILD_LIBS) $(LIBS)
|
||||
dnsmasq : $(objs)
|
||||
$(CC) $(LDFLAGS) -o $@ $(objs) $(build_libs) $(LIBS)
|
||||
|
||||
dnsmasq.pot : $(OBJS:.o=.c) dnsmasq.h config.h
|
||||
$(XGETTEXT) -d dnsmasq --foreign-user --omit-header --keyword=_ -o $@ -i $(OBJS:.o=.c)
|
||||
dnsmasq.pot : $(objs:.o=.c) $(hdrs)
|
||||
$(XGETTEXT) -d dnsmasq --foreign-user --omit-header --keyword=_ -o $@ -i $(objs:.o=.c)
|
||||
|
||||
%.mo : ../po/%.po dnsmasq.pot
|
||||
$(MSGMERGE) -o - ../po/$*.po dnsmasq.pot | $(MSGFMT) -o $*.mo -
|
||||
%.mo : $(top)/$(PO)/%.po dnsmasq.pot
|
||||
$(MSGMERGE) -o - $(top)/$(PO)/$*.po dnsmasq.pot | $(MSGFMT) -o $*.mo -
|
||||
|
||||
|
||||
.PHONY : all clean install install-common all-i18n install-i18n merge
|
||||
.PHONY : all clean mostly_clean install install-common all-i18n install-i18n merge baseline bloatcheck
|
||||
|
||||
@@ -6,7 +6,12 @@ include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
|
||||
forward.c helper.c lease.c log.c \
|
||||
netlink.c network.c option.c rfc1035.c \
|
||||
rfc2131.c tftp.c util.c conntrack.c
|
||||
rfc2131.c tftp.c util.c conntrack.c \
|
||||
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
|
||||
radv.c slaac.c auth.c ipset.c domain.c \
|
||||
dnssec.c dnssec-openssl.c blockdata.c tables.c \
|
||||
loop.c inotify.c poll.c rrfilter.c edns0.c arp.c \
|
||||
crypto.c dump.c ubus.c
|
||||
|
||||
LOCAL_MODULE := dnsmasq
|
||||
|
||||
@@ -15,4 +20,6 @@ LOCAL_C_INCLUDES := external/dnsmasq/src
|
||||
LOCAL_CFLAGS := -O2 -g -W -Wall -D__ANDROID__ -DNO_IPV6 -DNO_TFTP -DNO_SCRIPT
|
||||
LOCAL_SYSTEM_SHARED_LIBRARIES := libc libcutils
|
||||
|
||||
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
130
bld/bloat-o-meter
Executable file
130
bld/bloat-o-meter
Executable file
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2004 Matt Mackall <mpm@selenic.com>
|
||||
#
|
||||
# Inspired by perl Bloat-O-Meter (c) 1997 by Andi Kleen
|
||||
#
|
||||
# This software may be used and distributed according to the terms
|
||||
# of the GNU General Public License, incorporated herein by reference.
|
||||
|
||||
import sys, os#, re
|
||||
|
||||
def usage():
|
||||
sys.stderr.write("usage: %s [-t] file1 file2\n" % sys.argv[0])
|
||||
sys.exit(-1)
|
||||
|
||||
f1, f2 = (None, None)
|
||||
flag_timing, dashes = (False, False)
|
||||
|
||||
for f in sys.argv[1:]:
|
||||
if f.startswith("-"):
|
||||
if f == "--": # sym_args
|
||||
dashes = True
|
||||
break
|
||||
if f == "-t": # timings
|
||||
flag_timing = True
|
||||
else:
|
||||
if not os.path.exists(f):
|
||||
sys.stderr.write("Error: file '%s' does not exist\n" % f)
|
||||
usage()
|
||||
if f1 is None:
|
||||
f1 = f
|
||||
elif f2 is None:
|
||||
f2 = f
|
||||
if flag_timing:
|
||||
import time
|
||||
if f1 is None or f2 is None:
|
||||
usage()
|
||||
|
||||
sym_args = " ".join(sys.argv[3 + flag_timing + dashes:])
|
||||
def getsizes(file):
|
||||
sym, alias, lut = {}, {}, {}
|
||||
for l in os.popen("readelf -W -s %s %s" % (sym_args, file)).readlines():
|
||||
l = l.strip()
|
||||
if not (len(l) and l[0].isdigit() and len(l.split()) == 8):
|
||||
continue
|
||||
num, value, size, typ, bind, vis, ndx, name = l.split()
|
||||
if ndx == "UND": continue # skip undefined
|
||||
if typ in ["SECTION", "FILES"]: continue # skip sections and files
|
||||
if "." in name: name = "static." + name.split(".")[0]
|
||||
value = int(value, 16)
|
||||
size = int(size, 16) if size.startswith('0x') else int(size)
|
||||
if vis != "DEFAULT" and bind != "GLOBAL": # see if it is an alias
|
||||
alias[(value, size)] = {"name" : name}
|
||||
else:
|
||||
sym[name] = {"addr" : value, "size": size}
|
||||
lut[(value, size)] = 0
|
||||
for addr, sz in iter(alias.keys()):
|
||||
# If the non-GLOBAL sym has an implementation elsewhere then
|
||||
# it's an alias, disregard it.
|
||||
if not (addr, sz) in lut:
|
||||
# If this non-GLOBAL sym does not have an implementation at
|
||||
# another address, then treat it as a normal symbol.
|
||||
sym[alias[(addr, sz)]["name"]] = {"addr" : addr, "size": sz}
|
||||
for l in os.popen("readelf -W -S " + file).readlines():
|
||||
x = l.split()
|
||||
if len(x)<6: continue
|
||||
# Should take these into account too!
|
||||
#if x[1] not in [".text", ".rodata", ".symtab", ".strtab"]: continue
|
||||
if x[1] not in [".rodata"]: continue
|
||||
sym[x[1]] = {"addr" : int(x[3], 16), "size" : int(x[5], 16)}
|
||||
return sym
|
||||
|
||||
if flag_timing:
|
||||
start_t1 = int(time.time() * 1e9)
|
||||
old = getsizes(f1)
|
||||
if flag_timing:
|
||||
end_t1 = int(time.time() * 1e9)
|
||||
start_t2 = int(time.time() * 1e9)
|
||||
new = getsizes(f2)
|
||||
if flag_timing:
|
||||
end_t2 = int(time.time() * 1e9)
|
||||
start_t3 = int(time.time() * 1e9)
|
||||
grow, shrink, add, remove, up, down = 0, 0, 0, 0, 0, 0
|
||||
delta, common = [], {}
|
||||
|
||||
for name in iter(old.keys()):
|
||||
if name in new:
|
||||
common[name] = 1
|
||||
|
||||
for name in old:
|
||||
if name not in common:
|
||||
remove += 1
|
||||
sz = old[name]["size"]
|
||||
down += sz
|
||||
delta.append((-sz, name))
|
||||
|
||||
for name in new:
|
||||
if name not in common:
|
||||
add += 1
|
||||
sz = new[name]["size"]
|
||||
up += sz
|
||||
delta.append((sz, name))
|
||||
|
||||
for name in common:
|
||||
d = new[name].get("size", 0) - old[name].get("size", 0)
|
||||
if d>0: grow, up = grow+1, up+d
|
||||
elif d<0: shrink, down = shrink+1, down-d
|
||||
else:
|
||||
continue
|
||||
delta.append((d, name))
|
||||
|
||||
delta.sort()
|
||||
delta.reverse()
|
||||
if flag_timing:
|
||||
end_t3 = int(time.time() * 1e9)
|
||||
|
||||
print("%-48s %7s %7s %+7s" % ("function", "old", "new", "delta"))
|
||||
for d, n in delta:
|
||||
if d:
|
||||
old_sz = old.get(n, {}).get("size", "-")
|
||||
new_sz = new.get(n, {}).get("size", "-")
|
||||
print("%-48s %7s %7s %+7d" % (n, old_sz, new_sz, d))
|
||||
print("-"*78)
|
||||
total="(add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s)%%sTotal: %s bytes"\
|
||||
% (add, remove, grow, shrink, up, -down, up-down)
|
||||
print(total % (" "*(80-len(total))))
|
||||
if flag_timing:
|
||||
print("\n%d/%d; %d Parse origin/new; processing nsecs" %
|
||||
(end_t1-start_t1, end_t2-start_t2, end_t3-start_t3))
|
||||
print("total nsecs: %d" % (end_t3-start_t1))
|
||||
38
bld/get-version
Executable file
38
bld/get-version
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Determine the version string to build into a binary.
|
||||
# When building in the git repository, we can use the output
|
||||
# of "git describe" which gives an unequivocal answer.
|
||||
#
|
||||
# Failing that, we use the contents of the VERSION file
|
||||
# which has a set of references substituted into it by git.
|
||||
# If we can find one which matches $v[0-9].* then we assume it's
|
||||
# a version-number tag, else we just use the whole string.
|
||||
# If there is more than one v[0-9].* tag, sort them and use the
|
||||
# first. This favours, eg v2.63 over 2.63rc6.
|
||||
|
||||
# Change directory to the toplevel source directory.
|
||||
if test -z "$1" || ! test -d "$1" || ! cd "$1"; then
|
||||
echo "$0: First argument $1 must be toplevel dir." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if which git >/dev/null 2>&1 && \
|
||||
([ -d .git ] || grep '^gitdir:' .git >/dev/null 2>&1) && \
|
||||
git describe >/dev/null 2>&1; then
|
||||
git describe | sed 's/^v//'
|
||||
elif grep '\$Format:%d\$' $1/VERSION >/dev/null 2>&1; then
|
||||
# unsubstituted VERSION, but no git available.
|
||||
echo UNKNOWN
|
||||
else
|
||||
vers=`cat $1/VERSION | sed 's/[(), ]/,/ g' | tr ',' '\n' | grep ^v[0-9]`
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "${vers}" | sort -r | head -n 1 | sed 's/^v//'
|
||||
else
|
||||
cat $1/VERSION
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -4,6 +4,6 @@ for f in *; do
|
||||
if [ -d $f ]; then
|
||||
$2 -m 755 -d $1/$f/man8
|
||||
$2 -m 644 $f/dnsmasq.8 $1/$f/man8
|
||||
echo installing $1/$f/man8/dnsmasq.8
|
||||
echo installing $f/man8/dnsmasq.8
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
for f in *.mo; do
|
||||
$2 -m 755 -d $1/${f%.mo}/LC_MESSAGES
|
||||
$2 -m 644 $f $1/${f%.mo}/LC_MESSAGES/dnsmasq.mo
|
||||
echo installing $1/${f%.mo}/LC_MESSAGES/dnsmasq.mo
|
||||
echo installing ${f%.mo}/LC_MESSAGES/dnsmasq.mo
|
||||
done
|
||||
|
||||
|
||||
|
||||
@@ -2,10 +2,39 @@
|
||||
|
||||
search=$1
|
||||
shift
|
||||
pkg=$1
|
||||
shift
|
||||
op=$1
|
||||
shift
|
||||
|
||||
if grep "^\#.*define.*$search" config.h 2>&1 >/dev/null || \
|
||||
grep $search 2>&1 >/dev/null ; then
|
||||
exec $*
|
||||
in=`cat`
|
||||
|
||||
if grep "^\#[[:space:]]*define[[:space:]]*$search" config.h >/dev/null 2>&1 || \
|
||||
echo $in | grep $search >/dev/null 2>&1; then
|
||||
# Nasty, nasty, in --copy, arg 2 is another config to search for, use with NO_GMP
|
||||
if [ $op = "--copy" ]; then
|
||||
if grep "^\#[[:space:]]*define[[:space:]]*$pkg" config.h >/dev/null 2>&1 || \
|
||||
echo $in | grep $pkg >/dev/null 2>&1; then
|
||||
pkg=""
|
||||
else
|
||||
pkg="$*"
|
||||
fi
|
||||
elif grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \
|
||||
echo $in | grep ${search}_STATIC >/dev/null 2>&1; then
|
||||
pkg=`$pkg --static $op $*`
|
||||
else
|
||||
pkg=`$pkg $op $*`
|
||||
fi
|
||||
|
||||
if grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \
|
||||
echo $in | grep ${search}_STATIC >/dev/null 2>&1; then
|
||||
if [ $op = "--libs" ] || [ $op = "--copy" ]; then
|
||||
echo "-Wl,-Bstatic $pkg -Wl,-Bdynamic"
|
||||
else
|
||||
echo "$pkg"
|
||||
fi
|
||||
else
|
||||
echo "$pkg"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ sudo chmod 644 /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
|
||||
|
||||
Optionally, edit your dnsmasq configuration file to your liking.
|
||||
|
||||
To start the launchd job, which starts dnsmaq, reboot or use the command:
|
||||
To start the launchd job, which starts dnsmasq, reboot or use the command:
|
||||
sudo launchctl load /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
|
||||
|
||||
To stop the launchd job, which stops dnsmasq, use the command:
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
This is a patch against SuSEfirewall2-3.1-206 (SuSE 9.x and older)
|
||||
It fixes the depancy from the dns daemon name 'named'
|
||||
It fixes the dependency from the dns daemon name 'named'
|
||||
After appending the patch, the SuSEfirewall is again able to autodetect
|
||||
the dnsmasq named service.
|
||||
This is a very old bug in the SuSEfirewall script.
|
||||
The SuSE people think the name of the dns server will allways 'named'
|
||||
The SuSE people think the name of the dns server will always 'named'
|
||||
|
||||
|
||||
--- /sbin/SuSEfirewall2.orig 2004-01-23 13:30:09.000000000 +0100
|
||||
|
||||
@@ -13,10 +13,10 @@ connection comes out of the other side. However, sometimes, we want to
|
||||
maintain that relationship through the proxy and continue the connection
|
||||
mark on packets upstream of our proxy
|
||||
|
||||
DNSMasq includes such a feature enabled by the --conntrack
|
||||
Dnsmasq includes such a feature enabled by the --conntrack
|
||||
option. This allows, for example, using iptables to mark traffic from
|
||||
a particular IP, and that mark to be persisted to requests made *by*
|
||||
DNSMasq. Such a feature could be useful for bandwidth accounting,
|
||||
Dnsmasq. Such a feature could be useful for bandwidth accounting,
|
||||
captive portals and the like. Note a similar feature has been
|
||||
implemented in Squid 2.2
|
||||
|
||||
@@ -40,7 +40,7 @@ on IP address. 3) Saves the firewall mark back to the connection mark
|
||||
(which will persist it across related packets)
|
||||
|
||||
4) is applied to the OUTPUT table, which is where we first see packets
|
||||
generated locally. DNSMasq will have already copied the firewall mark
|
||||
generated locally. Dnsmasq will have already copied the firewall mark
|
||||
from the request, across to the new packet, and so all that remains is
|
||||
for iptables to copy it to the connection mark so it's persisted across
|
||||
packets.
|
||||
|
||||
43
contrib/dbus-test/dbus-test.py
Executable file
43
contrib/dbus-test/dbus-test.py
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/python
|
||||
import dbus
|
||||
|
||||
bus = dbus.SystemBus()
|
||||
p = bus.get_object("uk.org.thekelleys.dnsmasq", "/uk/org/thekelleys/dnsmasq")
|
||||
l = dbus.Interface(p, dbus_interface="uk.org.thekelleys.dnsmasq")
|
||||
|
||||
# The new more flexible SetServersEx method
|
||||
array = dbus.Array()
|
||||
array.append(["1.2.3.5"])
|
||||
array.append(["1.2.3.4#664", "foobar.com"])
|
||||
array.append(["1003:1234:abcd::1%eth0", "eng.mycorp.com", "lab.mycorp.com"])
|
||||
print l.SetServersEx(array)
|
||||
|
||||
# Must create a new object for dnsmasq as the introspection gives the wrong
|
||||
# signature for SetServers (av) while the code only expects a bunch of arguments
|
||||
# instead of an array of variants
|
||||
p = bus.get_object("uk.org.thekelleys.dnsmasq", "/uk/org/thekelleys/dnsmasq", introspect=False)
|
||||
l = dbus.Interface(p, dbus_interface="uk.org.thekelleys.dnsmasq")
|
||||
|
||||
# The previous method; all addresses in machine byte order
|
||||
print l.SetServers(dbus.UInt32(16909060), # 1.2.3.5
|
||||
dbus.UInt32(16909061), # 1.2.3.4
|
||||
"foobar.com",
|
||||
dbus.Byte(0x10), # 1003:1234:abcd::1
|
||||
dbus.Byte(0x03),
|
||||
dbus.Byte(0x12),
|
||||
dbus.Byte(0x34),
|
||||
dbus.Byte(0xab),
|
||||
dbus.Byte(0xcd),
|
||||
dbus.Byte(0x00),
|
||||
dbus.Byte(0x00),
|
||||
dbus.Byte(0x00),
|
||||
dbus.Byte(0x00),
|
||||
dbus.Byte(0x00),
|
||||
dbus.Byte(0x00),
|
||||
dbus.Byte(0x00),
|
||||
dbus.Byte(0x00),
|
||||
dbus.Byte(0x00),
|
||||
dbus.Byte(0x01),
|
||||
"eng.mycorp.com",
|
||||
"lab.mycorp.com")
|
||||
|
||||
@@ -55,7 +55,7 @@ Index: src/dnsmasq.c
|
||||
}
|
||||
|
||||
@@ -434,7 +433,7 @@
|
||||
/* lose the setuid and setgid capbilities */
|
||||
/* lose the setuid and setgid capabilities */
|
||||
if (capset(hdr, data) == -1)
|
||||
{
|
||||
- send_event(err_pipe[1], EVENT_CAP_ERR, errno);
|
||||
|
||||
6
contrib/lease-tools/Makefile
Normal file
6
contrib/lease-tools/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
CFLAGS?= -O2 -Wall -W
|
||||
|
||||
all: dhcp_release dhcp_release6 dhcp_lease_time
|
||||
|
||||
clean:
|
||||
rm -f *~ *.o core dhcp_release dhcp_release6 dhcp_lease_time
|
||||
@@ -12,9 +12,11 @@ If an error occurs or no lease exists for the given address,
|
||||
nothing is sent to stdout a message is sent to stderr and a
|
||||
non-zero error code is returned.
|
||||
|
||||
Requires dnsmasq 2.40 or later and may not work with other DHCP servers.
|
||||
Requires dnsmasq 2.67 or later and may not work with other DHCP servers.
|
||||
|
||||
The address argument is a dotted-quad IP addresses and mandatory.
|
||||
The address argument is a dotted-quad IP addresses and mandatory.
|
||||
.SH LIMITATIONS
|
||||
Only works with IPv4 addresses and DHCP leases.
|
||||
.SH SEE ALSO
|
||||
.BR dnsmasq (8)
|
||||
.SH AUTHOR
|
||||
@@ -20,7 +20,7 @@
|
||||
nothing is sent to stdout a message is sent to stderr and a
|
||||
non-zero error code is returned.
|
||||
|
||||
Requires dnsmasq 2.40 or later.
|
||||
This version requires dnsmasq 2.67 or later.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -46,6 +46,7 @@
|
||||
#define OPTION_LEASE_TIME 51
|
||||
#define OPTION_OVERLOAD 52
|
||||
#define OPTION_MESSAGE_TYPE 53
|
||||
#define OPTION_REQUESTED_OPTIONS 55
|
||||
#define OPTION_END 255
|
||||
#define DHCPINFORM 8
|
||||
#define DHCP_SERVER_PORT 67
|
||||
@@ -82,7 +83,7 @@ static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt
|
||||
if (p >= end - 2)
|
||||
return NULL; /* malformed packet */
|
||||
opt_len = option_len(p);
|
||||
if (p >= end - (2 + opt_len))
|
||||
if (end - p >= (2 + opt_len))
|
||||
return NULL; /* malformed packet */
|
||||
if (*p == opt && opt_len >= minsize)
|
||||
return p;
|
||||
@@ -167,6 +168,12 @@ int main(int argc, char **argv)
|
||||
*(p++) = 1;
|
||||
*(p++) = DHCPINFORM;
|
||||
|
||||
/* Explicitly request the lease time, it won't be sent otherwise:
|
||||
this is a dnsmasq extension, not standard. */
|
||||
*(p++) = OPTION_REQUESTED_OPTIONS;
|
||||
*(p++) = 1;
|
||||
*(p++) = OPTION_LEASE_TIME;
|
||||
|
||||
*(p++) = OPTION_END;
|
||||
|
||||
dest.sin_family = AF_INET;
|
||||
@@ -199,13 +206,13 @@ int main(int argc, char **argv)
|
||||
{
|
||||
unsigned int x;
|
||||
if ((x = t/86400))
|
||||
printf("%dd", x);
|
||||
printf("%ud", x);
|
||||
if ((x = (t/3600)%24))
|
||||
printf("%dh", x);
|
||||
printf("%uh", x);
|
||||
if ((x = (t/60)%60))
|
||||
printf("%dm", x);
|
||||
printf("%um", x);
|
||||
if ((x = t%60))
|
||||
printf("%ds", x);
|
||||
printf("%us", x);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -27,6 +27,8 @@ for ethernet. This encoding is the one used in dnsmasq lease files.
|
||||
The client-id is optional. If it is "*" then it treated as being missing.
|
||||
.SH NOTES
|
||||
MUST be run as root - will fail otherwise.
|
||||
.SH LIMITATIONS
|
||||
Only usable on IPv4 DHCP leases.
|
||||
.SH SEE ALSO
|
||||
.BR dnsmasq (8)
|
||||
.SH AUTHOR
|
||||
@@ -117,7 +117,7 @@ static ssize_t netlink_recv(int fd)
|
||||
msg.msg_flags = 0;
|
||||
while ((rc = recvmsg(fd, &msg, MSG_PEEK)) == -1 && errno == EINTR);
|
||||
|
||||
/* 2.2.x doesn't suport MSG_PEEK at all, returning EOPNOTSUPP, so we just grab a
|
||||
/* 2.2.x doesn't support MSG_PEEK at all, returning EOPNOTSUPP, so we just grab a
|
||||
big buffer and pray in that case. */
|
||||
if (rc == -1 && errno == EOPNOTSUPP)
|
||||
{
|
||||
@@ -255,10 +255,6 @@ int main(int argc, char **argv)
|
||||
struct ifreq ifr;
|
||||
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
int nl = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
struct iovec iov;
|
||||
|
||||
iov.iov_len = 200;
|
||||
iov.iov_base = malloc(iov.iov_len);
|
||||
|
||||
if (argc < 4 || argc > 5)
|
||||
{
|
||||
@@ -274,13 +270,19 @@ int main(int argc, char **argv)
|
||||
|
||||
/* This voodoo fakes up a packet coming from the correct interface, which really matters for
|
||||
a DHCP server */
|
||||
strcpy(ifr.ifr_name, argv[1]);
|
||||
strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name)-1);
|
||||
ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1)
|
||||
{
|
||||
perror("cannot setup interface");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (inet_addr(argv[2]) == INADDR_NONE)
|
||||
{
|
||||
perror("invalid ip address");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
lease.s_addr = inet_addr(argv[2]);
|
||||
server = find_interface(lease, nl, if_nametoindex(argv[1]));
|
||||
38
contrib/lease-tools/dhcp_release6.1
Normal file
38
contrib/lease-tools/dhcp_release6.1
Normal file
@@ -0,0 +1,38 @@
|
||||
.TH DHCP_RELEASE 1
|
||||
.SH NAME
|
||||
dhcp_release6 \- Release a DHCPv6 lease on a the local dnsmasq DHCP server.
|
||||
.SH SYNOPSIS
|
||||
.B dhcp_release6 --iface <interface> --client-id <client-id> --server-id
|
||||
server-id --iaid <iaid> --ip <IP> [--dry-run] [--help]
|
||||
.SH "DESCRIPTION"
|
||||
A utility which forces the DHCP server running on this machine to release a
|
||||
DHCPv6 lease.
|
||||
.SS OPTIONS
|
||||
.IP "-a, --ip"
|
||||
IPv6 address to release.
|
||||
.IP "-c, --client-id"
|
||||
Colon-separated hex string representing DHCPv6 client id. Normally
|
||||
it can be found in leases file both on client and server.
|
||||
.IP "-d, --dry-run"
|
||||
Print hexadecimal representation of generated DHCPv6 release packet to standard
|
||||
output and exit.
|
||||
.IP "-h, --help"
|
||||
print usage information to standard output and exit.
|
||||
.IP "-i, --iaid"
|
||||
Decimal representation of DHCPv6 IAID. Normally it can be found in leases file
|
||||
both on client and server.
|
||||
.IP "-n, --iface"
|
||||
Network interface to send a DHCPv6 release packet from.
|
||||
.IP "-s, --server-id"
|
||||
Colon-separated hex string representing DHCPv6 server id. Normally
|
||||
it can be found in leases file both on client and server.
|
||||
.SH NOTES
|
||||
MUST be run as root - will fail otherwise.
|
||||
.SH LIMITATIONS
|
||||
Only usable on IPv6 DHCP leases.
|
||||
.SH SEE ALSO
|
||||
.BR dnsmasq (8)
|
||||
.SH AUTHOR
|
||||
This manual page was written by Simon Kelley <simon@thekelleys.org.uk>.
|
||||
|
||||
|
||||
499
contrib/lease-tools/dhcp_release6.c
Normal file
499
contrib/lease-tools/dhcp_release6.c
Normal file
@@ -0,0 +1,499 @@
|
||||
/*
|
||||
dhcp_release6 --iface <interface> --client-id <client-id> --server-id
|
||||
server-id --iaid <iaid> --ip <IP> [--dry-run] [--help]
|
||||
MUST be run as root - will fail otherwise
|
||||
*/
|
||||
|
||||
/* Send a DHCPRELEASE message to IPv6 multicast address via the specified interface
|
||||
to tell the local DHCP server to delete a particular lease.
|
||||
|
||||
The interface argument is the interface in which a DHCP
|
||||
request _would_ be received if it was coming from the client,
|
||||
rather than being faked up here.
|
||||
|
||||
The client-id argument is colon-separated hex string and mandatory. Normally
|
||||
it can be found in leases file both on client and server
|
||||
|
||||
The server-id argument is colon-separated hex string and mandatory. Normally
|
||||
it can be found in leases file both on client and server.
|
||||
|
||||
The iaid argument is numeric string and mandatory. Normally
|
||||
it can be found in leases file both on client and server.
|
||||
|
||||
IP is an IPv6 address to release
|
||||
|
||||
If --dry-run is specified, dhcp_release6 just prints hexadecimal representation of
|
||||
packet to send to stdout and exits.
|
||||
|
||||
If --help is specified, dhcp_release6 print usage information to stdout and exits
|
||||
|
||||
|
||||
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define NOT_REPLY_CODE 115
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
|
||||
enum DHCP6_TYPES
|
||||
{
|
||||
SOLICIT = 1,
|
||||
ADVERTISE = 2,
|
||||
REQUEST = 3,
|
||||
CONFIRM = 4,
|
||||
RENEW = 5,
|
||||
REBIND = 6,
|
||||
REPLY = 7,
|
||||
RELEASE = 8,
|
||||
DECLINE = 9,
|
||||
RECONFIGURE = 10,
|
||||
INFORMATION_REQUEST = 11,
|
||||
RELAY_FORW = 12,
|
||||
RELAY_REPL = 13
|
||||
|
||||
};
|
||||
|
||||
enum DHCP6_OPTIONS
|
||||
{
|
||||
CLIENTID = 1,
|
||||
SERVERID = 2,
|
||||
IA_NA = 3,
|
||||
IA_TA = 4,
|
||||
IAADDR = 5,
|
||||
ORO = 6,
|
||||
PREFERENCE = 7,
|
||||
ELAPSED_TIME = 8,
|
||||
RELAY_MSG = 9,
|
||||
AUTH = 11,
|
||||
UNICAST = 12,
|
||||
STATUS_CODE = 13,
|
||||
RAPID_COMMIT = 14,
|
||||
USER_CLASS = 15,
|
||||
VENDOR_CLASS = 16,
|
||||
VENDOR_OPTS = 17,
|
||||
INTERFACE_ID = 18,
|
||||
RECONF_MSG = 19,
|
||||
RECONF_ACCEPT = 20,
|
||||
};
|
||||
|
||||
enum DHCP6_STATUSES
|
||||
{
|
||||
SUCCESS = 0,
|
||||
UNSPEC_FAIL = 1,
|
||||
NOADDR_AVAIL=2,
|
||||
NO_BINDING = 3,
|
||||
NOT_ON_LINK = 4,
|
||||
USE_MULTICAST =5
|
||||
};
|
||||
|
||||
static struct option longopts[] = {
|
||||
{"ip", required_argument, 0, 'a' },
|
||||
{"server-id", required_argument, 0, 's' },
|
||||
{"client-id", required_argument, 0, 'c' },
|
||||
{"iface", required_argument, 0, 'n' },
|
||||
{"iaid", required_argument, 0, 'i' },
|
||||
{"dry-run", no_argument, 0, 'd' },
|
||||
{"help", no_argument, 0, 'h' },
|
||||
{0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
const short DHCP6_CLIENT_PORT = 546;
|
||||
const short DHCP6_SERVER_PORT = 547;
|
||||
|
||||
const char* DHCP6_MULTICAST_ADDRESS = "ff02::1:2";
|
||||
|
||||
struct dhcp6_option {
|
||||
uint16_t type;
|
||||
uint16_t len;
|
||||
char value[1024];
|
||||
};
|
||||
|
||||
struct dhcp6_iaaddr_option {
|
||||
uint16_t type;
|
||||
uint16_t len;
|
||||
struct in6_addr ip;
|
||||
uint32_t preferred_lifetime;
|
||||
uint32_t valid_lifetime;
|
||||
};
|
||||
|
||||
struct dhcp6_iana_option {
|
||||
uint16_t type;
|
||||
uint16_t len;
|
||||
uint32_t iaid;
|
||||
uint32_t t1;
|
||||
uint32_t t2;
|
||||
char options[1024];
|
||||
};
|
||||
|
||||
|
||||
struct dhcp6_packet {
|
||||
size_t len;
|
||||
char buf[2048];
|
||||
};
|
||||
|
||||
size_t pack_duid(const char* str, char* dst)
|
||||
{
|
||||
char* tmp = strdup(str);
|
||||
char* tmp_to_free = tmp;
|
||||
char *ptr;
|
||||
uint8_t write_pos = 0;
|
||||
while ((ptr = strtok (tmp, ":")))
|
||||
{
|
||||
dst[write_pos] = (uint8_t) strtol(ptr, NULL, 16);
|
||||
write_pos += 1;
|
||||
tmp = NULL;
|
||||
}
|
||||
|
||||
free(tmp_to_free);
|
||||
return write_pos;
|
||||
}
|
||||
|
||||
struct dhcp6_option create_client_id_option(const char* duid)
|
||||
{
|
||||
struct dhcp6_option option;
|
||||
option.type = htons(CLIENTID);
|
||||
bzero(option.value, sizeof(option.value));
|
||||
option.len = htons(pack_duid(duid, option.value));
|
||||
return option;
|
||||
}
|
||||
|
||||
struct dhcp6_option create_server_id_option(const char* duid)
|
||||
{
|
||||
struct dhcp6_option option;
|
||||
option.type = htons(SERVERID);
|
||||
bzero(option.value, sizeof(option.value));
|
||||
option.len = htons(pack_duid(duid, option.value));
|
||||
return option;
|
||||
}
|
||||
|
||||
struct dhcp6_iaaddr_option create_iaadr_option(const char* ip)
|
||||
{
|
||||
struct dhcp6_iaaddr_option result;
|
||||
result.type =htons(IAADDR);
|
||||
/* no suboptions needed here, so length is 24 */
|
||||
result.len = htons(24);
|
||||
result.preferred_lifetime = 0;
|
||||
result.valid_lifetime = 0;
|
||||
int s = inet_pton(AF_INET6, ip, &(result.ip));
|
||||
if (s <= 0) {
|
||||
if (s == 0)
|
||||
fprintf(stderr, "Not in presentation format");
|
||||
else
|
||||
perror("inet_pton");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct dhcp6_iana_option create_iana_option(const char * iaid, struct dhcp6_iaaddr_option ia_addr)
|
||||
{
|
||||
struct dhcp6_iana_option result;
|
||||
result.type = htons(IA_NA);
|
||||
result.iaid = htonl(atoi(iaid));
|
||||
result.t1 = 0;
|
||||
result.t2 = 0;
|
||||
result.len = htons(12 + ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
|
||||
memcpy(result.options, &ia_addr, ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
|
||||
return result;
|
||||
}
|
||||
|
||||
struct dhcp6_packet create_release_packet(const char* iaid, const char* ip, const char* client_id, const char* server_id)
|
||||
{
|
||||
struct dhcp6_packet result;
|
||||
bzero(result.buf, sizeof(result.buf));
|
||||
/* message_type */
|
||||
result.buf[0] = RELEASE;
|
||||
/* tx_id */
|
||||
bzero(result.buf+1, 3);
|
||||
|
||||
struct dhcp6_option client_option = create_client_id_option(client_id);
|
||||
struct dhcp6_option server_option = create_server_id_option(server_id);
|
||||
struct dhcp6_iaaddr_option iaaddr_option = create_iaadr_option(ip);
|
||||
struct dhcp6_iana_option iana_option = create_iana_option(iaid, iaaddr_option);
|
||||
int offset = 4;
|
||||
memcpy(result.buf + offset, &client_option, ntohs(client_option.len) + 2*sizeof(uint16_t));
|
||||
offset += (ntohs(client_option.len)+ 2 *sizeof(uint16_t) );
|
||||
memcpy(result.buf + offset, &server_option, ntohs(server_option.len) + 2*sizeof(uint16_t) );
|
||||
offset += (ntohs(server_option.len)+ 2* sizeof(uint16_t));
|
||||
memcpy(result.buf + offset, &iana_option, ntohs(iana_option.len) + 2*sizeof(uint16_t) );
|
||||
offset += (ntohs(iana_option.len)+ 2* sizeof(uint16_t));
|
||||
result.len = offset;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t parse_iana_suboption(char* buf, size_t len)
|
||||
{
|
||||
size_t current_pos = 0;
|
||||
char option_value[1024];
|
||||
while (current_pos < len)
|
||||
{
|
||||
uint16_t option_type, option_len;
|
||||
memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
|
||||
memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
|
||||
option_type = ntohs(option_type);
|
||||
option_len = ntohs(option_len);
|
||||
current_pos += 2 * sizeof(uint16_t);
|
||||
if (option_type == STATUS_CODE)
|
||||
{
|
||||
uint16_t status;
|
||||
memcpy(&status, buf + current_pos, sizeof(uint16_t));
|
||||
status = ntohs(status);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
memcpy(option_value, buf + current_pos + sizeof(uint16_t) , option_len - sizeof(uint16_t));
|
||||
option_value[option_len-sizeof(uint16_t)] ='\0';
|
||||
fprintf(stderr, "Error: %s\n", option_value);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
int16_t parse_packet(char* buf, size_t len)
|
||||
{
|
||||
int16_t ret = -1;
|
||||
uint8_t type = buf[0];
|
||||
/*skipping tx id. you need it, uncomment following line
|
||||
uint16_t tx_id = ntohs((buf[1] <<16) + (buf[2] <<8) + buf[3]);
|
||||
*/
|
||||
size_t current_pos = 4;
|
||||
if (type != REPLY )
|
||||
return NOT_REPLY_CODE;
|
||||
|
||||
char option_value[1024];
|
||||
while (current_pos < len)
|
||||
{
|
||||
uint16_t option_type, option_len;
|
||||
memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
|
||||
memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
|
||||
option_type = ntohs(option_type);
|
||||
option_len = ntohs(option_len);
|
||||
current_pos += 2 * sizeof(uint16_t);
|
||||
if (option_type == STATUS_CODE)
|
||||
{
|
||||
uint16_t status;
|
||||
memcpy(&status, buf + current_pos, sizeof(uint16_t));
|
||||
status = ntohs(status);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
memcpy(option_value, buf + current_pos +sizeof(uint16_t) , option_len -sizeof(uint16_t));
|
||||
fprintf(stderr, "Error: %d %s\n", status, option_value);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Got success status, return that if there's no specific error in an IA_NA. */
|
||||
ret = SUCCESS;
|
||||
}
|
||||
|
||||
if (option_type == IA_NA )
|
||||
{
|
||||
uint16_t result = parse_iana_suboption(buf + current_pos +24, option_len -24);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
|
||||
current_pos += option_len;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usage(const char* arg, FILE* stream)
|
||||
{
|
||||
const char* usage_string ="--ip IPv6 --iface IFACE --server-id SERVER_ID --client-id CLIENT_ID --iaid IAID [--dry-run] | --help";
|
||||
fprintf (stream, "Usage: %s %s\n", arg, usage_string);
|
||||
}
|
||||
|
||||
int send_release_packet(const char* iface, struct dhcp6_packet* packet)
|
||||
{
|
||||
struct sockaddr_in6 server_addr, client_addr;
|
||||
char response[1400];
|
||||
int sock = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||
int i = 0;
|
||||
if (sock < 0)
|
||||
{
|
||||
perror("creating socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(sock, SOL_SOCKET, 25, iface, strlen(iface)) == -1)
|
||||
{
|
||||
perror("SO_BINDTODEVICE");
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&server_addr, 0, sizeof(server_addr));
|
||||
server_addr.sin6_family = AF_INET6;
|
||||
client_addr.sin6_family = AF_INET6;
|
||||
client_addr.sin6_port = htons(DHCP6_CLIENT_PORT);
|
||||
client_addr.sin6_flowinfo = 0;
|
||||
client_addr.sin6_scope_id =0;
|
||||
inet_pton(AF_INET6, "::", &client_addr.sin6_addr);
|
||||
bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6));
|
||||
inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr);
|
||||
server_addr.sin6_port = htons(DHCP6_SERVER_PORT);
|
||||
int16_t recv_size = 0;
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
if (sendto(sock, packet->buf, packet->len, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
|
||||
{
|
||||
perror("sendto failed");
|
||||
exit(4);
|
||||
}
|
||||
|
||||
recv_size = recvfrom(sock, response, sizeof(response), MSG_DONTWAIT, NULL, 0);
|
||||
if (recv_size == -1)
|
||||
{
|
||||
if (errno == EAGAIN)
|
||||
{
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
perror("recvfrom");
|
||||
}
|
||||
}
|
||||
|
||||
int16_t result = parse_packet(response, recv_size);
|
||||
if (result == NOT_REPLY_CODE)
|
||||
{
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
close(sock);
|
||||
return result;
|
||||
}
|
||||
|
||||
close(sock);
|
||||
fprintf(stderr, "Response timed out\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char * const argv[])
|
||||
{
|
||||
const char* UNINITIALIZED = "";
|
||||
const char* iface = UNINITIALIZED;
|
||||
const char* ip = UNINITIALIZED;
|
||||
const char* client_id = UNINITIALIZED;
|
||||
const char* server_id = UNINITIALIZED;
|
||||
const char* iaid = UNINITIALIZED;
|
||||
int dry_run = 0;
|
||||
while (1)
|
||||
{
|
||||
int option_index = 0;
|
||||
int c = getopt_long(argc, argv, "a:s:c:n:i:hd", longopts, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case 0:
|
||||
if (longopts[option_index].flag !=0)
|
||||
break;
|
||||
|
||||
printf ("option %s", longopts[option_index].name);
|
||||
if (optarg)
|
||||
printf (" with arg %s", optarg);
|
||||
printf ("\n");
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
iaid = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
iface = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
ip = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
client_id = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
dry_run = 1;
|
||||
break;
|
||||
case 's':
|
||||
server_id = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
usage(argv[0], stdout);
|
||||
return 0;
|
||||
case '?':
|
||||
usage(argv[0], stderr);
|
||||
return -1;
|
||||
default:
|
||||
abort();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (iaid == UNINITIALIZED)
|
||||
{
|
||||
fprintf(stderr, "Missing required iaid parameter\n");
|
||||
usage(argv[0], stderr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (server_id == UNINITIALIZED)
|
||||
{
|
||||
fprintf(stderr, "Missing required server-id parameter\n");
|
||||
usage(argv[0], stderr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (client_id == UNINITIALIZED)
|
||||
{
|
||||
fprintf(stderr, "Missing required client-id parameter\n");
|
||||
usage(argv[0], stderr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ip == UNINITIALIZED)
|
||||
{
|
||||
fprintf(stderr, "Missing required ip parameter\n");
|
||||
usage(argv[0], stderr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (iface == UNINITIALIZED)
|
||||
{
|
||||
fprintf(stderr, "Missing required iface parameter\n");
|
||||
usage(argv[0], stderr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct dhcp6_packet packet = create_release_packet(iaid, ip, client_id, server_id);
|
||||
|
||||
if (dry_run)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
for(i=0; i<packet.len; i++)
|
||||
printf("%hhx", packet.buf[i]);
|
||||
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return send_release_packet(iface, &packet);
|
||||
}
|
||||
36
contrib/mactable/macscript
Executable file
36
contrib/mactable/macscript
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
|
||||
STATUS_FILE="/tmp/dnsmasq-ip-mac.status"
|
||||
|
||||
# Script for dnsmasq lease-change hook.
|
||||
# Maintains the above file with an IP address/MAC address pairs,
|
||||
# one lease per line. Works with IPv4 and IPv6 leases, file is
|
||||
# atomically updated, so no races for users of the data.
|
||||
|
||||
action="$1"
|
||||
mac="$2" # IPv4
|
||||
ip="$3"
|
||||
|
||||
# ensure it always exists.
|
||||
|
||||
if [ ! -f "$STATUS_FILE" ]; then
|
||||
touch "$STATUS_FILE"
|
||||
fi
|
||||
|
||||
if [ -n "$DNSMASQ_IAID" ]; then
|
||||
mac="$DNSMASQ_MAC" # IPv6
|
||||
fi
|
||||
|
||||
# worry about an add or old action when the MAC address is not known:
|
||||
# leave any old one in place in that case.
|
||||
|
||||
if [ "$action" = "add" -o "$action" = "old" -o "$action" = "del" ]; then
|
||||
if [ -n "$mac" -o "$action" = "del" ]; then
|
||||
sed "/^${ip//./\.} / d" "$STATUS_FILE" > "$STATUS_FILE".new
|
||||
|
||||
if [ "$action" = "add" -o "$action" = "old" ]; then
|
||||
echo "$ip $mac" >> "$STATUS_FILE".new
|
||||
fi
|
||||
mv "$STATUS_FILE".new "$STATUS_FILE" # atomic update.
|
||||
fi
|
||||
fi
|
||||
@@ -34,11 +34,21 @@ if [ ${DNSMASQ_OLD_HOSTNAME} ] && [ ${action} = old ] ; then
|
||||
hostname=${DNSMASQ_OLD_HOSTNAME}
|
||||
fi
|
||||
|
||||
# IPv6 leases are not our concern. no NAT there!
|
||||
if [ ${DNSMASQ_IAID} ] ; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# action init is not relevant, and will only be seen when leasefile-ro is set.
|
||||
if [ ${action} = init ] ; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# action tftp is not relevant.
|
||||
if [ ${action} = tftp ] ; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ${hostname} ]; then
|
||||
ports=$(sed -n -e "/^${hostname}\ .*/ s/^.* //p" ${PORTSFILE})
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# first column of this file, then a DNAT port-forward will be set up
|
||||
# to the address which has just been allocated by DHCP . The second field
|
||||
# is port number(s). If there is only one, then the port-forward goes to
|
||||
# the same port on the DHCP-client, if there are two seperated with a
|
||||
# the same port on the DHCP-client, if there are two separated with a
|
||||
# colon, then the second number is the port to which the connection
|
||||
# is forwarded on the DHCP-client. By default, forwarding is set up
|
||||
# for TCP, but it can done for UDP instead by prefixing the port to "u".
|
||||
|
||||
18
contrib/reverse-dns/README
Normal file
18
contrib/reverse-dns/README
Normal file
@@ -0,0 +1,18 @@
|
||||
The script reads stdin and replaces all IP addresses with names before
|
||||
outputting it again. IPs from private networks are reverse looked up
|
||||
via dns. Other IP addresses are searched for in the dnsmasq query log.
|
||||
This gives names (CNAMEs if I understand DNS correctly) that are closer
|
||||
to the name the client originally asked for then the names obtained by
|
||||
reverse lookup. Just run
|
||||
|
||||
netstat -n -4 | ./reverse_replace.sh
|
||||
|
||||
to see what it does. It needs
|
||||
|
||||
log-queries
|
||||
log-facility=/var/log/dnsmasq.log
|
||||
|
||||
in the dnsmasq configuration.
|
||||
|
||||
The script runs on debian (with ash installed) and on busybox.
|
||||
|
||||
125
contrib/reverse-dns/reverse_replace.sh
Normal file
125
contrib/reverse-dns/reverse_replace.sh
Normal file
@@ -0,0 +1,125 @@
|
||||
#!/bin/ash
|
||||
# $Id: reverse_replace.sh 18 2015-03-01 16:12:35Z jo $
|
||||
#
|
||||
# Usage e.g.: netstat -n -4 | reverse_replace.sh
|
||||
# Parses stdin for IP4 addresses and replaces them
|
||||
# with names retrieved by parsing the dnsmasq log.
|
||||
# This currently only gives CNAMEs. But these
|
||||
# usually tell you more than the ones from reverse
|
||||
# lookups.
|
||||
#
|
||||
# This has been tested on debian and asuswrt. Please
|
||||
# report successful tests on other platforms.
|
||||
#
|
||||
# Author: Joachim Zobel <jz-2014@heute-morgen.de>
|
||||
# License: Consider this MIT style licensed. You can
|
||||
# do as you ike, but you must not remove my name.
|
||||
#
|
||||
|
||||
LOG=/var/log/dnsmasq.log
|
||||
MAX_LINES=15000
|
||||
|
||||
# sed regex do match IPs
|
||||
IP_regex='[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'
|
||||
# private IP ranges
|
||||
IP_private='\(^127\.\)\|\(^192\.168\.\)\|\(^10\.\)\|\(^172\.1[6-9]\.\)\|\(^172\.2[0-9]\.\)\|\(^172\.3[0-1]\.\)'
|
||||
|
||||
#######################################################################
|
||||
# Find Commands
|
||||
|
||||
HOST=nslookup
|
||||
if type host > /dev/null 2>&1; then
|
||||
# echo "No need for nslookup, host is there"
|
||||
HOST=host
|
||||
fi
|
||||
|
||||
#######################################################################
|
||||
# Functions
|
||||
|
||||
# Use shell variables for an (IP) lookup table
|
||||
create_lookup_table()
|
||||
{
|
||||
# Parse log into lookup table
|
||||
local CMDS="$( tail -"$MAX_LINES" "$LOG" | \
|
||||
grep " is $IP_regex" | \
|
||||
sed "s#.* \([^ ]*\) is \($IP_regex\).*#set_val \2 \1;#" )"
|
||||
|
||||
local IFS='
|
||||
'
|
||||
for CMD in $CMDS
|
||||
do
|
||||
eval $CMD
|
||||
done
|
||||
}
|
||||
|
||||
set_val()
|
||||
{
|
||||
local _IP=$(echo $1 | tr . _)
|
||||
local KEY="__IP__$_IP"
|
||||
eval "$KEY"=$2
|
||||
}
|
||||
|
||||
get_val()
|
||||
{
|
||||
local _IP=$(echo $1 | tr . _)
|
||||
local KEY="__IP__$_IP"
|
||||
eval echo -n '${'"$KEY"'}'
|
||||
}
|
||||
|
||||
dns_lookup()
|
||||
{
|
||||
local IP=$1
|
||||
|
||||
local RTN="$($HOST $IP | \
|
||||
sed 's#\s\+#\n#g' | \
|
||||
grep -v '^$' | \
|
||||
tail -1 | tr -d '\n' | \
|
||||
sed 's#\.$##')"
|
||||
if echo $RTN | grep -q NXDOMAIN; then
|
||||
echo -n $IP
|
||||
else
|
||||
echo -n "$RTN"
|
||||
fi
|
||||
}
|
||||
|
||||
reverse_dns()
|
||||
{
|
||||
local IP=$1
|
||||
|
||||
# Skip if it is not an IP
|
||||
if ! echo $IP | grep -q "^$IP_regex$"; then
|
||||
echo -n $IP
|
||||
return
|
||||
fi
|
||||
|
||||
# Do a dns lookup, if it is a local IP
|
||||
if echo $IP | grep -q $IP_private; then
|
||||
dns_lookup $IP
|
||||
return
|
||||
fi
|
||||
|
||||
local NAME="$(get_val $IP)"
|
||||
|
||||
if [ -z "$NAME" ]; then
|
||||
echo -n $IP
|
||||
else
|
||||
echo -n $NAME
|
||||
fi
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
# Main
|
||||
create_lookup_table
|
||||
|
||||
while read LINE; do
|
||||
for IP in $(echo "$LINE" | \
|
||||
sed "s#\b\($IP_regex\)\b#\n\1\n#g" | \
|
||||
grep $IP_regex)
|
||||
do
|
||||
NAME=`reverse_dns $IP `
|
||||
# echo "$NAME $IP"
|
||||
LINE=`echo "$LINE" | sed "s#$IP#$NAME#" `
|
||||
done
|
||||
echo $LINE
|
||||
done
|
||||
|
||||
57
contrib/systemd/dbus_activation
Normal file
57
contrib/systemd/dbus_activation
Normal file
@@ -0,0 +1,57 @@
|
||||
To: dnsmasq-discuss@lists.thekelleys.org.uk
|
||||
From: Alex Elsayed <eternaleye+usenet@gmail.com>
|
||||
Date: Tue, 15 May 2012 01:53:54 -0700
|
||||
Subject: [Dnsmasq-discuss] [PATCH] Support dbus activation
|
||||
|
||||
Introduce dbus service file and turn dbus on in the systemd
|
||||
unit.
|
||||
|
||||
Note to packagers:
|
||||
To add support for dbus activation, you must install the dbus
|
||||
service file (dbus/uk.org.thekelleys.dnsmasq.service) into
|
||||
$DATADIR/dbus-1/system-services.
|
||||
|
||||
---
|
||||
contrib/systemd/dnsmasq.service | 2 +-
|
||||
dbus/uk.org.thekelleys.dnsmasq.service | 7 +++++++
|
||||
2 files changed, 8 insertions(+), 1 deletion(-)
|
||||
create mode 100644 dbus/uk.org.thekelleys.dnsmasq.service
|
||||
|
||||
diff --git a/contrib/systemd/dnsmasq.service
|
||||
b/contrib/systemd/dnsmasq.service
|
||||
index a27fe6d..4a784d3 100644
|
||||
--- a/contrib/systemd/dnsmasq.service
|
||||
+++ b/contrib/systemd/dnsmasq.service
|
||||
@@ -5,7 +5,7 @@ Description=A lightweight DHCP and caching DNS server
|
||||
Type=dbus
|
||||
BusName=uk.org.thekelleys.dnsmasq
|
||||
ExecStartPre=/usr/sbin/dnsmasq --test
|
||||
-ExecStart=/usr/sbin/dnsmasq -k
|
||||
+ExecStart=/usr/sbin/dnsmasq -k -1
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
|
||||
[Install]
|
||||
diff --git a/dbus/uk.org.thekelleys.dnsmasq.service
|
||||
b/dbus/uk.org.thekelleys.dnsmasq.service
|
||||
new file mode 100644
|
||||
index 0000000..f5fe98d
|
||||
--- /dev/null
|
||||
+++ b/dbus/uk.org.thekelleys.dnsmasq.service
|
||||
@@ -0,0 +1,7 @@
|
||||
+[D-BUS Service]
|
||||
+Name=uk.org.thekelleys.dnsmasq
|
||||
+Exec=/usr/sbin/dnsmasq -k -1
|
||||
+User=root
|
||||
+SystemdService=dnsmasq.service
|
||||
+
|
||||
+
|
||||
--
|
||||
1.7.10.2
|
||||
|
||||
|
||||
|
||||
_______________________________________________
|
||||
Dnsmasq-discuss mailing list
|
||||
Dnsmasq-discuss@lists.thekelleys.org.uk
|
||||
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[Unit]
|
||||
Description=A lightweight DHCP and caching DNS server
|
||||
Description=dnsmasq - A lightweight DHCP and caching DNS server
|
||||
|
||||
[Service]
|
||||
Type=dbus
|
||||
|
||||
@@ -2,7 +2,7 @@ A remake of patch Bob Carroll had posted to dnsmasq,
|
||||
now compatible with version 2.47. Hopefully he doesn't
|
||||
mind (sending a copy of this mail to him too).
|
||||
|
||||
Maybe the patch in question is not acceptible
|
||||
Maybe the patch in question is not acceptable
|
||||
as it doesn't add new switch, rather it binds itself to "strict-order".
|
||||
|
||||
What it does is: if you have strict-order in the
|
||||
|
||||
10
contrib/try-all-ns/README-2.78
Normal file
10
contrib/try-all-ns/README-2.78
Normal file
@@ -0,0 +1,10 @@
|
||||
Hi,
|
||||
I updated the try-all-ns patch to work with the latest version of git. Ended up implementing it on top of master, 2.78test2-7-g63437ff. As that specific if-clause has been changed in the last few commits, it's not compatible for 2.77, sadly.
|
||||
|
||||
Find the patch attached.
|
||||
|
||||
Regards,
|
||||
|
||||
Rasmus Ahlberg
|
||||
Software Developer, R&D
|
||||
Electrolux Small Appliances
|
||||
29
contrib/try-all-ns/dnsmasq-2.68-try-all-ns
Normal file
29
contrib/try-all-ns/dnsmasq-2.68-try-all-ns
Normal file
@@ -0,0 +1,29 @@
|
||||
From: Jesse Glick <jglick@cloudbees.com>
|
||||
To: dnsmasq-discuss@lists.thekelleys.org.uk
|
||||
Subject: Re: [Dnsmasq-discuss] Ability to delegate to one server but fall
|
||||
back to another after NXDOMAIN?
|
||||
|
||||
|
||||
On Wed, Jan 15, 2014 at 12:30 PM, Simon Kelley <simon@thekelleys.org.uk> wrote:
|
||||
> > There's a (very old) patch in contrib/try-all-ns that would make a starting point
|
||||
This does not apply against trunk, so I tried to rework it. The
|
||||
following appears to do what I expect:
|
||||
|
||||
diff --git a/src/forward.c b/src/forward.c
|
||||
index 8167229..76070b5 100644
|
||||
--- a/src/forward.c
|
||||
+++ b/src/forward.c
|
||||
@@ -610,7 +610,11 @@ void reply_query(int fd, int family, time_t now)
|
||||
|
||||
if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) &&
|
||||
!option_bool(OPT_ORDER) &&
|
||||
- forward->forwardall == 0)
|
||||
+ forward->forwardall == 0 ||
|
||||
+ /* try each in turn */
|
||||
+ RCODE(header) == NXDOMAIN &&
|
||||
+ option_bool(OPT_ORDER) &&
|
||||
+ server->next != NULL)
|
||||
/* for broken servers, attempt to send to another one. */
|
||||
{
|
||||
unsigned char *pheader;
|
||||
|
||||
20
contrib/try-all-ns/dnsmasq-2.78xx-try-all-ns.patch
Normal file
20
contrib/try-all-ns/dnsmasq-2.78xx-try-all-ns.patch
Normal file
@@ -0,0 +1,20 @@
|
||||
diff --git a/src/forward.c b/src/forward.c
|
||||
index e3fa94b..ecf3b98 100644
|
||||
--- a/src/forward.c
|
||||
+++ b/src/forward.c
|
||||
@@ -789,9 +789,12 @@ void reply_query(int fd, int family, time_t now)
|
||||
|
||||
/* Note: if we send extra options in the EDNS0 header, we can't recreate
|
||||
the query from the reply. */
|
||||
- if (RCODE(header) == REFUSED &&
|
||||
- forward->forwardall == 0 &&
|
||||
- !(forward->flags & FREC_HAS_EXTRADATA))
|
||||
+ if ((RCODE(header) == REFUSED &&
|
||||
+ forward->forwardall == 0 &&
|
||||
+ !(forward->flags & FREC_HAS_EXTRADATA)) ||
|
||||
+ /* If strict-order is set, try next server on NXDOMAIN reply */
|
||||
+ (RCODE(header) == NXDOMAIN && option_bool(OPT_ORDER) &&
|
||||
+ server->next != NULL))
|
||||
/* for broken servers, attempt to send to another one. */
|
||||
{
|
||||
unsigned char *pheader;
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
This is the README for the DNSmasq webmin module.
|
||||
This is the README for the Dnsmasq webmin module.
|
||||
|
||||
Problems:
|
||||
|
||||
@@ -48,7 +48,7 @@ wade through the config file and man pages again.
|
||||
|
||||
If you modify it, or add a language file, and you have a spare moment,
|
||||
please e-mail me - I won't be upset at all if you fix my poor coding!
|
||||
(rather the opposite - I'd be pleased someone found it usefull)
|
||||
(rather the opposite - I'd be pleased someone found it useful)
|
||||
|
||||
Cheers,
|
||||
Neil Fisher <neil@magnecor.com.au>
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
CFLAGS?= -O2 -Wall -W
|
||||
|
||||
all: dhcp_release dhcp_lease_time
|
||||
|
||||
clean:
|
||||
rm -f *~ *.o core dhcp_release dhcp_lease_time
|
||||
@@ -4,7 +4,7 @@ reboot, then it will eventually be restored as hosts renew their
|
||||
leases. Until a host renews (which may take hours/days) it will
|
||||
not exist in the DNS if dnsmasq's DDNS function is in use.
|
||||
|
||||
*WRT systems remount all non-volatile fileystems read-only after boot,
|
||||
*WRT systems remount all non-volatile filesystems read-only after boot,
|
||||
so the normal leasefile will not work. They do, however have NV
|
||||
storage, accessed with the nvram command:
|
||||
|
||||
@@ -62,7 +62,7 @@ about 100 bytes, so restricting the number of leases to 50 will limit
|
||||
use to half that. (The default limit in the distributed source is 150)
|
||||
|
||||
Any UI script which reads the dnsmasq leasefile will have to be
|
||||
ammended, probably by changing it to read the output of
|
||||
amended, probably by changing it to read the output of
|
||||
`lease_update init` instead.
|
||||
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@ and avoids startup races with the provider of nameserver information.
|
||||
|
||||
|
||||
Dnsmasq provides one service on the DBus: uk.org.thekelleys.dnsmasq
|
||||
and a single object: /uk/org/thekelleys/dnsmasq
|
||||
and a single object: /uk/org/thekelleys/dnsmasq
|
||||
The name of the service may be changed by giving an argument to --enable-dbus.
|
||||
|
||||
1. METHODS
|
||||
----------
|
||||
@@ -39,6 +40,14 @@ ClearCache
|
||||
Returns nothing. Clears the domain name cache and re-reads
|
||||
/etc/hosts. The same as sending dnsmasq a HUP signal.
|
||||
|
||||
SetFilterWin2KOption
|
||||
--------------------
|
||||
Takes boolean, sets or resets the --filterwin2k option.
|
||||
|
||||
SetBogusPrivOption
|
||||
------------------
|
||||
Takes boolean, sets or resets the --bogus-priv option.
|
||||
|
||||
SetServers
|
||||
----------
|
||||
Returns nothing. Takes a set of arguments representing the new
|
||||
@@ -94,6 +103,152 @@ Each call to SetServers completely replaces the set of servers
|
||||
specified by via the DBus, but it leaves any servers specified via the
|
||||
command line or /etc/dnsmasq.conf or /etc/resolv.conf alone.
|
||||
|
||||
SetServersEx
|
||||
------------
|
||||
|
||||
This function is more flexible and the SetServers function, in that it can
|
||||
handle address scoping, port numbers, and is easier for clients to use.
|
||||
|
||||
Returns nothing. Takes a set of arguments representing the new
|
||||
upstream DNS servers to be used by dnsmasq. All addresses (both IPv4 and IPv6)
|
||||
are represented as STRINGS. Each server address may be followed by one or more
|
||||
STRINGS, which are the domains for which the preceding server should be used.
|
||||
|
||||
This function takes an array of STRING arrays, where each inner array represents
|
||||
a set of DNS servers and domains for which those servers may be used. Each
|
||||
string represents a list of upstream DNS servers first, and domains second.
|
||||
Mixing of domains and servers within a the string array is not allowed.
|
||||
|
||||
Examples.
|
||||
|
||||
[
|
||||
["1.2.3.4", "foobar.com"],
|
||||
["1003:1234:abcd::1%eth0", "eng.mycorp.com", "lab.mycorp.com"]
|
||||
]
|
||||
|
||||
is equivalent to
|
||||
|
||||
--server=/foobar.com/1.2.3.4 \
|
||||
--server=/eng.mycorp.com/lab.mycorp.com/1003:1234:abcd::1%eth0
|
||||
|
||||
An IPv4 address of 0.0.0.0 is interpreted as "no address, local only",
|
||||
so
|
||||
|
||||
[ ["0.0.0.0", "local.domain"] ]
|
||||
|
||||
is equivalent to
|
||||
|
||||
--local=/local.domain/
|
||||
|
||||
|
||||
Each call to SetServersEx completely replaces the set of servers
|
||||
specified by via the DBus, but it leaves any servers specified via the
|
||||
command line or /etc/dnsmasq.conf or /etc/resolv.conf alone.
|
||||
|
||||
|
||||
SetDomainServers
|
||||
----------------
|
||||
|
||||
Yes another variation for setting DNS servers, with the capability of
|
||||
SetServersEx, but without using arrays of arrays, which are not
|
||||
sendable with dbus-send. The arguments are an array of strings which
|
||||
are identical to the equivalent arguments --server, so the example
|
||||
for SetServersEx is represented as
|
||||
|
||||
[
|
||||
"/foobar.com/1.2.3.4"
|
||||
"/eng.mycorp.com/lab.mycorp.com/1003:1234:abcd::1%eth0"
|
||||
]
|
||||
|
||||
GetLoopServers
|
||||
--------------
|
||||
|
||||
(Only available if dnsmasq compiled with HAVE_LOOP)
|
||||
|
||||
Return an array of strings, each string is the IP address of an upstream
|
||||
server which has been found to loop queries back to this dnsmasq instance, and
|
||||
it therefore not being used.
|
||||
|
||||
AddDhcpLease
|
||||
------------
|
||||
|
||||
Returns nothing. Adds or updates a DHCP or DHCPv6 lease to the internal lease
|
||||
database, as if a client requested and obtained a lease.
|
||||
|
||||
If a lease for the IPv4 or IPv6 address already exist, it is overwritten.
|
||||
|
||||
Note that this function will trigger the DhcpLeaseAdded or DhcpLeaseUpdated
|
||||
D-Bus signal and will run the configured DHCP lease script accordingly.
|
||||
|
||||
This function takes many arguments which are the lease parameters:
|
||||
- A string with the textual representation of the IPv4 or IPv6 address of the
|
||||
client.
|
||||
|
||||
Examples:
|
||||
"192.168.1.115"
|
||||
"1003:1234:abcd::1%eth0"
|
||||
"2001:db8:abcd::1"
|
||||
|
||||
- A string representing the hardware address of the client, using the same
|
||||
format as the one used in the lease database.
|
||||
|
||||
Examples:
|
||||
|
||||
"00:23:45:67:89:ab"
|
||||
"06-00:20:e0:3b:13:af" (token ring)
|
||||
|
||||
- The hostname of the client, as an array of bytes (so there is no problem
|
||||
with non-ASCII character encoding). May be empty.
|
||||
|
||||
Example (for "hostname.or.fqdn"):
|
||||
[104, 111, 115, 116, 110, 97, 109, 101, 46, 111, 114, 46, 102, 113, 100, 110]
|
||||
|
||||
- The client identifier (IPv4) or DUID (IPv6) as an array of bytes. May be
|
||||
empty.
|
||||
|
||||
Examples:
|
||||
|
||||
DHCPv6 DUID:
|
||||
[0, 3, 0, 1, 0, 35, 69, 103, 137, 171]
|
||||
DHCPv4 client identifier:
|
||||
[255, 12, 34, 56, 78, 0, 1, 0, 1, 29, 9, 99, 190, 35, 69, 103, 137, 171]
|
||||
|
||||
- The duration of the lease, in seconds. If the lease is updated, then
|
||||
the duration replaces the previous duration.
|
||||
|
||||
Example:
|
||||
|
||||
7200
|
||||
|
||||
- The IAID (Identity association identifier) of the DHCPv6 lease, as a network
|
||||
byte-order unsigned integer. For DHCPv4 leases, this must be set to 0.
|
||||
|
||||
Example (for IPv6):
|
||||
|
||||
203569230
|
||||
|
||||
- A boolean which, if true, indicates that the DHCPv6 lease is for a temporary
|
||||
address (IA_TA). If false, the DHCPv6 lease is for a non-temporary address
|
||||
(IA_NA). For DHCPv4 leases, this must be set to false.
|
||||
|
||||
RemoveDhcpLease
|
||||
---------------
|
||||
|
||||
Returns nothing. Removes a DHCP or DHCPv6 lease to the internal lease
|
||||
database, as if a client sent a release message to abandon a lease.
|
||||
|
||||
This function takes only one parameter: the text representation of the
|
||||
IPv4 or IPv6 address of the lease to remove.
|
||||
|
||||
Note that this function will trigger the DhcpLeaseRemoved signal and the
|
||||
configured DHCP lease script will be run with the "del" action.
|
||||
|
||||
GetMetrics
|
||||
----------
|
||||
|
||||
Returns an array with various metrics for DNS and DHCP.
|
||||
|
||||
|
||||
2. SIGNALS
|
||||
----------
|
||||
|
||||
|
||||
1353
debian/changelog
vendored
Normal file
1353
debian/changelog
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5
debian/conffiles
vendored
Normal file
5
debian/conffiles
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/etc/init.d/dnsmasq
|
||||
/etc/default/dnsmasq
|
||||
/etc/dnsmasq.conf
|
||||
/etc/resolvconf/update.d/dnsmasq
|
||||
/etc/insserv.conf.d/dnsmasq
|
||||
62
debian/control
vendored
Normal file
62
debian/control
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
Source: dnsmasq
|
||||
Section: net
|
||||
Priority: optional
|
||||
Build-depends: gettext, libnetfilter-conntrack-dev [linux-any],
|
||||
libidn11-dev, libdbus-1-dev (>=0.61), libgmp-dev,
|
||||
nettle-dev (>=2.4-3), libbsd-dev [!linux-any],
|
||||
liblua5.2-dev
|
||||
Maintainer: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Homepage: http://www.thekelleys.org.uk/dnsmasq/doc.html
|
||||
Standards-Version: 3.9.8
|
||||
|
||||
Package: dnsmasq
|
||||
Architecture: all
|
||||
Depends: netbase, dnsmasq-base,
|
||||
init-system-helpers (>= 1.18~), lsb-base (>= 3.0-6)
|
||||
Suggests: resolvconf
|
||||
Conflicts: resolvconf (<<1.15)
|
||||
Description: Small caching DNS proxy and DHCP/TFTP server
|
||||
Dnsmasq is a lightweight, easy to configure, DNS forwarder and DHCP
|
||||
server. It is designed to provide DNS and optionally, DHCP, to a
|
||||
small network. It can serve the names of local machines which are
|
||||
not in the global DNS. The DHCP server integrates with the DNS
|
||||
server and allows machines with DHCP-allocated addresses
|
||||
to appear in the DNS with names configured either in each host or
|
||||
in a central configuration file. Dnsmasq supports static and dynamic
|
||||
DHCP leases and BOOTP/TFTP for network booting of diskless machines.
|
||||
|
||||
Package: dnsmasq-base
|
||||
Architecture: any
|
||||
Depends: adduser, ${shlibs:Depends}
|
||||
Breaks: dnsmasq (<< 2.63-1~)
|
||||
Replaces: dnsmasq (<< 2.63-1~), dnsmasq-base
|
||||
Recommends: dns-root-data
|
||||
Provides: dnsmasq-base
|
||||
Conflicts: dnsmasq-base-lua
|
||||
Description: Small caching DNS proxy and DHCP/TFTP server
|
||||
This package contains the dnsmasq executable and documentation, but
|
||||
not the infrastructure required to run it as a system daemon. For
|
||||
that, install the dnsmasq package.
|
||||
|
||||
Package: dnsmasq-base-lua
|
||||
Architecture: any
|
||||
Depends: adduser, ${shlibs:Depends}
|
||||
Breaks: dnsmasq (<< 2.63-1~)
|
||||
Replaces: dnsmasq (<< 2.63-1~), dnsmasq-base
|
||||
Recommends: dns-root-data
|
||||
Provides: dnsmasq-base
|
||||
Conflicts: dnsmasq-base
|
||||
Description: Small caching DNS proxy and DHCP/TFTP server
|
||||
This package contains the dnsmasq executable and documentation, but
|
||||
not the infrastructure required to run it as a system daemon. For
|
||||
that, install the dnsmasq package. This package is an alternative
|
||||
to dnsmasq-base which includes the LUA interpreter.
|
||||
|
||||
Package: dnsmasq-utils
|
||||
Architecture: linux-any
|
||||
Depends: ${shlibs:Depends}
|
||||
Conflicts: dnsmasq (<<2.40)
|
||||
Description: Utilities for manipulating DHCP leases
|
||||
Small utilities to query a DHCP server's lease database and
|
||||
remove leases from it. These programs are distributed with dnsmasq
|
||||
and may not work correctly with other DHCP servers.
|
||||
21
debian/copyright
vendored
Normal file
21
debian/copyright
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||
|
||||
It was downloaded from: http://www.thekelleys.org.uk/dnsmasq/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or
|
||||
(at your option) version 3 dated 29 June, 2007.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
On Debian GNU/Linux systems, the text of the GNU general public license is
|
||||
available in the file /usr/share/common-licenses/GPL-2 or
|
||||
/usr/share/common-licenses/GPL-3
|
||||
|
||||
The Debian package of dnsmasq was created by Simon Kelley with assistance
|
||||
from Lars Bahner.
|
||||
|
||||
18
debian/dbus.conf
vendored
Normal file
18
debian/dbus.conf
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE busconfig PUBLIC
|
||||
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
<busconfig>
|
||||
<policy user="root">
|
||||
<allow own="uk.org.thekelleys.dnsmasq"/>
|
||||
<allow send_destination="uk.org.thekelleys.dnsmasq"/>
|
||||
</policy>
|
||||
<policy user="dnsmasq">
|
||||
<allow own="uk.org.thekelleys.dnsmasq"/>
|
||||
<allow send_destination="uk.org.thekelleys.dnsmasq"/>
|
||||
</policy>
|
||||
<policy context="default">
|
||||
<deny own="uk.org.thekelleys.dnsmasq"/>
|
||||
<deny send_destination="uk.org.thekelleys.dnsmasq"/>
|
||||
</policy>
|
||||
</busconfig>
|
||||
|
||||
33
debian/default
vendored
Normal file
33
debian/default
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# This file has five functions:
|
||||
# 1) to completely disable starting dnsmasq,
|
||||
# 2) to set DOMAIN_SUFFIX by running `dnsdomainname`
|
||||
# 3) to select an alternative config file
|
||||
# by setting DNSMASQ_OPTS to --conf-file=<file>
|
||||
# 4) to tell dnsmasq to read the files in /etc/dnsmasq.d for
|
||||
# more configuration variables.
|
||||
# 5) to stop the resolvconf package from controlling dnsmasq's
|
||||
# idea of which upstream nameservers to use.
|
||||
# For upgraders from very old versions, all the shell variables set
|
||||
# here in previous versions are still honored by the init script
|
||||
# so if you just keep your old version of this file nothing will break.
|
||||
|
||||
#DOMAIN_SUFFIX=`dnsdomainname`
|
||||
#DNSMASQ_OPTS="--conf-file=/etc/dnsmasq.alt"
|
||||
|
||||
# Whether or not to run the dnsmasq daemon; set to 0 to disable.
|
||||
ENABLED=1
|
||||
|
||||
# By default search this drop directory for configuration options.
|
||||
# Libvirt leaves a file here to make the system dnsmasq play nice.
|
||||
# Comment out this line if you don't want this. The dpkg-* are file
|
||||
# endings which cause dnsmasq to skip that file. This avoids pulling
|
||||
# in backups made by dpkg.
|
||||
CONFIG_DIR=/etc/dnsmasq.d,.dpkg-dist,.dpkg-old,.dpkg-new
|
||||
|
||||
# If the resolvconf package is installed, dnsmasq will use its output
|
||||
# rather than the contents of /etc/resolv.conf to find upstream
|
||||
# nameservers. Uncommenting this line inhibits this behaviour.
|
||||
# Note that including a "resolv-file=<filename>" line in
|
||||
# /etc/dnsmasq.conf is not enough to override resolvconf if it is
|
||||
# installed: the line below must be uncommented.
|
||||
#IGNORE_RESOLVCONF=yes
|
||||
1
debian/dnsmasq-base.conffiles
vendored
Normal file
1
debian/dnsmasq-base.conffiles
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/etc/dbus-1/system.d/dnsmasq.conf
|
||||
24
debian/dnsmasq-base.postinst
vendored
Normal file
24
debian/dnsmasq-base.postinst
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# Create the dnsmasq user in dnsmasq-base, so that Dbus doesn't complain.
|
||||
|
||||
# create a user to run as (code stolen from dovecot-common)
|
||||
if [ "$1" = "configure" ]; then
|
||||
if [ -z "`id -u dnsmasq 2> /dev/null`" ]; then
|
||||
adduser --system --home /var/lib/misc --gecos "dnsmasq" \
|
||||
--no-create-home --disabled-password \
|
||||
--quiet dnsmasq || true
|
||||
fi
|
||||
|
||||
# Make the directory where we keep the pid file - this
|
||||
# has to be owned by "dnsmasq" so that the file can be unlinked.
|
||||
# This is only actually used by the dnsmasq binary package, not
|
||||
# dnsmasq-base, but it's much easier to create it here so that
|
||||
# we don't have synchronisation issues with the creation of the
|
||||
# dnsmasq user.
|
||||
if [ ! -d /run/dnsmasq ]; then
|
||||
mkdir /run/dnsmasq
|
||||
chown dnsmasq:nogroup /run/dnsmasq
|
||||
fi
|
||||
fi
|
||||
11
debian/dnsmasq-base.postrm
vendored
Normal file
11
debian/dnsmasq-base.postrm
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
if [ purge = "$1" ]; then
|
||||
if [ -x "$(command -v deluser)" ]; then
|
||||
deluser --quiet --system dnsmasq > /dev/null || true
|
||||
else
|
||||
echo >&2 "not removing dnsmasq system account because deluser command was not found"
|
||||
fi
|
||||
rm -rf /run/dnsmasq
|
||||
fi
|
||||
321
debian/init
vendored
Normal file
321
debian/init
vendored
Normal file
@@ -0,0 +1,321 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: dnsmasq
|
||||
# Required-Start: $network $remote_fs $syslog
|
||||
# Required-Stop: $network $remote_fs $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Description: DHCP and DNS server
|
||||
### END INIT INFO
|
||||
|
||||
# Don't exit on error status
|
||||
set +e
|
||||
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
DAEMON=/usr/sbin/dnsmasq
|
||||
NAME=dnsmasq
|
||||
DESC="DNS forwarder and DHCP server"
|
||||
|
||||
# Most configuration options in /etc/default/dnsmasq are deprecated
|
||||
# but still honoured.
|
||||
ENABLED=1
|
||||
if [ -r /etc/default/$NAME ]; then
|
||||
. /etc/default/$NAME
|
||||
fi
|
||||
|
||||
# Get the system locale, so that messages are in the correct language, and the
|
||||
# charset for IDN is correct
|
||||
if [ -r /etc/default/locale ]; then
|
||||
. /etc/default/locale
|
||||
export LANG
|
||||
fi
|
||||
|
||||
# The following test ensures the dnsmasq service is not started, when the
|
||||
# package 'dnsmasq' is removed but not purged, even if the dnsmasq-base
|
||||
# package is still in place.
|
||||
test -e /usr/share/dnsmasq/installed-marker || exit 0
|
||||
|
||||
test -x $DAEMON || exit 0
|
||||
|
||||
# Provide skeleton LSB log functions for backports which don't have LSB functions.
|
||||
if [ -f /lib/lsb/init-functions ]; then
|
||||
. /lib/lsb/init-functions
|
||||
else
|
||||
log_warning_msg () {
|
||||
echo "${@}."
|
||||
}
|
||||
|
||||
log_success_msg () {
|
||||
echo "${@}."
|
||||
}
|
||||
|
||||
log_daemon_msg () {
|
||||
echo -n "${1}: $2"
|
||||
}
|
||||
|
||||
log_end_msg () {
|
||||
if [ $1 -eq 0 ]; then
|
||||
echo "."
|
||||
elif [ $1 -eq 255 ]; then
|
||||
/bin/echo -e " (warning)."
|
||||
else
|
||||
/bin/echo -e " failed!"
|
||||
fi
|
||||
}
|
||||
fi
|
||||
|
||||
# RESOLV_CONF:
|
||||
# If the resolvconf package is installed then use the resolv conf file
|
||||
# that it provides as the default. Otherwise use /etc/resolv.conf as
|
||||
# the default.
|
||||
#
|
||||
# If IGNORE_RESOLVCONF is set in /etc/default/dnsmasq or an explicit
|
||||
# filename is set there then this inhibits the use of the resolvconf-provided
|
||||
# information.
|
||||
#
|
||||
# Note that if the resolvconf package is installed it is not possible to
|
||||
# override it just by configuration in /etc/dnsmasq.conf, it is necessary
|
||||
# to set IGNORE_RESOLVCONF=yes in /etc/default/dnsmasq.
|
||||
|
||||
if [ ! "$RESOLV_CONF" ] &&
|
||||
[ "$IGNORE_RESOLVCONF" != "yes" ] &&
|
||||
[ -x /sbin/resolvconf ]
|
||||
then
|
||||
RESOLV_CONF=/run/dnsmasq/resolv.conf
|
||||
fi
|
||||
|
||||
for INTERFACE in $DNSMASQ_INTERFACE; do
|
||||
DNSMASQ_INTERFACES="$DNSMASQ_INTERFACES -i $INTERFACE"
|
||||
done
|
||||
|
||||
for INTERFACE in $DNSMASQ_EXCEPT; do
|
||||
DNSMASQ_INTERFACES="$DNSMASQ_INTERFACES -I $INTERFACE"
|
||||
done
|
||||
|
||||
if [ ! "$DNSMASQ_USER" ]; then
|
||||
DNSMASQ_USER="dnsmasq"
|
||||
fi
|
||||
|
||||
# This tells dnsmasq to ignore DNS requests that don't come from a local network.
|
||||
# It's automatically ignored if --interface --except-interface, --listen-address
|
||||
# or --auth-server exist in the configuration, so for most installations, it will
|
||||
# have no effect, but for otherwise-unconfigured installations, it stops dnsmasq
|
||||
# from being vulnerable to DNS-reflection attacks.
|
||||
|
||||
DNSMASQ_OPTS="$DNSMASQ_OPTS --local-service"
|
||||
|
||||
# If the dns-root-data package is installed, then the trust anchors will be
|
||||
# available in $ROOT_DS, in BIND zone-file format. Reformat as dnsmasq
|
||||
# --trust-anchor options.
|
||||
|
||||
ROOT_DS="/usr/share/dns/root.ds"
|
||||
|
||||
if [ -f $ROOT_DS ]; then
|
||||
DNSMASQ_OPTS="$DNSMASQ_OPTS `env LC_ALL=C sed -rne "s/^([.a-zA-Z0-9]+)([[:space:]]+[0-9]+)*([[:space:]]+IN)*[[:space:]]+DS[[:space:]]+/--trust-anchor=\1,/;s/[[:space:]]+/,/gp" $ROOT_DS | tr '\n' ' '`"
|
||||
fi
|
||||
|
||||
start()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been started
|
||||
# 1 if daemon was already running
|
||||
# 2 if daemon could not be started
|
||||
|
||||
# /run may be volatile, so we need to ensure that
|
||||
# /run/dnsmasq exists here as well as in postinst
|
||||
if [ ! -d /run/dnsmasq ]; then
|
||||
mkdir /run/dnsmasq || return 2
|
||||
chown dnsmasq:nogroup /run/dnsmasq || return 2
|
||||
fi
|
||||
[ -x /sbin/restorecon ] && /sbin/restorecon /run/dnsmasq
|
||||
|
||||
start-stop-daemon --start --quiet --pidfile /run/dnsmasq/$NAME.pid --exec $DAEMON --test > /dev/null || return 1
|
||||
start-stop-daemon --start --quiet --pidfile /run/dnsmasq/$NAME.pid --exec $DAEMON -- \
|
||||
-x /run/dnsmasq/$NAME.pid \
|
||||
${MAILHOSTNAME:+ -m $MAILHOSTNAME} \
|
||||
${MAILTARGET:+ -t $MAILTARGET} \
|
||||
${DNSMASQ_USER:+ -u $DNSMASQ_USER} \
|
||||
${DNSMASQ_INTERFACES:+ $DNSMASQ_INTERFACES} \
|
||||
${DHCP_LEASE:+ -l $DHCP_LEASE} \
|
||||
${DOMAIN_SUFFIX:+ -s $DOMAIN_SUFFIX} \
|
||||
${RESOLV_CONF:+ -r $RESOLV_CONF} \
|
||||
${CACHESIZE:+ -c $CACHESIZE} \
|
||||
${CONFIG_DIR:+ -7 $CONFIG_DIR} \
|
||||
${DNSMASQ_OPTS:+ $DNSMASQ_OPTS} \
|
||||
|| return 2
|
||||
}
|
||||
|
||||
start_resolvconf()
|
||||
{
|
||||
# If interface "lo" is explicitly disabled in /etc/default/dnsmasq
|
||||
# Then dnsmasq won't be providing local DNS, so don't add it to
|
||||
# the resolvconf server set.
|
||||
for interface in $DNSMASQ_EXCEPT
|
||||
do
|
||||
[ $interface = lo ] && return
|
||||
done
|
||||
|
||||
# Also skip this if DNS functionality is disabled in /etc/dnsmasq.conf
|
||||
if grep -qs '^port=0' /etc/dnsmasq.conf; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -x /sbin/resolvconf ] ; then
|
||||
echo "nameserver 127.0.0.1" | /sbin/resolvconf -a lo.$NAME
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
stop()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been stopped
|
||||
# 1 if daemon was already stopped
|
||||
# 2 if daemon could not be stopped
|
||||
# other if a failure occurred
|
||||
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile /run/dnsmasq/$NAME.pid --name $NAME
|
||||
}
|
||||
|
||||
stop_resolvconf()
|
||||
{
|
||||
if [ -x /sbin/resolvconf ] ; then
|
||||
/sbin/resolvconf -d lo.$NAME
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
status()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon is running
|
||||
# 1 if daemon is dead and pid file exists
|
||||
# 3 if daemon is not running
|
||||
# 4 if daemon status is unknown
|
||||
start-stop-daemon --start --quiet --pidfile /run/dnsmasq/$NAME.pid --exec $DAEMON --test > /dev/null
|
||||
case "$?" in
|
||||
0) [ -e "/run/dnsmasq/$NAME.pid" ] && return 1 ; return 3 ;;
|
||||
1) return 0 ;;
|
||||
*) return 4 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
test "$ENABLED" != "0" || exit 0
|
||||
log_daemon_msg "Starting $DESC" "$NAME"
|
||||
start
|
||||
case "$?" in
|
||||
0)
|
||||
log_end_msg 0
|
||||
start_resolvconf
|
||||
exit 0
|
||||
;;
|
||||
1)
|
||||
log_success_msg "(already running)"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
log_end_msg 1
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
stop)
|
||||
stop_resolvconf
|
||||
if [ "$ENABLED" != "0" ]; then
|
||||
log_daemon_msg "Stopping $DESC" "$NAME"
|
||||
fi
|
||||
stop
|
||||
RETVAL="$?"
|
||||
if [ "$ENABLED" = "0" ]; then
|
||||
case "$RETVAL" in
|
||||
0) log_daemon_msg "Stopping $DESC" "$NAME"; log_end_msg 0 ;;
|
||||
esac
|
||||
exit 0
|
||||
fi
|
||||
case "$RETVAL" in
|
||||
0) log_end_msg 0 ; exit 0 ;;
|
||||
1) log_warning_msg "(not running)" ; exit 0 ;;
|
||||
*) log_end_msg 1; exit 1 ;;
|
||||
esac
|
||||
;;
|
||||
restart|force-reload)
|
||||
test "$ENABLED" != "0" || exit 1
|
||||
$DAEMON --test ${CONFIG_DIR:+ -7 $CONFIG_DIR} ${DNSMASQ_OPTS:+ $DNSMASQ_OPTS} >/dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
NAME="configuration syntax check"
|
||||
RETVAL="2"
|
||||
else
|
||||
stop_resolvconf
|
||||
stop
|
||||
RETVAL="$?"
|
||||
fi
|
||||
log_daemon_msg "Restarting $DESC" "$NAME"
|
||||
case "$RETVAL" in
|
||||
0|1)
|
||||
sleep 2
|
||||
start
|
||||
case "$?" in
|
||||
0)
|
||||
log_end_msg 0
|
||||
start_resolvconf
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
log_end_msg 1
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
log_end_msg 1
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
status)
|
||||
log_daemon_msg "Checking $DESC" "$NAME"
|
||||
status
|
||||
case "$?" in
|
||||
0) log_success_msg "(running)" ; exit 0 ;;
|
||||
1) log_success_msg "(dead, pid file exists)" ; exit 1 ;;
|
||||
3) log_success_msg "(not running)" ; exit 3 ;;
|
||||
*) log_success_msg "(unknown)" ; exit 4 ;;
|
||||
esac
|
||||
;;
|
||||
dump-stats)
|
||||
kill -s USR1 `cat /run/dnsmasq/$NAME.pid`
|
||||
;;
|
||||
systemd-start-resolvconf)
|
||||
start_resolvconf
|
||||
;;
|
||||
systemd-stop-resolvconf)
|
||||
stop_resolvconf
|
||||
;;
|
||||
systemd-exec)
|
||||
# /run may be volatile, so we need to ensure that
|
||||
# /run/dnsmasq exists here as well as in postinst
|
||||
if [ ! -d /run/dnsmasq ]; then
|
||||
mkdir /run/dnsmasq || return 2
|
||||
chown dnsmasq:nogroup /run/dnsmasq || return 2
|
||||
fi
|
||||
exec $DAEMON -x /run/dnsmasq/$NAME.pid \
|
||||
${MAILHOSTNAME:+ -m $MAILHOSTNAME} \
|
||||
${MAILTARGET:+ -t $MAILTARGET} \
|
||||
${DNSMASQ_USER:+ -u $DNSMASQ_USER} \
|
||||
${DNSMASQ_INTERFACES:+ $DNSMASQ_INTERFACES} \
|
||||
${DHCP_LEASE:+ -l $DHCP_LEASE} \
|
||||
${DOMAIN_SUFFIX:+ -s $DOMAIN_SUFFIX} \
|
||||
${RESOLV_CONF:+ -r $RESOLV_CONF} \
|
||||
${CACHESIZE:+ -c $CACHESIZE} \
|
||||
${CONFIG_DIR:+ -7 $CONFIG_DIR} \
|
||||
${DNSMASQ_OPTS:+ $DNSMASQ_OPTS}
|
||||
;;
|
||||
*)
|
||||
echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload|dump-stats|status}" >&2
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
1
debian/insserv
vendored
Normal file
1
debian/insserv
vendored
Normal file
@@ -0,0 +1 @@
|
||||
$named dnsmasq
|
||||
2
debian/installed-marker
vendored
Normal file
2
debian/installed-marker
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# This file indicates dnsmasq (and not just dnsmasq-base) is installed.
|
||||
# It is an implementation detail of the dnsmasq init script.
|
||||
3
debian/lintian-override
vendored
Normal file
3
debian/lintian-override
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# dnsmasq-base and dnsmasq-base-lua are mutually exclusive and both
|
||||
# provide /usr/share/doc/dnsmasq-base
|
||||
dnsmasq-base-lua binary: usr-share-doc-symlink-without-dependency dnsmasq-base
|
||||
38
debian/postinst
vendored
Normal file
38
debian/postinst
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# Code copied from dh_systemd_enable ----------------------
|
||||
# This will only remove masks created by d-s-h on package removal.
|
||||
deb-systemd-helper unmask dnsmasq.service >/dev/null || true
|
||||
|
||||
# was-enabled defaults to true, so new installations run enable.
|
||||
if deb-systemd-helper --quiet was-enabled dnsmasq.service; then
|
||||
# Enables the unit on first installation, creates new
|
||||
# symlinks on upgrades if the unit file has changed.
|
||||
deb-systemd-helper enable dnsmasq.service >/dev/null || true
|
||||
else
|
||||
# Update the statefile to add new symlinks (if any), which need to be
|
||||
# cleaned up on purge. Also remove old symlinks.
|
||||
deb-systemd-helper update-state dnsmasq.service >/dev/null || true
|
||||
fi
|
||||
# End code copied from dh_systemd_enable ------------------
|
||||
|
||||
if [ -x /etc/init.d/dnsmasq ]; then
|
||||
update-rc.d dnsmasq defaults 15 85 >/dev/null
|
||||
|
||||
if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ]; then
|
||||
if [ -e /run/dnsmasq/dnsmasq.pid ]; then
|
||||
ACTION=restart
|
||||
else
|
||||
ACTION=start
|
||||
fi
|
||||
|
||||
if [ -x /usr/sbin/invoke-rc.d ] ; then
|
||||
invoke-rc.d dnsmasq $ACTION || true
|
||||
else
|
||||
/etc/init.d/dnsmasq $ACTION || true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
22
debian/postrm
vendored
Normal file
22
debian/postrm
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
if [ purge = "$1" ]; then
|
||||
update-rc.d dnsmasq remove >/dev/null
|
||||
fi
|
||||
|
||||
# Code copied from dh_systemd_enable ----------------------
|
||||
if [ "$1" = "remove" ]; then
|
||||
if [ -x "/usr/bin/deb-systemd-helper" ]; then
|
||||
deb-systemd-helper mask dnsmasq.service >/dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$1" = "purge" ]; then
|
||||
if [ -x "/usr/bin/deb-systemd-helper" ]; then
|
||||
deb-systemd-helper purge dnsmasq.service >/dev/null
|
||||
deb-systemd-helper unmask dnsmasq.service >/dev/null
|
||||
fi
|
||||
fi
|
||||
# End code copied from dh_systemd_enable ------------------
|
||||
|
||||
14
debian/prerm
vendored
Normal file
14
debian/prerm
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
if [ "$1" = "remove" ]; then
|
||||
if [ -x /usr/sbin/invoke-rc.d ] ; then
|
||||
invoke-rc.d dnsmasq stop || true
|
||||
else
|
||||
/etc/init.d/dnsmasq stop || true
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
|
||||
79
debian/readme
vendored
Normal file
79
debian/readme
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
Notes on configuring dnsmasq as packaged for Debian.
|
||||
|
||||
(1) To configure dnsmasq edit /etc/dnsmasq.conf. The file is well
|
||||
commented; see also the dnsmasq.8 man page for explanation of
|
||||
the options. The file /etc/default/dnsmasq also exists but it
|
||||
shouldn't need to be touched in most cases. To set up DHCP
|
||||
options you might need to refer to a copy of RFC 2132. This is
|
||||
available on Debian systems in the package doc-rfc-std as the file
|
||||
/usr/share/doc/RFC/draft-standard/rfc2132.txt.gz .
|
||||
|
||||
(2) Installing the dnsmasq package also creates the directory
|
||||
/etc/dnsmasq.d which is searched by dnsmasq for configuration file
|
||||
fragments. This behaviour can be disabled by editing
|
||||
/etc/default/dnsmasq.
|
||||
|
||||
(3) If the Debian resolvconf package is installed then, regardless
|
||||
of what interface configuration daemons are employed, the list of
|
||||
nameservers to which dnsmasq should forward queries can be found
|
||||
in /var/run/dnsmasq/resolv.conf; also, 127.0.0.1 is listed as the
|
||||
first nameserver address in /etc/resolv.conf. This works using the
|
||||
default configurations of resolvconf and dnsmasq.
|
||||
|
||||
(4) In the absence of resolvconf, if you are using dhcpcd then
|
||||
dnsmasq should read the list of nameservers from the automatically
|
||||
generated file /etc/dhcpc/resolv.conf. You should list 127.0.0.1
|
||||
as the first nameserver address in /etc/resolv.conf.
|
||||
|
||||
(5) In the absence of resolvconf, if you are using pppd then
|
||||
dnsmasq should read the list of nameservers from the automatically
|
||||
generated file /etc/ppp/resolv.conf. You should list 127.0.0.1
|
||||
as the first nameserver address in /etc/resolv.conf.
|
||||
|
||||
(6) In the absence of resolvconf, dns-nameservers lines in
|
||||
/etc/network/interfaces are ignored. If you do not use
|
||||
resolvconf, list 127.0.0.1 as the first nameserver address
|
||||
in /etc/resolv.conf and configure your nameservers using
|
||||
"server=<IP-address>" lines in /etc/dnsmasq.conf.
|
||||
|
||||
(7) If you run multiple DNS servers on a single machine, each
|
||||
listening on a different interface, then it is necessary to use
|
||||
the bind-interfaces option by uncommenting "bind-interfaces" in
|
||||
/etc/dnsmasq.conf. This option stops dnsmasq from binding the
|
||||
wildcard address and allows servers listening on port 53 on
|
||||
interfaces not in use by dnsmasq to work. The Debian
|
||||
libvirt package will add a configuration file in /etc/dnsmasq.d
|
||||
which does this so that the "system" dnsmasq and "private" dnsmasq
|
||||
instances started by libvirt do not clash.
|
||||
|
||||
(8) The following options are supported in DEB_BUILD_OPTIONS
|
||||
noopt : compile without optimisation.
|
||||
nostrip : don't remove symbols from binary.
|
||||
nodocs : omit documentation.
|
||||
notftp : omit TFTP support.
|
||||
nodhcp : omit DHCP support.
|
||||
nodhcp6 : omit DHCPv6 support.
|
||||
noscript : omit lease-change script support.
|
||||
uselua : provide support for lease-change scripts written
|
||||
in Lua.
|
||||
noipv6 : omit IPv6 support.
|
||||
nodbus : omit DBus support.
|
||||
noconntrack : omit connection tracking support.
|
||||
noipset : omit IPset support.
|
||||
nortc : compile alternate mode suitable for systems without an RTC.
|
||||
noi18n : omit translations and internationalisation support.
|
||||
noidn : omit international domain name support, must be
|
||||
combined with noi18n to be effective.
|
||||
gitversion : set the version of the produced packages from the
|
||||
git-derived versioning information on the source,
|
||||
rather than the debian changelog.
|
||||
|
||||
(9) Dnsmasq comes as three packages - dnsmasq-utils, dnsmasq-base and
|
||||
dnsmasq. Dnsmasq-base provides the dnsmasq executable and
|
||||
documentation (including this file). Dnsmasq, which depends on
|
||||
dnsmasq-base, provides the init script and configuration
|
||||
infrastructure. This file assumes that both are installed. It is
|
||||
possible to install only dnsmasq-base and use dnsmasq as a
|
||||
non-"system" daemon. Libvirt, for instance, does this.
|
||||
Dnsmasq-utils provides the utilities dhcp_release and
|
||||
dhcp_lease_time.
|
||||
7
debian/readme.dnsmasq.d
vendored
Normal file
7
debian/readme.dnsmasq.d
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# All files in this directory will be read by dnsmasq as
|
||||
# configuration files, except if their names end in
|
||||
# ".dpkg-dist",".dpkg-old" or ".dpkg-new"
|
||||
#
|
||||
# This can be changed by editing /etc/default/dnsmasq
|
||||
|
||||
|
||||
84
debian/resolvconf
vendored
Normal file
84
debian/resolvconf
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Script to update the resolver list for dnsmasq
|
||||
#
|
||||
# N.B. Resolvconf may run us even if dnsmasq is not (yet) running.
|
||||
# If dnsmasq is installed then we go ahead and update the resolver list
|
||||
# in case dnsmasq is started later.
|
||||
#
|
||||
# Assumption: On entry, PWD contains the resolv.conf-type files.
|
||||
#
|
||||
# This file is part of the dnsmasq package.
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
RUN_DIR="/run/dnsmasq"
|
||||
RSLVRLIST_FILE="${RUN_DIR}/resolv.conf"
|
||||
TMP_FILE="${RSLVRLIST_FILE}_new.$$"
|
||||
MY_NAME_FOR_RESOLVCONF="dnsmasq"
|
||||
|
||||
[ -x /usr/sbin/dnsmasq ] || exit 0
|
||||
[ -x /lib/resolvconf/list-records ] || exit 1
|
||||
|
||||
PATH=/bin:/sbin
|
||||
|
||||
report_err() { echo "$0: Error: $*" >&2 ; }
|
||||
|
||||
# Stores arguments (minus duplicates) in RSLT, separated by spaces
|
||||
# Doesn't work properly if an argument itself contains whitespace
|
||||
uniquify()
|
||||
{
|
||||
RSLT=""
|
||||
while [ "$1" ] ; do
|
||||
for E in $RSLT ; do
|
||||
[ "$1" = "$E" ] && { shift ; continue 2 ; }
|
||||
done
|
||||
RSLT="${RSLT:+$RSLT }$1"
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
if [ ! -d "$RUN_DIR" ] && ! mkdir --parents --mode=0755 "$RUN_DIR" ; then
|
||||
report_err "Failed trying to create directory $RUN_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RSLVCNFFILES=""
|
||||
for F in $(/lib/resolvconf/list-records --after "lo.$MY_NAME_FOR_RESOLVCONF") ; do
|
||||
case "$F" in
|
||||
"lo.$MY_NAME_FOR_RESOLVCONF")
|
||||
# Omit own record
|
||||
;;
|
||||
lo.*)
|
||||
# Include no more records after one for a local nameserver
|
||||
RSLVCNFFILES="${RSLVCNFFILES:+$RSLVCNFFILES }$F"
|
||||
break
|
||||
;;
|
||||
*)
|
||||
RSLVCNFFILES="${RSLVCNFFILES:+$RSLVCNFFILES }$F"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
NMSRVRS=""
|
||||
if [ "$RSLVCNFFILES" ] ; then
|
||||
uniquify $(sed -n -e 's/^[[:space:]]*nameserver[[:space:]]\+//p' $RSLVCNFFILES)
|
||||
NMSRVRS="$RSLT"
|
||||
fi
|
||||
|
||||
# Dnsmasq uses the mtime of $RSLVRLIST_FILE, with a resolution of one second,
|
||||
# to detect changes in the file. This means that if a resolvconf update occurs
|
||||
# within one second of the previous one then dnsmasq may fail to notice the
|
||||
# more recent change. To work around this problem we sleep one second here
|
||||
# if necessary in order to ensure that the new mtime is different.
|
||||
if [ -f "$RSLVRLIST_FILE" ] && [ "$(ls -go --time-style='+%s' "$RSLVRLIST_FILE" | { read p h s t n ; echo "$t" ; })" = "$(date +%s)" ] ; then
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
clean_up() { rm -f "$TMP_FILE" ; }
|
||||
trap clean_up EXIT
|
||||
: >| "$TMP_FILE"
|
||||
for N in $NMSRVRS ; do echo "nameserver $N" >> "$TMP_FILE" ; done
|
||||
mv -f "$TMP_FILE" "$RSLVRLIST_FILE"
|
||||
|
||||
13
debian/resolvconf-package
vendored
Normal file
13
debian/resolvconf-package
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
# Resolvconf packaging event hook script for the dnsmasq package
|
||||
restart_dnsmasq() {
|
||||
if which invoke-rc.d >/dev/null 2>&1 ; then
|
||||
invoke-rc.d dnsmasq restart
|
||||
elif [ -x /etc/init.d/dnsmasq ] ; then
|
||||
/etc/init.d/dnsmasq restart
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
install) restart_dnsmasq ;;
|
||||
esac
|
||||
291
debian/rules
vendored
Executable file
291
debian/rules
vendored
Executable file
@@ -0,0 +1,291 @@
|
||||
#!/usr/bin/make -f
|
||||
# debian/rules file - for dnsmasq.
|
||||
# Copyright 2001-2018 by Simon Kelley
|
||||
# Based on the sample in the debian hello package which carries the following:
|
||||
# Copyright 1994,1995 by Ian Jackson.
|
||||
# I hereby give you perpetual unlimited permission to copy,
|
||||
# modify and relicense this file, provided that you do not remove
|
||||
# my name from the file itself. (I assert my moral right of
|
||||
# paternity under the Copyright, Designs and Patents Act 1988.)
|
||||
# This file may have to be extensively modified
|
||||
|
||||
package=dnsmasq-base
|
||||
|
||||
dpkg_buildflags := DEB_BUILD_MAINT_OPTIONS="hardening=+all,+pie,+bindnow" dpkg-buildflags
|
||||
|
||||
CFLAGS = $(shell $(dpkg_buildflags) --get CFLAGS)
|
||||
CFLAGS += $(shell $(dpkg_buildflags) --get CPPFLAGS)
|
||||
CFLAGS += -Wall -W
|
||||
|
||||
LDFLAGS = $(shell $(dpkg_buildflags) --get LDFLAGS)
|
||||
|
||||
DEB_COPTS = $(COPTS)
|
||||
|
||||
TARGET = install-i18n
|
||||
|
||||
DEB_HOST_ARCH_OS := $(shell dpkg-architecture -qDEB_HOST_ARCH_OS)
|
||||
DEB_HOST_GNU_TYPE := $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
|
||||
DEB_BUILD_GNU_TYPE := $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
|
||||
BUILD_DATE := $(shell dpkg-parsechangelog --show-field Date)
|
||||
|
||||
ifeq ($(origin CC),default)
|
||||
CC = $(DEB_HOST_GNU_TYPE)-gcc
|
||||
endif
|
||||
|
||||
# Support non-cross-builds on systems without gnu-triplet-binaries for pkg-config.
|
||||
ifeq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
|
||||
PKG_CONFIG=pkg-config
|
||||
else
|
||||
PKG_CONFIG=$(DEB_HOST_GNU_TYPE)-pkg-config
|
||||
endif
|
||||
|
||||
# Force package version based on git tags.
|
||||
ifneq (,$(filter gitversion,$(DEB_BUILD_OPTIONS)))
|
||||
PACKAGE_VERSION = $(shell bld/get-version `pwd` | sed 's/test/~&/; s/[a-z]/~&/; s/-/./g; s/$$/-1/; s/^/-v/';)
|
||||
endif
|
||||
|
||||
ifeq (,$(filter nodbus,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DHAVE_DBUS
|
||||
endif
|
||||
|
||||
ifeq (,$(filter noidn, $(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DHAVE_IDN
|
||||
endif
|
||||
|
||||
ifeq (,$(filter noconntrack,$(DEB_BUILD_OPTIONS)))
|
||||
ifeq ($(DEB_HOST_ARCH_OS),linux)
|
||||
DEB_COPTS += -DHAVE_CONNTRACK
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter noipset,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DNO_IPSET
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nodhcp6,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DNO_DHCP6
|
||||
endif
|
||||
|
||||
ifneq (,$(filter noipv6,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DNO_IPV6
|
||||
endif
|
||||
|
||||
ifneq (,$(filter notftp,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DNO_TFTP
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nodhcp,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DNO_DHCP
|
||||
endif
|
||||
|
||||
ifneq (,$(filter noscript,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DNO_SCRIPT
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nortc,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DHAVE_BROKEN_RTC
|
||||
endif
|
||||
|
||||
ifneq (,$(filter noi18n,$(DEB_BUILD_OPTIONS)))
|
||||
TARGET = install
|
||||
endif
|
||||
|
||||
ifneq (,$(filter uselua,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DHAVE_LUASCRIPT
|
||||
endif
|
||||
|
||||
ifeq (,$(filter nodnssec,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DHAVE_DNSSEC
|
||||
endif
|
||||
|
||||
ifneq ($(DEB_HOST_ARCH_OS),linux)
|
||||
# For strlcpy in FreeBSD
|
||||
LDFLAGS += -lbsd
|
||||
endif
|
||||
|
||||
define build_tree
|
||||
rm -rf $1
|
||||
install -m 755 \
|
||||
-d $1/DEBIAN \
|
||||
-d $1/etc/dbus-1/system.d \
|
||||
-d $1/usr/share/doc/$(package) \
|
||||
-d $1/usr/share/doc/$(package)/examples \
|
||||
-d $1/usr/share/$(package) \
|
||||
-d $1/var/lib/misc
|
||||
|
||||
endef
|
||||
|
||||
define add_docs
|
||||
# Need to remove paypal links in Debian Package for policy reasons.
|
||||
sed -e /\<H2\>Donations/Q -e /icon.png/d doc.html -e /favicon.ico/d >$1/usr/share/doc/$(package)/doc.html
|
||||
echo "</BODY>" >>$1/usr/share/doc/$(package)/doc.html
|
||||
install -m 644 setup.html $1/usr/share/doc/$(package)/.
|
||||
install -m 644 dnsmasq.conf.example $1/usr/share/doc/$(package)/examples/.
|
||||
install -m 644 FAQ $1/usr/share/doc/$(package)/.
|
||||
gzip -9n $1/usr/share/doc/$(package)/FAQ
|
||||
install -m 644 CHANGELOG $1/usr/share/doc/$(package)/changelog
|
||||
gzip -9n $1/usr/share/doc/$(package)/changelog
|
||||
install -m 644 CHANGELOG.archive $1/usr/share/doc/$(package)/changelog.archive
|
||||
gzip -9n $1/usr/share/doc/$(package)/changelog.archive
|
||||
install -m 644 dbus/DBus-interface $1/usr/share/doc/$(package)/.
|
||||
gzip -9n $1/usr/share/doc/$(package)/DBus-interface
|
||||
gzip -9n $1/usr/share/man/man8/dnsmasq.8
|
||||
for f in $1/usr/share/man/*; do \
|
||||
if [ -f $$f/man8/dnsmasq.8 ]; then \
|
||||
gzip -9n $$f/man8/dnsmasq.8 ; \
|
||||
fi \
|
||||
done
|
||||
endef
|
||||
|
||||
define add_files
|
||||
install -m 644 trust-anchors.conf $1/usr/share/$(package)/.
|
||||
install -m 644 debian/dnsmasq-base.conffiles $1/DEBIAN/conffiles
|
||||
install -m 755 debian/dnsmasq-base.postinst $1/DEBIAN/postinst
|
||||
install -m 755 debian/dnsmasq-base.postrm $1/DEBIAN/postrm
|
||||
install -m 644 debian/changelog $1/usr/share/doc/$(package)/changelog.Debian
|
||||
gzip -9n $1/usr/share/doc/$(package)/changelog.Debian
|
||||
install -m 644 debian/readme $1/usr/share/doc/$(package)/README.Debian
|
||||
install -m 644 debian/copyright $1/usr/share/doc/$(package)/copyright
|
||||
install -m 644 debian/dbus.conf $1/etc/dbus-1/system.d/dnsmasq.conf
|
||||
endef
|
||||
|
||||
clean:
|
||||
$(checkdir)
|
||||
make BUILDDIR=debian/build/no-lua clean
|
||||
make BUILDDIR=debian/build/lua clean
|
||||
make -C contrib/lease-tools clean
|
||||
rm -rf debian/build debian/trees debian/*~ debian/files debian/substvars debian/utils-substvars
|
||||
|
||||
binary-indep: checkroot
|
||||
$(checkdir)
|
||||
rm -rf debian/trees/daemon
|
||||
install -m 755 \
|
||||
-d debian/trees/daemon/DEBIAN \
|
||||
-d debian/trees/daemon/usr/share/doc \
|
||||
-d debian/trees/daemon/etc/init.d \
|
||||
-d debian/trees/daemon/etc/dnsmasq.d \
|
||||
-d debian/trees/daemon/etc/resolvconf/update.d \
|
||||
-d debian/trees/daemon/usr/lib/resolvconf/dpkg-event.d \
|
||||
-d debian/trees/daemon/usr/share/dnsmasq \
|
||||
-d debian/trees/daemon/etc/default \
|
||||
-d debian/trees/daemon/lib/systemd/system \
|
||||
-d debian/trees/daemon/usr/lib/tmpfiles.d \
|
||||
-d debian/trees/daemon/etc/insserv.conf.d
|
||||
install -m 644 debian/conffiles debian/trees/daemon/DEBIAN
|
||||
install -m 755 debian/postinst debian/postrm debian/prerm debian/trees/daemon/DEBIAN
|
||||
install -m 755 debian/init debian/trees/daemon/etc/init.d/dnsmasq
|
||||
install -m 755 debian/resolvconf debian/trees/daemon/etc/resolvconf/update.d/dnsmasq
|
||||
install -m 755 debian/resolvconf-package debian/trees/daemon/usr/lib/resolvconf/dpkg-event.d/dnsmasq
|
||||
install -m 644 debian/installed-marker debian/trees/daemon/usr/share/dnsmasq
|
||||
install -m 644 debian/default debian/trees/daemon/etc/default/dnsmasq
|
||||
install -m 644 dnsmasq.conf.example debian/trees/daemon/etc/dnsmasq.conf
|
||||
install -m 644 debian/readme.dnsmasq.d debian/trees/daemon/etc/dnsmasq.d/README
|
||||
install -m 644 debian/systemd.service debian/trees/daemon/lib/systemd/system/dnsmasq.service
|
||||
install -m 644 debian/tmpfiles.conf debian/trees/daemon/usr/lib/tmpfiles.d/dnsmasq.conf
|
||||
install -m 644 debian/insserv debian/trees/daemon/etc/insserv.conf.d/dnsmasq
|
||||
ln -s $(package) debian/trees/daemon/usr/share/doc/dnsmasq
|
||||
cd debian/trees/daemon && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||
dpkg-gencontrol $(PACKAGE_VERSION) -T -pdnsmasq -Pdebian/trees/daemon
|
||||
find debian/trees/daemon -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||
chown -R root.root debian/trees/daemon
|
||||
chmod -R g-ws debian/trees/daemon
|
||||
dpkg --build debian/trees/daemon ..
|
||||
|
||||
binary-arch: checkroot
|
||||
$(call build_tree,debian/trees/base)
|
||||
make $(TARGET) BUILDDIR=debian/build/no-lua PREFIX=/usr DESTDIR=`pwd`/debian/trees/base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG)
|
||||
ifeq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS)))
|
||||
$(call add_docs,debian/trees/base)
|
||||
else
|
||||
rm -rf debian/trees/base/usr/share/man
|
||||
endif
|
||||
$(call add_files,debian/trees/base)
|
||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/base/usr/sbin/dnsmasq
|
||||
endif
|
||||
cd debian/trees/base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||
dpkg-shlibdeps --warnings=1 debian/trees/base/usr/sbin/dnsmasq
|
||||
dpkg-gencontrol $(PACKAGE_VERSION) -pdnsmasq-base -Pdebian/trees/base
|
||||
find debian/trees/base -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||
chown -R root.root debian/trees/base
|
||||
chmod -R g-ws debian/trees/base
|
||||
dpkg --build debian/trees/base ..
|
||||
|
||||
$(call build_tree,debian/trees/lua-base)
|
||||
make $(TARGET) BUILDDIR=debian/build/lua PREFIX=/usr DESTDIR=`pwd`/debian/trees/lua-base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="-DHAVE_LUASCRIPT $(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG)
|
||||
ifeq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS)))
|
||||
$(call add_docs,debian/trees/lua-base)
|
||||
else
|
||||
rm -rf debian/trees/lua-base/usr/share/man
|
||||
endif
|
||||
$(call add_files,debian/trees/lua-base)
|
||||
install -m 755 -d debian/trees/lua-base/usr/share/lintian/overrides
|
||||
install -m 644 debian/lintian-override debian/trees/lua-base/usr/share/lintian/overrides/dnsmasq-base-lua
|
||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/lua-base/usr/sbin/dnsmasq
|
||||
endif
|
||||
ln -s $(package) debian/trees/lua-base/usr/share/doc/dnsmasq-base-lua
|
||||
cd debian/trees/lua-base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||
dpkg-shlibdeps --warnings=1 debian/trees/lua-base/usr/sbin/dnsmasq
|
||||
dpkg-gencontrol $(PACKAGE_VERSION) -pdnsmasq-base-lua -Pdebian/trees/lua-base
|
||||
find debian/trees/lua-base -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||
chown -R root.root debian/trees/lua-base
|
||||
chmod -R g-ws debian/trees/lua-base
|
||||
dpkg --build debian/trees/lua-base ..
|
||||
|
||||
|
||||
ifeq ($(DEB_HOST_ARCH_OS),linux)
|
||||
rm -rf debian/trees/utils
|
||||
install -m 755 -d debian/trees/utils/DEBIAN \
|
||||
-d debian/trees/utils/usr/bin \
|
||||
-d debian/trees/utils/usr/share/doc/dnsmasq-utils
|
||||
ifeq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS)))
|
||||
install -m 755 -d debian/trees/utils/usr/share/man/man1
|
||||
endif
|
||||
make -C contrib/lease-tools PREFIX=/usr DESTDIR=`pwd`/debian/trees/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG)
|
||||
install -m 755 contrib/lease-tools/dhcp_release debian/trees/utils/usr/bin/dhcp_release
|
||||
install -m 755 contrib/lease-tools/dhcp_release6 debian/trees/utils/usr/bin/dhcp_release6
|
||||
install -m 755 contrib/lease-tools/dhcp_lease_time debian/trees/utils/usr/bin/dhcp_lease_time
|
||||
ifeq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS)))
|
||||
install -m 644 contrib/lease-tools/dhcp_release.1 debian/trees/utils/usr/share/man/man1/dhcp_release.1
|
||||
gzip -9n debian/trees/utils/usr/share/man/man1/dhcp_release.1
|
||||
install -m 644 contrib/lease-tools/dhcp_release6.1 debian/trees/utils/usr/share/man/man1/dhcp_release6.1
|
||||
gzip -9n debian/trees/utils/usr/share/man/man1/dhcp_release6.1
|
||||
install -m 644 contrib/lease-tools/dhcp_lease_time.1 debian/trees/utils/usr/share/man/man1/dhcp_lease_time.1
|
||||
gzip -9n debian/trees/utils/usr/share/man/man1/dhcp_lease_time.1
|
||||
endif
|
||||
install -m 644 debian/copyright debian/trees/utils/usr/share/doc/dnsmasq-utils/copyright
|
||||
install -m 644 debian/changelog debian/trees/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
||||
gzip -9n debian/trees/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/utils/usr/bin/dhcp_release
|
||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/utils/usr/bin/dhcp_release6
|
||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/utils/usr/bin/dhcp_lease_time
|
||||
endif
|
||||
cd debian/trees/utils && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||
dpkg-shlibdeps -Tdebian/utils-substvars debian/trees/utils/usr/bin/dhcp_release debian/trees/utils/usr/bin/dhcp_release6 debian/trees/utils/usr/bin/dhcp_lease_time
|
||||
dpkg-gencontrol $(PACKAGE_VERSION) -Tdebian/utils-substvars -pdnsmasq-utils -Pdebian/trees/utils
|
||||
find debian/trees/utils -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||
chown -R root.root debian/trees/utils
|
||||
chmod -R g-ws debian/trees/utils
|
||||
dpkg --build debian/trees/utils ..
|
||||
endif
|
||||
|
||||
define checkdir
|
||||
test -f Makefile -a -f debian/rules
|
||||
endef
|
||||
|
||||
# Below here is fairly generic really
|
||||
|
||||
binary: binary-arch binary-indep
|
||||
|
||||
build:
|
||||
build-arch:
|
||||
build-indep:
|
||||
|
||||
checkroot:
|
||||
test root = "`whoami`"
|
||||
|
||||
.PHONY: binary binary-arch binary-indep clean checkroot
|
||||
|
||||
|
||||
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
@@ -0,0 +1 @@
|
||||
1.0
|
||||
31
debian/systemd.service
vendored
Normal file
31
debian/systemd.service
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
[Unit]
|
||||
Description=dnsmasq - A lightweight DHCP and caching DNS server
|
||||
Requires=network.target
|
||||
Wants=nss-lookup.target
|
||||
Before=nss-lookup.target
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
PIDFile=/run/dnsmasq/dnsmasq.pid
|
||||
|
||||
# Test the config file and refuse starting if it is not valid.
|
||||
ExecStartPre=/usr/sbin/dnsmasq --test
|
||||
|
||||
# We run dnsmasq via the /etc/init.d/dnsmasq script which acts as a
|
||||
# wrapper picking up extra configuration files and then execs dnsmasq
|
||||
# itself, when called with the "systemd-exec" function.
|
||||
ExecStart=/etc/init.d/dnsmasq systemd-exec
|
||||
|
||||
# The systemd-*-resolvconf functions configure (and deconfigure)
|
||||
# resolvconf to work with the dnsmasq DNS server. They're called like
|
||||
# this to get correct error handling (ie don't start-resolvconf if the
|
||||
# dnsmasq daemon fails to start.
|
||||
ExecStartPost=/etc/init.d/dnsmasq systemd-start-resolvconf
|
||||
ExecStop=/etc/init.d/dnsmasq systemd-stop-resolvconf
|
||||
|
||||
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
1
debian/tmpfiles.conf
vendored
Normal file
1
debian/tmpfiles.conf
vendored
Normal file
@@ -0,0 +1 @@
|
||||
d /run/dnsmasq 755 dnsmasq nogroup
|
||||
@@ -4,6 +4,11 @@
|
||||
# as the long options legal on the command line. See
|
||||
# "/usr/sbin/dnsmasq --help" or "man 8 dnsmasq" for details.
|
||||
|
||||
# Listen on this specific port instead of the standard DNS port
|
||||
# (53). Setting this to zero completely disables DNS function,
|
||||
# leaving only DHCP and/or TFTP.
|
||||
#port=5353
|
||||
|
||||
# The following two options make you a better netizen, since they
|
||||
# tell dnsmasq to filter out queries which the public DNS cannot
|
||||
# answer, and which load the servers (especially the root servers)
|
||||
@@ -15,6 +20,18 @@
|
||||
# Never forward addresses in the non-routed address spaces.
|
||||
#bogus-priv
|
||||
|
||||
# Uncomment these to enable DNSSEC validation and caching:
|
||||
# (Requires dnsmasq to be built with DNSSEC option.)
|
||||
#conf-file=%%PREFIX%%/share/dnsmasq/trust-anchors.conf
|
||||
#dnssec
|
||||
|
||||
# Replies which are not DNSSEC signed may be legitimate, because the domain
|
||||
# is unsigned, or may be forgeries. Setting this option tells dnsmasq to
|
||||
# check that an unsigned reply is OK, by finding a secure proof that a DS
|
||||
# record somewhere between the root and the domain does not exist.
|
||||
# The cost of setting this is that even queries in unsigned domains will need
|
||||
# one or more extra DNS queries to verify.
|
||||
#dnssec-check-unsigned
|
||||
|
||||
# Uncomment this to filter useless windows-originated DNS requests
|
||||
# which can trigger dial-on-demand links needlessly.
|
||||
@@ -64,12 +81,16 @@
|
||||
# --address (and --server) work with IPv6 addresses too.
|
||||
#address=/www.thekelleys.org.uk/fe80::20d:60ff:fe36:f83
|
||||
|
||||
# Add the IPs of all queries to yahoo.com, google.com, and their
|
||||
# subdomains to the vpn and search ipsets:
|
||||
#ipset=/yahoo.com/google.com/vpn,search
|
||||
|
||||
# You can control how dnsmasq talks to a server: this forces
|
||||
# queries to 10.1.2.3 to be routed via eth1
|
||||
# server=10.1.2.3@eth1
|
||||
|
||||
# and this sets the source (ie local) address used to talk to
|
||||
# 10.1.2.3 to 192.168.1.1 port 55 (there must be a interface with that
|
||||
# 10.1.2.3 to 192.168.1.1 port 55 (there must be an interface with that
|
||||
# IP on the machine, obviously).
|
||||
# server=10.1.2.3@192.168.1.1#55
|
||||
|
||||
@@ -157,6 +178,44 @@
|
||||
# an explicit netmask instead.
|
||||
#dhcp-range=192.168.0.0,static
|
||||
|
||||
# Enable DHCPv6. Note that the prefix-length does not need to be specified
|
||||
# and defaults to 64 if missing/
|
||||
#dhcp-range=1234::2, 1234::500, 64, 12h
|
||||
|
||||
# Do Router Advertisements, BUT NOT DHCP for this subnet.
|
||||
#dhcp-range=1234::, ra-only
|
||||
|
||||
# Do Router Advertisements, BUT NOT DHCP for this subnet, also try and
|
||||
# add names to the DNS for the IPv6 address of SLAAC-configured dual-stack
|
||||
# hosts. Use the DHCPv4 lease to derive the name, network segment and
|
||||
# MAC address and assume that the host will also have an
|
||||
# IPv6 address calculated using the SLAAC algorithm.
|
||||
#dhcp-range=1234::, ra-names
|
||||
|
||||
# Do Router Advertisements, BUT NOT DHCP for this subnet.
|
||||
# Set the lifetime to 46 hours. (Note: minimum lifetime is 2 hours.)
|
||||
#dhcp-range=1234::, ra-only, 48h
|
||||
|
||||
# Do DHCP and Router Advertisements for this subnet. Set the A bit in the RA
|
||||
# so that clients can use SLAAC addresses as well as DHCP ones.
|
||||
#dhcp-range=1234::2, 1234::500, slaac
|
||||
|
||||
# Do Router Advertisements and stateless DHCP for this subnet. Clients will
|
||||
# not get addresses from DHCP, but they will get other configuration information.
|
||||
# They will use SLAAC for addresses.
|
||||
#dhcp-range=1234::, ra-stateless
|
||||
|
||||
# Do stateless DHCP, SLAAC, and generate DNS names for SLAAC addresses
|
||||
# from DHCPv4 leases.
|
||||
#dhcp-range=1234::, ra-stateless, ra-names
|
||||
|
||||
# Do router advertisements for all subnets where we're doing DHCPv6
|
||||
# Unless overridden by ra-stateless, ra-names, et al, the router
|
||||
# advertisements will have the M and O bits set, so that the clients
|
||||
# get addresses and configuration from DHCPv6, and the A bit reset, so the
|
||||
# clients don't use SLAAC addresses.
|
||||
#enable-ra
|
||||
|
||||
# Supply parameters for specified hosts using DHCP. There are lots
|
||||
# of valid alternatives, so we will give examples of each. Note that
|
||||
# IP addresses DO NOT have to be in the range given above, they just
|
||||
@@ -192,6 +251,13 @@
|
||||
# the IP address 192.168.0.60
|
||||
#dhcp-host=id:01:02:02:04,192.168.0.60
|
||||
|
||||
# Always give the InfiniBand interface with hardware address
|
||||
# 80:00:00:48:fe:80:00:00:00:00:00:00:f4:52:14:03:00:28:05:81 the
|
||||
# ip address 192.168.0.61. The client id is derived from the prefix
|
||||
# ff:00:00:00:00:00:02:00:00:02:c9:00 and the last 8 pairs of
|
||||
# hex digits of the hardware address.
|
||||
#dhcp-host=id:ff:00:00:00:00:00:02:00:00:02:c9:00:f4:52:14:03:00:28:05:81,192.168.0.61
|
||||
|
||||
# Always give the host with client identifier "marjorie"
|
||||
# the IP address 192.168.0.60
|
||||
#dhcp-host=id:marjorie,192.168.0.60
|
||||
@@ -219,7 +285,13 @@
|
||||
# any machine with Ethernet address starting 11:22:33:
|
||||
#dhcp-host=11:22:33:*:*:*,set:red
|
||||
|
||||
# Ignore any clients which are specified in dhcp-host lines
|
||||
# Give a fixed IPv6 address and name to client with
|
||||
# DUID 00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2
|
||||
# Note the MAC addresses CANNOT be used to identify DHCPv6 clients.
|
||||
# Note also that the [] around the IPv6 address are obligatory.
|
||||
#dhcp-host=id:00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2, fred, [1234::5]
|
||||
|
||||
# Ignore any clients which are not specified in dhcp-host lines
|
||||
# or /etc/ethers. Equivalent to ISC "deny unknown-clients".
|
||||
# This relies on the special "known" tag which is set when
|
||||
# a host is matched.
|
||||
@@ -270,6 +342,24 @@
|
||||
# Set the NTP time server addresses to 192.168.0.4 and 10.10.0.5
|
||||
#dhcp-option=option:ntp-server,192.168.0.4,10.10.0.5
|
||||
|
||||
# Send DHCPv6 option. Note [] around IPv6 addresses.
|
||||
#dhcp-option=option6:dns-server,[1234::77],[1234::88]
|
||||
|
||||
# Send DHCPv6 option for namservers as the machine running
|
||||
# dnsmasq and another.
|
||||
#dhcp-option=option6:dns-server,[::],[1234::88]
|
||||
|
||||
# Ask client to poll for option changes every six hours. (RFC4242)
|
||||
#dhcp-option=option6:information-refresh-time,6h
|
||||
|
||||
# Set option 58 client renewal time (T1). Defaults to half of the
|
||||
# lease time if not specified. (RFC2132)
|
||||
#dhcp-option=option:T1,1m
|
||||
|
||||
# Set option 59 rebinding time (T2). Defaults to 7/8 of the
|
||||
# lease time if not specified. (RFC2132)
|
||||
#dhcp-option=option:T2,2m
|
||||
|
||||
# Set the NTP time server address to be the same machine as
|
||||
# is running dnsmasq
|
||||
#dhcp-option=42,0.0.0.0
|
||||
@@ -304,6 +394,9 @@
|
||||
#dhcp-option=45,0.0.0.0 # netbios datagram distribution server
|
||||
#dhcp-option=46,8 # netbios node type
|
||||
|
||||
# Send an empty WPAD option. This may be REQUIRED to get windows 7 to behave.
|
||||
#dhcp-option=252,"\n"
|
||||
|
||||
# Send RFC-3397 DNS domain search DHCP option. WARNING: Your DHCP client
|
||||
# probably doesn't support this......
|
||||
#dhcp-option=option:domain-search,eng.apple.com,marketing.apple.com
|
||||
@@ -343,22 +436,22 @@
|
||||
#dhcp-option-force=211,30i
|
||||
|
||||
# Set the boot filename for netboot/PXE. You will only need
|
||||
# this is you want to boot machines over the network and you will need
|
||||
# a TFTP server; either dnsmasq's built in TFTP server or an
|
||||
# this if you want to boot machines over the network and you will need
|
||||
# a TFTP server; either dnsmasq's built-in TFTP server or an
|
||||
# external one. (See below for how to enable the TFTP server.)
|
||||
#dhcp-boot=pxelinux.0
|
||||
|
||||
# The same as above, but use custom tftp-server instead machine running dnsmasq
|
||||
#dhcp-boot=pxelinux,server.name,192.168.1.100
|
||||
|
||||
# Boot for Etherboot gPXE. The idea is to send two different
|
||||
# filenames, the first loads gPXE, and the second tells gPXE what to
|
||||
# load. The dhcp-match sets the gpxe tag for requests from gPXE.
|
||||
#dhcp-match=set:gpxe,175 # gPXE sends a 175 option.
|
||||
#dhcp-boot=tag:!gpxe,undionly.kpxe
|
||||
#dhcp-boot=mybootimage
|
||||
# Boot for iPXE. The idea is to send two different
|
||||
# filenames, the first loads iPXE, and the second tells iPXE what to
|
||||
# load. The dhcp-match sets the ipxe tag for requests from iPXE.
|
||||
#dhcp-boot=undionly.kpxe
|
||||
#dhcp-match=set:ipxe,175 # iPXE sends a 175 option.
|
||||
#dhcp-boot=tag:ipxe,http://boot.ipxe.org/demo/boot.php
|
||||
|
||||
# Encapsulated options for Etherboot gPXE. All the options are
|
||||
# Encapsulated options for iPXE. All the options are
|
||||
# encapsulated within option 175
|
||||
#dhcp-option=encap:175, 1, 5b # priority code
|
||||
#dhcp-option=encap:175, 176, 1b # no-proxydhcp
|
||||
@@ -408,6 +501,9 @@
|
||||
# Set the root directory for files available via FTP.
|
||||
#tftp-root=/var/ftpd
|
||||
|
||||
# Do not abort if the tftp-root is unavailable
|
||||
#tftp-no-fail
|
||||
|
||||
# Make the TFTP server more secure: with this set, only files owned by
|
||||
# the user dnsmasq is running as will be send over the net.
|
||||
#tftp-secure
|
||||
@@ -418,7 +514,7 @@
|
||||
#tftp-no-blocksize
|
||||
|
||||
# Set the boot file name only when the "red" tag is set.
|
||||
#dhcp-boot=net:red,pxelinux.red-net
|
||||
#dhcp-boot=tag:red,pxelinux.red-net
|
||||
|
||||
# An example of dhcp-boot with an external TFTP server: the name and IP
|
||||
# address of the server are given after the filename.
|
||||
@@ -429,7 +525,7 @@
|
||||
# (using /etc/hosts) then that name can be specified as the
|
||||
# tftp_servername (the third option to dhcp-boot) and in that
|
||||
# case dnsmasq resolves this name and returns the resultant IP
|
||||
# addresses in round robin fasion. This facility can be used to
|
||||
# addresses in round robin fashion. This facility can be used to
|
||||
# load balance the tftp load among a set of servers.
|
||||
#dhcp-boot=/var/ftpd/pxelinux.0,boothost,tftp_server_name
|
||||
|
||||
@@ -451,6 +547,14 @@
|
||||
# http://www.isc.org/files/auth.html
|
||||
#dhcp-authoritative
|
||||
|
||||
# Set the DHCP server to enable DHCPv4 Rapid Commit Option per RFC 4039.
|
||||
# In this mode it will respond to a DHCPDISCOVER message including a Rapid Commit
|
||||
# option with a DHCPACK including a Rapid Commit option and fully committed address
|
||||
# and configuration information. This must only be enabled if either the server is
|
||||
# the only server for the subnet, or multiple servers are present and they each
|
||||
# commit a binding for all clients.
|
||||
#dhcp-rapid-commit
|
||||
|
||||
# Run an executable when a DHCP lease is created or destroyed.
|
||||
# The arguments sent to the script are "add" or "del",
|
||||
# then the MAC address, the IP address and finally the hostname
|
||||
@@ -463,7 +567,7 @@
|
||||
# If you want to disable negative caching, uncomment this.
|
||||
#no-negcache
|
||||
|
||||
# Normally responses which come form /etc/hosts and the DHCP lease
|
||||
# Normally responses which come from /etc/hosts and the DHCP lease
|
||||
# file have Time-To-Live set as zero, which conventionally means
|
||||
# do not cache further. If you are happy to trade lower load on the
|
||||
# server for potentially stale date, you can set a time-to-live (in
|
||||
@@ -559,6 +663,17 @@
|
||||
# Log lots of extra information about DHCP transactions.
|
||||
#log-dhcp
|
||||
|
||||
# Include a another lot of configuration options.
|
||||
# Include another lot of configuration options.
|
||||
#conf-file=/etc/dnsmasq.more.conf
|
||||
#conf-dir=/etc/dnsmasq.d
|
||||
|
||||
# Include all the files in a directory except those ending in .bak
|
||||
#conf-dir=/etc/dnsmasq.d,.bak
|
||||
|
||||
# Include all files in a directory which end in .conf
|
||||
#conf-dir=/etc/dnsmasq.d/,*.conf
|
||||
|
||||
# If a DHCP client claims that its name is "wpad", ignore that.
|
||||
# This fixes a security hole. see CERT Vulnerability VU#598349
|
||||
#dhcp-name-match=set:wpad-ignore,wpad
|
||||
#dhcp-ignore-names=tag:wpad-ignore
|
||||
|
||||
164
doc.html
164
doc.html
@@ -1,8 +1,7 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE> Dnsmasq - a DNS forwarder for NAT firewalls.</TITLE>
|
||||
<link rel="icon"
|
||||
href="http://www.thekelleys.org.uk/dnsmasq/images/favicon.ico">
|
||||
<TITLE> Dnsmasq - network services for small networks.</TITLE>
|
||||
<link rel="icon" href="http://www.thekelleys.org.uk/dnsmasq/images/favicon.ico">
|
||||
</HEAD>
|
||||
<BODY BGCOLOR="WHITE">
|
||||
<table width="100%" border="0" cellpadding="0" cellspacing="0">
|
||||
@@ -11,111 +10,92 @@
|
||||
<td align="middle" valign="middle"><h1>Dnsmasq</h1></td>
|
||||
<td align="right" valign="middle"><img border="0" src="http://www.thekelleys.org.uk/dnsmasq/images/icon.png" /></td></tr>
|
||||
</table>
|
||||
Dnsmasq provides network infrastructure for small networks: DNS, DHCP, router advertisement and network boot. It is designed to be
|
||||
lightweight and have a small footprint, suitable for resource constrained routers and firewalls. It has also been widely used
|
||||
for tethering on smartphones and portable hotspots, and to support virtual networking in virtualisation frameworks.
|
||||
Supported platforms include Linux (with glibc and uclibc), Android, *BSD, and Mac OS X. Dnsmasq is included in most
|
||||
Linux distributions and the ports systems of FreeBSD, OpenBSD and NetBSD. Dnsmasq provides full IPv6 support.
|
||||
|
||||
Dnsmasq is a lightweight, easy to configure DNS forwarder and DHCP
|
||||
server. It is designed to provide DNS and, optionally, DHCP, to a
|
||||
small network. It can serve the names of local machines which are
|
||||
not in the global DNS. The DHCP server integrates with the DNS
|
||||
server and allows machines with DHCP-allocated addresses
|
||||
to appear in the DNS with names configured either in each host or
|
||||
in a central configuration file. Dnsmasq supports static and dynamic
|
||||
DHCP leases and BOOTP/TFTP/PXE for network booting of diskless machines.
|
||||
<P>
|
||||
Dnsmasq is targeted at home networks using NAT and
|
||||
connected to the internet via a modem, cable-modem or ADSL
|
||||
connection but would be a good choice for any smallish network (up to
|
||||
1000 clients is known to work) where low
|
||||
resource use and ease of configuration are important.
|
||||
<P>
|
||||
Supported platforms include Linux (with glibc and uclibc), *BSD,
|
||||
Solaris and Mac OS X.
|
||||
Dnsmasq is included in at least the following Linux distributions:
|
||||
Gentoo, Debian, Slackware, Suse, Fedora,
|
||||
Smoothwall, IP-Cop, floppyfw, Firebox, LEAF, Freesco, fli4l,
|
||||
CoyoteLinux, Endian Firewall and
|
||||
Clarkconnect. It is also available as FreeBSD, OpenBSD and NetBSD ports and is used in
|
||||
Linksys wireless routers (dd-wrt, openwrt and the stock firmware) and the m0n0wall project.
|
||||
<P>
|
||||
Dnsmasq provides the following features:
|
||||
The DNS subsystem provides a local DNS server for the network, with forwarding of all query types to upstream recursive DNS servers and
|
||||
caching of common record types (A, AAAA, CNAME and PTR, also DNSKEY and DS when DNSSEC is enabled).
|
||||
<DIR>
|
||||
|
||||
<LI>
|
||||
The DNS configuration of machines behind the firewall is simple and
|
||||
doesn't depend on the details of the ISP's dns servers
|
||||
<LI>
|
||||
Clients which try to do DNS lookups while a modem link to the
|
||||
internet is down will time out immediately.
|
||||
</LI>
|
||||
<LI>
|
||||
Dnsmasq will serve names from the /etc/hosts file on the firewall
|
||||
machine: If the names of local machines are there, then they can all
|
||||
be addressed without having to maintain /etc/hosts on each machine.
|
||||
</LI>
|
||||
<LI>
|
||||
The integrated DHCP server supports static and dynamic DHCP leases and
|
||||
multiple networks and IP ranges. It works across BOOTP relays and
|
||||
supports DHCP options including RFC3397 DNS search lists.
|
||||
Machines which are configured by DHCP have their names automatically
|
||||
included in the DNS and the names can specified by each machine or
|
||||
centrally by associating a name with a MAC address in the dnsmasq
|
||||
config file.
|
||||
</LI>
|
||||
<LI>
|
||||
Dnsmasq caches internet addresses (A records and AAAA records) and address-to-name
|
||||
mappings (PTR records), reducing the load on upstream servers and
|
||||
improving performance (especially on modem connections).
|
||||
</LI>
|
||||
<LI>
|
||||
Dnsmasq can be configured to automatically pick up the addresses of
|
||||
its upstream nameservers from ppp or dhcp configuration. It will
|
||||
automatically reload this information if it changes. This facility
|
||||
will be of particular interest to maintainers of Linux firewall
|
||||
distributions since it allows dns configuration to be made automatic.
|
||||
</LI>
|
||||
<LI>
|
||||
On IPv6-enabled boxes, dnsmasq can both talk to upstream servers via IPv6
|
||||
and offer DNS service via IPv6. On dual-stack (IPv4 and IPv6) boxes it talks
|
||||
both protocols and can even act as IPv6-to-IPv4 or IPv4-to-IPv6 forwarder.
|
||||
</LI>
|
||||
<LI>
|
||||
Dnsmasq can be configured to send queries for certain domains to
|
||||
upstream servers handling only those domains. This makes integration
|
||||
with private DNS systems easy.
|
||||
</LI>
|
||||
<LI>
|
||||
Dnsmasq supports MX and SRV records and can be configured to return MX records
|
||||
for any or all local machines.
|
||||
</LI>
|
||||
<LI>Local DNS names can be defined by reading /etc/hosts, by importing names from the DHCP subsystem, or by configuration of a wide range of useful record types.</LI>
|
||||
<LI>Upstream servers can be configured in a variety of convenient ways, including dynamic configuration as these change on moving upstream network.
|
||||
<LI>Authoritative DNS mode allows local DNS names may be exported to zone in the global DNS. Dnsmasq acts as authoritative server for this zone, and also provides
|
||||
zone transfer to secondaries for the zone, if required.</LI>
|
||||
<LI>DNSSEC validation may be performed on DNS replies from upstream nameservers, providing security against spoofing and cache poisoning.</LI>
|
||||
<LI>Specified sub-domains can be directed to their own upstream DNS servers, making VPN configuration easy.</LI>
|
||||
<LI>Internationalised domain names are supported.
|
||||
</DIR>
|
||||
<P>
|
||||
The DHCP subsystem supports DHCPv4, DHCPv6, BOOTP and PXE.
|
||||
<DIR>
|
||||
<LI> Both static and dynamic DHCP leases are supported, along with stateless mode in DHCPv6.</LI>
|
||||
<LI> The PXE system is a full PXE server, supporting netboot menus and multiple architecture support. It
|
||||
includes proxy-mode, where the PXE system co-operates with another DHCP server.</LI>
|
||||
<LI> There is a built in read-only TFTP server to support netboot.</LI>
|
||||
<LI> Machines which are configured by DHCP have their names automatically
|
||||
included in the DNS and the names can specified by each machine or
|
||||
centrally by associating a name with a MAC address or UID in the dnsmasq
|
||||
configuration file.</LI>
|
||||
</DIR>
|
||||
<P>
|
||||
The Router Advertisement subsystem provides basic autoconfiguration for IPv6 hosts. It can be used stand-alone or in conjunction with DHCPv6.
|
||||
<DIR>
|
||||
<LI> The M and O bits are configurable, to control hosts' use of DHCPv6.</LI>
|
||||
<LI> Router advertisements can include the RDNSS option.</LI>
|
||||
<LI> There is a mode which uses name information from DHCPv4 configuration to provide DNS entries
|
||||
for autoconfigured IPv6 addresses which would otherwise be anonymous.</LI>
|
||||
</DIR>
|
||||
<P>
|
||||
|
||||
For extra compactness, unused features may be omitted at compile time.
|
||||
|
||||
<H2>Download.</H2>
|
||||
|
||||
<A HREF="http://www.thekelleys.org.uk/dnsmasq/"> Download</A> dnsmasq here.
|
||||
<H2>Get code.</H2>
|
||||
|
||||
<A HREF="http://www.thekelleys.org.uk/dnsmasq/">Download</A> dnsmasq here.
|
||||
The tarball includes this documentation, source, and manpage.
|
||||
There is also a <A HREF="CHANGELOG"> CHANGELOG</A> and a <A HREF="FAQ">FAQ</A>.
|
||||
Dnsmasq is part of the Debian distribution, it can be downloaded from
|
||||
<A HREF="http://ftp.debian.org/debian/pool/main/d/dnsmasq/"> here</A> or installed using <TT>apt</TT>.
|
||||
|
||||
<H2>Links.</H2>
|
||||
Damien Raude-Morvan has an article in French at <A HREF="http://www.drazzib.com/docs-dnsmasq.html">http://www.drazzib.com/docs-dnsmasq.html</A>
|
||||
There is a good article about dnsmasq at <A
|
||||
HREF="http://www.enterprisenetworkingplanet.com/netos/article.php/3377351">http://www.enterprisenetworkingplanet.com/netos/article.php/3377351</A>
|
||||
and another at <A
|
||||
HREF="http://www.linux.com/articles/149040">http://www.linux.com/articles/149040</A>
|
||||
and Ilya Evseev has an article in Russian about dnsmasq to be found at
|
||||
<A HREF="http://ilya-evseev.narod.ru/articles/dnsmasq">
|
||||
http://ilya-evseev.narod.ru/articles/dnsmasq</A>. Ismael Ull has an
|
||||
article about dnsmasq in Spanish at <A HREF="http://www.mey-online.com.ar/blog/index.php/archives/guia-rapida-de-dnsmasq">http://www.mey-online.com.ar/blog/index.php/archives/guia-rapida-de-dnsmasq</A>
|
||||
Dnsmasq has a git repository which contains the complete release
|
||||
history of version 2 and development history from 2.60. You can
|
||||
<A HREF="http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=summary">browse</A>
|
||||
the repo, or get a copy using git protocol with the command
|
||||
|
||||
<PRE><TT>git clone git://thekelleys.org.uk/dnsmasq.git </TT></PRE>
|
||||
|
||||
or
|
||||
|
||||
<PRE><TT>git clone http://thekelleys.org.uk/git/dnsmasq.git </TT></PRE>
|
||||
|
||||
<H2>License.</H2>
|
||||
Dnsmasq is distributed under the GPL. See the file COPYING in the distribution
|
||||
Dnsmasq is distributed under the GPL, version 2 or version 3 at your discretion. See the files COPYING and COPYING-v3 in the distribution
|
||||
for details.
|
||||
|
||||
<H2>Contact.</H2>
|
||||
There is a dnsmasq mailing list at <A
|
||||
HREF="http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss">
|
||||
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss</A> which should be the
|
||||
first location for queries, bugreports, suggestions etc.
|
||||
Dnsmasq was written by Simon Kelley. You can contact me at <A
|
||||
first location for queries, bugreports, suggestions etc. The list is mirrored, with a
|
||||
search facility, at <A HREF="https://www.mail-archive.com/dnsmasq-discuss@lists.thekelleys.org.uk/">
|
||||
https://www.mail-archive.com/dnsmasq-discuss@lists.thekelleys.org.uk/</A>.
|
||||
You can contact me at <A
|
||||
HREF="mailto:simon@thekelleys.org.uk">simon@thekelleys.org.uk</A>.
|
||||
|
||||
<H2>Donations.</H2>
|
||||
Dnsmasq is mainly written and maintained by Simon Kelley. For most of its life, dnsmasq has been a spare-time project.
|
||||
These days I'm working on it as my main activity.
|
||||
I don't have an employer or anyone who pays me regularly to work on dnsmasq. If you'd like to make
|
||||
a contribution towards my expenses, please use the donation button below.
|
||||
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
|
||||
<input type="hidden" name="cmd" value="_s-xclick">
|
||||
<input type="hidden" name="hosted_button_id" value="V3X9GVW5GX6DA">
|
||||
<input type="image" src="https://www.paypalobjects.com/en_US/GB/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal – The safer, easier way to pay online.">
|
||||
<img alt="" border="0" src="https://www.paypalobjects.com/en_GB/i/scr/pixel.gif" width="1" height="1">
|
||||
</form>
|
||||
|
||||
|
||||
</BODY>
|
||||
|
||||
|
||||
BIN
logo/favicon.ico
BIN
logo/favicon.ico
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
1423
man/dnsmasq.8
1423
man/dnsmasq.8
File diff suppressed because it is too large
Load Diff
@@ -478,7 +478,8 @@ la traza reversa direcci
|
||||
.TP
|
||||
.B \-c, --cache-size=<tamaño de caché>
|
||||
Fijar el tamaño del caché de dnsmasq. El predeterminado es 150 nombres.
|
||||
Fijar el tamaño a cero deshabilita el caché.
|
||||
Fijar el tamaño a cero deshabilita el caché. Nota: el gran tamaño de
|
||||
caché afecta el rendimiento.
|
||||
.TP
|
||||
.B \-N, --no-negcache
|
||||
Deshabilitar caché negativo. El caché negativo le permite a dnsmasq
|
||||
@@ -1062,10 +1063,14 @@ esta opci
|
||||
cuando hay cambios hechos a el client-id y tiempos de arriendo y vencimiento.
|
||||
.TP
|
||||
.B --bridge-interface=<nombre de interface>,<alias>[,<alias>]
|
||||
Tratar paquetes de pedidos DHCP que llegan a cualquiera de las interfaces <alias>
|
||||
como si hubieran llegado a la interface <nombre de interface>. Esta opción
|
||||
es necesaria al usar bridging estilo viejo en plataformas BSD, dado a que
|
||||
los paquetes llegan a interfaces tap que no tienen una dirección IP.
|
||||
Tratar paquetes de pedidos DHCP (v4 y v6) y de IPv6 Router Solicit que
|
||||
llegan a cualquiera de las interfaces <alias> como si hubieran llegado
|
||||
a la interface <nombre de interface>. Esta opción permite que dnsmasq
|
||||
puede proporcionar los servicios DHCP y RA a través de interfaces
|
||||
ethernet sin dirección y sin puente; por ejemplo en un nodo de cálculo
|
||||
de OpenStack, donde cada una de esas interfaces es una interfaz TAP
|
||||
para una máquina virtual, o al usar bridging estilo viejo en
|
||||
plataformas BSD.
|
||||
.TP
|
||||
.B \-s, --domain=<dominio>[,<rango de IPs>]
|
||||
Especifica los dominios DNS para el servidor DHCP. Dominios pueden ser
|
||||
|
||||
1095
man/fr/dnsmasq.8
1095
man/fr/dnsmasq.8
File diff suppressed because it is too large
Load Diff
1783
po/pt_BR.po
1783
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
10
setup.html
10
setup.html
@@ -78,7 +78,7 @@ by modifying MODIFY_RESOLV_CONF_DYNAMICALLY="no" in <TT>/etc/sysconfig/network/c
|
||||
|
||||
|
||||
<h3>Automatic DNS server configuration with DHCP.</h3>
|
||||
You need to get your DHCP client to write the addresse(s) of the DNS
|
||||
You need to get your DHCP client to write the address(es) of the DNS
|
||||
servers to a file other than <TT>/etc/resolv.conf</TT>. For dhcpcd, the
|
||||
<TT>dhcpcd.exe</TT> script gets run with the addresses of the nameserver(s) in
|
||||
the shell variable <TT>$DNS</TT>. The following bit of shell script
|
||||
@@ -86,8 +86,8 @@ uses that to write a file suitable for dnsmasq.
|
||||
<PRE>
|
||||
|
||||
echo -n >|/etc/dhcpc/resolv.conf
|
||||
dnsservs=${DNS//,/ }
|
||||
for serv in $dnsservs; do
|
||||
dnsservers=${DNS//,/ }
|
||||
for serv in $dnsservers; do
|
||||
echo "nameserver $serv" >>/etc/dhcpc/resolv.conf
|
||||
done
|
||||
|
||||
@@ -125,7 +125,7 @@ address of its ethernet card. For the former to work, a machine needs to know it
|
||||
requests a DHCP lease. For dhcpcd, the -h option specifies this. The
|
||||
names may be anything as far as DHCP is concerned, but dnsmasq adds
|
||||
some limitations. By default the names must no have a domain part, ie
|
||||
they must just be a alphanumeric name, without any dots. This is a
|
||||
they must just be alphanumeric names, without any dots. This is a
|
||||
security feature to stop a machine on your network telling DHCP that
|
||||
its name is "www.microsoft.com" and thereby grabbing traffic which
|
||||
shouldn't go to it. A domain part is only allowed by dnsmasq in DHCP machine names
|
||||
@@ -186,7 +186,7 @@ more than one nameserver just include as many
|
||||
|
||||
<H2>Local domains.</H2>
|
||||
Sometimes people have local domains which they do not want forwarded
|
||||
to upstream servers. This is accomodated by using server options
|
||||
to upstream servers. This is accommodated by using server options
|
||||
without the server IP address. To make things clearer <TT>local</TT>
|
||||
is a synonym for <TT>server</TT>. For example the option
|
||||
<TT>local=/localnet/</TT> ensures that any domain name query which ends in
|
||||
|
||||
247
src/arp.c
Normal file
247
src/arp.c
Normal file
@@ -0,0 +1,247 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or
|
||||
(at your option) version 3 dated 29 June, 2007.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
/* Time between forced re-loads from kernel. */
|
||||
#define INTERVAL 90
|
||||
|
||||
#define ARP_MARK 0
|
||||
#define ARP_FOUND 1 /* Confirmed */
|
||||
#define ARP_NEW 2 /* Newly created */
|
||||
#define ARP_EMPTY 3 /* No MAC addr */
|
||||
|
||||
struct arp_record {
|
||||
unsigned short hwlen, status;
|
||||
int family;
|
||||
unsigned char hwaddr[DHCP_CHADDR_MAX];
|
||||
struct all_addr addr;
|
||||
struct arp_record *next;
|
||||
};
|
||||
|
||||
static struct arp_record *arps = NULL, *old = NULL, *freelist = NULL;
|
||||
static time_t last = 0;
|
||||
|
||||
static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
|
||||
{
|
||||
struct arp_record *arp;
|
||||
|
||||
(void)parmv;
|
||||
|
||||
if (maclen > DHCP_CHADDR_MAX)
|
||||
return 1;
|
||||
|
||||
#ifndef HAVE_IPV6
|
||||
if (family != AF_INET)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
/* Look for existing entry */
|
||||
for (arp = arps; arp; arp = arp->next)
|
||||
{
|
||||
if (family != arp->family || arp->status == ARP_NEW)
|
||||
continue;
|
||||
|
||||
if (family == AF_INET)
|
||||
{
|
||||
if (arp->addr.addr.addr4.s_addr != ((struct in_addr *)addrp)->s_addr)
|
||||
continue;
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
{
|
||||
if (!IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, (struct in6_addr *)addrp))
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (arp->status == ARP_EMPTY)
|
||||
{
|
||||
/* existing address, was negative. */
|
||||
arp->status = ARP_NEW;
|
||||
arp->hwlen = maclen;
|
||||
memcpy(arp->hwaddr, mac, maclen);
|
||||
}
|
||||
else if (arp->hwlen == maclen && memcmp(arp->hwaddr, mac, maclen) == 0)
|
||||
/* Existing entry matches - confirm. */
|
||||
arp->status = ARP_FOUND;
|
||||
else
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!arp)
|
||||
{
|
||||
/* New entry */
|
||||
if (freelist)
|
||||
{
|
||||
arp = freelist;
|
||||
freelist = freelist->next;
|
||||
}
|
||||
else if (!(arp = whine_malloc(sizeof(struct arp_record))))
|
||||
return 1;
|
||||
|
||||
arp->next = arps;
|
||||
arps = arp;
|
||||
arp->status = ARP_NEW;
|
||||
arp->hwlen = maclen;
|
||||
arp->family = family;
|
||||
memcpy(arp->hwaddr, mac, maclen);
|
||||
if (family == AF_INET)
|
||||
arp->addr.addr.addr4.s_addr = ((struct in_addr *)addrp)->s_addr;
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
memcpy(&arp->addr.addr.addr6, addrp, IN6ADDRSZ);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If in lazy mode, we cache absence of ARP entries. */
|
||||
int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now)
|
||||
{
|
||||
struct arp_record *arp, *tmp, **up;
|
||||
int updated = 0;
|
||||
|
||||
again:
|
||||
|
||||
/* If the database is less then INTERVAL old, look in there */
|
||||
if (difftime(now, last) < INTERVAL)
|
||||
{
|
||||
/* addr == NULL -> just make cache up-to-date */
|
||||
if (!addr)
|
||||
return 0;
|
||||
|
||||
for (arp = arps; arp; arp = arp->next)
|
||||
{
|
||||
if (addr->sa.sa_family != arp->family)
|
||||
continue;
|
||||
|
||||
if (arp->family == AF_INET &&
|
||||
arp->addr.addr.addr4.s_addr != addr->in.sin_addr.s_addr)
|
||||
continue;
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (arp->family == AF_INET6 &&
|
||||
!IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, &addr->in6.sin6_addr))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
/* Only accept positive entries unless in lazy mode. */
|
||||
if (arp->status != ARP_EMPTY || lazy || updated)
|
||||
{
|
||||
if (mac && arp->hwlen != 0)
|
||||
memcpy(mac, arp->hwaddr, arp->hwlen);
|
||||
return arp->hwlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found, try the kernel */
|
||||
if (!updated)
|
||||
{
|
||||
updated = 1;
|
||||
last = now;
|
||||
|
||||
/* Mark all non-negative entries */
|
||||
for (arp = arps; arp; arp = arp->next)
|
||||
if (arp->status != ARP_EMPTY)
|
||||
arp->status = ARP_MARK;
|
||||
|
||||
iface_enumerate(AF_UNSPEC, NULL, filter_mac);
|
||||
|
||||
/* Remove all unconfirmed entries to old list. */
|
||||
for (arp = arps, up = &arps; arp; arp = tmp)
|
||||
{
|
||||
tmp = arp->next;
|
||||
|
||||
if (arp->status == ARP_MARK)
|
||||
{
|
||||
*up = arp->next;
|
||||
arp->next = old;
|
||||
old = arp;
|
||||
}
|
||||
else
|
||||
up = &arp->next;
|
||||
}
|
||||
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* record failure, so we don't consult the kernel each time
|
||||
we're asked for this address */
|
||||
if (freelist)
|
||||
{
|
||||
arp = freelist;
|
||||
freelist = freelist->next;
|
||||
}
|
||||
else
|
||||
arp = whine_malloc(sizeof(struct arp_record));
|
||||
|
||||
if (arp)
|
||||
{
|
||||
arp->next = arps;
|
||||
arps = arp;
|
||||
arp->status = ARP_EMPTY;
|
||||
arp->family = addr->sa.sa_family;
|
||||
arp->hwlen = 0;
|
||||
|
||||
if (addr->sa.sa_family == AF_INET)
|
||||
arp->addr.addr.addr4.s_addr = addr->in.sin_addr.s_addr;
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
memcpy(&arp->addr.addr.addr6, &addr->in6.sin6_addr, IN6ADDRSZ);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_arp_script_run(void)
|
||||
{
|
||||
struct arp_record *arp;
|
||||
|
||||
/* Notify any which went, then move to free list */
|
||||
if (old)
|
||||
{
|
||||
#ifdef HAVE_SCRIPT
|
||||
if (option_bool(OPT_SCRIPT_ARP))
|
||||
queue_arp(ACTION_ARP_DEL, old->hwaddr, old->hwlen, old->family, &old->addr);
|
||||
#endif
|
||||
arp = old;
|
||||
old = arp->next;
|
||||
arp->next = freelist;
|
||||
freelist = arp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (arp = arps; arp; arp = arp->next)
|
||||
if (arp->status == ARP_NEW)
|
||||
{
|
||||
#ifdef HAVE_SCRIPT
|
||||
if (option_bool(OPT_SCRIPT_ARP))
|
||||
queue_arp(ACTION_ARP, arp->hwaddr, arp->hwlen, arp->family, &arp->addr);
|
||||
#endif
|
||||
arp->status = ARP_FOUND;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
892
src/auth.c
Normal file
892
src/auth.c
Normal file
@@ -0,0 +1,892 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or
|
||||
(at your option) version 3 dated 29 June, 2007.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#ifdef HAVE_AUTH
|
||||
|
||||
static struct addrlist *find_addrlist(struct addrlist *list, int flag, struct all_addr *addr_u)
|
||||
{
|
||||
do {
|
||||
if (!(list->flags & ADDRLIST_IPV6))
|
||||
{
|
||||
struct in_addr netmask, addr = addr_u->addr.addr4;
|
||||
|
||||
if (!(flag & F_IPV4))
|
||||
continue;
|
||||
|
||||
netmask.s_addr = htonl(~(in_addr_t)0 << (32 - list->prefixlen));
|
||||
|
||||
if (is_same_net(addr, list->addr.addr.addr4, netmask))
|
||||
return list;
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else if (is_same_net6(&(addr_u->addr.addr6), &list->addr.addr.addr6, list->prefixlen))
|
||||
return list;
|
||||
#endif
|
||||
|
||||
} while ((list = list->next));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct addrlist *find_subnet(struct auth_zone *zone, int flag, struct all_addr *addr_u)
|
||||
{
|
||||
if (!zone->subnet)
|
||||
return NULL;
|
||||
|
||||
return find_addrlist(zone->subnet, flag, addr_u);
|
||||
}
|
||||
|
||||
static struct addrlist *find_exclude(struct auth_zone *zone, int flag, struct all_addr *addr_u)
|
||||
{
|
||||
if (!zone->exclude)
|
||||
return NULL;
|
||||
|
||||
return find_addrlist(zone->exclude, flag, addr_u);
|
||||
}
|
||||
|
||||
static int filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
|
||||
{
|
||||
if (find_exclude(zone, flag, addr_u))
|
||||
return 0;
|
||||
|
||||
/* No subnets specified, no filter */
|
||||
if (!zone->subnet)
|
||||
return 1;
|
||||
|
||||
return find_subnet(zone, flag, addr_u) != NULL;
|
||||
}
|
||||
|
||||
int in_zone(struct auth_zone *zone, char *name, char **cut)
|
||||
{
|
||||
size_t namelen = strlen(name);
|
||||
size_t domainlen = strlen(zone->domain);
|
||||
|
||||
if (cut)
|
||||
*cut = NULL;
|
||||
|
||||
if (namelen >= domainlen &&
|
||||
hostname_isequal(zone->domain, &name[namelen - domainlen]))
|
||||
{
|
||||
|
||||
if (namelen == domainlen)
|
||||
return 1;
|
||||
|
||||
if (name[namelen - domainlen - 1] == '.')
|
||||
{
|
||||
if (cut)
|
||||
*cut = &name[namelen - domainlen - 1];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr,
|
||||
int local_query, int do_bit, int have_pseudoheader)
|
||||
{
|
||||
char *name = daemon->namebuff;
|
||||
unsigned char *p, *ansp;
|
||||
int qtype, qclass, rc;
|
||||
int nameoffset, axfroffset = 0;
|
||||
int q, anscount = 0, authcount = 0;
|
||||
struct crec *crecp;
|
||||
int auth = !local_query, trunc = 0, nxdomain = 1, soa = 0, ns = 0, axfr = 0;
|
||||
struct auth_zone *zone = NULL;
|
||||
struct addrlist *subnet = NULL;
|
||||
char *cut;
|
||||
struct mx_srv_record *rec, *move, **up;
|
||||
struct txt_record *txt;
|
||||
struct interface_name *intr;
|
||||
struct naptr *na;
|
||||
struct all_addr addr;
|
||||
struct cname *a, *candidate;
|
||||
unsigned int wclen;
|
||||
|
||||
if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
|
||||
return 0;
|
||||
|
||||
/* determine end of question section (we put answers there) */
|
||||
if (!(ansp = skip_questions(header, qlen)))
|
||||
return 0; /* bad packet */
|
||||
|
||||
/* now process each question, answers go in RRs after the question */
|
||||
p = (unsigned char *)(header+1);
|
||||
|
||||
for (q = ntohs(header->qdcount); q != 0; q--)
|
||||
{
|
||||
unsigned short flag = 0;
|
||||
int found = 0;
|
||||
int cname_wildcard = 0;
|
||||
|
||||
/* save pointer to name for copying into answers */
|
||||
nameoffset = p - (unsigned char *)header;
|
||||
|
||||
/* now extract name as .-concatenated string into name */
|
||||
if (!extract_name(header, qlen, &p, name, 1, 4))
|
||||
return 0; /* bad packet */
|
||||
|
||||
GETSHORT(qtype, p);
|
||||
GETSHORT(qclass, p);
|
||||
|
||||
if (qclass != C_IN)
|
||||
{
|
||||
auth = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((qtype == T_PTR || qtype == T_SOA || qtype == T_NS) &&
|
||||
(flag = in_arpa_name_2_addr(name, &addr)) &&
|
||||
!local_query)
|
||||
{
|
||||
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
||||
if ((subnet = find_subnet(zone, flag, &addr)))
|
||||
break;
|
||||
|
||||
if (!zone)
|
||||
{
|
||||
auth = 0;
|
||||
continue;
|
||||
}
|
||||
else if (qtype == T_SOA)
|
||||
soa = 1, found = 1;
|
||||
else if (qtype == T_NS)
|
||||
ns = 1, found = 1;
|
||||
}
|
||||
|
||||
if (qtype == T_PTR && flag)
|
||||
{
|
||||
intr = NULL;
|
||||
|
||||
if (flag == F_IPV4)
|
||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||
{
|
||||
struct addrlist *addrlist;
|
||||
|
||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||
if (!(addrlist->flags & ADDRLIST_IPV6) && addr.addr.addr4.s_addr == addrlist->addr.addr.addr4.s_addr)
|
||||
break;
|
||||
|
||||
if (addrlist)
|
||||
break;
|
||||
else
|
||||
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
|
||||
intr = intr->next;
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else if (flag == F_IPV6)
|
||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||
{
|
||||
struct addrlist *addrlist;
|
||||
|
||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||
if ((addrlist->flags & ADDRLIST_IPV6) && IN6_ARE_ADDR_EQUAL(&addr.addr.addr6, &addrlist->addr.addr.addr6))
|
||||
break;
|
||||
|
||||
if (addrlist)
|
||||
break;
|
||||
else
|
||||
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
|
||||
intr = intr->next;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (intr)
|
||||
{
|
||||
if (local_query || in_zone(zone, intr->name, NULL))
|
||||
{
|
||||
found = 1;
|
||||
log_query(flag | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->auth_ttl, NULL,
|
||||
T_PTR, C_IN, "d", intr->name))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((crecp = cache_find_by_addr(NULL, &addr, now, flag)))
|
||||
do {
|
||||
strcpy(name, cache_get_name(crecp));
|
||||
|
||||
if (crecp->flags & F_DHCP && !option_bool(OPT_DHCP_FQDN))
|
||||
{
|
||||
char *p = strchr(name, '.');
|
||||
if (p)
|
||||
*p = 0; /* must be bare name */
|
||||
|
||||
/* add external domain */
|
||||
if (zone)
|
||||
{
|
||||
strcat(name, ".");
|
||||
strcat(name, zone->domain);
|
||||
}
|
||||
log_query(flag | F_DHCP | F_REVERSE, name, &addr, record_source(crecp->uid));
|
||||
found = 1;
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->auth_ttl, NULL,
|
||||
T_PTR, C_IN, "d", name))
|
||||
anscount++;
|
||||
}
|
||||
else if (crecp->flags & (F_DHCP | F_HOSTS) && (local_query || in_zone(zone, name, NULL)))
|
||||
{
|
||||
log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid));
|
||||
found = 1;
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->auth_ttl, NULL,
|
||||
T_PTR, C_IN, "d", name))
|
||||
anscount++;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
} while ((crecp = cache_find_by_addr(crecp, &addr, now, flag)));
|
||||
|
||||
if (found)
|
||||
nxdomain = 0;
|
||||
else
|
||||
log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | (auth ? F_AUTH : 0), NULL, &addr, NULL);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
cname_restart:
|
||||
if (found)
|
||||
/* NS and SOA .arpa requests have set found above. */
|
||||
cut = NULL;
|
||||
else
|
||||
{
|
||||
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
||||
if (in_zone(zone, name, &cut))
|
||||
break;
|
||||
|
||||
if (!zone)
|
||||
{
|
||||
auth = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (rec = daemon->mxnames; rec; rec = rec->next)
|
||||
if (!rec->issrv && (rc = hostname_issubdomain(name, rec->name)))
|
||||
{
|
||||
nxdomain = 0;
|
||||
|
||||
if (rc == 2 && qtype == T_MX)
|
||||
{
|
||||
found = 1;
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||
NULL, T_MX, C_IN, "sd", rec->weight, rec->target))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
|
||||
for (move = NULL, up = &daemon->mxnames, rec = daemon->mxnames; rec; rec = rec->next)
|
||||
if (rec->issrv && (rc = hostname_issubdomain(name, rec->name)))
|
||||
{
|
||||
nxdomain = 0;
|
||||
|
||||
if (rc == 2 && qtype == T_SRV)
|
||||
{
|
||||
found = 1;
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||
NULL, T_SRV, C_IN, "sssd",
|
||||
rec->priority, rec->weight, rec->srvport, rec->target))
|
||||
|
||||
anscount++;
|
||||
}
|
||||
|
||||
/* unlink first SRV record found */
|
||||
if (!move)
|
||||
{
|
||||
move = rec;
|
||||
*up = rec->next;
|
||||
}
|
||||
else
|
||||
up = &rec->next;
|
||||
}
|
||||
else
|
||||
up = &rec->next;
|
||||
|
||||
/* put first SRV record back at the end. */
|
||||
if (move)
|
||||
{
|
||||
*up = move;
|
||||
move->next = NULL;
|
||||
}
|
||||
|
||||
for (txt = daemon->rr; txt; txt = txt->next)
|
||||
if ((rc = hostname_issubdomain(name, txt->name)))
|
||||
{
|
||||
nxdomain = 0;
|
||||
if (rc == 2 && txt->class == qtype)
|
||||
{
|
||||
found = 1;
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, querystr(NULL, txt->class));
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||
NULL, txt->class, C_IN, "t", txt->len, txt->txt))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
|
||||
for (txt = daemon->txt; txt; txt = txt->next)
|
||||
if (txt->class == C_IN && (rc = hostname_issubdomain(name, txt->name)))
|
||||
{
|
||||
nxdomain = 0;
|
||||
if (rc == 2 && qtype == T_TXT)
|
||||
{
|
||||
found = 1;
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||
NULL, T_TXT, C_IN, "t", txt->len, txt->txt))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
|
||||
for (na = daemon->naptr; na; na = na->next)
|
||||
if ((rc = hostname_issubdomain(name, na->name)))
|
||||
{
|
||||
nxdomain = 0;
|
||||
if (rc == 2 && qtype == T_NAPTR)
|
||||
{
|
||||
found = 1;
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||
NULL, T_NAPTR, C_IN, "sszzzd",
|
||||
na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (qtype == T_A)
|
||||
flag = F_IPV4;
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (qtype == T_AAAA)
|
||||
flag = F_IPV6;
|
||||
#endif
|
||||
|
||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||
if ((rc = hostname_issubdomain(name, intr->name)))
|
||||
{
|
||||
struct addrlist *addrlist;
|
||||
|
||||
nxdomain = 0;
|
||||
|
||||
if (rc == 2 && flag)
|
||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||
if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == qtype &&
|
||||
(local_query || filter_zone(zone, flag, &addrlist->addr)))
|
||||
{
|
||||
#ifdef HAVE_IPV6
|
||||
if (addrlist->flags & ADDRLIST_REVONLY)
|
||||
continue;
|
||||
#endif
|
||||
found = 1;
|
||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||
qtype == T_A ? "4" : "6", &addrlist->addr))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cut)
|
||||
{
|
||||
nxdomain = 0;
|
||||
|
||||
if (qtype == T_SOA)
|
||||
{
|
||||
auth = soa = 1; /* inhibits auth section */
|
||||
found = 1;
|
||||
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>");
|
||||
}
|
||||
else if (qtype == T_AXFR)
|
||||
{
|
||||
struct iname *peers;
|
||||
|
||||
if (peer_addr->sa.sa_family == AF_INET)
|
||||
peer_addr->in.sin_port = 0;
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
{
|
||||
peer_addr->in6.sin6_port = 0;
|
||||
peer_addr->in6.sin6_scope_id = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (peers = daemon->auth_peers; peers; peers = peers->next)
|
||||
if (sockaddr_isequal(peer_addr, &peers->addr))
|
||||
break;
|
||||
|
||||
/* Refuse all AXFR unless --auth-sec-servers or auth-peers is set */
|
||||
if ((!daemon->secondary_forward_server && !daemon->auth_peers) ||
|
||||
(daemon->auth_peers && !peers))
|
||||
{
|
||||
if (peer_addr->sa.sa_family == AF_INET)
|
||||
inet_ntop(AF_INET, &peer_addr->in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
inet_ntop(AF_INET6, &peer_addr->in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN);
|
||||
#endif
|
||||
|
||||
my_syslog(LOG_WARNING, _("ignoring zone transfer request from %s"), daemon->addrbuff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
auth = 1;
|
||||
soa = 1; /* inhibits auth section */
|
||||
ns = 1; /* ensure we include NS records! */
|
||||
axfr = 1;
|
||||
found = 1;
|
||||
axfroffset = nameoffset;
|
||||
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>");
|
||||
}
|
||||
else if (qtype == T_NS)
|
||||
{
|
||||
auth = 1;
|
||||
ns = 1; /* inhibits auth section */
|
||||
found = 1;
|
||||
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>");
|
||||
}
|
||||
}
|
||||
|
||||
if (!option_bool(OPT_DHCP_FQDN) && cut)
|
||||
{
|
||||
*cut = 0; /* remove domain part */
|
||||
|
||||
if (!strchr(name, '.') && (crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6)))
|
||||
{
|
||||
if (crecp->flags & F_DHCP)
|
||||
do
|
||||
{
|
||||
nxdomain = 0;
|
||||
if ((crecp->flags & flag) &&
|
||||
(local_query || filter_zone(zone, flag, &(crecp->addr.addr))))
|
||||
{
|
||||
*cut = '.'; /* restore domain part */
|
||||
log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
|
||||
*cut = 0; /* remove domain part */
|
||||
found = 1;
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||
qtype == T_A ? "4" : "6", &crecp->addr))
|
||||
anscount++;
|
||||
}
|
||||
} while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4 | F_IPV6)));
|
||||
}
|
||||
|
||||
*cut = '.'; /* restore domain part */
|
||||
}
|
||||
|
||||
if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6)))
|
||||
{
|
||||
if ((crecp->flags & F_HOSTS) || (((crecp->flags & F_DHCP) && option_bool(OPT_DHCP_FQDN))))
|
||||
do
|
||||
{
|
||||
nxdomain = 0;
|
||||
if ((crecp->flags & flag) && (local_query || filter_zone(zone, flag, &(crecp->addr.addr))))
|
||||
{
|
||||
log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
|
||||
found = 1;
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||
qtype == T_A ? "4" : "6", &crecp->addr))
|
||||
anscount++;
|
||||
}
|
||||
} while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4 | F_IPV6)));
|
||||
}
|
||||
|
||||
/* Only supply CNAME if no record for any type is known. */
|
||||
if (nxdomain)
|
||||
{
|
||||
/* Check for possible wildcard match against *.domain
|
||||
return length of match, to get longest.
|
||||
Note that if return length of wildcard section, so
|
||||
we match b.simon to _both_ *.simon and b.simon
|
||||
but return a longer (better) match to b.simon.
|
||||
*/
|
||||
for (wclen = 0, candidate = NULL, a = daemon->cnames; a; a = a->next)
|
||||
if (a->alias[0] == '*')
|
||||
{
|
||||
char *test = name;
|
||||
|
||||
while ((test = strchr(test+1, '.')))
|
||||
{
|
||||
if (hostname_isequal(test, &(a->alias[1])))
|
||||
{
|
||||
if (strlen(test) > wclen && !cname_wildcard)
|
||||
{
|
||||
wclen = strlen(test);
|
||||
candidate = a;
|
||||
cname_wildcard = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (hostname_isequal(a->alias, name) && strlen(a->alias) > wclen)
|
||||
{
|
||||
/* Simple case, no wildcard */
|
||||
wclen = strlen(a->alias);
|
||||
candidate = a;
|
||||
}
|
||||
|
||||
if (candidate)
|
||||
{
|
||||
log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
|
||||
strcpy(name, candidate->target);
|
||||
if (!strchr(name, '.'))
|
||||
{
|
||||
strcat(name, ".");
|
||||
strcat(name, zone->domain);
|
||||
}
|
||||
found = 1;
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->auth_ttl, &nameoffset,
|
||||
T_CNAME, C_IN, "d", name))
|
||||
anscount++;
|
||||
|
||||
goto cname_restart;
|
||||
}
|
||||
else if (cache_find_non_terminal(name, now))
|
||||
nxdomain = 0;
|
||||
|
||||
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Add auth section */
|
||||
if (auth && zone)
|
||||
{
|
||||
char *authname;
|
||||
int newoffset, offset = 0;
|
||||
|
||||
if (!subnet)
|
||||
authname = zone->domain;
|
||||
else
|
||||
{
|
||||
/* handle NS and SOA for PTR records */
|
||||
|
||||
authname = name;
|
||||
|
||||
if (!(subnet->flags & ADDRLIST_IPV6))
|
||||
{
|
||||
in_addr_t a = ntohl(subnet->addr.addr.addr4.s_addr) >> 8;
|
||||
char *p = name;
|
||||
|
||||
if (subnet->prefixlen >= 24)
|
||||
p += sprintf(p, "%u.", a & 0xff);
|
||||
a = a >> 8;
|
||||
if (subnet->prefixlen >= 16 )
|
||||
p += sprintf(p, "%u.", a & 0xff);
|
||||
a = a >> 8;
|
||||
p += sprintf(p, "%u.in-addr.arpa", a & 0xff);
|
||||
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
{
|
||||
char *p = name;
|
||||
int i;
|
||||
|
||||
for (i = subnet->prefixlen-1; i >= 0; i -= 4)
|
||||
{
|
||||
int dig = ((unsigned char *)&subnet->addr.addr.addr6)[i>>3];
|
||||
p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
|
||||
}
|
||||
p += sprintf(p, "ip6.arpa");
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* handle NS and SOA in auth section or for explicit queries */
|
||||
newoffset = ansp - (unsigned char *)header;
|
||||
if (((anscount == 0 && !ns) || soa) &&
|
||||
add_resource_record(header, limit, &trunc, 0, &ansp,
|
||||
daemon->auth_ttl, NULL, T_SOA, C_IN, "ddlllll",
|
||||
authname, daemon->authserver, daemon->hostmaster,
|
||||
daemon->soa_sn, daemon->soa_refresh,
|
||||
daemon->soa_retry, daemon->soa_expiry,
|
||||
daemon->auth_ttl))
|
||||
{
|
||||
offset = newoffset;
|
||||
if (soa)
|
||||
anscount++;
|
||||
else
|
||||
authcount++;
|
||||
}
|
||||
|
||||
if (anscount != 0 || ns)
|
||||
{
|
||||
struct name_list *secondary;
|
||||
|
||||
newoffset = ansp - (unsigned char *)header;
|
||||
if (add_resource_record(header, limit, &trunc, -offset, &ansp,
|
||||
daemon->auth_ttl, NULL, T_NS, C_IN, "d", offset == 0 ? authname : NULL, daemon->authserver))
|
||||
{
|
||||
if (offset == 0)
|
||||
offset = newoffset;
|
||||
if (ns)
|
||||
anscount++;
|
||||
else
|
||||
authcount++;
|
||||
}
|
||||
|
||||
if (!subnet)
|
||||
for (secondary = daemon->secondary_forward_server; secondary; secondary = secondary->next)
|
||||
if (add_resource_record(header, limit, &trunc, offset, &ansp,
|
||||
daemon->auth_ttl, NULL, T_NS, C_IN, "d", secondary->name))
|
||||
{
|
||||
if (ns)
|
||||
anscount++;
|
||||
else
|
||||
authcount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (axfr)
|
||||
{
|
||||
for (rec = daemon->mxnames; rec; rec = rec->next)
|
||||
if (in_zone(zone, rec->name, &cut))
|
||||
{
|
||||
if (cut)
|
||||
*cut = 0;
|
||||
|
||||
if (rec->issrv)
|
||||
{
|
||||
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
|
||||
NULL, T_SRV, C_IN, "sssd", cut ? rec->name : NULL,
|
||||
rec->priority, rec->weight, rec->srvport, rec->target))
|
||||
|
||||
anscount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
|
||||
NULL, T_MX, C_IN, "sd", cut ? rec->name : NULL, rec->weight, rec->target))
|
||||
anscount++;
|
||||
}
|
||||
|
||||
/* restore config data */
|
||||
if (cut)
|
||||
*cut = '.';
|
||||
}
|
||||
|
||||
for (txt = daemon->rr; txt; txt = txt->next)
|
||||
if (in_zone(zone, txt->name, &cut))
|
||||
{
|
||||
if (cut)
|
||||
*cut = 0;
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
|
||||
NULL, txt->class, C_IN, "t", cut ? txt->name : NULL, txt->len, txt->txt))
|
||||
anscount++;
|
||||
|
||||
/* restore config data */
|
||||
if (cut)
|
||||
*cut = '.';
|
||||
}
|
||||
|
||||
for (txt = daemon->txt; txt; txt = txt->next)
|
||||
if (txt->class == C_IN && in_zone(zone, txt->name, &cut))
|
||||
{
|
||||
if (cut)
|
||||
*cut = 0;
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
|
||||
NULL, T_TXT, C_IN, "t", cut ? txt->name : NULL, txt->len, txt->txt))
|
||||
anscount++;
|
||||
|
||||
/* restore config data */
|
||||
if (cut)
|
||||
*cut = '.';
|
||||
}
|
||||
|
||||
for (na = daemon->naptr; na; na = na->next)
|
||||
if (in_zone(zone, na->name, &cut))
|
||||
{
|
||||
if (cut)
|
||||
*cut = 0;
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
|
||||
NULL, T_NAPTR, C_IN, "sszzzd", cut ? na->name : NULL,
|
||||
na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
|
||||
anscount++;
|
||||
|
||||
/* restore config data */
|
||||
if (cut)
|
||||
*cut = '.';
|
||||
}
|
||||
|
||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||
if (in_zone(zone, intr->name, &cut))
|
||||
{
|
||||
struct addrlist *addrlist;
|
||||
|
||||
if (cut)
|
||||
*cut = 0;
|
||||
|
||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||
if (!(addrlist->flags & ADDRLIST_IPV6) &&
|
||||
(local_query || filter_zone(zone, F_IPV4, &addrlist->addr)) &&
|
||||
add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
||||
daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addrlist->addr))
|
||||
anscount++;
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||
if ((addrlist->flags & ADDRLIST_IPV6) &&
|
||||
(local_query || filter_zone(zone, F_IPV6, &addrlist->addr)) &&
|
||||
add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
||||
daemon->auth_ttl, NULL, T_AAAA, C_IN, "6", cut ? intr->name : NULL, &addrlist->addr))
|
||||
anscount++;
|
||||
#endif
|
||||
|
||||
/* restore config data */
|
||||
if (cut)
|
||||
*cut = '.';
|
||||
}
|
||||
|
||||
for (a = daemon->cnames; a; a = a->next)
|
||||
if (in_zone(zone, a->alias, &cut))
|
||||
{
|
||||
strcpy(name, a->target);
|
||||
if (!strchr(name, '.'))
|
||||
{
|
||||
strcat(name, ".");
|
||||
strcat(name, zone->domain);
|
||||
}
|
||||
|
||||
if (cut)
|
||||
*cut = 0;
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
||||
daemon->auth_ttl, NULL,
|
||||
T_CNAME, C_IN, "d", cut ? a->alias : NULL, name))
|
||||
anscount++;
|
||||
}
|
||||
|
||||
cache_enumerate(1);
|
||||
while ((crecp = cache_enumerate(0)))
|
||||
{
|
||||
if ((crecp->flags & (F_IPV4 | F_IPV6)) &&
|
||||
!(crecp->flags & (F_NEG | F_NXDOMAIN)) &&
|
||||
(crecp->flags & F_FORWARD))
|
||||
{
|
||||
if ((crecp->flags & F_DHCP) && !option_bool(OPT_DHCP_FQDN))
|
||||
{
|
||||
char *cache_name = cache_get_name(crecp);
|
||||
if (!strchr(cache_name, '.') &&
|
||||
(local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))))
|
||||
{
|
||||
qtype = T_A;
|
||||
#ifdef HAVE_IPV6
|
||||
if (crecp->flags & F_IPV6)
|
||||
qtype = T_AAAA;
|
||||
#endif
|
||||
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
||||
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||
(crecp->flags & F_IPV4) ? "4" : "6", cache_name, &crecp->addr))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((crecp->flags & F_HOSTS) || (((crecp->flags & F_DHCP) && option_bool(OPT_DHCP_FQDN))))
|
||||
{
|
||||
strcpy(name, cache_get_name(crecp));
|
||||
if (in_zone(zone, name, &cut) &&
|
||||
(local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))))
|
||||
{
|
||||
qtype = T_A;
|
||||
#ifdef HAVE_IPV6
|
||||
if (crecp->flags & F_IPV6)
|
||||
qtype = T_AAAA;
|
||||
#endif
|
||||
if (cut)
|
||||
*cut = 0;
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
||||
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||
(crecp->flags & F_IPV4) ? "4" : "6", cut ? name : NULL, &crecp->addr))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* repeat SOA as last record */
|
||||
if (add_resource_record(header, limit, &trunc, axfroffset, &ansp,
|
||||
daemon->auth_ttl, NULL, T_SOA, C_IN, "ddlllll",
|
||||
daemon->authserver, daemon->hostmaster,
|
||||
daemon->soa_sn, daemon->soa_refresh,
|
||||
daemon->soa_retry, daemon->soa_expiry,
|
||||
daemon->auth_ttl))
|
||||
anscount++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* done all questions, set up header and return length of result */
|
||||
/* clear authoritative and truncated flags, set QR flag */
|
||||
header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
|
||||
|
||||
if (local_query)
|
||||
{
|
||||
/* set RA flag */
|
||||
header->hb4 |= HB4_RA;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* clear RA flag */
|
||||
header->hb4 &= ~HB4_RA;
|
||||
}
|
||||
|
||||
/* authoritative */
|
||||
if (auth)
|
||||
header->hb3 |= HB3_AA;
|
||||
|
||||
/* truncation */
|
||||
if (trunc)
|
||||
header->hb3 |= HB3_TC;
|
||||
|
||||
if ((auth || local_query) && nxdomain)
|
||||
SET_RCODE(header, NXDOMAIN);
|
||||
else
|
||||
SET_RCODE(header, NOERROR); /* no error */
|
||||
header->ancount = htons(anscount);
|
||||
header->nscount = htons(authcount);
|
||||
header->arcount = htons(0);
|
||||
|
||||
/* Advertise our packet size limit in our reply */
|
||||
if (have_pseudoheader)
|
||||
return add_pseudoheader(header, ansp - (unsigned char *)header, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
|
||||
|
||||
return ansp - (unsigned char *)header;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
152
src/blockdata.c
Normal file
152
src/blockdata.c
Normal file
@@ -0,0 +1,152 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or
|
||||
(at your option) version 3 dated 29 June, 2007.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
|
||||
static struct blockdata *keyblock_free;
|
||||
static unsigned int blockdata_count, blockdata_hwm, blockdata_alloced;
|
||||
|
||||
static void blockdata_expand(int n)
|
||||
{
|
||||
struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
|
||||
|
||||
if (new)
|
||||
{
|
||||
int i;
|
||||
|
||||
new[n-1].next = keyblock_free;
|
||||
keyblock_free = new;
|
||||
|
||||
for (i = 0; i < n - 1; i++)
|
||||
new[i].next = &new[i+1];
|
||||
|
||||
blockdata_alloced += n;
|
||||
}
|
||||
}
|
||||
|
||||
/* Preallocate some blocks, proportional to cachesize, to reduce heap fragmentation. */
|
||||
void blockdata_init(void)
|
||||
{
|
||||
keyblock_free = NULL;
|
||||
blockdata_alloced = 0;
|
||||
blockdata_count = 0;
|
||||
blockdata_hwm = 0;
|
||||
|
||||
/* Note that daemon->cachesize is enforced to have non-zero size if OPT_DNSSEC_VALID is set */
|
||||
if (option_bool(OPT_DNSSEC_VALID))
|
||||
blockdata_expand(daemon->cachesize);
|
||||
}
|
||||
|
||||
void blockdata_report(void)
|
||||
{
|
||||
if (option_bool(OPT_DNSSEC_VALID))
|
||||
my_syslog(LOG_INFO, _("DNSSEC memory in use %u, max %u, allocated %u"),
|
||||
blockdata_count * sizeof(struct blockdata),
|
||||
blockdata_hwm * sizeof(struct blockdata),
|
||||
blockdata_alloced * sizeof(struct blockdata));
|
||||
}
|
||||
|
||||
struct blockdata *blockdata_alloc(char *data, size_t len)
|
||||
{
|
||||
struct blockdata *block, *ret = NULL;
|
||||
struct blockdata **prev = &ret;
|
||||
size_t blen;
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
if (!keyblock_free)
|
||||
blockdata_expand(50);
|
||||
|
||||
if (keyblock_free)
|
||||
{
|
||||
block = keyblock_free;
|
||||
keyblock_free = block->next;
|
||||
blockdata_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* failed to alloc, free partial chain */
|
||||
blockdata_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (blockdata_hwm < blockdata_count)
|
||||
blockdata_hwm = blockdata_count;
|
||||
|
||||
blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
|
||||
memcpy(block->key, data, blen);
|
||||
data += blen;
|
||||
len -= blen;
|
||||
*prev = block;
|
||||
prev = &block->next;
|
||||
block->next = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void blockdata_free(struct blockdata *blocks)
|
||||
{
|
||||
struct blockdata *tmp;
|
||||
|
||||
if (blocks)
|
||||
{
|
||||
for (tmp = blocks; tmp->next; tmp = tmp->next)
|
||||
blockdata_count--;
|
||||
tmp->next = keyblock_free;
|
||||
keyblock_free = blocks;
|
||||
blockdata_count--;
|
||||
}
|
||||
}
|
||||
|
||||
/* if data == NULL, return pointer to static block of sufficient size */
|
||||
void *blockdata_retrieve(struct blockdata *block, size_t len, void *data)
|
||||
{
|
||||
size_t blen;
|
||||
struct blockdata *b;
|
||||
void *new, *d;
|
||||
|
||||
static unsigned int buff_len = 0;
|
||||
static unsigned char *buff = NULL;
|
||||
|
||||
if (!data)
|
||||
{
|
||||
if (len > buff_len)
|
||||
{
|
||||
if (!(new = whine_malloc(len)))
|
||||
return NULL;
|
||||
if (buff)
|
||||
free(buff);
|
||||
buff = new;
|
||||
}
|
||||
data = buff;
|
||||
}
|
||||
|
||||
for (d = data, b = block; len > 0 && b; b = b->next)
|
||||
{
|
||||
blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
|
||||
memcpy(d, b->key, blen);
|
||||
d += blen;
|
||||
len -= blen;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#endif
|
||||
318
src/bpf.c
318
src/bpf.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -17,23 +17,23 @@
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#if defined(HAVE_BSD_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
|
||||
#include <ifaddrs.h>
|
||||
|
||||
static struct iovec ifconf = {
|
||||
.iov_base = NULL,
|
||||
.iov_len = 0
|
||||
};
|
||||
|
||||
static struct iovec ifreq = {
|
||||
.iov_base = NULL,
|
||||
.iov_len = 0
|
||||
};
|
||||
|
||||
#include <sys/param.h>
|
||||
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#if defined(__FreeBSD__)
|
||||
# include <net/if_var.h>
|
||||
#endif
|
||||
#include <netinet/in_var.h>
|
||||
#ifdef HAVE_IPV6
|
||||
# include <netinet6/in6_var.h>
|
||||
#endif
|
||||
|
||||
#ifndef SA_SIZE
|
||||
#define SA_SIZE(sa) \
|
||||
@@ -42,6 +42,13 @@ static struct iovec ifreq = {
|
||||
1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) )
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BSD_NETWORK
|
||||
static int del_family = 0;
|
||||
static struct all_addr del_addr;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
|
||||
|
||||
int arp_enumerate(void *parm, int (*callback)())
|
||||
{
|
||||
int mib[6];
|
||||
@@ -50,8 +57,12 @@ int arp_enumerate(void *parm, int (*callback)())
|
||||
struct rt_msghdr *rtm;
|
||||
struct sockaddr_inarp *sin2;
|
||||
struct sockaddr_dl *sdl;
|
||||
struct iovec buff;
|
||||
int rc;
|
||||
|
||||
|
||||
buff.iov_base = NULL;
|
||||
buff.iov_len = 0;
|
||||
|
||||
mib[0] = CTL_NET;
|
||||
mib[1] = PF_ROUTE;
|
||||
mib[2] = 0;
|
||||
@@ -67,9 +78,9 @@ int arp_enumerate(void *parm, int (*callback)())
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (!expand_buf(&ifconf, needed))
|
||||
if (!expand_buf(&buff, needed))
|
||||
return 0;
|
||||
if ((rc = sysctl(mib, 6, ifconf.iov_base, &needed, NULL, 0)) == 0 ||
|
||||
if ((rc = sysctl(mib, 6, buff.iov_base, &needed, NULL, 0)) == 0 ||
|
||||
errno != ENOMEM)
|
||||
break;
|
||||
needed += needed / 8;
|
||||
@@ -77,7 +88,7 @@ int arp_enumerate(void *parm, int (*callback)())
|
||||
if (rc == -1)
|
||||
return 0;
|
||||
|
||||
for (next = ifconf.iov_base ; next < (char *)ifconf.iov_base + needed; next += rtm->rtm_msglen)
|
||||
for (next = buff.iov_base ; next < (char *)buff.iov_base + needed; next += rtm->rtm_msglen)
|
||||
{
|
||||
rtm = (struct rt_msghdr *)next;
|
||||
sin2 = (struct sockaddr_inarp *)(rtm + 1);
|
||||
@@ -88,19 +99,14 @@ int arp_enumerate(void *parm, int (*callback)())
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* defined(HAVE_BSD_NETWORK) && !defined(__APPLE__) */
|
||||
|
||||
|
||||
int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
{
|
||||
char *ptr;
|
||||
struct ifreq *ifr;
|
||||
struct ifconf ifc;
|
||||
int fd, errsav, ret = 0;
|
||||
int lastlen = 0;
|
||||
size_t len = 0;
|
||||
|
||||
struct ifaddrs *head, *addrs;
|
||||
int errsave, fd = -1, ret = 0;
|
||||
|
||||
if (family == AF_UNSPEC)
|
||||
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
|
||||
return arp_enumerate(parm, callback);
|
||||
@@ -108,100 +114,138 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
return 0; /* need code for Solaris and MacOS*/
|
||||
#endif
|
||||
|
||||
if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
|
||||
/* AF_LINK doesn't exist in Linux, so we can't use it in our API */
|
||||
if (family == AF_LOCAL)
|
||||
family = AF_LINK;
|
||||
|
||||
if (getifaddrs(&head) == -1)
|
||||
return 0;
|
||||
|
||||
while(1)
|
||||
{
|
||||
len += 10*sizeof(struct ifreq);
|
||||
|
||||
if (!expand_buf(&ifconf, len))
|
||||
goto err;
|
||||
|
||||
ifc.ifc_len = len;
|
||||
ifc.ifc_buf = ifconf.iov_base;
|
||||
|
||||
if (ioctl(fd, SIOCGIFCONF, &ifc) == -1)
|
||||
{
|
||||
if (errno != EINVAL || lastlen != 0)
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ifc.ifc_len == lastlen)
|
||||
break; /* got a big enough buffer now */
|
||||
lastlen = ifc.ifc_len;
|
||||
}
|
||||
}
|
||||
|
||||
for (ptr = ifc.ifc_buf; ptr < (char *)(ifc.ifc_buf + ifc.ifc_len); ptr += len)
|
||||
{
|
||||
/* subsequent entries may not be aligned, so copy into
|
||||
an aligned buffer to avoid nasty complaints about
|
||||
unaligned accesses. */
|
||||
|
||||
len = sizeof(struct ifreq);
|
||||
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
ifr = (struct ifreq *)ptr;
|
||||
if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_ifru))
|
||||
len = ifr->ifr_addr.sa_len + offsetof(struct ifreq, ifr_ifru);
|
||||
#if defined(HAVE_BSD_NETWORK) && defined(HAVE_IPV6)
|
||||
if (family == AF_INET6)
|
||||
fd = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||
#endif
|
||||
|
||||
if (!expand_buf(&ifreq, len))
|
||||
goto err;
|
||||
|
||||
ifr = (struct ifreq *)ifreq.iov_base;
|
||||
memcpy(ifr, ptr, len);
|
||||
|
||||
if (ifr->ifr_addr.sa_family == family)
|
||||
|
||||
for (addrs = head; addrs; addrs = addrs->ifa_next)
|
||||
{
|
||||
if (addrs->ifa_addr->sa_family == family)
|
||||
{
|
||||
int iface_index = if_nametoindex(addrs->ifa_name);
|
||||
|
||||
if (iface_index == 0 || !addrs->ifa_addr ||
|
||||
(!addrs->ifa_netmask && family != AF_LINK))
|
||||
continue;
|
||||
|
||||
if (family == AF_INET)
|
||||
{
|
||||
struct in_addr addr, netmask, broadcast;
|
||||
broadcast.s_addr = 0;
|
||||
addr = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr;
|
||||
if (ioctl(fd, SIOCGIFNETMASK, ifr) == -1)
|
||||
addr = ((struct sockaddr_in *) addrs->ifa_addr)->sin_addr;
|
||||
#ifdef HAVE_BSD_NETWORK
|
||||
if (del_family == AF_INET && del_addr.addr.addr4.s_addr == addr.s_addr)
|
||||
continue;
|
||||
netmask = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr;
|
||||
if (ioctl(fd, SIOCGIFBRDADDR, ifr) != -1)
|
||||
broadcast = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr;
|
||||
if (!((*callback)(addr,
|
||||
(int)if_nametoindex(ifr->ifr_name),
|
||||
netmask, broadcast,
|
||||
parm)))
|
||||
#endif
|
||||
netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr;
|
||||
if (addrs->ifa_broadaddr)
|
||||
broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;
|
||||
else
|
||||
broadcast.s_addr = 0;
|
||||
if (!((*callback)(addr, iface_index, NULL, netmask, broadcast, parm)))
|
||||
goto err;
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else if (family == AF_INET6)
|
||||
{
|
||||
struct in6_addr *addr = &((struct sockaddr_in6 *)&ifr->ifr_addr)->sin6_addr;
|
||||
struct in6_addr *addr = &((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_addr;
|
||||
unsigned char *netmask = (unsigned char *) &((struct sockaddr_in6 *) addrs->ifa_netmask)->sin6_addr;
|
||||
int scope_id = ((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_scope_id;
|
||||
int i, j, prefix = 0;
|
||||
u32 valid = 0xffffffff, preferred = 0xffffffff;
|
||||
int flags = 0;
|
||||
#ifdef HAVE_BSD_NETWORK
|
||||
if (del_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(&del_addr.addr.addr6, addr))
|
||||
continue;
|
||||
#endif
|
||||
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
|
||||
struct in6_ifreq ifr6;
|
||||
|
||||
memset(&ifr6, 0, sizeof(ifr6));
|
||||
safe_strncpy(ifr6.ifr_name, addrs->ifa_name, sizeof(ifr6.ifr_name));
|
||||
|
||||
ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
|
||||
if (fd != -1 && ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
|
||||
{
|
||||
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE)
|
||||
flags |= IFACE_TENTATIVE;
|
||||
|
||||
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED)
|
||||
flags |= IFACE_DEPRECATED;
|
||||
|
||||
#ifdef IN6_IFF_TEMPORARY
|
||||
if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_TEMPORARY)))
|
||||
flags |= IFACE_PERMANENT;
|
||||
#endif
|
||||
|
||||
#ifdef IN6_IFF_PRIVACY
|
||||
if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_PRIVACY)))
|
||||
flags |= IFACE_PERMANENT;
|
||||
#endif
|
||||
}
|
||||
|
||||
ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
|
||||
if (fd != -1 && ioctl(fd, SIOCGIFALIFETIME_IN6, &ifr6) != -1)
|
||||
{
|
||||
valid = ifr6.ifr_ifru.ifru_lifetime.ia6t_vltime;
|
||||
preferred = ifr6.ifr_ifru.ifru_lifetime.ia6t_pltime;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < IN6ADDRSZ; i++, prefix += 8)
|
||||
if (netmask[i] != 0xff)
|
||||
break;
|
||||
|
||||
if (i != IN6ADDRSZ && netmask[i])
|
||||
for (j = 7; j > 0; j--, prefix++)
|
||||
if ((netmask[i] & (1 << j)) == 0)
|
||||
break;
|
||||
|
||||
/* voodoo to clear interface field in address */
|
||||
if (!option_bool(OPT_NOWILD) && IN6_IS_ADDR_LINKLOCAL(addr))
|
||||
{
|
||||
addr->s6_addr[2] = 0;
|
||||
addr->s6_addr[3] = 0;
|
||||
}
|
||||
if (!((*callback)(addr,
|
||||
(int)((struct sockaddr_in6 *)&ifr->ifr_addr)->sin6_scope_id,
|
||||
(int)if_nametoindex(ifr->ifr_name), 0,
|
||||
parm)))
|
||||
}
|
||||
|
||||
if (!((*callback)(addr, prefix, scope_id, iface_index, flags,
|
||||
(int) preferred, (int)valid, parm)))
|
||||
goto err;
|
||||
}
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
else if (family == AF_LINK)
|
||||
{
|
||||
/* Assume ethernet again here */
|
||||
struct sockaddr_dl *sdl = (struct sockaddr_dl *) addrs->ifa_addr;
|
||||
if (sdl->sdl_alen != 0 &&
|
||||
!((*callback)(iface_index, ARPHRD_ETHER, LLADDR(sdl), sdl->sdl_alen, parm)))
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
errsav = errno;
|
||||
close(fd);
|
||||
errno = errsav;
|
||||
errsave = errno;
|
||||
freeifaddrs(head);
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
errno = errsave;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#endif /* defined(HAVE_BSD_NETWORK) || defined(HAVE_SOLARIS_NETWORK) */
|
||||
|
||||
|
||||
#if defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP)
|
||||
@@ -213,13 +257,10 @@ void init_bpf(void)
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* useful size which happens to be sufficient */
|
||||
if (expand_buf(&ifreq, sizeof(struct ifreq)))
|
||||
{
|
||||
sprintf(ifreq.iov_base, "/dev/bpf%d", i++);
|
||||
if ((daemon->dhcp_raw_fd = open(ifreq.iov_base, O_RDWR, 0)) != -1)
|
||||
return;
|
||||
}
|
||||
sprintf(daemon->dhcp_buff, "/dev/bpf%d", i++);
|
||||
if ((daemon->dhcp_raw_fd = open(daemon->dhcp_buff, O_RDWR, 0)) != -1)
|
||||
return;
|
||||
|
||||
if (errno != EBUSY)
|
||||
die(_("cannot create DHCP BPF socket: %s"), NULL, EC_BADNET);
|
||||
}
|
||||
@@ -320,9 +361,90 @@ void send_via_bpf(struct dhcp_packet *mess, size_t len,
|
||||
iov[3].iov_base = mess;
|
||||
iov[3].iov_len = len;
|
||||
|
||||
while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send());
|
||||
while (retry_send(writev(daemon->dhcp_raw_fd, iov, 4)));
|
||||
}
|
||||
|
||||
#endif /* defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP) */
|
||||
|
||||
|
||||
#ifdef HAVE_BSD_NETWORK
|
||||
|
||||
void route_init(void)
|
||||
{
|
||||
/* AF_UNSPEC: all addr families */
|
||||
daemon->routefd = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
|
||||
|
||||
if (daemon->routefd == -1 || !fix_fd(daemon->routefd))
|
||||
die(_("cannot create PF_ROUTE socket: %s"), NULL, EC_BADNET);
|
||||
}
|
||||
|
||||
void route_sock(void)
|
||||
{
|
||||
struct if_msghdr *msg;
|
||||
int rc = recv(daemon->routefd, daemon->packet, daemon->packet_buff_sz, 0);
|
||||
|
||||
if (rc < 4)
|
||||
return;
|
||||
|
||||
msg = (struct if_msghdr *)daemon->packet;
|
||||
|
||||
if (rc < msg->ifm_msglen)
|
||||
return;
|
||||
|
||||
if (msg->ifm_version != RTM_VERSION)
|
||||
{
|
||||
static int warned = 0;
|
||||
if (!warned)
|
||||
{
|
||||
my_syslog(LOG_WARNING, _("Unknown protocol version from route socket"));
|
||||
warned = 1;
|
||||
}
|
||||
}
|
||||
else if (msg->ifm_type == RTM_NEWADDR)
|
||||
{
|
||||
del_family = 0;
|
||||
queue_event(EVENT_NEWADDR);
|
||||
}
|
||||
else if (msg->ifm_type == RTM_DELADDR)
|
||||
{
|
||||
/* There's a race in the kernel, such that if we run iface_enumerate() immediately
|
||||
we get a DELADDR event, the deleted address still appears. Here we store the deleted address
|
||||
in a static variable, and omit it from the set returned by iface_enumerate() */
|
||||
int mask = ((struct ifa_msghdr *)msg)->ifam_addrs;
|
||||
int maskvec[] = { RTA_DST, RTA_GATEWAY, RTA_NETMASK, RTA_GENMASK,
|
||||
RTA_IFP, RTA_IFA, RTA_AUTHOR, RTA_BRD };
|
||||
int of;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0, of = sizeof(struct ifa_msghdr); of < rc && i < sizeof(maskvec)/sizeof(maskvec[0]); i++)
|
||||
if (mask & maskvec[i])
|
||||
{
|
||||
struct sockaddr *sa = (struct sockaddr *)((char *)msg + of);
|
||||
size_t diff = (sa->sa_len != 0) ? sa->sa_len : sizeof(long);
|
||||
|
||||
if (maskvec[i] == RTA_IFA)
|
||||
{
|
||||
del_family = sa->sa_family;
|
||||
if (del_family == AF_INET)
|
||||
del_addr.addr.addr4 = ((struct sockaddr_in *)sa)->sin_addr;
|
||||
#ifdef HAVE_IPV6
|
||||
else if (del_family == AF_INET6)
|
||||
del_addr.addr.addr6 = ((struct sockaddr_in6 *)sa)->sin6_addr;
|
||||
#endif
|
||||
else
|
||||
del_family = 0;
|
||||
}
|
||||
|
||||
of += diff;
|
||||
/* round up as needed */
|
||||
if (diff & (sizeof(long) - 1))
|
||||
of += sizeof(long) - (diff & (sizeof(long) - 1));
|
||||
}
|
||||
|
||||
queue_event(EVENT_NEWADDR);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_BSD_NETWORK */
|
||||
|
||||
|
||||
|
||||
1277
src/cache.c
1277
src/cache.c
File diff suppressed because it is too large
Load Diff
481
src/config.h
481
src/config.h
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -14,32 +14,181 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define VERSION "2.59"
|
||||
|
||||
#define FTABSIZ 150 /* max number of outstanding requests (default) */
|
||||
#define MAX_PROCS 20 /* max no children for TCP requests */
|
||||
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
|
||||
#define TCP_MAX_QUERIES 100 /* Maximum number of queries per incoming TCP connection */
|
||||
#define TCP_BACKLOG 32 /* kernel backlog limit for TCP connections */
|
||||
#define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */
|
||||
#define SAFE_PKTSZ 1280 /* "go anywhere" UDP packet size */
|
||||
#define KEYBLOCK_LEN 40 /* choose to minimise fragmentation when storing DNSSEC keys */
|
||||
#define DNSSEC_WORK 50 /* Max number of queries to validate one question */
|
||||
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
|
||||
#define FORWARD_TEST 50 /* try all servers every 50 queries */
|
||||
#define FORWARD_TIME 20 /* or 20 seconds */
|
||||
#define UDP_TEST_TIME 60 /* How often to reset our idea of max packet size. */
|
||||
#define SERVERS_LOGGED 30 /* Only log this many servers when logging state */
|
||||
#define LOCALS_LOGGED 8 /* Only log this many local addresses when logging state */
|
||||
#define RANDOM_SOCKS 64 /* max simultaneous random ports */
|
||||
#define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */
|
||||
#define CACHESIZ 150 /* default cache size */
|
||||
#define TTL_FLOOR_LIMIT 3600 /* don't allow --min-cache-ttl to raise TTL above this under any circumstances */
|
||||
#define MAXLEASES 1000 /* maximum number of DHCP leases */
|
||||
#define PING_WAIT 3 /* wait for ping address-in-use test */
|
||||
#define PING_CACHE_TIME 30 /* Ping test assumed to be valid this long. */
|
||||
#define DECLINE_BACKOFF 600 /* disable DECLINEd static addresses for this long */
|
||||
#define DHCP_PACKET_MAX 16384 /* hard limit on DHCP packet size */
|
||||
#define SMALLDNAME 40 /* most domain names are smaller than this */
|
||||
#define SMALLDNAME 50 /* most domain names are smaller than this */
|
||||
#define CNAME_CHAIN 10 /* chains longer than this atr dropped for loop protection */
|
||||
#define HOSTSFILE "/etc/hosts"
|
||||
#define ETHERSFILE "/etc/ethers"
|
||||
#ifdef __uClinux__
|
||||
# define RESOLVFILE "/etc/config/resolv.conf"
|
||||
#else
|
||||
# define RESOLVFILE "/etc/resolv.conf"
|
||||
#endif
|
||||
#define RUNFILE "/var/run/dnsmasq.pid"
|
||||
#define DEFLEASE 3600 /* default lease time, 1 hour */
|
||||
#define CHUSER "nobody"
|
||||
#define CHGRP "dip"
|
||||
#define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */
|
||||
#define LOG_MAX 5 /* log-queue length */
|
||||
#define RANDFILE "/dev/urandom"
|
||||
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq" /* Default - may be overridden by config */
|
||||
#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
|
||||
#define AUTH_TTL 600 /* default TTL for auth DNS */
|
||||
#define SOA_REFRESH 1200 /* SOA refresh default */
|
||||
#define SOA_RETRY 180 /* SOA retry default */
|
||||
#define SOA_EXPIRY 1209600 /* SOA expiry default */
|
||||
#define LOOP_TEST_DOMAIN "test" /* domain for loop testing, "test" is reserved by RFC 2606 and won't therefore clash */
|
||||
#define LOOP_TEST_TYPE T_TXT
|
||||
|
||||
/* compile-time options: uncomment below to enable or do eg.
|
||||
make COPTS=-DHAVE_BROKEN_RTC
|
||||
|
||||
HAVE_BROKEN_RTC
|
||||
define this on embedded systems which don't have an RTC
|
||||
which keeps time over reboots. Causes dnsmasq to use uptime
|
||||
for timing, and keep lease lengths rather than expiry times
|
||||
in its leases file. This also make dnsmasq "flash disk friendly".
|
||||
Normally, dnsmasq tries very hard to keep the on-disk leases file
|
||||
up-to-date: rewriting it after every renewal. When HAVE_BROKEN_RTC
|
||||
is in effect, the lease file is only written when a new lease is
|
||||
created, or an old one destroyed. (Because those are the only times
|
||||
it changes.) This vastly reduces the number of file writes, and makes
|
||||
it viable to keep the lease file on a flash filesystem.
|
||||
NOTE: when enabling or disabling this, be sure to delete any old
|
||||
leases file, otherwise dnsmasq may get very confused.
|
||||
|
||||
HAVE_TFTP
|
||||
define this to get dnsmasq's built-in TFTP server.
|
||||
|
||||
HAVE_DHCP
|
||||
define this to get dnsmasq's DHCPv4 server.
|
||||
|
||||
HAVE_DHCP6
|
||||
define this to get dnsmasq's DHCPv6 server. (implies HAVE_DHCP).
|
||||
|
||||
HAVE_SCRIPT
|
||||
define this to get the ability to call scripts on lease-change.
|
||||
|
||||
HAVE_LUASCRIPT
|
||||
define this to get the ability to call Lua script on lease-change. (implies HAVE_SCRIPT)
|
||||
|
||||
HAVE_DBUS
|
||||
define this if you want to link against libdbus, and have dnsmasq
|
||||
support some methods to allow (re)configuration of the upstream DNS
|
||||
servers via DBus.
|
||||
|
||||
HAVE_UBUS
|
||||
define this if you want to link against libubus
|
||||
|
||||
HAVE_IDN
|
||||
define this if you want international domain name 2003 support.
|
||||
|
||||
HAVE_LIBIDN2
|
||||
define this if you want international domain name 2008 support.
|
||||
|
||||
HAVE_CONNTRACK
|
||||
define this to include code which propagates conntrack marks from
|
||||
incoming DNS queries to the corresponding upstream queries. This adds
|
||||
a build-dependency on libnetfilter_conntrack, but the resulting binary will
|
||||
still run happily on a kernel without conntrack support.
|
||||
|
||||
HAVE_IPSET
|
||||
define this to include the ability to selectively add resolved ip addresses
|
||||
to given ipsets.
|
||||
|
||||
HAVE_AUTH
|
||||
define this to include the facility to act as an authoritative DNS
|
||||
server for one or more zones.
|
||||
|
||||
HAVE_DNSSEC
|
||||
include DNSSEC validator.
|
||||
|
||||
HAVE_DUMPFILE
|
||||
include code to dump packets to a libpcap-format file for debugging.
|
||||
|
||||
HAVE_LOOP
|
||||
include functionality to probe for and remove DNS forwarding loops.
|
||||
|
||||
HAVE_INOTIFY
|
||||
use the Linux inotify facility to efficiently re-read configuration files.
|
||||
|
||||
NO_ID
|
||||
Don't report *.bind CHAOS info to clients, forward such requests upstream instead.
|
||||
NO_IPV6
|
||||
NO_TFTP
|
||||
NO_DHCP
|
||||
NO_DHCP6
|
||||
NO_SCRIPT
|
||||
NO_LARGEFILE
|
||||
NO_AUTH
|
||||
NO_DUMPFILE
|
||||
NO_INOTIFY
|
||||
these are available to explicitly disable compile time options which would
|
||||
otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or
|
||||
which are enabled by default in the distributed source tree. Building dnsmasq
|
||||
with something like "make COPTS=-DNO_SCRIPT" will do the trick.
|
||||
NO_GMP
|
||||
Don't use and link against libgmp, Useful if nettle is built with --enable-mini-gmp.
|
||||
|
||||
LEASEFILE
|
||||
CONFFILE
|
||||
RESOLVFILE
|
||||
the default locations of these files are determined below, but may be overridden
|
||||
in a build command line using COPTS.
|
||||
|
||||
*/
|
||||
|
||||
/* Defining this builds a binary which handles time differently and works better on a system without a
|
||||
stable RTC (it uses uptime, not epoch time) and writes the DHCP leases file less often to avoid flash wear.
|
||||
*/
|
||||
|
||||
/* #define HAVE_BROKEN_RTC */
|
||||
|
||||
/* The default set of options to build. Built with these options, dnsmasq
|
||||
has no library dependencies other than libc */
|
||||
|
||||
#define HAVE_DHCP
|
||||
#define HAVE_DHCP6
|
||||
#define HAVE_TFTP
|
||||
#define HAVE_SCRIPT
|
||||
#define HAVE_AUTH
|
||||
#define HAVE_IPSET
|
||||
#define HAVE_LOOP
|
||||
#define HAVE_DUMPFILE
|
||||
|
||||
/* Build options which require external libraries.
|
||||
|
||||
Defining HAVE_<opt>_STATIC as _well_ as HAVE_<opt> will link the library statically.
|
||||
|
||||
You can use "make COPTS=-DHAVE_<opt>" instead of editing these.
|
||||
*/
|
||||
|
||||
/* #define HAVE_LUASCRIPT */
|
||||
/* #define HAVE_DBUS */
|
||||
/* #define HAVE_IDN */
|
||||
/* #define HAVE_LIBIDN2 */
|
||||
/* #define HAVE_CONNTRACK */
|
||||
/* #define HAVE_DNSSEC */
|
||||
|
||||
|
||||
/* Default locations for important system files. */
|
||||
|
||||
#ifndef LEASEFILE
|
||||
# if defined(__FreeBSD__) || defined (__OpenBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
|
||||
@@ -61,135 +210,40 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define DEFLEASE 3600 /* default lease time, 1 hour */
|
||||
#define CHUSER "nobody"
|
||||
#define CHGRP "dip"
|
||||
#define NAMESERVER_PORT 53
|
||||
#define DHCP_SERVER_PORT 67
|
||||
#define DHCP_CLIENT_PORT 68
|
||||
#define DHCP_SERVER_ALTPORT 1067
|
||||
#define DHCP_CLIENT_ALTPORT 1068
|
||||
#define PXE_PORT 4011
|
||||
#define TFTP_PORT 69
|
||||
#define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */
|
||||
#define LOG_MAX 5 /* log-queue length */
|
||||
#define RANDFILE "/dev/urandom"
|
||||
#define EDNS0_OPTION_MAC 5 /* dyndns.org temporary assignment */
|
||||
#ifndef RESOLVFILE
|
||||
# if defined(__uClinux__)
|
||||
# define RESOLVFILE "/etc/config/resolv.conf"
|
||||
# else
|
||||
# define RESOLVFILE "/etc/resolv.conf"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* DBUS interface specifics */
|
||||
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq"
|
||||
#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
|
||||
#ifndef RUNFILE
|
||||
# if defined(__ANDROID__)
|
||||
# define RUNFILE "/data/dnsmasq.pid"
|
||||
# else
|
||||
# define RUNFILE "/var/run/dnsmasq.pid"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Follows system specific switches. If you run on a
|
||||
new system, you may want to edit these.
|
||||
May replace this with Autoconf one day.
|
||||
/* platform dependent options: these are determined automatically below
|
||||
|
||||
HAVE_LINUX_NETWORK
|
||||
HAVE_BSD_NETWORK
|
||||
HAVE_SOLARIS_NETWORK
|
||||
define exactly one of these to alter interaction with kernel networking.
|
||||
|
||||
HAVE_BROKEN_RTC
|
||||
define this on embedded systems which don't have an RTC
|
||||
which keeps time over reboots. Causes dnsmasq to use uptime
|
||||
for timing, and keep lease lengths rather than expiry times
|
||||
in its leases file. This also make dnsmasq "flash disk friendly".
|
||||
Normally, dnsmasq tries very hard to keep the on-disk leases file
|
||||
up-to-date: rewriting it after every renewal. When HAVE_BROKEN_RTC
|
||||
is in effect, the lease file is only written when a new lease is
|
||||
created, or an old one destroyed. (Because those are the only times
|
||||
it changes.) This vastly reduces the number of file writes, and makes
|
||||
it viable to keep the lease file on a flash filesystem.
|
||||
NOTE: when enabling or disabling this, be sure to delete any old
|
||||
leases file, otherwise dnsmasq may get very confused.
|
||||
|
||||
HAVE_TFTP
|
||||
define this to get dnsmasq's built-in TFTP server.
|
||||
|
||||
HAVE_DHCP
|
||||
define this to get dnsmasq's DHCP server.
|
||||
|
||||
HAVE_SCRIPT
|
||||
define this to get the ability to call scripts on lease-change
|
||||
|
||||
HAVE_GETOPT_LONG
|
||||
define this if you have GNU libc or GNU getopt.
|
||||
|
||||
HAVE_ARC4RANDOM
|
||||
define this if you have arc4random() to get better security from DNS spoofs
|
||||
by using really random ids (OpenBSD)
|
||||
defined when GNU-style getopt_long available.
|
||||
|
||||
HAVE_SOCKADDR_SA_LEN
|
||||
define this if struct sockaddr has sa_len field (*BSD)
|
||||
|
||||
HAVE_DBUS
|
||||
define this if you want to link against libdbus, and have dnsmasq
|
||||
support some methods to allow (re)configuration of the upstream DNS
|
||||
servers via DBus.
|
||||
|
||||
HAVE_IDN
|
||||
define this if you want international domain name support.
|
||||
NOTE: for backwards compatibility, IDN support is automatically
|
||||
included when internationalisation support is built, using the
|
||||
*-i18n makefile targets, even if HAVE_IDN is not explicitly set.
|
||||
|
||||
HAVE_CONNTRACK
|
||||
define this to include code which propogates conntrack marks from
|
||||
incoming DNS queries to the corresponding upstream queries. This adds
|
||||
a build-dependency on libnetfilter_conntrack, but the resulting binary will
|
||||
still run happily on a kernel without conntrack support.
|
||||
|
||||
NOTES:
|
||||
For Linux you should define
|
||||
HAVE_LINUX_NETWORK
|
||||
HAVE_GETOPT_LONG
|
||||
you should NOT define
|
||||
HAVE_ARC4RANDOM
|
||||
HAVE_SOCKADDR_SA_LEN
|
||||
|
||||
For *BSD systems you should define
|
||||
HAVE_BSD_NETWORK
|
||||
HAVE_SOCKADDR_SA_LEN
|
||||
and you MAY define
|
||||
HAVE_ARC4RANDOM - OpenBSD and FreeBSD and NetBSD version 2.0 or later
|
||||
HAVE_GETOPT_LONG - NetBSD, later FreeBSD
|
||||
(FreeBSD and OpenBSD only if you link GNU getopt)
|
||||
|
||||
defined if struct sockaddr has sa_len field (*BSD)
|
||||
*/
|
||||
|
||||
/* platform independent options- uncomment to enable */
|
||||
#define HAVE_DHCP
|
||||
#define HAVE_TFTP
|
||||
#define HAVE_SCRIPT
|
||||
/* #define HAVE_BROKEN_RTC */
|
||||
/* #define HAVE_DBUS */
|
||||
/* #define HAVE_IDN */
|
||||
/* #define HAVE_CONNTRACK */
|
||||
|
||||
/* Allow TFTP to be disabled with COPTS=-DNO_TFTP */
|
||||
#ifdef NO_TFTP
|
||||
#undef HAVE_TFTP
|
||||
#endif
|
||||
|
||||
/* Allow DHCP to be disabled with COPTS=-DNO_DHCP */
|
||||
#ifdef NO_DHCP
|
||||
#undef HAVE_DHCP
|
||||
#endif
|
||||
|
||||
/* Allow scripts to be disabled with COPTS=-DNO_SCRIPT */
|
||||
#ifdef NO_SCRIPT
|
||||
#undef HAVE_SCRIPT
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* platform dependent options. */
|
||||
|
||||
/* Must preceed __linux__ since uClinux defines __linux__ too. */
|
||||
/* Must precede __linux__ since uClinux defines __linux__ too. */
|
||||
#if defined(__uClinux__)
|
||||
#define HAVE_LINUX_NETWORK
|
||||
#define HAVE_GETOPT_LONG
|
||||
#undef HAVE_ARC4RANDOM
|
||||
#undef HAVE_SOCKADDR_SA_LEN
|
||||
/* Never use fork() on uClinux. Note that this is subtly different from the
|
||||
--keep-in-foreground option, since it also suppresses forking new
|
||||
@@ -203,7 +257,6 @@ NOTES:
|
||||
((__UCLIBC_MAJOR__==0) && (__UCLIBC_MINOR__==9) && (__UCLIBC_SUBLEVEL__<21))
|
||||
# define HAVE_GETOPT_LONG
|
||||
#endif
|
||||
#undef HAVE_ARC4RANDOM
|
||||
#undef HAVE_SOCKADDR_SA_LEN
|
||||
#if !defined(__ARCH_HAS_MMU__) && !defined(__UCLIBC_HAS_MMU__)
|
||||
# define NO_FORK
|
||||
@@ -218,7 +271,6 @@ NOTES:
|
||||
#elif defined(__linux__)
|
||||
#define HAVE_LINUX_NETWORK
|
||||
#define HAVE_GETOPT_LONG
|
||||
#undef HAVE_ARC4RANDOM
|
||||
#undef HAVE_SOCKADDR_SA_LEN
|
||||
|
||||
#elif defined(__FreeBSD__) || \
|
||||
@@ -226,61 +278,198 @@ NOTES:
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD_kernel__)
|
||||
#define HAVE_BSD_NETWORK
|
||||
/* Later verions of FreeBSD have getopt_long() */
|
||||
/* Later versions of FreeBSD have getopt_long() */
|
||||
#if defined(optional_argument) && defined(required_argument)
|
||||
# define HAVE_GETOPT_LONG
|
||||
#endif
|
||||
#if !defined(__FreeBSD_kernel__)
|
||||
# define HAVE_ARC4RANDOM
|
||||
#endif
|
||||
#define HAVE_SOCKADDR_SA_LEN
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
#define HAVE_BSD_NETWORK
|
||||
#define HAVE_GETOPT_LONG
|
||||
#define HAVE_ARC4RANDOM
|
||||
#define HAVE_SOCKADDR_SA_LEN
|
||||
/* Define before sys/socket.h is included so we get socklen_t */
|
||||
#define _BSD_SOCKLEN_T_
|
||||
|
||||
/* Select the RFC_3542 version of the IPv6 socket API.
|
||||
Define before netinet6/in6.h is included. */
|
||||
#define __APPLE_USE_RFC_3542
|
||||
#define NO_IPSET
|
||||
|
||||
#elif defined(__NetBSD__)
|
||||
#define HAVE_BSD_NETWORK
|
||||
#define HAVE_GETOPT_LONG
|
||||
#undef HAVE_ARC4RANDOM
|
||||
#define HAVE_SOCKADDR_SA_LEN
|
||||
|
||||
#elif defined(__sun) || defined(__sun__)
|
||||
#define HAVE_SOLARIS_NETWORK
|
||||
#define HAVE_GETOPT_LONG
|
||||
#undef HAVE_ARC4RANDOM
|
||||
#undef HAVE_SOCKADDR_SA_LEN
|
||||
#define ETHER_ADDR_LEN 6
|
||||
|
||||
#endif
|
||||
|
||||
/* Decide if we're going to support IPv6 */
|
||||
/* IPv6 can be forced off with "make COPTS=-DNO_IPV6" */
|
||||
/* We assume that systems which don't have IPv6
|
||||
headers don't have ntop and pton either */
|
||||
|
||||
#if defined(INET6_ADDRSTRLEN) && defined(IPV6_V6ONLY) && !defined(NO_IPV6)
|
||||
#if defined(INET6_ADDRSTRLEN) && defined(IPV6_V6ONLY)
|
||||
# define HAVE_IPV6
|
||||
# define ADDRSTRLEN INET6_ADDRSTRLEN
|
||||
# if defined(SOL_IPV6)
|
||||
# define IPV6_LEVEL SOL_IPV6
|
||||
# else
|
||||
# define IPV6_LEVEL IPPROTO_IPV6
|
||||
#else
|
||||
# if !defined(INET_ADDRSTRLEN)
|
||||
# define INET_ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */
|
||||
# endif
|
||||
#elif defined(INET_ADDRSTRLEN)
|
||||
# undef HAVE_IPV6
|
||||
# define ADDRSTRLEN INET_ADDRSTRLEN
|
||||
#endif
|
||||
|
||||
|
||||
/* rules to implement compile-time option dependencies and
|
||||
the NO_XXX flags */
|
||||
|
||||
#ifdef NO_IPV6
|
||||
#undef HAVE_IPV6
|
||||
#endif
|
||||
|
||||
#ifdef NO_TFTP
|
||||
#undef HAVE_TFTP
|
||||
#endif
|
||||
|
||||
#ifdef NO_DHCP
|
||||
#undef HAVE_DHCP
|
||||
#undef HAVE_DHCP6
|
||||
#endif
|
||||
|
||||
#if defined(NO_DHCP6) || !defined(HAVE_IPV6)
|
||||
#undef HAVE_DHCP6
|
||||
#endif
|
||||
|
||||
/* DHCP6 needs DHCP too */
|
||||
#ifdef HAVE_DHCP6
|
||||
#define HAVE_DHCP
|
||||
#endif
|
||||
|
||||
#if defined(NO_SCRIPT) || defined(NO_FORK)
|
||||
#undef HAVE_SCRIPT
|
||||
#undef HAVE_LUASCRIPT
|
||||
#endif
|
||||
|
||||
/* Must HAVE_SCRIPT to HAVE_LUASCRIPT */
|
||||
#ifdef HAVE_LUASCRIPT
|
||||
#define HAVE_SCRIPT
|
||||
#endif
|
||||
|
||||
#ifdef NO_AUTH
|
||||
#undef HAVE_AUTH
|
||||
#endif
|
||||
|
||||
#if defined(NO_IPSET)
|
||||
#undef HAVE_IPSET
|
||||
#endif
|
||||
|
||||
#ifdef NO_LOOP
|
||||
#undef HAVE_LOOP
|
||||
#endif
|
||||
|
||||
#ifdef NO_DUMPFILE
|
||||
#undef HAVE_DUMPFILE
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_LINUX_NETWORK) && !defined(NO_INOTIFY)
|
||||
#define HAVE_INOTIFY
|
||||
#endif
|
||||
|
||||
/* Define a string indicating which options are in use.
|
||||
DNSMASQ_COMPILE_OPTS is only defined in dnsmasq.c */
|
||||
|
||||
#ifdef DNSMASQ_COMPILE_OPTS
|
||||
|
||||
static char *compile_opts =
|
||||
#ifndef HAVE_IPV6
|
||||
"no-"
|
||||
#endif
|
||||
"IPv6 "
|
||||
#ifndef HAVE_GETOPT_LONG
|
||||
"no-"
|
||||
#endif
|
||||
"GNU-getopt "
|
||||
#ifdef HAVE_BROKEN_RTC
|
||||
"no-RTC "
|
||||
#endif
|
||||
#ifdef NO_FORK
|
||||
"no-MMU "
|
||||
#endif
|
||||
#ifndef HAVE_DBUS
|
||||
"no-"
|
||||
#endif
|
||||
"DBus "
|
||||
#ifndef LOCALEDIR
|
||||
"no-"
|
||||
#endif
|
||||
"i18n "
|
||||
#if defined(HAVE_LIBIDN2)
|
||||
"IDN2 "
|
||||
#else
|
||||
# undef HAVE_IPV6
|
||||
# define ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */
|
||||
#if !defined(HAVE_IDN)
|
||||
"no-"
|
||||
#endif
|
||||
"IDN "
|
||||
#endif
|
||||
#ifndef HAVE_DHCP
|
||||
"no-"
|
||||
#endif
|
||||
"DHCP "
|
||||
#if defined(HAVE_DHCP)
|
||||
# if !defined (HAVE_DHCP6)
|
||||
"no-"
|
||||
# endif
|
||||
"DHCPv6 "
|
||||
#endif
|
||||
#if !defined(HAVE_SCRIPT)
|
||||
"no-scripts "
|
||||
#else
|
||||
# if !defined(HAVE_LUASCRIPT)
|
||||
"no-"
|
||||
# endif
|
||||
"Lua "
|
||||
#endif
|
||||
#ifndef HAVE_TFTP
|
||||
"no-"
|
||||
#endif
|
||||
"TFTP "
|
||||
#ifndef HAVE_CONNTRACK
|
||||
"no-"
|
||||
#endif
|
||||
"conntrack "
|
||||
#ifndef HAVE_IPSET
|
||||
"no-"
|
||||
#endif
|
||||
"ipset "
|
||||
#ifndef HAVE_AUTH
|
||||
"no-"
|
||||
#endif
|
||||
"auth "
|
||||
#ifndef HAVE_DNSSEC
|
||||
"no-"
|
||||
#endif
|
||||
"DNSSEC "
|
||||
#ifdef NO_ID
|
||||
"no-ID "
|
||||
#endif
|
||||
#ifndef HAVE_LOOP
|
||||
"no-"
|
||||
#endif
|
||||
"loop-detect "
|
||||
#ifndef HAVE_INOTIFY
|
||||
"no-"
|
||||
#endif
|
||||
"inotify "
|
||||
#ifndef HAVE_DUMPFILE
|
||||
"no-"
|
||||
#endif
|
||||
"dumpfile";
|
||||
|
||||
#endif
|
||||
|
||||
/* Can't do scripts without fork */
|
||||
#ifdef NOFORK
|
||||
# undef HAVE_SCRIPT
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
460
src/crypto.c
Normal file
460
src/crypto.c
Normal file
@@ -0,0 +1,460 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or
|
||||
(at your option) version 3 dated 29 June, 2007.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
|
||||
#include <nettle/rsa.h>
|
||||
#include <nettle/dsa.h>
|
||||
#include <nettle/ecdsa.h>
|
||||
#include <nettle/ecc-curve.h>
|
||||
#include <nettle/eddsa.h>
|
||||
#include <nettle/nettle-meta.h>
|
||||
#include <nettle/bignum.h>
|
||||
|
||||
/* Implement a "hash-function" to the nettle API, which simply returns
|
||||
the input data, concatenated into a single, statically maintained, buffer.
|
||||
|
||||
Used for the EdDSA sigs, which operate on the whole message, rather
|
||||
than a digest. */
|
||||
|
||||
struct null_hash_digest
|
||||
{
|
||||
uint8_t *buff;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
struct null_hash_ctx
|
||||
{
|
||||
size_t len;
|
||||
};
|
||||
|
||||
static size_t null_hash_buff_sz = 0;
|
||||
static uint8_t *null_hash_buff = NULL;
|
||||
#define BUFF_INCR 128
|
||||
|
||||
static void null_hash_init(void *ctx)
|
||||
{
|
||||
((struct null_hash_ctx *)ctx)->len = 0;
|
||||
}
|
||||
|
||||
static void null_hash_update(void *ctxv, size_t length, const uint8_t *src)
|
||||
{
|
||||
struct null_hash_ctx *ctx = ctxv;
|
||||
size_t new_len = ctx->len + length;
|
||||
|
||||
if (new_len > null_hash_buff_sz)
|
||||
{
|
||||
uint8_t *new;
|
||||
|
||||
if (!(new = whine_malloc(new_len + BUFF_INCR)))
|
||||
return;
|
||||
|
||||
if (null_hash_buff)
|
||||
{
|
||||
if (ctx->len != 0)
|
||||
memcpy(new, null_hash_buff, ctx->len);
|
||||
free(null_hash_buff);
|
||||
}
|
||||
|
||||
null_hash_buff_sz = new_len + BUFF_INCR;
|
||||
null_hash_buff = new;
|
||||
}
|
||||
|
||||
memcpy(null_hash_buff + ctx->len, src, length);
|
||||
ctx->len += length;
|
||||
}
|
||||
|
||||
|
||||
static void null_hash_digest(void *ctx, size_t length, uint8_t *dst)
|
||||
{
|
||||
(void)length;
|
||||
|
||||
((struct null_hash_digest *)dst)->buff = null_hash_buff;
|
||||
((struct null_hash_digest *)dst)->len = ((struct null_hash_ctx *)ctx)->len;
|
||||
}
|
||||
|
||||
static struct nettle_hash null_hash = {
|
||||
"null_hash",
|
||||
sizeof(struct null_hash_ctx),
|
||||
sizeof(struct null_hash_digest),
|
||||
0,
|
||||
(nettle_hash_init_func *) null_hash_init,
|
||||
(nettle_hash_update_func *) null_hash_update,
|
||||
(nettle_hash_digest_func *) null_hash_digest
|
||||
};
|
||||
|
||||
/* Find pointer to correct hash function in nettle library */
|
||||
const struct nettle_hash *hash_find(char *name)
|
||||
{
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
/* We provide a "null" hash which returns the input data as digest. */
|
||||
if (strcmp(null_hash.name, name) == 0)
|
||||
return &null_hash;
|
||||
|
||||
/* libnettle >= 3.4 provides nettle_lookup_hash() which avoids nasty ABI
|
||||
incompatibilities if sizeof(nettle_hashes) changes between library
|
||||
versions. It also #defines nettle_hashes, so use that to tell
|
||||
if we have the new facilities. */
|
||||
|
||||
#ifdef nettle_hashes
|
||||
return nettle_lookup_hash(name);
|
||||
#else
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; nettle_hashes[i]; i++)
|
||||
if (strcmp(nettle_hashes[i]->name, name) == 0)
|
||||
return nettle_hashes[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* expand ctx and digest memory allocations if necessary and init hash function */
|
||||
int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp)
|
||||
{
|
||||
static void *ctx = NULL;
|
||||
static unsigned char *digest = NULL;
|
||||
static unsigned int ctx_sz = 0;
|
||||
static unsigned int digest_sz = 0;
|
||||
|
||||
void *new;
|
||||
|
||||
if (ctx_sz < hash->context_size)
|
||||
{
|
||||
if (!(new = whine_malloc(hash->context_size)))
|
||||
return 0;
|
||||
if (ctx)
|
||||
free(ctx);
|
||||
ctx = new;
|
||||
ctx_sz = hash->context_size;
|
||||
}
|
||||
|
||||
if (digest_sz < hash->digest_size)
|
||||
{
|
||||
if (!(new = whine_malloc(hash->digest_size)))
|
||||
return 0;
|
||||
if (digest)
|
||||
free(digest);
|
||||
digest = new;
|
||||
digest_sz = hash->digest_size;
|
||||
}
|
||||
|
||||
*ctxp = ctx;
|
||||
*digestp = digest;
|
||||
|
||||
hash->init(ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dnsmasq_rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
||||
unsigned char *digest, size_t digest_len, int algo)
|
||||
{
|
||||
unsigned char *p;
|
||||
size_t exp_len;
|
||||
|
||||
static struct rsa_public_key *key = NULL;
|
||||
static mpz_t sig_mpz;
|
||||
|
||||
(void)digest_len;
|
||||
|
||||
if (key == NULL)
|
||||
{
|
||||
if (!(key = whine_malloc(sizeof(struct rsa_public_key))))
|
||||
return 0;
|
||||
|
||||
nettle_rsa_public_key_init(key);
|
||||
mpz_init(sig_mpz);
|
||||
}
|
||||
|
||||
if ((key_len < 3) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
|
||||
return 0;
|
||||
|
||||
key_len--;
|
||||
if ((exp_len = *p++) == 0)
|
||||
{
|
||||
GETSHORT(exp_len, p);
|
||||
key_len -= 2;
|
||||
}
|
||||
|
||||
if (exp_len >= key_len)
|
||||
return 0;
|
||||
|
||||
key->size = key_len - exp_len;
|
||||
mpz_import(key->e, exp_len, 1, 1, 0, 0, p);
|
||||
mpz_import(key->n, key->size, 1, 1, 0, 0, p + exp_len);
|
||||
|
||||
mpz_import(sig_mpz, sig_len, 1, 1, 0, 0, sig);
|
||||
|
||||
switch (algo)
|
||||
{
|
||||
case 1:
|
||||
return nettle_rsa_md5_verify_digest(key, digest, sig_mpz);
|
||||
case 5: case 7:
|
||||
return nettle_rsa_sha1_verify_digest(key, digest, sig_mpz);
|
||||
case 8:
|
||||
return nettle_rsa_sha256_verify_digest(key, digest, sig_mpz);
|
||||
case 10:
|
||||
return nettle_rsa_sha512_verify_digest(key, digest, sig_mpz);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dnsmasq_dsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
||||
unsigned char *digest, size_t digest_len, int algo)
|
||||
{
|
||||
unsigned char *p;
|
||||
unsigned int t;
|
||||
|
||||
static mpz_t y;
|
||||
static struct dsa_params *params = NULL;
|
||||
static struct dsa_signature *sig_struct;
|
||||
|
||||
(void)digest_len;
|
||||
|
||||
if (params == NULL)
|
||||
{
|
||||
if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))) ||
|
||||
!(params = whine_malloc(sizeof(struct dsa_params))))
|
||||
return 0;
|
||||
|
||||
mpz_init(y);
|
||||
nettle_dsa_params_init(params);
|
||||
nettle_dsa_signature_init(sig_struct);
|
||||
}
|
||||
|
||||
if ((sig_len < 41) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
|
||||
return 0;
|
||||
|
||||
t = *p++;
|
||||
|
||||
if (key_len < (213 + (t * 24)))
|
||||
return 0;
|
||||
|
||||
mpz_import(params->q, 20, 1, 1, 0, 0, p); p += 20;
|
||||
mpz_import(params->p, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
|
||||
mpz_import(params->g, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
|
||||
mpz_import(y, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
|
||||
|
||||
mpz_import(sig_struct->r, 20, 1, 1, 0, 0, sig+1);
|
||||
mpz_import(sig_struct->s, 20, 1, 1, 0, 0, sig+21);
|
||||
|
||||
(void)algo;
|
||||
|
||||
return nettle_dsa_verify(params, y, digest_len, digest, sig_struct);
|
||||
}
|
||||
|
||||
static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len,
|
||||
unsigned char *sig, size_t sig_len,
|
||||
unsigned char *digest, size_t digest_len, int algo)
|
||||
{
|
||||
unsigned char *p;
|
||||
unsigned int t;
|
||||
struct ecc_point *key;
|
||||
|
||||
static struct ecc_point *key_256 = NULL, *key_384 = NULL;
|
||||
static mpz_t x, y;
|
||||
static struct dsa_signature *sig_struct;
|
||||
|
||||
if (!sig_struct)
|
||||
{
|
||||
if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))))
|
||||
return 0;
|
||||
|
||||
nettle_dsa_signature_init(sig_struct);
|
||||
mpz_init(x);
|
||||
mpz_init(y);
|
||||
}
|
||||
|
||||
switch (algo)
|
||||
{
|
||||
case 13:
|
||||
if (!key_256)
|
||||
{
|
||||
if (!(key_256 = whine_malloc(sizeof(struct ecc_point))))
|
||||
return 0;
|
||||
|
||||
nettle_ecc_point_init(key_256, &nettle_secp_256r1);
|
||||
}
|
||||
|
||||
key = key_256;
|
||||
t = 32;
|
||||
break;
|
||||
|
||||
case 14:
|
||||
if (!key_384)
|
||||
{
|
||||
if (!(key_384 = whine_malloc(sizeof(struct ecc_point))))
|
||||
return 0;
|
||||
|
||||
nettle_ecc_point_init(key_384, &nettle_secp_384r1);
|
||||
}
|
||||
|
||||
key = key_384;
|
||||
t = 48;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sig_len != 2*t || key_len != 2*t ||
|
||||
!(p = blockdata_retrieve(key_data, key_len, NULL)))
|
||||
return 0;
|
||||
|
||||
mpz_import(x, t , 1, 1, 0, 0, p);
|
||||
mpz_import(y, t , 1, 1, 0, 0, p + t);
|
||||
|
||||
if (!ecc_point_set(key, x, y))
|
||||
return 0;
|
||||
|
||||
mpz_import(sig_struct->r, t, 1, 1, 0, 0, sig);
|
||||
mpz_import(sig_struct->s, t, 1, 1, 0, 0, sig + t);
|
||||
|
||||
return nettle_ecdsa_verify(key, digest_len, digest, sig_struct);
|
||||
}
|
||||
|
||||
static int dnsmasq_eddsa_verify(struct blockdata *key_data, unsigned int key_len,
|
||||
unsigned char *sig, size_t sig_len,
|
||||
unsigned char *digest, size_t digest_len, int algo)
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
if (key_len != ED25519_KEY_SIZE ||
|
||||
sig_len != ED25519_SIGNATURE_SIZE ||
|
||||
digest_len != sizeof(struct null_hash_digest) ||
|
||||
!(p = blockdata_retrieve(key_data, key_len, NULL)))
|
||||
return 0;
|
||||
|
||||
/* The "digest" returned by the null_hash function is simply a struct null_hash_digest
|
||||
which has a pointer to the actual data and a length, because the buffer
|
||||
may need to be extended during "hashing". */
|
||||
|
||||
switch (algo)
|
||||
{
|
||||
case 15:
|
||||
return ed25519_sha512_verify(p,
|
||||
((struct null_hash_digest *)digest)->len,
|
||||
((struct null_hash_digest *)digest)->buff,
|
||||
sig);
|
||||
case 16:
|
||||
/* Ed448 when available */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int (*verify_func(int algo))(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
||||
unsigned char *digest, size_t digest_len, int algo)
|
||||
{
|
||||
|
||||
/* Enure at runtime that we have support for this digest */
|
||||
if (!hash_find(algo_digest_name(algo)))
|
||||
return NULL;
|
||||
|
||||
/* This switch defines which sig algorithms we support, can't introspect Nettle for that. */
|
||||
switch (algo)
|
||||
{
|
||||
case 1: case 5: case 7: case 8: case 10:
|
||||
return dnsmasq_rsa_verify;
|
||||
|
||||
case 3: case 6:
|
||||
return dnsmasq_dsa_verify;
|
||||
|
||||
case 13: case 14:
|
||||
return dnsmasq_ecdsa_verify;
|
||||
|
||||
case 15: case 16:
|
||||
return dnsmasq_eddsa_verify;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
||||
unsigned char *digest, size_t digest_len, int algo)
|
||||
{
|
||||
|
||||
int (*func)(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
||||
unsigned char *digest, size_t digest_len, int algo);
|
||||
|
||||
func = verify_func(algo);
|
||||
|
||||
if (!func)
|
||||
return 0;
|
||||
|
||||
return (*func)(key_data, key_len, sig, sig_len, digest, digest_len, algo);
|
||||
}
|
||||
|
||||
/* Note the ds_digest_name(), algo_digest_name() and nsec3_digest_name()
|
||||
define which algo numbers we support. If algo_digest_name() returns
|
||||
non-NULL for an algorithm number, we assume that algorithm is
|
||||
supported by verify(). */
|
||||
|
||||
/* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
|
||||
char *ds_digest_name(int digest)
|
||||
{
|
||||
switch (digest)
|
||||
{
|
||||
case 1: return "sha1";
|
||||
case 2: return "sha256";
|
||||
case 3: return "gosthash94";
|
||||
case 4: return "sha384";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
|
||||
char *algo_digest_name(int algo)
|
||||
{
|
||||
switch (algo)
|
||||
{
|
||||
case 1: return NULL; /* RSA/MD5 - Must Not Implement. RFC 6944 para 2.3. */
|
||||
case 2: return NULL; /* Diffie-Hellman */
|
||||
case 3: return "sha1"; /* DSA/SHA1 */
|
||||
case 5: return "sha1"; /* RSA/SHA1 */
|
||||
case 6: return "sha1"; /* DSA-NSEC3-SHA1 */
|
||||
case 7: return "sha1"; /* RSASHA1-NSEC3-SHA1 */
|
||||
case 8: return "sha256"; /* RSA/SHA-256 */
|
||||
case 10: return "sha512"; /* RSA/SHA-512 */
|
||||
case 12: return NULL; /* ECC-GOST */
|
||||
case 13: return "sha256"; /* ECDSAP256SHA256 */
|
||||
case 14: return "sha384"; /* ECDSAP384SHA384 */
|
||||
case 15: return "null_hash"; /* ED25519 */
|
||||
case 16: return NULL; /* ED448 */
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* http://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml */
|
||||
char *nsec3_digest_name(int digest)
|
||||
{
|
||||
switch (digest)
|
||||
{
|
||||
case 1: return "sha1";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
706
src/dbus.c
706
src/dbus.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
const char* introspection_xml =
|
||||
const char* introspection_xml_template =
|
||||
"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
|
||||
"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
|
||||
"<node name=\"" DNSMASQ_PATH "\">\n"
|
||||
@@ -29,15 +29,32 @@ const char* introspection_xml =
|
||||
" <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
|
||||
" </method>\n"
|
||||
" </interface>\n"
|
||||
" <interface name=\"" DNSMASQ_SERVICE "\">\n"
|
||||
" <interface name=\"%s\">\n"
|
||||
" <method name=\"ClearCache\">\n"
|
||||
" </method>\n"
|
||||
" <method name=\"GetVersion\">\n"
|
||||
" <arg name=\"version\" direction=\"out\" type=\"s\"/>\n"
|
||||
" </method>\n"
|
||||
#ifdef HAVE_LOOP
|
||||
" <method name=\"GetLoopServers\">\n"
|
||||
" <arg name=\"server\" direction=\"out\" type=\"as\"/>\n"
|
||||
" </method>\n"
|
||||
#endif
|
||||
" <method name=\"SetServers\">\n"
|
||||
" <arg name=\"servers\" direction=\"in\" type=\"av\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetDomainServers\">\n"
|
||||
" <arg name=\"servers\" direction=\"in\" type=\"as\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetServersEx\">\n"
|
||||
" <arg name=\"servers\" direction=\"in\" type=\"aas\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetFilterWin2KOption\">\n"
|
||||
" <arg name=\"filterwin2k\" direction=\"in\" type=\"b\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetBogusPrivOption\">\n"
|
||||
" <arg name=\"boguspriv\" direction=\"in\" type=\"b\"/>\n"
|
||||
" </method>\n"
|
||||
" <signal name=\"DhcpLeaseAdded\">\n"
|
||||
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
||||
@@ -53,9 +70,29 @@ const char* introspection_xml =
|
||||
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hostname\" type=\"s\"/>\n"
|
||||
" </signal>\n"
|
||||
#ifdef HAVE_DHCP
|
||||
" <method name=\"AddDhcpLease\">\n"
|
||||
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hostname\" type=\"ay\"/>\n"
|
||||
" <arg name=\"clid\" type=\"ay\"/>\n"
|
||||
" <arg name=\"lease_duration\" type=\"u\"/>\n"
|
||||
" <arg name=\"ia_id\" type=\"u\"/>\n"
|
||||
" <arg name=\"is_temporary\" type=\"b\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"DeleteDhcpLease\">\n"
|
||||
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"success\" type=\"b\" direction=\"out\"/>\n"
|
||||
" </method>\n"
|
||||
#endif
|
||||
" <method name=\"GetMetrics\">\n"
|
||||
" <arg name=\"metrics\" direction=\"out\" type=\"a{su}\"/>\n"
|
||||
" </method>\n"
|
||||
" </interface>\n"
|
||||
"</node>\n";
|
||||
|
||||
static char *introspection_xml = NULL;
|
||||
|
||||
struct watch {
|
||||
DBusWatch *watch;
|
||||
struct watch *next;
|
||||
@@ -83,33 +120,32 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data)
|
||||
|
||||
static void remove_watch(DBusWatch *watch, void *data)
|
||||
{
|
||||
struct watch **up, *w;
|
||||
struct watch **up, *w, *tmp;
|
||||
|
||||
for (up = &(daemon->watches), w = daemon->watches; w; w = w->next)
|
||||
if (w->watch == watch)
|
||||
{
|
||||
*up = w->next;
|
||||
free(w);
|
||||
}
|
||||
else
|
||||
up = &(w->next);
|
||||
for (up = &(daemon->watches), w = daemon->watches; w; w = tmp)
|
||||
{
|
||||
tmp = w->next;
|
||||
if (w->watch == watch)
|
||||
{
|
||||
*up = tmp;
|
||||
free(w);
|
||||
}
|
||||
else
|
||||
up = &(w->next);
|
||||
}
|
||||
|
||||
w = data; /* no warning */
|
||||
}
|
||||
|
||||
static void dbus_read_servers(DBusMessage *message)
|
||||
{
|
||||
struct server *serv, *tmp, **up;
|
||||
DBusMessageIter iter;
|
||||
union mysockaddr addr, source_addr;
|
||||
char *domain;
|
||||
|
||||
dbus_message_iter_init(message, &iter);
|
||||
|
||||
/* mark everything from DBUS */
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
if (serv->flags & SERV_FROM_DBUS)
|
||||
serv->flags |= SERV_MARK;
|
||||
|
||||
mark_servers(SERV_FROM_DBUS);
|
||||
|
||||
while (1)
|
||||
{
|
||||
@@ -143,13 +179,16 @@ static void dbus_read_servers(DBusMessage *message)
|
||||
dbus_message_iter_get_basic(&iter, &p[i]);
|
||||
dbus_message_iter_next (&iter);
|
||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BYTE)
|
||||
break;
|
||||
{
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef HAVE_IPV6
|
||||
my_syslog(LOG_WARNING, _("attempt to set an IPv6 server address via DBus - no IPv6 support"));
|
||||
#else
|
||||
if (i == sizeof(struct in6_addr)-1)
|
||||
if (i == sizeof(struct in6_addr))
|
||||
{
|
||||
memcpy(&addr.in6.sin6_addr, p, sizeof(struct in6_addr));
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
@@ -169,6 +208,7 @@ static void dbus_read_servers(DBusMessage *message)
|
||||
/* At the end */
|
||||
break;
|
||||
|
||||
/* process each domain */
|
||||
do {
|
||||
if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING)
|
||||
{
|
||||
@@ -179,83 +219,425 @@ static void dbus_read_servers(DBusMessage *message)
|
||||
domain = NULL;
|
||||
|
||||
if (!skip)
|
||||
{
|
||||
/* See if this is already there, and unmark */
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
if ((serv->flags & SERV_FROM_DBUS) &&
|
||||
(serv->flags & SERV_MARK))
|
||||
{
|
||||
if (!(serv->flags & SERV_HAS_DOMAIN) && !domain)
|
||||
{
|
||||
serv->flags &= ~SERV_MARK;
|
||||
break;
|
||||
}
|
||||
if ((serv->flags & SERV_HAS_DOMAIN) &&
|
||||
domain &&
|
||||
hostname_isequal(domain, serv->domain))
|
||||
{
|
||||
serv->flags &= ~SERV_MARK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!serv && (serv = whine_malloc(sizeof (struct server))))
|
||||
{
|
||||
/* Not found, create a new one. */
|
||||
memset(serv, 0, sizeof(struct server));
|
||||
|
||||
if (domain)
|
||||
serv->domain = whine_malloc(strlen(domain)+1);
|
||||
|
||||
if (domain && !serv->domain)
|
||||
{
|
||||
free(serv);
|
||||
serv = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
serv->next = daemon->servers;
|
||||
daemon->servers = serv;
|
||||
serv->flags = SERV_FROM_DBUS;
|
||||
if (domain)
|
||||
{
|
||||
strcpy(serv->domain, domain);
|
||||
serv->flags |= SERV_HAS_DOMAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serv)
|
||||
{
|
||||
if (source_addr.in.sin_family == AF_INET &&
|
||||
addr.in.sin_addr.s_addr == 0 &&
|
||||
serv->domain)
|
||||
serv->flags |= SERV_NO_ADDR;
|
||||
else
|
||||
{
|
||||
serv->flags &= ~SERV_NO_ADDR;
|
||||
serv->addr = addr;
|
||||
serv->source_addr = source_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING);
|
||||
add_update_server(SERV_FROM_DBUS, &addr, &source_addr, NULL, domain);
|
||||
|
||||
} while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING);
|
||||
}
|
||||
|
||||
|
||||
/* unlink and free anything still marked. */
|
||||
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
||||
cleanup_servers();
|
||||
}
|
||||
|
||||
#ifdef HAVE_LOOP
|
||||
static DBusMessage *dbus_reply_server_loop(DBusMessage *message)
|
||||
{
|
||||
DBusMessageIter args, args_iter;
|
||||
struct server *serv;
|
||||
DBusMessage *reply = dbus_message_new_method_return(message);
|
||||
|
||||
dbus_message_iter_init_append (reply, &args);
|
||||
dbus_message_iter_open_container (&args, DBUS_TYPE_ARRAY,DBUS_TYPE_STRING_AS_STRING, &args_iter);
|
||||
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
if (serv->flags & SERV_LOOP)
|
||||
{
|
||||
prettyprint_addr(&serv->addr, daemon->addrbuff);
|
||||
dbus_message_iter_append_basic (&args_iter, DBUS_TYPE_STRING, &daemon->addrbuff);
|
||||
}
|
||||
|
||||
dbus_message_iter_close_container (&args, &args_iter);
|
||||
|
||||
return reply;
|
||||
}
|
||||
#endif
|
||||
|
||||
static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
||||
{
|
||||
DBusMessageIter iter, array_iter, string_iter;
|
||||
DBusMessage *error = NULL;
|
||||
const char *addr_err;
|
||||
char *dup = NULL;
|
||||
|
||||
if (!dbus_message_iter_init(message, &iter))
|
||||
{
|
||||
tmp = serv->next;
|
||||
if (serv->flags & SERV_MARK)
|
||||
{
|
||||
server_gone(serv);
|
||||
*up = serv->next;
|
||||
free(serv);
|
||||
}
|
||||
else
|
||||
up = &serv->next;
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Failed to initialize dbus message iter");
|
||||
}
|
||||
|
||||
/* check that the message contains an array of arrays */
|
||||
if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
|
||||
(dbus_message_iter_get_element_type(&iter) != (strings ? DBUS_TYPE_STRING : DBUS_TYPE_ARRAY)))
|
||||
{
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
strings ? "Expected array of string" : "Expected array of string arrays");
|
||||
}
|
||||
|
||||
mark_servers(SERV_FROM_DBUS);
|
||||
|
||||
/* array_iter points to each "as" element in the outer array */
|
||||
dbus_message_iter_recurse(&iter, &array_iter);
|
||||
while (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_INVALID)
|
||||
{
|
||||
const char *str = NULL;
|
||||
union mysockaddr addr, source_addr;
|
||||
int flags = 0;
|
||||
char interface[IF_NAMESIZE];
|
||||
char *str_addr, *str_domain = NULL;
|
||||
|
||||
if (strings)
|
||||
{
|
||||
dbus_message_iter_get_basic(&array_iter, &str);
|
||||
if (!str || !strlen (str))
|
||||
{
|
||||
error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Empty string");
|
||||
break;
|
||||
}
|
||||
|
||||
/* dup the string because it gets modified during parsing */
|
||||
if (dup)
|
||||
free(dup);
|
||||
if (!(dup = str_domain = whine_malloc(strlen(str)+1)))
|
||||
break;
|
||||
|
||||
strcpy(str_domain, str);
|
||||
|
||||
/* point to address part of old string for error message */
|
||||
if ((str_addr = strrchr(str, '/')))
|
||||
str = str_addr+1;
|
||||
|
||||
if ((str_addr = strrchr(str_domain, '/')))
|
||||
{
|
||||
if (*str_domain != '/' || str_addr == str_domain)
|
||||
{
|
||||
error = dbus_message_new_error_printf(message,
|
||||
DBUS_ERROR_INVALID_ARGS,
|
||||
"No domain terminator '%s'",
|
||||
str);
|
||||
break;
|
||||
}
|
||||
*str_addr++ = 0;
|
||||
str_domain++;
|
||||
}
|
||||
else
|
||||
{
|
||||
str_addr = str_domain;
|
||||
str_domain = NULL;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* check the types of the struct and its elements */
|
||||
if ((dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY) ||
|
||||
(dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_STRING))
|
||||
{
|
||||
error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected inner array of strings");
|
||||
break;
|
||||
}
|
||||
|
||||
/* string_iter points to each "s" element in the inner array */
|
||||
dbus_message_iter_recurse(&array_iter, &string_iter);
|
||||
if (dbus_message_iter_get_arg_type(&string_iter) != DBUS_TYPE_STRING)
|
||||
{
|
||||
/* no IP address given */
|
||||
error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected IP address");
|
||||
break;
|
||||
}
|
||||
|
||||
dbus_message_iter_get_basic(&string_iter, &str);
|
||||
if (!str || !strlen (str))
|
||||
{
|
||||
error = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Empty IP address");
|
||||
break;
|
||||
}
|
||||
|
||||
/* dup the string because it gets modified during parsing */
|
||||
if (dup)
|
||||
free(dup);
|
||||
if (!(dup = str_addr = whine_malloc(strlen(str)+1)))
|
||||
break;
|
||||
|
||||
strcpy(str_addr, str);
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
memset(&source_addr, 0, sizeof(source_addr));
|
||||
memset(&interface, 0, sizeof(interface));
|
||||
|
||||
/* parse the IP address */
|
||||
if ((addr_err = parse_server(str_addr, &addr, &source_addr, (char *) &interface, &flags)))
|
||||
{
|
||||
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid IP address '%s': %s",
|
||||
str, addr_err);
|
||||
break;
|
||||
}
|
||||
|
||||
/* 0.0.0.0 for server address == NULL, for Dbus */
|
||||
if (addr.in.sin_family == AF_INET &&
|
||||
addr.in.sin_addr.s_addr == 0)
|
||||
flags |= SERV_NO_ADDR;
|
||||
|
||||
if (strings)
|
||||
{
|
||||
char *p;
|
||||
|
||||
do {
|
||||
if (str_domain)
|
||||
{
|
||||
if ((p = strchr(str_domain, '/')))
|
||||
*p++ = 0;
|
||||
}
|
||||
else
|
||||
p = NULL;
|
||||
|
||||
add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str_domain);
|
||||
} while ((str_domain = p));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* jump past the address to the domain list (if any) */
|
||||
dbus_message_iter_next (&string_iter);
|
||||
|
||||
/* parse domains and add each server/domain pair to the list */
|
||||
do {
|
||||
str = NULL;
|
||||
if (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING)
|
||||
dbus_message_iter_get_basic(&string_iter, &str);
|
||||
dbus_message_iter_next (&string_iter);
|
||||
|
||||
add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str);
|
||||
} while (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING);
|
||||
}
|
||||
|
||||
/* jump to next element in outer array */
|
||||
dbus_message_iter_next(&array_iter);
|
||||
}
|
||||
|
||||
cleanup_servers();
|
||||
|
||||
if (dup)
|
||||
free(dup);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static DBusMessage *dbus_set_bool(DBusMessage *message, int flag, char *name)
|
||||
{
|
||||
DBusMessageIter iter;
|
||||
dbus_bool_t enabled;
|
||||
|
||||
if (!dbus_message_iter_init(message, &iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "Expected boolean argument");
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &enabled);
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
my_syslog(LOG_INFO, _("Enabling --%s option from D-Bus"), name);
|
||||
set_option_bool(flag);
|
||||
}
|
||||
else
|
||||
{
|
||||
my_syslog(LOG_INFO, _("Disabling --%s option from D-Bus"), name);
|
||||
reset_option_bool(flag);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
static DBusMessage *dbus_add_lease(DBusMessage* message)
|
||||
{
|
||||
struct dhcp_lease *lease;
|
||||
const char *ipaddr, *hwaddr, *hostname, *tmp;
|
||||
const unsigned char* clid;
|
||||
int clid_len, hostname_len, hw_len, hw_type;
|
||||
dbus_uint32_t expires, ia_id;
|
||||
dbus_bool_t is_temporary;
|
||||
struct all_addr addr;
|
||||
time_t now = dnsmasq_time();
|
||||
unsigned char dhcp_chaddr[DHCP_CHADDR_MAX];
|
||||
|
||||
DBusMessageIter iter, array_iter;
|
||||
if (!dbus_message_iter_init(message, &iter))
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Failed to initialize dbus message iter");
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected string as first argument");
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &ipaddr);
|
||||
dbus_message_iter_next(&iter);
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected string as second argument");
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &hwaddr);
|
||||
dbus_message_iter_next(&iter);
|
||||
|
||||
if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
|
||||
(dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected byte array as third argument");
|
||||
|
||||
dbus_message_iter_recurse(&iter, &array_iter);
|
||||
dbus_message_iter_get_fixed_array(&array_iter, &hostname, &hostname_len);
|
||||
tmp = memchr(hostname, '\0', hostname_len);
|
||||
if (tmp)
|
||||
{
|
||||
if (tmp == &hostname[hostname_len - 1])
|
||||
hostname_len--;
|
||||
else
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Hostname contains an embedded NUL character");
|
||||
}
|
||||
dbus_message_iter_next(&iter);
|
||||
|
||||
if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
|
||||
(dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected byte array as fourth argument");
|
||||
|
||||
dbus_message_iter_recurse(&iter, &array_iter);
|
||||
dbus_message_iter_get_fixed_array(&array_iter, &clid, &clid_len);
|
||||
dbus_message_iter_next(&iter);
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected uint32 as fifth argument");
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &expires);
|
||||
dbus_message_iter_next(&iter);
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected uint32 as sixth argument");
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &ia_id);
|
||||
dbus_message_iter_next(&iter);
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected uint32 as sixth argument");
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &is_temporary);
|
||||
|
||||
if (inet_pton(AF_INET, ipaddr, &addr.addr.addr4))
|
||||
{
|
||||
if (ia_id != 0 || is_temporary)
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"ia_id and is_temporary must be zero for IPv4 lease");
|
||||
|
||||
if (!(lease = lease_find_by_addr(addr.addr.addr4)))
|
||||
lease = lease4_allocate(addr.addr.addr4);
|
||||
}
|
||||
#ifdef HAVE_DHCP6
|
||||
else if (inet_pton(AF_INET6, ipaddr, &addr.addr.addr6))
|
||||
{
|
||||
if (!(lease = lease6_find_by_addr(&addr.addr.addr6, 128, 0)))
|
||||
lease = lease6_allocate(&addr.addr.addr6,
|
||||
is_temporary ? LEASE_TA : LEASE_NA);
|
||||
lease_set_iaid(lease, ia_id);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid IP address '%s'", ipaddr);
|
||||
|
||||
hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL, &hw_type);
|
||||
if (hw_type == 0 && hw_len != 0)
|
||||
hw_type = ARPHRD_ETHER;
|
||||
|
||||
lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type,
|
||||
clid_len, now, 0);
|
||||
lease_set_expires(lease, expires, now);
|
||||
if (hostname_len != 0)
|
||||
lease_set_hostname(lease, hostname, 0, get_domain(lease->addr), NULL);
|
||||
|
||||
lease_update_file(now);
|
||||
lease_update_dns(0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DBusMessage *dbus_del_lease(DBusMessage* message)
|
||||
{
|
||||
struct dhcp_lease *lease;
|
||||
DBusMessageIter iter;
|
||||
const char *ipaddr;
|
||||
DBusMessage *reply;
|
||||
struct all_addr addr;
|
||||
dbus_bool_t ret = 1;
|
||||
time_t now = dnsmasq_time();
|
||||
|
||||
if (!dbus_message_iter_init(message, &iter))
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Failed to initialize dbus message iter");
|
||||
|
||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Expected string as first argument");
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &ipaddr);
|
||||
|
||||
if (inet_pton(AF_INET, ipaddr, &addr.addr.addr4))
|
||||
lease = lease_find_by_addr(addr.addr.addr4);
|
||||
#ifdef HAVE_DHCP6
|
||||
else if (inet_pton(AF_INET6, ipaddr, &addr.addr.addr6))
|
||||
lease = lease6_find_by_addr(&addr.addr.addr6, 128, 0);
|
||||
#endif
|
||||
else
|
||||
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid IP address '%s'", ipaddr);
|
||||
|
||||
if (lease)
|
||||
{
|
||||
lease_prune(lease, now);
|
||||
lease_update_file(now);
|
||||
lease_update_dns(0);
|
||||
}
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
if ((reply = dbus_message_new_method_return(message)))
|
||||
dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &ret,
|
||||
DBUS_TYPE_INVALID);
|
||||
|
||||
|
||||
return reply;
|
||||
}
|
||||
#endif
|
||||
|
||||
static DBusMessage *dbus_get_metrics(DBusMessage* message)
|
||||
{
|
||||
DBusMessage *reply = dbus_message_new_method_return(message);
|
||||
DBusMessageIter array, dict, iter;
|
||||
int i;
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{su}", &array);
|
||||
|
||||
for (i = 0; i < __METRIC_MAX; i++) {
|
||||
const char *key = get_metric_name(i);
|
||||
dbus_uint32_t value = daemon->metrics[i];
|
||||
|
||||
dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
|
||||
dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
|
||||
dbus_message_iter_append_basic(&dict, DBUS_TYPE_UINT32, &value);
|
||||
dbus_message_iter_close_container(&array, &dict);
|
||||
}
|
||||
|
||||
dbus_message_iter_close_container(&iter, &array);
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
@@ -263,39 +645,101 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
void *user_data)
|
||||
{
|
||||
char *method = (char *)dbus_message_get_member(message);
|
||||
|
||||
DBusMessage *reply = NULL;
|
||||
int clear_cache = 0, new_servers = 0;
|
||||
|
||||
if (dbus_message_is_method_call(message, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
|
||||
{
|
||||
DBusMessage *reply = dbus_message_new_method_return(message);
|
||||
|
||||
dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection_xml, DBUS_TYPE_INVALID);
|
||||
dbus_connection_send (connection, reply, NULL);
|
||||
dbus_message_unref (reply);
|
||||
/* string length: "%s" provides space for termination zero */
|
||||
if (!introspection_xml &&
|
||||
(introspection_xml = whine_malloc(strlen(introspection_xml_template) + strlen(daemon->dbus_name))))
|
||||
sprintf(introspection_xml, introspection_xml_template, daemon->dbus_name);
|
||||
|
||||
if (introspection_xml)
|
||||
{
|
||||
reply = dbus_message_new_method_return(message);
|
||||
dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection_xml, DBUS_TYPE_INVALID);
|
||||
}
|
||||
}
|
||||
else if (strcmp(method, "GetVersion") == 0)
|
||||
{
|
||||
char *v = VERSION;
|
||||
DBusMessage *reply = dbus_message_new_method_return(message);
|
||||
reply = dbus_message_new_method_return(message);
|
||||
|
||||
dbus_message_append_args(reply, DBUS_TYPE_STRING, &v, DBUS_TYPE_INVALID);
|
||||
dbus_connection_send (connection, reply, NULL);
|
||||
dbus_message_unref (reply);
|
||||
}
|
||||
#ifdef HAVE_LOOP
|
||||
else if (strcmp(method, "GetLoopServers") == 0)
|
||||
{
|
||||
reply = dbus_reply_server_loop(message);
|
||||
}
|
||||
#endif
|
||||
else if (strcmp(method, "SetServers") == 0)
|
||||
{
|
||||
my_syslog(LOG_INFO, _("setting upstream servers from DBus"));
|
||||
dbus_read_servers(message);
|
||||
check_servers();
|
||||
new_servers = 1;
|
||||
}
|
||||
else if (strcmp(method, "SetServersEx") == 0)
|
||||
{
|
||||
reply = dbus_read_servers_ex(message, 0);
|
||||
new_servers = 1;
|
||||
}
|
||||
else if (strcmp(method, "SetDomainServers") == 0)
|
||||
{
|
||||
reply = dbus_read_servers_ex(message, 1);
|
||||
new_servers = 1;
|
||||
}
|
||||
else if (strcmp(method, "SetFilterWin2KOption") == 0)
|
||||
{
|
||||
reply = dbus_set_bool(message, OPT_FILTER, "filterwin2k");
|
||||
}
|
||||
else if (strcmp(method, "SetBogusPrivOption") == 0)
|
||||
{
|
||||
reply = dbus_set_bool(message, OPT_BOGUSPRIV, "bogus-priv");
|
||||
}
|
||||
#ifdef HAVE_DHCP
|
||||
else if (strcmp(method, "AddDhcpLease") == 0)
|
||||
{
|
||||
reply = dbus_add_lease(message);
|
||||
}
|
||||
else if (strcmp(method, "DeleteDhcpLease") == 0)
|
||||
{
|
||||
reply = dbus_del_lease(message);
|
||||
}
|
||||
#endif
|
||||
else if (strcmp(method, "GetMetrics") == 0)
|
||||
{
|
||||
reply = dbus_get_metrics(message);
|
||||
}
|
||||
else if (strcmp(method, "ClearCache") == 0)
|
||||
clear_cache_and_reload(dnsmasq_time());
|
||||
clear_cache = 1;
|
||||
else
|
||||
return (DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
|
||||
|
||||
if (new_servers)
|
||||
{
|
||||
my_syslog(LOG_INFO, _("setting upstream servers from DBus"));
|
||||
check_servers();
|
||||
if (option_bool(OPT_RELOAD))
|
||||
clear_cache = 1;
|
||||
}
|
||||
|
||||
if (clear_cache)
|
||||
clear_cache_and_reload(dnsmasq_time());
|
||||
|
||||
method = user_data; /* no warning */
|
||||
|
||||
/* If no reply or no error, return nothing */
|
||||
if (!reply)
|
||||
reply = dbus_message_new_method_return(message);
|
||||
|
||||
if (reply)
|
||||
{
|
||||
dbus_connection_send (connection, reply, NULL);
|
||||
dbus_message_unref (reply);
|
||||
}
|
||||
|
||||
return (DBUS_HANDLER_RESULT_HANDLED);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -315,7 +759,7 @@ char *dbus_init(void)
|
||||
dbus_connection_set_watch_functions(connection, add_watch, remove_watch,
|
||||
NULL, NULL, NULL);
|
||||
dbus_error_init (&dbus_error);
|
||||
dbus_bus_request_name (connection, DNSMASQ_SERVICE, 0, &dbus_error);
|
||||
dbus_bus_request_name (connection, daemon->dbus_name, 0, &dbus_error);
|
||||
if (dbus_error_is_set (&dbus_error))
|
||||
return (char *)dbus_error.message;
|
||||
|
||||
@@ -325,7 +769,7 @@ char *dbus_init(void)
|
||||
|
||||
daemon->dbus = connection;
|
||||
|
||||
if ((message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, "Up")))
|
||||
if ((message = dbus_message_new_signal(DNSMASQ_PATH, daemon->dbus_name, "Up")))
|
||||
{
|
||||
dbus_connection_send(connection, message, NULL);
|
||||
dbus_message_unref(message);
|
||||
@@ -335,8 +779,7 @@ char *dbus_init(void)
|
||||
}
|
||||
|
||||
|
||||
void set_dbus_listeners(int *maxfdp,
|
||||
fd_set *rset, fd_set *wset, fd_set *eset)
|
||||
void set_dbus_listeners(void)
|
||||
{
|
||||
struct watch *w;
|
||||
|
||||
@@ -346,19 +789,17 @@ void set_dbus_listeners(int *maxfdp,
|
||||
unsigned int flags = dbus_watch_get_flags(w->watch);
|
||||
int fd = dbus_watch_get_unix_fd(w->watch);
|
||||
|
||||
bump_maxfd(fd, maxfdp);
|
||||
|
||||
if (flags & DBUS_WATCH_READABLE)
|
||||
FD_SET(fd, rset);
|
||||
poll_listen(fd, POLLIN);
|
||||
|
||||
if (flags & DBUS_WATCH_WRITABLE)
|
||||
FD_SET(fd, wset);
|
||||
poll_listen(fd, POLLOUT);
|
||||
|
||||
FD_SET(fd, eset);
|
||||
poll_listen(fd, POLLERR);
|
||||
}
|
||||
}
|
||||
|
||||
void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
|
||||
void check_dbus_listeners()
|
||||
{
|
||||
DBusConnection *connection = (DBusConnection *)daemon->dbus;
|
||||
struct watch *w;
|
||||
@@ -369,13 +810,13 @@ void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
|
||||
unsigned int flags = 0;
|
||||
int fd = dbus_watch_get_unix_fd(w->watch);
|
||||
|
||||
if (FD_ISSET(fd, rset))
|
||||
if (poll_check(fd, POLLIN))
|
||||
flags |= DBUS_WATCH_READABLE;
|
||||
|
||||
if (FD_ISSET(fd, wset))
|
||||
if (poll_check(fd, POLLOUT))
|
||||
flags |= DBUS_WATCH_WRITABLE;
|
||||
|
||||
if (FD_ISSET(fd, eset))
|
||||
if (poll_check(fd, POLLERR))
|
||||
flags |= DBUS_WATCH_ERROR;
|
||||
|
||||
if (flags != 0)
|
||||
@@ -396,7 +837,7 @@ void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname)
|
||||
DBusConnection *connection = (DBusConnection *)daemon->dbus;
|
||||
DBusMessage* message = NULL;
|
||||
DBusMessageIter args;
|
||||
char *action_str, *addr, *mac = daemon->namebuff;
|
||||
char *action_str, *mac = daemon->namebuff;
|
||||
unsigned char *p;
|
||||
int i;
|
||||
|
||||
@@ -406,10 +847,21 @@ void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname)
|
||||
if (!hostname)
|
||||
hostname = "";
|
||||
|
||||
p = extended_hwaddr(lease->hwaddr_type, lease->hwaddr_len,
|
||||
lease->hwaddr, lease->clid_len, lease->clid, &i);
|
||||
print_mac(mac, p, i);
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (lease->flags & (LEASE_TA | LEASE_NA))
|
||||
{
|
||||
print_mac(mac, lease->clid, lease->clid_len);
|
||||
inet_ntop(AF_INET6, &lease->addr6, daemon->addrbuff, ADDRSTRLEN);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
p = extended_hwaddr(lease->hwaddr_type, lease->hwaddr_len,
|
||||
lease->hwaddr, lease->clid_len, lease->clid, &i);
|
||||
print_mac(mac, p, i);
|
||||
inet_ntop(AF_INET, &lease->addr, daemon->addrbuff, ADDRSTRLEN);
|
||||
}
|
||||
|
||||
if (action == ACTION_DEL)
|
||||
action_str = "DhcpLeaseDeleted";
|
||||
else if (action == ACTION_ADD)
|
||||
@@ -419,14 +871,12 @@ void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname)
|
||||
else
|
||||
return;
|
||||
|
||||
addr = inet_ntoa(lease->addr);
|
||||
|
||||
if (!(message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, action_str)))
|
||||
if (!(message = dbus_message_new_signal(DNSMASQ_PATH, daemon->dbus_name, action_str)))
|
||||
return;
|
||||
|
||||
dbus_message_iter_init_append(message, &args);
|
||||
|
||||
if (dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &addr) &&
|
||||
|
||||
if (dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &daemon->addrbuff) &&
|
||||
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &mac) &&
|
||||
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &hostname))
|
||||
dbus_connection_send(connection, message, NULL);
|
||||
|
||||
906
src/dhcp-common.c
Normal file
906
src/dhcp-common.c
Normal file
@@ -0,0 +1,906 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or
|
||||
(at your option) version 3 dated 29 June, 2007.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
|
||||
void dhcp_common_init(void)
|
||||
{
|
||||
/* These each hold a DHCP option max size 255
|
||||
and get a terminating zero added */
|
||||
daemon->dhcp_buff = safe_malloc(DHCP_BUFF_SZ);
|
||||
daemon->dhcp_buff2 = safe_malloc(DHCP_BUFF_SZ);
|
||||
daemon->dhcp_buff3 = safe_malloc(DHCP_BUFF_SZ);
|
||||
|
||||
/* dhcp_packet is used by v4 and v6, outpacket only by v6
|
||||
sizeof(struct dhcp_packet) is as good an initial size as any,
|
||||
even for v6 */
|
||||
expand_buf(&daemon->dhcp_packet, sizeof(struct dhcp_packet));
|
||||
#ifdef HAVE_DHCP6
|
||||
if (daemon->dhcp6)
|
||||
expand_buf(&daemon->outpacket, sizeof(struct dhcp_packet));
|
||||
#endif
|
||||
}
|
||||
|
||||
ssize_t recv_dhcp_packet(int fd, struct msghdr *msg)
|
||||
{
|
||||
ssize_t sz;
|
||||
|
||||
while (1)
|
||||
{
|
||||
msg->msg_flags = 0;
|
||||
while ((sz = recvmsg(fd, msg, MSG_PEEK | MSG_TRUNC)) == -1 && errno == EINTR);
|
||||
|
||||
if (sz == -1)
|
||||
return -1;
|
||||
|
||||
if (!(msg->msg_flags & MSG_TRUNC))
|
||||
break;
|
||||
|
||||
/* Very new Linux kernels return the actual size needed,
|
||||
older ones always return truncated size */
|
||||
if ((size_t)sz == msg->msg_iov->iov_len)
|
||||
{
|
||||
if (!expand_buf(msg->msg_iov, sz + 100))
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
expand_buf(msg->msg_iov, sz);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while ((sz = recvmsg(fd, msg, 0)) == -1 && errno == EINTR);
|
||||
|
||||
return (msg->msg_flags & MSG_TRUNC) ? -1 : sz;
|
||||
}
|
||||
|
||||
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
|
||||
{
|
||||
struct tag_if *exprs;
|
||||
struct dhcp_netid_list *list;
|
||||
|
||||
for (exprs = daemon->tag_if; exprs; exprs = exprs->next)
|
||||
if (match_netid(exprs->tag, tags, 1))
|
||||
for (list = exprs->set; list; list = list->next)
|
||||
{
|
||||
list->list->next = tags;
|
||||
tags = list->list;
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
|
||||
struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *context_tags, struct dhcp_opt *opts)
|
||||
{
|
||||
struct dhcp_netid *tagif = run_tag_if(tags);
|
||||
struct dhcp_opt *opt;
|
||||
struct dhcp_opt *tmp;
|
||||
|
||||
/* flag options which are valid with the current tag set (sans context tags) */
|
||||
for (opt = opts; opt; opt = opt->next)
|
||||
{
|
||||
opt->flags &= ~DHOPT_TAGOK;
|
||||
if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
|
||||
match_netid(opt->netid, tagif, 0))
|
||||
opt->flags |= DHOPT_TAGOK;
|
||||
}
|
||||
|
||||
/* now flag options which are valid, including the context tags,
|
||||
otherwise valid options are inhibited if we found a higher priority one above */
|
||||
if (context_tags)
|
||||
{
|
||||
struct dhcp_netid *last_tag;
|
||||
|
||||
for (last_tag = context_tags; last_tag->next; last_tag = last_tag->next);
|
||||
last_tag->next = tags;
|
||||
tagif = run_tag_if(context_tags);
|
||||
|
||||
/* reset stuff with tag:!<tag> which now matches. */
|
||||
for (opt = opts; opt; opt = opt->next)
|
||||
if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
|
||||
(opt->flags & DHOPT_TAGOK) &&
|
||||
!match_netid(opt->netid, tagif, 0))
|
||||
opt->flags &= ~DHOPT_TAGOK;
|
||||
|
||||
for (opt = opts; opt; opt = opt->next)
|
||||
if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925 | DHOPT_TAGOK)) &&
|
||||
match_netid(opt->netid, tagif, 0))
|
||||
{
|
||||
struct dhcp_opt *tmp;
|
||||
for (tmp = opts; tmp; tmp = tmp->next)
|
||||
if (tmp->opt == opt->opt && opt->netid && (tmp->flags & DHOPT_TAGOK))
|
||||
break;
|
||||
if (!tmp)
|
||||
opt->flags |= DHOPT_TAGOK;
|
||||
}
|
||||
}
|
||||
|
||||
/* now flag untagged options which are not overridden by tagged ones */
|
||||
for (opt = opts; opt; opt = opt->next)
|
||||
if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925 | DHOPT_TAGOK)) && !opt->netid)
|
||||
{
|
||||
for (tmp = opts; tmp; tmp = tmp->next)
|
||||
if (tmp->opt == opt->opt && (tmp->flags & DHOPT_TAGOK))
|
||||
break;
|
||||
if (!tmp)
|
||||
opt->flags |= DHOPT_TAGOK;
|
||||
else if (!tmp->netid)
|
||||
my_syslog(MS_DHCP | LOG_WARNING, _("Ignoring duplicate dhcp-option %d"), tmp->opt);
|
||||
}
|
||||
|
||||
/* Finally, eliminate duplicate options later in the chain, and therefore earlier in the config file. */
|
||||
for (opt = opts; opt; opt = opt->next)
|
||||
if (opt->flags & DHOPT_TAGOK)
|
||||
for (tmp = opt->next; tmp; tmp = tmp->next)
|
||||
if (tmp->opt == opt->opt)
|
||||
tmp->flags &= ~DHOPT_TAGOK;
|
||||
|
||||
return tagif;
|
||||
}
|
||||
|
||||
/* Is every member of check matched by a member of pool?
|
||||
If tagnotneeded, untagged is OK */
|
||||
int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotneeded)
|
||||
{
|
||||
struct dhcp_netid *tmp1;
|
||||
|
||||
if (!check && !tagnotneeded)
|
||||
return 0;
|
||||
|
||||
for (; check; check = check->next)
|
||||
{
|
||||
/* '#' for not is for backwards compat. */
|
||||
if (check->net[0] != '!' && check->net[0] != '#')
|
||||
{
|
||||
for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
|
||||
if (strcmp(check->net, tmp1->net) == 0)
|
||||
break;
|
||||
if (!tmp1)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
|
||||
if (strcmp((check->net)+1, tmp1->net) == 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* return domain or NULL if none. */
|
||||
char *strip_hostname(char *hostname)
|
||||
{
|
||||
char *dot = strchr(hostname, '.');
|
||||
|
||||
if (!dot)
|
||||
return NULL;
|
||||
|
||||
*dot = 0; /* truncate */
|
||||
if (strlen(dot+1) != 0)
|
||||
return dot+1;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void log_tags(struct dhcp_netid *netid, u32 xid)
|
||||
{
|
||||
if (netid && option_bool(OPT_LOG_OPTS))
|
||||
{
|
||||
char *s = daemon->namebuff;
|
||||
for (*s = 0; netid; netid = netid->next)
|
||||
{
|
||||
/* kill dupes. */
|
||||
struct dhcp_netid *n;
|
||||
|
||||
for (n = netid->next; n; n = n->next)
|
||||
if (strcmp(netid->net, n->net) == 0)
|
||||
break;
|
||||
|
||||
if (!n)
|
||||
{
|
||||
strncat (s, netid->net, (MAXDNAME-1) - strlen(s));
|
||||
if (netid->next)
|
||||
strncat (s, ", ", (MAXDNAME-1) - strlen(s));
|
||||
}
|
||||
}
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("%u tags: %s"), xid, s);
|
||||
}
|
||||
}
|
||||
|
||||
int match_bytes(struct dhcp_opt *o, unsigned char *p, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (o->len > len)
|
||||
return 0;
|
||||
|
||||
if (o->len == 0)
|
||||
return 1;
|
||||
|
||||
if (o->flags & DHOPT_HEX)
|
||||
{
|
||||
if (memcmp_masked(o->val, p, o->len, o->u.wildcard_mask))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
for (i = 0; i <= (len - o->len); )
|
||||
{
|
||||
if (memcmp(o->val, p + i, o->len) == 0)
|
||||
return 1;
|
||||
|
||||
if (o->flags & DHOPT_STRING)
|
||||
i++;
|
||||
else
|
||||
i += o->len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type)
|
||||
{
|
||||
struct hwaddr_config *conf_addr;
|
||||
|
||||
for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
|
||||
if (conf_addr->wildcard_mask == 0 &&
|
||||
conf_addr->hwaddr_len == len &&
|
||||
(conf_addr->hwaddr_type == type || conf_addr->hwaddr_type == 0) &&
|
||||
memcmp(conf_addr->hwaddr, hwaddr, len) == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_config_in_context(struct dhcp_context *context, struct dhcp_config *config)
|
||||
{
|
||||
if (!context) /* called via find_config() from lease_update_from_configs() */
|
||||
return 1;
|
||||
|
||||
if (!(config->flags & (CONFIG_ADDR | CONFIG_ADDR6)))
|
||||
return 1;
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if ((context->flags & CONTEXT_V6) && (config->flags & CONFIG_WILDCARD))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
for (; context; context = context->current)
|
||||
#ifdef HAVE_DHCP6
|
||||
if (context->flags & CONTEXT_V6)
|
||||
{
|
||||
if ((config->flags & CONFIG_ADDR6) && is_same_net6(&config->addr6, &context->start6, context->prefix))
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if ((config->flags & CONFIG_ADDR) && is_same_net(config->addr, context->start, context->netmask))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||
struct dhcp_context *context,
|
||||
unsigned char *clid, int clid_len,
|
||||
unsigned char *hwaddr, int hw_len,
|
||||
int hw_type, char *hostname)
|
||||
{
|
||||
int count, new;
|
||||
struct dhcp_config *config, *candidate;
|
||||
struct hwaddr_config *conf_addr;
|
||||
|
||||
if (clid)
|
||||
for (config = configs; config; config = config->next)
|
||||
if (config->flags & CONFIG_CLID)
|
||||
{
|
||||
if (config->clid_len == clid_len &&
|
||||
memcmp(config->clid, clid, clid_len) == 0 &&
|
||||
is_config_in_context(context, config))
|
||||
return config;
|
||||
|
||||
/* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
|
||||
cope with that here. This is IPv4 only. context==NULL implies IPv4,
|
||||
see lease_update_from_configs() */
|
||||
if ((!context || !(context->flags & CONTEXT_V6)) && *clid == 0 && config->clid_len == clid_len-1 &&
|
||||
memcmp(config->clid, clid+1, clid_len-1) == 0 &&
|
||||
is_config_in_context(context, config))
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
if (hwaddr)
|
||||
for (config = configs; config; config = config->next)
|
||||
if (config_has_mac(config, hwaddr, hw_len, hw_type) &&
|
||||
is_config_in_context(context, config))
|
||||
return config;
|
||||
|
||||
if (hostname && context)
|
||||
for (config = configs; config; config = config->next)
|
||||
if ((config->flags & CONFIG_NAME) &&
|
||||
hostname_isequal(config->hostname, hostname) &&
|
||||
is_config_in_context(context, config))
|
||||
return config;
|
||||
|
||||
|
||||
if (!hwaddr)
|
||||
return NULL;
|
||||
|
||||
/* use match with fewest wildcard octets */
|
||||
for (candidate = NULL, count = 0, config = configs; config; config = config->next)
|
||||
if (is_config_in_context(context, config))
|
||||
for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
|
||||
if (conf_addr->wildcard_mask != 0 &&
|
||||
conf_addr->hwaddr_len == hw_len &&
|
||||
(conf_addr->hwaddr_type == hw_type || conf_addr->hwaddr_type == 0) &&
|
||||
(new = memcmp_masked(conf_addr->hwaddr, hwaddr, hw_len, conf_addr->wildcard_mask)) > count)
|
||||
{
|
||||
count = new;
|
||||
candidate = config;
|
||||
}
|
||||
|
||||
return candidate;
|
||||
}
|
||||
|
||||
void dhcp_update_configs(struct dhcp_config *configs)
|
||||
{
|
||||
/* Some people like to keep all static IP addresses in /etc/hosts.
|
||||
This goes through /etc/hosts and sets static addresses for any DHCP config
|
||||
records which don't have an address and whose name matches.
|
||||
We take care to maintain the invariant that any IP address can appear
|
||||
in at most one dhcp-host. Since /etc/hosts can be re-read by SIGHUP,
|
||||
restore the status-quo ante first. */
|
||||
|
||||
struct dhcp_config *config, *conf_tmp;
|
||||
struct crec *crec;
|
||||
int prot = AF_INET;
|
||||
|
||||
for (config = configs; config; config = config->next)
|
||||
if (config->flags & CONFIG_ADDR_HOSTS)
|
||||
config->flags &= ~(CONFIG_ADDR | CONFIG_ADDR6 | CONFIG_ADDR_HOSTS);
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
again:
|
||||
#endif
|
||||
|
||||
if (daemon->port != 0)
|
||||
for (config = configs; config; config = config->next)
|
||||
{
|
||||
int conflags = CONFIG_ADDR;
|
||||
int cacheflags = F_IPV4;
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (prot == AF_INET6)
|
||||
{
|
||||
conflags = CONFIG_ADDR6;
|
||||
cacheflags = F_IPV6;
|
||||
}
|
||||
#endif
|
||||
if (!(config->flags & conflags) &&
|
||||
(config->flags & CONFIG_NAME) &&
|
||||
(crec = cache_find_by_name(NULL, config->hostname, 0, cacheflags)) &&
|
||||
(crec->flags & F_HOSTS))
|
||||
{
|
||||
if (cache_find_by_name(crec, config->hostname, 0, cacheflags))
|
||||
{
|
||||
/* use primary (first) address */
|
||||
while (crec && !(crec->flags & F_REVERSE))
|
||||
crec = cache_find_by_name(crec, config->hostname, 0, cacheflags);
|
||||
if (!crec)
|
||||
continue; /* should be never */
|
||||
inet_ntop(prot, &crec->addr.addr, daemon->addrbuff, ADDRSTRLEN);
|
||||
my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"),
|
||||
config->hostname, daemon->addrbuff);
|
||||
}
|
||||
|
||||
if (prot == AF_INET &&
|
||||
(!(conf_tmp = config_find_by_address(configs, crec->addr.addr.addr.addr4)) || conf_tmp == config))
|
||||
{
|
||||
config->addr = crec->addr.addr.addr.addr4;
|
||||
config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS;
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (prot == AF_INET6 &&
|
||||
(!(conf_tmp = config_find_by_address6(configs, &crec->addr.addr.addr.addr6, 128, 0)) || conf_tmp == config))
|
||||
{
|
||||
memcpy(&config->addr6, &crec->addr.addr.addr.addr6, IN6ADDRSZ);
|
||||
config->flags |= CONFIG_ADDR6 | CONFIG_ADDR_HOSTS;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
inet_ntop(prot, &crec->addr.addr, daemon->addrbuff, ADDRSTRLEN);
|
||||
my_syslog(MS_DHCP | LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"),
|
||||
daemon->addrbuff, config->hostname);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (prot == AF_INET)
|
||||
{
|
||||
prot = AF_INET6;
|
||||
goto again;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
char *whichdevice(void)
|
||||
{
|
||||
/* If we are doing DHCP on exactly one interface, and running linux, do SO_BINDTODEVICE
|
||||
to that device. This is for the use case of (eg) OpenStack, which runs a new
|
||||
dnsmasq instance for each VLAN interface it creates. Without the BINDTODEVICE,
|
||||
individual processes don't always see the packets they should.
|
||||
SO_BINDTODEVICE is only available Linux.
|
||||
|
||||
Note that if wildcards are used in --interface, or --interface is not used at all,
|
||||
or a configured interface doesn't yet exist, then more interfaces may arrive later,
|
||||
so we can't safely assert there is only one interface and proceed.
|
||||
*/
|
||||
|
||||
struct irec *iface, *found;
|
||||
struct iname *if_tmp;
|
||||
|
||||
if (!daemon->if_names)
|
||||
return NULL;
|
||||
|
||||
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
|
||||
if (if_tmp->name && (!if_tmp->used || strchr(if_tmp->name, '*')))
|
||||
return NULL;
|
||||
|
||||
for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next)
|
||||
if (iface->dhcp_ok)
|
||||
{
|
||||
if (!found)
|
||||
found = iface;
|
||||
else if (strcmp(found->name, iface->name) != 0)
|
||||
return NULL; /* more than one. */
|
||||
}
|
||||
|
||||
if (found)
|
||||
return found->name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bindtodevice(char *device, int fd)
|
||||
{
|
||||
size_t len = strlen(device)+1;
|
||||
if (len > IFNAMSIZ)
|
||||
len = IFNAMSIZ;
|
||||
/* only allowed by root. */
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, device, len) == -1 &&
|
||||
errno != EPERM)
|
||||
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct opttab_t {
|
||||
char *name;
|
||||
u16 val, size;
|
||||
} opttab[] = {
|
||||
{ "netmask", 1, OT_ADDR_LIST },
|
||||
{ "time-offset", 2, 4 },
|
||||
{ "router", 3, OT_ADDR_LIST },
|
||||
{ "dns-server", 6, OT_ADDR_LIST },
|
||||
{ "log-server", 7, OT_ADDR_LIST },
|
||||
{ "lpr-server", 9, OT_ADDR_LIST },
|
||||
{ "hostname", 12, OT_INTERNAL | OT_NAME },
|
||||
{ "boot-file-size", 13, 2 | OT_DEC },
|
||||
{ "domain-name", 15, OT_NAME },
|
||||
{ "swap-server", 16, OT_ADDR_LIST },
|
||||
{ "root-path", 17, OT_NAME },
|
||||
{ "extension-path", 18, OT_NAME },
|
||||
{ "ip-forward-enable", 19, 1 },
|
||||
{ "non-local-source-routing", 20, 1 },
|
||||
{ "policy-filter", 21, OT_ADDR_LIST },
|
||||
{ "max-datagram-reassembly", 22, 2 | OT_DEC },
|
||||
{ "default-ttl", 23, 1 | OT_DEC },
|
||||
{ "mtu", 26, 2 | OT_DEC },
|
||||
{ "all-subnets-local", 27, 1 },
|
||||
{ "broadcast", 28, OT_INTERNAL | OT_ADDR_LIST },
|
||||
{ "router-discovery", 31, 1 },
|
||||
{ "router-solicitation", 32, OT_ADDR_LIST },
|
||||
{ "static-route", 33, OT_ADDR_LIST },
|
||||
{ "trailer-encapsulation", 34, 1 },
|
||||
{ "arp-timeout", 35, 4 | OT_DEC },
|
||||
{ "ethernet-encap", 36, 1 },
|
||||
{ "tcp-ttl", 37, 1 },
|
||||
{ "tcp-keepalive", 38, 4 | OT_DEC },
|
||||
{ "nis-domain", 40, OT_NAME },
|
||||
{ "nis-server", 41, OT_ADDR_LIST },
|
||||
{ "ntp-server", 42, OT_ADDR_LIST },
|
||||
{ "vendor-encap", 43, OT_INTERNAL },
|
||||
{ "netbios-ns", 44, OT_ADDR_LIST },
|
||||
{ "netbios-dd", 45, OT_ADDR_LIST },
|
||||
{ "netbios-nodetype", 46, 1 },
|
||||
{ "netbios-scope", 47, 0 },
|
||||
{ "x-windows-fs", 48, OT_ADDR_LIST },
|
||||
{ "x-windows-dm", 49, OT_ADDR_LIST },
|
||||
{ "requested-address", 50, OT_INTERNAL | OT_ADDR_LIST },
|
||||
{ "lease-time", 51, OT_INTERNAL | OT_TIME },
|
||||
{ "option-overload", 52, OT_INTERNAL },
|
||||
{ "message-type", 53, OT_INTERNAL | OT_DEC },
|
||||
{ "server-identifier", 54, OT_INTERNAL | OT_ADDR_LIST },
|
||||
{ "parameter-request", 55, OT_INTERNAL },
|
||||
{ "message", 56, OT_INTERNAL },
|
||||
{ "max-message-size", 57, OT_INTERNAL },
|
||||
{ "T1", 58, OT_TIME},
|
||||
{ "T2", 59, OT_TIME},
|
||||
{ "vendor-class", 60, 0 },
|
||||
{ "client-id", 61, OT_INTERNAL },
|
||||
{ "nis+-domain", 64, OT_NAME },
|
||||
{ "nis+-server", 65, OT_ADDR_LIST },
|
||||
{ "tftp-server", 66, OT_NAME },
|
||||
{ "bootfile-name", 67, OT_NAME },
|
||||
{ "mobile-ip-home", 68, OT_ADDR_LIST },
|
||||
{ "smtp-server", 69, OT_ADDR_LIST },
|
||||
{ "pop3-server", 70, OT_ADDR_LIST },
|
||||
{ "nntp-server", 71, OT_ADDR_LIST },
|
||||
{ "irc-server", 74, OT_ADDR_LIST },
|
||||
{ "user-class", 77, 0 },
|
||||
{ "rapid-commit", 80, 0 },
|
||||
{ "FQDN", 81, OT_INTERNAL },
|
||||
{ "agent-id", 82, OT_INTERNAL },
|
||||
{ "client-arch", 93, 2 | OT_DEC },
|
||||
{ "client-interface-id", 94, 0 },
|
||||
{ "client-machine-id", 97, 0 },
|
||||
{ "subnet-select", 118, OT_INTERNAL },
|
||||
{ "domain-search", 119, OT_RFC1035_NAME },
|
||||
{ "sip-server", 120, 0 },
|
||||
{ "classless-static-route", 121, 0 },
|
||||
{ "vendor-id-encap", 125, 0 },
|
||||
{ "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
static const struct opttab_t opttab6[] = {
|
||||
{ "client-id", 1, OT_INTERNAL },
|
||||
{ "server-id", 2, OT_INTERNAL },
|
||||
{ "ia-na", 3, OT_INTERNAL },
|
||||
{ "ia-ta", 4, OT_INTERNAL },
|
||||
{ "iaaddr", 5, OT_INTERNAL },
|
||||
{ "oro", 6, OT_INTERNAL },
|
||||
{ "preference", 7, OT_INTERNAL | OT_DEC },
|
||||
{ "unicast", 12, OT_INTERNAL },
|
||||
{ "status", 13, OT_INTERNAL },
|
||||
{ "rapid-commit", 14, OT_INTERNAL },
|
||||
{ "user-class", 15, OT_INTERNAL | OT_CSTRING },
|
||||
{ "vendor-class", 16, OT_INTERNAL | OT_CSTRING },
|
||||
{ "vendor-opts", 17, OT_INTERNAL },
|
||||
{ "sip-server-domain", 21, OT_RFC1035_NAME },
|
||||
{ "sip-server", 22, OT_ADDR_LIST },
|
||||
{ "dns-server", 23, OT_ADDR_LIST },
|
||||
{ "domain-search", 24, OT_RFC1035_NAME },
|
||||
{ "nis-server", 27, OT_ADDR_LIST },
|
||||
{ "nis+-server", 28, OT_ADDR_LIST },
|
||||
{ "nis-domain", 29, OT_RFC1035_NAME },
|
||||
{ "nis+-domain", 30, OT_RFC1035_NAME },
|
||||
{ "sntp-server", 31, OT_ADDR_LIST },
|
||||
{ "information-refresh-time", 32, OT_TIME },
|
||||
{ "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME },
|
||||
{ "ntp-server", 56, 0 },
|
||||
{ "bootfile-url", 59, OT_NAME },
|
||||
{ "bootfile-param", 60, OT_CSTRING },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void display_opts(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf(_("Known DHCP options:\n"));
|
||||
|
||||
for (i = 0; opttab[i].name; i++)
|
||||
if (!(opttab[i].size & OT_INTERNAL))
|
||||
printf("%3d %s\n", opttab[i].val, opttab[i].name);
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
void display_opts6(void)
|
||||
{
|
||||
int i;
|
||||
printf(_("Known DHCPv6 options:\n"));
|
||||
|
||||
for (i = 0; opttab6[i].name; i++)
|
||||
if (!(opttab6[i].size & OT_INTERNAL))
|
||||
printf("%3d %s\n", opttab6[i].val, opttab6[i].name);
|
||||
}
|
||||
#endif
|
||||
|
||||
int lookup_dhcp_opt(int prot, char *name)
|
||||
{
|
||||
const struct opttab_t *t;
|
||||
int i;
|
||||
|
||||
(void)prot;
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (prot == AF_INET6)
|
||||
t = opttab6;
|
||||
else
|
||||
#endif
|
||||
t = opttab;
|
||||
|
||||
for (i = 0; t[i].name; i++)
|
||||
if (strcasecmp(t[i].name, name) == 0)
|
||||
return t[i].val;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lookup_dhcp_len(int prot, int val)
|
||||
{
|
||||
const struct opttab_t *t;
|
||||
int i;
|
||||
|
||||
(void)prot;
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (prot == AF_INET6)
|
||||
t = opttab6;
|
||||
else
|
||||
#endif
|
||||
t = opttab;
|
||||
|
||||
for (i = 0; t[i].name; i++)
|
||||
if (val == t[i].val)
|
||||
return t[i].size & ~OT_DEC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len, char *buf, int buf_len)
|
||||
{
|
||||
int o, i, j, nodecode = 0;
|
||||
const struct opttab_t *ot = opttab;
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (prot == AF_INET6)
|
||||
ot = opttab6;
|
||||
#endif
|
||||
|
||||
for (o = 0; ot[o].name; o++)
|
||||
if (ot[o].val == opt)
|
||||
{
|
||||
if (buf)
|
||||
{
|
||||
memset(buf, 0, buf_len);
|
||||
|
||||
if (ot[o].size & OT_ADDR_LIST)
|
||||
{
|
||||
struct all_addr addr;
|
||||
int addr_len = INADDRSZ;
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (prot == AF_INET6)
|
||||
addr_len = IN6ADDRSZ;
|
||||
#endif
|
||||
for (buf[0]= 0, i = 0; i <= opt_len - addr_len; i += addr_len)
|
||||
{
|
||||
if (i != 0)
|
||||
strncat(buf, ", ", buf_len - strlen(buf));
|
||||
/* align */
|
||||
memcpy(&addr, &val[i], addr_len);
|
||||
inet_ntop(prot, &val[i], daemon->addrbuff, ADDRSTRLEN);
|
||||
strncat(buf, daemon->addrbuff, buf_len - strlen(buf));
|
||||
}
|
||||
}
|
||||
else if (ot[o].size & OT_NAME)
|
||||
for (i = 0, j = 0; i < opt_len && j < buf_len ; i++)
|
||||
{
|
||||
char c = val[i];
|
||||
if (isprint((int)c))
|
||||
buf[j++] = c;
|
||||
}
|
||||
#ifdef HAVE_DHCP6
|
||||
/* We don't handle compressed rfc1035 names, so no good in IPv4 land */
|
||||
else if ((ot[o].size & OT_RFC1035_NAME) && prot == AF_INET6)
|
||||
{
|
||||
i = 0, j = 0;
|
||||
while (i < opt_len && val[i] != 0)
|
||||
{
|
||||
int k, l = i + val[i] + 1;
|
||||
for (k = i + 1; k < opt_len && k < l && j < buf_len ; k++)
|
||||
{
|
||||
char c = val[k];
|
||||
if (isprint((int)c))
|
||||
buf[j++] = c;
|
||||
}
|
||||
i = l;
|
||||
if (val[i] != 0 && j < buf_len)
|
||||
buf[j++] = '.';
|
||||
}
|
||||
}
|
||||
else if ((ot[o].size & OT_CSTRING))
|
||||
{
|
||||
int k, len;
|
||||
unsigned char *p;
|
||||
|
||||
i = 0, j = 0;
|
||||
while (1)
|
||||
{
|
||||
p = &val[i];
|
||||
GETSHORT(len, p);
|
||||
for (k = 0; k < len && j < buf_len; k++)
|
||||
{
|
||||
char c = *p++;
|
||||
if (isprint((int)c))
|
||||
buf[j++] = c;
|
||||
}
|
||||
i += len +2;
|
||||
if (i >= opt_len)
|
||||
break;
|
||||
|
||||
if (j < buf_len)
|
||||
buf[j++] = ',';
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if ((ot[o].size & (OT_DEC | OT_TIME)) && opt_len != 0)
|
||||
{
|
||||
unsigned int dec = 0;
|
||||
|
||||
for (i = 0; i < opt_len; i++)
|
||||
dec = (dec << 8) | val[i];
|
||||
|
||||
if (ot[o].size & OT_TIME)
|
||||
prettyprint_time(buf, dec);
|
||||
else
|
||||
sprintf(buf, "%u", dec);
|
||||
}
|
||||
else
|
||||
nodecode = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (opt_len != 0 && buf && (!ot[o].name || nodecode))
|
||||
{
|
||||
int trunc = 0;
|
||||
if (opt_len > 14)
|
||||
{
|
||||
trunc = 1;
|
||||
opt_len = 14;
|
||||
}
|
||||
print_mac(buf, val, opt_len);
|
||||
if (trunc)
|
||||
strncat(buf, "...", buf_len - strlen(buf));
|
||||
|
||||
|
||||
}
|
||||
|
||||
return ot[o].name ? ot[o].name : "";
|
||||
|
||||
}
|
||||
|
||||
void log_context(int family, struct dhcp_context *context)
|
||||
{
|
||||
/* Cannot use dhcp_buff* for RA contexts */
|
||||
|
||||
void *start = &context->start;
|
||||
void *end = &context->end;
|
||||
char *template = "", *p = daemon->namebuff;
|
||||
|
||||
*p = 0;
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (family == AF_INET6)
|
||||
{
|
||||
struct in6_addr subnet = context->start6;
|
||||
if (!(context->flags & CONTEXT_TEMPLATE))
|
||||
setaddr6part(&subnet, 0);
|
||||
inet_ntop(AF_INET6, &subnet, daemon->addrbuff, ADDRSTRLEN);
|
||||
start = &context->start6;
|
||||
end = &context->end6;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (family != AF_INET && (context->flags & CONTEXT_DEPRECATE))
|
||||
strcpy(daemon->namebuff, _(", prefix deprecated"));
|
||||
else
|
||||
{
|
||||
p += sprintf(p, _(", lease time "));
|
||||
prettyprint_time(p, context->lease_time);
|
||||
p += strlen(p);
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (context->flags & CONTEXT_CONSTRUCTED)
|
||||
{
|
||||
char ifrn_name[IFNAMSIZ];
|
||||
|
||||
template = p;
|
||||
p += sprintf(p, ", ");
|
||||
|
||||
if (indextoname(daemon->icmp6fd, context->if_index, ifrn_name))
|
||||
sprintf(p, "%s for %s", (context->flags & CONTEXT_OLD) ? "old prefix" : "constructed", ifrn_name);
|
||||
}
|
||||
else if (context->flags & CONTEXT_TEMPLATE && !(context->flags & CONTEXT_RA_STATELESS))
|
||||
{
|
||||
template = p;
|
||||
p += sprintf(p, ", ");
|
||||
|
||||
sprintf(p, "template for %s", context->template_interface);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(context->flags & CONTEXT_OLD) &&
|
||||
((context->flags & CONTEXT_DHCP) || family == AF_INET))
|
||||
{
|
||||
#ifdef HAVE_DHCP6
|
||||
if (context->flags & CONTEXT_RA_STATELESS)
|
||||
{
|
||||
if (context->flags & CONTEXT_TEMPLATE)
|
||||
strncpy(daemon->dhcp_buff, context->template_interface, DHCP_BUFF_SZ);
|
||||
else
|
||||
strcpy(daemon->dhcp_buff, daemon->addrbuff);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
inet_ntop(family, start, daemon->dhcp_buff, DHCP_BUFF_SZ);
|
||||
inet_ntop(family, end, daemon->dhcp_buff3, DHCP_BUFF_SZ);
|
||||
my_syslog(MS_DHCP | LOG_INFO,
|
||||
(context->flags & CONTEXT_RA_STATELESS) ?
|
||||
_("%s stateless on %s%.0s%.0s%s") :
|
||||
(context->flags & CONTEXT_STATIC) ?
|
||||
_("%s, static leases only on %.0s%s%s%.0s") :
|
||||
(context->flags & CONTEXT_PROXY) ?
|
||||
_("%s, proxy on subnet %.0s%s%.0s%.0s") :
|
||||
_("%s, IP range %s -- %s%s%.0s"),
|
||||
(family != AF_INET) ? "DHCPv6" : "DHCP",
|
||||
daemon->dhcp_buff, daemon->dhcp_buff3, daemon->namebuff, template);
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (context->flags & CONTEXT_TEMPLATE)
|
||||
{
|
||||
strcpy(daemon->addrbuff, context->template_interface);
|
||||
template = "";
|
||||
}
|
||||
|
||||
if ((context->flags & CONTEXT_RA_NAME) && !(context->flags & CONTEXT_OLD))
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCPv4-derived IPv6 names on %s%s"), daemon->addrbuff, template);
|
||||
|
||||
if ((context->flags & CONTEXT_RA) || (option_bool(OPT_RA) && (context->flags & CONTEXT_DHCP) && family == AF_INET6))
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("router advertisement on %s%s"), daemon->addrbuff, template);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void log_relay(int family, struct dhcp_relay *relay)
|
||||
{
|
||||
inet_ntop(family, &relay->local, daemon->addrbuff, ADDRSTRLEN);
|
||||
inet_ntop(family, &relay->server, daemon->namebuff, ADDRSTRLEN);
|
||||
|
||||
if (relay->interface)
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s to %s via %s"), daemon->addrbuff, daemon->namebuff, relay->interface);
|
||||
else
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s to %s"), daemon->addrbuff, daemon->namebuff);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -13,6 +13,15 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#define DHCP_SERVER_PORT 67
|
||||
#define DHCP_CLIENT_PORT 68
|
||||
#define DHCP_SERVER_ALTPORT 1067
|
||||
#define DHCP_CLIENT_ALTPORT 1068
|
||||
#define PXE_PORT 4011
|
||||
|
||||
/* These each hold a DHCP option max size 255
|
||||
and get a terminating zero added */
|
||||
#define DHCP_BUFF_SZ 256
|
||||
|
||||
#define BOOTREQUEST 1
|
||||
#define BOOTREPLY 2
|
||||
@@ -45,6 +54,7 @@
|
||||
#define OPTION_SNAME 66
|
||||
#define OPTION_FILENAME 67
|
||||
#define OPTION_USER_CLASS 77
|
||||
#define OPTION_RAPID_COMMIT 80
|
||||
#define OPTION_CLIENT_FQDN 81
|
||||
#define OPTION_AGENT_ID 82
|
||||
#define OPTION_ARCH 93
|
||||
807
src/dhcp.c
807
src/dhcp.c
File diff suppressed because it is too large
Load Diff
75
src/dhcp6-protocol.h
Normal file
75
src/dhcp6-protocol.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or
|
||||
(at your option) version 3 dated 29 June, 2007.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define DHCPV6_SERVER_PORT 547
|
||||
#define DHCPV6_CLIENT_PORT 546
|
||||
|
||||
#define ALL_SERVERS "FF05::1:3"
|
||||
#define ALL_RELAY_AGENTS_AND_SERVERS "FF02::1:2"
|
||||
|
||||
#define DHCP6SOLICIT 1
|
||||
#define DHCP6ADVERTISE 2
|
||||
#define DHCP6REQUEST 3
|
||||
#define DHCP6CONFIRM 4
|
||||
#define DHCP6RENEW 5
|
||||
#define DHCP6REBIND 6
|
||||
#define DHCP6REPLY 7
|
||||
#define DHCP6RELEASE 8
|
||||
#define DHCP6DECLINE 9
|
||||
#define DHCP6RECONFIGURE 10
|
||||
#define DHCP6IREQ 11
|
||||
#define DHCP6RELAYFORW 12
|
||||
#define DHCP6RELAYREPL 13
|
||||
|
||||
#define OPTION6_CLIENT_ID 1
|
||||
#define OPTION6_SERVER_ID 2
|
||||
#define OPTION6_IA_NA 3
|
||||
#define OPTION6_IA_TA 4
|
||||
#define OPTION6_IAADDR 5
|
||||
#define OPTION6_ORO 6
|
||||
#define OPTION6_PREFERENCE 7
|
||||
#define OPTION6_ELAPSED_TIME 8
|
||||
#define OPTION6_RELAY_MSG 9
|
||||
#define OPTION6_AUTH 11
|
||||
#define OPTION6_UNICAST 12
|
||||
#define OPTION6_STATUS_CODE 13
|
||||
#define OPTION6_RAPID_COMMIT 14
|
||||
#define OPTION6_USER_CLASS 15
|
||||
#define OPTION6_VENDOR_CLASS 16
|
||||
#define OPTION6_VENDOR_OPTS 17
|
||||
#define OPTION6_INTERFACE_ID 18
|
||||
#define OPTION6_RECONFIGURE_MSG 19
|
||||
#define OPTION6_RECONF_ACCEPT 20
|
||||
#define OPTION6_DNS_SERVER 23
|
||||
#define OPTION6_DOMAIN_SEARCH 24
|
||||
#define OPTION6_REFRESH_TIME 32
|
||||
#define OPTION6_REMOTE_ID 37
|
||||
#define OPTION6_SUBSCRIBER_ID 38
|
||||
#define OPTION6_FQDN 39
|
||||
#define OPTION6_CLIENT_MAC 79
|
||||
|
||||
/* replace this with the real number when allocated.
|
||||
defining this also enables the relevant code. */
|
||||
/* #define OPTION6_PREFIX_CLASS 99 */
|
||||
|
||||
|
||||
#define DHCP6SUCCESS 0
|
||||
#define DHCP6UNSPEC 1
|
||||
#define DHCP6NOADDRS 2
|
||||
#define DHCP6NOBINDING 3
|
||||
#define DHCP6NOTONLINK 4
|
||||
#define DHCP6USEMULTI 5
|
||||
|
||||
799
src/dhcp6.c
Normal file
799
src/dhcp6.c
Normal file
@@ -0,0 +1,799 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or
|
||||
(at your option) version 3 dated 29 June, 2007.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
struct iface_param {
|
||||
struct dhcp_context *current;
|
||||
struct dhcp_relay *relay;
|
||||
struct in6_addr fallback, relay_local, ll_addr, ula_addr;
|
||||
int ind, addr_match;
|
||||
};
|
||||
|
||||
|
||||
static int complete_context6(struct in6_addr *local, int prefix,
|
||||
int scope, int if_index, int flags,
|
||||
unsigned int preferred, unsigned int valid, void *vparam);
|
||||
static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, void *parm);
|
||||
|
||||
void dhcp6_init(void)
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr_in6 saddr;
|
||||
#if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
|
||||
int class = IPTOS_CLASS_CS6;
|
||||
#endif
|
||||
int oneopt = 1;
|
||||
|
||||
if ((fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1 ||
|
||||
#if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
|
||||
setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &class, sizeof(class)) == -1 ||
|
||||
#endif
|
||||
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &oneopt, sizeof(oneopt)) == -1 ||
|
||||
!fix_fd(fd) ||
|
||||
!set_ipv6pktinfo(fd))
|
||||
die (_("cannot create DHCPv6 socket: %s"), NULL, EC_BADNET);
|
||||
|
||||
/* When bind-interfaces is set, there might be more than one dnsmasq
|
||||
instance binding port 547. That's OK if they serve different networks.
|
||||
Need to set REUSEADDR|REUSEPORT to make this possible.
|
||||
Handle the case that REUSEPORT is defined, but the kernel doesn't
|
||||
support it. This handles the introduction of REUSEPORT on Linux. */
|
||||
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
#ifdef SO_REUSEPORT
|
||||
if ((rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt))) == -1 &&
|
||||
errno == ENOPROTOOPT)
|
||||
rc = 0;
|
||||
#endif
|
||||
|
||||
if (rc != -1)
|
||||
rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
|
||||
|
||||
if (rc == -1)
|
||||
die(_("failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"), NULL, EC_BADNET);
|
||||
}
|
||||
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
saddr.sin6_len = sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
saddr.sin6_family = AF_INET6;
|
||||
saddr.sin6_addr = in6addr_any;
|
||||
saddr.sin6_port = htons(DHCPV6_SERVER_PORT);
|
||||
|
||||
if (bind(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in6)))
|
||||
die(_("failed to bind DHCPv6 server socket: %s"), NULL, EC_BADNET);
|
||||
|
||||
daemon->dhcp6fd = fd;
|
||||
}
|
||||
|
||||
void dhcp6_packet(time_t now)
|
||||
{
|
||||
struct dhcp_context *context;
|
||||
struct dhcp_relay *relay;
|
||||
struct iface_param parm;
|
||||
struct cmsghdr *cmptr;
|
||||
struct msghdr msg;
|
||||
int if_index = 0;
|
||||
union {
|
||||
struct cmsghdr align; /* this ensures alignment */
|
||||
char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
|
||||
} control_u;
|
||||
struct sockaddr_in6 from;
|
||||
ssize_t sz;
|
||||
struct ifreq ifr;
|
||||
struct iname *tmp;
|
||||
unsigned short port;
|
||||
struct in6_addr dst_addr;
|
||||
|
||||
memset(&dst_addr, 0, sizeof(dst_addr));
|
||||
|
||||
msg.msg_control = control_u.control6;
|
||||
msg.msg_controllen = sizeof(control_u);
|
||||
msg.msg_flags = 0;
|
||||
msg.msg_name = &from;
|
||||
msg.msg_namelen = sizeof(from);
|
||||
msg.msg_iov = &daemon->dhcp_packet;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
if ((sz = recv_dhcp_packet(daemon->dhcp6fd, &msg)) == -1)
|
||||
return;
|
||||
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
|
||||
{
|
||||
union {
|
||||
unsigned char *c;
|
||||
struct in6_pktinfo *p;
|
||||
} p;
|
||||
p.c = CMSG_DATA(cmptr);
|
||||
|
||||
if_index = p.p->ipi6_ifindex;
|
||||
dst_addr = p.p->ipi6_addr;
|
||||
}
|
||||
|
||||
if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
|
||||
return;
|
||||
|
||||
if ((port = relay_reply6(&from, sz, ifr.ifr_name)) == 0)
|
||||
{
|
||||
struct dhcp_bridge *bridge, *alias;
|
||||
|
||||
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
|
||||
return;
|
||||
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
|
||||
return;
|
||||
|
||||
parm.current = NULL;
|
||||
parm.relay = NULL;
|
||||
memset(&parm.relay_local, 0, IN6ADDRSZ);
|
||||
parm.ind = if_index;
|
||||
parm.addr_match = 0;
|
||||
memset(&parm.fallback, 0, IN6ADDRSZ);
|
||||
memset(&parm.ll_addr, 0, IN6ADDRSZ);
|
||||
memset(&parm.ula_addr, 0, IN6ADDRSZ);
|
||||
|
||||
/* If the interface on which the DHCPv6 request was received is
|
||||
an alias of some other interface (as specified by the
|
||||
--bridge-interface option), change parm.ind so that we look
|
||||
for DHCPv6 contexts associated with the aliased interface
|
||||
instead of with the aliasing one. */
|
||||
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
|
||||
{
|
||||
for (alias = bridge->alias; alias; alias = alias->next)
|
||||
if (wildcard_matchn(alias->iface, ifr.ifr_name, IF_NAMESIZE))
|
||||
{
|
||||
parm.ind = if_nametoindex(bridge->iface);
|
||||
if (!parm.ind)
|
||||
{
|
||||
my_syslog(MS_DHCP | LOG_WARNING,
|
||||
_("unknown interface %s in bridge-interface"),
|
||||
bridge->iface);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (alias)
|
||||
break;
|
||||
}
|
||||
|
||||
for (context = daemon->dhcp6; context; context = context->next)
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&context->start6) && context->prefix == 0)
|
||||
{
|
||||
/* wildcard context for DHCP-stateless only */
|
||||
parm.current = context;
|
||||
context->current = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unlinked contexts are marked by context->current == context */
|
||||
context->current = context;
|
||||
memset(&context->local6, 0, IN6ADDRSZ);
|
||||
}
|
||||
|
||||
for (relay = daemon->relay6; relay; relay = relay->next)
|
||||
relay->current = relay;
|
||||
|
||||
if (!iface_enumerate(AF_INET6, &parm, complete_context6))
|
||||
return;
|
||||
|
||||
if (daemon->if_names || daemon->if_addrs)
|
||||
{
|
||||
|
||||
for (tmp = daemon->if_names; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
|
||||
break;
|
||||
|
||||
if (!tmp && !parm.addr_match)
|
||||
return;
|
||||
}
|
||||
|
||||
if (parm.relay)
|
||||
{
|
||||
/* Ignore requests sent to the ALL_SERVERS multicast address for relay when
|
||||
we're listening there for DHCPv6 server reasons. */
|
||||
struct in6_addr all_servers;
|
||||
|
||||
inet_pton(AF_INET6, ALL_SERVERS, &all_servers);
|
||||
|
||||
if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers))
|
||||
relay_upstream6(parm.relay, sz, &from.sin6_addr, from.sin6_scope_id, now);
|
||||
return;
|
||||
}
|
||||
|
||||
/* May have configured relay, but not DHCP server */
|
||||
if (!daemon->doing_dhcp6)
|
||||
return;
|
||||
|
||||
lease_prune(NULL, now); /* lose any expired leases */
|
||||
|
||||
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
|
||||
&parm.ll_addr, &parm.ula_addr, sz, &from.sin6_addr, now);
|
||||
|
||||
lease_update_file(now);
|
||||
lease_update_dns(0);
|
||||
}
|
||||
|
||||
/* The port in the source address of the original request should
|
||||
be correct, but at least once client sends from the server port,
|
||||
so we explicitly send to the client port to a client, and the
|
||||
server port to a relay. */
|
||||
if (port != 0)
|
||||
{
|
||||
from.sin6_port = htons(port);
|
||||
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
|
||||
save_counter(0), 0, (struct sockaddr *)&from,
|
||||
sizeof(from))));
|
||||
}
|
||||
}
|
||||
|
||||
void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsigned int *maclenp, unsigned int *mactypep, time_t now)
|
||||
{
|
||||
/* Receiving a packet from a host does not populate the neighbour
|
||||
cache, so we send a neighbour discovery request if we can't
|
||||
find the sender. Repeat a few times in case of packet loss. */
|
||||
|
||||
struct neigh_packet neigh;
|
||||
union mysockaddr addr;
|
||||
int i, maclen;
|
||||
|
||||
neigh.type = ND_NEIGHBOR_SOLICIT;
|
||||
neigh.code = 0;
|
||||
neigh.reserved = 0;
|
||||
neigh.target = *client;
|
||||
/* RFC4443 section-2.3: checksum has to be zero to be calculated */
|
||||
neigh.checksum = 0;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
addr.in6.sin6_family = AF_INET6;
|
||||
addr.in6.sin6_port = htons(IPPROTO_ICMPV6);
|
||||
addr.in6.sin6_addr = *client;
|
||||
addr.in6.sin6_scope_id = iface;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
if ((maclen = find_mac(&addr, mac, 0, now)) != 0)
|
||||
break;
|
||||
|
||||
sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, &addr.sa, sizeof(addr));
|
||||
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 100000000; /* 100ms */
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
*maclenp = maclen;
|
||||
*mactypep = ARPHRD_ETHER;
|
||||
}
|
||||
|
||||
static int complete_context6(struct in6_addr *local, int prefix,
|
||||
int scope, int if_index, int flags, unsigned int preferred,
|
||||
unsigned int valid, void *vparam)
|
||||
{
|
||||
struct dhcp_context *context;
|
||||
struct dhcp_relay *relay;
|
||||
struct iface_param *param = vparam;
|
||||
struct iname *tmp;
|
||||
|
||||
(void)scope; /* warning */
|
||||
|
||||
if (if_index == param->ind)
|
||||
{
|
||||
if (IN6_IS_ADDR_LINKLOCAL(local))
|
||||
param->ll_addr = *local;
|
||||
else if (IN6_IS_ADDR_ULA(local))
|
||||
param->ula_addr = *local;
|
||||
|
||||
if (!IN6_IS_ADDR_LOOPBACK(local) &&
|
||||
!IN6_IS_ADDR_LINKLOCAL(local) &&
|
||||
!IN6_IS_ADDR_MULTICAST(local))
|
||||
{
|
||||
/* if we have --listen-address config, see if the
|
||||
arrival interface has a matching address. */
|
||||
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
|
||||
if (tmp->addr.sa.sa_family == AF_INET6 &&
|
||||
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, local))
|
||||
param->addr_match = 1;
|
||||
|
||||
/* Determine a globally address on the arrival interface, even
|
||||
if we have no matching dhcp-context, because we're only
|
||||
allocating on remote subnets via relays. This
|
||||
is used as a default for the DNS server option. */
|
||||
param->fallback = *local;
|
||||
|
||||
for (context = daemon->dhcp6; context; context = context->next)
|
||||
{
|
||||
if ((context->flags & CONTEXT_DHCP) &&
|
||||
!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
|
||||
prefix <= context->prefix &&
|
||||
is_same_net6(local, &context->start6, context->prefix) &&
|
||||
is_same_net6(local, &context->end6, context->prefix))
|
||||
{
|
||||
|
||||
|
||||
/* link it onto the current chain if we've not seen it before */
|
||||
if (context->current == context)
|
||||
{
|
||||
struct dhcp_context *tmp, **up;
|
||||
|
||||
/* use interface values only for constructed contexts */
|
||||
if (!(context->flags & CONTEXT_CONSTRUCTED))
|
||||
preferred = valid = 0xffffffff;
|
||||
else if (flags & IFACE_DEPRECATED)
|
||||
preferred = 0;
|
||||
|
||||
if (context->flags & CONTEXT_DEPRECATE)
|
||||
preferred = 0;
|
||||
|
||||
/* order chain, longest preferred time first */
|
||||
for (up = ¶m->current, tmp = param->current; tmp; tmp = tmp->current)
|
||||
if (tmp->preferred <= preferred)
|
||||
break;
|
||||
else
|
||||
up = &tmp->current;
|
||||
|
||||
context->current = *up;
|
||||
*up = context;
|
||||
context->local6 = *local;
|
||||
context->preferred = preferred;
|
||||
context->valid = valid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (relay = daemon->relay6; relay; relay = relay->next)
|
||||
if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr.addr6) && relay->current == relay &&
|
||||
(IN6_IS_ADDR_UNSPECIFIED(¶m->relay_local) || IN6_ARE_ADDR_EQUAL(local, ¶m->relay_local)))
|
||||
{
|
||||
relay->current = param->relay;
|
||||
param->relay = relay;
|
||||
param->relay_local = *local;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct in6_addr *net, int prefix, u64 addr)
|
||||
{
|
||||
struct dhcp_config *config;
|
||||
|
||||
for (config = configs; config; config = config->next)
|
||||
if ((config->flags & CONFIG_ADDR6) &&
|
||||
is_same_net6(&config->addr6, net, prefix) &&
|
||||
(prefix == 128 || addr6part(&config->addr6) == addr))
|
||||
return config;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len, int temp_addr,
|
||||
int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans)
|
||||
{
|
||||
/* Find a free address: exclude anything in use and anything allocated to
|
||||
a particular hwaddr/clientid/hostname in our configuration.
|
||||
Try to return from contexts which match netids first.
|
||||
|
||||
Note that we assume the address prefix lengths are 64 or greater, so we can
|
||||
get by with 64 bit arithmetic.
|
||||
*/
|
||||
|
||||
u64 start, addr;
|
||||
struct dhcp_context *c, *d;
|
||||
int i, pass;
|
||||
u64 j;
|
||||
|
||||
/* hash hwaddr: use the SDBM hashing algorithm. This works
|
||||
for MAC addresses, let's see how it manages with client-ids!
|
||||
For temporary addresses, we generate a new random one each time. */
|
||||
if (temp_addr)
|
||||
j = rand64();
|
||||
else
|
||||
for (j = iaid, i = 0; i < clid_len; i++)
|
||||
j = clid[i] + (j << 6) + (j << 16) - j;
|
||||
|
||||
for (pass = 0; pass <= plain_range ? 1 : 0; pass++)
|
||||
for (c = context; c; c = c->current)
|
||||
if (c->flags & (CONTEXT_DEPRECATE | CONTEXT_STATIC | CONTEXT_RA_STATELESS | CONTEXT_USED))
|
||||
continue;
|
||||
else if (!match_netid(c->filter, netids, pass))
|
||||
continue;
|
||||
else
|
||||
{
|
||||
if (!temp_addr && option_bool(OPT_CONSEC_ADDR))
|
||||
/* seed is largest extant lease addr in this context */
|
||||
start = lease_find_max_addr6(c) + serial;
|
||||
else
|
||||
{
|
||||
u64 range = 1 + addr6part(&c->end6) - addr6part(&c->start6);
|
||||
u64 offset = j + c->addr_epoch;
|
||||
|
||||
/* don't divide by zero if range is whole 2^64 */
|
||||
if (range != 0)
|
||||
offset = offset % range;
|
||||
|
||||
start = addr6part(&c->start6) + offset;
|
||||
}
|
||||
|
||||
/* iterate until we find a free address. */
|
||||
addr = start;
|
||||
|
||||
do {
|
||||
/* eliminate addresses in use by the server. */
|
||||
for (d = context; d; d = d->current)
|
||||
if (addr == addr6part(&d->local6))
|
||||
break;
|
||||
|
||||
if (!d &&
|
||||
!lease6_find_by_addr(&c->start6, c->prefix, addr) &&
|
||||
!config_find_by_address6(daemon->dhcp_conf, &c->start6, c->prefix, addr))
|
||||
{
|
||||
*ans = c->start6;
|
||||
setaddr6part (ans, addr);
|
||||
return c;
|
||||
}
|
||||
|
||||
addr++;
|
||||
|
||||
if (addr == addr6part(&c->end6) + 1)
|
||||
addr = addr6part(&c->start6);
|
||||
|
||||
} while (addr != start);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* can dynamically allocate addr */
|
||||
struct dhcp_context *address6_available(struct dhcp_context *context,
|
||||
struct in6_addr *taddr,
|
||||
struct dhcp_netid *netids,
|
||||
int plain_range)
|
||||
{
|
||||
u64 start, end, addr = addr6part(taddr);
|
||||
struct dhcp_context *tmp;
|
||||
|
||||
for (tmp = context; tmp; tmp = tmp->current)
|
||||
{
|
||||
start = addr6part(&tmp->start6);
|
||||
end = addr6part(&tmp->end6);
|
||||
|
||||
if (!(tmp->flags & (CONTEXT_STATIC | CONTEXT_RA_STATELESS)) &&
|
||||
is_same_net6(&tmp->start6, taddr, tmp->prefix) &&
|
||||
is_same_net6(&tmp->end6, taddr, tmp->prefix) &&
|
||||
addr >= start &&
|
||||
addr <= end &&
|
||||
match_netid(tmp->filter, netids, plain_range))
|
||||
return tmp;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* address OK if configured */
|
||||
struct dhcp_context *address6_valid(struct dhcp_context *context,
|
||||
struct in6_addr *taddr,
|
||||
struct dhcp_netid *netids,
|
||||
int plain_range)
|
||||
{
|
||||
struct dhcp_context *tmp;
|
||||
|
||||
for (tmp = context; tmp; tmp = tmp->current)
|
||||
if (is_same_net6(&tmp->start6, taddr, tmp->prefix) &&
|
||||
match_netid(tmp->filter, netids, plain_range))
|
||||
return tmp;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr)
|
||||
{
|
||||
if (!config || !(config->flags & CONFIG_ADDR6))
|
||||
return 0;
|
||||
|
||||
if ((config->flags & CONFIG_WILDCARD) && context->prefix == 64)
|
||||
{
|
||||
*addr = context->start6;
|
||||
setaddr6part(addr, addr6part(&config->addr6));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (is_same_net6(&context->start6, &config->addr6, context->prefix))
|
||||
{
|
||||
*addr = config->addr6;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void make_duid(time_t now)
|
||||
{
|
||||
(void)now;
|
||||
|
||||
if (daemon->duid_config)
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
daemon->duid = p = safe_malloc(daemon->duid_config_len + 6);
|
||||
daemon->duid_len = daemon->duid_config_len + 6;
|
||||
PUTSHORT(2, p); /* DUID_EN */
|
||||
PUTLONG(daemon->duid_enterprise, p);
|
||||
memcpy(p, daemon->duid_config, daemon->duid_config_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
time_t newnow = 0;
|
||||
|
||||
/* If we have no persistent lease database, or a non-stable RTC, use DUID_LL (newnow == 0) */
|
||||
#ifndef HAVE_BROKEN_RTC
|
||||
/* rebase epoch to 1/1/2000 */
|
||||
if (!option_bool(OPT_LEASE_RO) || daemon->lease_change_command)
|
||||
newnow = now - 946684800;
|
||||
#endif
|
||||
|
||||
iface_enumerate(AF_LOCAL, &newnow, make_duid1);
|
||||
|
||||
if(!daemon->duid)
|
||||
die("Cannot create DHCPv6 server DUID: %s", NULL, EC_MISC);
|
||||
}
|
||||
}
|
||||
|
||||
static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, void *parm)
|
||||
{
|
||||
/* create DUID as specified in RFC3315. We use the MAC of the
|
||||
first interface we find that isn't loopback or P-to-P and
|
||||
has address-type < 256. Address types above 256 are things like
|
||||
tunnels which don't have usable MAC addresses. */
|
||||
|
||||
unsigned char *p;
|
||||
(void)index;
|
||||
(void)parm;
|
||||
time_t newnow = *((time_t *)parm);
|
||||
|
||||
if (type >= 256)
|
||||
return 1;
|
||||
|
||||
if (newnow == 0)
|
||||
{
|
||||
daemon->duid = p = safe_malloc(maclen + 4);
|
||||
daemon->duid_len = maclen + 4;
|
||||
PUTSHORT(3, p); /* DUID_LL */
|
||||
PUTSHORT(type, p); /* address type */
|
||||
}
|
||||
else
|
||||
{
|
||||
daemon->duid = p = safe_malloc(maclen + 8);
|
||||
daemon->duid_len = maclen + 8;
|
||||
PUTSHORT(1, p); /* DUID_LLT */
|
||||
PUTSHORT(type, p); /* address type */
|
||||
PUTLONG(*((time_t *)parm), p); /* time */
|
||||
}
|
||||
|
||||
memcpy(p, mac, maclen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct cparam {
|
||||
time_t now;
|
||||
int newone, newname;
|
||||
};
|
||||
|
||||
static int construct_worker(struct in6_addr *local, int prefix,
|
||||
int scope, int if_index, int flags,
|
||||
int preferred, int valid, void *vparam)
|
||||
{
|
||||
char ifrn_name[IFNAMSIZ];
|
||||
struct in6_addr start6, end6;
|
||||
struct dhcp_context *template, *context;
|
||||
|
||||
(void)scope;
|
||||
(void)flags;
|
||||
(void)valid;
|
||||
(void)preferred;
|
||||
|
||||
struct cparam *param = vparam;
|
||||
|
||||
if (IN6_IS_ADDR_LOOPBACK(local) ||
|
||||
IN6_IS_ADDR_LINKLOCAL(local) ||
|
||||
IN6_IS_ADDR_MULTICAST(local))
|
||||
return 1;
|
||||
|
||||
if (!(flags & IFACE_PERMANENT))
|
||||
return 1;
|
||||
|
||||
if (flags & IFACE_DEPRECATED)
|
||||
return 1;
|
||||
|
||||
if (!indextoname(daemon->icmp6fd, if_index, ifrn_name))
|
||||
return 0;
|
||||
|
||||
for (template = daemon->dhcp6; template; template = template->next)
|
||||
if (!(template->flags & (CONTEXT_TEMPLATE | CONTEXT_CONSTRUCTED)))
|
||||
{
|
||||
/* non-template entries, just fill in interface and local addresses */
|
||||
if (prefix <= template->prefix &&
|
||||
is_same_net6(local, &template->start6, template->prefix) &&
|
||||
is_same_net6(local, &template->end6, template->prefix))
|
||||
{
|
||||
/* First time found, do fast RA. */
|
||||
if (template->if_index != if_index || !IN6_ARE_ADDR_EQUAL(&template->local6, local))
|
||||
{
|
||||
ra_start_unsolicited(param->now, template);
|
||||
param->newone = 1;
|
||||
}
|
||||
|
||||
template->if_index = if_index;
|
||||
template->local6 = *local;
|
||||
}
|
||||
|
||||
}
|
||||
else if (wildcard_match(template->template_interface, ifrn_name) &&
|
||||
template->prefix >= prefix)
|
||||
{
|
||||
start6 = *local;
|
||||
setaddr6part(&start6, addr6part(&template->start6));
|
||||
end6 = *local;
|
||||
setaddr6part(&end6, addr6part(&template->end6));
|
||||
|
||||
for (context = daemon->dhcp6; context; context = context->next)
|
||||
if (!(context->flags & CONTEXT_TEMPLATE) &&
|
||||
IN6_ARE_ADDR_EQUAL(&start6, &context->start6) &&
|
||||
IN6_ARE_ADDR_EQUAL(&end6, &context->end6))
|
||||
{
|
||||
/* If there's an absolute address context covering this address
|
||||
then don't construct one as well. */
|
||||
if (!(context->flags & CONTEXT_CONSTRUCTED))
|
||||
break;
|
||||
|
||||
if (context->if_index == if_index)
|
||||
{
|
||||
int cflags = context->flags;
|
||||
context->flags &= ~(CONTEXT_GC | CONTEXT_OLD);
|
||||
if (cflags & CONTEXT_OLD)
|
||||
{
|
||||
/* address went, now it's back, and on the same interface */
|
||||
log_context(AF_INET6, context);
|
||||
/* fast RAs for a while */
|
||||
ra_start_unsolicited(param->now, context);
|
||||
param->newone = 1;
|
||||
/* Add address to name again */
|
||||
if (context->flags & CONTEXT_RA_NAME)
|
||||
param->newname = 1;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!context && (context = whine_malloc(sizeof (struct dhcp_context))))
|
||||
{
|
||||
*context = *template;
|
||||
context->start6 = start6;
|
||||
context->end6 = end6;
|
||||
context->flags &= ~CONTEXT_TEMPLATE;
|
||||
context->flags |= CONTEXT_CONSTRUCTED;
|
||||
context->if_index = if_index;
|
||||
context->local6 = *local;
|
||||
context->saved_valid = 0;
|
||||
|
||||
context->next = daemon->dhcp6;
|
||||
daemon->dhcp6 = context;
|
||||
|
||||
ra_start_unsolicited(param->now, context);
|
||||
/* we created a new one, need to call
|
||||
lease_update_file to get periodic functions called */
|
||||
param->newone = 1;
|
||||
|
||||
/* Will need to add new putative SLAAC addresses to existing leases */
|
||||
if (context->flags & CONTEXT_RA_NAME)
|
||||
param->newname = 1;
|
||||
|
||||
log_context(AF_INET6, context);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void dhcp_construct_contexts(time_t now)
|
||||
{
|
||||
struct dhcp_context *context, *tmp, **up;
|
||||
struct cparam param;
|
||||
param.newone = 0;
|
||||
param.newname = 0;
|
||||
param.now = now;
|
||||
|
||||
for (context = daemon->dhcp6; context; context = context->next)
|
||||
if (context->flags & CONTEXT_CONSTRUCTED)
|
||||
context->flags |= CONTEXT_GC;
|
||||
|
||||
iface_enumerate(AF_INET6, ¶m, construct_worker);
|
||||
|
||||
for (up = &daemon->dhcp6, context = daemon->dhcp6; context; context = tmp)
|
||||
{
|
||||
|
||||
tmp = context->next;
|
||||
|
||||
if (context->flags & CONTEXT_GC && !(context->flags & CONTEXT_OLD))
|
||||
{
|
||||
if ((context->flags & CONTEXT_RA) || option_bool(OPT_RA))
|
||||
{
|
||||
/* previously constructed context has gone. advertise it's demise */
|
||||
context->flags |= CONTEXT_OLD;
|
||||
context->address_lost_time = now;
|
||||
/* Apply same ceiling of configured lease time as in radv.c */
|
||||
if (context->saved_valid > context->lease_time)
|
||||
context->saved_valid = context->lease_time;
|
||||
/* maximum time is 2 hours, from RFC */
|
||||
if (context->saved_valid > 7200) /* 2 hours */
|
||||
context->saved_valid = 7200;
|
||||
ra_start_unsolicited(now, context);
|
||||
param.newone = 1; /* include deletion */
|
||||
|
||||
if (context->flags & CONTEXT_RA_NAME)
|
||||
param.newname = 1;
|
||||
|
||||
log_context(AF_INET6, context);
|
||||
|
||||
up = &context->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we were never doing RA for this, so free now */
|
||||
*up = context->next;
|
||||
free(context);
|
||||
}
|
||||
}
|
||||
else
|
||||
up = &context->next;
|
||||
}
|
||||
|
||||
if (param.newone)
|
||||
{
|
||||
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||
{
|
||||
if (param.newname)
|
||||
lease_update_slaac(now);
|
||||
lease_update_file(now);
|
||||
}
|
||||
else
|
||||
/* Not doing DHCP, so no lease system, manage alarms for ra only */
|
||||
send_alarm(periodic_ra(now), now);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -14,6 +14,11 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define NAMESERVER_PORT 53
|
||||
#define TFTP_PORT 69
|
||||
#define MIN_PORT 1024 /* first non-reserved port */
|
||||
#define MAX_PORT 65535u
|
||||
|
||||
#define IN6ADDRSZ 16
|
||||
#define INADDRSZ 4
|
||||
|
||||
@@ -33,24 +38,50 @@
|
||||
|
||||
#define C_IN 1 /* the arpa internet */
|
||||
#define C_CHAOS 3 /* for chaos net (MIT) */
|
||||
#define C_HESIOD 4 /* hesiod */
|
||||
#define C_ANY 255 /* wildcard match */
|
||||
|
||||
#define T_A 1
|
||||
#define T_NS 2
|
||||
#define T_NS 2
|
||||
#define T_MD 3
|
||||
#define T_MF 4
|
||||
#define T_CNAME 5
|
||||
#define T_SOA 6
|
||||
#define T_MB 7
|
||||
#define T_MG 8
|
||||
#define T_MR 9
|
||||
#define T_PTR 12
|
||||
#define T_MINFO 14
|
||||
#define T_MX 15
|
||||
#define T_TXT 16
|
||||
#define T_RP 17
|
||||
#define T_AFSDB 18
|
||||
#define T_RT 21
|
||||
#define T_SIG 24
|
||||
#define T_PX 26
|
||||
#define T_AAAA 28
|
||||
#define T_NXT 30
|
||||
#define T_SRV 33
|
||||
#define T_NAPTR 35
|
||||
#define T_KX 36
|
||||
#define T_DNAME 39
|
||||
#define T_OPT 41
|
||||
#define T_DS 43
|
||||
#define T_RRSIG 46
|
||||
#define T_NSEC 47
|
||||
#define T_DNSKEY 48
|
||||
#define T_NSEC3 50
|
||||
#define T_TKEY 249
|
||||
#define T_TSIG 250
|
||||
#define T_AXFR 252
|
||||
#define T_MAILB 253
|
||||
#define T_ANY 255
|
||||
#define T_CAA 257
|
||||
|
||||
#define EDNS0_OPTION_MAC 65001 /* dyndns.org temporary assignment */
|
||||
#define EDNS0_OPTION_CLIENT_SUBNET 8 /* IANA */
|
||||
#define EDNS0_OPTION_NOMDEVICEID 65073 /* Nominum temporary assignment */
|
||||
#define EDNS0_OPTION_NOMCPEID 65074 /* Nominum temporary assignment */
|
||||
|
||||
struct dns_header {
|
||||
u16 id;
|
||||
@@ -58,18 +89,20 @@ struct dns_header {
|
||||
u16 qdcount,ancount,nscount,arcount;
|
||||
};
|
||||
|
||||
#define HB3_QR 0x80
|
||||
#define HB3_QR 0x80 /* Query */
|
||||
#define HB3_OPCODE 0x78
|
||||
#define HB3_AA 0x04
|
||||
#define HB3_TC 0x02
|
||||
#define HB3_RD 0x01
|
||||
#define HB3_AA 0x04 /* Authoritative Answer */
|
||||
#define HB3_TC 0x02 /* TrunCated */
|
||||
#define HB3_RD 0x01 /* Recursion Desired */
|
||||
|
||||
#define HB4_RA 0x80
|
||||
#define HB4_AD 0x20
|
||||
#define HB4_CD 0x10
|
||||
#define HB4_RA 0x80 /* Recursion Available */
|
||||
#define HB4_AD 0x20 /* Authenticated Data */
|
||||
#define HB4_CD 0x10 /* Checking Disabled */
|
||||
#define HB4_RCODE 0x0f
|
||||
|
||||
#define OPCODE(x) (((x)->hb3 & HB3_OPCODE) >> 3)
|
||||
#define SET_OPCODE(x, code) (x)->hb3 = ((x)->hb3 & ~HB3_OPCODE) | code
|
||||
|
||||
#define RCODE(x) ((x)->hb4 & HB4_RCODE)
|
||||
#define SET_RCODE(x, code) (x)->hb4 = ((x)->hb4 & ~HB4_RCODE) | code
|
||||
|
||||
@@ -109,3 +142,16 @@ struct dns_header {
|
||||
(cp) += 4; \
|
||||
}
|
||||
|
||||
#define CHECK_LEN(header, pp, plen, len) \
|
||||
((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
|
||||
|
||||
#define ADD_RDLEN(header, pp, plen, len) \
|
||||
(!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1))
|
||||
|
||||
/* Escape character in our presentation format for names.
|
||||
Cannot be '.' or /000 and must be !isprint().
|
||||
Note that escaped chars are stored as
|
||||
<NAME_ESCAPE> <orig-char+1>
|
||||
to ensure that the escaped form of /000 doesn't include /000
|
||||
*/
|
||||
#define NAME_ESCAPE 1
|
||||
1365
src/dnsmasq.c
1365
src/dnsmasq.c
File diff suppressed because it is too large
Load Diff
989
src/dnsmasq.h
989
src/dnsmasq.h
File diff suppressed because it is too large
Load Diff
2093
src/dnssec.c
Normal file
2093
src/dnssec.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user