summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Volkov <pva@gentoo.org>2010-08-05 10:18:28 +0000
committerPeter Volkov <pva@gentoo.org>2010-08-05 10:18:28 +0000
commit35d058def5e188222d630e4a1c7a958c5ec6da7d (patch)
tree10ab6683faf140a655a79436a0c72876aa2299c0
parentsys-cluster/vzctl: version bump. Added patch to fix vzpostup. (diff)
downloadpva-35d058def5e188222d630e4a1c7a958c5ec6da7d.tar.gz
pva-35d058def5e188222d630e4a1c7a958c5ec6da7d.tar.bz2
pva-35d058def5e188222d630e4a1c7a958c5ec6da7d.zip
net-misc/dhcp: Version bump. Add radius patch. Update ldap patch. Merge patches from altlinux.
svn path=/; revision=440
-rw-r--r--net-misc/dhcp/Manifest94
-rw-r--r--net-misc/dhcp/dhcp-3.0.7.ebuild (renamed from net-misc/dhcp/dhcp-3.0.5.ebuild)28
-rw-r--r--net-misc/dhcp/files/altlinux.patch1853
-rw-r--r--net-misc/dhcp/files/dhcp-3.0-paranoia.patch4
-rw-r--r--net-misc/dhcp/files/dhcp-3.0.3-no_isc_blurb.patch16
-rw-r--r--net-misc/dhcp/files/dhcp-3.0.3-x-option.patch20
-rw-r--r--net-misc/dhcp/files/dhcp-3.0.4-dhclient-stdin-conf.patch4
-rw-r--r--net-misc/dhcp/files/dhcp-3.0.5-bpf-nofallback.patch6
-rw-r--r--net-misc/dhcp/files/dhcp-3.0.5-ldap.patch (renamed from net-misc/dhcp/files/dhcp-3.0.5-ldap-patch)725
-rw-r--r--net-misc/dhcp/files/dhcp-3.0.7-potential-buffer-overflow.patch31
-rw-r--r--net-misc/dhcp/files/dhcp-3.0.7-potential-premature-server-termination.patch15
-rw-r--r--net-misc/dhcp/files/dhcp-3.0.7-radius-v3.patch2990
-rw-r--r--net-misc/dhcp/files/dhcp-3.0.7-warning-format.patch125
13 files changed, 5639 insertions, 272 deletions
diff --git a/net-misc/dhcp/Manifest b/net-misc/dhcp/Manifest
index dbd74ad..3e68fc8 100644
--- a/net-misc/dhcp/Manifest
+++ b/net-misc/dhcp/Manifest
@@ -1,96 +1,30 @@
+AUX altlinux.patch 59621 RMD160 a537670156ce6eab3eafd2f268ea2371240bbf31 SHA1 6e541cdf0ee43b0952569c9b21c92bd55154736c SHA256 e17b60af030fdfceabd812a3b65a537edbb87b3179562b84eec77dbf46a4a991
AUX dhcp-3.0-fix-perms.patch 485 RMD160 3857270dffed5feee95609aeb37d0c9ef8844945 SHA1 1217265a8a7f1416b781e9f79e8dfb8304268e6c SHA256 a805a60b36e148886887aebb797e80f642386b3e55ef4a0b5132f96a2877e018
-MD5 d909d81a4d4ea39ddfc9898d33488c73 files/dhcp-3.0-fix-perms.patch 485
-RMD160 3857270dffed5feee95609aeb37d0c9ef8844945 files/dhcp-3.0-fix-perms.patch 485
-SHA256 a805a60b36e148886887aebb797e80f642386b3e55ef4a0b5132f96a2877e018 files/dhcp-3.0-fix-perms.patch 485
-AUX dhcp-3.0-paranoia.patch 5366 RMD160 7c64e3dac5b07ff3859fcaa7a8b0e52a0c50446c SHA1 a30103c138e480766f84644fffb1d0897709c27d SHA256 a8db9eb98397a9c1b3a0de07fc107c39dc4f6a4a331d404fc6fcc4a8dbc7aeae
-MD5 66becf9870e0293bbd35d1fba770751a files/dhcp-3.0-paranoia.patch 5366
-RMD160 7c64e3dac5b07ff3859fcaa7a8b0e52a0c50446c files/dhcp-3.0-paranoia.patch 5366
-SHA256 a8db9eb98397a9c1b3a0de07fc107c39dc4f6a4a331d404fc6fcc4a8dbc7aeae files/dhcp-3.0-paranoia.patch 5366
+AUX dhcp-3.0-paranoia.patch 5339 RMD160 51840be98b7ed7321817ce60b350b5ffd75d31cb SHA1 09b6f1196bd7bf55b2e9ec5c671e2be1f0811cdf SHA256 379e4121793a30bbc9fb3e910c37d1144841b8664aecb20ffbdf08d26c1822c1
AUX dhcp-3.0.2-gmake.patch 1872 RMD160 d2d41c0a7e002103d68605d2492bfe716bb2889e SHA1 f60c89233f06ca8554cd5cc9ed0301b597a724f7 SHA256 b2bbfc1d1f5b4d03ff3f53b3974ec32731e5f626de8f8d127328591e4c721215
-MD5 d0f61288e81ce020573f3f6965af8489 files/dhcp-3.0.2-gmake.patch 1872
-RMD160 d2d41c0a7e002103d68605d2492bfe716bb2889e files/dhcp-3.0.2-gmake.patch 1872
-SHA256 b2bbfc1d1f5b4d03ff3f53b3974ec32731e5f626de8f8d127328591e4c721215 files/dhcp-3.0.2-gmake.patch 1872
AUX dhcp-3.0.3-dhclient-dbus.patch 2774 RMD160 250582d89894a58a297786c4a6884b54219c4b6f SHA1 74760ca00712ff529e6b97457408515098563f88 SHA256 d70292c5b61648ba5970ab436429ced33e807bd6f68ba06dcd2b9d4073b02ea4
-MD5 eef265cca1745a6efdfc8d4d1ca2c453 files/dhcp-3.0.3-dhclient-dbus.patch 2774
-RMD160 250582d89894a58a297786c4a6884b54219c4b6f files/dhcp-3.0.3-dhclient-dbus.patch 2774
-SHA256 d70292c5b61648ba5970ab436429ced33e807bd6f68ba06dcd2b9d4073b02ea4 files/dhcp-3.0.3-dhclient-dbus.patch 2774
AUX dhcp-3.0.3-dhclient-hostname.patch 523 RMD160 38c20bcc417822ae858626eb5d0eaf7e669c1ca0 SHA1 5d2c3a1da74a1d151c9fbf08e01e4545e989078c SHA256 57c09edd2bf48cd65745e3b14499f7f3c26d529f60fd2ab122887ae968e26bbd
-MD5 8c4c668abfe5c8b78eb7066391686d30 files/dhcp-3.0.3-dhclient-hostname.patch 523
-RMD160 38c20bcc417822ae858626eb5d0eaf7e669c1ca0 files/dhcp-3.0.3-dhclient-hostname.patch 523
-SHA256 57c09edd2bf48cd65745e3b14499f7f3c26d529f60fd2ab122887ae968e26bbd files/dhcp-3.0.3-dhclient-hostname.patch 523
AUX dhcp-3.0.3-dhclient-metric.patch 7270 RMD160 04187868f66e03a62dafd31b4cdcdd2029283ce5 SHA1 1d726d1526ae97adbdf1b259bb55e05145060375 SHA256 7e5ace014ed55d7d4e90a6cdac7dec4842ea9d178bb19bf6cdccf295eba9da7d
-MD5 f63ddf696f98bd5e300aae865cdbfdb9 files/dhcp-3.0.3-dhclient-metric.patch 7270
-RMD160 04187868f66e03a62dafd31b4cdcdd2029283ce5 files/dhcp-3.0.3-dhclient-metric.patch 7270
-SHA256 7e5ace014ed55d7d4e90a6cdac7dec4842ea9d178bb19bf6cdccf295eba9da7d files/dhcp-3.0.3-dhclient-metric.patch 7270
AUX dhcp-3.0.3-dhclient-mtu.patch 6413 RMD160 2517c7fe58d7dca95bdbdc80e96b6260cc205e56 SHA1 da342800bafee86726570aa0a5e4e3c8bd5f1371 SHA256 0a4bff3c4c44252125f66a3a4423f677465592b84a8f7f500bad9ba4e3b5cb06
-MD5 3bcd2752845eff3da0231a6eccee762a files/dhcp-3.0.3-dhclient-mtu.patch 6413
-RMD160 2517c7fe58d7dca95bdbdc80e96b6260cc205e56 files/dhcp-3.0.3-dhclient-mtu.patch 6413
-SHA256 0a4bff3c4c44252125f66a3a4423f677465592b84a8f7f500bad9ba4e3b5cb06 files/dhcp-3.0.3-dhclient-mtu.patch 6413
AUX dhcp-3.0.3-dhclient-no-down.patch 2332 RMD160 26d0c88534b71070e81c86c12b76a2b4ec7c9c2c SHA1 b2a00d46754414e937dc6c3d63a28b63b3b57ac9 SHA256 a5a67de79f6435d9bc4eeea416aff7a904ab567e5e8d75ecf34495bc9f2c5a44
-MD5 0579a1b0e12f48c466ba6893d76c5fff files/dhcp-3.0.3-dhclient-no-down.patch 2332
-RMD160 26d0c88534b71070e81c86c12b76a2b4ec7c9c2c files/dhcp-3.0.3-dhclient-no-down.patch 2332
-SHA256 a5a67de79f6435d9bc4eeea416aff7a904ab567e5e8d75ecf34495bc9f2c5a44 files/dhcp-3.0.3-dhclient-no-down.patch 2332
AUX dhcp-3.0.3-dhclient-ntp.patch 5868 RMD160 41522438308fc8b82dc298752192d1c77b4c26aa SHA1 48b5dd346e714880f8b4af1d95f3ec2ce8074a66 SHA256 751fdfa0b36eab386f4029284d61c0c2b41b3135878738caa02e512999f2ca65
-MD5 3eab8a40f0a84d3b2d9d406fa4b687c0 files/dhcp-3.0.3-dhclient-ntp.patch 5868
-RMD160 41522438308fc8b82dc298752192d1c77b4c26aa files/dhcp-3.0.3-dhclient-ntp.patch 5868
-SHA256 751fdfa0b36eab386f4029284d61c0c2b41b3135878738caa02e512999f2ca65 files/dhcp-3.0.3-dhclient-ntp.patch 5868
AUX dhcp-3.0.3-dhclient-resolvconf.patch 6671 RMD160 e4a4825df57fb2eed317a44d474f48edbef21fd7 SHA1 aaa15866035759fb4d39a7b00146995115b718ec SHA256 b27c5eeef6efdc8252e68f660424acdfdffaa1a308ec209773cfac78d9faf2a6
-MD5 7193ef2ec3466c4c82aae445e1e5d47d files/dhcp-3.0.3-dhclient-resolvconf.patch 6671
-RMD160 e4a4825df57fb2eed317a44d474f48edbef21fd7 files/dhcp-3.0.3-dhclient-resolvconf.patch 6671
-SHA256 b27c5eeef6efdc8252e68f660424acdfdffaa1a308ec209773cfac78d9faf2a6 files/dhcp-3.0.3-dhclient-resolvconf.patch 6671
AUX dhcp-3.0.3-dhclient-stdin-conf.patch 1948 RMD160 42f32a5bbfe2a937827c2972ef84cfa78c2c401c SHA1 ac7afd5ecbde5348e9acea532dab1e01e3a58e8b SHA256 e1bfd26b7da10acc4bd718e35aae4235308abcacde78dedf39533b11ab18b3ae
-MD5 d81606fd8cdd2376018c6466fe9cf0ef files/dhcp-3.0.3-dhclient-stdin-conf.patch 1948
-RMD160 42f32a5bbfe2a937827c2972ef84cfa78c2c401c files/dhcp-3.0.3-dhclient-stdin-conf.patch 1948
-SHA256 e1bfd26b7da10acc4bd718e35aae4235308abcacde78dedf39533b11ab18b3ae files/dhcp-3.0.3-dhclient-stdin-conf.patch 1948
AUX dhcp-3.0.3-libdst.patch 322 RMD160 5216c754a912cfcfc65683afcf44dbe1a7871212 SHA1 804bab67ae06269336c51183d5ff1e8ba45c20b5 SHA256 68e9a081739736980c0ad834dfa6197f940982f53d4d16054715c0346b5b9eca
-MD5 2bfa28477aff891d25c06a00677d261c files/dhcp-3.0.3-libdst.patch 322
-RMD160 5216c754a912cfcfc65683afcf44dbe1a7871212 files/dhcp-3.0.3-libdst.patch 322
-SHA256 68e9a081739736980c0ad834dfa6197f940982f53d4d16054715c0346b5b9eca files/dhcp-3.0.3-libdst.patch 322
-AUX dhcp-3.0.3-no_isc_blurb.patch 3002 RMD160 d70f89e1763bfeb23ce8f09399426983df01f7c8 SHA1 99a9fe69988226d29ccc6c2dc745ffab9b66817c SHA256 09c451cd9667fc8effcecd640f4cbe8629d41f6abacf9d1f2f923aab1f6e0bbb
-MD5 85a5d65a92d74e828c539b6642962463 files/dhcp-3.0.3-no_isc_blurb.patch 3002
-RMD160 d70f89e1763bfeb23ce8f09399426983df01f7c8 files/dhcp-3.0.3-no_isc_blurb.patch 3002
-SHA256 09c451cd9667fc8effcecd640f4cbe8629d41f6abacf9d1f2f923aab1f6e0bbb files/dhcp-3.0.3-no_isc_blurb.patch 3002
-AUX dhcp-3.0.3-x-option.patch 6478 RMD160 a0fa5b3c7caf2d303a76c3d6fc135783cfa2bbc6 SHA1 4c77474307f9e657e45618f93ba9120eafd83a9e SHA256 6628629a95ee7e711f9dbce6b7d527b15f98eaf7592a1d0855d7bf65961bc3f7
-MD5 1145d8fd3020b1997955cd84b9730702 files/dhcp-3.0.3-x-option.patch 6478
-RMD160 a0fa5b3c7caf2d303a76c3d6fc135783cfa2bbc6 files/dhcp-3.0.3-x-option.patch 6478
-SHA256 6628629a95ee7e711f9dbce6b7d527b15f98eaf7592a1d0855d7bf65961bc3f7 files/dhcp-3.0.3-x-option.patch 6478
-AUX dhcp-3.0.4-dhclient-stdin-conf.patch 2176 RMD160 fae08899f6b57da3ec7ab0068e288bbdf2fbf2ae SHA1 c10c35dcf4a94f45f4bc98147a70e9dcf3f01dd5 SHA256 80141fe71e52774f1c7b1a02f2cbd49bc646f19753ceefc1c3605104df0cae5f
-MD5 f47ef574359340021a78f5c2f67e4954 files/dhcp-3.0.4-dhclient-stdin-conf.patch 2176
-RMD160 fae08899f6b57da3ec7ab0068e288bbdf2fbf2ae files/dhcp-3.0.4-dhclient-stdin-conf.patch 2176
-SHA256 80141fe71e52774f1c7b1a02f2cbd49bc646f19753ceefc1c3605104df0cae5f files/dhcp-3.0.4-dhclient-stdin-conf.patch 2176
-AUX dhcp-3.0.5-bpf-nofallback.patch 1473 RMD160 1a5ece77cb481416935b0d2eea53e85dc4c4ee93 SHA1 d4cad638075a98606e07c633551c8a1d2f78f2e7 SHA256 b215c5ff4a282b475f28168250c05bbbc85e7c37e7af92616571d499b8c14da6
-MD5 223f1d74612d89f327d0afaaa08d34bb files/dhcp-3.0.5-bpf-nofallback.patch 1473
-RMD160 1a5ece77cb481416935b0d2eea53e85dc4c4ee93 files/dhcp-3.0.5-bpf-nofallback.patch 1473
-SHA256 b215c5ff4a282b475f28168250c05bbbc85e7c37e7af92616571d499b8c14da6 files/dhcp-3.0.5-bpf-nofallback.patch 1473
-AUX dhcp-3.0.5-ldap-patch 177648 RMD160 d9ac63f6b66836051bbebf8d5b47c8dfbf77da55 SHA1 49be2d613b5ef7a4cfeb3525fa2833c4d73612ad SHA256 9fd1caf8005288a68ede58476beec7a5a1c0b502a2adb42143013b3c901d225c
-MD5 9a58b7febb69783c15ab9dd635baee74 files/dhcp-3.0.5-ldap-patch 177648
-RMD160 d9ac63f6b66836051bbebf8d5b47c8dfbf77da55 files/dhcp-3.0.5-ldap-patch 177648
-SHA256 9fd1caf8005288a68ede58476beec7a5a1c0b502a2adb42143013b3c901d225c files/dhcp-3.0.5-ldap-patch 177648
+AUX dhcp-3.0.3-no_isc_blurb.patch 2862 RMD160 6706bc856b1d0e30fd93403a8e5cdd15e57ea792 SHA1 52e763b51e17403e779aa98a5c0d0c02e13022fd SHA256 766570c192b372868b350c2cc7eaefcd9914561a9f980cd6c4601375bd1aa444
+AUX dhcp-3.0.3-x-option.patch 6228 RMD160 cd31d37eace4886e21b39525fa1203169497a58e SHA1 48cc7ee769333ddf8b887347461092a90e9aa2c7 SHA256 de6aae4ef49dd76a8979fff976c0798692b706c33340d4ce8173ea2585880024
+AUX dhcp-3.0.4-dhclient-stdin-conf.patch 2166 RMD160 a1852bc6ab935f37fe4fa669e4a065b20e11003c SHA1 d903c564ed380b26a34d3b323e1a60b6c104785f SHA256 b483de8f02cbddc7b6be6a88ba40345ee78d153054dcf36bf436483016a84493
+AUX dhcp-3.0.5-bpf-nofallback.patch 1375 RMD160 e5a9ab6dd47f5fa8972ab96a196947fa69fc17e6 SHA1 b37f2e1e3d8c0a54c6ecb91fa8aad4c14e2fc5df SHA256 76421e85f065bdd044469f22176a0f1ab714a42cc9eee3b61d89f5e4db6d1ecd
+AUX dhcp-3.0.5-ldap.patch 192308 RMD160 f1080479d3e085027e2d8c9c39d91db67b7b436b SHA1 3a594beb0c51a5f61aa65f617e4fdf606cd31c8f SHA256 e700472acb890b504ae5199500a0e87ca1da607946b2f3a8a8958f82d0a277c0
+AUX dhcp-3.0.7-potential-buffer-overflow.patch 1219 RMD160 d77b4be9af662e39e513e47d90216780fab81176 SHA1 805948e42184a01be1fd3d21e9254fdb0a1275f2 SHA256 3cbd15bbfb1ab4911703375c8455085f25462ff5a379df82055f3e86ae4adb60
+AUX dhcp-3.0.7-potential-premature-server-termination.patch 706 RMD160 6c55020aa5b619f3a7b592921bdb6c837034cb19 SHA1 1b931d806991c49511bd22a63ed16a540c8dd67c SHA256 796933c09898082c394c224c47f0169752a5b6c46a84b4a7882f7bee3a9fe701
+AUX dhcp-3.0.7-radius-gentoo-v3.patch 136198 RMD160 6a867ddfd7fbd922826c98fb2a4b0b03e6b9be33 SHA1 4e49d905ef71cf34e692bb8bc9f537ed37e7821e SHA256 ea948056c31f7168406e59baf9aa888f50ec4425e9ded447a90ce64f597492f3
+AUX dhcp-3.0.7-radius-v3.patch 136778 RMD160 f9c6c349c9b5a98ab25f618df5f39ede7c888f4a SHA1 7b71df0ee3cf51e9c8d646de24ecfc1e2aeda16b SHA256 14be3e9ba1e06cee3344c786282062e3f540efa524d8503ea8bb17c6f0430894
+AUX dhcp-3.0.7-warning-format.patch 3314 RMD160 35a1000d47d9bd961caa32850c0de5b8d083ac45 SHA1 3995c4d1f393ddad6e0a453bc61b100bf520c8c2 SHA256 22862d15c4091c7ecb9e4fc73313e6ae76b826dc7e0efe0814626f721263cb54
AUX dhcpd.conf 1092 RMD160 936bb112c7cdf8e669b695599252d1f6626be2f3 SHA1 cbabbcea73a0cbc9692462683b983c96d6f18b0c SHA256 b86d27e0560689057b01a352474582fceb3a398eaf3b17f901378ec56284c4d5
-MD5 3f165a207e98ea92deb7ebfbbf4c2cf7 files/dhcpd.conf 1092
-RMD160 936bb112c7cdf8e669b695599252d1f6626be2f3 files/dhcpd.conf 1092
-SHA256 b86d27e0560689057b01a352474582fceb3a398eaf3b17f901378ec56284c4d5 files/dhcpd.conf 1092
AUX dhcpd.init 2071 RMD160 05e493d00fb94814255d6f262bd8bdbe3f0af0a8 SHA1 8c794b9fe3bf07cf87e1ef90dc2e1b96f4e56786 SHA256 ce40811360f87baf6c608be23a9c0f9de5faa07021db9da5424f2f214bb5dfa4
-MD5 f2163f74f1d3467a579961d79a629b69 files/dhcpd.init 2071
-RMD160 05e493d00fb94814255d6f262bd8bdbe3f0af0a8 files/dhcpd.init 2071
-SHA256 ce40811360f87baf6c608be23a9c0f9de5faa07021db9da5424f2f214bb5dfa4 files/dhcpd.init 2071
AUX dhcrelay.conf 421 RMD160 456edbc9bcc8d3a44db5bb6dbf0c3003c3e7419c SHA1 78ecdb000382893fb49d0052ced063955b0ad9cf SHA256 409b895ed489e75c1a08f72961b45d641b93fd9357f528abc78b1fd036b7f730
-MD5 db84514fe15fd7d81136afbaae738f55 files/dhcrelay.conf 421
-RMD160 456edbc9bcc8d3a44db5bb6dbf0c3003c3e7419c files/dhcrelay.conf 421
-SHA256 409b895ed489e75c1a08f72961b45d641b93fd9357f528abc78b1fd036b7f730 files/dhcrelay.conf 421
AUX dhcrelay.init 748 RMD160 da83794f49e52f072924386b2fd4511d07d985e6 SHA1 fc84da7339a230717a067d9135c6dece038dfb0b SHA256 0d16910b1197946165da7812acffecef8ee3b31cdf8f9a596ca6ecb19756fcee
-MD5 6e2bc3e08290c60d4f339ab9182fce07 files/dhcrelay.init 748
-RMD160 da83794f49e52f072924386b2fd4511d07d985e6 files/dhcrelay.init 748
-SHA256 0d16910b1197946165da7812acffecef8ee3b31cdf8f9a596ca6ecb19756fcee files/dhcrelay.init 748
-DIST dhcp-3.0.5.tar.gz 876591 RMD160 b968e7520fd936bd6f888f77734f3db7df23a636 SHA1 6501ba0e3dbd83ff57d3274538c4e4a1848ffc64 SHA256 dd445fb2a341cdd69e85693dce6f8fda1a1c9d0e98d34c01afc3e68d8037ffb6
-EBUILD dhcp-3.0.5.ebuild 7652 RMD160 0277522a8362a18237de8d706081fc6df04d5194 SHA1 0bcc348cc69d86e5e0169c7fa7d1e060b86263f8 SHA256 4ad81fbb883c00b51423aea6dfeb4e39ffbcc7c6f25a83a1dd831c85271fed34
-MD5 0c5c056885e94949aee6eaa8454e1162 dhcp-3.0.5.ebuild 7652
-RMD160 0277522a8362a18237de8d706081fc6df04d5194 dhcp-3.0.5.ebuild 7652
-SHA256 4ad81fbb883c00b51423aea6dfeb4e39ffbcc7c6f25a83a1dd831c85271fed34 dhcp-3.0.5.ebuild 7652
+DIST dhcp-3.0.7.tar.gz 888829 RMD160 3b16c0459883425c3d978dc2c38783a8986a121c SHA1 d6e8fd6f8e3bd04930ff74b400fca6eb7a5c715a SHA256 9ec6fbd37b4705fd8eed782b64790a246c56b5fd1d5e7de3109b6c23f41b9c50
+EBUILD dhcp-3.0.7.ebuild 7942 RMD160 1ebdcdcd72815cc15eec765d21699c92a490cc4f SHA1 348aaa8b52e7aef8fc0af1c97f76709b5cd8386f SHA256 3e4cce5c0b97af2126b385537a86bf0873b51c669ae2fec998105a75e2c61d91
MISC README 319 RMD160 62483e4a3760ffbd3d6e0b2baa224a4319c76f60 SHA1 c7ba6880d2ea45db7bdde861979b1dad2c509488 SHA256 3855d5a6eff0b021dfebfd43bbba4887c1d655f97d0194d3256737350e3b8764
-MD5 095a35ba4df0c0eb6ca054e496cdafb6 README 319
-RMD160 62483e4a3760ffbd3d6e0b2baa224a4319c76f60 README 319
-SHA256 3855d5a6eff0b021dfebfd43bbba4887c1d655f97d0194d3256737350e3b8764 README 319
-MD5 baa5fba0594aaaf320323529af67db24 files/digest-dhcp-3.0.5 232
-RMD160 412ca9be8de7ae69927b5914b742d8a3e367d7b2 files/digest-dhcp-3.0.5 232
-SHA256 3dc56e680549f1bbbce372b339d5bf1d0474bfd8a45d950f5542bec89117606d files/digest-dhcp-3.0.5 232
diff --git a/net-misc/dhcp/dhcp-3.0.5.ebuild b/net-misc/dhcp/dhcp-3.0.7.ebuild
index 25f0148..4919321 100644
--- a/net-misc/dhcp/dhcp-3.0.5.ebuild
+++ b/net-misc/dhcp/dhcp-3.0.7.ebuild
@@ -2,6 +2,7 @@
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/net-misc/dhcp/dhcp-3.0.5.ebuild,v 1.2 2006/12/20 12:35:53 uberlord Exp $
+EAPI="2"
inherit eutils flag-o-matic multilib toolchain-funcs
MY_PV="${PV//_beta/b}"
@@ -9,25 +10,27 @@ MY_PV="${MY_PV//_rc/rc}"
MY_P="${PN}-${MY_PV}"
DESCRIPTION="ISC Dynamic Host Configuration Protocol"
HOMEPAGE="http://www.isc.org/products/DHCP"
-SRC_URI="ftp://ftp.isc.org/isc/dhcp/${MY_P}.tar.gz"
+SRC_URI="ftp://ftp.isc.org/isc/dhcp/dhcp-3.0-history/${MY_P}.tar.gz"
LICENSE="isc-dhcp"
SLOT="0"
KEYWORDS="~alpha ~amd64 ~arm ~hppa ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc ~sparc-fbsd ~x86 ~x86-fbsd"
-IUSE="doc minimal static selinux kernel_linux ldap-ssl"
+IUSE="doc kernel_linux ldap-ssl minimal radius static selinux"
DEPEND="selinux? ( sec-policy/selinux-dhcp )
kernel_linux? ( sys-apps/net-tools )"
PROVIDE="virtual/dhcpc"
-S="${WORKDIR}/${MY_P}"
+S=${WORKDIR}/${MY_P}
-src_unpack() {
- unpack ${A}
- cd "${S}"
+pkg_setup () {
+ if use ldap-ssl && use radius; then
+ die "ldap-ssl and radius patches are incompatible. Wanna fix? Send me patch ;)"
+ fi
+}
- use ldap-ssl && epatch "${FILESDIR}/${PN}"-3.0.5-ldap-patch
+src_prepare() {
# Gentoo patches - these will probably never be accepted upstream
# Enable chroot support
epatch "${FILESDIR}/${PN}"-3.0-paranoia.patch
@@ -67,6 +70,14 @@ src_unpack() {
# Add dbus support to dhclient
epatch "${FILESDIR}/${PN}"-3.0.3-dhclient-dbus.patch
+ # Altlinux patches http://git.altlinux.org/gears/d/dhcp.git
+ epatch "${FILESDIR}"/${P}-potential-premature-server-termination.patch
+ epatch "${FILESDIR}"/${P}-potential-buffer-overflow.patch
+ epatch "${FILESDIR}"/${P}-warning-format.patch
+
+ use ldap-ssl && epatch "${FILESDIR}/${PN}"-3.0.5-ldap.patch
+ use radius && epatch "${FILESDIR}/${PN}"-3.0.7-radius-gentoo-v3.patch
+
# Brand the version with Gentoo
# include revision if >0
local newver="${MY_PV}-Gentoo"
@@ -109,7 +120,7 @@ src_unpack() {
[[ -d doc/ja_JP.eucJP ]] && rm -rf doc/ja_JP.eucJP
}
-src_compile() {
+src_configure() {
use static && append-ldflags -static
cat <<-END >> includes/site.h
@@ -153,7 +164,6 @@ src_compile() {
if use minimal ; then
sed -i -e 's/\(server\|relay\|dhcpctl\)/ /g' work.*/Makefile || die
fi
- emake || die "compile problem"
}
src_install() {
diff --git a/net-misc/dhcp/files/altlinux.patch b/net-misc/dhcp/files/altlinux.patch
new file mode 100644
index 0000000..8e6b69b
--- /dev/null
+++ b/net-misc/dhcp/files/altlinux.patch
@@ -0,0 +1,1853 @@
+ Makefile | 14 +++---
+ Makefile.conf | 2 +-
+ README | 16 ++++++
+ client/Makefile.dist | 2 +-
+ client/dhclient.c | 33 +++++++++----
+ client/scripts/linux | 51 +++++++++++++-------
+ common/Makefile.dist | 4 +-
+ common/bpf.c | 2 +-
+ common/comapi.c | 2 +-
+ common/dns.c | 4 +-
+ common/droproot.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++
+ common/inet.c | 2 +-
+ common/lpf.c | 1 +
+ common/packet.c | 1 +
+ common/parse.c | 31 ++++++++++--
+ common/print.c | 23 +++++----
+ common/tree.c | 18 ++++----
+ common/upf.c | 2 +-
+ dhcpctl/dhcpctl.3 | 5 +-
+ dst/Makefile.dist | 4 +-
+ dst/dst_api.c | 10 ++++-
+ dst/dst_support.c | 4 +-
+ dst/hmac_link.c | 2 +-
+ includes/cf/linux.h | 4 +-
+ includes/dhcpd.h | 3 +
+ minires/res_mkupdate.c | 8 ++--
+ minires/res_query.c | 2 +-
+ omapip/errwarn.c | 82 ++++++++++++++++++++------------
+ omapip/iscprint.c | 18 ++++----
+ omapip/result.c | 2 +-
+ relay/Makefile.dist | 2 +-
+ relay/dhcrelay.8 | 22 ++++++++-
+ relay/dhcrelay.c | 49 +++++++++++++------
+ server/Makefile.dist | 2 +-
+ server/confpars.c | 7 ++-
+ server/db.c | 4 +-
+ server/ddns.c | 2 +-
+ server/dhcp.c | 6 ++-
+ server/dhcpd.8 | 19 ++++++++
+ server/dhcpd.c | 83 +++++++++++++++++++++-----------
+ server/dhcpd.conf.5 | 21 ++++-----
+ server/failover.c | 12 ++--
+ server/omapi.c | 2 +-
+ 43 files changed, 504 insertions(+), 200 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index 78867f8..3bbc8b8 100644
+--- a/Makefile
++++ b/Makefile
+@@ -33,7 +33,7 @@ all:
+ if [ ! -d work.$$sysname ]; then \
+ echo No build directory for $$sysname - please run ./configure.; \
+ else \
+- (cd work.$$sysname; make all); \
++ $(MAKE) -C work.$$sysname all; \
+ fi
+
+ install:
+@@ -41,7 +41,7 @@ install:
+ if [ ! -d work.$$sysname ]; then \
+ echo No build directory for $$sysname - please run ./configure.; \
+ else \
+- (cd work.$$sysname; make install); \
++ $(MAKE) -C work.$$sysname install; \
+ fi
+
+ depend:
+@@ -49,7 +49,7 @@ depend:
+ if [ ! -d work.$$sysname ]; then \
+ echo No build directory for $$sysname - please run ./configure.; \
+ else \
+- (cd work.$$sysname; make depend); \
++ $(MAKE) -C work.$$sysname depend; \
+ fi
+
+ clean:
+@@ -57,7 +57,7 @@ clean:
+ if [ ! -d work.$$sysname ]; then \
+ echo No build directory for $$sysname - please run ./configure.; \
+ else \
+- (cd work.$$sysname; make clean); \
++ $(MAKE) -C work.$$sysname clean; \
+ fi
+
+ realclean:
+@@ -65,7 +65,7 @@ realclean:
+ if [ ! -d work.$$sysname ]; then \
+ echo No build directory for $$sysname - please run ./configure.; \
+ else \
+- (cd work.$$sysname; make realclean); \
++ $(MAKE) -C work.$$sysname realclean; \
+ fi
+
+ distclean:
+@@ -73,7 +73,7 @@ distclean:
+ if [ ! -d work.$$sysname ]; then \
+ echo No build directory for $$sysname - please run ./configure.; \
+ else \
+- (cd work.$$sysname; make distclean); \
++ $(MAKE) -C work.$$sysname distclean; \
+ fi
+
+ links:
+@@ -81,6 +81,6 @@ links:
+ if [ ! -d work.$$sysname ]; then \
+ echo No build directory for $$sysname - please run ./configure.; \
+ else \
+- (cd work.$$sysname; make links); \
++ $(MAKE) -C work.$$sysname links; \
+ fi
+
+diff --git a/Makefile.conf b/Makefile.conf
+index acdfb58..c6cb3ea 100644
+--- a/Makefile.conf
++++ b/Makefile.conf
+@@ -50,7 +50,7 @@ DEBUG = -g
+ #WARNERR = -Werror
+ RANLIB = ranlib
+ MKDEP = mkdep
+-CLIENT_PATH = '"PATH=/usr/ucb:/usr/bin:/usr/sbin:/bin:/sbin"'
++CLIENT_PATH = '"PATH=/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin"'
+
+ BINDLIB = ../minires/libres.a
+ BINDINC =
+diff --git a/README b/README
+index 2aa92bd..4747c9d 100644
+--- a/README
++++ b/README
+@@ -1,6 +1,7 @@
+ Internet Systems Consortium DHCP Distribution
+ Version 3.0.7
+ May 14, 2008
++ (with modifications for ALT Linux)
+
+ README FILE
+
+@@ -458,6 +459,21 @@ for AIX would be welcome.
+
+ SUPPORT
+
++Please note the following before requesting help:
++
++This software is a part of the Internet Software Consortium's DHCP suite
++with modifications for ALT Linux.
++The ISC folks quite reasonably require that you do not bother them with
++questions on software that includes third-party modifications and might
++not be based off their latest code. Hence, please direct any questions
++to the community@ mailing list instead; the subscription instructions
++are given at http://lists.altlinux.org/mailman/listinfo/community .
++
++The rest of this section describes the ISC's original guidelines on
++requesting support and/or reporting bugs. These will only apply to
++you if you reproduce your problem on the latest version of ISC's DHCP
++suite as available from ftp://ftp.isc.org .
++
+ The Internet Systems Consortium DHCP server is developed and distributed
+ by ISC in the public trust, thanks to the generous donations of its
+ sponsors. ISC now also offers commercial quality support contracts for
+diff --git a/client/Makefile.dist b/client/Makefile.dist
+index c123963..5ee6e71 100644
+--- a/client/Makefile.dist
++++ b/client/Makefile.dist
+@@ -128,6 +128,6 @@ dhclient.leases.cat5: dhclient.leases.man5
+
+
+ dhclient: $(OBJS) $(DHCPLIB)
+- $(CC) $(LFLAGS) -o $(PROG) $(OBJS) $(DHCPLIB) $(LIBS)
++ $(CC) -pie $(LFLAGS) -o $(PROG) $(OBJS) $(DHCPLIB) $(LIBS)
+
+ # Dependencies (semi-automatically-generated)
+diff --git a/client/dhclient.c b/client/dhclient.c
+index 921dade..79c52c9 100644
+--- a/client/dhclient.c
++++ b/client/dhclient.c
+@@ -262,9 +262,9 @@ int main (argc, argv, envp)
+
+ if (!quiet) {
+ log_info ("%s %s", message, DHCP_VERSION);
+- log_info (copyright);
+- log_info (arr);
+- log_info (url);
++ log_info ("%s", copyright);
++ log_info ("%s", arr);
++ log_info ("%s", url);
+ log_info ("%s", "");
+ } else
+ log_perror = 0;
+@@ -470,9 +470,9 @@ int main (argc, argv, envp)
+ static void usage ()
+ {
+ log_info ("%s %s", message, DHCP_VERSION);
+- log_info (copyright);
+- log_info (arr);
+- log_info (url);
++ log_info ("%s", copyright);
++ log_info ("%s", arr);
++ log_info ("%s", url);
+
+ log_error ("Usage: dhclient [-1dqr] [-nw] [-p <port>] %s",
+ "[-s server]");
+@@ -1092,7 +1092,8 @@ void dhcpoffer (packet)
+ return;
+ }
+
+- sprintf (obuf, "%s from %s", name, piaddr (packet -> client_addr));
++ snprintf (obuf, sizeof(obuf),
++ "%s from %s", name, piaddr (packet -> client_addr));
+
+
+ /* If this lease doesn't supply the minimum required parameters,
+@@ -2512,8 +2513,15 @@ void script_write_params (client, prefix, lease)
+ if (data.len > 3) {
+ struct iaddr netmask, subnet, broadcast;
+
+- memcpy (netmask.iabuf, data.data, data.len);
+- netmask.len = data.len;
++ /*
++ * No matter the length of the subnet-mask option,
++ * use only the first four octets. Note that
++ * subnet-mask options longer than 4 octets are not
++ * in conformance with RFC 2132, but servers with this
++ * flaw do exist.
++ */
++ memcpy(netmask.iabuf, data.data, 4);
++ netmask.len = 4;
+ data_string_forget (&data, MDL);
+
+ subnet = subnet_number (lease -> address, netmask);
+@@ -2648,7 +2656,7 @@ void client_envadd (struct client_state *client,
+ {
+ char spbuf [1024];
+ char *s;
+- unsigned len, i;
++ int len;
+ struct string_list *val;
+ va_list list;
+
+@@ -2656,6 +2664,11 @@ void client_envadd (struct client_state *client,
+ len = vsnprintf (spbuf, sizeof spbuf, fmt, list);
+ va_end (list);
+
++/* Handle truncation on glibc 2.0.x or possible unexpected errors on others;
++ * avoid integer overflow in the addition below. */
++ if (len < 0 || len > 0x3fffffff)
++ return;
++
+ val = dmalloc (strlen (prefix) + strlen (name) + 1 /* = */ +
+ len + sizeof *val, MDL);
+ if (!val)
+diff --git a/client/scripts/linux b/client/scripts/linux
+index 31ddd2f..26a2d2e 100755
+--- a/client/scripts/linux
++++ b/client/scripts/linux
+@@ -1,8 +1,6 @@
+ #!/bin/bash
+ # dhclient-script for Linux. Dan Halbert, March, 1997.
+ # Updated for Linux 2.[12] by Brian J. Murrell, January 1999.
+-# No guarantees about this. I'm a novice at the details of Linux
+-# networking.
+
+ # Notes:
+
+@@ -19,13 +17,13 @@
+ # address if it is not supplied. This might be much more easily done
+ # by the dhclient C code, and passed on.
+
+-# 4. TIMEOUT not tested. ping has a flag I don't know, and I'm suspicious
+-# of the $1 in its args.
+-
+ make_resolv_conf() {
+- if [ "x$new_domain_name" != x ] && [ x"$new_domain_name_servers" != x ]; then
+- echo search $new_domain_name >/etc/resolv.conf
++ if [ -n "$new_domain_name" ] || [ -n "$new_domain_name_servers" ]; then
++ echo '; generated by /sbin/dhclient-script' > /etc/resolv.conf
+ chmod 644 /etc/resolv.conf
++ if [ -n "$new_domain_name" ]; then
++ echo search $new_domain_name >> /etc/resolv.conf
++ fi
+ for nameserver in $new_domain_name_servers; do
+ echo nameserver $nameserver >>/etc/resolv.conf
+ done
+@@ -53,6 +51,22 @@ if [ -f /etc/dhclient-enter-hooks ]; then
+ fi
+ fi
+
++cd /etc/sysconfig/network-scripts
++. /etc/sysconfig/network-scripts/network-functions
++. /etc/rc.d/init.d/functions
++
++[ -f ../network ] && . ../network
++[ -f ../networking/network ] && . ../networking/network
++
++CONFIG="ifcfg-$interface"
++
++[ -f "${CONFIG}" ] || {
++ echo $"$0: configuration for $interface not found." >&2
++ exit_with_hooks 1
++}
++
++source_config
++
+ release=`uname -r`
+ release=`expr $release : '\(.*\)\..*'`
+ relminor=`echo $release |sed -e 's/[0-9]*\.\([0-9][0-9]*\)\(\..*\)*$/\1/'`
+@@ -106,13 +120,10 @@ fi
+
+ if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
+ [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then
+- current_hostname=`hostname`
+- if [ x$current_hostname = x ] || \
+- [ x$current_hostname = x$old_host_name ]; then
+- if [ x$current_hostname = x ] || \
+- [ x$new_host_name != x$old_host_name ]; then
+- hostname $new_host_name
+- fi
++ if [ -n "$new_host_name" ] && need_hostname; then
++ if need_hostname || [ "`hostname`" != "$new_host_name" ]; then
++ hostname $new_host_name
++ fi
+ fi
+
+ if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \
+@@ -146,7 +157,10 @@ if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
+ ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
+ route add -host $alias_ip_address $interface:0
+ fi
+- make_resolv_conf
++ if [ "${PEERDNS}" != "no" ]; then
++ make_resolv_conf
++ fi
++
+ exit_with_hooks 0
+ fi
+
+@@ -174,8 +188,7 @@ if [ x$reason = xTIMEOUT ]; then
+ ifconfig $interface inet $new_ip_address $new_subnet_arg \
+ $new_broadcast_arg
+ set $new_routers
+- ############## what is -w in ping?
+- if ping -q -c 1 $1; then
++ if ping -q -c 1 -w 10 $1; then
+ if [ x$new_ip_address != x$alias_ip_address ] && \
+ [ x$alias_ip_address != x ]; then
+ ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg
+@@ -188,7 +201,9 @@ if [ x$reason = xTIMEOUT ]; then
+ for router in $new_routers; do
+ route add default gw $router
+ done
+- make_resolv_conf
++ if [ "${PEERDNS}" != "no" ]; then
++ make_resolv_conf
++ fi
+ exit_with_hooks 0
+ fi
+ ifconfig $interface inet 0 down
+diff --git a/common/Makefile.dist b/common/Makefile.dist
+index 5e40a0f..cd2defe 100644
+--- a/common/Makefile.dist
++++ b/common/Makefile.dist
+@@ -25,11 +25,11 @@ SEDMANPAGES = dhcp-options.man5 dhcp-eval.man5
+ SRC = raw.c parse.c nit.c icmp.c dispatch.c conflex.c upf.c bpf.c socket.c \
+ lpf.c dlpi.c packet.c tr.c ethernet.c memory.c print.c options.c \
+ inet.c tree.c tables.c alloc.c fddi.c ctrace.c dns.c resolv.c \
+- execute.c discover.c comapi.c
++ execute.c discover.c comapi.c droproot.c
+ OBJ = raw.o parse.o nit.o icmp.o dispatch.o conflex.o upf.o bpf.o socket.o \
+ lpf.o dlpi.o packet.o tr.o ethernet.o memory.o print.o options.o \
+ inet.o tree.o tables.o alloc.o fddi.o ctrace.o dns.o resolv.o \
+- execute.o discover.o comapi.o
++ execute.o discover.o comapi.o droproot.o
+ MAN = dhcp-options.5 dhcp-eval.5
+
+ INCLUDES = -I$(TOP) $(BINDINC) -I$(TOP)/includes
+diff --git a/common/bpf.c b/common/bpf.c
+index 6a387d9..6f50f11 100644
+--- a/common/bpf.c
++++ b/common/bpf.c
+@@ -91,7 +91,7 @@ int if_register_bpf (info)
+ /* Open a BPF device */
+ for (b = 0; 1; b++) {
+ /* %Audit% 31 bytes max. %2004.06.17,Safe% */
+- sprintf(filename, BPF_FORMAT, b);
++ snprintf(filename, sizeof(filename), BPF_FORMAT, b);
+ sock = open (filename, O_RDWR, 0);
+ if (sock < 0) {
+ if (errno == EBUSY) {
+diff --git a/common/comapi.c b/common/comapi.c
+index 1307968..c58ffde 100644
+--- a/common/comapi.c
++++ b/common/comapi.c
+@@ -288,7 +288,7 @@ isc_result_t dhcp_group_signal_handler (omapi_object_t *h,
+ /* Group objects always have to have names. */
+ if (!group -> name) {
+ char hnbuf [64];
+- sprintf (hnbuf, "ng%08lx%08lx",
++ snprintf (hnbuf, sizeof(hnbuf), "ng%08lx%08lx",
+ (unsigned long)cur_time,
+ (unsigned long)group);
+ group -> name = dmalloc (strlen (hnbuf) + 1, MDL);
+diff --git a/common/dns.c b/common/dns.c
+index 03a76a8..c489201 100644
+--- a/common/dns.c
++++ b/common/dns.c
+@@ -533,7 +533,7 @@ isc_result_t ddns_update_a (struct data_string *ddns_fwd_name,
+ return ISC_R_INVALIDARG;
+
+ /* %Audit% Cannot exceed 16 bytes. %2004.06.17,Safe% */
+- sprintf (ddns_address, "%u.%u.%u.%u",
++ snprintf (ddns_address, sizeof(ddns_address), "%u.%u.%u.%u",
+ ddns_addr.iabuf[0], ddns_addr.iabuf[1],
+ ddns_addr.iabuf[2], ddns_addr.iabuf[3]);
+
+@@ -794,7 +794,7 @@ isc_result_t ddns_remove_a (struct data_string *ddns_fwd_name,
+ return ISC_R_INVALIDARG;
+
+ /* %Audit% Cannot exceed 16 bytes. %2004.06.17,Safe% */
+- sprintf (ddns_address, "%u.%u.%u.%u",
++ snprintf (ddns_address, sizeof(ddns_address), "%u.%u.%u.%u",
+ ddns_addr.iabuf[0], ddns_addr.iabuf[1],
+ ddns_addr.iabuf[2], ddns_addr.iabuf[3]);
+
+diff --git a/common/droproot.c b/common/droproot.c
+new file mode 100644
+index 0000000..36c42dd
+--- /dev/null
++++ b/common/droproot.c
+@@ -0,0 +1,121 @@
++#include "dhcpd.h"
++#include <unistd.h>
++#include <time.h>
++#include <pwd.h>
++#define group real_group
++#include <grp.h>
++#undef group
++
++#include <sys/capability.h>
++#include <sys/prctl.h>
++
++static int minimized = 0;
++
++void
++dhcpd_priv_minimize(const char *user, const char *dir)
++{
++ struct passwd *pw;
++ uid_t uid;
++ gid_t gid;
++
++ if (!*user)
++ return;
++
++ if (!(pw = getpwnam(user)))
++ log_fatal("Failed to lower privileges: getpwnam: %s", user);
++
++ uid = pw->pw_uid;
++ gid = pw->pw_gid;
++
++ tzset();
++
++ if (initgroups(user, gid))
++ log_fatal("Failed to lower privileges: initgroups: %s/%u: %m",
++ user, (unsigned) gid);
++
++ endpwent();
++
++ if (*dir && (chdir(dir) || chroot(".")))
++ log_fatal("Failed to lower privileges: chroot: %s: %m", dir);
++
++ if (setgid(gid))
++ log_fatal("Failed to lower privileges: setgid: %s/%u: %m",
++ user, (unsigned) gid);
++
++ if (prctl(PR_SET_KEEPCAPS, 1))
++ log_fatal("Failed to lower privileges: prctl: %m");
++
++ if (setreuid(uid, uid))
++ log_fatal("Failed to lower privileges: setreuid: %s/%u: %m",
++ user, (unsigned) uid);
++
++ cap_t caps = cap_from_text("cap_net_bind_service=ep");
++
++ if (!caps)
++ log_fatal("Failed to lower privileges: cap_from_text: %m");
++
++ if (cap_set_proc(caps) < 0)
++ log_fatal("Failed to lower privileges: cap_set_proc: %m");
++
++ cap_free(caps);
++ minimized = 1;
++}
++
++static void
++drop_minimized(void)
++{
++ cap_t caps = cap_from_text("all-ep");
++ if (!caps)
++ log_fatal("Failed to lower privileges: cap_from_text: %m");
++
++ if (cap_set_proc(caps) < 0)
++ log_fatal("Failed to lower privileges: cap_set_proc: %m");
++
++ cap_free(caps);
++}
++
++static void
++drop_all(const char *user, const char *dir)
++{
++ struct passwd *pw;
++ uid_t uid;
++ gid_t gid;
++
++ if (!(pw = getpwnam(user)))
++ log_fatal("Failed to lower privileges: getpwnam: %s", user);
++
++ uid = pw->pw_uid;
++ gid = pw->pw_gid;
++
++ tzset();
++
++ if (initgroups(user, gid))
++ log_fatal("Failed to lower privileges: initgroups: %s/%u: %m",
++ user, (unsigned) gid);
++
++ endpwent();
++
++ if (*dir && (chdir(dir) || chroot(".")))
++ log_fatal("Failed to lower privileges: chroot: %s: %m", dir);
++
++ if (setgid(gid))
++ log_fatal("Failed to lower privileges: setgid: %s/%u: %m",
++ user, (unsigned) gid);
++
++ if (setuid(uid))
++ log_fatal("Failed to lower privileges: setuid: %s/%u: %m",
++ user, (unsigned) uid);
++}
++
++
++void
++dhcpd_priv_drop(const char *user, const char *dir)
++{
++ if (!*user)
++ return;
++
++ if (minimized)
++ drop_minimized();
++ else
++ drop_all(user, dir);
++}
+diff --git a/common/inet.c b/common/inet.c
+index 3c86e5a..488b15a 100644
+--- a/common/inet.c
++++ b/common/inet.c
+@@ -188,7 +188,7 @@ int addr_eq (addr1, addr2)
+ char *piaddr (addr)
+ struct iaddr addr;
+ {
+- static char pbuf [4 * 16];
++ static char pbuf [4 * sizeof(addr.iabuf)];
+ char *s = pbuf;
+ int i;
+
+diff --git a/common/lpf.c b/common/lpf.c
+index dc7f3f2..3f19b43 100644
+--- a/common/lpf.c
++++ b/common/lpf.c
+@@ -253,6 +253,7 @@ static void lpf_tr_filter_setup (info)
+
+ /* Set up the bpf filter program structure. This is defined in
+ bpf.c */
++ memset(&p, '\0', sizeof p);
+ p.len = dhcp_bpf_tr_filter_len;
+ p.filter = dhcp_bpf_tr_filter;
+
+diff --git a/common/packet.c b/common/packet.c
+index 668106c..fdd569f 100644
+--- a/common/packet.c
++++ b/common/packet.c
+@@ -141,6 +141,7 @@ void assemble_udp_ip_header (interface, buf, bufix,
+ struct udphdr udp;
+
+ /* Fill out the IP header */
++ memset( &ip, '\0', sizeof ip);
+ IP_V_SET (&ip, 4);
+ IP_HL_SET (&ip, 20);
+ ip.ip_tos = IPTOS_LOWDELAY;
+diff --git a/common/parse.c b/common/parse.c
+index 9efd146..f4d6c46 100644
+--- a/common/parse.c
++++ b/common/parse.c
+@@ -4798,6 +4798,25 @@ int parse_X (cfile, buf, max)
+ return len;
+ }
+
++static ssize_t
++write_loop (int fd, const char *buffer, size_t count)
++{
++ ssize_t offset = 0;
++
++ while (count > 0)
++ {
++ ssize_t block = write (fd, &buffer[offset], count);
++
++ if (block < 0 && errno == EINTR)
++ continue;
++ if (block <= 0)
++ return offset ? : block;
++ offset += block;
++ count -= block;
++ }
++ return offset;
++}
++
+ int parse_warn (struct parse *cfile, const char *fmt, ...)
+ {
+ va_list list;
+@@ -4838,14 +4857,14 @@ int parse_warn (struct parse *cfile, const char *fmt, ...)
+ #endif
+
+ if (log_perror) {
+- write (STDERR_FILENO, mbuf, strlen (mbuf));
+- write (STDERR_FILENO, "\n", 1);
+- write (STDERR_FILENO, cfile -> token_line,
++ write_loop (STDERR_FILENO, mbuf, strlen (mbuf));
++ write_loop (STDERR_FILENO, "\n", 1);
++ write_loop (STDERR_FILENO, cfile -> token_line,
+ strlen (cfile -> token_line));
+- write (STDERR_FILENO, "\n", 1);
++ write_loop (STDERR_FILENO, "\n", 1);
+ if (cfile -> lexchar < 81)
+- write (STDERR_FILENO, lexbuf, lix);
+- write (STDERR_FILENO, "^\n", 2);
++ write_loop (STDERR_FILENO, lexbuf, lix);
++ write_loop (STDERR_FILENO, "^\n", 2);
+ }
+
+ cfile -> warnings_occurred = 1;
+diff --git a/common/print.c b/common/print.c
+index 446de78..969f8ab 100644
+--- a/common/print.c
++++ b/common/print.c
+@@ -311,7 +311,7 @@ void dump_raw (buf, len)
+ lbuf[54]=' ';
+ lbuf[55]=' ';
+ lbuf[73]='\0';
+- log_info (lbuf);
++ log_info ("%s", lbuf);
+ }
+ memset(lbuf, ' ', 79);
+ lbuf [79] = 0;
+@@ -335,7 +335,7 @@ void dump_raw (buf, len)
+ lbuf[54]=' ';
+ lbuf[55]=' ';
+ lbuf[73]='\0';
+- log_info (lbuf);
++ log_info ("%s", lbuf);
+ }
+
+ void hash_dump (table)
+@@ -437,7 +437,7 @@ char *print_dec_1 (val)
+ unsigned long val;
+ {
+ static char vbuf [32];
+- sprintf (vbuf, "%lu", val);
++ snprintf (vbuf, sizeof(vbuf), "%lu", val);
+ return vbuf;
+ }
+
+@@ -445,7 +445,7 @@ char *print_dec_2 (val)
+ unsigned long val;
+ {
+ static char vbuf [32];
+- sprintf (vbuf, "%lu", val);
++ snprintf (vbuf, sizeof(vbuf), "%lu", val);
+ return vbuf;
+ }
+
+@@ -478,7 +478,7 @@ static unsigned print_subexpression (expr, buf, len)
+ case expr_check:
+ rv = 10 + strlen (expr -> data.check -> name);
+ if (len > rv) {
+- sprintf (buf, "(check %s)",
++ snprintf (buf, len, "(check %s)",
+ expr -> data.check -> name);
+ return rv;
+ }
+@@ -585,7 +585,7 @@ static unsigned print_subexpression (expr, buf, len)
+ case expr_host_lookup:
+ rv = 15 + strlen (expr -> data.host_lookup -> hostname);
+ if (len > rv) {
+- sprintf (buf, "(dns-lookup %s)",
++ snprintf (buf, len, "(dns-lookup %s)",
+ expr -> data.host_lookup -> hostname);
+ return rv;
+ }
+@@ -669,7 +669,7 @@ static unsigned print_subexpression (expr, buf, len)
+ rv = strlen (s) + 2 + (strlen (expr -> data.option -> name) +
+ strlen (expr -> data.option -> universe -> name));
+ if (len > rv) {
+- sprintf (buf, "(option %s.%s)",
++ snprintf (buf, len, "(option %s.%s)",
+ expr -> data.option -> universe -> name,
+ expr -> data.option -> name);
+ return rv;
+@@ -805,7 +805,7 @@ static unsigned print_subexpression (expr, buf, len)
+ rv = 10 + (strlen (expr -> data.option -> name) +
+ strlen (expr -> data.option -> universe -> name));
+ if (len > rv) {
+- sprintf (buf, "(exists %s.%s)",
++ snprintf (buf, len, "(exists %s.%s)",
+ expr -> data.option -> universe -> name,
+ expr -> data.option -> name);
+ return rv;
+@@ -815,7 +815,8 @@ static unsigned print_subexpression (expr, buf, len)
+ case expr_variable_exists:
+ rv = 10 + strlen (expr -> data.variable);
+ if (len > rv) {
+- sprintf (buf, "(defined %s)", expr -> data.variable);
++ snprintf (buf, len,
++ "(defined %s)", expr -> data.variable);
+ return rv;
+ }
+ break;
+@@ -823,7 +824,7 @@ static unsigned print_subexpression (expr, buf, len)
+ case expr_variable_reference:
+ rv = strlen (expr -> data.variable);
+ if (len > rv) {
+- sprintf (buf, "%s", expr -> data.variable);
++ snprintf (buf, len, "%s", expr -> data.variable);
+ return rv;
+ }
+ break;
+@@ -1106,7 +1107,7 @@ int token_indent_data_string (FILE *file, int col, int indent,
+ }
+
+ for (i = 0; i < data -> len; i++) {
+- sprintf (obuf, "%2.2x", data -> data [i]);
++ snprintf (obuf, sizeof(obuf), "%2.2x", data -> data [i]);
+ col = token_print_indent (file, col, indent,
+ i == 0 ? prefix : "",
+ (i + 1 == data -> len
+diff --git a/common/tree.c b/common/tree.c
+index 56d262f..7130839 100644
+--- a/common/tree.c
++++ b/common/tree.c
+@@ -738,8 +738,8 @@ int evaluate_dns_expression (result, packet, lease, client_state, in_options,
+ (*result) -> r_data =
+ (*result) -> r_data_ephem;
+ /*%Audit% 16 bytes max. %2004.06.17,Safe%*/
+- sprintf ((char *)(*result) -> r_data_ephem,
+- "%u.%u.%u.%u",
++ snprintf ((char *)(*result) -> r_data_ephem,
++ 16, "%u.%u.%u.%u",
+ data.data [0] & 0xff,
+ data.data [1] & 0xff,
+ data.data [2] & 0xff,
+@@ -3428,7 +3428,7 @@ int write_expression (file, expr, col, indent, firstp)
+ col = write_expression (file, expr -> data.extract_int,
+ col, indent, 1);
+ col = token_print_indent (file, col, scol, "", " ", ",");
+- sprintf (obuf, "%d", width);
++ snprintf (obuf, sizeof(obuf), "%d", width);
+ col = token_print_indent (file, col, scol, " ", "", obuf);
+ col = token_print_indent (file, col, indent, "", "", ")");
+ break;
+@@ -3451,7 +3451,7 @@ int write_expression (file, expr, col, indent, firstp)
+ col = write_expression (file, expr -> data.extract_int,
+ col, indent, 1);
+ col = token_print_indent (file, col, scol, "", " ", ",");
+- sprintf (obuf, "%d", width);
++ snprintf (obuf, sizeof(obuf), "%d", width);
+ col = token_print_indent (file, col, scol, " ", "", obuf);
+ col = token_print_indent (file, col, indent, "", "",
+ ")");
+@@ -3466,7 +3466,7 @@ int write_expression (file, expr, col, indent, firstp)
+ goto encode_int;
+
+ case expr_const_int:
+- sprintf (obuf, "%lu", expr -> data.const_int);
++ snprintf (obuf, sizeof(obuf), "%lu", expr -> data.const_int);
+ col = token_print_indent (file, col, indent, "", "", obuf);
+ break;
+
+@@ -3615,11 +3615,11 @@ int write_expression (file, expr, col, indent, firstp)
+ col = token_print_indent (file, col, indent, " ", "",
+ "(");
+ scol = col;
+- sprintf (obuf, "%d", expr -> data.ns_add.rrclass);
++ snprintf (obuf, sizeof(obuf), "%d", expr -> data.ns_add.rrclass);
+ col = token_print_indent (file, col, scol, "", "", obuf);
+ col = token_print_indent (file, col, scol, "", " ",
+ ",");
+- sprintf (obuf, "%d", expr -> data.ns_add.rrtype);
++ snprintf (obuf, sizeof(obuf), "%d", expr -> data.ns_add.rrtype);
+ col = token_print_indent (file, col, scol, "", "", obuf);
+ col = token_print_indent (file, col, scol, "", " ",
+ ",");
+@@ -3644,11 +3644,11 @@ int write_expression (file, expr, col, indent, firstp)
+ "(");
+ finish_ns_small:
+ scol = col;
+- sprintf (obuf, "%d", expr -> data.ns_add.rrclass);
++ snprintf (obuf, sizeof(obuf), "%d", expr -> data.ns_add.rrclass);
+ col = token_print_indent (file, col, scol, "", "", obuf);
+ col = token_print_indent (file, col, scol, "", " ",
+ ",");
+- sprintf (obuf, "%d", expr -> data.ns_add.rrtype);
++ snprintf (obuf, sizeof(obuf), "%d", expr -> data.ns_add.rrtype);
+ col = token_print_indent (file, col, scol, "", "", obuf);
+ col = token_print_indent (file, col, scol, "", " ",
+ ",");
+diff --git a/common/upf.c b/common/upf.c
+index 89c217a..116449b 100644
+--- a/common/upf.c
++++ b/common/upf.c
+@@ -80,7 +80,7 @@ int if_register_upf (info)
+ /* Open a UPF device */
+ for (b = 0; 1; b++) {
+ /* %Audit% Cannot exceed 36 bytes. %2004.06.17,Safe% */
+- sprintf(filename, "/dev/pf/pfilt%d", b);
++ snprintf(filename, sizeof(filename), "/dev/pf/pfilt%d", b);
+
+ sock = open (filename, O_RDWR, 0);
+ if (sock < 0) {
+diff --git a/dhcpctl/dhcpctl.3 b/dhcpctl/dhcpctl.3
+index 352bf3b..880285d 100644
+--- a/dhcpctl/dhcpctl.3
++++ b/dhcpctl/dhcpctl.3
+@@ -43,7 +43,8 @@
+ .\"
+ .\"
+ .Sh SYNOPSIS
+-.Fd #include <dhcpctl/dhcpctl.h>
++.Fd #include <dhcpctl.h>
++.sp
+ .Ft dhcpctl_status
+ .Fo dhcpctl_initialize
+ .Fa void
+@@ -426,7 +427,7 @@ that most error checking has been ommitted for brevity.
+ #include <netinet/in.h>
+
+ #include <isc/result.h>
+-#include <dhcpctl/dhcpctl.h>
++#include <dhcpctl.h>
+
+ int main (int argc, char **argv) {
+ dhcpctl_data_string ipaddrstring = NULL;
+diff --git a/dst/Makefile.dist b/dst/Makefile.dist
+index ffe7e4e..9282e59 100644
+--- a/dst/Makefile.dist
++++ b/dst/Makefile.dist
+@@ -30,7 +30,9 @@ CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) -DHMAC_MD5 -DMINIRES_LIB
+
+ all: libdst.a
+
+-install:
++install: all
++ mkdir -p $(DESTDIR)$(LIBDIR)
++ $(INSTALL) libdst.a $(DESTDIR)$(LIBDIR)/
+
+ libdst.a: $(OBJ)
+ rm -f dst.a
+diff --git a/dst/dst_api.c b/dst/dst_api.c
+index 64114cb..ff396f2 100644
+--- a/dst/dst_api.c
++++ b/dst/dst_api.c
+@@ -440,6 +440,7 @@ dst_s_write_private_key(const DST_KEY *key)
+ if ((nn = fwrite(encoded_block, 1, len, fp)) != len) {
+ EREPORT(("dst_write_private_key(): Write failure on %s %d != %d errno=%d\n",
+ file, out_len, nn, errno));
++ fclose(fp);
+ return (-5);
+ }
+ fclose(fp);
+@@ -526,6 +527,7 @@ dst_s_read_public_key(const char *in_name, const unsigned in_id, int in_alg)
+ /* Locate and skip "KEY" */
+ if (c != 'K' && c != 'k') {
+ EREPORT(("\"KEY\" doesn't appear in file: %s", name));
++ fclose(fp);
+ return NULL;
+ }
+ while ((c = getc(fp)) != EOF)
+@@ -540,10 +542,15 @@ dst_s_read_public_key(const char *in_name, const unsigned in_id, int in_alg)
+ if (fscanf(fp, "%d %d %d", &flags, &proto, &alg) != 3) {
+ EREPORT(("dst_read_public_key(): Can not read flag/proto/alg field from %s\n"
+ ,name));
++ fclose(fp);
+ return (NULL);
+ }
+ /* read in the key string */
+- fgets(enckey, sizeof(enckey), fp);
++ if (!fgets(enckey, sizeof(enckey), fp)) {
++ EREPORT(("Key too short in file: %s", name));
++ fclose(fp);
++ return NULL;
++ }
+
+ /* If we aren't at end-of-file, something is wrong. */
+ while ((c = getc(fp)) != EOF)
+@@ -551,6 +558,7 @@ dst_s_read_public_key(const char *in_name, const unsigned in_id, int in_alg)
+ break;
+ if (!feof(fp)) {
+ EREPORT(("Key too long in file: %s", name));
++ fclose(fp);
+ return NULL;
+ }
+ fclose(fp);
+diff --git a/dst/dst_support.c b/dst/dst_support.c
+index 581445b..a8c1ba8 100644
+--- a/dst/dst_support.c
++++ b/dst/dst_support.c
+@@ -418,8 +418,8 @@ dst_s_build_filename(char *filename, const char *name, unsigned id,
+ if (filename_length < 1 + strlen(name) + 4 + 6 + 1 + strlen(suffix))
+ return (-1);
+ my_id = id;
+- sprintf(filename, "K%s+%03d+%05d.%s", name, alg, my_id,
+- (const char *) suffix);
++ snprintf(filename, filename_length, "K%s+%03d+%05d.%s",
++ name, alg, my_id, (const char *) suffix);
+ if (strrchr(filename, '/'))
+ return (-1);
+ if (strrchr(filename, '\\'))
+diff --git a/dst/hmac_link.c b/dst/hmac_link.c
+index 90b92e2..ad95c7a 100644
+--- a/dst/hmac_link.c
++++ b/dst/hmac_link.c
+@@ -280,7 +280,7 @@ dst_hmac_md5_key_to_file_format(const DST_KEY *dkey, char *buff,
+ hkey = (HMAC_Key *) dkey->dk_KEY_struct;
+ memset(buff, 0, buff_len); /* just in case */
+ /* write file header */
+- sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_HMAC_MD5, "HMAC");
++ snprintf(buff, buff_len, key_file_fmt_str, KEY_FILE_FORMAT, KEY_HMAC_MD5, "HMAC");
+
+ bp = (char *) strchr(buff, '\0');
+ b_len = buff_len - (bp - buff);
+diff --git a/includes/cf/linux.h b/includes/cf/linux.h
+index a286084..d37e335 100644
+--- a/includes/cf/linux.h
++++ b/includes/cf/linux.h
+@@ -83,11 +83,11 @@ extern int h_errno;
+ directory. */
+
+ #ifndef _PATH_DHCPD_DB
+-#define _PATH_DHCPD_DB "/var/state/dhcp/dhcpd.leases"
++#define _PATH_DHCPD_DB "/state/dhcpd.leases"
+ #endif
+
+ #ifndef _PATH_DHCLIENT_DB
+-#define _PATH_DHCLIENT_DB "/var/state/dhcp/dhclient.leases"
++#define _PATH_DHCLIENT_DB "/var/lib/dhcp/dhclient/state/dhclient.leases"
+ #endif
+
+ /* Varargs stuff... */
+diff --git a/includes/dhcpd.h b/includes/dhcpd.h
+index ba2911b..d6acec1 100644
+--- a/includes/dhcpd.h
++++ b/includes/dhcpd.h
+@@ -2643,3 +2643,6 @@ OMAPI_OBJECT_ALLOC_DECL (dhcp_failover_link, dhcp_failover_link_t,
+ #endif /* FAILOVER_PROTOCOL */
+
+ const char *binding_state_print (enum failover_state);
++
++extern void dhcpd_priv_minimize(const char *server_user, const char *server_jail);
++extern void dhcpd_priv_drop(const char *server_user, const char *server_jail);
+diff --git a/minires/res_mkupdate.c b/minires/res_mkupdate.c
+index 19f2d50..537f636 100644
+--- a/minires/res_mkupdate.c
++++ b/minires/res_mkupdate.c
+@@ -1113,14 +1113,14 @@ cgetprotobynumber(int proto) { /* Host byte order. */
+
+ const char *
+ res_protocolname(int num) {
+- static char number[8];
++ static char number[2 + sizeof(num) * 3];
+ struct protoent *pp;
+
+ if (protolist == (struct valuelist *)0)
+ res_buildprotolist();
+ pp = cgetprotobynumber(num);
+ if (pp == 0) {
+- (void) sprintf(number, "%d", num);
++ (void) snprintf(number, sizeof(number), "%d", num);
+ return (number);
+ }
+ return (pp->p_name);
+@@ -1128,14 +1128,14 @@ res_protocolname(int num) {
+
+ const char *
+ res_servicename(u_int16_t port, const char *proto) { /* Host byte order. */
+- static char number[8];
++ static char number[2 + sizeof(port) * 3];
+ struct servent *ss;
+
+ if (servicelist == (struct valuelist *)0)
+ res_buildservicelist();
+ ss = cgetservbyport(htons(port), proto);
+ if (ss == 0) {
+- (void) sprintf(number, "%d", port);
++ (void) snprintf(number, sizeof(number), "%d", port);
+ return (number);
+ }
+ return (ss->s_name);
+diff --git a/minires/res_query.c b/minires/res_query.c
+index 7c3912f..170d999 100644
+--- a/minires/res_query.c
++++ b/minires/res_query.c
+@@ -375,7 +375,7 @@ res_nquerydomain(res_state statp,
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return ISC_R_NOSPACE;
+ }
+- sprintf(nbuf, "%s.%s", name, domain);
++ snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
+ }
+ return res_nquery(statp,
+ longname, class, type, answer, anslen, ansret);
+diff --git a/omapip/errwarn.c b/omapip/errwarn.c
+index be0e6d8..f1d7343 100644
+--- a/omapip/errwarn.c
++++ b/omapip/errwarn.c
+@@ -51,6 +51,25 @@ void (*log_cleanup) (void);
+ static char mbuf [CVT_BUF_MAX + 1];
+ static char fbuf [CVT_BUF_MAX + 1];
+
++static ssize_t
++write_loop (int fd, const char *buffer, size_t count)
++{
++ ssize_t offset = 0;
++
++ while (count > 0)
++ {
++ ssize_t block = write (fd, &buffer[offset], count);
++
++ if (block < 0 && errno == EINTR)
++ continue;
++ if (block <= 0)
++ return offset ? : block;
++ offset += block;
++ count -= block;
++ }
++ return offset;
++}
++
+ /* Log an error message, then exit... */
+
+ void log_fatal (const char * fmt, ... )
+@@ -67,33 +86,31 @@ void log_fatal (const char * fmt, ... )
+ va_end (list);
+
+ #ifndef DEBUG
+- syslog (log_priority | LOG_ERR, "%s", mbuf);
++ if (*mbuf)
++ syslog (log_priority | LOG_ERR, "%s", mbuf);
+ #endif
+
+ /* Also log it to stderr? */
+- if (log_perror) {
+- write (STDERR_FILENO, mbuf, strlen (mbuf));
+- write (STDERR_FILENO, "\n", 1);
++ if (log_perror && *mbuf) {
++ write_loop (STDERR_FILENO, mbuf, strlen (mbuf));
++ write_loop (STDERR_FILENO, "\n", 1);
+ }
+
+ #if !defined (NOMINUM)
++ log_error ("%s", "Please note the following before requesting help:");
+ log_error ("%s", "");
+- log_error ("If you did not get this software from ftp.isc.org, please");
+- log_error ("get the latest from ftp.isc.org and install that before");
+- log_error ("requesting help.");
+- log_error ("%s", "");
+- log_error ("If you did get this software from ftp.isc.org and have not");
+- log_error ("yet read the README, please read it before requesting help.");
+- log_error ("If you intend to request help from the dhcp-server@isc.org");
+- log_error ("mailing list, please read the section on the README about");
+- log_error ("submitting bug reports and requests for help.");
++ log_error ("%s", "This software is a part of the Internet Software Consortium's DHCP suite");
++ log_error ("%s", "with modifications for ALT Linux.");
++ log_error ("%s", "The ISC folks quite reasonably require that you do not bother them with");
++ log_error ("%s", "questions on software that includes third-party modifications and might");
++ log_error ("%s", "not be based off their latest code. Hence, please direct any questions");
++ log_error ("%s", "to the community@ mailing list instead; the subscription instructions");
++ log_error ("%s", "are given at http://lists.altlinux.org/mailman/listinfo/community .");
+ log_error ("%s", "");
+- log_error ("Please do not under any circumstances send requests for");
+- log_error ("help directly to the authors of this software - please");
+- log_error ("send them to the appropriate mailing list as described in");
+- log_error ("the README file.");
++ log_error ("%s", "Please also read the SUPPORT section on the README about");
++ log_error ("%s", "submitting bug reports and requests for help.");
+ log_error ("%s", "");
+- log_error ("exiting.");
++ log_error ("%s", "exiting.");
+ #endif
+ if (log_cleanup)
+ (*log_cleanup) ();
+@@ -116,12 +133,13 @@ int log_error (const char * fmt, ...)
+ va_end (list);
+
+ #ifndef DEBUG
+- syslog (log_priority | LOG_ERR, "%s", mbuf);
++ if (*mbuf)
++ syslog (log_priority | LOG_ERR, "%s", mbuf);
+ #endif
+
+- if (log_perror) {
+- write (STDERR_FILENO, mbuf, strlen (mbuf));
+- write (STDERR_FILENO, "\n", 1);
++ if (log_perror && *mbuf) {
++ write_loop (STDERR_FILENO, mbuf, strlen (mbuf));
++ write_loop (STDERR_FILENO, "\n", 1);
+ }
+
+ return 0;
+@@ -143,12 +161,13 @@ int log_info (const char *fmt, ...)
+ va_end (list);
+
+ #ifndef DEBUG
+- syslog (log_priority | LOG_INFO, "%s", mbuf);
++ if (*mbuf)
++ syslog (log_priority | LOG_INFO, "%s", mbuf);
+ #endif
+
+- if (log_perror) {
+- write (STDERR_FILENO, mbuf, strlen (mbuf));
+- write (STDERR_FILENO, "\n", 1);
++ if (log_perror && *mbuf) {
++ write_loop (STDERR_FILENO, mbuf, strlen (mbuf));
++ write_loop (STDERR_FILENO, "\n", 1);
+ }
+
+ return 0;
+@@ -170,12 +189,13 @@ int log_debug (const char *fmt, ...)
+ va_end (list);
+
+ #ifndef DEBUG
+- syslog (log_priority | LOG_DEBUG, "%s", mbuf);
++ if (*mbuf)
++ syslog (log_priority | LOG_DEBUG, "%s", mbuf);
+ #endif
+
+- if (log_perror) {
+- write (STDERR_FILENO, mbuf, strlen (mbuf));
+- write (STDERR_FILENO, "\n", 1);
++ if (log_perror && *mbuf) {
++ write_loop (STDERR_FILENO, mbuf, strlen (mbuf));
++ write_loop (STDERR_FILENO, "\n", 1);
+ }
+
+ return 0;
+@@ -236,7 +256,7 @@ char *strerror (err)
+ static char errbuf [128];
+
+ if (err < 0 || err >= sys_nerr) {
+- sprintf (errbuf, "Error %d", err);
++ snprintf (errbuf, sizeof(errbuf), "Error %d", err);
+ return errbuf;
+ }
+ return sys_errlist [err];
+diff --git a/omapip/iscprint.c b/omapip/iscprint.c
+index de331a1..e3e5e80 100644
+--- a/omapip/iscprint.c
++++ b/omapip/iscprint.c
+@@ -230,7 +230,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+ head = "";
+ tmpui = tmpi;
+ }
+- sprintf(buf, "%u", tmpui);
++ snprintf(buf, sizeof(buf), "%u", tmpui);
+ goto printint;
+ case 'o':
+ if (q)
+@@ -239,7 +239,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+ tmpui = va_arg(ap, long int);
+ else
+ tmpui = va_arg(ap, int);
+- sprintf(buf, alt ? "%#o"
++ snprintf(buf, sizeof(buf), alt ? "%#o"
+ : "%o", tmpui);
+ goto printint;
+ case 'u':
+@@ -249,7 +249,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+ tmpui = va_arg(ap, unsigned long int);
+ else
+ tmpui = va_arg(ap, unsigned int);
+- sprintf(buf, "%u", tmpui);
++ snprintf(buf, sizeof(buf), "%u", tmpui);
+ goto printint;
+ case 'x':
+ if (q)
+@@ -263,7 +263,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+ if (precision > 2)
+ precision -= 2;
+ }
+- sprintf(buf, "%x", tmpui);
++ snprintf(buf, sizeof(buf), "%x", tmpui);
+ goto printint;
+ case 'X':
+ if (q)
+@@ -277,7 +277,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+ if (precision > 2)
+ precision -= 2;
+ }
+- sprintf(buf, "%X", tmpui);
++ snprintf(buf, sizeof(buf), "%X", tmpui);
+ goto printint;
+ printint:
+ if (precision != 0 || width != 0) {
+@@ -403,7 +403,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+ break;
+ case 'p':
+ v = va_arg(ap, void *);
+- sprintf(buf, "%p", v);
++ snprintf(buf, sizeof(buf), "%p", v);
+ length = strlen(buf);
+ if (precision > length)
+ zeropad = precision - length;
+@@ -479,7 +479,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+ */
+ if (precision > 512)
+ precision = 512;
+- sprintf(fmt, "%%%s%s.%lu%s%c", alt ? "#" : "",
++ snprintf(fmt, sizeof(fmt), "%%%s%s.%lu%s%c", alt ? "#" : "",
+ plus ? "+" : space ? " " : "",
+ precision, l ? "L" : "", *format);
+ switch (*format) {
+@@ -491,12 +491,12 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+ #ifdef HAVE_LONG_DOUBLE
+ if (l) {
+ ldbl = va_arg(ap, long double);
+- sprintf(buf, fmt, ldbl);
++ snprintf(buf, sizeof(buf), fmt, ldbl);
+ } else
+ #endif
+ {
+ dbl = va_arg(ap, double);
+- sprintf(buf, fmt, dbl);
++ snprintf(buf, sizeof(buf), fmt, dbl);
+ }
+ length = strlen(buf);
+ if (width > 0) {
+diff --git a/omapip/result.c b/omapip/result.c
+index 2274689..e598e26 100644
+--- a/omapip/result.c
++++ b/omapip/result.c
+@@ -114,6 +114,6 @@ const char *isc_result_totext (isc_result_t result)
+
+ if (result >= ISC_R_SUCCESS && result < ISC_R_NRESULTS)
+ return text [result];
+- sprintf(ebuf, "unknown error: %d", result);
++ snprintf(ebuf, sizeof(ebuf), "unknown error: %d", result);
+ return ebuf;
+ }
+diff --git a/relay/Makefile.dist b/relay/Makefile.dist
+index 8f1da98..b5fc8c4 100644
+--- a/relay/Makefile.dist
++++ b/relay/Makefile.dist
+@@ -83,6 +83,6 @@ dhcrelay.man8: dhcrelay.8
+ -e "s#RUNDIR#$(VARRUN)#" < dhcrelay.8 >dhcrelay.man8
+
+ dhcrelay: dhcrelay.o $(DHCPLIB)
+- $(CC) $(LFLAGS) -o $(PROG) dhcrelay.o $(DHCPLIB) $(LIBS)
++ $(CC) -pie $(LFLAGS) -o $(PROG) dhcrelay.o $(DHCPLIB) $(LIBS) -lcap
+
+ # Dependencies (semi-automatically-generated)
+diff --git a/relay/dhcrelay.8 b/relay/dhcrelay.8
+index 115d8a3..82aff34 100644
+--- a/relay/dhcrelay.8
++++ b/relay/dhcrelay.8
+@@ -77,6 +77,14 @@ dhcrelay - Dynamic Host Configuration Protocol Relay Agent
+ |
+ .I discard
+ ]
++[
++.B -u
++.I user
++]
++[
++.B -j
++.I chroot-dir
++]
+ .I server0
+ [
+ .I ...serverN
+@@ -139,6 +147,11 @@ This can be unhelpful in a system startup script - to disable this
+ behaviour, specify the
+ .B -q
+ flag.
++.PP
++Upon startup, this version of dhcrelay will switch to a non-root
++pseudo-user and enter a chroot jail. The default username (\fIdhcrelay\fR)
++and the default chroot jail directory path (\fI/var/empty\fR)
++may be overridden with the \fB-u\fR and \fB-j\fR options, respectively.
+ .SH RELAY AGENT INFORMATION OPTIONS
+ If the
+ .B -a
+@@ -239,7 +252,12 @@ has been written for Internet Systems Consortium
+ by Ted Lemon in cooperation with Vixie
+ Enterprises. To learn more about Internet Systems Consortium,
+ see
+-.B http://www.isc.org/isc.
++.BR http://www.isc.org/isc .
+ To learn more about Vixie
+ Enterprises, see
+-.B http://www.vix.com.
++.BR http://www.vix.com .
++.PP
++This version of dhcrelay has been modified for ALT Linux
++.RB ( http://www.altlinux.com/ ).
++In particular, the privilege reduction functionality and the \fB-u\fR
++and \fB-j\fR options are Openwall/ALT Linux extensions.
+diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
+index 5d19ec2..3eb629d 100644
+--- a/relay/dhcrelay.c
++++ b/relay/dhcrelay.c
+@@ -106,23 +106,28 @@ int main (argc, argv, envp)
+ int argc;
+ char **argv, **envp;
+ {
+- int i;
++ int i, null_fd;
+ struct servent *ent;
+ struct server_list *sp = (struct server_list *)0;
+ int no_daemon = 0;
+ int quiet = 0;
+ isc_result_t status;
+ char *s;
++ char *server_user = "dhcrelay";
++ char *server_jail = "/var/empty";
+
+ /* Make sure we have stdin, stdout and stderr. */
+- i = open ("/dev/null", O_RDWR);
+- if (i == 0)
+- i = open ("/dev/null", O_RDWR);
+- if (i == 1) {
+- i = open ("/dev/null", O_RDWR);
++ null_fd = open ("/dev/null", O_RDWR);
++ if (null_fd == 0)
++ null_fd = open ("/dev/null", O_RDWR);
++ if (null_fd == 1)
++ null_fd = open ("/dev/null", O_RDWR);
++ if (null_fd == 2) {
++ null_fd = open ("/dev/null", O_RDWR);
+ log_perror = 0; /* No sense logging to /dev/null. */
+- } else if (i != -1)
+- close (i);
++ }
++ if (null_fd < 0)
++ log_fatal ("Can't open %s: %m", "/dev/null");
+
+ #ifdef SYSLOG_4_2
+ openlog ("dhcrelay", LOG_NDELAY);
+@@ -185,6 +190,14 @@ int main (argc, argv, envp)
+ if (++i == argc)
+ usage ();
+ dhcp_max_agent_option_packet_length = atoi (argv [i]);
++ } else if (!strcmp (argv [i], "-u")) {
++ if (++i == argc)
++ usage ();
++ server_user = argv[i];
++ } else if (!strcmp (argv [i], "-j")) {
++ if (++i == argc)
++ usage ();
++ server_jail = argv[i];
+ } else if (!strcmp (argv [i], "-m")) {
+ if (++i == argc)
+ usage ();
+@@ -239,9 +252,9 @@ int main (argc, argv, envp)
+
+ if (!quiet) {
+ log_info ("%s %s", message, DHCP_VERSION);
+- log_info (copyright);
+- log_info (arr);
+- log_info (url);
++ log_info ("%s", copyright);
++ log_info ("%s", arr);
++ log_info ("%s", url);
+ } else {
+ quiet = 0;
+ log_perror = 0;
+@@ -310,12 +323,17 @@ int main (argc, argv, envp)
+ }
+ }
+
+- close (0);
+- close (1);
+- close (2);
++ if (dup2 (null_fd, 0) != 0 ||
++ dup2 (null_fd, 1) != 1 ||
++ dup2 (null_fd, 2) != 2)
++ log_fatal("Can't daemonize: %m");
++ close (null_fd);
++ null_fd = -1;
+ pid = setsid ();
+ }
+
++ dhcpd_priv_drop(server_user, server_jail);
++
+ /* Start dispatching packets and timeouts... */
+ dispatch ();
+
+@@ -455,10 +473,11 @@ void relay (ip, packet, length, from_port, from, hfrom)
+
+ static void usage ()
+ {
+- log_fatal ("Usage: dhcrelay [-p <port>] [-d] [-D] [-i %s%s%s%s",
++ log_fatal ("Usage: dhcrelay [-p <port>] [-d] [-D] [-i %s%s%s%s%s",
+ "interface] [-q] [-a]\n ",
+ "[-c count] [-A length] ",
+ "[-m append|replace|forward|discard]\n",
++ "[-u user] [-j chroot-dir]\n",
+ " [server1 [... serverN]]");
+ }
+
+diff --git a/server/Makefile.dist b/server/Makefile.dist
+index b7d1216..9202441 100644
+--- a/server/Makefile.dist
++++ b/server/Makefile.dist
+@@ -103,6 +103,6 @@ dhcpd.leases.man5: dhcpd.leases.5
+ -e "s#RUNDIR#$(VARRUN)#g" < dhcpd.leases.5 >dhcpd.leases.man5
+
+ dhcpd: $(OBJS) $(COBJ) $(DHCPLIB)
+- $(CC) $(LFLAGS) -o dhcpd $(OBJS) $(DHCPLIB) $(LIBS)
++ $(CC) -pie $(LFLAGS) -o dhcpd $(OBJS) $(DHCPLIB) $(LIBS) -lcap
+
+ # Dependencies (semi-automatically-generated)
+diff --git a/server/confpars.c b/server/confpars.c
+index cb12397..e658edd 100644
+--- a/server/confpars.c
++++ b/server/confpars.c
+@@ -1013,10 +1013,13 @@ void parse_failover_peer (cfile, group, type)
+ parse_warn (cfile, "peer address may not be omitted");
+
+ /* XXX - when/if we get a port number assigned, just set as default */
++ /* See http://bugzilla.redhat.com/show_bug.cgi?id=167292
++ * IANA registration by Bernard Volz <volz at cisco.com>
++ */
+ if (!peer -> me.port)
+- parse_warn (cfile, "local port may not be omitted");
++ peer -> me.port = 647;
+ if (!peer -> partner.port)
+- parse_warn (cfile, "peer port may not be omitted");
++ peer -> partner.port = 847;
+
+ if (peer -> i_am == primary) {
+ if (!peer -> hba) {
+diff --git a/server/db.c b/server/db.c
+index bb0ab86..d1e6c8d 100644
+--- a/server/db.c
++++ b/server/db.c
+@@ -81,7 +81,7 @@ int write_lease (lease)
+ if (lease -> starts != MAX_TIME) {
+ t = gmtime (&lease -> starts);
+ /* %Audit% Cannot exceed 59 bytes. %2004.06.17,Safe% */
+- sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;",
++ snprintf (tbuf, sizeof(tbuf), "%d %d/%02d/%02d %02d:%02d:%02d;",
+ t -> tm_wday, t -> tm_year + 1900,
+ t -> tm_mon + 1, t -> tm_mday,
+ t -> tm_hour, t -> tm_min, t -> tm_sec);
+@@ -98,7 +98,7 @@ int write_lease (lease)
+ if (lease -> ends != MAX_TIME) {
+ t = gmtime (&lease -> ends);
+ /* %Audit% Cannot exceed 59 bytes. %2004.06.17,Safe% */
+- sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;",
++ snprintf (tbuf, sizeof(tbuf), "%d %d/%02d/%02d %02d:%02d:%02d;",
+ t -> tm_wday, t -> tm_year + 1900,
+ t -> tm_mon + 1, t -> tm_mday,
+ t -> tm_hour, t -> tm_min, t -> tm_sec);
+diff --git a/server/ddns.c b/server/ddns.c
+index 7c2df4b..1459a4c 100644
+--- a/server/ddns.c
++++ b/server/ddns.c
+@@ -499,7 +499,7 @@ int ddns_updates (struct packet *packet,
+ ddns_rev_name.data = ddns_rev_name.buffer -> data;
+
+ /* %Audit% Cannot exceed 17 bytes. %2004.06.17,Safe% */
+- sprintf ((char *)ddns_rev_name.buffer -> data,
++ snprintf ((char *)ddns_rev_name.buffer -> data, 17,
+ "%u.%u.%u.%u.",
+ lease -> ip_addr . iabuf[3] & 0xff,
+ lease -> ip_addr . iabuf[2] & 0xff,
+diff --git a/server/dhcp.c b/server/dhcp.c
+index f502b19..3dcb49d 100644
+--- a/server/dhcp.c
++++ b/server/dhcp.c
+@@ -81,7 +81,7 @@ void dhcp (packet)
+ s = dhcp_type_names [packet -> packet_type - 1];
+ } else {
+ /* %Audit% Cannot exceed 28 bytes. %2004.06.17,Safe% */
+- sprintf (typebuf, "type %d", packet -> packet_type);
++ snprintf (typebuf, sizeof(typebuf), "type %d", packet -> packet_type);
+ s = typebuf;
+ }
+
+@@ -447,7 +447,7 @@ void dhcprequest (packet, ms_nulltp, ip_lease)
+ /* piaddr() should not return more than a 15 byte string.
+ * safe.
+ */
+- sprintf (smbuf, " (%s)", piaddr (sip));
++ snprintf (smbuf, sizeof(smbuf), " (%s)", piaddr (sip));
+ have_server_identifier = 1;
+ } else
+ smbuf [0] = 0;
+@@ -1800,6 +1800,8 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
+ host_reference (&host, h, MDL);
+ }
+ if (!host) {
++ if (hp)
++ host_dereference (&hp, MDL);
+ find_hosts_by_haddr (&hp,
+ packet -> raw -> htype,
+ packet -> raw -> chaddr,
+diff --git a/server/dhcpd.8 b/server/dhcpd.8
+index b63336a..8ff7b50 100644
+--- a/server/dhcpd.8
++++ b/server/dhcpd.8
+@@ -74,6 +74,14 @@ dhcpd - Dynamic Host Configuration Protocol Server
+ .I trace-playback-file
+ ]
+ [
++.B -u
++.I user
++]
++[
++.B -j
++.I chroot-dir
++]
++[
+ .I if0
+ [
+ .I ...ifN
+@@ -239,6 +247,12 @@ using the \fB-lf\fR switch, so that the DHCP server doesn't wipe out
+ your existing lease file with its test data. The DHCP server will
+ refuse to operate in playback mode unless you specify an alternate
+ lease file.
++.PP
++Upon startup, this version of the DHCP server will switch to a non-root
++pseudo-user and enter a chroot jail. The default username (\fIdhcpd\fR)
++and the default chroot jail directory path (\fI/var/lib/dhcp/dhcpd\fR)
++may be overridden with the \fB-u\fR and \fB-j\fR options, respectively.
++.PP
+ .SH CONFIGURATION
+ The syntax of the dhcpd.conf(5) file is discussed separately. This
+ section should be used as an overview of the configuration process,
+@@ -746,3 +760,8 @@ Consortium. Version 3 of the DHCP server was funded by Nominum, Inc.
+ Information about Internet Systems Consortium is available at
+ .B http://www.isc.org/\fR.
+ Information about Nominum can be found at \fBhttp://www.nominum.com/\fR.
++.PP
++This version of dhcpd has been modified for ALT Linux
++.RB ( http://www.altlinux.com/ ).
++In particular, the privilege reduction functionality and the \fB-u\fR
++and \fB-j\fR options are Openwall/ALT Linux extensions.
+diff --git a/server/dhcpd.c b/server/dhcpd.c
+index 8deb8d0..977df25 100644
+--- a/server/dhcpd.c
++++ b/server/dhcpd.c
+@@ -197,7 +197,7 @@ int main (argc, argv, envp)
+ int argc;
+ char **argv, **envp;
+ {
+- int i, status;
++ int i, status, null_fd;
+ struct servent *ent;
+ char *s;
+ int cftest = 0;
+@@ -224,16 +224,21 @@ int main (argc, argv, envp)
+ char *traceinfile = (char *)0;
+ char *traceoutfile = (char *)0;
+ #endif
++ char *server_user = "dhcpd";
++ char *server_jail = "/var/lib/dhcp/dhcpd";
+
+ /* Make sure we have stdin, stdout and stderr. */
+- status = open ("/dev/null", O_RDWR);
+- if (status == 0)
+- status = open ("/dev/null", O_RDWR);
+- if (status == 1) {
+- status = open ("/dev/null", O_RDWR);
++ null_fd = open ("/dev/null", O_RDWR);
++ if (null_fd == 0)
++ null_fd = open ("/dev/null", O_RDWR);
++ if (null_fd == 1)
++ null_fd = open ("/dev/null", O_RDWR);
++ if (null_fd == 2) {
++ null_fd = open ("/dev/null", O_RDWR);
+ log_perror = 0; /* No sense logging to /dev/null. */
+- } else if (status != -1)
+- close (status);
++ }
++ if (null_fd < 0)
++ log_fatal ("Can't open %s: %m", "/dev/null");
+
+ /* Set up the client classification system. */
+ classification_setup ();
+@@ -319,6 +324,14 @@ int main (argc, argv, envp)
+ } else if (!strcmp (argv [i], "-q")) {
+ quiet = 1;
+ quiet_interface_discovery = 1;
++ } else if (!strcmp (argv [i], "-u")) {
++ if (++i == argc)
++ usage();
++ server_user = argv[i];
++ } else if (!strcmp (argv [i], "-j")) {
++ if (++i == argc)
++ usage();
++ server_jail = argv[i];
+ } else if (!strcmp (argv [i], "--version")) {
+ log_info ("isc-dhcpd-%s", DHCP_VERSION);
+ exit (0);
+@@ -366,9 +379,9 @@ int main (argc, argv, envp)
+
+ if (!quiet) {
+ log_info ("%s %s", message, DHCP_VERSION);
+- log_info (copyright);
+- log_info (arr);
+- log_info (url);
++ log_info ("%s", copyright);
++ log_info ("%s", arr);
++ log_info ("%s", url);
+ } else {
+ quiet = 0;
+ log_perror = 0;
+@@ -498,12 +511,6 @@ int main (argc, argv, envp)
+
+ group_write_hook = group_writer;
+
+- /* Start up the database... */
+- db_startup (lftest);
+-
+- if (lftest)
+- exit (0);
+-
+ /* Discover all the network interfaces and initialize them. */
+ discover_interfaces (DISCOVER_SERVER);
+
+@@ -524,7 +531,6 @@ int main (argc, argv, envp)
+ #if defined (TRACING)
+ trace_seed_stash (trace_srandom, seed + cur_time);
+ #endif
+- postdb_startup ();
+
+ #ifndef DEBUG
+ if (daemon) {
+@@ -555,14 +561,18 @@ int main (argc, argv, envp)
+
+ /* Write new pid file. */
+ if ((i = open(path_dhcpd_pid, O_WRONLY|O_CREAT|O_TRUNC, 0644)) >= 0) {
+- sprintf(pbuf, "%d\n", (int) getpid());
+- write(i, pbuf, strlen(pbuf));
++ snprintf(pbuf, sizeof(pbuf), "%d\n", (int) getpid());
++ if (write(i, pbuf, strlen(pbuf)) != strlen(pbuf))
++ log_fatal("Error writing pid file: %s: %m",
++ path_dhcpd_pid);
+ close(i);
+ } else {
+ log_error("Can't create PID file %s: %m.", path_dhcpd_pid);
+ }
+
+
++ dhcpd_priv_minimize (server_user, server_jail);
++
+ /* If we were requested to log to stdout on the command line,
+ keep doing so; otherwise, stop. */
+ if (log_perror == -1)
+@@ -572,11 +582,25 @@ int main (argc, argv, envp)
+
+ if (daemon) {
+ /* Become session leader and get pid... */
+- close (0);
+- close (1);
+- close (2);
++ if (dup2 (null_fd, 0) != 0 ||
++ dup2 (null_fd, 1) != 1 ||
++ dup2 (null_fd, 2) != 2)
++ log_fatal("Can't daemonize: %m");
++ close (null_fd);
++ null_fd = -1;
+ pid = setsid ();
+ }
++
++ /* Start up the database... */
++ db_startup (lftest);
++
++ if (lftest)
++ exit (0);
++
++ postdb_startup ();
++
++ dhcpd_priv_drop (server_user, server_jail);
++
+ #endif /* !DEBUG */
+
+ #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
+@@ -788,9 +812,9 @@ void postconf_initialization (int quiet)
+ log_perror = 0;
+ log_info ("%s %s",
+ message, DHCP_VERSION);
+- log_info (copyright);
+- log_info (arr);
+- log_info (url);
++ log_info ("%s", copyright);
++ log_info ("%s", arr);
++ log_info ("%s", url);
+ log_perror = tmp;
+ }
+ } else
+@@ -862,11 +886,12 @@ void postdb_startup (void)
+ static void usage ()
+ {
+ log_info ("%s %s", message, DHCP_VERSION);
+- log_info (copyright);
+- log_info (arr);
++ log_info ("%s", copyright);
++ log_info ("%s", arr);
+
+- log_fatal ("Usage: dhcpd [-p <UDP port #>] [-d] [-f]%s%s%s%s",
++ log_fatal ("Usage: dhcpd [-p <UDP port #>] [-d] [-f]%s%s%s%s%s",
+ "\n [-cf config-file] [-lf lease-file]",
++ "\n [-u user] [-j chroot-dir]",
+ #if defined (TRACING)
+ "\n [-tf trace-output-file]",
+ "\n [-play trace-input-file]",
+diff --git a/server/dhcpd.conf.5 b/server/dhcpd.conf.5
+index 04afd4e..ad29ebb 100644
+--- a/server/dhcpd.conf.5
++++ b/server/dhcpd.conf.5
+@@ -531,9 +531,9 @@ primary server might look like this:
+ failover peer "foo" {
+ primary;
+ address anthrax.rc.vix.com;
+- port 519;
++ port 647;
+ peer address trantor.rc.vix.com;
+- peer port 520;
++ peer port 847;
+ max-response-delay 60;
+ max-unacked-updates 10;
+ mclt 3600;
+@@ -592,9 +592,7 @@ statement
+ .B port \fIport-number\fR\fB;\fR
+ .PP
+ The \fBport\fR statement declares the TCP port on which the server
+-should listen for connections from its failover peer. This statement
+-may not currently be omitted, because the failover protocol does not
+-yet have a reserved TCP port number.
++should listen for connections from its failover peer.
+ .RE
+ .PP
+ The
+@@ -606,10 +604,8 @@ statement
+ .PP
+ The \fBpeer port\fR statement declares the TCP port to which the
+ server should connect to reach its failover peer for failover
+-messages. This statement may not be omitted because the failover
+-protocol does not yet have a reserved TCP port number. The port
+-number declared in the \fBpeer port\fR statement may be the same as
+-the port number declared in the \fBport\fR statement.
++messages. The port number declared in the \fBpeer port\fR statement
++may be the same as the port number declared in the \fBport\fR statement.
+ .RE
+ .PP
+ The
+@@ -2038,8 +2034,8 @@ The syntax of the \fIsyslog.conf\fR file may be different on some
+ operating systems - consult the \fIsyslog.conf\fR manual page to be
+ sure. To get syslog to start logging to the new file, you must first
+ create the file with correct ownership and permissions (usually, the
+-same owner and permissions of your /var/log/messages or
+-/usr/adm/messages file should be fine) and send a SIGHUP to syslogd.
++same owner and permissions of your /var/log/messages
++file should be fine) and send a SIGHUP to syslogd.
+ Some systems support log rollover using a shell script or program
+ called newsyslog or logrotate, and you may be able to configure this
+ as well so that your log file doesn't grow uncontrollably.
+@@ -2114,7 +2110,8 @@ statement
+ The \fInext-server\fR statement is used to specify the host address of
+ the server from which the initial boot file (specified in the
+ \fIfilename\fR statement) is to be loaded. \fIServer-name\fR should
+-be a numeric IP address or a domain name.
++be a numeric IP address or a domain name. If no \fInext-server\fR
++statement applies to a given client, the address 0.0.0.0 is used.
+ .RE
+ .PP
+ The
+diff --git a/server/failover.c b/server/failover.c
+index 1be6c04..8dca575 100644
+--- a/server/failover.c
++++ b/server/failover.c
+@@ -3615,7 +3615,7 @@ failover_option_t *dhcp_failover_make_option (unsigned code,
+ val = va_arg (va, unsigned);
+ #if defined (DEBUG_FAILOVER_MESSAGES)
+ /* %Audit% Cannot exceed 24 bytes. %2004.06.17,Safe% */
+- sprintf (tbuf, " %d", val);
++ snprintf (tbuf, sizeof(tbuf), " %d", val);
+ failover_print (obuf, obufix, obufmax, tbuf);
+ #endif
+ option.data [i + 4] = val;
+@@ -3635,7 +3635,7 @@ failover_option_t *dhcp_failover_make_option (unsigned code,
+
+ #if defined (DEBUG_FAILOVER_MESSAGES)
+ /*%Audit% Cannot exceed 17 bytes. %2004.06.17,Safe%*/
+- sprintf (tbuf, " %u.%u.%u.%u",
++ snprintf (tbuf, sizeof(tbuf), " %u.%u.%u.%u",
+ iaddr [0], iaddr [1], iaddr [2], iaddr [3]);
+ failover_print (obuf, obufix, obufmax, tbuf);
+ #endif
+@@ -3648,7 +3648,7 @@ failover_option_t *dhcp_failover_make_option (unsigned code,
+ val = va_arg (va, unsigned);
+ #if defined (DEBUG_FAILOVER_MESSAGES)
+ /*%Audit% Cannot exceed 24 bytes. %2004.06.17,Safe%*/
+- sprintf (tbuf, " %d", val);
++ snprintf (tbuf, sizeof(tbuf), " %d", val);
+ failover_print (obuf, obufix, obufmax, tbuf);
+ #endif
+ putULong (&option.data [4 + i * 4], val);
+@@ -3661,7 +3661,7 @@ failover_option_t *dhcp_failover_make_option (unsigned code,
+ #if defined (DEBUG_FAILOVER_MESSAGES)
+ for (i = 0; i < count; i++) {
+ /* 23 bytes plus nul, safe. */
+- sprintf (tbuf, " %d", bval [i]);
++ snprintf (tbuf, sizeof(tbuf), " %d", bval [i]);
+ failover_print (obuf, obufix, obufmax, tbuf);
+ }
+ #endif
+@@ -3699,7 +3699,7 @@ failover_option_t *dhcp_failover_make_option (unsigned code,
+ #if defined (DEBUG_FAILOVER_MESSAGES)
+ for (i = 4; i < size; i++) {
+ /*%Audit% Cannot exceed 24 bytes. %2004.06.17,Safe%*/
+- sprintf (tbuf, " %d", option.data [i]);
++ snprintf (tbuf, sizeof(tbuf), " %d", option.data [i]);
+ failover_print (obuf, obufix, obufmax, tbuf);
+ }
+ #endif
+@@ -3710,7 +3710,7 @@ failover_option_t *dhcp_failover_make_option (unsigned code,
+ val = va_arg (va, u_int32_t);
+ #if defined (DEBUG_FAILOVER_MESSAGES)
+ /*%Audit% Cannot exceed 24 bytes. %2004.06.17,Safe%*/
+- sprintf (tbuf, " %d", val);
++ snprintf (tbuf, sizeof(tbuf), " %d", val);
+ failover_print (obuf, obufix, obufmax, tbuf);
+ #endif
+ putUShort (&option.data [4 + i * 2], val);
+diff --git a/server/omapi.c b/server/omapi.c
+index c87f05b..f807c5d 100644
+--- a/server/omapi.c
++++ b/server/omapi.c
+@@ -1186,7 +1186,7 @@ isc_result_t dhcp_host_signal_handler (omapi_object_t *h,
+
+ if (!host -> name) {
+ char hnbuf [64];
+- sprintf (hnbuf, "nh%08lx%08lx",
++ snprintf (hnbuf, sizeof(hnbuf), "nh%08lx%08lx",
+ (unsigned long)cur_time, (unsigned long)host);
+ host -> name = dmalloc (strlen (hnbuf) + 1, MDL);
+ if (!host -> name)
diff --git a/net-misc/dhcp/files/dhcp-3.0-paranoia.patch b/net-misc/dhcp/files/dhcp-3.0-paranoia.patch
index 886f5cb..a461863 100644
--- a/net-misc/dhcp/files/dhcp-3.0-paranoia.patch
+++ b/net-misc/dhcp/files/dhcp-3.0-paranoia.patch
@@ -37,8 +37,8 @@ ari edelkind (12/10/2001)
last modified 12/10/2001
---- dhcp-3.0/server/dhcpd.c Thu Jun 21 22:12:58 2001
-+++ dhcp-3.0+paranoia/server/dhcpd.c Wed Oct 17 08:23:00 2001
+--- server/dhcpd.c Thu Jun 21 22:12:58 2001
++++ server/dhcpd.c Wed Oct 17 08:23:00 2001
@@ -56,6 +56,16 @@
#include "version.h"
#include <omapip/omapip_p.h>
diff --git a/net-misc/dhcp/files/dhcp-3.0.3-no_isc_blurb.patch b/net-misc/dhcp/files/dhcp-3.0.3-no_isc_blurb.patch
index 38f7713..1b894fa 100644
--- a/net-misc/dhcp/files/dhcp-3.0.3-no_isc_blurb.patch
+++ b/net-misc/dhcp/files/dhcp-3.0.3-no_isc_blurb.patch
@@ -1,8 +1,8 @@
Patch nobbled from RedHat, and adapted to work with dhclient and dhrelay
by Roy Marples <uberlord@gentoo.org>
---- dhcp-3.0.3/omapip/errwarn.c.no_isc_blurb 2004-09-30 16:38:32.000000000 -0400
-+++ dhcp-3.0.3/omapip/errwarn.c 2005-04-18 13:45:49.037158000 -0400
+--- omapip/errwarn.c 2004-09-30 16:38:32.000000000 -0400
++++ omapip/errwarn.c 2005-04-18 13:45:49.037158000 -0400
@@ -45,6 +45,8 @@
int log_perror = 1;
#endif
@@ -36,8 +36,8 @@ by Roy Marples <uberlord@gentoo.org>
if (log_cleanup)
(*log_cleanup) ();
exit (1);
---- dhcp-3.0.3/client/dhclient.c.no_isc_blurb 2005-04-18 13:21:08.509169000 -0400
-+++ dhcp-3.0.3/client/dhclient.c 2005-04-18 13:49:27.574402000 -0400
+--- client/dhclient.c 2005-04-18 13:21:08.509169000 -0400
++++ client/dhclient.c 2005-04-18 13:49:27.574402000 -0400
@@ -34,7 +34,7 @@
static char ocopyright[] =
"$Id: dhcp-3.0.3-no_isc_blurb.patch,v 1.1 2005/12/09 14:13:30 uberlord Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
@@ -64,8 +64,8 @@ by Roy Marples <uberlord@gentoo.org>
} else if (!strcmp (argv [i], "-s")) {
if (++i == argc)
usage ();
---- dhcp-3.0.3/server/dhcpd.c.no_isc_blurb 2005-12-08 10:01:40.000000000 +0000
-+++ dhcp-3.0.3/server/dhcpd.c 2005-12-08 10:05:55.000000000 +0000
+--- server/dhcpd.c 2005-12-08 10:01:40.000000000 +0000
++++ server/dhcpd.c 2005-12-08 10:05:55.000000000 +0000
@@ -62,6 +62,9 @@
struct iaddr server_identifier;
int server_identifier_matched;
@@ -84,8 +84,8 @@ by Roy Marples <uberlord@gentoo.org>
} else if (!strcmp (argv [i], "--version")) {
log_info ("isc-dhcpd-%s", DHCP_VERSION);
exit (0);
---- dhcp-3.0.3/relay/dhcrelay.c.no_isc_blurb 2005-12-08 10:21:00.000000000 +0000
-+++ dhcp-3.0.3/relay/dhcrelay.c 2005-12-08 10:21:50.000000000 +0000
+--- relay/dhcrelay.c 2005-12-08 10:21:00.000000000 +0000
++++ relay/dhcrelay.c 2005-12-08 10:21:50.000000000 +0000
@@ -102,6 +102,8 @@
static char message [] = "Internet Systems Consortium DHCP Relay Agent";
static char url [] = "For info, please visit http://www.isc.org/sw/dhcp/";
diff --git a/net-misc/dhcp/files/dhcp-3.0.3-x-option.patch b/net-misc/dhcp/files/dhcp-3.0.3-x-option.patch
index 5f5c1a8..cc15838 100644
--- a/net-misc/dhcp/files/dhcp-3.0.3-x-option.patch
+++ b/net-misc/dhcp/files/dhcp-3.0.3-x-option.patch
@@ -1,5 +1,5 @@
---- dhcp-3.0.2/common/parse.c.extended_option_environment 2005-04-05 17:49:36.513062562 -0400
-+++ dhcp-3.0.2/common/parse.c 2005-04-05 17:49:36.580052656 -0400
+--- common/parse.c 2005-04-05 17:49:36.513062562 -0400
++++ common/parse.c 2005-04-05 17:49:36.580052656 -0400
@@ -1270,6 +1270,10 @@
option_hash_add (option -> universe -> hash,
(const char *)option -> name,
@@ -11,8 +11,8 @@
return 1;
}
---- dhcp-3.0.2/common/tables.c.extended_option_environment 2004-09-01 13:06:35.000000000 -0400
-+++ dhcp-3.0.2/common/tables.c 2005-04-05 18:04:23.915838623 -0400
+--- common/tables.c 2004-09-01 13:06:35.000000000 -0400
++++ common/tables.c 2005-04-05 18:04:23.915838623 -0400
@@ -1238,3 +1238,40 @@
fqdn_universe.name, 0,
&fqdn_universe, MDL);
@@ -54,8 +54,8 @@
+ return tfind( option, &(new_option_info_tree), new_option_info_comparator );
+}
+#endif
---- dhcp-3.0.2/includes/dhcpd.h.extended_option_environment 2004-11-24 12:39:16.000000000 -0500
-+++ dhcp-3.0.2/includes/dhcpd.h 2005-04-05 17:49:36.613047777 -0400
+--- includes/dhcpd.h 2004-11-24 12:39:16.000000000 -0500
++++ includes/dhcpd.h 2005-04-05 17:49:36.613047777 -0400
@@ -1800,6 +1800,13 @@
void initialize_common_option_spaces PROTO ((void));
struct universe *config_universe;
@@ -70,8 +70,8 @@
/* stables.c */
#if defined (FAILOVER_PROTOCOL)
extern failover_option_t null_failover_option;
---- dhcp-3.0.2/client/dhclient.c.extended_option_environment 2005-04-05 17:49:36.566054726 -0400
-+++ dhcp-3.0.2/client/dhclient.c 2005-04-05 17:49:36.617047185 -0400
+--- client/dhclient.c 2005-04-05 17:49:36.566054726 -0400
++++ client/dhclient.c 2005-04-05 17:49:36.617047185 -0400
@@ -74,7 +74,9 @@
int onetry=0;
int quiet=0;
@@ -191,8 +191,8 @@
}
++i;
} while (i != 2);
---- dhcp-3.0.2/client/dhclient.8.extended_option_environment 2004-09-29 19:01:46.000000000 -0400
-+++ dhcp-3.0.2/client/dhclient.8 2005-04-05 17:49:36.619046889 -0400
+--- client/dhclient.8 2004-09-29 19:01:46.000000000 -0400
++++ client/dhclient.8 2005-04-05 17:49:36.619046889 -0400
@@ -78,6 +78,9 @@
.B -w
]
diff --git a/net-misc/dhcp/files/dhcp-3.0.4-dhclient-stdin-conf.patch b/net-misc/dhcp/files/dhcp-3.0.4-dhclient-stdin-conf.patch
index 3fedc7c..1c27447 100644
--- a/net-misc/dhcp/files/dhcp-3.0.4-dhclient-stdin-conf.patch
+++ b/net-misc/dhcp/files/dhcp-3.0.4-dhclient-stdin-conf.patch
@@ -1,4 +1,4 @@
---- common/conflex.c.orig 2006-02-21 16:21:45.000000000 +0000
+--- common/conflex.c 2006-02-21 16:21:45.000000000 +0000
+++ common/conflex.c 2006-02-21 16:23:06.000000000 +0000
@@ -90,7 +90,7 @@
struct parse **cfile;
@@ -9,7 +9,7 @@
close((*cfile)->file);
if ((*cfile)->bufsiz)
---- client/clparse.c.orig 2006-02-22 09:37:12.000000000 +0000
+--- client/clparse.c 2006-02-22 09:37:12.000000000 +0000
+++ client/clparse.c 2006-02-22 09:38:26.000000000 +0000
@@ -97,6 +97,11 @@
status = read_client_conf_file (path_dhclient_conf,
diff --git a/net-misc/dhcp/files/dhcp-3.0.5-bpf-nofallback.patch b/net-misc/dhcp/files/dhcp-3.0.5-bpf-nofallback.patch
index 2fae6f2..da52dcc 100644
--- a/net-misc/dhcp/files/dhcp-3.0.5-bpf-nofallback.patch
+++ b/net-misc/dhcp/files/dhcp-3.0.5-bpf-nofallback.patch
@@ -1,5 +1,4 @@
-diff -ur common.orig/bpf.c common/bpf.c
---- common.orig/bpf.c 2006-09-20 12:52:47 +0100
+--- common/bpf.c 2006-09-20 12:52:47 +0100
+++ common/bpf.c 2006-09-20 12:53:22 +0100
@@ -354,10 +354,6 @@
int result;
@@ -30,8 +29,7 @@ diff -ur common.orig/bpf.c common/bpf.c
- }
}
#endif
-diff -ur includes.orig/osdep.h includes/osdep.h
---- includes.orig/osdep.h 2006-09-20 12:54:52 +0100
+--- includes/osdep.h 2006-09-20 12:54:52 +0100
+++ includes/osdep.h 2006-09-20 12:56:40 +0100
@@ -190,7 +190,7 @@
Currently, all low-level packet interfaces use BSD sockets as a
diff --git a/net-misc/dhcp/files/dhcp-3.0.5-ldap-patch b/net-misc/dhcp/files/dhcp-3.0.5-ldap.patch
index 36cbecf..2e85437 100644
--- a/net-misc/dhcp/files/dhcp-3.0.5-ldap-patch
+++ b/net-misc/dhcp/files/dhcp-3.0.5-ldap.patch
@@ -1,7 +1,43 @@
diff -Naur dhcp-3.0.5/Changelog-LDAP dhcp-3.0.5-ldap/Changelog-LDAP
--- dhcp-3.0.5/Changelog-LDAP 1969-12-31 19:00:00.000000000 -0500
-+++ dhcp-3.0.5-ldap/Changelog-LDAP 2006-12-14 12:32:33.000000000 -0500
-@@ -0,0 +1,215 @@
++++ dhcp-3.0.5-ldap/Changelog-LDAP 2007-02-23 14:06:33.000000000 -0500
+@@ -0,0 +1,251 @@
++2007-2-23 Brian Masney <masneyb@ntelos.net>
++ * contrib/dhcpd-conf-to-ldap.pl - fixed a parsing bug in which
++ didn't handle correctly quoted string containing spaces.
++ (Rapha?l Luta <raphael.luta@aptiwan.com>)
++
++ * dst/Makefile.dist server/Makefile.dist site.conf - updated build
++ method when using -lssl.
++ (from Marius Tomaschewski <mt@suse.de>)
++
++ * server/ldap.c - fix for ldap_read_function to avoid returning
++ empty strings (skipped host declaration from ldap) that are causing
++ parsing errors in ldap-dynamic mode.
++ (from Marius Tomaschewski <mt@suse.de>)
++
++ * includes/dhcpd.h README.ldap server/dhcpd.c server/ldap.c
++ server/stables.c - added ldap-ssl <off|start_tls|ldaps|on> option and
++ several ldap-tls* options, that are described in the "man ldap.conf".
++ (from Marius Tomaschewski <mt@suse.de>)
++
++ * includes/dhcpd.h server/ldap.c server/stables.c - added ldap-referrals
++ <on|off> option. Also implemented a LDAP rebuind function
++ (from Kalyan <skalyanasundaram@novell.com>)
++
++ * includes/dhcpd.h server/ldap.c server/stables.c - renamed dhcpd.conf
++ option ldap-server-cn to ldap-dhcp-server-cn
++ (from Marius Tomaschewski <mt@suse.de>)
++
++ * contrib/dhcp.schema - schema updates
++ (from Kalyan <skalyanasundaram@novell.com>)
++
++ * server/ldap.c server/ldap_casa.c - CASA support fixes
++ (from Marius Tomaschewski <mt@suse.de>)
++
++ * server/ldap.c - added strncat() fix
++ (from Marius Tomaschewski <mt@suse.de>)
++
+2006-12-15 Brian Masney <masneyb@ntelos.net>
+ * server/ldap.c (ldap_read_config) - unbind from the LDAP server after
+ the config file has been ran if the server is being ran in static mode
@@ -219,8 +255,8 @@ diff -Naur dhcp-3.0.5/Changelog-LDAP dhcp-3.0.5-ldap/Changelog-LDAP
+
diff -Naur dhcp-3.0.5/README.ldap dhcp-3.0.5-ldap/README.ldap
--- dhcp-3.0.5/README.ldap 1969-12-31 19:00:00.000000000 -0500
-+++ dhcp-3.0.5-ldap/README.ldap 2006-12-14 10:03:41.000000000 -0500
-@@ -0,0 +1,172 @@
++++ dhcp-3.0.5-ldap/README.ldap 2007-02-23 13:13:36.000000000 -0500
+@@ -0,0 +1,190 @@
+LDAP Support in DHCP
+Brian Masney <masneyb@ntelos.net>
+Last updated 3/23/2003
@@ -266,6 +302,7 @@ diff -Naur dhcp-3.0.5/README.ldap dhcp-3.0.5-ldap/README.ldap
+SSL, you will need to perform the following steps:
+
+ * Edit the includes/site.h file and uncomment the USE_SSL line
++ or specify "-DUSE_SSL" via CFLAGS.
+ * Edit the dst/Makefile.dist file and remove md5_dgst.c and md5_dgst.o
+ from the SRC= and OBJ= lines (around line 24)
+ * Now run configure in the base source directory. If you chose to enable
@@ -287,6 +324,23 @@ diff -Naur dhcp-3.0.5/README.ldap dhcp-3.0.5-ldap/README.ldap
+ldap-method dynamic;
+ldap-debug-file "/var/log/dhcp-ldap-startup.log";
+
++If SSL has been enabled at compile time using the USE_SSL flag, the dhcp
++server trys to use TLS if possible, but continues without TLS if not.
++
++You can modify this behaviour using following option in /etc/dhcpd.conf:
++
++ldap-ssl <off | ldaps | start_tls | on>
++ off: disables TLS/LDAPS.
++ ldaps: enables LDAPS -- don't forget to set ldap-port to 636.
++ start_tls: enables TLS using START_TLS command
++ on: enables LDAPS if ldap-port is set to 636 or TLS in
++ other cases.
++
++See also "man 5 ldap.conf" for description the following TLS related
++options:
++ ldap-tls-reqcert, ldap-tls-ca-file, ldap-tls-ca-dir, ldap-tls-cert
++ ldap-tls-key, ldap-tls-crlcheck, ldap-tls-ciphers, ldap-tls-randfile
++
+All of these parameters should be self explanatory except for the ldap-method.
+You can set this to static or dynamic. If you set it to static, the
+configuration is read once on startup, and LDAP isn't used anymore. But, if you
@@ -486,8 +540,8 @@ diff -Naur dhcp-3.0.5/common/print.c dhcp-3.0.5-ldap/common/print.c
char *s;
diff -Naur dhcp-3.0.5/contrib/dhcp.schema dhcp-3.0.5-ldap/contrib/dhcp.schema
--- dhcp-3.0.5/contrib/dhcp.schema 1969-12-31 19:00:00.000000000 -0500
-+++ dhcp-3.0.5-ldap/contrib/dhcp.schema 2006-12-14 10:03:41.000000000 -0500
-@@ -0,0 +1,467 @@
++++ dhcp-3.0.5-ldap/contrib/dhcp.schema 2007-02-23 12:53:22.000000000 -0500
+@@ -0,0 +1,462 @@
+attributetype ( 2.16.840.1.113719.1.203.4.1
+ NAME 'dhcpPrimaryDN'
+ EQUALITY distinguishedNameMatch
@@ -758,73 +812,67 @@ diff -Naur dhcp-3.0.5/contrib/dhcp.schema dhcp-3.0.5-ldap/contrib/dhcp.schema
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+attributetype ( 2.16.840.1.113719.1.203.4.46
-+ NAME 'dhcpFailOverRole'
++ NAME 'dhcpFailOverPrimaryServer'
+ EQUALITY caseIgnoreIA5Match
-+ DESC 'Role of the DHCP Server. Either primary or secondary'
++ DESC 'IP address or DNS name of the server playing primary role in DHC Load Balancing and Fail over.'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 2.16.840.1.113719.1.203.4.47
-+ NAME 'dhcpFailOverReceiveAddress'
-+ EQUALITY caseIgnoreIA5Match
-+ DESC 'IP address or DNS name on which the server should listen for connections from its fail over peer'
-+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
-+
-+attributetype ( 2.16.840.1.113719.1.203.4.48
-+ NAME 'dhcpFailOverPeerAddress'
++ NAME 'dhcpFailOverSecondaryServer'
+ EQUALITY caseIgnoreIA5Match
-+ DESC 'IP address or DNS name to which the server should connect to reach its fail over peer'
++ DESC 'IP address or DNS name of the server playing secondary role in DHC Load Balancing and Fail over.'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
-+attributetype ( 2.16.840.1.113719.1.203.4.49
-+ NAME 'dhcpFailOverPeerPort'
++attributetype ( 2.16.840.1.113719.1.203.4.48
++ NAME 'dhcpFailOverPrimaryPort'
+ EQUALITY integerMatch
-+ DESC 'Port to which server should connect to reach its fail over peer'
++ DESC 'Port on which primary server listens for connections from its fail over peer (secondary server)'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
-+attributetype ( 2.16.840.1.113719.1.203.4.50
-+ NAME 'dhcpFailOverReceivePort'
++attributetype ( 2.16.840.1.113719.1.203.4.49
++ NAME 'dhcpFailOverSecondaryPort'
+ EQUALITY integerMatch
-+ DESC 'Port on which server should listen for connections from its fail over peer'
++ DESC 'Port on which secondary server listens for connections from its fail over peer (primary server)'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
-+attributetype ( 2.16.840.1.113719.1.203.4.51
++attributetype ( 2.16.840.1.113719.1.203.4.50
+ NAME 'dhcpFailOverResponseDelay'
+ EQUALITY integerMatch
+ DESC 'Maximum response time in seconds, before Server assumes that connection to fail over peer has failed'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
-+attributetype ( 2.16.840.1.113719.1.203.4.52
-+ NAME 'dhcpFailOverUnpackedUpdates'
++attributetype ( 2.16.840.1.113719.1.203.4.51
++ NAME 'dhcpFailOverUnackedUpdates'
+ EQUALITY integerMatch
+ DESC 'Number of BNDUPD messages that server can send before it receives BNDACK from its fail over peer'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
-+attributetype ( 2.16.840.1.113719.1.203.4.53
++attributetype ( 2.16.840.1.113719.1.203.4.52
+ NAME 'dhcpFailOverSplit'
+ EQUALITY integerMatch
+ DESC 'Split between the primary and secondary servers for fail over purpose'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
-+attributetype ( 2.16.840.1.113719.1.203.4.54
++attributetype ( 2.16.840.1.113719.1.203.4.53
+ NAME 'dhcpFailOverLoadBalanceTime'
+ EQUALITY integerMatch
+ DESC 'Cutoff time in seconds, after which load balance is disabled'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
-+attributetype ( 2.16.840.1.113719.1.203.4.55
++attributetype ( 2.16.840.1.113719.1.203.4.54
+ NAME 'dhcpFailOverPeerDN'
+ EQUALITY distinguishedNameMatch
+ DESC 'The DNs of Fail over peers. In case of locator object, this will be list of fail over peers in the tree. In case of Subnet and pool, it will be a single Fail Over Peer'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
+#List of all servers in the tree
-+attributetype ( 2.16.840.1.113719.1.203.4.56
++attributetype ( 2.16.840.1.113719.1.203.4.55
+ NAME 'dhcpServerDN'
+ EQUALITY distinguishedNameMatch
+ DESC 'List of all DHCP Servers in the tree. Used by dhcpLocatorObject'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
+
-+attributetype ( 2.16.840.1.113719.1.203.4.57
++attributetype ( 2.16.840.1.113719.1.203.4.56
+ NAME 'dhcpComments'
+ EQUALITY caseIgnoreIA5Match
+ DESC 'Generic attribute that allows coments within any DHCP object'
@@ -905,7 +953,7 @@ diff -Naur dhcp-3.0.5/contrib/dhcp.schema dhcp-3.0.5-ldap/contrib/dhcp.schema
+ DESC 'This class represents an IP Address, which may or may not have been leased.'
+ SUP top
+ MUST ( cn $ dhcpAddressState )
-+ MAY ( dhcpExpirationTime $ dhcpStartTimeOfState $ dhcpLastTransactionTime $ dhcpBootpFlag $ dhcpDomainName $ dhcpDnsStatus $ dhcpRequestedHostName $ dhcpAssignedHostName $ dhcpReservedForClient $ dhcpAssignedToClient $ dhcpRelayAgentInfo $ dhcpHWAddress $ dhcpOption )
++ MAY ( dhcpExpirationTime $ dhcpStartTimeOfState $ dhcpLastTransactionTime $ dhcpBootpFlag $ dhcpDomainName $ dhcpDnsStatus $ dhcpRequestedHostName $ dhcpAssignedHostName $ dhcpReservedForClient $ dhcpAssignedToClient $ dhcpRelayAgentInfo $ dhcpHWAddress )
+ X-NDS_CONTAINMENT ( 'dhcpService' 'dhcpSubnet' 'dhcpPool') )
+
+objectclass ( 2.16.840.1.113719.1.203.6.11
@@ -944,7 +992,8 @@ diff -Naur dhcp-3.0.5/contrib/dhcp.schema dhcp-3.0.5-ldap/contrib/dhcp.schema
+ NAME 'dhcpFailOverPeer'
+ DESC 'This class defines the Fail over peer'
+ SUP top
-+ MUST ( cn $ dhcpFailOverRole $ dhcpFailOverReceiveAddress $ dhcpFailOverPeerAddress $ dhcpFailoverReceivePort $ dhcpFailOverPeerPort ) MAY ( dhcpFailOverResponseDelay $ dhcpFailOverUnackedUpdates $ dhcpMaxClientLeadTime $ dhcpFailOverSplit $ dhcpHashBucketAssignment $ dhcpFailOverLoadBalanceTime $ dhcpComments $ dhcpOption) X-NDS_CONTAINMENT ('dhcpService' 'dhcpSharedNetwork' 'dhcpSubnet') )
++ MUST ( cn $ dhcpFailOverPrimaryServer $ dhcpFailOverSecondaryServer $ dhcpFailoverPrimaryPort $ dhcpFailOverSecondaryPort) MAY (dhcpFailOverResponseDelay $ dhcpFailOverUnackedUpdates $ dhcpMaxClientLeadTime $ dhcpFailOverSplit $ dhcpHashBucketAssignment $ dhcpFailOverLoadBalanceTime $ dhcpComments )
++ X-NDS_CONTAINMENT ('dhcpService' 'dhcpSharedNetwork' 'dhcpSubnet') )
+
+objectclass ( 2.16.840.1.113719.1.203.6.16
+ NAME 'dhcpLocator'
@@ -957,8 +1006,8 @@ diff -Naur dhcp-3.0.5/contrib/dhcp.schema dhcp-3.0.5-ldap/contrib/dhcp.schema
+
diff -Naur dhcp-3.0.5/contrib/dhcpd-conf-to-ldap.pl dhcp-3.0.5-ldap/contrib/dhcpd-conf-to-ldap.pl
--- dhcp-3.0.5/contrib/dhcpd-conf-to-ldap.pl 1969-12-31 19:00:00.000000000 -0500
-+++ dhcp-3.0.5-ldap/contrib/dhcpd-conf-to-ldap.pl 2006-12-14 10:03:41.000000000 -0500
-@@ -0,0 +1,752 @@
++++ dhcp-3.0.5-ldap/contrib/dhcpd-conf-to-ldap.pl 2007-02-23 14:01:43.000000000 -0500
+@@ -0,0 +1,760 @@
+#!/usr/bin/perl -w
+
+# Brian Masney <masneyb@ntelos.net>
@@ -1050,6 +1099,14 @@ diff -Naur dhcp-3.0.5/contrib/dhcpd-conf-to-ldap.pl dhcp-3.0.5-ldap/contrib/dhcp
+
+ if (($token, $newline) = $line =~ /^(.*?)\s+(.*)/)
+ {
++ if ($token =~ /^"/) {
++ #handle quoted token
++ if ($token !~ /"\s*$/)
++ {
++ ($tok, $newline) = $newline =~ /([^"]+")(.*)/;
++ $token .= " $tok";
++ }
++ }
+ $line = $newline;
+ }
+ else
@@ -3033,21 +3090,43 @@ diff -Naur dhcp-3.0.5/doc/draft-ietf-dhc-ldap-schema-01.txt dhcp-3.0.5-ldap/doc/
+
diff -Naur dhcp-3.0.5/dst/Makefile.dist dhcp-3.0.5-ldap/dst/Makefile.dist
--- dhcp-3.0.5/dst/Makefile.dist 2004-06-10 13:59:28.000000000 -0400
-+++ dhcp-3.0.5-ldap/dst/Makefile.dist 2006-12-14 10:03:41.000000000 -0500
-@@ -21,8 +21,8 @@
- # <info@isc.org>
- # http://www.isc.org/
++++ dhcp-3.0.5-ldap/dst/Makefile.dist 2007-02-23 13:41:54.000000000 -0500
+@@ -23,12 +23,13 @@
--SRC = dst_support.c dst_api.c hmac_link.c md5_dgst.c base64.c prandom.c
--OBJ = dst_support.o dst_api.o hmac_link.o md5_dgst.o base64.o prandom.o
-+SRC = dst_support.c dst_api.c hmac_link.c base64.c prandom.c
-+OBJ = dst_support.o dst_api.o hmac_link.o base64.o prandom.o
+ SRC = dst_support.c dst_api.c hmac_link.c md5_dgst.c base64.c prandom.c
+ OBJ = dst_support.o dst_api.o hmac_link.o md5_dgst.o base64.o prandom.o
++OBJ_NM5= dst_support.o dst_api.o hmac_link.o base64.o prandom.o
HDRS = dst_internal.h md5.h md5_locl.h
INCLUDES = $(BINDINC) -I$(TOP)/includes
+ CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) -DHMAC_MD5 -DMINIRES_LIB
+
+-all: libdst.a
++all: libdst.a libdst-nomd5.a
+
+ install:
+
+@@ -37,11 +38,16 @@
+ ar cruv libdst.a $(OBJ)
+ $(RANLIB) libdst.a
+
++libdst-nomd5.a: $(OBJ_NM5)
++ rm -f libdst-nomd5.a
++ ar cruv libdst-nomd5.a $(OBJ_NM5)
++ $(RANLIB) libdst-nomd5.a
++
+ depend:
+ $(MKDEP) $(INCLUDES) $(PREDEFINES) $(SRC)
+
+ clean:
+- -rm -f $(OBJ) libdst.a
++ -rm -f $(OBJ) libdst.a libdst-nomd5.a
+
+ realclean: clean
+ -rm -f *~ $(CATMANPAGES) $(SEDMANPAGES)
diff -Naur dhcp-3.0.5/includes/dhcpd.h dhcp-3.0.5-ldap/includes/dhcpd.h
--- dhcp-3.0.5/includes/dhcpd.h 2006-05-17 16:16:59.000000000 -0400
-+++ dhcp-3.0.5-ldap/includes/dhcpd.h 2006-12-14 10:03:41.000000000 -0500
++++ dhcp-3.0.5-ldap/includes/dhcpd.h 2007-02-23 13:13:36.000000000 -0500
@@ -79,6 +79,11 @@
#include <isc-dhcp/result.h>
#include <omapip/omapip_p.h>
@@ -3069,7 +3148,7 @@ diff -Naur dhcp-3.0.5/includes/dhcpd.h dhcp-3.0.5-ldap/includes/dhcpd.h
};
/* Variable-length array of data. */
-@@ -244,6 +251,26 @@
+@@ -244,6 +251,32 @@
u_int8_t hbuf [17];
};
@@ -3077,6 +3156,12 @@ diff -Naur dhcp-3.0.5/includes/dhcpd.h dhcp-3.0.5-ldap/includes/dhcpd.h
+# define LDAP_BUFFER_SIZE 8192
+# define LDAP_METHOD_STATIC 0
+# define LDAP_METHOD_DYNAMIC 1
++#if defined (USE_SSL)
++# define LDAP_SSL_OFF 0
++# define LDAP_SSL_ON 1
++# define LDAP_SSL_TLS 2
++# define LDAP_SSL_LDAPS 3
++#endif
+
+/* This is a tree of the current configuration we are building from LDAP */
+
@@ -3096,7 +3181,7 @@ diff -Naur dhcp-3.0.5/includes/dhcpd.h dhcp-3.0.5-ldap/includes/dhcpd.h
typedef enum {
server_startup = 0,
server_running = 1,
-@@ -426,6 +453,17 @@
+@@ -426,6 +459,29 @@
# define DEFAULT_PING_TIMEOUT 1
#endif
@@ -3108,13 +3193,25 @@ diff -Naur dhcp-3.0.5/includes/dhcpd.h dhcp-3.0.5-ldap/includes/dhcpd.h
+# define SV_LDAP_BASE_DN 51
+# define SV_LDAP_METHOD 52
+# define SV_LDAP_DEBUG_FILE 53
-+# define SV_LDAP_SERVER_CN 54
++# define SV_LDAP_DHCP_SERVER_CN 54
++# define SV_LDAP_REFERRALS 55
++#if defined (USE_SSL)
++# define SV_LDAP_SSL 56
++# define SV_LDAP_TLS_REQCERT 57
++# define SV_LDAP_TLS_CA_FILE 58
++# define SV_LDAP_TLS_CA_DIR 59
++# define SV_LDAP_TLS_CERT 60
++# define SV_LDAP_TLS_KEY 61
++# define SV_LDAP_TLS_CRLCHECK 62
++# define SV_LDAP_TLS_CIPHERS 63
++# define SV_LDAP_TLS_RANDFILE 64
++#endif
+#endif
+
#if !defined (DEFAULT_DEFAULT_LEASE_TIME)
# define DEFAULT_DEFAULT_LEASE_TIME 43200
#endif
-@@ -1531,7 +1569,7 @@
+@@ -1531,7 +1587,7 @@
char *quotify_string (const char *, const char *, int);
char *quotify_buf (const unsigned char *, unsigned, const char *, int);
char *print_base64 (const unsigned char *, unsigned, const char *, int);
@@ -3123,7 +3220,7 @@ diff -Naur dhcp-3.0.5/includes/dhcpd.h dhcp-3.0.5-ldap/includes/dhcpd.h
void print_lease PROTO ((struct lease *));
void dump_raw PROTO ((const unsigned char *, unsigned));
void dump_packet_option (struct option_cache *, struct packet *,
-@@ -2632,3 +2670,14 @@
+@@ -2632,3 +2688,19 @@
#endif /* FAILOVER_PROTOCOL */
const char *binding_state_print (enum failover_state);
@@ -3131,6 +3228,11 @@ diff -Naur dhcp-3.0.5/includes/dhcpd.h dhcp-3.0.5-ldap/includes/dhcpd.h
+/* ldap.c */
+#if defined(LDAP_CONFIGURATION)
+extern struct enumeration ldap_methods;
++#if defined (USE_SSL)
++extern struct enumeration ldap_ssl_usage_enum;
++extern struct enumeration ldap_tls_reqcert_enum;
++extern struct enumeration ldap_tls_crlcheck_enum;
++#endif
+isc_result_t ldap_read_config (void);
+int find_haddr_in_ldap (struct host_decl **, int, unsigned,
+ const unsigned char *, const char *, int);
@@ -3244,8 +3346,8 @@ diff -Naur dhcp-3.0.5/includes/site.h dhcp-3.0.5-ldap/includes/site.h
+/* #define USE_SSL */
diff -Naur dhcp-3.0.5/server/Makefile.dist dhcp-3.0.5-ldap/server/Makefile.dist
--- dhcp-3.0.5/server/Makefile.dist 2004-06-10 13:59:50.000000000 -0400
-+++ dhcp-3.0.5-ldap/server/Makefile.dist 2006-12-14 10:03:41.000000000 -0500
-@@ -25,9 +25,9 @@
++++ dhcp-3.0.5-ldap/server/Makefile.dist 2007-02-23 13:41:54.000000000 -0500
+@@ -25,14 +25,14 @@
CATMANPAGES = dhcpd.cat8 dhcpd.conf.cat5 dhcpd.leases.cat5
SEDMANPAGES = dhcpd.man8 dhcpd.conf.man5 dhcpd.leases.man5
SRCS = dhcpd.c dhcp.c bootp.c confpars.c db.c class.c failover.c \
@@ -3257,6 +3359,12 @@ diff -Naur dhcp-3.0.5/server/Makefile.dist dhcp-3.0.5-ldap/server/Makefile.dist
PROG = dhcpd
MAN = dhcpd.8 dhcpd.conf.5 dhcpd.leases.5
+ INCLUDES = -I$(TOP) $(BINDINC) -I$(TOP)/includes
+-DHCPLIB = ../common/libdhcp.a $(BINDLIB) ../omapip/libomapi.a ../dst/libdst.a
++DHCPLIB = ../common/libdhcp.a $(BINDLIB) ../omapip/libomapi.a ../dst/libdst-nomd5.a -lssl -lcrypto -lldap -llber
+ CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS)
+
+ all: $(PROG) $(CATMANPAGES)
diff -Naur dhcp-3.0.5/server/class.c dhcp-3.0.5-ldap/server/class.c
--- dhcp-3.0.5/server/class.c 2004-06-10 13:59:51.000000000 -0400
+++ dhcp-3.0.5-ldap/server/class.c 2006-12-14 10:03:41.000000000 -0500
@@ -3315,21 +3423,26 @@ diff -Naur dhcp-3.0.5/server/confpars.c dhcp-3.0.5-ldap/server/confpars.c
isc_result_t read_conf_file (const char *filename, struct group *group,
diff -Naur dhcp-3.0.5/server/dhcpd.c dhcp-3.0.5-ldap/server/dhcpd.c
--- dhcp-3.0.5/server/dhcpd.c 2006-07-17 11:23:44.000000000 -0400
-+++ dhcp-3.0.5-ldap/server/dhcpd.c 2006-12-14 10:03:41.000000000 -0500
-@@ -436,6 +436,9 @@
++++ dhcp-3.0.5-ldap/server/dhcpd.c 2007-02-23 13:13:36.000000000 -0500
+@@ -436,6 +436,14 @@
/* Add the ddns update style enumeration prior to parsing. */
add_enumeration (&ddns_styles);
add_enumeration (&syslog_enum);
+#if defined (LDAP_CONFIGURATION)
+ add_enumeration (&ldap_methods);
++#if defined (USE_SSL)
++ add_enumeration (&ldap_ssl_usage_enum);
++ add_enumeration (&ldap_tls_reqcert_enum);
++ add_enumeration (&ldap_tls_crlcheck_enum);
++#endif
+#endif
if (!group_allocate (&root_group, MDL))
log_fatal ("Can't allocate root group!");
diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
--- dhcp-3.0.5/server/ldap.c 1969-12-31 19:00:00.000000000 -0500
-+++ dhcp-3.0.5-ldap/server/ldap.c 2006-12-14 12:28:56.000000000 -0500
-@@ -0,0 +1,1741 @@
++++ dhcp-3.0.5-ldap/server/ldap.c 2007-02-23 13:36:24.000000000 -0500
+@@ -0,0 +1,1977 @@
+/* ldap.c
+
+ Routines for reading the configuration from LDAP */
@@ -3383,11 +3496,23 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ *ldap_username = NULL,
+ *ldap_password = NULL,
+ *ldap_base_dn = NULL,
-+ *ldap_server_cn = NULL,
++ *ldap_dhcp_server_cn = NULL,
+ *ldap_debug_file = NULL;
+static int ldap_port = LDAP_PORT,
+ ldap_method = LDAP_METHOD_DYNAMIC,
++ ldap_referrals = -1,
+ ldap_debug_fd = -1;
++#if defined (USE_SSL)
++static int ldap_use_ssl = -1, /* try TLS if possible */
++ ldap_tls_reqcert = -1,
++ ldap_tls_crlcheck = -1;
++static char *ldap_tls_ca_file = NULL,
++ *ldap_tls_ca_dir = NULL,
++ *ldap_tls_cert = NULL,
++ *ldap_tls_key = NULL,
++ *ldap_tls_ciphers = NULL,
++ *ldap_tls_randfile = NULL;
++#endif
+static struct ldap_config_stack *ldap_stack = NULL;
+
+typedef struct ldap_dn_node {
@@ -3400,6 +3525,13 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+static ldap_dn_node *ldap_service_dn_tail = NULL;
+
+
++static char *
++x_strncat(char *dst, const char *src, size_t dst_size)
++{
++ size_t len = strlen(dst);
++ return strncat(dst, src, dst_size > len ? dst_size - len - 1: 0);
++}
++
+static void
+ldap_parse_class (struct ldap_config_stack *item, struct parse *cfile)
+{
@@ -3414,9 +3546,9 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ return;
+ }
+
-+ strncat (cfile->inbuf, "class \"", LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, "\" {\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "class \"", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "\" {\n", LDAP_BUFFER_SIZE);
+
+ item->close_brace = 1;
+ ldap_value_free (tempstr);
@@ -3448,11 +3580,11 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ return;
+ }
+
-+ strncat (cfile->inbuf, "subclass ", LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, classdata[0], LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "subclass ", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, classdata[0], LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
+
+ item->close_brace = 1;
+ ldap_value_free (tempstr);
@@ -3476,14 +3608,14 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+
+ hwaddr = ldap_get_values (ld, item->ldent, "dhcpHWAddress");
+
-+ strncat (cfile->inbuf, "host ", LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "host ", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
+
+ if (hwaddr != NULL && hwaddr[0] != NULL)
+ {
-+ strncat (cfile->inbuf, " {\nhardware ", LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, hwaddr[0], LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, " {\nhardware ", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, hwaddr[0], LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+ ldap_value_free (hwaddr);
+ }
+
@@ -3506,9 +3638,9 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ return;
+ }
+
-+ strncat (cfile->inbuf, "shared-network \"", LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, "\" {\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "shared-network \"", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "\" {\n", LDAP_BUFFER_SIZE);
+
+ item->close_brace = 1;
+ ldap_value_free (tempstr);
@@ -3560,14 +3692,14 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ return;
+ }
+
-+ strncat (cfile->inbuf, "subnet ", LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "subnet ", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
+
-+ strncat (cfile->inbuf, " netmask ", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, " netmask ", LDAP_BUFFER_SIZE);
+ parse_netmask (strtol (netmaskstr[0], NULL, 10), netmaskbuf);
-+ strncat (cfile->inbuf, netmaskbuf, LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, netmaskbuf, LDAP_BUFFER_SIZE);
+
-+ strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
+
+ ldap_value_free (tempstr);
+ ldap_value_free (netmaskstr);
@@ -3576,10 +3708,10 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ {
+ for (i=0; tempstr[i] != NULL; i++)
+ {
-+ strncat (cfile->inbuf, "range", LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, tempstr[i], LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "range", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, tempstr[i], LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+ }
+ ldap_value_free (tempstr);
+ }
@@ -3594,17 +3726,17 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ char **tempstr;
+ int i;
+
-+ strncat (cfile->inbuf, "pool {\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "pool {\n", LDAP_BUFFER_SIZE);
+
+ if ((tempstr = ldap_get_values (ld, item->ldent, "dhcpRange")) != NULL)
+ {
-+ strncat (cfile->inbuf, "range", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "range", LDAP_BUFFER_SIZE);
+ for (i=0; tempstr[i] != NULL; i++)
+ {
-+ strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, tempstr[i], LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, tempstr[i], LDAP_BUFFER_SIZE);
+ }
-+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+ ldap_value_free (tempstr);
+ }
+
@@ -3612,8 +3744,8 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ {
+ for (i=0; tempstr[i] != NULL; i++)
+ {
-+ strncat (cfile->inbuf, tempstr[i], LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, tempstr[i], LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+ }
+ ldap_value_free (tempstr);
+ }
@@ -3625,7 +3757,7 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+static void
+ldap_parse_group (struct ldap_config_stack *item, struct parse *cfile)
+{
-+ strncat (cfile->inbuf, "group {\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "group {\n", LDAP_BUFFER_SIZE);
+ item->close_brace = 1;
+}
+
@@ -3637,25 +3769,25 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+
+ if ((tempstr = ldap_get_values (ld, item->ldent, "cn")) != NULL)
+ {
-+ strncat (cfile->inbuf, "key ", LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "key ", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
+ ldap_value_free (tempstr);
+ }
+
+ if ((tempstr = ldap_get_values (ld, item->ldent, "dhcpKeyAlgorithm")) != NULL)
+ {
-+ strncat (cfile->inbuf, "algorithm ", LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "algorithm ", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+ ldap_value_free (tempstr);
+ }
+
+ if ((tempstr = ldap_get_values (ld, item->ldent, "dhcpKeySecret")) != NULL)
+ {
-+ strncat (cfile->inbuf, "secret ", LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "secret ", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+ ldap_value_free (tempstr);
+ }
+
@@ -3673,18 +3805,18 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+
+ if ((tempstr = ldap_get_values (ld, item->ldent, "cn")) != NULL)
+ {
-+ strncat (cfile->inbuf, "zone ", LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "zone ", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
+ ldap_value_free (tempstr);
+ }
+
+ if ((tempstr = ldap_get_values (ld, item->ldent, "dhcpDnsZoneServer")) != NULL)
+ {
-+ strncat (cfile->inbuf, "primary ", LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "primary ", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, tempstr[0], LDAP_BUFFER_SIZE);
+
-+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+ ldap_value_free (tempstr);
+ }
+
@@ -3712,9 +3844,9 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ strncpy (keyCn, cnFindStart, len);
+ keyCn[len] = '\0';
+
-+ strncat (cfile->inbuf, "key ", LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, keyCn, LDAP_BUFFER_SIZE);
-+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "key ", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, keyCn, LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
+
+ dfree (keyCn, MDL);
+ }
@@ -3787,7 +3919,7 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ {
+ ret = dmalloc (db.len + 1, MDL);
+ if (ret == NULL)
-+ log_fatal ("no memory for ldap username");
++ log_fatal ("no memory for ldap option %d value", option_name);
+
+ memcpy (ret, db.data, db.len);
+ ret[db.len] = 0;
@@ -3857,6 +3989,69 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ return (ret);
+}
+
++int
++ldap_rebind_cb (LDAP *ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *parms)
++{
++ int ret;
++ LDAPURLDesc *ldapurl = NULL;
++ char *who = NULL, *pwd = NULL;
++
++ log_info("LDAP rebind to '%s'", url);
++ if ((ret = ldap_url_parse(url, &ldapurl)) != LDAP_SUCCESS)
++ {
++ log_error ("Error: Can not parse ldap rebind url '%s': %s",
++ url, ldap_err2string(ret));
++ return ret;
++ }
++
++
++#if defined (USE_SSL)
++ if (strcasecmp(ldapurl->lud_scheme, "ldaps") == 0)
++ {
++ int opt = LDAP_OPT_X_TLS_HARD;
++ if ((ret = ldap_set_option (ld, LDAP_OPT_X_TLS, &opt)) != LDAP_SUCCESS)
++ {
++ log_error ("Error: Cannot init LDAPS session to %s:%d: %s",
++ ldapurl->lud_host, ldapurl->lud_port, ldap_err2string (ret));
++ return ret;
++ }
++ else
++ {
++ log_info ("LDAPS session successfully enabled to %s", ldap_server);
++ }
++ }
++ else
++ if (strcasecmp(ldapurl->lud_scheme, "ldap") == 0 &&
++ ldap_use_ssl != LDAP_SSL_OFF)
++ {
++ if ((ret = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS)
++ {
++ log_error ("Error: Cannot start TLS session to %s:%d: %s",
++ ldapurl->lud_host, ldapurl->lud_port, ldap_err2string (ret));
++ return ret;
++ }
++ else
++ {
++ log_info ("TLS session successfully started to %s:%d",
++ ldapurl->lud_host, ldapurl->lud_port);
++ }
++ }
++#endif
++
++
++ if (ldap_username != NULL || *ldap_username != '\0')
++ {
++ who = ldap_username;
++ pwd = ldap_password;
++ }
++
++ if ((ret = ldap_simple_bind_s (ld, who, pwd)) != LDAP_SUCCESS)
++ {
++ log_error ("Error: Cannot login into ldap server %s:%d: %s",
++ ldapurl->lud_host, ldapurl->lud_port, ldap_err2string (ret));
++ }
++ return ret;
++}
+
+static void
+ldap_start (void)
@@ -3878,16 +4073,32 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ options, &global_scope, root_group, (struct group *) NULL);
+
+ ldap_server = _do_lookup_dhcp_string_option (options, SV_LDAP_SERVER);
-+ ldap_server_cn = _do_lookup_dhcp_string_option (options,
-+ SV_LDAP_SERVER_CN);
++ ldap_dhcp_server_cn = _do_lookup_dhcp_string_option (options,
++ SV_LDAP_DHCP_SERVER_CN);
+ ldap_port = _do_lookup_dhcp_int_option (options, SV_LDAP_PORT);
+ ldap_base_dn = _do_lookup_dhcp_string_option (options, SV_LDAP_BASE_DN);
+ ldap_method = _do_lookup_dhcp_enum_option (options, SV_LDAP_METHOD);
+ ldap_debug_file = _do_lookup_dhcp_string_option (options,
+ SV_LDAP_DEBUG_FILE);
++ ldap_referrals = _do_lookup_dhcp_enum_option (options, SV_LDAP_REFERRALS);
++
++#if defined (USE_SSL)
++ ldap_use_ssl = _do_lookup_dhcp_enum_option (options, SV_LDAP_SSL);
++ if( ldap_use_ssl != LDAP_SSL_OFF)
++ {
++ ldap_tls_reqcert = _do_lookup_dhcp_enum_option (options, SV_LDAP_TLS_REQCERT);
++ ldap_tls_ca_file = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CA_FILE);
++ ldap_tls_ca_dir = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CA_DIR);
++ ldap_tls_cert = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CERT);
++ ldap_tls_key = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_KEY);
++ ldap_tls_crlcheck = _do_lookup_dhcp_enum_option (options, SV_LDAP_TLS_CRLCHECK);
++ ldap_tls_ciphers = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CIPHERS);
++ ldap_tls_randfile = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_RANDFILE);
++ }
++#endif
+
+#if defined (LDAP_CASA_AUTH)
-+ if (!load_uname_pwd_from_miCASA(ldap_username,ldap_password))
++ if (!load_uname_pwd_from_miCASA(&ldap_username,&ldap_password))
+ {
+#if defined (DEBUG_LDAP)
+ log_info ("Authentication credential taken from file");
@@ -3923,9 +4134,105 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ log_info ("Connecting to LDAP server %s:%d", ldap_server, ldap_port);
+#endif
+
++#if defined (USE_SSL)
++ if (ldap_use_ssl == -1)
++ {
++ /*
++ ** There was no "ldap-ssl" option in dhcpd.conf (also not "off").
++ ** Let's try, if we can use an anonymous TLS session without to
++ ** verify the server certificate -- if not continue without TLS.
++ */
++ int opt = LDAP_OPT_X_TLS_ALLOW;
++ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT,
++ &opt)) != LDAP_SUCCESS)
++ {
++ log_error ("Warning: Cannot set LDAP TLS require cert option to 'allow': %s",
++ ldap_err2string (ret));
++ }
++ }
++
++ if (ldap_use_ssl != LDAP_SSL_OFF)
++ {
++ if (ldap_tls_reqcert != -1)
++ {
++ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT,
++ &ldap_tls_reqcert)) != LDAP_SUCCESS)
++ {
++ log_error ("Cannot set LDAP TLS require cert option: %s",
++ ldap_err2string (ret));
++ }
++ }
++
++ if( ldap_tls_ca_file != NULL)
++ {
++ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTFILE,
++ ldap_tls_ca_file)) != LDAP_SUCCESS)
++ {
++ log_error ("Cannot set LDAP TLS CA certificate file %s: %s",
++ ldap_tls_ca_file, ldap_err2string (ret));
++ }
++ }
++ if( ldap_tls_ca_dir != NULL)
++ {
++ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTDIR,
++ ldap_tls_ca_dir)) != LDAP_SUCCESS)
++ {
++ log_error ("Cannot set LDAP TLS CA certificate dir %s: %s",
++ ldap_tls_ca_dir, ldap_err2string (ret));
++ }
++ }
++ if( ldap_tls_cert != NULL)
++ {
++ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CERTFILE,
++ ldap_tls_cert)) != LDAP_SUCCESS)
++ {
++ log_error ("Cannot set LDAP TLS client certificate file %s: %s",
++ ldap_tls_cert, ldap_err2string (ret));
++ }
++ }
++ if( ldap_tls_key != NULL)
++ {
++ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_KEYFILE,
++ ldap_tls_key)) != LDAP_SUCCESS)
++ {
++ log_error ("Cannot set LDAP TLS certificate key file %s: %s",
++ ldap_tls_key, ldap_err2string (ret));
++ }
++ }
++ if( ldap_tls_crlcheck != -1)
++ {
++ int opt = ldap_tls_crlcheck;
++ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CRLCHECK,
++ &opt)) != LDAP_SUCCESS)
++ {
++ log_error ("Cannot set LDAP TLS crl check option: %s",
++ ldap_err2string (ret));
++ }
++ }
++ if( ldap_tls_ciphers != NULL)
++ {
++ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CIPHER_SUITE,
++ ldap_tls_ciphers)) != LDAP_SUCCESS)
++ {
++ log_error ("Cannot set LDAP TLS cipher suite %s: %s",
++ ldap_tls_ciphers, ldap_err2string (ret));
++ }
++ }
++ if( ldap_tls_randfile != NULL)
++ {
++ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_RANDOM_FILE,
++ ldap_tls_randfile)) != LDAP_SUCCESS)
++ {
++ log_error ("Cannot set LDAP TLS random file %s: %s",
++ ldap_tls_randfile, ldap_err2string (ret));
++ }
++ }
++ }
++#endif
++
+ if ((ld = ldap_init (ldap_server, ldap_port)) == NULL)
+ {
-+ log_error ("Cannot init ldap session to %s", ldap_server);
++ log_error ("Cannot init ldap session to %s:%d", ldap_server, ldap_port);
+ return;
+ }
+
@@ -3936,12 +4243,56 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ ldap_err2string (ret));
+ }
+
++ if (ldap_referrals != -1)
++ {
++ if ((ret = ldap_set_option (ld, LDAP_OPT_REFERRALS, ldap_referrals ?
++ LDAP_OPT_ON : LDAP_OPT_OFF)) != LDAP_OPT_SUCCESS)
++ {
++ log_error ("Cannot %s LDAP referrals option: %s",
++ (ldap_referrals ? "enable" : "disable"),
++ ldap_err2string (ret));
++ }
++ }
++
++ if ((ret = ldap_set_rebind_proc(ld, ldap_rebind_cb, NULL)) != LDAP_SUCCESS)
++ {
++ log_error ("Warning: Cannot set ldap rebind procedure: %s",
++ ldap_err2string (ret));
++ }
++
+#if defined (USE_SSL)
-+ if ((ret = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS)
-+ log_error ("Warning: Cannot start TLS session to %s: %s",
-+ ldap_server, ldap_err2string (ret));
-+ else
-+ log_info ("TLS session successfully started to %s", ldap_server);
++ if (ldap_use_ssl == LDAP_SSL_LDAPS ||
++ (ldap_use_ssl == LDAP_SSL_ON && ldap_port == LDAPS_PORT))
++ {
++ int opt = LDAP_OPT_X_TLS_HARD;
++ if ((ret = ldap_set_option (ld, LDAP_OPT_X_TLS, &opt)) != LDAP_SUCCESS)
++ {
++ log_error ("Error: Cannot init LDAPS session to %s:%d: %s",
++ ldap_server, ldap_port, ldap_err2string (ret));
++ ldap_stop();
++ return;
++ }
++ else
++ {
++ log_info ("LDAPS session successfully enabled to %s:%d",
++ ldap_server, ldap_port);
++ }
++ }
++ else if (ldap_use_ssl != LDAP_SSL_OFF)
++ {
++ if ((ret = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS)
++ {
++ log_error ("Error: Cannot start TLS session to %s:%d: %s",
++ ldap_server, ldap_port, ldap_err2string (ret));
++ ldap_stop();
++ return;
++ }
++ else
++ {
++ log_info ("TLS session successfully started to %s:%d",
++ ldap_server, ldap_port);
++ }
++ }
+#endif
+
+ if (ldap_username != NULL && *ldap_username != '\0')
@@ -3949,8 +4300,8 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ if ((ret = ldap_simple_bind_s (ld, ldap_username,
+ ldap_password)) != LDAP_SUCCESS)
+ {
-+ log_error ("Error: Cannot login into ldap server %s: %s", ldap_server,
-+ ldap_err2string (ret));
++ log_error ("Error: Cannot login into ldap server %s:%d: %s",
++ ldap_server, ldap_port, ldap_err2string (ret));
+ ldap_stop();
+ return;
+ }
@@ -4063,7 +4414,7 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+
+ if (ldap_stack != NULL && ldap_stack->close_brace)
+ {
-+ strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
+ ldap_stack->close_brace = 0;
+ }
+
@@ -4073,7 +4424,7 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ {
+ if (ldap_stack->close_brace)
+ {
-+ strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
+ ldap_stack->close_brace = 0;
+ }
+
@@ -4084,7 +4435,7 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+
+ if (ldap_stack != NULL && ldap_stack->close_brace)
+ {
-+ strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
++ x_strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
+ ldap_stack->close_brace = 0;
+ }
+}
@@ -4160,16 +4511,16 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ continue;
+ }
+
-+ strncat (buffer, tempstr[i], size);
++ x_strncat (buffer, tempstr[i], size);
+
+ switch((int) check_statement_end (tempstr[i]))
+ {
+ case '}':
+ case ';':
-+ strncat (buffer, "\n", size);
++ x_strncat (buffer, "\n", size);
+ break;
+ default:
-+ strncat (buffer, ";\n", size);
++ x_strncat (buffer, ";\n", size);
+ break;
+ }
+ }
@@ -4180,15 +4531,15 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ {
+ for (i=0; tempstr[i] != NULL; i++)
+ {
-+ strncat (buffer, "option ", size);
-+ strncat (buffer, tempstr[i], size);
++ x_strncat (buffer, "option ", size);
++ x_strncat (buffer, tempstr[i], size);
+ switch ((int) check_statement_end (tempstr[i]))
+ {
+ case ';':
-+ strncat (buffer, "\n", size);
++ x_strncat (buffer, "\n", size);
+ break;
+ default:
-+ strncat (buffer, ";\n", size);
++ x_strncat (buffer, ";\n", size);
+ break;
+ }
+ }
@@ -4343,12 +4694,13 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ cfile->inbuf[0] = '\0';
+ cfile->buflen = 0;
+
++ while (ldap_stack != NULL && *cfile->inbuf == '\0')
++ ldap_generate_config_string (cfile);
++
+ if (ldap_stack == NULL && *cfile->inbuf == '\0')
+ return (EOF);
+
-+ if (ldap_stack != NULL && *cfile->inbuf == '\0')
-+ ldap_generate_config_string (cfile);
-+
++ cfile->bufix = 1;
+ cfile->buflen = strlen (cfile->inbuf);
+ if (cfile->buflen > 0)
+ ldap_write_debug (cfile->inbuf, cfile->buflen);
@@ -4357,9 +4709,6 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ log_info ("Sending config line '%s'", cfile->inbuf);
+#endif
+
-+ cfile->buflen = strlen (cfile->inbuf);
-+ cfile->bufix = 1;
-+
+ return (cfile->inbuf[0]);
+}
+
@@ -4448,10 +4797,10 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ return (res);
+
+ uname (&unme);
-+ if (ldap_server_cn != NULL)
++ if (ldap_dhcp_server_cn != NULL)
+ {
+ snprintf (hfilter, sizeof (hfilter),
-+ "(&(objectClass=dhcpServer)(cn=%s))", ldap_server_cn);
++ "(&(objectClass=dhcpServer)(cn=%s))", ldap_dhcp_server_cn);
+ }
+ else
+ {
@@ -4473,7 +4822,7 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+ hfilter, NULL, 0, &hostres)) != LDAP_SUCCESS)
+ {
+ log_error ("Cannot find host LDAP entry %s %s",
-+ ((ldap_server_cn == NULL)?(unme.nodename):(ldap_server_cn)), hfilter);
++ ((ldap_dhcp_server_cn == NULL)?(unme.nodename):(ldap_dhcp_server_cn)), hfilter);
+ if(NULL != hostres)
+ ldap_msgfree (hostres);
+ ldap_stop();
@@ -5073,7 +5422,7 @@ diff -Naur dhcp-3.0.5/server/ldap.c dhcp-3.0.5-ldap/server/ldap.c
+#endif
diff -Naur dhcp-3.0.5/server/ldap_casa.c dhcp-3.0.5-ldap/server/ldap_casa.c
--- dhcp-3.0.5/server/ldap_casa.c 1969-12-31 19:00:00.000000000 -0500
-+++ dhcp-3.0.5-ldap/server/ldap_casa.c 2006-12-14 10:03:41.000000000 -0500
++++ dhcp-3.0.5-ldap/server/ldap_casa.c 2007-02-23 12:48:56.000000000 -0500
@@ -0,0 +1,138 @@
+/* ldap_casa.c
+
@@ -5158,9 +5507,9 @@ diff -Naur dhcp-3.0.5/server/ldap_casa.c dhcp-3.0.5-ldap/server/ldap_casa.c
+load_uname_pwd_from_miCASA (char **ldap_username, char **ldap_password)
+ {
+ int result = 0;
-+ int32_t credentialtype = SSCS_CRED_TYPE_SERVER_F;
-+ SSCS_BASIC_CREDENTIAL credential = {0};
-+ SSCS_SECRET_ID_T applicationSecretId = {0};
++ uint32_t credentialtype = SSCS_CRED_TYPE_SERVER_F;
++ SSCS_BASIC_CREDENTIAL credential;
++ SSCS_SECRET_ID_T applicationSecretId;
+ char *tempVar = NULL;
+
+ const char applicationName[10] = "dhcp-ldap";
@@ -5182,15 +5531,15 @@ diff -Naur dhcp-3.0.5/server/ldap_casa.c dhcp-3.0.5-ldap/server/ldap_casa.c
+ if(credential.unLen)
+ {
+ tempVar = dmalloc (credential.unLen + 1, MDL);
-+ memcpy(tempVar , credential.username, credential.unLen);
+ if (!tempVar)
+ log_fatal ("no memory for ldap_username");
++ memcpy(tempVar , credential.username, credential.unLen);
+ *ldap_username = tempVar;
+
+ tempVar = dmalloc (credential.pwordLen + 1, MDL);
-+ memcpy(tempVar, credential.password, credential.pwordLen);
+ if (!tempVar)
+ log_fatal ("no memory for ldap_password");
++ memcpy(tempVar, credential.password, credential.pwordLen);
+ *ldap_password = tempVar;
+
+#if defined (DEBUG_LDAP)
@@ -5231,8 +5580,8 @@ diff -Naur dhcp-3.0.5/server/mdb.c dhcp-3.0.5-ldap/server/mdb.c
h.hbuf [0] = htype;
diff -Naur dhcp-3.0.5/server/stables.c dhcp-3.0.5-ldap/server/stables.c
--- dhcp-3.0.5/server/stables.c 2004-06-10 13:59:58.000000000 -0400
-+++ dhcp-3.0.5-ldap/server/stables.c 2006-12-14 10:03:41.000000000 -0500
-@@ -483,6 +483,16 @@
++++ dhcp-3.0.5-ldap/server/stables.c 2007-02-23 13:13:36.000000000 -0500
+@@ -483,6 +483,38 @@
{ "log-facility", "Nsyslog-facilities.", &server_universe, 44 },
{ "do-forward-updates", "f", &server_universe, 45 },
{ "ping-timeout", "T", &server_universe, 46 },
@@ -5244,20 +5593,42 @@ diff -Naur dhcp-3.0.5/server/stables.c dhcp-3.0.5-ldap/server/stables.c
+ { "ldap-base-dn", "t", &server_universe, 51 },
+ { "ldap-method", "Nldap-methods.", &server_universe, 52 },
+ { "ldap-debug-file", "t", &server_universe, 53 },
-+ { "ldap-server-cn", "t", &server_universe, 54 },
++ { "ldap-dhcp-server-cn", "t", &server_universe, 54 },
++ { "ldap-referrals", "f", &server_universe, 55 },
++#if defined(USE_SSL)
++ { "ldap-ssl", "Nldap-ssl-usage.", &server_universe, 56 },
++ { "ldap-tls-reqcert", "Nldap-tls-reqcert.", &server_universe, 57 },
++ { "ldap-tls-ca-file", "t", &server_universe, 58 },
++ { "ldap-tls-ca-dir", "t", &server_universe, 59 },
++ { "ldap-tls-cert", "t", &server_universe, 60 },
++ { "ldap-tls-key", "t", &server_universe, 61 },
++ { "ldap-tls-crlcheck", "Nldap-tls-crlcheck.", &server_universe, 62 },
++ { "ldap-tls-ciphers", "t", &server_universe, 63 },
++ { "ldap-tls-randfile", "t", &server_universe, 64 },
++#else
++ { "unknown-56", "X", &server_universe, 56 },
++ { "unknown-57", "X", &server_universe, 57 },
++ { "unknown-58", "X", &server_universe, 58 },
++ { "unknown-59", "X", &server_universe, 59 },
++ { "unknown-60", "X", &server_universe, 60 },
++ { "unknown-61", "X", &server_universe, 61 },
++ { "unknown-62", "X", &server_universe, 62 },
++ { "unknown-63", "X", &server_universe, 63 },
++ { "unknown-64", "X", &server_universe, 64 },
++#endif
+#else
{ "unknown-47", "X", &server_universe, 47 },
{ "unknown-48", "X", &server_universe, 48 },
{ "unknown-49", "X", &server_universe, 49 },
-@@ -491,6 +501,7 @@
- { "unknown-52", "X", &server_universe, 52 },
- { "unknown-53", "X", &server_universe, 53 },
- { "unknown-54", "X", &server_universe, 54 },
+@@ -501,6 +533,7 @@
+ { "unknown-62", "X", &server_universe, 62 },
+ { "unknown-63", "X", &server_universe, 63 },
+ { "unknown-64", "X", &server_universe, 64 },
+#endif
- { "unknown-55", "X", &server_universe, 55 },
- { "unknown-56", "X", &server_universe, 56 },
- { "unknown-57", "X", &server_universe, 57 },
-@@ -694,6 +705,20 @@
+ { "unknown-65", "X", &server_universe, 65 },
+ { "unknown-66", "X", &server_universe, 66 },
+ { "unknown-67", "X", &server_universe, 67 },
+@@ -694,6 +727,61 @@
{ "option-end", "e", &server_universe, 255 },
};
@@ -5273,6 +5644,47 @@ diff -Naur dhcp-3.0.5/server/stables.c dhcp-3.0.5-ldap/server/stables.c
+ "ldap-methods",
+ ldap_values
+};
++
++#if defined(USE_SSL)
++struct enumeration_value ldap_ssl_usage_values [] = {
++ { "off", LDAP_SSL_OFF },
++ { "on", LDAP_SSL_ON },
++ { "ldaps", LDAP_SSL_LDAPS},
++ { "start_tls", LDAP_SSL_TLS },
++ { (char *) 0, 0 }
++};
++struct enumeration ldap_ssl_usage_enum = {
++ (struct enumeration *)0,
++ "ldap-ssl-usage",
++ ldap_ssl_usage_values
++};
++
++struct enumeration_value ldap_tls_reqcert_values [] = {
++ { "never", LDAP_OPT_X_TLS_NEVER },
++ { "hard", LDAP_OPT_X_TLS_HARD },
++ { "demand", LDAP_OPT_X_TLS_DEMAND},
++ { "allow", LDAP_OPT_X_TLS_ALLOW },
++ { "try", LDAP_OPT_X_TLS_TRY },
++ { (char *) 0, 0 }
++};
++struct enumeration ldap_tls_reqcert_enum = {
++ (struct enumeration *)0,
++ "ldap-tls-reqcert",
++ ldap_tls_reqcert_values
++};
++
++struct enumeration_value ldap_tls_crlcheck_values [] = {
++ { "none", LDAP_OPT_X_TLS_CRL_NONE},
++ { "peer", LDAP_OPT_X_TLS_CRL_PEER},
++ { "all", LDAP_OPT_X_TLS_CRL_ALL },
++ { (char *) 0, 0 }
++};
++struct enumeration ldap_tls_crlcheck_enum = {
++ (struct enumeration *)0,
++ "ldap-tls-crlcheck",
++ ldap_tls_crlcheck_values
++};
++#endif
+#endif
+
struct enumeration_value ddns_styles_values [] = {
@@ -5280,9 +5692,8 @@ diff -Naur dhcp-3.0.5/server/stables.c dhcp-3.0.5-ldap/server/stables.c
{ "ad-hoc", 1 },
diff -Naur dhcp-3.0.5/site.conf dhcp-3.0.5-ldap/site.conf
--- dhcp-3.0.5/site.conf 1999-07-07 11:20:10.000000000 -0400
-+++ dhcp-3.0.5-ldap/site.conf 2006-12-14 10:03:41.000000000 -0500
-@@ -1,2 +1,4 @@
++++ dhcp-3.0.5-ldap/site.conf 2007-02-23 13:41:54.000000000 -0500
+@@ -1,2 +1,3 @@
# Put local site configuration stuff here to override the default
# settings in Makefile.conf
+#COPTS = -DDEBUG_LDAP -DLDAP_CASA_AUTH -DDEBUG_CLASS_MATCHING -Wall -O -Wno-unused
-+LIBS=-lssl -lcrypto -lldap -llber
diff --git a/net-misc/dhcp/files/dhcp-3.0.7-potential-buffer-overflow.patch b/net-misc/dhcp/files/dhcp-3.0.7-potential-buffer-overflow.patch
new file mode 100644
index 0000000..4ce0b92
--- /dev/null
+++ b/net-misc/dhcp/files/dhcp-3.0.7-potential-buffer-overflow.patch
@@ -0,0 +1,31 @@
+From: Dmitry V. Levin <ldv@altlinux.org>
+Date: Tue, 14 Jul 2009 22:05:53 +0000 (+0000)
+Subject: client/dhclient.c (script_write_params): Fix potential buffer overflow
+X-Git-Tag: 3.0.7-alt3~1
+X-Git-Url: http://git.altlinux.org/gears/d/dhcp.git?p=dhcp.git;a=commitdiff_plain;h=6d7f731ad28602f5b56c37f6280a2fd94f7ec83c;hp=33bf80b9815d2872cbb0ada6fb040a207c96caa5
+
+client/dhclient.c (script_write_params): Fix potential buffer overflow
+---
+
+diff --git a/dhcp/client/dhclient.c b/dhcp/client/dhclient.c
+index 5570c24..79c52c9 100644
+--- a/dhcp/client/dhclient.c
++++ b/dhcp/client/dhclient.c
+@@ -2513,8 +2513,15 @@ void script_write_params (client, prefix, lease)
+ if (data.len > 3) {
+ struct iaddr netmask, subnet, broadcast;
+
+- memcpy (netmask.iabuf, data.data, data.len);
+- netmask.len = data.len;
++ /*
++ * No matter the length of the subnet-mask option,
++ * use only the first four octets. Note that
++ * subnet-mask options longer than 4 octets are not
++ * in conformance with RFC 2132, but servers with this
++ * flaw do exist.
++ */
++ memcpy(netmask.iabuf, data.data, 4);
++ netmask.len = 4;
+ data_string_forget (&data, MDL);
+
+ subnet = subnet_number (lease -> address, netmask);
diff --git a/net-misc/dhcp/files/dhcp-3.0.7-potential-premature-server-termination.patch b/net-misc/dhcp/files/dhcp-3.0.7-potential-premature-server-termination.patch
new file mode 100644
index 0000000..1cf6c96
--- /dev/null
+++ b/net-misc/dhcp/files/dhcp-3.0.7-potential-premature-server-termination.patch
@@ -0,0 +1,15 @@
+X-Git-Url: http://git.altlinux.org/gears/d/dhcp.git?p=dhcp.git;a=blobdiff_plain;f=dhcp%2Fserver%2Fdhcp.c;h=3dcb49d87d6293e4cf2fb1bf5e2214d256d848fa;hp=31fd31a74b240fd5fb02ccb7d81753dba58bede6;hb=087fec40e650fc2f3ba6083f8c191e696e731f1c;hpb=e50eab553114765b9fb382438981100df9e4d522
+
+diff --git a/dhcp/server/dhcp.c b/dhcp/server/dhcp.c
+index 31fd31a..3dcb49d 100644
+--- a/dhcp/server/dhcp.c
++++ b/dhcp/server/dhcp.c
+@@ -1800,6 +1800,8 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
+ host_reference (&host, h, MDL);
+ }
+ if (!host) {
++ if (hp)
++ host_dereference (&hp, MDL);
+ find_hosts_by_haddr (&hp,
+ packet -> raw -> htype,
+ packet -> raw -> chaddr,
diff --git a/net-misc/dhcp/files/dhcp-3.0.7-radius-v3.patch b/net-misc/dhcp/files/dhcp-3.0.7-radius-v3.patch
new file mode 100644
index 0000000..74a7bb6
--- /dev/null
+++ b/net-misc/dhcp/files/dhcp-3.0.7-radius-v3.patch
@@ -0,0 +1,2990 @@
+diff -ruN dhcp-3.0.7.orig/common/dhcp2radius.c dhcp-3.0.7/common/dhcp2radius.c
+--- dhcp-3.0.7.orig/common/dhcp2radius.c 1970-01-01 03:00:00.000000000 +0300
++++ dhcp-3.0.7/common/dhcp2radius.c 2009-09-06 14:15:53.000000000 +0400
+@@ -0,0 +1,2011 @@
++/* START PATCH CODE */
++#include <stdio.h>
++#include <string.h>
++#include <stdint.h>
++#include <stdlib.h>
++#include <openssl/md5.h>
++#include <signal.h>
++#include <sys/ioctl.h>
++#include <sys/socket.h>
++#include <sys/types.h>
++#include <netinet/in.h>
++#include <net/if_arp.h>
++#include <arpa/inet.h>
++#include <time.h>
++
++#include "dhcpd.h"
++#include "dhcp2radius.h"
++
++int32_t use_dhcp2radius;
++
++XID_NODE * xid_list_top = 0; /* Указатель на начало списка кэша DHCP */
++XID_NODE * xid_list_ptr = 0; /* указатель на текущий элемент списка кэша DHCP */
++struct counter_node * counter = 0; /* Указатель на нулевой элемент массива-счётчика частоты запросов */
++uint16_t counter_end = 0; /* Содержит индекс последующего элемента за последним
++ используемым элементом счётчика */
++uint16_t counter_size = MIN_COUNTER_SIZE; /* Указывает текущий размер массива счётчика частоты запросов */
++time_t xid_ttl = DEFAULT_XID_TTL; /* Время в течение которого хранятся узлы кэша */
++uint16_t radius_port = RADIUS_PORT; /* Порт на который релей отправляет RADIUS запросы. По умолчанию равен 1812 */
++float max_qps = MAX_DHCP_QPS; /* Максимально допустимая частота отправки DHCP запросов
++ всеми клиентами суммарно */
++float max_qps_from_host = MAX_QPS_FROM_HOST; /* Максимально допустимая частота
++ отправки запросов DHCP одним клиентом */
++uint32_t cache_list_len = MAX_CACHE_LIST_LEN; /* Максимальная длина кэша DHCP. Переменная нужна для возможности
++ задания этого параметра из командной строки.
++ В данной версии - не реализовано */
++int16_t dhcp_cache_len = 0; /* Текущая длина кэша */
++time_t normal_clients_counter[QUERY_TIME_RING_LEN]; /* Массив используемый как кольцевой буфер для
++ подсчёта частоты запросов в секунду */
++uint16_t ring_ptr; /* Указатель на последний элемент кольцевого буфера для подсчёта частоты DHCP запросов */
++struct sockaddr_in * radius_servers; /* Указатель на список массив хранящий адреса RADIUS серверов */
++int radius_servers_count; /* Число доступных RADIUS серверов */
++int unfinished_requests; /* Переменная хранящая число необработанных RADIUS-сервером запросов.
++ Т.е. число DHCP запросов для которых не получены ответы RADIUS сервера.
++ Переменная используется для обнаружения "падения" RADIUS сервера и
++ переключения на резервный сервер, если таковой указан */
++int server_index = BASIC_SERVER_INDEX; /* Индекс массива серверов, указывающий на RADIUS сервер
++ к которому в текущий момент времени пересылаются запросы */
++uint32_t time_to_restore_primary_server_index; /* Время (в секундах) через которое производится попытка переключиться
++ на первичный RADIUS сервера, если на данный момент осуществлено
++ переключение на резервный */
++time_t primary_server_down_time; /* Фиксируется время (секунд), в которое "упал" PRIMARY RADIUS сервер */
++#ifdef __linux__
++int updating_arp_cache_perm; /* Указывает - обновлять ли ARP кэш при получении RADIUS сообщений с cached == 0 */
++int arp_cache_perm_len = DEF_ARP_CACHE_PERM_LEN; /* Длина массива хранящего кэш статических (флаг PERM) ARP записей */
++int arp_entry_count; /* Число зафиксированных ARP в текущий момент времени */
++struct arp_entry * arp_cache_perm; /* Указатель на начало динамического массива содержащего ARP записи */
++#endif
++struct ignored_dhcp_interface * start_dhcp_ignor_list = 0; /* Указатель на список интерфейсов на которых
++ игнорируются DHCP запросы */
++struct ignored_dhcp_interface * end_dhcp_ignor_list = 0; /* Указатель на последний элемент списка */
++const uint8_t magic_cookie[] = {99, 130, 83, 99};
++
++unsigned char rad_secret[RAD_SECRET_SIZE]; /* Пароль для доступа на Radius-сервер */
++unsigned char rad_users_passwd[RAD_PASSWD_SIZE]; /* Пароль пользователя, в качестве имени применяется MAC адрес клиента */
++
++unsigned long forward_client_packets_errors; /* Хранит число неудачных попыток передать запрос на RADIUS сервер */
++uint16_t radius_dhcp_relay_port; /* Порт с которого отправляет запрос DHCP relay агент */
++int radius_allow_cache; /* Переменная указывающая на возможность кэширования ответов RADIUS */
++int radius_allow_dynamic_cache; /* Переменная указывающая на возможность кэширования ответов для клиентов
++ не имеющих привязки MAC -> IP */
++int radius_use_mac_delim; /* Использовать ":" в качестве разделителя MAC адреса в запросах к
++ RADIUS серверу, если true */
++uint8_t * opts_send_to_srv; /* Указатель на массив опций отправляемых на RADIUS сервер при запросе
++ клиентом адреса. Инициализируется в случае использования
++ опции radius-send-opts-to-srv */
++
++isc_result_t got_radius_packet(uint8_t * raw_packet, uint32_t length)
++{
++ RAD_MESSAGE auth_pack;
++ int rad_msg_len = 0;
++ char str_dhcp_type[20] = ""; /* Строка используемая для вывода в лог строкового представления
++ типа пакета, например: DHCPDISCOVER, DHCPACK и т.д.*/
++ struct interface_info * out = 0; /* Указатель определяющий выходной интерфейс для отправляемого пакета */
++ struct sockaddr_in to; /* IP информация о хосте назначения пакета */
++ struct hardware hto, *htop; /* Физический адрес хоста назначения */
++ struct in_addr user_if; /* Интерфейс хоста на котором запущен dhcpd находящийся в подсети клиента */
++
++ static struct rad_header prev_rad_pack;
++ if(memcmp(&prev_rad_pack, raw_packet, sizeof(prev_rad_pack)))
++ memcpy(&prev_rad_pack, raw_packet, sizeof(prev_rad_pack)); /* Новый пакет, сохраняем его копию */
++ else
++ return ISC_R_UNEXPECTED; /* Дубликат */
++
++ if (length < sizeof(struct rad_header))
++ {
++ log_error("PATCH: received RADIUS packet with invalid length: %d, minimum lenght is: %d",
++ length, sizeof(struct rad_header));
++ return ISC_R_UNEXPECTED;
++ }
++ /* Обрабатываем полученный ответ RADIUS сервера преобразовывая его в DHCP */
++ if( !(length = dispatch_radius_packet((struct dhcp_packet*) raw_packet, length, &user_if, &hto.hbuf[1])))
++ return ISC_R_UNEXPECTED;
++
++ /* Ищем среди списка обслуживаемых интерфейсов интерфейс расположенный в подсети
++ клиента запросившего адрес что бы отправить ответ через него */
++ for (out = interfaces; out; out = out -> next)
++ if (!memcmp (&out -> primary_address, &user_if, sizeof (user_if)))
++ break;
++
++ if(!out)
++ {
++ log_info("No such interface for sending BOOTREPLY (user interface %s)", inet_ntoa(user_if));
++ return ISC_R_UNEXPECTED;
++ }
++
++ bzero(&to, sizeof(to));
++
++ struct dhcp_packet * dhcp_pack = (struct dhcp_packet *) raw_packet;
++
++ if ( ( !(dhcp_pack -> flags & htons (BOOTP_BROADCAST) )/* Отправляем юникастом если нет флага BROADCAST */
++ || dhcp_pack -> giaddr.s_addr ) ) /* Или если пакет должен быть отправлен через агента пересылки */
++ {
++ to.sin_addr = dhcp_pack -> giaddr.s_addr ? dhcp_pack -> giaddr : dhcp_pack -> yiaddr;
++ to.sin_port = dhcp_pack -> giaddr.s_addr ? radius_dhcp_relay_port : remote_port;
++ htop = &hto;
++ }
++ else
++ {
++ to.sin_addr.s_addr = htonl (INADDR_BROADCAST);
++ to.sin_port = remote_port;
++ /* hardware address is broadcast */
++ htop = NULL;
++ }
++ to.sin_family = AF_INET;
++#ifdef HAVE_SA_LEN
++ to.sin_len = sizeof to;
++#endif
++
++ /* Задаём тип и длину физического адреса хоста назначения */
++ hto.hbuf [0] = dhcp_pack -> htype;
++ hto.hlen = dhcp_pack -> hlen + 1;
++
++ /* Определяем тип DHCP сообщения отправляемого клиенту */
++ bzero(str_dhcp_type, sizeof(str_dhcp_type));
++ get_dhcp_type(dhcp_pack, str_dhcp_type);
++
++ if (send_packet (out,
++ (struct packet *)0,
++ dhcp_pack, length, out -> primary_address,
++ &to, htop) < 0) {
++ ++forward_client_packets_errors;
++ }
++ else
++ {
++ static char to_str[16];
++ strncpy(to_str, inet_ntoa(to.sin_addr), sizeof(to_str) - 1);
++ log_info ("Convert RADIUS-reply for %s in %s (IP: %s) and %s to %s",
++ print_hw_addr (dhcp_pack -> htype, dhcp_pack -> hlen, dhcp_pack -> chaddr),
++ str_dhcp_type,
++ inet_ntoa(dhcp_pack -> yiaddr),
++ dhcp_pack -> giaddr.s_addr ? "forwarded" : "sended",
++ to_str);
++ }
++ return ISC_R_SUCCESS;
++}
++
++isc_result_t got_dhcp_packet(uint8_t * raw_packet, uint32_t length, const struct sockaddr_in * from,
++ struct interface_info * ip, struct hardware * hfrom)
++{
++ RAD_MESSAGE auth_pack;
++ time_t now;
++ char str_dhcp_type[20] = ""; /* Строка используемая для вывода в лог строкового представления
++ типа пакета, например: DHCPDISCOVER, DHCPACK и т.д.*/
++ uint8_t from_cache = 0;
++ struct interface_info * out = 0; /* Указатель определяющий выходной интерфейс для отправляемого пакета */
++ struct sockaddr_in to; /* IP информация о хосте назначения пакета */
++ struct hardware hto, *htop; /* Физический адрес хоста назначения */
++
++ int ret = 0;
++
++ if(time(&now) == (time_t) -1)
++ {
++ log_error("time() failed! Processing packet aborted.");
++ return ISC_R_UNEXPECTED;
++ }
++
++
++ /* Иначе это запрос от DHCP клиента или агента пересылки.
++ Сперва проверяем пакет на соответствие минимальной длине */
++ if (length < DHCP_FIXED_NON_UDP - DHCP_SNAME_LEN - DHCP_FILE_LEN)
++ return ISC_R_UNEXPECTED;
++
++ struct dhcp_packet * dhcp_pack = (struct dhcp_packet*) raw_packet;
++
++ /* Проверяем не получен-ли запрос с интерфейса на котором игнорируются DHCP запросы */
++ if(from -> sin_port == remote_port && found_ignored_interfase(ip -> name))
++ {
++ bzero(str_dhcp_type, sizeof(str_dhcp_type));
++ get_dhcp_type(dhcp_pack, str_dhcp_type);
++ log_info("INFO: Ignore %s from %s on interface %s",
++ str_dhcp_type,
++ print_hw_addr (dhcp_pack -> htype, dhcp_pack -> hlen, dhcp_pack -> chaddr),
++ ip -> name);
++ return ISC_R_UNEXPECTED;
++ }
++ /* Обрабатываем DHCP запрос, в результате выполнения этой функции
++ либо получаем сформированный RADIUS запрос (в структуре auth_pack),
++ либо если для данного клиента найдена информация в кэше - получаем
++ сформированный BOOTREPLY (в структуре на которую указывает raw_packet).
++ Длина выходной информации сохраняется в переменной length */
++ ret = dispatch_dhcp_packet((struct dhcp_packet*)raw_packet, &length, ip, hfrom,
++ &from_cache, &auth_pack);
++
++ if(!ret)
++ return ISC_R_UNEXPECTED;
++
++ if(ret < 0)
++ {
++ log_info("INFO: Can't processed DHCP packet.");
++ return ISC_R_UNEXPECTED;
++ }
++
++ /* Если задано время через которое производится попытка
++ тестирования упавшего первичного RADIUS сервера на
++ работоспособность, то пробуем переключиться на него */
++ if(time_to_restore_primary_server_index
++ &&
++ (server_index != PRIMARY_SERVER_INDEX)
++ )
++ {
++ if( (now = time(0)) == ((time_t) -1))
++ {
++ log_fatal("FATAL: time() error! Abort execution. Quit.");
++ exit (-1);
++ }
++ if( (now - primary_server_down_time) >
++ time_to_restore_primary_server_index)
++ {
++ server_index = PRIMARY_SERVER_INDEX;
++ log_info("INFO: Primary server down %u seconds earlier. Attempting change RADIUS server to primary: %s",
++ now - primary_server_down_time,
++ inet_ntoa(radius_servers[server_index].sin_addr));
++ unfinished_requests = 0;
++ }
++ }
++
++ /* Проверяем - не ушёл ли RADIUS-сервер в down */
++ if(!from_cache &&
++ is_unfinished_requests_overflow(&unfinished_requests, INC, MAX_UNFINISHED_REQ, ZEROING_UNFIN_REQ))
++ {
++ log_info("ERROR: RADIUS server %s down!", inet_ntoa(radius_servers[server_index].sin_addr));
++ /* Если упал первичный сервер, то отмечаем последнее время падения */
++ if(server_index == PRIMARY_SERVER_INDEX)
++ {
++ primary_server_down_time = time(0);
++ if(primary_server_down_time == ((time_t) -1))
++ {
++ log_fatal("FATAL: time() error! Abort execution. Quit.");
++ exit (-1);
++ }
++ }
++ /* Если есть дублирующие сервера, то переключаемся на следующий */
++ if(radius_servers_count > 1)
++ {
++ if(server_index == radius_servers_count - 1)
++ server_index = 0;
++ else ++server_index;
++ log_info("WARN: Changing RADIUS server to %s (#%d)",
++ inet_ntoa(radius_servers[server_index].sin_addr), server_index + 1 );
++ unfinished_requests = 0;
++ }
++ else log_info("ERROR: can't change the server, because there are no duplicating servers.");
++ }
++
++ /* Если переменная from_cache != 0, это значит что в структуре на которую указывает
++ dhcp_pack содержится BOOTREPLY из кэша dhcpd и нет необходимости отправлять
++ запрос на RADIUS сервер. Потому сразу отправляем ответ DHCP клиенту */
++ bzero(&to, sizeof(to));
++ to.sin_family = AF_INET;
++ if(from_cache)
++ {
++ out = ip;
++ /* Задаём физический адрес хоста назначения */
++ if(dhcp_pack -> giaddr.s_addr)
++ memcpy(&hto.hbuf[1], &hfrom -> hbuf[1], hfrom -> hlen - 1);
++ else
++ memcpy(&hto.hbuf [1], dhcp_pack -> chaddr, dhcp_pack -> hlen);
++ hto.hbuf [0] = dhcp_pack -> htype;
++ hto.hlen = dhcp_pack -> hlen + 1;
++
++ if (!(dhcp_pack -> flags & htons (BOOTP_BROADCAST)) &&
++ can_unicast_without_arp (out))
++ {
++ to.sin_addr = dhcp_pack -> giaddr.s_addr ? dhcp_pack -> giaddr : dhcp_pack -> yiaddr;
++ to.sin_port = dhcp_pack -> giaddr.s_addr ? radius_dhcp_relay_port : remote_port;
++ htop = &hto;
++ }
++ else
++ {
++ to.sin_addr.s_addr = htonl (INADDR_BROADCAST);
++ to.sin_port = remote_port;
++ /* hardware address is broadcast */
++ htop = NULL;
++ }
++ }
++ else /* from_cache == 0 - запрос от клиента не найден в кэше, потому */
++ { /* пересылаем его на RADIUS сервер */
++ to = radius_servers[server_index];
++ out = ((fallback_interface) ? fallback_interface : interfaces);
++ }
++
++ if (send_packet
++ (
++ out,
++ (struct packet *)0,
++ ((from_cache)? dhcp_pack : (struct dhcp_packet *)&auth_pack),
++ length, out -> primary_address, &to, (struct hardware *)htop
++ ) < 0
++ )
++ {
++ log_error("PATCH: Error - can't send packet to %s (%s/%s)",
++ inet_ntoa (to.sin_addr),
++ print_hw_addr (dhcp_pack -> htype, dhcp_pack -> hlen, dhcp_pack -> chaddr), out -> name);
++ ++forward_client_packets_errors;
++ }
++ else
++ {
++ static char to_str[16];
++ strncpy(to_str, inet_ntoa(to.sin_addr), sizeof(to_str) - 1);
++
++ static char from_str[16]; /* Строка используемая для сохранения строкового представления
++ IP адреса агента пересылки если таковой используется */
++ if(dhcp_pack -> giaddr.s_addr)
++ strncpy(from_str, inet_ntoa(dhcp_pack -> giaddr), sizeof(from_str));
++
++ bzero(str_dhcp_type, sizeof(str_dhcp_type));
++ get_dhcp_type(dhcp_pack, str_dhcp_type);
++
++ if(from_cache)
++ log_info("Creating %s (IP: %s) for %s/%s and %s to %s",
++ str_dhcp_type,
++ inet_ntoa(dhcp_pack -> yiaddr),
++ print_hw_addr (dhcp_pack -> htype, dhcp_pack -> hlen, dhcp_pack -> chaddr),
++ ip -> name,
++ (dhcp_pack -> giaddr.s_addr) ? "forwarded" : "sended",
++ to_str);
++ else
++ log_info ("Convert %s %s/%s to RADIUS and %s to %s",
++ str_dhcp_type,
++ print_hw_addr (dhcp_pack -> htype, dhcp_pack -> hlen, dhcp_pack -> chaddr),
++ dhcp_pack -> giaddr.s_addr ? from_str : ip -> name, /* Если агент пересылки не используется -
++ указываем имя интерфейса на котором получен запрос */
++ "forwarded",
++ to_str);
++ }
++ return ISC_R_SUCCESS;
++}
++
++/*
++ Функция удаляющая кэшированные xid узлы при изменении соответствия IP - MAC клиента.
++ Такое возможно в случае смены MAC-адреса клиента: старому IP адресу будет соответстовать
++ новый MAC адрес, старая информация из кэша должна быть удалёна.
++*/
++int delete_xid_if_mac_not_equal(uint32_t ip, uint8_t * mac)
++{
++ XID_NODE * xid_ptr = xid_list_top;
++ while(xid_ptr)
++ {
++ if( xid_ptr -> out_packet &&
++ (xid_ptr -> out_packet -> yiaddr.s_addr == ip) &&
++ memcmp(mac, xid_ptr -> out_packet -> chaddr, MAC_ADDR_LEN)
++ )
++ xid_ptr = delete_xid(xid_ptr);
++ else
++ xid_ptr = xid_ptr -> next;
++ }
++ return 1;
++}
++
++#ifdef __linux__
++/*
++ Получаем ARP-кэш статически привязанных MAC адресов из ядра ОС.
++ ДАННЫЙ ВАРИАНТ ПОДХОДИТ ТОЛЬКО ДЛЯ LINUX!!!
++*/
++int get_arp_cache_perm(void)
++{
++
++ int type, flags, num;
++ char ip[16];
++ char string[256];
++ char mask[20];
++ char device[20];
++ unsigned char hw[MAC_ADDR_LEN];
++ FILE * proc_fd = fopen(PROC_ARP, "r");
++ if(!proc_fd)
++ log_fatal("FATAL: Can't open system ARP-table in: %s", PROC_ARP);
++ arp_entry_count = 0;
++ bzero(string, sizeof(string));
++ bzero(ip, sizeof(ip));
++ while(fgets(string, sizeof(string), proc_fd))
++ {
++ if(arp_entry_count == arp_cache_perm_len)
++ {
++ arp_cache_perm_len *= 2;
++ log_info("INFO: Reallocating memory for ARP cache. New size is: %d", arp_cache_perm_len);
++ arp_cache_perm = (struct arp_entry*) realloc(arp_cache_perm, arp_cache_perm_len * sizeof(struct arp_entry));
++ if(!arp_cache_perm)
++ return 0;
++ }
++ num = sscanf(string, "%s 0x%x 0x%x %X:%X:%X:%X:%X:%X %100s %100s\n",
++ ip, &type, &flags,
++ &hw[0], &hw[1], &hw[2], &hw[3], &hw[4], &hw[5],
++ mask, device);
++ if(num < 4)
++ continue;
++ if(flags & ATF_PERM)
++ {
++ if(!inet_aton(ip, &arp_cache_perm[arp_entry_count].ip))
++ {
++ log_error("ERROR: Can't convert IP from ARP cache to binary format.");
++ continue;
++ }
++ memcpy(arp_cache_perm[arp_entry_count].mac, hw, MAC_ADDR_LEN);
++ ++ arp_entry_count;
++ }
++ }
++ return 1;
++}
++
++/*
++ Функция обновляющая ARP таблицу ОС согласно информации полученной с RADIUS сервера.
++ Выполняется при смене физического адреса клиента в базе RADIUS.
++*/
++int update_arp_cache_perm(uint32_t ip, unsigned char * mac)
++{
++ int i;
++ int ip_found = 0;
++ /* Обновляем информацию в собственной ARP таблице dhcpd */
++ for(i = 0; i < arp_entry_count; ++i)
++ {
++ if(arp_cache_perm[i].ip.s_addr == ip)
++ {
++ if(!memcmp(arp_cache_perm[i].mac, mac, MAC_ADDR_LEN)) /* Если переданный и найденный MAC адреса равны, */
++ return 0; /* то выходим, т.к. нечего обновлять */
++ ip_found = 1;
++ break;
++ }
++ }
++ if(!ip_found) /* Если IP адрес не найден в текущей ARP таблице, */
++ { /* то добавляем его в таблицу */
++ if(arp_entry_count == arp_cache_perm_len) /* Если ARP таблица dhcpd заполнена на 100%, */
++ { /* выделяем для неё дополнительную память */
++ arp_cache_perm_len *= 2;
++ arp_cache_perm = (struct arp_entry*) realloc(arp_cache_perm, arp_cache_perm_len * sizeof(struct arp_entry));
++ if(!arp_cache_perm)
++ return -1;
++ }
++ arp_cache_perm[i].ip.s_addr = ip; /* Заполняем поле IP адрес в новой строке ARP таблицы dhcpd */
++ ++ arp_entry_count;
++ }
++ memcpy(arp_cache_perm[i].mac, mac, MAC_ADDR_LEN); /* Копируем новый MAC адрес в ARP таблицу dhcpd */
++
++ /* Обновляем ARP таблицу ядра ОС */
++ struct arpreq req;
++ uint32_t sockfd;
++ if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
++ {
++ log_error("ERROR: Create socket for update ARP cache failed.");
++ return -1;
++ }
++ bzero((char *) &req, sizeof(req));
++ req.arp_pa.sa_family = PF_INET;
++ memcpy((char *)&req.arp_pa.sa_data + 2, &ip, sizeof(ip));
++ req.arp_ha.sa_family = PF_LOCAL;
++ memcpy(req.arp_ha.sa_data, mac, MAC_ADDR_LEN);
++ req.arp_flags = ATF_PERM | ATF_COM;
++ if (ioctl(sockfd, SIOCSARP, &req) < 0)
++ {
++ log_error("ERROR: ioctl for set ARP entry failed.");
++ return -1;
++ }
++
++ return 1;
++}
++#endif
++
++/*
++ Функция выполняет подсчёт общего усреднённого числа DHCP запросов от всех клиентов
++ за единицу времени TIME_DELTA, а так же - подсчёт усреднённого числа запросов
++ от конкретного хоста указанного в mac_addr. Любой из параметров
++ функции может быть равен нулю. Вызов функции с обоими параметрами равными нулю
++ можно применить для принудительного уменьшения размера счётчика,
++ без внешнего запроса от DHCP клиента - если в счётчике будут обнаружены
++ устаревшие элементы.
++*/
++float qps_hosts(uint8_t * mac_addr, float * qps_summary)
++{
++ float hits = 0;
++ time_t now = time(0);
++ int i = 0;
++
++ if(qps_summary)
++ *qps_summary = 0;
++ /* Проверяем достаточно-ли места для добавления нового элемента в счётчик */
++ if(mac_addr && (counter_size <= counter_end) )
++ { /* Перераспределяем память для счётчика */
++ counter_size *= 2; /* Увеличиваем размер массива счётчика в 2 раза*/
++ counter = (struct counter_node*) realloc(counter, sizeof(struct counter_node) * counter_size);
++ if(!counter)
++ {
++ log_fatal("FATAL: realloc for resizing QPS counter failed!");
++ }
++ log_info("INFO: Realloc memory for QPS counter. New counter size is: %u", counter_size);
++ }
++ if(mac_addr)
++ { /* Добавляем новый элемент в счётчик */
++ memcpy(counter[counter_end].mac_addr, mac_addr, MAC_ADDR_LEN);
++ counter[counter_end].timestamp = now;
++ }
++
++ ++ counter_end;
++
++ /* Начало обработки статистической информации */
++ for(;i < counter_end; i++)
++ { /* Это условие выполняется если узел устарел */
++ if( (now - counter[i].timestamp) > TIME_DELTA )
++ { /* Удаляем устаревший узел */
++ counter[i] = counter[counter_end - 1]; /* Просто переносим в него
++ значение последнего элемента счётчика */
++ -- counter_end; /* И укорачиваем счётчик на 1 элемент */
++ -- i;
++ continue;
++ }
++
++ /* Производим подсчёт запросов для конкретного хоста */
++ if( mac_addr /* Считаем только если в функцию передан адрес хоста-источника */
++ &&
++ !memcmp(counter[i].mac_addr, mac_addr, MAC_ADDR_LEN)
++ &&
++ (now - counter[i].timestamp <= TIME_DELTA_HOST)
++ )
++ { /* Найден узел содержащий информацию о хосте пославшем данный запрос */
++ ++hits;
++ }
++ }
++ /* Производим подсчёт общего числа запросов за TIME_DELTA. Т.к. все устаревшие
++ узлы уже удалены, то общее число запросов равно числу значимых элементов счётчика */
++ if(qps_summary)
++ *qps_summary = counter_end;
++ /* Проверяем, если значение размера счётчика больше минимально допустимого
++ и хотя бы 60% массива счётчика не используется, то перераспределяем память
++ освобождая не используемые участки */
++ if(counter_size > MIN_COUNTER_SIZE
++ &&
++ (counter_end - 1) < ((counter_size / 10) * 4) /* Во второй части сравнения вычисляется 40% размера счётчика */
++ )
++ {
++ counter_size /= 2;
++ counter = (struct counter_node*) realloc(counter, sizeof(struct counter_node) * counter_size);
++ if(!counter)
++ log_fatal("FATAL: realloc failed for QPS counter!");
++ log_info("INFO: Realloc memory for QPS counter. New counter size is: %u", counter_size);
++ }
++ /* Вычисляем среднее число запросов в секунду за TIME_DELTA */
++ if(qps_summary)
++ (*qps_summary) /= TIME_DELTA;
++ return hits / TIME_DELTA_HOST;
++}
++
++/*
++ Подсчитывает среднее число DHCP запросов в секунду за время TIME_DELTA секунд от всех клиентов
++*/
++float count_queries_per_sec(void)
++{
++ uint16_t queries_count = 0;
++ time_t now = time(0);
++ int i = 0;
++
++ time_t oldest_time = 0, newest_time = 0;
++
++ if(ring_ptr == QUERY_TIME_RING_LEN)
++ oldest_time = normal_clients_counter [0];
++ else
++ oldest_time = normal_clients_counter [ring_ptr];
++ if(ring_ptr == 0)
++ newest_time = normal_clients_counter [QUERY_TIME_RING_LEN - 1];
++ else
++ newest_time = normal_clients_counter [ring_ptr - 1];
++
++ if( (now - newest_time) > TIME_DELTA)
++ return 0;
++
++ if(newest_time - oldest_time > 0)
++ return QUERY_TIME_RING_LEN / (newest_time - oldest_time) ;
++ return (float)0xFFFFFFFF;
++}
++
++/*
++ Функция сменяющая текущий используемый RADIUS сервер
++ при получении внешнего сигнала SIGNAL_CHANGE_SERV
++*/
++void change_server(int sign)
++{
++ log_info("INFO: Recv SIGNAL_CHANGE_SERV signal.");
++ if(radius_servers_count > 1)
++ {
++ if(server_index == PRIMARY_SERVER_INDEX)
++ primary_server_down_time = time(0);
++ if(server_index == radius_servers_count - 1)
++ server_index = 0;
++ else ++server_index;
++ log_info("INFO: Changing RADIUS server to %s (#%d)",
++ inet_ntoa(radius_servers[server_index].sin_addr), server_index + 1 );
++ unfinished_requests = 0;
++ }
++ else log_info("ERROR: can't change the server, because there are no duplicating servers.");
++ return;
++}
++
++/*
++ Функция устанавливающая текущим RADIUS сервером - первичный сервер, т.е. сервер
++ заданный первым в параметрах командной строки при получении сигнала SIGNAL_SET_PRI_SERVER
++*/
++inline void set_default_server(int sign)
++{
++ log_info("INFO: receiving SIGNAL_SET_PRI_SERVER signal. Current server is: %s",
++ inet_ntoa(radius_servers[server_index].sin_addr));
++ server_index = BASIC_SERVER_INDEX;
++ log_info("INFO: Set RADIUS server to: %s", inet_ntoa(radius_servers[server_index].sin_addr));
++ return;
++}
++
++/*
++ Функция выводящая в лог статистическую информацию и содержимое DHCP кэша релея
++ при получении сигнала SIGSTAT
++*/
++void print_stat(int sign)
++{
++ XID_NODE * tmp_ptr = xid_list_top;
++ int numb = 0;
++ struct in_addr ip;
++ time_t ttl;
++ float qps = 0;
++ char dhcp_info[1024];
++
++ log_info ("#*************************************************************************#");
++ log_info ("dhcpd patch version: %s", PATCH_VERSION);
++ log_info ("Current XID's list:");
++ log_info ("---");
++ for(;tmp_ptr; ++numb)
++ {
++ log_info("XID number: %u", numb + 1);
++ log_info("XID value: %u", ntohl(tmp_ptr -> xid));
++ log_info("XID rad_req.id: %u", tmp_ptr -> req_header.id);
++ ip.s_addr = tmp_ptr -> relay_if_index;
++ log_info("XID relay_if_index: %u (%s)", ntohl(tmp_ptr -> relay_if_index), inet_ntoa(ip));
++ ip.s_addr = tmp_ptr -> if_index;
++ log_info("XID if_index: %u (%s)", ntohl(tmp_ptr -> if_index), inet_ntoa(ip));
++ log_info("XID DHCP client MAC address: %s", print_hw_addr (1, MAC_ADDR_LEN, tmp_ptr-> chaddr));
++ log_info("XID hw_from MAC address: %s", print_hw_addr (1, MAC_ADDR_LEN, tmp_ptr-> hw_from));
++ switch(tmp_ptr -> server_msg_type)
++ {
++ case DHCPOFFER: log_info("Last server response: DHCPOFFER"); break;
++ case DHCPACK: log_info("Last server response: DHCPACK"); break;
++ case DHCPNAK: log_info("Last server response: DHCPNAK"); break;
++ case 0: log_info("Last server response: Server not respond yet"); break;
++ default: log_info("Unknown server response: %u", tmp_ptr -> server_msg_type); break;
++ }
++ switch(tmp_ptr -> client_msg_type)
++ {
++ case DHCPDISCOVER: log_info("Last client request: DHCPDISCOVER"); break;
++ case DHCPREQUEST: log_info("Last client request: DHCPREQUEST"); break;
++ default: log_info("Last client request: unknown client request type"); break;
++ }
++
++ if(tmp_ptr -> dhcp_flags & htons (BOOTP_BROADCAST))
++ log_info("XID flags: BROADCAST");
++ ttl = xid_ttl - (time(0) - tmp_ptr -> timestamp);
++ log_info("XID ttl: %u", (ttl > 0)? ttl: 0);
++
++ if(tmp_ptr -> out_packet && (tmp_ptr -> out_packet -> op == BOOTREPLY) && tmp_ptr -> allow_cache)
++ {
++ bzero(dhcp_info, sizeof(dhcp_info));
++ memcpy(&ip, &tmp_ptr -> out_packet -> yiaddr, sizeof(struct in_addr));
++ strcat(dhcp_info, "you addr: ");
++ strcat(dhcp_info, inet_ntoa(ip));
++ if(get_dhcp_option(tmp_ptr -> out_packet, tmp_ptr -> out_pack_len, DHO_SUBNET_MASK, &ip.s_addr, sizeof(ip.s_addr)))
++ strcat(dhcp_info, " subnet mask: ");
++ strcat(dhcp_info, inet_ntoa(ip));
++ if(get_dhcp_option(tmp_ptr -> out_packet, tmp_ptr -> out_pack_len, DHO_ROUTERS, &ip.s_addr, sizeof(ip.s_addr)))
++ strcat(dhcp_info, " default gw: ");
++ strcat(dhcp_info, inet_ntoa(ip));
++ log_info("DHCP info: '%s'", dhcp_info);
++ }
++ log_info("---");
++
++ tmp_ptr = tmp_ptr -> next;
++ }
++ log_info ("End XID list. Summary XID count: %u.", numb);
++ qps_hosts(0, &qps);
++ log_info ("QPS: %g", count_queries_per_sec());
++ log_info ("DHCP cache lenght: %u", dhcp_cache_len);
++ if(server_index != PRIMARY_SERVER_INDEX)
++ {
++ char * down_time;
++ down_time = ctime(&primary_server_down_time);
++ down_time[strlen(down_time) - 1] = 0;
++ log_info("Primary server down time: %s", down_time);
++ }
++ log_info ("Current RADIUS server: %s%s",
++ inet_ntoa(radius_servers[server_index].sin_addr),
++ (server_index == PRIMARY_SERVER_INDEX)? " (primary)": " (backup server)");
++ log_info ("Unfinished RADIUS requests: %u", unfinished_requests);
++
++ log_info("Hits counter lenght: %u", counter_end);
++ log_info("Hits counter size: %u", counter_size);
++#ifdef __linux__
++ if(updating_arp_cache_perm)
++ log_info("ARP entry count: %d", arp_entry_count);
++#endif
++ log_info ("#*************************************************************************#");
++ return;
++}
++
++/*
++ Функция шифрующая пароль для доступа к RADIUS-серверу.
++ INCOMPLETE: Текущий вариант не соответствует требованиям безопасности предъявляемым
++ к RADIUS клиентам. В данной ситуации это не слишком опасно, т.к. протокол
++ DHCP в своём чистом виде в принципе не поддерживает шифрование передаваемой информации.
++*/
++int encrypt_passwd(char * passwd,
++ uint8_t * encr_passwd, char *shared_key,
++ uint8_t * auth)
++{
++ unsigned char full_passwd[16];
++ uint8_t md5_hash[16];
++ unsigned int i = 0;
++ MD5_CTX context;
++
++ /* Verify input data */
++ if(!passwd || (strlen(passwd) > 16))return 0;
++ if(!encr_passwd) return 1;
++ if(!shared_key) return 2;
++ if(!auth) return 3;
++
++ bzero(full_passwd, sizeof(full_passwd));
++ bzero(encr_passwd, ENCR_PWD_LEN);
++
++ memcpy(full_passwd, passwd, strlen(passwd)); /* Дополняем пароль до 16ти символов */
++
++ /* Generate MD5 sum for encrypting password */
++ MD5_Init(&context);
++ MD5_Update(&context, shared_key, strlen(shared_key));
++ MD5_Update(&context, auth, MD5_LEN);
++ MD5_Final(md5_hash, &context);
++
++ /* Encrypting password */
++ for(i = 0; i < sizeof(full_passwd); i++)
++ encr_passwd[i] = full_passwd[i] ^ md5_hash[i];
++
++ return ENCR_PWD_LEN;
++}
++
++uint8_t make_radius_vsa(uint8_t * out_buffer, uint8_t ob_len, const uint32_t vendor_id,
++ const uint16_t vsa, const uint8_t vsa_len, uint8_t * vsa_value)
++{
++ uint8_t *buf_ptr = out_buffer;
++ uint8_t const *ob_end = out_buffer + ob_len;
++
++ if(buf_ptr + sizeof(vendor_id) > ob_end)
++ return 0;
++ memcpy(buf_ptr, &vendor_id, sizeof(vendor_id));
++ buf_ptr += sizeof(vendor_id);
++
++ if(buf_ptr + sizeof(vsa) > ob_end)
++ return 0;
++ memcpy(buf_ptr, &vsa, sizeof(vsa));
++ buf_ptr += sizeof(vsa);
++
++ uint8_t full_len = sizeof(vsa) + sizeof(vsa_len) + vsa_len;
++ if(buf_ptr + sizeof(full_len) > ob_end)
++ return 0;
++ memcpy(buf_ptr, &full_len, sizeof(full_len));
++ buf_ptr += sizeof(full_len);
++
++ if(buf_ptr + vsa_len > ob_end)
++ return 0;
++ memcpy(buf_ptr, vsa_value, vsa_len);
++ buf_ptr += vsa_len;
++
++ return buf_ptr - out_buffer;
++}
++
++/*
++ Функция добавляющая RADIUS атрибут rad_attr (значение по адресу * value) в буфер message_buffer.
++ Возвращает число байт на которое увеличился размер буфера занимаемый RADIUS атрибутами
++*/
++inline uint8_t add_radius_attribute(uint8_t * message_buffer, uint8_t const * mb_end,
++ uint8_t rad_attr, void * value, uint8_t value_len)
++{
++ if(message_buffer + VALUE_OFFSET + value_len > mb_end) /* Проверка на переполнение буфера */
++ {
++ log_error("PATCH: Can't add RADIUS attribute - buffer overflow.");
++ return 0;
++ }
++ /* Формат информационного поля RADIUS сообщения.
++ 1 байт - имя атрибута
++ 1 байт - длина атрибута и значения формируется из длин полей: имя атрибута, длина, значение атрибута
++ X байт - значение атрибута
++ */
++ message_buffer[ATTR_OFFSET] = rad_attr;
++ message_buffer[LEN_OFFSET] = value_len + 2;
++ memcpy(&message_buffer[VALUE_OFFSET], value, value_len);
++ return VALUE_OFFSET + value_len;
++}
++/*
++ Функция формирующая RADIUS-Access-Request
++*/
++int assemble_auth_message( RAD_MESSAGE *access_req, const struct dhcp_packet * packet, unsigned length,
++ char *user_name, char *passwd, uint32_t subnet)
++{
++ union
++ {
++ uint8_t auth[MD5_LEN];
++ uint32_t digits[4];
++ }auth_union;
++
++ static uint8_t encr_passwd[ENCR_PWD_LEN];
++ int32_t ret = 0;
++ uint32_t attr_ptr = 0;
++ int32_t i;
++
++ bzero(access_req, sizeof(RAD_MESSAGE));
++ access_req -> header.code = RAD_ACCESS_REQ;
++ access_req -> header.id = (uint8_t) random();
++ uint8_t const * msg_end = access_req -> message + sizeof(access_req -> message);
++
++ for(i = 0; i < 4; i++)
++ auth_union.digits[i] = random(); /* Генерируем случайный идентификатор RADIUS запроса */
++ memcpy(access_req->header.auth, auth_union.auth, MD5_LEN);
++
++ ret = encrypt_passwd(passwd, encr_passwd, rad_secret, auth_union.auth);
++ if(ret != ENCR_PWD_LEN)
++ {
++ log_error ("PATCH: error - encrypt_passwd() failed. Return value %d . Exiting from assemble_auth_message()!", ret);
++ return 0;
++ }
++
++ ret = add_radius_attribute(access_req -> message + attr_ptr, msg_end,
++ USER_NAME_ATTR, user_name, strlen(user_name));
++ if(!ret)
++ return 0;
++ attr_ptr += ret;
++
++ ret = add_radius_attribute(access_req -> message + attr_ptr, msg_end,
++ USER_PASS_ATTR, encr_passwd, ENCR_PWD_LEN);
++ if(!ret)
++ return 0;
++ attr_ptr += ret;
++
++ /* В качестве атрибута NAS_PORT используется IP адрес интерфейса на котором
++ получен DHCP запрос представленный как число типа int32_t */
++ ret = add_radius_attribute(access_req -> message + attr_ptr, msg_end,
++ NAS_PORT, &subnet, sizeof(subnet));
++ if(!ret)
++ return 0;
++ attr_ptr += ret;
++
++ if(opts_send_to_srv) /* Если какие-либо DHCP опции нужно отправить на RADIUS сервер */
++ {
++ uint8_t option_buffer[256];
++ uint8_t option_len;
++ for(i = 0; opts_send_to_srv[i]; ++i)
++ {
++ uint8_t vsa_buffer[254];
++
++ if( (option_len = get_dhcp_option(packet, length, opts_send_to_srv[i], option_buffer, sizeof(option_buffer)) ) )
++ {
++ ret = make_radius_vsa(vsa_buffer, sizeof(vsa_buffer), htonl(VSA_DHCP),
++ htons((const uint16_t) opts_send_to_srv[i]), option_len, option_buffer);
++ if(!ret)
++ return 0;
++
++ ret = add_radius_attribute(access_req -> message + attr_ptr, msg_end, RAD_VSA, vsa_buffer , ret);
++ if(!ret)
++ return 0;
++ attr_ptr += ret;
++ }
++ }
++ }
++
++ int full_packet_len = sizeof(RAD_HEADER) + attr_ptr;
++ if(full_packet_len < RADIUS_MIN_PACK_LEN)
++ full_packet_len = 20;
++
++ access_req->header.pack_len = htons(full_packet_len);
++
++ return full_packet_len;
++}
++
++/*
++ Функция проверяющая соответствие значения аутентификатора в ответе сервера
++ значению аутентификатора в запросе сохранённом в списке кэша.
++*/
++int calc_reply_auth(RAD_MESSAGE *packet, uint8_t *original_auth,
++ const char *secret)
++{
++ uint8_t repl_checksumm[MD5_LEN];
++ uint8_t auth[MD5_LEN];
++ MD5_CTX context;
++
++ if (!original_auth)
++ return -1;
++
++ memcpy(auth, packet->header.auth, MD5_LEN);
++ memcpy(packet->header.auth, original_auth, MD5_LEN);
++
++ MD5_Init(&context);
++ MD5_Update(&context, (uint8_t *)packet, ntohs(packet->header.pack_len));
++ MD5_Update(&context, secret, strlen(secret));
++ MD5_Final(repl_checksumm, &context);
++
++ memcpy(packet->header.auth, auth, MD5_LEN);
++
++ return memcmp(auth, repl_checksumm, MD5_LEN);
++}
++
++/*
++ Функция удаляющая устаревшие элементы кэша DHCP
++*/
++int delete_old_xid(XID_NODE * start_xid_list)
++{
++ XID_NODE * xid_ptr = start_xid_list;
++ int deleted_xid_count = 0;
++ static time_t now;
++ if(time(&now) == (time_t)-1)
++ {
++ log_error("time() failed! Adding xid aborted.");
++ return 0;
++ }
++ while(xid_ptr)
++ {
++ if((now - xid_ptr->timestamp) > xid_ttl)
++ {
++ xid_ptr = delete_xid(xid_ptr);
++ deleted_xid_count++;
++ } else xid_ptr = xid_ptr->next;
++ }
++ return deleted_xid_count;
++}
++
++/*
++ Функция добавляющая новый элемент в DHCP кэш.
++*/
++XID_NODE * add_xid(struct dhcp_packet *packet, uint8_t dhcp_type, uint32_t if_index, struct hardware * hw_from)
++{
++ static time_t now;
++ if(dhcp_type <= 0)
++ {
++ log_info ("INFO Invalid DHCP message type %d for xid: %d hw addr: %s - add_xid aborted.",
++ dhcp_type, ntohl( packet -> xid), print_hw_addr(1, MAC_ADDR_LEN, packet -> chaddr));
++ return 0;
++ }
++
++ if((int)search_xid(packet -> chaddr, if_index, packet -> giaddr.s_addr))
++ return 0; /* Если подобный клиент уже есть в кэше,
++ то не добавляем новый узел */
++
++ if( time(&now) == (time_t) -1 )
++ {
++ log_error("time() failed! Adding xid aborted.");
++ return 0;
++ }
++
++
++ XID_NODE * xid;
++ xid = malloc(sizeof(XID_NODE));
++ if(!xid)
++ {
++ log_error("Creating DHCP cache failed!");
++ return 0;
++ }
++ bzero(xid, sizeof(XID_NODE));
++ xid -> client_msg_type = dhcp_type;
++ xid -> timestamp = now;
++ xid -> if_index = if_index;
++ xid -> relay_if_index = packet -> giaddr.s_addr;
++ xid -> xid = packet -> xid;
++ xid -> dhcp_flags = packet -> flags;
++ memcpy(xid -> chaddr, packet -> chaddr, MAC_ADDR_LEN);
++ memcpy(xid -> hw_from, hw_from -> hbuf + 1, MAC_ADDR_LEN);
++
++ if(!xid_list_top) /* Если в кэше нет ни одного элемента */
++ xid_list_top = xid;
++ else
++ {
++ xid_list_ptr -> next = xid;
++ xid_list_ptr -> next -> prev = xid_list_ptr;
++ }
++
++ xid_list_ptr = xid;
++
++ return xid_list_ptr;
++}
++
++/*
++ Устанавливает указанный тип DHCP сообщения, возвращает предыдущее значение типа
++*/
++uint16_t set_dhcp_type(struct dhcp_packet *request, uint16_t new_type)
++{
++ uint8_t *option = (uint8_t *)request + sizeof (struct dhcp_packet) - DHCP_MAX_OPTION_LEN;
++ const uint8_t * opt_end = (const uint8_t *)request + sizeof(struct dhcp_packet);
++ uint8_t opt_len, old_type;
++ if(memcmp(option, magic_cookie, sizeof(magic_cookie))) /* Выходим если не найдено magic_cookie - */
++ return -1; /* начало поля опций */
++ option += sizeof(magic_cookie);
++ while((option < opt_end) && (*option != 255))
++ {
++ if(*option == DHO_DHCP_MESSAGE_TYPE)
++ {
++ old_type = *(option + 2);
++ *(option + 2) = new_type;
++ if(new_type == DHCPNAK)
++ request -> flags |= htons (BOOTP_BROADCAST); /* Флаг broadcast */
++ return old_type;
++ }
++ else option += *(option + 1) + 2;
++ }
++ return 0;
++}
++
++/*
++ Функция получающая значение заданной опции из DHCP пакета
++*/
++uint8_t get_dhcp_option(const struct dhcp_packet *request, uint16_t packet_len, uint8_t req_option,
++ void * option_value, const size_t value_size)
++{
++ /* Calculate start address for field "options" in DHCP packet */
++ uint8_t *option = (uint8_t *)request + sizeof (struct dhcp_packet) - DHCP_MAX_OPTION_LEN;
++ /* End options equal end packet */
++ const uint8_t * opt_end = (const uint8_t *)request + packet_len;
++ if(memcmp(option, magic_cookie, sizeof(magic_cookie)))/* Check "Magic cookie" in first 4 bytes options-field */
++ {
++ log_info("magic cookie not found!");
++ return -1;
++ }
++ option += sizeof(magic_cookie);
++
++ int opt_len;
++ while((option < opt_end) && (*option != DHO_END))
++ {
++ opt_len = *(option + 1);
++ if((option + opt_len) > opt_end)
++ {
++ log_error("WARN: Invalid value in DHCP-option length. Attempting DoS?");
++ return -1;
++ }
++ /* Возможно что первые некоторые байты поля опций пусты, например
++ в случае применения функции до задания типа DHCP сообщения
++ в функции translate_rad_to_dhcp(), либо в следсвии возможных ошибок протокола */
++ if(!*option)
++ {
++ option += 3; /* Минимальный размер одного поля 3 байта: атрибут(1 байт)|длина (1 байт)|значение(минимум 1 байт). */
++ continue; /* Перескакиваем на следующую опцию. */
++ }
++ if(*option == req_option)
++ {
++ if(opt_len > value_size)
++ {
++ printf("\nWARNING! Option's length is more than was expected (opcode: %d op_len: %d > expected_len: %d). Attempting DoS?\n",
++ *option, opt_len, value_size);
++ return -1;
++ }
++
++ if(option_value)
++ memcpy(option_value, option + 2, opt_len);
++
++ return *(option + 1);
++ }
++ else
++ option += *(option + 1) + 2;
++ }
++ return 0;
++}
++
++/*
++ Функция возвращающая тип DHCP сообщения, а так же строковую информацию о нём через указатель str_dhcp_type
++*/
++uint16_t get_dhcp_type(struct dhcp_packet *request, char * str_dhcp_type)
++{
++ uint8_t *option = (uint8_t *)request + sizeof (struct dhcp_packet) - DHCP_MAX_OPTION_LEN;
++ const uint8_t * opt_end = (const uint8_t *)request + sizeof(struct dhcp_packet);
++ uint8_t opt_len, dhcp_type;
++ if(memcmp(option, magic_cookie, sizeof(magic_cookie)))return -1;
++ option += sizeof(magic_cookie);
++ while((option < opt_end) && (*option != 255))
++ {
++ if(*option == DHO_DHCP_MESSAGE_TYPE)
++ {
++ if(str_dhcp_type)
++ { /*Возвращаем строку указывающую тип*/
++ switch(*(option + 2))
++ {
++ case DHCPDISCOVER: memcpy(str_dhcp_type, "DHCPDISCOVER", strlen("DHCPDISCOVER")); break;
++ case DHCPOFFER: memcpy(str_dhcp_type, "DHCPOFFER", strlen("DHCPOFFER")); break;
++ case DHCPREQUEST: memcpy(str_dhcp_type, "DHCPREQUEST", strlen("DHCPREQUEST")); break;
++ case DHCPDECLINE: memcpy(str_dhcp_type, "DHCPDECLINE", strlen("DHCPDECLINE")); break;
++ case DHCPACK: memcpy(str_dhcp_type, "DHCPACK", strlen("DHCPACK")); break;
++ case DHCPNAK: memcpy(str_dhcp_type, "DHCPNAK", strlen("DHCPNAK")); break;
++ case DHCPRELEASE: memcpy(str_dhcp_type, "DHCPRELEASE", strlen("DHCPRELEASE")); break;
++ case DHCPINFORM: memcpy(str_dhcp_type, "DHCPINFORM", strlen("DHCPINFORM")); break;
++ default: memcpy(str_dhcp_type, "UNKNOWN", strlen("UNKNOWN")); break;
++ }
++ }
++ return *(option + 2);
++ }
++ else option += *(option + 1) + 2;
++ }
++ return 0;
++}
++
++/*
++ Функция получающая основную запрашиваемую клиентом информацию из DHCP сообщения
++*/
++int get_dhcp_request_info(struct dhcp_packet *request, DHCP_REQ_INFO * request_info)
++{
++ uint8_t *option = (uint8_t*)request->options;
++ const uint8_t * opt_end = (const uint8_t *)request + sizeof(struct dhcp_packet);
++ uint8_t opt_len, dhcp_type;
++ if(memcmp(option, magic_cookie, sizeof(magic_cookie)))
++ return 0; /* Выходим, если не найдена последовательность magic_cookie */
++ option += sizeof(magic_cookie);
++
++ short options_found = 0;
++ while((option < opt_end) && (options_found < 2) && (*option != 255))
++ {
++ switch((uint8_t)*option)
++ {
++ case DHO_DHCP_SERVER_IDENTIFIER:
++ memcpy(&request_info->server_id, option + 2, *(option + 1));
++ options_found++;
++ break;
++ case DHO_DHCP_REQUESTED_ADDRESS:
++ memcpy(&request_info->req_addr, option + 2, *(option + 1));
++ options_found++;
++ break;
++ }
++ if(options_found == 2)
++ {
++ return 1;
++ }
++ else option += *(option + 1) + 2;
++ }
++ if(request_info->client_addr.s_addr == 0)
++ request_info->client_addr = request->ciaddr;
++ return 1;
++}
++
++/*
++ Функция удаляющая элемент кэша на который ссылается указатель xid_n
++*/
++inline XID_NODE * delete_xid(XID_NODE *xid_n)
++{
++ if(xid_n == xid_list_top)
++ {
++ if(xid_list_ptr == xid_list_top)
++ {
++ xid_list_top = 0;
++ xid_list_ptr = 0;
++ }
++ else xid_list_top = xid_n->next;
++ }
++ else if(!xid_n->next)
++ {
++ xid_n->prev->next = 0;
++ xid_list_ptr = xid_n->prev;
++ }
++ else
++ {
++ xid_n->prev->next = xid_n->next;
++ xid_n->next->prev = xid_n->prev;
++ }
++ XID_NODE * next_xid = xid_n->next;
++
++ if(xid_n -> out_packet)
++ free(xid_n -> out_packet);
++ free(xid_n);
++
++ -- dhcp_cache_len;
++ return next_xid;
++}
++
++/*
++ Функция удаляющая дублирующиеся по MAC адресу клиента и значению xid элементы кэша.
++ Такое бывает необходимо в случае повторной инициализации клиентом процесса получения
++ IP адреса - в последующих пакетах поле xid будет иметь другое значение.
++ В таком случае все предыдущие запросы являются устаревшими и будут удалены.
++ Кроме MAC адреса сверяется индекс интерфейса на котором получен запрос от клиента.
++ Индексом интерфейса является его основной (не алиасный!) IP адрес
++ представленный как число типа uint32_t
++*/
++int del_duplicate_xid(uint32_t xid, uint8_t * hw_addr, uint32_t if_index, uint32_t relay_if_index)
++{
++ XID_NODE * xid_ptr = xid_list_top;
++ int ret_code = 0;
++ if(relay_if_index)
++ {
++ while(xid_ptr)
++ {
++ if( !memcmp(xid_ptr -> chaddr, hw_addr, MAC_ADDR_LEN) &&
++ (xid_ptr -> xid != xid) &&
++ (xid_ptr -> relay_if_index == relay_if_index)
++ )
++ {
++ xid_ptr = delete_xid(xid_ptr);
++ ++ret_code;
++ }
++ else xid_ptr = xid_ptr -> next;
++ }
++ }
++ else
++ {
++ while(xid_ptr)
++ {
++ if( !memcmp(xid_ptr -> chaddr, hw_addr, MAC_ADDR_LEN) &&
++ (xid_ptr -> xid != xid) &&
++ (xid_ptr -> if_index == if_index)
++ )
++ {
++ xid_ptr = delete_xid(xid_ptr);
++ ++ret_code;
++ }
++ else xid_ptr = xid_ptr -> next;
++ }
++ }
++ return ret_code;
++}
++
++/*
++ Функция производящая поиск нужного узла кэша и возвращающая в случае успеха указатель на него.
++*/
++XID_NODE * search_xid(uint8_t * hw_addr, uint32_t if_index, uint32_t relay_if_index)
++{
++ XID_NODE * tmp_ptr = xid_list_top;
++
++ if(relay_if_index)
++ {
++ while(tmp_ptr)
++ {
++ if(!memcmp(tmp_ptr -> chaddr, hw_addr, MAC_ADDR_LEN) &&
++ (tmp_ptr -> relay_if_index == relay_if_index) )
++ return tmp_ptr;
++ tmp_ptr = tmp_ptr -> next;
++ }
++ }
++ else
++ {
++ /* Иначе производим поиск по MAC-адресу клиента и ID интерфейса на котором получен запрос.
++ Запрос может быть получен локально от клиента, и тогда ID равен tmp_ptr->if_index,
++ либо запрос может быть переслан от клиента агентом пересылки.
++ Тогда ID равен tmp_ptr -> out_packet -> giaddr.s_addr */
++ while(tmp_ptr)
++ {
++ if(!memcmp(tmp_ptr -> chaddr, hw_addr, MAC_ADDR_LEN) &&
++ (tmp_ptr -> if_index == if_index) )
++ return tmp_ptr;
++ tmp_ptr = tmp_ptr -> next;
++ }
++ }
++ return 0;
++}
++
++/*
++ Возвращает смещение с байтах поля указанного option
++ относительно начала заголовка DHCP пакета.
++*/
++int dhcp_option_offset(const uint16_t option)
++{
++ static struct dhcp_packet * pack;
++ switch(option)
++ {
++ case dhcp_op:
++ return (uint8_t*)(&pack -> op) - (uint8_t *)pack;
++ case dhcp_hwtype:
++ return (uint8_t*)(&pack -> htype) - (uint8_t *)pack;
++ case dhcp_hwlen:
++ return (uint8_t*)(&pack -> hlen) - (uint8_t *)pack;
++ case dhcp_hops:
++ return (uint8_t*)(&pack -> hops) - (uint8_t *)pack;
++ case dhcp_xid:
++ return (uint8_t*)(&pack -> xid) - (uint8_t *)pack;
++ case dhcp_secs:
++ return (uint8_t*)(&pack -> secs) - (uint8_t *)pack;
++ case dhcp_flags:
++ return (uint8_t*)(&pack -> flags) - (uint8_t *)pack;
++ case dhcp_ciaddr:
++ return (uint8_t*)(&pack -> ciaddr) - (uint8_t *)pack;
++ case dhcp_yiaddr:
++ return (uint8_t*)&pack -> yiaddr - (uint8_t *)pack;
++ case dhcp_siaddr:
++ return (uint8_t*)(&pack -> siaddr) - (uint8_t *)pack;
++ case dhcp_giaddr:
++ return (uint8_t*)(&pack -> giaddr) - (uint8_t *)pack;
++ case dhcp_chaddr:
++ return (uint8_t*)(&pack -> chaddr) - (uint8_t *)pack;
++ case dhcp_sname:
++ return (uint8_t*)(&pack -> sname) - (uint8_t *)pack;
++ case dhcp_bootfile:
++ return (uint8_t*)(&pack -> file) - (uint8_t *)pack;
++ default:
++ return OPTIONAL_OFFSET;
++ }
++}
++
++/*
++ Функция производящая разбор RADIUS VSA
++*/
++int dispatch_radius_vsa(const int length, const uint8_t * attr_cont, struct dhcp_packet * out_packet,
++ unsigned int * opt_len, AUX_ATTRS *aux_attrs)
++{
++ uint32_t vendor_id = ntohl(*((uint32_t *) attr_cont));
++ if(vendor_id != VSA_DHCP)
++ {
++ log_info("PATCH: found unknown RADIUS VSA vendor ID: %u.", vendor_id);
++ return INVALID_VSA;
++ }
++
++
++ uint16_t option = ntohs(((PVSA_DHCP_HEADER) attr_cont) -> type);
++ uint8_t data_len = ((PVSA_DHCP_HEADER) attr_cont) -> length - 3; /* 3 - суммарная длина полей length & type */
++ uint8_t *data = (uint8_t*) &((PVSA_DHCP_HEADER) attr_cont) -> data;
++ int offset = OPTIONAL_OFFSET;
++
++ if(option > MAX_STD_DHCP_OPT)
++ offset = dhcp_option_offset(option);
++
++ if(offset != OPTIONAL_OFFSET) /* Поле из DHCP заголовка */
++ memcpy(((uint8_t *) out_packet) + offset, data, data_len);
++ else if(option < MAX_STD_DHCP_OPT) /* Опция из стандартного набора DHCP опций */
++ {
++ *((out_packet -> options) + (*opt_len)++) = option;
++ *((out_packet -> options) + (*opt_len)++) = data_len;
++ memcpy((uint8_t*)(out_packet -> options) + *opt_len, data, data_len);
++ *opt_len += data_len;
++ } else /* Служебная опция нуждающаяся в дополнительной обработке перед записью в DHCP пакет */
++ {
++ switch(option)
++ {
++ case RAD_IFINDEX:
++ aux_attrs -> if_index = *((uint32_t*)data);
++ break;
++ case RAD_DYN_CLIENT:
++ /* Данный атрибут свидетельствует о том что для этого клиента нет привязки MAC -> IP */
++ /* Устанавливаем разрешение для кэширования, если оно разрешено глобальными настройками */
++ /* См. опцию "radius-allow-dynamic-cache" */
++ aux_attrs -> allow_cache = radius_allow_dynamic_cache;
++ break;
++ default:
++ return INVALID_VSA;
++ break;
++ }
++ }
++ return offset;
++}
++
++/* Функция создающая DHCPNAK сообщение в буфере на который указывает out_packet */
++void make_dhcp_nak(struct dhcp_packet * out_packet, XID_NODE * cur_xid, const uint32_t server_id)
++{
++ *(out_packet->options + sizeof(magic_cookie) + 2) = DHCPNAK;
++ out_packet->flags |= htons (BOOTP_BROADCAST); /* Флаг broadcast */
++ out_packet->ciaddr.s_addr = 0;
++ out_packet->yiaddr.s_addr = 0;
++ out_packet -> siaddr.s_addr = server_id;
++ *(out_packet->options + sizeof(magic_cookie) + 3) = DHO_DHCP_SERVER_IDENTIFIER;
++ *(out_packet->options + sizeof(magic_cookie) + 4) = sizeof(server_id);
++ memcpy(out_packet->options + sizeof(magic_cookie) + 5, &server_id, sizeof(server_id));
++ cur_xid -> server_msg_type = DHCPNAK;
++}
++
++/* Функция возвращающая классовую маску */
++inline uint32_t make_default_netmask(const uint32_t addr)
++{
++ if(addr <= 0x7FFFFFFF)
++ return 0xFF000000;
++ if(addr <= 0xBFFF0000)
++ return 0xFFFF0000;
++ if(addr <= 0xDFFFFF00)
++ return 0xFFFFFF00;
++ return 0xFFFFFFFF;
++}
++
++/*
++ Функция устанавливающая тип DHCP сообщения в исходящем пакете клиенту.
++*/
++uint8_t set_dhcp_type_of_out_packet(struct dhcp_packet * out_packet, const int out_pack_len,
++ XID_NODE * cur_xid, const server_id)
++{
++ uint8_t out_packet_type = DHCPACK;
++ /* Выбираем тип сообщения который будет отправлен в DHCP пакете к клиенту */
++ *(out_packet->options + sizeof(magic_cookie)) = DHO_DHCP_MESSAGE_TYPE;
++ *(out_packet->options + sizeof(magic_cookie) + 1) = 1;
++ switch (cur_xid -> client_msg_type)
++ {
++ case DHCPDISCOVER:
++ *(out_packet->options + sizeof(magic_cookie) + 2) = DHCPOFFER;
++ cur_xid -> server_msg_type = DHCPOFFER;
++ /* Записываем в XID предлагаемый пользователю адрес */
++ memcpy(&cur_xid -> request_info.client_addr, &out_packet -> yiaddr, sizeof(struct in_addr));
++ break;
++ case DHCPREQUEST:
++ {
++ uint32_t subnet_mask;
++ if(!get_dhcp_option(out_packet, out_pack_len, DHO_SUBNET_MASK, &subnet_mask, sizeof(subnet_mask)))
++ subnet_mask = make_default_netmask(cur_xid -> request_info.client_addr.s_addr);
++
++ if( cur_xid -> request_info.client_addr.s_addr &&
++ ( (cur_xid -> request_info.client_addr.s_addr & subnet_mask) !=
++ (out_packet -> yiaddr.s_addr & subnet_mask) )
++ ) /* Игнорируем запрос если клиент запрашивает иную подсеть */
++ {
++ log_info("Ignore DHCPREQUEST because the IP address of the client (%s) is incorrect.",
++ inet_ntoa(cur_xid -> request_info.client_addr));
++ return 0;
++ }
++
++ if(cur_xid -> request_info.req_addr &&
++ ( (cur_xid -> request_info.req_addr & subnet_mask) !=
++ (out_packet -> yiaddr.s_addr & subnet_mask) ) )
++ {
++ make_dhcp_nak(out_packet, cur_xid, server_id);
++ out_packet_type = DHCPNAK;
++ }
++ else /* Проверяем адрес с которого клиент послал запрос на соответсвие предлагаемому
++ клиенту адресу. Если они не совпадают - отвергаем запрос */
++ if(cur_xid -> request_info.client_addr.s_addr != 0)
++ {
++ if(out_packet -> yiaddr.s_addr != cur_xid -> request_info.client_addr.s_addr)
++ {
++ make_dhcp_nak(out_packet, cur_xid, server_id);
++ out_packet_type = DHCPNAK;
++ }else
++ {
++ *(out_packet->options + sizeof(magic_cookie) + 2) = DHCPACK;
++ cur_xid -> server_msg_type = DHCPACK;
++ }
++ }
++ else if(cur_xid->request_info.req_addr != 0)
++ {
++ if(cur_xid->request_info.req_addr != out_packet->yiaddr.s_addr)
++ {
++ make_dhcp_nak(out_packet, cur_xid, server_id);
++ out_packet_type = DHCPNAK;
++ }
++ else
++ {
++ *(out_packet->options + sizeof(magic_cookie) + 2) = DHCPACK;
++ cur_xid -> server_msg_type = DHCPACK;
++ }
++ }else
++ {
++ struct in_addr ip;
++ ip.s_addr = cur_xid->request_info.req_addr;
++ log_error("WARN: Found invalid DHCP-request \"required address\":%s \"client address\" %s (hw: %s), state: %d",
++ inet_ntoa(cur_xid->request_info.client_addr),
++ inet_ntoa(ip),
++ print_hw_addr ( 1, MAC_ADDR_LEN, cur_xid -> chaddr),
++ cur_xid -> server_msg_type);
++ return 0;
++ }
++ }
++ break;
++ default:
++ break;
++ } /* End switch () */
++ return out_packet_type;
++}
++
++/*
++ Функция преобразующая полученный от сервера RADIUS-Access-Accept в DHCP-сообщение клиенту
++ запросившему IP адрес
++*/
++int translate_rad_to_dhcp(RAD_MESSAGE *rad_pack, struct dhcp_packet * out_packet, uint16_t received_length,
++ uint32_t * user_interface ) /* Параметр необходим для корректной обработки */
++{ /* запросов с xid == 0 */
++ if(!out_packet)
++ {
++ log_error("NULL pointer *out_packet in function translate_rad_to_dhcp(). Exiting whith error code 0.");
++ return 0;
++ }
++
++ bzero(out_packet, sizeof(struct dhcp_packet));
++
++ uint8_t * attr_ptr = (uint8_t *)rad_pack + sizeof(RAD_HEADER); /* Указатель на начало
++ обрабатываемого RADIUS атрибута */
++ uint8_t * attr_cont = 0; /* Указатель на начало значения атрибута */
++ unsigned int opt_len = 0;
++ /* Вставляем "magic cookie" в начало DHCP опций: 99.130.83.99 */
++ memcpy(out_packet->options, magic_cookie, sizeof(magic_cookie));
++ opt_len += sizeof(magic_cookie) + /* Задаём начальную длину пакета равной длине */
++ 3;/* "magic cookie" + длина DHCP-Message-type */
++ if( received_length != ntohs(rad_pack -> header.pack_len))
++ {
++ log_error("ERROR: Invalid length in RADIUS header."
++ "Received %u bytes, but length = %u in RADIUS header.",
++ received_length, ntohs(rad_pack -> header.pack_len));
++ return 0;
++ }
++
++ /* Начинаем разбор переданных атрибутов */
++ uint8_t rad_attr = 0;
++ uint8_t attr_len = 0;
++ AUX_ATTRS aux_attrs;
++ bzero(&aux_attrs, sizeof(aux_attrs));
++ aux_attrs.allow_cache = radius_allow_cache;
++ /* Цикл пока не достигнем конца пакета */
++ while( attr_ptr < (uint8_t *) rad_pack + ntohs(rad_pack -> header.pack_len) )
++ {
++ rad_attr = *attr_ptr;
++ attr_len = *(attr_ptr + 1);
++ attr_cont = attr_ptr + 2;
++
++ /* Проверка на неправильную длину атрибута */
++ if( (uint8_t *)(rad_attr + attr_len) > (uint8_t *)(rad_pack + received_length))
++ {
++ log_error("ERROR: Invalid RADIUS attribute length: %u. "
++ "End of option exceed the bounds of packet.",
++ attr_len);
++ return 0;
++ }
++ /* Проверка на переполнение поля опций DHCP пакета */
++ if(opt_len + attr_len > DHCP_MAX_OPTION_LEN)
++ {
++ log_error("ERROR: DHCP_OPTION owerflow! Exiting from translate_rad_to_dhcp() with error code 0.");
++ return 0;
++ }
++
++ if(rad_attr == RAD_VSA)
++ {
++ if(dispatch_radius_vsa(attr_len, attr_cont, out_packet, &opt_len, &aux_attrs) == INVALID_VSA)
++ log_info("PATCH: Skip this attribute.");
++ }else
++ log_info ("WARN: dhcp2radius for dhcpd patch support only RADIUS VSA. Attribute: %u, len: %u not supported.",
++ rad_attr, attr_len);
++ attr_ptr += attr_len;
++ } /* End while(...)*/
++
++ XID_NODE * cur_xid;
++ cur_xid = search_xid(out_packet -> chaddr, aux_attrs.if_index, out_packet -> giaddr.s_addr);
++ if(!cur_xid)
++ {
++ struct in_addr ip;
++ ip.s_addr = aux_attrs.if_index;
++ log_info("WARN: Can't find request info for client %s from interface %s (%u)",
++ print_hw_addr ( 1, MAC_ADDR_LEN, out_packet -> chaddr), inet_ntoa(ip), aux_attrs.if_index);
++ return 0;
++ }
++
++ *user_interface = cur_xid -> if_index;
++
++ cur_xid -> allow_cache = aux_attrs.allow_cache;
++ out_packet -> flags = cur_xid -> dhcp_flags;
++
++ int out_pack_len = sizeof(struct dhcp_packet) - DHCP_MAX_OPTION_LEN + opt_len;
++ uint32_t server_id;
++ if(!get_dhcp_option(out_packet, out_pack_len, DHO_DHCP_SERVER_IDENTIFIER, &server_id, sizeof(server_id)))
++ return -1;
++
++ /* Выбираем тип сообщения который будет отправлен в DHCP пакете к клиенту */
++ uint8_t out_packet_type = set_dhcp_type_of_out_packet(out_packet, out_pack_len, cur_xid, server_id);
++ if(!out_packet_type)
++ return 0;
++ if(out_packet_type == DHCPNAK)
++ {
++ *(out_packet->options + sizeof(magic_cookie) + 5 + sizeof(server_id)) = DHO_END;
++ out_pack_len = sizeof(struct dhcp_packet) - DHCP_MAX_OPTION_LEN + /* Общая длина пакета складывается из: */
++ sizeof(magic_cookie) + /* размера обязательного поля magic_cookie, */
++ 3 + /* размера поля указывающего тип DHCP сообщения
++ включая длину полей указыающих имя и длину
++ DHCP атрибута (1 + 1 + 1 = 3), */
++ 2 + sizeof(server_id) + /* размера идентификатора сервера, так же
++ включая длину служебных полей */
++ 1; /* и длины опции-завершителя DHO_END */
++ }
++ else
++ {
++ *(out_packet->options + opt_len++) = DHO_END;
++ ++out_pack_len;
++ }
++
++ out_packet -> op = BOOTREPLY;
++ out_packet -> htype = HTYPE_ETHER;
++ out_packet -> hlen = MAC_ADDR_LEN;
++ out_packet -> xid = cur_xid -> xid;
++#ifdef __linux__
++ /* Обновляем, если это необходимо статическую ARP таблицу ОС */
++ if(updating_arp_cache_perm && !out_packet -> giaddr.s_addr && /* Должно быть разрешено обновление, пакет не должен */
++ aux_attrs.allow_cache && out_packet -> yiaddr.s_addr) /* быть отправлен через агента пересылки, должно быть */
++ { /* разрешено кэширование данного клиента и должен быть */
++ int ret_code = update_arp_cache_perm(out_packet -> yiaddr.s_addr, out_packet -> chaddr); /* известен его адрес */
++ if(ret_code < 0)
++ log_error("ERROR: Can't updating ARP cache for %s (hw: %s)",
++ inet_ntoa(out_packet -> yiaddr), print_hw_addr(1, MAC_ADDR_LEN, out_packet -> chaddr));
++ if(ret_code > 0)
++ log_info("INFO: Updating ARP entry for %s (new hw address: %s)",
++ inet_ntoa(out_packet -> yiaddr), print_hw_addr(1, MAC_ADDR_LEN, out_packet -> chaddr));
++ }
++#endif
++ return out_pack_len;
++}
++
++uint16_t update_xid_node(XID_NODE * xid, struct dhcp_packet * packet, unsigned pack_len)
++{
++ uint16_t msg_type = DHCPNAK;
++ struct in_addr requested_addr;
++ if( !get_dhcp_option(packet, pack_len,
++ DHO_DHCP_REQUESTED_ADDRESS, &requested_addr.s_addr, sizeof(requested_addr.s_addr)) )
++ requested_addr.s_addr = 0;
++ if(!xid -> out_packet)
++ {
++ log_error("PATCH: NULL argument for update_xid_node() found!");
++ return 0;
++ }
++ /* Сюда попадают пакеты обязательно имеющие тип DHCPREQUEST,
++ следовательно у них обязательно должно быть
++ заполнено одно из ниже указанных полей */
++ if(requested_addr.s_addr)
++ {
++ if(requested_addr.s_addr != xid -> out_packet -> yiaddr.s_addr)
++ {
++ xid -> out_packet -> yiaddr.s_addr = 0;
++ xid -> out_packet -> ciaddr.s_addr = 0;
++ }
++ else
++ msg_type = DHCPACK;
++ }
++ else if(packet -> ciaddr.s_addr)
++ {
++ if(packet -> ciaddr.s_addr != xid -> out_packet -> yiaddr.s_addr)
++ {
++ xid -> out_packet -> yiaddr.s_addr = 0;
++ xid -> out_packet -> ciaddr.s_addr = 0;
++ }
++ else msg_type = DHCPACK;
++ }
++ else
++ {
++ log_error("INFO: Invalid DHCPREQUEST for xid: %d hw addr: %s.",
++ ntohl( packet -> xid), print_hw_addr(1, MAC_ADDR_LEN, packet -> chaddr));
++ return 0;
++ }
++
++ xid -> out_packet -> xid = packet -> xid;
++ xid -> xid = packet -> xid;
++
++ set_dhcp_type( xid -> out_packet, msg_type);
++ xid -> server_msg_type = msg_type;
++ return msg_type;
++}
++
++/*
++ Функция удаляющая самый старый запрос в DHCP кэше
++*/
++inline int delete_oldest_cache_node(XID_NODE * cache_node)
++{
++ delete_xid(xid_list_top);
++ return dhcp_cache_len;
++}
++
++/*
++ Функция проверяющая не превышено-ли максимально допустимое число запросов на которые не
++ получены ответы от сервера. Применяется для переключения на резервный сервер в случае
++ падения основного.
++*/
++inline int is_unfinished_requests_overflow(int * count, int inc, int max_count, int zeroing)
++{
++ static int counter = 0;
++ if(++counter == zeroing)
++ *count = counter = 0;
++ if(!inc && *count > 0)
++ -- *count;
++ else
++ if(inc)
++ ++ *count;
++ if(*count > max_count)
++ return *count;
++ return 0;
++}
++
++/*
++ Функция анализирующая RADIUS-Response
++*/
++int dispatch_radius_packet(struct dhcp_packet * packet, unsigned length,
++ struct in_addr * user_if, uint8_t * hw_from)
++{
++ RAD_MESSAGE *rad_ptr;
++ rad_ptr = (RAD_MESSAGE *) packet;
++ struct dhcp_packet tmp_dhcp_pack;
++ XID_NODE * xid;
++
++ is_unfinished_requests_overflow(&unfinished_requests, DEC, MAX_UNFINISHED_REQ, ZEROING_UNFIN_REQ);
++
++ if(rad_ptr->header.code != RAD_ACCESS_ACK)
++ {
++ if(rad_ptr -> header.code == RAD_ACCESS_NAK) /* Access Reject приходит в случае отсутствия */
++ { /* пула адресов для данного сегмента */
++ XID_NODE * xid = xid_list_top;
++ while(xid)
++ {
++ if(xid -> req_header.id == rad_ptr -> header.id &&
++ calc_reply_auth(rad_ptr, xid -> req_header.auth, rad_secret) == 0)
++ {
++ static struct in_addr ip;
++ static char srv_addr[16];
++ strncpy(srv_addr, inet_ntoa(radius_servers[server_index].sin_addr), sizeof(srv_addr));
++ ip.s_addr = xid -> relay_if_index ? xid -> relay_if_index : xid -> if_index;
++ log_info("RADIUS server %s reject DHCP client %s from %s",
++ srv_addr,
++ print_hw_addr(HTYPE_ETHER, MAC_ADDR_LEN, xid -> chaddr),
++ inet_ntoa(ip));
++ goto rejected_ok;
++ }
++ xid = xid -> next;
++ }
++ log_info("RADIUS-Access-Reject found, but I can't found DHCP info for him.");
++rejected_ok:;
++ }
++ else log_info ("INFO: Recv RADIUS, code: %u - this is not Request-Accept. Drop this packet.",
++ rad_ptr -> header.code);
++ return 0;
++ }
++
++ length = translate_rad_to_dhcp((RAD_MESSAGE *)packet, &tmp_dhcp_pack, length, &user_if -> s_addr);
++
++ if(!length)
++ return 0;
++ if((signed int)length < 0)
++ {
++ log_debug("WARN: invalid client IP address. BOOTREPLY aborted.");
++ return 0;
++ }
++
++ xid = search_xid(tmp_dhcp_pack.chaddr, user_if -> s_addr, tmp_dhcp_pack.giaddr.s_addr);
++
++ memcpy(hw_from, xid -> hw_from, MAC_ADDR_LEN);
++
++ if(!xid)
++ {
++ log_info ("INFO: Get unknown xid %d with unknown user interface: %u in RADIUS. BOOTREPLY aborted.",
++ tmp_dhcp_pack.xid, user_if -> s_addr);
++ return 0;
++ }
++
++ if(calc_reply_auth(rad_ptr, xid -> req_header.auth, rad_secret) != 0)
++ {
++ log_info ("WARN: Invalid autentificator in RADIUS. BOOTREPLY aborted.");
++ return 0;
++ }
++
++ if(rad_ptr->header.id != xid->req_header.id)
++ {
++ log_info ("INFO: Invalid RADIUS-id in RADIUS-reply. BOOTREPLY aborted.");
++ return 0;
++ }
++
++ bzero(packet, sizeof(struct dhcp_packet));
++ memcpy(packet, &tmp_dhcp_pack, sizeof(struct dhcp_packet));
++
++ if(xid -> allow_cache)
++ { /* Если разрешено кэширование то */
++ /* копируем DHCPREPLY в поле out_packet для хранения в кэше */
++ xid -> out_packet = (struct dhcp_packet *) calloc(1, length);
++ if(!xid -> out_packet)
++ log_fatal("PATCH: Can't allocate memory to cache for DHCP packet.");
++ memcpy(xid -> out_packet, packet, length);
++ xid -> out_pack_len = length;
++ }
++
++ delete_xid_if_mac_not_equal(packet -> yiaddr.s_addr, packet -> chaddr);
++
++ return length;
++}
++
++/*
++ Функция анализирующая полученный от клиента DHCP запрос
++*/
++int dispatch_dhcp_packet(struct dhcp_packet * packet,
++ unsigned * length,
++ struct interface_info *ip,
++ struct hardware * hw_from,
++ uint8_t * from_cache,
++ RAD_MESSAGE * auth_pack)
++{
++ XID_NODE * xid_ptr;
++ uint16_t dhcp_type = 0;
++ static char str_dhcp_type[20];
++ float qps = 0; /* Общее усреднённое число запросов в секунду */
++ float qps_host = 0; /* Усреднённое число запросов от конкретного хоста */
++
++ /*log_info("hw_from: %s", print_hw_addr(hw_from -> hbuf[0], hw_from -> hlen - 1, hw_from -> hbuf + 1));*/
++
++ /* Определяем тип DHCP запроса */
++ bzero(str_dhcp_type, sizeof(str_dhcp_type));
++ dhcp_type = get_dhcp_type(packet, str_dhcp_type);
++
++ if(dhcp_type == DHCPDISCOVER || dhcp_type == DHCPREQUEST)
++ {
++ qps = count_queries_per_sec();
++
++ /* Начинаем вычисления числа запросов для каждого отдельно взятого хоста в секунду */
++ qps_host = qps_hosts(packet -> chaddr, 0);
++ if(qps_host > max_qps_from_host)
++ {
++ log_info("ERROR: Exceed maximum DHCP queries per second (%g/sec) for host %s/%s. Maximum: %g/sec. Drop request.",
++ qps_host,
++ print_hw_addr (packet -> htype, packet -> hlen, packet -> chaddr),
++ ip -> name,
++ max_qps_from_host);
++ return -1;
++ }
++ /* Если клиент не блокирован по числу запросов в секунду,
++ то добавляем временной штамп в кольцевой буфер */
++ if(ring_ptr >= RING_MAX)
++ ring_ptr = 0;
++ normal_clients_counter[ring_ptr] = time(0);
++ ++ring_ptr;
++
++ delete_old_xid(xid_list_top); /* Удаляем старые узлы dhcp-транзакций */
++ static DHCP_REQ_INFO new_req_info;
++ bzero(&new_req_info, sizeof(new_req_info));
++ if(dhcp_type == DHCPREQUEST) /* Если тип запроса DHCPREQUEST то возможно мы уже имеем */
++ { /* кэшированный ответ */
++ /* Возвращает структуру содержащую адрес клиента, запрашиваемый адрес */
++ get_dhcp_request_info(packet, &new_req_info); /* и идентификатор сервера */
++ xid_ptr = search_xid(packet -> chaddr, ip -> primary_address.s_addr, packet -> giaddr.s_addr);
++
++ if( xid_ptr /* Если соответствующий узел найден */
++ && xid_ptr -> out_packet /* и существует кэшированный пакет */
++ && xid_ptr -> allow_cache /* и разрешено его кэширование */
++ && xid_ptr -> out_packet -> op) /* и в нём уже имеется ответ сервера */
++ {
++ uint32_t subnet_mask;
++ if(!get_dhcp_option(xid_ptr -> out_packet, xid_ptr -> out_pack_len, DHO_SUBNET_MASK,
++ &subnet_mask, sizeof(subnet_mask)))
++ subnet_mask = make_default_netmask(xid_ptr -> request_info.client_addr.s_addr);
++
++ if( packet -> ciaddr.s_addr &&
++ ( (packet -> ciaddr.s_addr & subnet_mask) !=
++ (xid_ptr -> out_packet -> yiaddr.s_addr & subnet_mask) ) )
++ return 0; /* Игнорируем запрос если клиент запрашивает иную подсеть */
++
++ /* Информация для этого адреса уже есть в кэше */
++ /* Отправляем клиенту кэшированный ответ заменив поле типа */
++ switch(xid_ptr -> server_msg_type)
++ { /* В этих случаях XID содержит ответный пакет */
++ case DHCPOFFER:
++ case DHCPACK:
++ case DHCPNAK:
++ if(!( dhcp_type = update_xid_node(xid_ptr, packet, *length)) )
++ {
++ log_info("Can't update cache node.");
++ return -1;
++ }
++ /* Отдаём клиенту кэшированный пакет */
++ memcpy(packet, xid_ptr -> out_packet, xid_ptr -> out_pack_len);
++ memcpy(hw_from -> hbuf + 1, xid_ptr -> hw_from, MAC_ADDR_LEN);
++ *length = xid_ptr -> out_pack_len;
++
++ static char from_str[16]; /* Строка используемая для сохранения строкового представления
++ IP адреса агента пересылки если таковой используется */
++ if(packet -> giaddr.s_addr)
++ strncpy(from_str, inet_ntoa(packet -> giaddr), sizeof(from_str));
++
++ log_info ("Received %s (%s/%s) found in dhcpd cache.", str_dhcp_type,
++ print_hw_addr (packet -> htype, MAC_ADDR_LEN , packet -> chaddr),
++ packet -> giaddr.s_addr ? inet_ntoa(packet -> giaddr) : ip -> name);
++ *from_cache = 1;
++ if(qps > max_qps)
++ log_error("WARN: Exceed maximum DHCP queries per second - %g/sec (%g/sec max)."
++ " But DHCP-response found in cache. Sending packet...",
++ qps, max_qps);
++ xid_ptr -> client_msg_type = DHCPREQUEST;
++ return 1;
++ break;
++ }
++ }
++ }
++
++ /* Тип DHCP запроса - DHCPDISCOVER, либо запрещено кэширование для данного клиента,
++ значит необходима пересылка данных на RADIUS сервер. */
++ /* Проверяем не превышено ли пороговое значение числа запросов в секунду */
++ if(qps > max_qps)
++ { /* Если превышен, то дропаем новый запрос */
++ log_error("ERROR: Exceed maximum DHCP queries per second - %g/sec (%g/sec)",
++ qps, max_qps);
++ log_error("ERROR: Drop %s from %s/%s !", str_dhcp_type,
++ print_hw_addr (packet -> htype, packet -> hlen, packet -> chaddr),
++ ip -> name);
++ return -1;
++ }
++
++ /* Если наш запрос не найден в кэше, то проверяем не достиг-ли кэш максимального размера */
++ if( dhcp_cache_len >= MAX_CACHE_LIST_LEN &&
++ !search_xid(packet -> chaddr, ip -> primary_address.s_addr, packet -> giaddr.s_addr)/* Если запрос найден в кэше */
++ ) /* то нет нужды удалять старый узел, либо дропать запрос, т.к. старый узел будет удалён в ходе */
++ { /* добавления нового и размер кэша не увеличится */
++ if(delete_oldest_cache_node(xid_list_top) < 0)
++ {
++ log_error("ERROR: Can't delete oldest cache node! Drop %s from %s/%s", str_dhcp_type,
++ print_hw_addr (packet -> htype, packet -> hlen, packet -> chaddr),
++ ip -> name);
++ return -1;
++ }
++ else
++ log_info("WARN: Cache overflow. The oldest cache node has been dropped. Cache length now is: %u",
++ dhcp_cache_len);
++ }
++ /* Добавляем новый узел в кэш */
++ del_duplicate_xid(packet -> xid, packet -> chaddr, ip -> primary_address.s_addr, packet -> giaddr.s_addr);
++ xid_ptr = add_xid(packet, dhcp_type, ip -> primary_address.s_addr, hw_from);
++ uint8_t mac_addr[STR_MAC_ADDR_LEN];
++ bzero(mac_addr, sizeof(mac_addr));
++ sprintf(mac_addr,
++ (radius_use_mac_delim)?
++ "%02x:%02x:%02x:%02x:%02x:%02x" :
++ "%02x%02x%02x%02x%02x%02x",
++ packet -> chaddr[0], packet -> chaddr[1], packet -> chaddr[2],
++ packet -> chaddr[3], packet -> chaddr[4], packet -> chaddr[5]);
++ *length = assemble_auth_message(auth_pack, packet, *length,
++ mac_addr, rad_users_passwd,
++ packet -> giaddr.s_addr ?
++ packet -> giaddr.s_addr :
++ ip -> primary_address.s_addr);
++ if(!*length)
++ {
++ log_error("PATCH: Can't create RADIUS-ACCESS-REQUEST");
++ return -1;
++ }
++
++ if(!xid_ptr) /* Если не добавлен новый узел в список, значит ответ */
++ { /* сервера уже есть в кэше */
++ xid_ptr = search_xid(packet->chaddr, ip -> primary_address.s_addr, packet -> giaddr.s_addr);
++ if(!xid_ptr)
++ {
++ log_error("WARN: search_xid() in dispatch_dhcp_packet() return zero.");
++ return -1;
++ }
++ xid_ptr -> req_header.id = auth_pack -> header.id;
++ xid_ptr -> client_msg_type = dhcp_type;
++ memcpy(xid_ptr -> req_header.auth, &auth_pack -> header.auth, MD5_LEN);
++ }
++ else
++ memcpy(&xid_ptr -> req_header, &auth_pack -> header, sizeof(RAD_HEADER));
++
++ if(new_req_info.client_addr.s_addr || new_req_info.req_addr)
++ memcpy(&xid_ptr -> request_info, &new_req_info, sizeof(new_req_info));
++ }
++ else
++ {
++ if(dhcp_type != DHCPOFFER && dhcp_type != DHCPACK && dhcp_type != DHCPNAK) /* Пакеты отправляемые агентам пересылки */
++ log_info ("Ignore BOOTREQUEST: type - %s from client %s (%s/%s)",
++ (strlen(str_dhcp_type))? str_dhcp_type: "'unknown'",
++ (strlen(str_dhcp_type))? inet_ntoa(packet -> ciaddr): "'unknown'",
++ (strlen(str_dhcp_type))?
++ print_hw_addr (packet -> htype, packet -> hlen, packet -> chaddr):"'unknown'",
++ ip -> name);
++ return 0;
++ }
++ return 1;
++}
++
++/*
++ Функция добавляющая интерфейс в список интерфейсов игнорируемых для DHCP запросов.
++*/
++int32_t add_dhcp_ignored_interface(char * if_name)
++{
++ if(!if_name)
++ return 0;
++ if(!start_dhcp_ignor_list)
++ {
++ start_dhcp_ignor_list = malloc(sizeof(struct ignored_dhcp_interface));
++ start_dhcp_ignor_list -> if_name = malloc(strlen(if_name) + 1);
++ strcpy(start_dhcp_ignor_list -> if_name, if_name);
++ start_dhcp_ignor_list -> next = 0;
++ end_dhcp_ignor_list = start_dhcp_ignor_list;
++ }
++ else
++ {
++ end_dhcp_ignor_list -> next = malloc(sizeof(struct ignored_dhcp_interface));
++ end_dhcp_ignor_list = end_dhcp_ignor_list -> next;
++ end_dhcp_ignor_list -> if_name = malloc(strlen(if_name) + 1);
++ strcpy(end_dhcp_ignor_list -> if_name, if_name);
++ end_dhcp_ignor_list -> next = 0;
++ }
++ return 1;
++}
++
++int32_t found_ignored_interfase(char * if_name)
++{
++ if(!if_name)
++ return 0;
++ struct ignored_dhcp_interface * ign_ptr = start_dhcp_ignor_list;
++ while(ign_ptr)
++ {
++ if(!strcmp(ign_ptr -> if_name, if_name))
++ return 1;
++ ign_ptr = ign_ptr -> next;
++ }
++ return 0;
++}
++
++/* END PATCH CODE */
+diff -ruN dhcp-3.0.7.orig/common/discover.c dhcp-3.0.7/common/discover.c
+--- dhcp-3.0.7.orig/common/discover.c 2007-05-02 00:42:55.000000000 +0400
++++ dhcp-3.0.7/common/discover.c 2009-09-06 14:15:24.000000000 +0400
+@@ -40,6 +40,12 @@
+ #include "dhcpd.h"
+ #include <sys/ioctl.h>
+
++/* START PATCH CODE */
++#ifdef PATCHED_SERVER
++#include "dhcp2radius.h"
++#endif
++/* END PATCH CODE */
++
+ struct interface_info *interfaces, *dummy_interfaces, *fallback_interface;
+ int interfaces_invalidated;
+ int quiet_interface_discovery;
+@@ -604,7 +610,13 @@
+ sizeof tmp -> ifp -> ifr_addr);
+
+ /* We must have a subnet declaration for each interface. */
++/* START PATCH CODE */
++#ifdef PATCHED_SERVER
++ if (!tmp -> shared_network && (state == DISCOVER_SERVER) && !use_dhcp2radius) {
++#else
+ if (!tmp -> shared_network && (state == DISCOVER_SERVER)) {
++#endif
++/* END PATCH CODE */
+ log_error ("%s", "");
+ log_error ("No subnet declaration for %s (%s).",
+ tmp -> name, inet_ntoa (foo.sin_addr));
+@@ -764,6 +776,8 @@
+ struct hardware hfrom;
+ struct iaddr ifrom;
+ int result;
++
++
+ union {
+ unsigned char packbuf [4095]; /* Packet input buffer.
+ Must be as large as largest
+@@ -782,16 +796,51 @@
+ log_error ("receive_packet failed on %s: %m", ip -> name);
+ return ISC_R_UNEXPECTED;
+ }
++
+ if (result == 0)
+ return ISC_R_UNEXPECTED;
+
++
+ /* If we didn't at least get the fixed portion of the BOOTP
+ packet, drop the packet. We're allowing packets with no
+ sname or filename, because we're aware of at least one
+ client that sends such packets, but this definitely falls
+ into the category of being forgiving. */
++/* START PATCH CODE */
++#ifndef PATCHED_SERVER
+ if (result < DHCP_FIXED_NON_UDP - DHCP_SNAME_LEN - DHCP_FILE_LEN)
+ return ISC_R_UNEXPECTED;
++#endif
++
++#ifdef PATCHED_SERVER
++ if(use_dhcp2radius) /* Если в конфигурационном файле: use-dhcp2radius true */
++ {
++ /* Определяем какого типа полученный пакет: DHCP/RADIUS/??? */
++ if(from.sin_port == radius_port)
++ { /* Recieved RADIUS packet */
++ return got_radius_packet((uint8_t *)&u.packet, result);
++ }
++ else if( (from.sin_port == remote_port) || (from.sin_port == radius_dhcp_relay_port) )
++ {
++ return got_dhcp_packet((uint8_t *)&u.packet, result, &from, ip, &hfrom);
++ } else
++ { /* Если порт отправителя пакета не равен порту RADIUS сервера, не равен
++ порту DHCP клиентов (remote_port) и не равен
++ порту агента пересылки - не обрабатываем этот пакет */
++ char addr_str[16];
++ bzero(addr_str, sizeof(addr_str));
++ if(!inet_ntop(AF_INET, &from.sin_addr, addr_str, sizeof(addr_str)))
++ {
++ log_info("Can't do inet_ntop().");
++ }
++
++ log_info("Received packet from: %s hw: %s. Port is unexpected: %d - I'm don't know what is this!",
++ addr_str, print_hw_addr (hfrom.hbuf [0], hfrom.hlen - 1, &hfrom.hbuf [1]), ntohs(from.sin_port));
++ return ISC_R_UNEXPECTED;
++ }
++ }
++#endif
++/* END PATCH CODE */
+
+ if (bootp_packet_handler) {
+ ifrom.len = 4;
+diff -ruN dhcp-3.0.7.orig/common/Makefile.dist dhcp-3.0.7/common/Makefile.dist
+--- dhcp-3.0.7.orig/common/Makefile.dist 2004-09-22 00:33:35.000000000 +0400
++++ dhcp-3.0.7/common/Makefile.dist 2009-09-06 14:17:55.000000000 +0400
+@@ -25,11 +25,11 @@
+ SRC = raw.c parse.c nit.c icmp.c dispatch.c conflex.c upf.c bpf.c socket.c \
+ lpf.c dlpi.c packet.c tr.c ethernet.c memory.c print.c options.c \
+ inet.c tree.c tables.c alloc.c fddi.c ctrace.c dns.c resolv.c \
+- execute.c discover.c comapi.c
++ execute.c discover.c comapi.c dhcp2radius.c
+ OBJ = raw.o parse.o nit.o icmp.o dispatch.o conflex.o upf.o bpf.o socket.o \
+ lpf.o dlpi.o packet.o tr.o ethernet.o memory.o print.o options.o \
+ inet.o tree.o tables.o alloc.o fddi.o ctrace.o dns.o resolv.o \
+- execute.o discover.o comapi.o
++ execute.o discover.o comapi.o dhcp2radius.o
+ MAN = dhcp-options.5 dhcp-eval.5
+
+ INCLUDES = -I$(TOP) $(BINDINC) -I$(TOP)/includes
+diff -ruN dhcp-3.0.7.orig/common/packet.c dhcp-3.0.7/common/packet.c
+--- dhcp-3.0.7.orig/common/packet.c 2007-05-02 00:42:55.000000000 +0400
++++ dhcp-3.0.7/common/packet.c 2009-09-06 14:15:24.000000000 +0400
+@@ -325,7 +325,13 @@
+ 8, IPPROTO_UDP + ulen))));
+
+ udp_packets_seen++;
++/* START PATCH CODE */
++#ifdef PATCHED_SERVER
++ if (usum && usum != sum && interface -> primary_address.s_addr != htonl(INADDR_LOOPBACK)) {
++#else
+ if (usum && usum != sum) {
++#endif
++/* END PATCH CODE */
+ udp_packets_bad_checksum++;
+ if (udp_packets_seen > 4 &&
+ (udp_packets_seen / udp_packets_bad_checksum) < 2) {
+diff -ruN dhcp-3.0.7.orig/includes/dhcp2radius.h dhcp-3.0.7/includes/dhcp2radius.h
+--- dhcp-3.0.7.orig/includes/dhcp2radius.h 1970-01-01 03:00:00.000000000 +0300
++++ dhcp-3.0.7/includes/dhcp2radius.h 2009-09-06 14:16:56.000000000 +0400
+@@ -0,0 +1,342 @@
++
++#ifndef RAD2DHCP_H
++
++#define RAD2DHCP_H
++#pragma pack(1)
++/*
++#define FULL_DEBUG_OUT
++#define DEBUG_TR_RAD_TO_DHCP
++*/
++
++#define PATCH_VERSION "RADIUS to DHCP patch (dhcp2radius) v 0.1.1 2009.06.24"
++#define HOME_PAGE "http://www.netpatch.ru/dhcp2radius.html"
++
++#define RADIUS_PORT 1812
++#define RELAY_PORT 67
++#define DHCP_CLIENT_PORT 68
++#define RADIUS_MIN_PACK_LEN 20 /* Минимальная длина RADIUS сообщения */
++#define IPV4_ALEN 4
++
++/*
++ Смещения в RADIUS пакете
++*/
++#define ATTR_OFFSET 0
++#define LEN_OFFSET 1
++#define VALUE_OFFSET 2
++
++
++#define OPTIONAL_OFFSET -1
++#define INVALID_VSA -2
++
++#define MAX_STD_DHCP_OPT 0xFF
++
++/* Коды пакетов протокола Radius */
++#define RAD_ACCESS_REQ 1 /* Запрос доступа (отправка MAC адреса на сервер) */
++#define RAD_ACCESS_ACK 2 /* Доступ подтверждён (успешное получение конфигурационной информации от сервера) */
++#define RAD_ACCESS_NAK 3 /* Доступ запрещён (не удалось получить конфигурацию от сервера) */
++
++/* Значения атрибутов протокола Radius
++используемые в пакете Access-Request */
++#define USER_NAME_ATTR 1
++#define USER_PASS_ATTR 2
++#define NAS_PORT 5
++
++/* Значения атрибутов протокола Radius
++используемые в пакете Access-Accept */
++#define RAD_IFINDEX 0x0F01
++#define RAD_DYN_CLIENT 0x0F02
++
++/* Определяем работу протокола DHCP через Vendor-Specific атрибуты */
++#define RAD_VSA 0x1A
++/* Vendor ID == DHCP. Используется файл dictionary.dhcp из
++ стандартной поставки FreeRADIUS. См. подробности описания
++ атрибутов в этом файле */
++#define VSA_DHCP 0x36
++
++#define SIGSTAT 64 /* Сигнал при получении которого dhcrelay выдаёт статистику работы в лог */
++#define SIGNAL_SET_PRI_SERVER 63 /* Сигнал, получив который dhcrelay устанавливает server_index */
++ /* в значение по умолчанию, т.е. на основной сервер */
++#define SIGNAL_CHANGE_SERV 62 /* При получении этого сигнала dhcrelay устанавливает server_index */
++ /* на следующий элемент в массиве серверов если таковой имеется */
++
++#ifdef OLD
++/* Опция используемая в dhcp-пакете для
++указания статических маршрутов в сети */
++#define DHO_STATIC_ROUTE 249
++#endif
++
++/* Используется в функциях аутентификации RADIUS */
++#define MD5_LEN 16
++#define MAC_ADDR_LEN 6
++#define ENCR_PWD_LEN 16
++#define RAD_SECRET_SIZE 17
++#define RAD_PASSWD_SIZE 17
++
++#define DEFAULT_XID_TTL 86400 /* Одни сутки */
++#define MAX_CACHE_LIST_LEN 3000 /* Максимальная длина списка кэша запросов */
++#define QUERY_TIME_RING_LEN 350 /* Длина массива служащего для подсчёта частоты запросов */
++#define RING_MAX QUERY_TIME_RING_LEN
++#define TIME_DELTA 10.0 /* Время (сек.) за которое производится подсчёт */
++ /* среднего числа DHCP запросов в секунду */
++#define TIME_DELTA_HOST 5.0 /* То же что и TIME_DELTA, только для отдельно взятого хоста */
++#define MAX_DHCP_QPS 10.0 /* Суммарное максимально допустимое число DHCP запросов в секунду */
++#define MAX_QPS_FROM_HOST 4.0 /* Максимально допустимое число DHCP запросов в секунду от одного хоста */
++#define MIN_COUNTER_SIZE 100 /* Минимальная длина динамического массива счётчика запросов */
++
++#define DEFAULT_SERV_ARR_SIZE 10 /* Размер массива серверов по умолчанию */
++#define BASIC_SERVER_INDEX 0 /* Индекс массива серверов обозначающий основной сервер, */
++ /* запросы к которому отправляются в штатном режиме работы релея */
++#define PRIMARY_SERVER_INDEX BASIC_SERVER_INDEX
++#define INC 1
++#define DEC 0
++#define MAX_UNFINISHED_REQ 30
++#define ZEROING_UNFIN_REQ 50
++
++#define DEF_ARP_CACHE_PERM_LEN 1024
++#ifdef __linux__
++#define PROC_ARP "/proc/net/arp"
++#endif
++#define STR_MAC_ADDR_LEN 18
++
++/* Используется что бы определить начало поля dhcp-options */
++extern const uint8_t magic_cookie[];
++extern int32_t use_dhcp2radius;
++extern struct sockaddr_in * radius_servers; /* Указатель на список массив хранящий адреса RADIUS серверов */
++extern int radius_servers_count; /* Число доступных RADIUS серверов */
++extern unsigned char rad_secret[]; /* Пароль для доступа на Radius-сервер */
++extern unsigned char rad_users_passwd[]; /* Пароль пользователя, в качестве имени применяется MAC адрес клиента */
++extern uint32_t time_to_restore_primary_server_index; /* Время (в секундах) через которое производится попытка переключиться
++ на первичный RADIUS сервера, если на данный момент осуществлено
++ переключение на резервный */
++extern time_t xid_ttl; /* Время в течение которого хранятся узлы кэша */
++extern uint16_t radius_port; /* Порт на который релей отправляет RADIUS запросы. По умолчанию равен 1812 */
++extern float max_qps; /* Максимально допустимая частота отправки DHCP запросов
++ всеми клиентами суммарно */
++extern float max_qps_from_host; /* Максимально допустимая частота
++ отправки запросов DHCP одним клиентом */
++extern uint32_t cache_list_len; /* Максимальная длина кэша DHCP. Переменная нужна для возможности
++ задания этого параметра из командной строки.
++ В данной версии - не реализовано */
++extern int updating_arp_cache_perm; /* Указывает - обновлять ли ARP кэш при получении RADIUS сообщений с cached == 0 */
++extern struct counter_node * counter; /* Указатель на нулевой элемент массива-счётчика частоты запросов */
++extern time_t normal_clients_counter[QUERY_TIME_RING_LEN]; /* Массив используемый как кольцевой буфер для
++ подсчёта частоты запросов в секунду */
++extern struct arp_entry * arp_cache_perm; /* Указатель на начало динамического массива содержащего ARP записи */
++extern int arp_cache_perm_len; /* Длина массива хранящего кэш статических (флаг PERM) ARP записей */
++extern int server_index; /* Индекс массива серверов, указывающий на RADIUS сервер
++ к которому в текущий момент времени пересылаются запросы */
++extern time_t primary_server_down_time; /* Фиксируется время (секунд), в которое "упал" PRIMARY RADIUS сервер */
++extern int unfinished_requests; /* Переменная хранящая число необработанных RADIUS-сервером запросов.
++ Т.е. число DHCP запросов для которых не получены ответы RADIUS сервера.
++ Переменная используется для обнаружения "падения" RADIUS сервера и
++ переключения на резервный сервер, если таковой указан */
++extern unsigned long forward_client_packets_errors; /* Хранит число неудачных попыток передать запрос на RADIUS сервер */
++extern uint16_t radius_dhcp_relay_port; /* Порт с которого отправляет запрос DHCP relay агент */
++extern int radius_allow_cache; /* Переменная указывающая на возможность кэширования ответов RADIUS */
++extern int radius_allow_dynamic_cache; /* Переменная указывающая на возможность кэширования ответов для клиентов
++ не имеющих привязки MAC -> IP */
++extern int radius_use_mac_delim;
++extern uint8_t * opts_send_to_srv; /* Указатель на массив опций отправляемых на RADIUS сервер при запросе
++ клиентом адреса. Инициализируется в случае использования
++ опции radius-send-opts-to-srv */
++
++/* Структура описывающая заголовок пакета Radius */
++typedef struct rad_header
++{
++ uint8_t code;
++ uint8_t id;
++ uint16_t pack_len;
++ uint8_t auth[16];
++}RAD_HEADER;
++
++/* Полный формат пакета Radius */
++typedef struct rad_message
++{
++ RAD_HEADER header;
++ uint8_t message[4096 - sizeof(RAD_HEADER)];
++}RAD_MESSAGE;
++
++/* Структура входящая в состав xid_list_node и описывающая
++DHCP-запрос полученный от клиента */
++typedef struct dhcp_req_info
++{
++ struct in_addr client_addr;
++ uint32_t server_id;
++ uint32_t req_addr;
++}DHCP_REQ_INFO;
++
++/* Структура узла служащего для обработки DHCP ответов - определения
++типа DHCP ответа отправляемого клиенту. Одновременно служит кэшем DHCP ответов. */
++typedef struct xid_list_node
++{
++ uint8_t allow_cache; /* Булева переменная, принимает значение TRUE если разрешено кэширование DHCP ответов */
++ struct dhcp_packet * out_packet; /* Указатель на структуру для кэширования BOOTREPLY */
++ uint32_t out_pack_len; /* Хранит длину кэшированного пакета что бы не высчитывать её перед повторной
++ отправкой при использовании кэша */
++ uint32_t if_index; /* Индекс интерфейса на котором был получен запрос от клиента */
++ uint32_t relay_if_index; /* Индекс интерфейса на котором DHCPRELAY получил запрос от клиента */
++ uint8_t client_msg_type;
++ uint8_t server_msg_type; /* Возможные состояния транзакции: XID_DISCOVER|XID_OFFER|XID_REUQEST|XID_ACK */
++ uint32_t xid; /* Копируется из dhcp-пакета запроса конфигурации */
++ uint8_t hw_from[MAC_ADDR_LEN]; /* MAC адрес хоста с которого получен DHCP запрос. Равен либо MAC адресу клиента
++ (поле chaddr), либо MAC адресу агента пересылки
++ (промежуточного маршрутизатора) */
++ uint8_t chaddr[MAC_ADDR_LEN]; /* MAC адрес клиента запросившего конфигурацию */
++ uint16_t dhcp_flags; /* Флаги из dhcp-пакета запроса конфигурации. Необходимо для учёта BROADCAST */
++ DHCP_REQ_INFO request_info; /* Служит для определения валидности запроса клиента, т.е. соотвествия
++ запрашиваемого адреса предлагаемому */
++ RAD_HEADER req_header; /* Заголовок запроса Radius отправленного на сервер для получения конфигурации */
++ time_t timestamp; /* Используется для вычисления устаревших узлов кэша */
++ struct xid_list_node *prev; /* Указатель на предыдущий узел списка транзакций */
++ struct xid_list_node *next; /* Указатель на последующий узел списка транзакций */
++} XID_NODE;
++
++typedef struct counter_node
++{
++ uint8_t mac_addr[MAC_ADDR_LEN];
++ time_t timestamp;
++} COUNTER_NODE;
++
++/* Структура для хранения информации о статическом ARP кэше сервера */
++typedef struct arp_entry
++{
++ struct in_addr ip;
++ unsigned char mac[MAC_ADDR_LEN];
++} ARP_ENTRY;
++
++/* Структура для хранения имени игнорируемого интерфейса. Структуры объединяются в список */
++
++typedef struct ignored_dhcp_interface
++{
++ char *if_name;
++ struct ignored_dhcp_interface * next;
++} IGN_DHCP_ENTRY;
++
++/* Структура описывающая заголовок RADIUS VSA */
++typedef struct radius_vsa_dhcp_header
++{
++ uint32_t vendor_id;
++ uint16_t type;
++ uint8_t length; /* Длина VSA данных включая поле type && length */
++ uint8_t *data;
++} VSA_DHCP_HEADER, *PVSA_DHCP_HEADER;
++
++/* Коды полей в DHCP заголовке */
++typedef enum dhcp_header_codes
++{
++ dhcp_op = 256, /* 0: Message opcode/type */
++ dhcp_hwtype, /* 1: Hardware addr type (net/if_types.h) */
++ dhcp_hwlen, /* 2: Hardware addr length */
++ dhcp_hops, /* 3: Number of relay agent hops from client */
++ dhcp_xid, /* 4: Transaction ID */
++ dhcp_secs, /* 8: Seconds since client started looking */
++ dhcp_flags, /* 10: Flag bits */
++ dhcp_ciaddr, /* 12: Client IP address (if already in use) */
++ dhcp_yiaddr, /* 16: Client IP address */
++ dhcp_siaddr, /* 18: IP address of next server to talk to */
++ dhcp_giaddr, /* 20: DHCP relay agent IP address */
++ dhcp_chaddr, /* 24: Client hardware address */
++ dhcp_sname, /* 40: Server name */
++ dhcp_bootfile /* 104: Boot filename */
++}DHCP_HCODES;
++
++typedef struct auxiliary_attributes
++{
++ uint32_t if_index;
++ int allow_cache;
++}AUX_ATTRS;
++
++/* Функции применяемые для работы с Radius-сервером */
++/* Обработчик DHCP сообщений от клиентов */
++isc_result_t got_dhcp_packet(uint8_t * raw_packet, uint32_t length, const struct sockaddr_in * from,
++ struct interface_info * ip, struct hardware * hfrom);
++/* Функция анализирующая полученный от клиента DHCP запрос */
++isc_result_t got_dhcp_packet(uint8_t * raw_packet, uint32_t length, const struct sockaddr_in * from,
++ struct interface_info * ip, struct hardware * hfrom);
++/* Обработчик RADIUS сообщений от RADIUS сервер от RADIUS сервераа */
++isc_result_t got_radius_packet(uint8_t * raw_packet, uint32_t length);
++/* Функция анализирующая RADIUS-Response */
++int dispatch_radius_packet(struct dhcp_packet * packet, unsigned length,
++ struct in_addr * user_if, uint8_t * hw_from);
++/* Функция производящая разбор RADIUS VSA */
++int dispatch_radius_vsa(const int length, const uint8_t * attr_cont, struct dhcp_packet * out_packet,
++ unsigned int * opt_len, AUX_ATTRS *aux_attrs);
++/* Возвращает смещение с байтах поля указанного option относительно начала заголовка DHCP пакета. */
++int dhcp_option_offset(const uint16_t option);
++/* Функция создающая RADIUS VSA и помещающая его по адресу out_bufffer */
++uint8_t make_radius_vsa(uint8_t * out_buffer, uint8_t ob_len, const uint32_t vendor_id,
++ const uint16_t vsa, const uint8_t vsa_len, uint8_t * vsa_value);
++/* Функция добавляющая RADIUS атрибут */
++inline uint8_t add_radius_attribute(uint8_t * message_buffer, uint8_t const * mb_end,
++ uint8_t rad_attr, void * value, uint8_t value_len);
++/* Функция устанавливающая тип DHCP сообщения в исходящем пакете клиенту */
++uint8_t set_dhcp_type_of_out_packet(struct dhcp_packet * out_packet, const int out_pack_len,
++ XID_NODE * cur_xid, const server_id);
++/* Функция возвращающая классовую маску */
++inline uint32_t make_default_netmask(const uint32_t addr);
++/* Добавляем интефейс в список игнорируемых */
++int32_t add_dhcp_ignored_interface(char * if_name);
++/* Производим поиск по списку игнорируемых интерфейсов, возвращаем != 0 если найдено */
++int32_t found_ignored_interfase(char * if_name);
++/* Проверка на переполнение не обработанных DHCP запросов. Такое переполнение может случиться
++ в случае падения RADIUS сервера */
++inline int is_unfinished_requests_overflow(int * count, int inc, int max_count, int zeroing);
++/* Печатам текущий список узлов dhcp-транзакций */
++void print_stat(int sign);
++/* Шифруем пароль для передачи в radius-пакете */
++int encrypt_passwd(char * passwd, uint8_t * encr_passwd,
++ char *shared_key, uint8_t * auth);
++/* Сборка пакета radius-Access-Request для отправки на radius-сервер */
++int assemble_auth_message( RAD_MESSAGE *access_req, const struct dhcp_packet * packet, unsigned length,
++ char *user_name, char *passwd, uint32_t subnet);
++/* Подсчёт контрольной суммы ответа radius-Access-Accept */
++static int calc_reply_auth(RAD_MESSAGE *packet, uint8_t *original_auth, const char *secret);
++/* Добавляем новый узел в список узлов dhcp-транзакций */
++XID_NODE * add_xid(struct dhcp_packet *packet, uint8_t dhcp_type, uint32_t if_index, struct hardware * hw_from);
++/* Функция получающая основную запрашиваемую клиентом информацию из DHCP сообщения */
++int get_dhcp_request_info(struct dhcp_packet *request, DHCP_REQ_INFO * request_info);
++/* Функция создающая DHCPNAK сообщение в буфере на который указывает out_packet */
++void make_dhcp_nak(struct dhcp_packet * out_packet, XID_NODE * cur_xid, const uint32_t server_id);
++/* Определение dhcp-типа пакета (DHCPDISCOVER/DHCPREQUEST/etc...) */
++uint16_t get_dhcp_type(struct dhcp_packet *request, char * str_dhcp_type);
++/* Присваивает option_value значение запрошенной опции находящейся в DHCP пакете */
++uint8_t get_dhcp_option(const struct dhcp_packet *request, uint16_t packet_len, uint8_t req_option,
++ void * option_value, const size_t option_size);
++/* Удаление узла dhcp-транзакции */
++inline XID_NODE * delete_xid(XID_NODE *xid_n);
++/* Удаление старых узлов dhcp-транзакций, у которых поле истекло время ожидания */
++int delete_old_xid(XID_NODE * start_xid_list);
++/* Удаление дублирующихся по MAC-адресу узлов dhcp-транзакций */
++int del_duplicate_xid(uint32_t xid, uint8_t * hw_addr, uint32_t if_index, uint32_t relay_if_index);
++/* Поиск узла dhcp-транзакции либо только по MAC-адресу, либо по MAC-адресу и значению xid */
++XID_NODE * search_xid(uint8_t * hw_addr, uint32_t if_index, uint32_t relay_if_index);
++/* Преобразование пакета radius в dhcp-пакет готовый для отправки клиенту запросившему конфигурационную информацию */
++int translate_rad_to_dhcp(RAD_MESSAGE *rad_pack, struct dhcp_packet * out_packet, uint16_t received_length,
++ uint32_t * user_interface ); /* Параметр необходим для корректной обработки */
++/* Устанавливает указанный тип DHCP сообщения, возвращает предыдущее значение типа */
++uint16_t set_dhcp_type(struct dhcp_packet *request, uint16_t new_type);
++/* Обновляет поля DHCP пакета в кэше перед отправкой пакета клиенту */
++uint16_t update_xid_node(XID_NODE * xid, struct dhcp_packet * packet, unsigned pack_len);
++/* Функция удаляющая самый старый запрос в DHCP кэше */
++int delete_oldest_cache_node(XID_NODE * cache_node);
++/* Подсчитывает среднее число DHCP запросов в секунду за время TIME_DELTA секунд */
++float count_queries_per_sec(void);
++/* Устанавливаем обработчик для смены индекса массива RADIUS серверов на значение по умолчанию */
++inline void set_default_server(int sign);
++/* Устанавливаем обработчик для смены индекса массива */
++void change_server(int sign);
++/* Берём ARP-кэш статически привязанных MAC адресов. ДАННЫЙ ВАРИАНТ ПОДХОДИТ ТОЛЬКО ДЛЯ LINUX!!! */
++int get_arp_cache_perm(void);
++#ifdef __linux__
++/* Функция обновляющая статический ARP кэш на роутере, если для IP сменился MAC */
++int update_arp_cache_perm(uint32_t ip, unsigned char * mac);
++#endif
++/* Функция удаляющая кэшированные xid узлы при изменении соответствия IP - MACклиента */
++int delete_xid_if_mac_not_equal(uint32_t ip, uint8_t * mac);
++/* Печтает help-info для ключей патча*/
++static void patch_help (void);
++/* Функция выполняет подсчёт общего усреднённого числа DHCP запросов */
++float qps_hosts(uint8_t * mac_addr, float * qps_summary);
++
++#endif
++
+diff -ruN dhcp-3.0.7.orig/includes/dhcpd.h dhcp-3.0.7/includes/dhcpd.h
+--- dhcp-3.0.7.orig/includes/dhcpd.h 2008-01-22 20:28:23.000000000 +0300
++++ dhcp-3.0.7/includes/dhcpd.h 2009-09-06 14:15:24.000000000 +0400
+@@ -32,6 +32,10 @@
+ * ``http://www.nominum.com''.
+ */
+
++
++/* START PATCH CODE */
++#define PATCHED_SERVER
++/* END PATCH CODE */
+ #ifndef __CYGWIN32__
+ #include <sys/types.h>
+ #include <netinet/in.h>
+@@ -75,7 +79,6 @@
+ #include "tree.h"
+ #include "inet.h"
+ #include "dhctoken.h"
+-
+ #include <isc-dhcp/result.h>
+ #include <omapip/omapip_p.h>
+
+@@ -428,6 +431,45 @@
+ #define SV_DO_FORWARD_UPDATES 45
+ #define SV_PING_TIMEOUT 46
+
++/* START PATCH CODE */
++#ifdef PATCHED_SERVER
++
++/* { "use-dhcp2radius", "f", &server_universe, 100 },*/
++#define SV_RAD2DHCP 100
++/* { "radius-servers", "IA", &server_universe, 101 },*/
++#define SV_RADIUS_SERVERS 101
++/* { "radius-secret", "t", &server_universe, 102 },*/
++#define SV_RADIUS_SECRET 102
++/* { "radius-password", "t", &server_universe, 103 },*/
++#define SV_RADIUS_PASSWORD 103
++/* { "radius-server-restore", "L", &server_universe, 104 },*/
++#define SV_RADIUS_SRV_RESTORE 104
++/* { "radius-port", "S", &server_universe, 105 },*/
++#define SV_RADIUS_SRV_PORT 105
++/* { "radius-client-freq", "L", &server_universe, 106 },*/
++#define SV_RADIUS_CLIENT_FREQ 106
++/* { "radius-cache-ttl", "L", &server_universe, 107 },*/
++#define SV_RADIUS_CACHE_TTL 107
++/* { "radius-freq-summ", "L", &server_universe, 108 },*/
++#define SV_RADIUS_FREQ_SUM 108
++/* { "radius-update-arp", "f", &server_universe, 109 },*/
++#define SV_RADIUS_UPDATE_ARP 109
++/* { "radius-cache-maxlen", "L", &server_universe, 110 },*/
++#define SV_RADIUS_CACHE_MAXLEN 110
++/* { "radius-dhcp-relay-port", "S", &server_universe, 111 },*/
++#define SV_RADIUS_DHCP_RELAY_PORT 111
++/* { "radius-allow-cache", "f", &server_universe, 112 },*/
++#define SV_RADIUS_ALLOW_CACHE 112
++/* { "radius-allow-dynamic-cache", "f",&server_universe, 113 },*/
++#define SV_RADIUS_ALLOW_DYN_CACHE 113
++/* { "radius-send-opts-to-srv", "X", &server_universe, 114 },*/
++#define SV_RADIUS_SEND_OPTS_TO_SRV 114
++/* { "radius-use-mac-delimiter", "f", &server_universe, 115 },*/
++#define SV_RADIUS_USE_MAC_DELIM 115
++
++#endif /* #ifdef PATCHED_SERVER */
++/* END PATCH CODE */
++
+ #if !defined (DEFAULT_PING_TIMEOUT)
+ # define DEFAULT_PING_TIMEOUT 1
+ #endif
+@@ -2643,3 +2685,4 @@
+ #endif /* FAILOVER_PROTOCOL */
+
+ const char *binding_state_print (enum failover_state);
++
+diff -ruN dhcp-3.0.7.orig/server/dhcpd.c dhcp-3.0.7/server/dhcpd.c
+--- dhcp-3.0.7.orig/server/dhcpd.c 2008-05-15 00:54:24.000000000 +0400
++++ dhcp-3.0.7/server/dhcpd.c 2009-09-06 14:15:24.000000000 +0400
+@@ -47,6 +47,16 @@
+ #include "version.h"
+ #include <omapip/omapip_p.h>
+
++/* START PATCH CODE */
++
++#ifdef PATCHED_SERVER
++
++#include "dhcp2radius.h"
++const char patch_info[] = "Patched by Chebotarev Roman. Home page: " HOME_PAGE "\n"
++ "Patch version info: " PATCH_VERSION;
++#endif /* PATCHED_SERVER */
++/* END PATCH CODE */
++
+ static void usage PROTO ((void));
+
+ struct iaddr server_identifier;
+@@ -316,6 +326,14 @@
+ cftest = 1;
+ lftest = 1;
+ log_perror = -1;
++#ifdef PATCHED_SERVER
++ } else if( !strcmp (argv [i], "-I"))
++ {
++ if(++i == argc)
++ usage();
++ if(!add_dhcp_ignored_interface(argv[i]))
++ log_fatal("PATCH: Can't add interface '%s' to ignored DHCP interfaces list.", argv[i]);
++#endif
+ } else if (!strcmp (argv [i], "-q")) {
+ quiet = 1;
+ quiet_interface_discovery = 1;
+@@ -367,6 +385,11 @@
+ if (!quiet) {
+ log_info ("%s %s", message, DHCP_VERSION);
+ log_info (copyright);
++/* START PATCH CODE */
++#ifdef PATCHED_SERVER
++ log_info (patch_info);
++#endif
++/* END PATCH CODE */
+ log_info (arr);
+ log_info (url);
+ } else {
+@@ -589,6 +612,16 @@
+ omapi_set_int_value ((omapi_object_t *)dhcp_control_object,
+ (omapi_object_t *)0, "state", server_running);
+
++/* START PATCH CODE */
++#ifdef PATCHED_SERVER
++ if(signal(SIGSTAT, print_stat) == SIG_ERR) /* Для вывода статистики */
++ log_error("ERROR: signal() for handling SIGSTAT failed. Runtime statistic not available.");
++ if(signal(SIGNAL_SET_PRI_SERVER, set_default_server) == SIG_ERR) /* Для принудительного включения первичного */
++ log_error("ERROR: signal() for handling SIGNAL_SET_PRI_SERVER failed."); /* RADIUS-сервера */
++ if(signal(SIGNAL_CHANGE_SERV, change_server) == SIG_ERR) /* Для принудительной смены RADIUS сервера */
++ log_error("ERROR: signal() for handling SIGNAL_CHANGE_SERV failed."); /* на следующий по списку */
++#endif
++/* END PATCH CODE */
+ /* Receive packets and dispatch them... */
+ dispatch ();
+
+@@ -596,6 +629,293 @@
+ return 0;
+ }
+
++/* START PATCH CODE */
++#ifdef PATCHED_SERVER
++
++void patch_configure(struct option_state *options)
++{
++ struct parse *parse;
++ char *s;
++ struct data_string db;
++ struct option_cache *oc;
++ bzero(&db, sizeof(db));
++ oc = lookup_option (config_universe, options, SV_RAD2DHCP);
++ if (oc)
++ {
++ int ignorep;
++ if((use_dhcp2radius = evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
++ (struct lease *)0, 0,
++ options,
++ (struct option_state *)0,
++ &global_scope, oc, MDL)))
++ {
++ data_string_forget (&db, MDL);
++ log_info("PATCH: dhcp2radius ability is enabled.");
++ int i;
++
++ oc = lookup_option (&server_universe, options, SV_RADIUS_SRV_PORT);
++ if (oc &&
++ evaluate_option_cache (&db, (struct packet *)0,
++ (struct lease *)0, (struct client_state *)0,
++ options, (struct option_state *)0,
++ &global_scope, oc, MDL))
++ {
++ if(db.len != sizeof(radius_port))
++ log_fatal("PATCH ERROR: invalid 'RADIUS port' length: %d must be: %d",
++ db.len, sizeof(radius_port));
++ radius_port = htons(getUShort(db.data));
++ data_string_forget (&db, MDL);
++ }
++ else
++ radius_port = htons(RADIUS_PORT);
++
++
++ oc = lookup_option (&server_universe, options, SV_RADIUS_SERVERS);
++ if (oc &&
++ evaluate_option_cache (&db, (struct packet *)0,
++ (struct lease *)0, (struct client_state *)0,
++ options, (struct option_state *)0,
++ &global_scope, oc, MDL))
++ {
++ if(db.len % IPV4_ALEN)
++ log_fatal("PATCH ERROR: Invalid RADIUS servers address length.");
++ radius_servers_count = (int)(db.len / IPV4_ALEN);
++ radius_servers = calloc(radius_servers_count, sizeof(struct sockaddr_in));
++ if(!radius_servers)
++ log_fatal("FATAL: Can't allocate memory for RADIUS servers list.");
++ for(i = 0; i < radius_servers_count; ++i)
++ {
++ memcpy(&radius_servers[i].sin_addr.s_addr, db.data + IPV4_ALEN * i, IPV4_ALEN);
++ radius_servers[i].sin_port = radius_port;
++ radius_servers[i].sin_family = AF_INET;
++#ifdef HAVE_SA_LEN
++ radius_servers[i].sin_len = sizeof(radius_servers[i]);
++#endif
++ }
++ data_string_forget (&db, MDL);
++ }
++ else
++ log_fatal("PATCH ERROR: RADIUS servers not found in configuration file!");
++
++
++ oc = lookup_option (&server_universe, options, SV_RADIUS_SECRET);
++ if (oc &&
++ evaluate_option_cache (&db, (struct packet *)0,
++ (struct lease *)0, (struct client_state *)0,
++ options, (struct option_state *)0,
++ &global_scope, oc, MDL))
++ {
++ if(db.len > (RAD_SECRET_SIZE - 1) )
++ log_fatal("PATCH ERROR: RADIUS secret too long. Maximum length - %d.", RAD_SECRET_SIZE - 1);
++ bzero(rad_secret, RAD_SECRET_SIZE);
++ strncpy(rad_secret, db.data, RAD_SECRET_SIZE - 1);
++ data_string_forget (&db, MDL);
++ }
++ else
++ log_fatal("PATCH ERROR: RADIUS secret not found in configuration file!");
++
++
++ oc = lookup_option (&server_universe, options, SV_RADIUS_PASSWORD);
++ if (oc &&
++ evaluate_option_cache (&db, (struct packet *)0,
++ (struct lease *)0, (struct client_state *)0,
++ options, (struct option_state *)0,
++ &global_scope, oc, MDL))
++ {
++ if(db.len > (RAD_PASSWD_SIZE - 1) )
++ log_fatal("PATCH ERROR: RADIUS password too long. Maximum length - %d.", RAD_PASSWD_SIZE - 1);
++ bzero(rad_users_passwd, RAD_PASSWD_SIZE);
++ strncpy(rad_users_passwd, db.data, RAD_PASSWD_SIZE - 1);
++ data_string_forget (&db, MDL);
++ }
++ else
++ log_fatal("PATCH ERROR: RADIUS password not found in configuration file!");
++
++
++ oc = lookup_option (&server_universe, options, SV_RADIUS_SRV_RESTORE);
++ if (oc &&
++ evaluate_option_cache (&db, (struct packet *)0,
++ (struct lease *)0, (struct client_state *)0,
++ options, (struct option_state *)0,
++ &global_scope, oc, MDL))
++ {
++ if(db.len != sizeof(time_to_restore_primary_server_index))
++ log_fatal("PATCH ERROR: invalid 'time to restore primary server' length: %d must be: %d",
++ db.len, sizeof(time_to_restore_primary_server_index));
++ time_to_restore_primary_server_index = getULong(db.data);
++ data_string_forget (&db, MDL);
++ }
++ else
++ time_to_restore_primary_server_index = 0;
++
++
++ oc = lookup_option (&server_universe, options, SV_RADIUS_CACHE_TTL);
++ if (oc &&
++ evaluate_option_cache (&db, (struct packet *)0,
++ (struct lease *)0, (struct client_state *)0,
++ options, (struct option_state *)0,
++ &global_scope, oc, MDL))
++ {
++ if(db.len != sizeof(xid_ttl))
++ log_fatal("PATCH ERROR: invalid 'cache ttl' length: %d must be: %d",
++ db.len, sizeof(xid_ttl));
++ xid_ttl = getULong(db.data);
++ data_string_forget (&db, MDL);
++ }
++ else
++ xid_ttl = DEFAULT_XID_TTL;
++
++ oc = lookup_option (&server_universe, options, SV_RADIUS_DHCP_RELAY_PORT);
++ if (oc &&
++ evaluate_option_cache (&db, (struct packet *)0,
++ (struct lease *)0, (struct client_state *)0,
++ options, (struct option_state *)0,
++ &global_scope, oc, MDL))
++ {
++ if(db.len != sizeof(xid_ttl))
++ log_fatal("PATCH ERROR: invalid 'cache ttl' length: %d must be: %d",
++ db.len, sizeof(radius_dhcp_relay_port));
++ radius_dhcp_relay_port = htons(getUShort(db.data));
++ data_string_forget (&db, MDL);
++ }
++ else
++ radius_dhcp_relay_port = htons(RELAY_PORT);
++
++
++ oc = lookup_option (&server_universe, options, SV_RADIUS_CLIENT_FREQ);
++ if (oc &&
++ evaluate_option_cache (&db, (struct packet *)0,
++ (struct lease *)0, (struct client_state *)0,
++ options, (struct option_state *)0,
++ &global_scope, oc, MDL))
++ {
++ if(db.len != sizeof(unsigned long))
++ log_fatal("PATCH ERROR: invalid 'RADIUS maximum frequency queries from one host' length:"
++ " %d must be: %d", db.len, sizeof(unsigned long));
++ max_qps_from_host = (float) getULong(db.data);
++ data_string_forget (&db, MDL);
++ }
++ else
++ max_qps_from_host = MAX_QPS_FROM_HOST;
++
++
++ oc = lookup_option (&server_universe, options, SV_RADIUS_FREQ_SUM);
++ if (oc &&
++ evaluate_option_cache (&db, (struct packet *)0,
++ (struct lease *)0, (struct client_state *)0,
++ options, (struct option_state *)0,
++ &global_scope, oc, MDL))
++ {
++ if(db.len != sizeof(unsigned long))
++ log_fatal("PATCH ERROR: invalid 'RADIUS summary frequency of DHCP queries' length: %d must be: %d",
++ db.len, sizeof(unsigned long));
++ max_qps = (float) getULong(db.data);
++ data_string_forget (&db, MDL);
++ }
++ else
++ max_qps = MAX_DHCP_QPS;
++
++
++ oc = lookup_option (&server_universe, options, SV_RADIUS_CACHE_MAXLEN);
++ if (oc &&
++ evaluate_option_cache (&db, (struct packet *)0,
++ (struct lease *)0, (struct client_state *)0,
++ options, (struct option_state *)0,
++ &global_scope, oc, MDL))
++ {
++ if(db.len != sizeof(cache_list_len))
++ log_fatal("PATCH ERROR: invalid 'RADIUS cache maximum length' length: %d must be: %d",
++ db.len, sizeof(cache_list_len));
++ cache_list_len = getULong(db.data);
++ data_string_forget (&db, MDL);
++ }
++ else
++ cache_list_len = MAX_CACHE_LIST_LEN;
++
++ oc = lookup_option (&server_universe, options, SV_RADIUS_USE_MAC_DELIM);
++ if(oc)
++ radius_use_mac_delim = evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
++ (struct lease *)0, 0, options,
++ (struct option_state *)0,
++ &global_scope, oc, MDL);
++
++#ifdef __linux__
++ oc = lookup_option (&server_universe, options, SV_RADIUS_UPDATE_ARP);
++ if(oc)
++ updating_arp_cache_perm = evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
++ (struct lease *)0, 0, options,
++ (struct option_state *)0,
++ &global_scope, oc, MDL);
++#endif
++
++ oc = lookup_option (config_universe, options, SV_RADIUS_ALLOW_CACHE);
++ if(oc)
++ {
++ radius_allow_cache = evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
++ (struct lease *)0, 0, options,
++ (struct option_state *)0,
++ &global_scope, oc, MDL);
++ }
++ else /* По умолчанию кэш для клиентов имеющих привязку MAC -> IP разрешён */
++ radius_allow_cache = 1;
++
++
++ if(radius_allow_cache &&
++ (oc = lookup_option (config_universe, options, SV_RADIUS_ALLOW_DYN_CACHE)) )
++ radius_allow_dynamic_cache = evaluate_boolean_option_cache (&ignorep, (struct packet *)0,
++ (struct lease *)0, 0, options,
++ (struct option_state *)0,
++ &global_scope, oc, MDL);
++ else /* По умолчанию кэш для клиентов не имеющих привязки MAC -> IP отключен */
++ radius_allow_dynamic_cache = 0;
++
++
++ oc = lookup_option (&server_universe, options, SV_RADIUS_SEND_OPTS_TO_SRV);
++ if (oc &&
++ evaluate_option_cache (&db, (struct packet *)0,
++ (struct lease *)0, (struct client_state *)0,
++ options, (struct option_state *)0,
++ &global_scope, oc, MDL))
++ {
++ opts_send_to_srv = malloc(db.len + 1);
++ if(!opts_send_to_srv)
++ log_fatal("FATAL: Can't allocate memory for array of options that are sent to the server.");
++ opts_send_to_srv[db.len] = 0; /* отмечаем конец опций */
++ memcpy(opts_send_to_srv, db.data, db.len);
++ data_string_forget (&db, MDL);
++ }
++
++ /* Инициализируем глобальные структуры данных необходимые для работы */
++ bzero(normal_clients_counter, sizeof(normal_clients_counter)); /* Обнуляем кольцевой буфер */
++ /* Создаём динамический массив для счётчика запросов */
++ counter = malloc(sizeof(struct counter_node) * MIN_COUNTER_SIZE);
++
++ if(!counter)
++ log_fatal("FATAL: malloc error for counter");
++
++ bzero(counter, MIN_COUNTER_SIZE);
++#ifdef __linux__
++ if(updating_arp_cache_perm)
++ {
++ if( !(arp_cache_perm = calloc(arp_cache_perm_len, sizeof(struct arp_entry))) )
++ log_fatal("FATAL: Can't allocate memory for copy ARP cache.");
++ if(! get_arp_cache_perm())
++ log_fatal("FATAL: Can't get ARP cache. Try launch dhcrelay without updating ARP cache option.\n");
++ }
++#endif
++ }
++ else
++ log_info("PATCH: DHCP to RADIUS ability is disabled.");
++ }
++ else
++ log_info("PATCH: DHCP to RADIUS ability is disabled.");
++
++ return;
++}
++
++#endif /* PATCHED_SERVER */
++/* END PATCH CODE */
++
+ void postconf_initialization (int quiet)
+ {
+ struct option_state *options = (struct option_state *)0;
+@@ -789,6 +1109,11 @@
+ log_info ("%s %s",
+ message, DHCP_VERSION);
+ log_info (copyright);
++/* START PATCH CODE */
++#ifdef PATCHED_SERVER
++ log_info (patch_info);
++#endif
++/* END PATCH CODE */
+ log_info (arr);
+ log_info (url);
+ log_perror = tmp;
+@@ -799,6 +1124,12 @@
+ }
+ }
+
++/* START PATCH CODE */
++#ifdef PATCHED_SERVER
++ patch_configure(options);
++#endif
++/* END PATCH CODE */
++
+ /* Don't need the options anymore. */
+ option_state_dereference (&options, MDL);
+
+@@ -863,6 +1194,11 @@
+ {
+ log_info ("%s %s", message, DHCP_VERSION);
+ log_info (copyright);
++/* START PATCH CODE */
++#ifdef PATCHED_SERVER
++ log_info (patch_info);
++#endif
++/* END PATCH CODE */
+ log_info (arr);
+
+ log_fatal ("Usage: dhcpd [-p <UDP port #>] [-d] [-f]%s%s%s%s",
+diff -ruN dhcp-3.0.7.orig/server/stables.c dhcp-3.0.7/server/stables.c
+--- dhcp-3.0.7.orig/server/stables.c 2004-06-10 21:59:58.000000000 +0400
++++ dhcp-3.0.7/server/stables.c 2009-09-06 14:15:24.000000000 +0400
+@@ -536,6 +536,24 @@
+ { "unknown-97", "X", &server_universe, 97 },
+ { "unknown-98", "X", &server_universe, 98 },
+ { "unknown-99", "X", &server_universe, 99 },
++#ifdef PATCHED_SERVER
++ { "use-dhcp2radius", "f", &server_universe, 100 },
++ { "radius-servers", "IA", &server_universe, 101 },
++ { "radius-secret", "t", &server_universe, 102 },
++ { "radius-password", "t", &server_universe, 103 },
++ { "radius-server-restore", "L", &server_universe, 104 },
++ { "radius-port", "S", &server_universe, 105 },
++ { "radius-client-freq", "L", &server_universe, 106 },
++ { "radius-cache-ttl", "L", &server_universe, 107 },
++ { "radius-freq-summ", "L", &server_universe, 108 },
++ { "radius-update-arp", "f", &server_universe, 109 },
++ { "radius-cache-maxlen", "L", &server_universe, 110 },
++ { "radius-dhcp-relay-port", "S", &server_universe, 111 },
++ { "radius-allow-cache", "f", &server_universe, 112 },
++ { "radius-allow-dynamic-cache", "f",&server_universe, 113 },
++ { "radius-send-opts-to-srv", "X", &server_universe, 114 },
++ { "radius-use-mac-delimiter", "f", &server_universe, 115 },
++#else
+ { "unknown-100", "X", &server_universe, 100 },
+ { "unknown-101", "X", &server_universe, 101 },
+ { "unknown-102", "X", &server_universe, 102 },
+@@ -552,6 +570,7 @@
+ { "unknown-113", "X", &server_universe, 113 },
+ { "unknown-114", "X", &server_universe, 114 },
+ { "unknown-115", "X", &server_universe, 115 },
++#endif
+ { "unknown-116", "X", &server_universe, 116 },
+ { "unknown-117", "X", &server_universe, 117 },
+ { "unknown-118", "X", &server_universe, 118 },
diff --git a/net-misc/dhcp/files/dhcp-3.0.7-warning-format.patch b/net-misc/dhcp/files/dhcp-3.0.7-warning-format.patch
new file mode 100644
index 0000000..d80ed69
--- /dev/null
+++ b/net-misc/dhcp/files/dhcp-3.0.7-warning-format.patch
@@ -0,0 +1,125 @@
+From e0319a2abba3ff10035c47f7ea84ab93abc3f371 Mon Sep 17 00:00:00 2001
+From: Afanasov Dmitry <ender@altlinux.org>
+Date: Tue, 12 May 2009 15:23:39 +0400
+Subject: [PATCH] fix warning about format functions
+
+---
+ dhcp/client/dhclient.c | 12 ++++++------
+ dhcp/common/print.c | 4 ++--
+ dhcp/relay/dhcrelay.c | 6 +++---
+ dhcp/server/dhcpd.c | 16 ++++++++--------
+ 4 files changed, 19 insertions(+), 19 deletions(-)
+
+diff --git a/dhcp/client/dhclient.c b/dhcp/client/dhclient.c
+index c9998fe..5570c24 100644
+--- a/dhcp/client/dhclient.c
++++ b/dhcp/client/dhclient.c
+@@ -262,9 +262,9 @@ int main (argc, argv, envp)
+
+ if (!quiet) {
+ log_info ("%s %s", message, DHCP_VERSION);
+- log_info (copyright);
+- log_info (arr);
+- log_info (url);
++ log_info ("%s", copyright);
++ log_info ("%s", arr);
++ log_info ("%s", url);
+ log_info ("%s", "");
+ } else
+ log_perror = 0;
+@@ -470,9 +470,9 @@ int main (argc, argv, envp)
+ static void usage ()
+ {
+ log_info ("%s %s", message, DHCP_VERSION);
+- log_info (copyright);
+- log_info (arr);
+- log_info (url);
++ log_info ("%s", copyright);
++ log_info ("%s", arr);
++ log_info ("%s", url);
+
+ log_error ("Usage: dhclient [-1dqr] [-nw] [-p <port>] %s",
+ "[-s server]");
+diff --git a/dhcp/common/print.c b/dhcp/common/print.c
+index a49e747..969f8ab 100644
+--- a/dhcp/common/print.c
++++ b/dhcp/common/print.c
+@@ -311,7 +311,7 @@ void dump_raw (buf, len)
+ lbuf[54]=' ';
+ lbuf[55]=' ';
+ lbuf[73]='\0';
+- log_info (lbuf);
++ log_info ("%s", lbuf);
+ }
+ memset(lbuf, ' ', 79);
+ lbuf [79] = 0;
+@@ -335,7 +335,7 @@ void dump_raw (buf, len)
+ lbuf[54]=' ';
+ lbuf[55]=' ';
+ lbuf[73]='\0';
+- log_info (lbuf);
++ log_info ("%s", lbuf);
+ }
+
+ void hash_dump (table)
+diff --git a/dhcp/relay/dhcrelay.c b/dhcp/relay/dhcrelay.c
+index 5dfd0e8..3eb629d 100644
+--- a/dhcp/relay/dhcrelay.c
++++ b/dhcp/relay/dhcrelay.c
+@@ -252,9 +252,9 @@ int main (argc, argv, envp)
+
+ if (!quiet) {
+ log_info ("%s %s", message, DHCP_VERSION);
+- log_info (copyright);
+- log_info (arr);
+- log_info (url);
++ log_info ("%s", copyright);
++ log_info ("%s", arr);
++ log_info ("%s", url);
+ } else {
+ quiet = 0;
+ log_perror = 0;
+diff --git a/dhcp/server/dhcpd.c b/dhcp/server/dhcpd.c
+index f0166e7..977df25 100644
+--- a/dhcp/server/dhcpd.c
++++ b/dhcp/server/dhcpd.c
+@@ -379,9 +379,9 @@ int main (argc, argv, envp)
+
+ if (!quiet) {
+ log_info ("%s %s", message, DHCP_VERSION);
+- log_info (copyright);
+- log_info (arr);
+- log_info (url);
++ log_info ("%s", copyright);
++ log_info ("%s", arr);
++ log_info ("%s", url);
+ } else {
+ quiet = 0;
+ log_perror = 0;
+@@ -812,9 +812,9 @@ void postconf_initialization (int quiet)
+ log_perror = 0;
+ log_info ("%s %s",
+ message, DHCP_VERSION);
+- log_info (copyright);
+- log_info (arr);
+- log_info (url);
++ log_info ("%s", copyright);
++ log_info ("%s", arr);
++ log_info ("%s", url);
+ log_perror = tmp;
+ }
+ } else
+@@ -886,8 +886,8 @@ void postdb_startup (void)
+ static void usage ()
+ {
+ log_info ("%s %s", message, DHCP_VERSION);
+- log_info (copyright);
+- log_info (arr);
++ log_info ("%s", copyright);
++ log_info ("%s", arr);
+
+ log_fatal ("Usage: dhcpd [-p <UDP port #>] [-d] [-f]%s%s%s%s%s",
+ "\n [-cf config-file] [-lf lease-file]",
+--
+1.7.2.1
+