Compare commits

...
Author SHA1 Message Date
Wouter Wijngaards 0cb879967d Scrubber fixup.
git-svn-id: file:///svn/unbound/branches/support-1.0@1179 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-08-07 06:56:08 +00:00
Wouter Wijngaards 2703db44aa iana port update.
git-svn-id: file:///svn/unbound/branches/support-1.0@1178 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-08-05 11:39:32 +00:00
Wouter Wijngaards d5ac360be4 fixup DS test for apex validation of NODATA.
git-svn-id: file:///svn/unbound/branches/support-1.0@1177 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-08-05 10:54:27 +00:00
Wouter Wijngaards f91066ba47 iana update more.
git-svn-id: file:///svn/unbound/branches/support-1.0@1175 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-08-04 13:07:55 +00:00
Wouter Wijngaards e31c9620b1 fix bug #201 from trunk , and iana port update.
git-svn-id: file:///svn/unbound/branches/support-1.0@1174 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-08-04 12:43:00 +00:00
Wouter Wijngaards d99661bb57 DS lookup bugfix for qtype DS by the client.
git-svn-id: file:///svn/unbound/branches/support-1.0@1169 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-30 21:04:46 +00:00
Wouter Wijngaards c1a40f1beb #198 bug fixups.
git-svn-id: file:///svn/unbound/branches/support-1.0@1162 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-21 07:59:29 +00:00
Wouter Wijngaards 56d9e9677e #198 fix.
git-svn-id: file:///svn/unbound/branches/support-1.0@1161 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-19 15:34:57 +00:00
Wouter Wijngaards c13d85690b branch for 1.0 support
git-svn-id: file:///svn/unbound/branches/support-1.0@1158 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-18 13:00:57 +00:00
Wouter Wijngaards 45dd63d7c8 TODO request.
git-svn-id: file:///svn/unbound/trunk@1157 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-18 11:00:49 +00:00
Wouter Wijngaards 8ab18cb0f7 fds max test before start.
git-svn-id: file:///svn/unbound/trunk@1156 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-17 10:07:40 +00:00
Wouter Wijngaards 4e2ca85842 fix bug #195.
git-svn-id: file:///svn/unbound/trunk@1155 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-17 09:00:38 +00:00
Wouter Wijngaards 71d292580b fixup #196.
git-svn-id: file:///svn/unbound/trunk@1154 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-17 08:45:12 +00:00
Wouter Wijngaards d4b612e48b 1.0.1 tag
trunk to 1.0.2
sha256 support in trunk makedist.sh



git-svn-id: file:///svn/unbound/trunk@1153 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-16 13:16:36 +00:00
Wouter Wijngaards 3d7ad2de3c fixed makedist for manpage editing
git-svn-id: file:///svn/unbound/trunk@1152 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-16 12:15:23 +00:00
Wouter Wijngaards 24cb32dc6b update with testcode matches with ldns testcode.
git-svn-id: file:///svn/unbound/trunk@1151 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-16 09:51:54 +00:00
Wouter Wijngaards 4263f2a692 - lowered log_hex blocksize to fit through BSD syslog linesize.
- no useless initialisation if getpwnam not available.
- iana, ldns snapshot updated.



git-svn-id: file:///svn/unbound/trunk@1150 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-15 15:05:12 +00:00
Wouter Wijngaards 8459b5f55f fixup error handling in libunbound ub_resolve().
git-svn-id: file:///svn/unbound/trunk@1149 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-15 10:22:39 +00:00
Wouter Wijngaards 6acc20abf4 fixup for type DS queries from clients when trustanchor for that name exists.
git-svn-id: file:///svn/unbound/trunk@1148 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-15 09:45:50 +00:00
Wouter Wijngaards 498039108b iana portlist update
git-svn-id: file:///svn/unbound/trunk@1147 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-15 08:14:03 +00:00
Wouter Wijngaards d165625c4d default local zones draft 06.
git-svn-id: file:///svn/unbound/trunk@1146 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-15 07:46:40 +00:00
Wouter Wijngaards af6cbba475 changelog entry
git-svn-id: file:///svn/unbound/trunk@1145 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-14 09:19:02 +00:00
Matthijs Mekking 14f657933c free prev and origin after failing reading root hints.
note:
valgrind still complains about the following:

==19935==    by 0x40581E1: ldns_key_buf2rsa_raw (dnssec.c:421)
==19935==    by 0x40B1151: dnskey_verify_rrset_sig (val_sigcrypt.c:1265)




git-svn-id: file:///svn/unbound/trunk@1144 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-07-03 14:01:15 +00:00
Wouter Wijngaards 1808c93e15 import ldns portability fixes.
git-svn-id: file:///svn/unbound/trunk@1143 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-27 10:28:37 +00:00
Wouter Wijngaards 8078891a28 script to update trust anchors.
git-svn-id: file:///svn/unbound/trunk@1142 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-26 18:47:09 +00:00
Wouter Wijngaards 9a102eed3e streamtcp fixup.
git-svn-id: file:///svn/unbound/trunk@1141 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-26 14:24:22 +00:00
Wouter Wijngaards 02c493bd2d fixup compile.
git-svn-id: file:///svn/unbound/trunk@1140 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-25 15:57:41 +00:00
Wouter Wijngaards e2f8a1cb82 mingw port continues.
git-svn-id: file:///svn/unbound/trunk@1139 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-25 14:36:10 +00:00
Wouter Wijngaards 78a3c4e93d fixup unit test for lameness changes.
git-svn-id: file:///svn/unbound/trunk@1138 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-25 09:56:22 +00:00
Wouter Wijngaards 5eb7ff35ca fixup for newegg lameness.
git-svn-id: file:///svn/unbound/trunk@1137 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-25 09:39:57 +00:00
Wouter Wijngaards 4e1eab891b fixup test typos.
git-svn-id: file:///svn/unbound/trunk@1136 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-25 08:12:13 +00:00
Wouter Wijngaards 31a3035c60 Ancil test typo.
git-svn-id: file:///svn/unbound/trunk@1135 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-24 15:06:32 +00:00
Wouter Wijngaards aaab8cb352 fwd_ancil detect failure correctly.
git-svn-id: file:///svn/unbound/trunk@1134 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-24 14:53:30 +00:00
Wouter Wijngaards fc0dcf12c3 updated ldns tarball with mingw32 platform support.
git-svn-id: file:///svn/unbound/trunk@1133 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-24 14:46:21 +00:00
Wouter Wijngaards 4664c66f06 fixup tests to make test program. please lint.
git-svn-id: file:///svn/unbound/trunk@1132 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-24 14:40:53 +00:00
Wouter Wijngaards 56f3cd33ec Fixup ipv6 availability test.
git-svn-id: file:///svn/unbound/trunk@1131 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-24 14:35:53 +00:00
Wouter Wijngaards a64adc395f ipv6 test working for windows.
git-svn-id: file:///svn/unbound/trunk@1130 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-24 14:18:06 +00:00
Wouter Wijngaards 66f896ddbf iana update.
checklocks.c is not in the compile path for production code anymore.



git-svn-id: file:///svn/unbound/trunk@1129 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-24 09:24:08 +00:00
Wouter Wijngaards ee5ee20071 Porting continues. TCP works fine now.
git-svn-id: file:///svn/unbound/trunk@1128 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-23 13:52:03 +00:00
Wouter Wijngaards fc3fc7a1f3 unit test, testbound, basic udp and tcp tests are working on XP.
ipv6 not supported by OS is a warning (nonfatal).

git-svn-id: file:///svn/unbound/trunk@1127 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-18 14:27:30 +00:00
Wouter Wijngaards 7be0e5b814 testbound works on XP.
ioctlsocket nicer error message.

git-svn-id: file:///svn/unbound/trunk@1126 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-18 08:16:04 +00:00
Wouter Wijngaards d4cfee1f00 busy porting tests.
git-svn-id: file:///svn/unbound/trunk@1125 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-17 15:21:48 +00:00
Wouter Wijngaards f7059107b3 winsock_event handler, working resolution and validation on windows.
git-svn-id: file:///svn/unbound/trunk@1124 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-17 14:57:18 +00:00
Wouter Wijngaards 7a528cdf53 set USE_WINSOCK if on windows. error string routine. start and clean winsock.
git-svn-id: file:///svn/unbound/trunk@1123 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-16 15:02:52 +00:00
Wouter Wijngaards f90f5a2583 windows threads. detect gdi32. nicer DISABLED_THREADS define. Compiles on mingw32.
git-svn-id: file:///svn/unbound/trunk@1122 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-16 13:39:46 +00:00
Wouter Wijngaards 76ee7a352a iana portlist update
git-svn-id: file:///svn/unbound/trunk@1121 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-16 07:00:39 +00:00
Wouter Wijngaards 148e8a69c9 compiles cleaner on ming32, socketpair compat.
git-svn-id: file:///svn/unbound/trunk@1120 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-13 15:32:16 +00:00
Wouter Wijngaards 39e4ba0e78 fix mkdir check.
git-svn-id: file:///svn/unbound/trunk@1119 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-13 13:26:15 +00:00
Wouter Wijngaards afda1a8bcc mingw32 porting.
git-svn-id: file:///svn/unbound/trunk@1118 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-13 13:20:54 +00:00
Wouter Wijngaards 092a325270 unused definitions.
git-svn-id: file:///svn/unbound/trunk@1117 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-13 09:44:25 +00:00
Wouter Wijngaards cc6322ac0f newer autoconf.
git-svn-id: file:///svn/unbound/trunk@1116 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-10 09:52:25 +00:00
Wouter Wijngaards 2487f435f6 port to xandros.
git-svn-id: file:///svn/unbound/trunk@1115 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-10 09:42:25 +00:00
Wouter Wijngaards 423e1a95a8 Bug#183 fixup.
git-svn-id: file:///svn/unbound/trunk@1114 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-09 14:59:29 +00:00
Wouter Wijngaards 8ffff3c0a3 more portable lex warning fix.
git-svn-id: file:///svn/unbound/trunk@1113 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-09 09:34:40 +00:00
Wouter Wijngaards 39e01091e7 Fixup warning.
git-svn-id: file:///svn/unbound/trunk@1112 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-09 09:29:44 +00:00
Wouter Wijngaards 8527bd4aff Fixup Richard Doty reported lameness detection fault.
git-svn-id: file:///svn/unbound/trunk@1111 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-09 08:29:59 +00:00
Wouter Wijngaards 1dec098624 iana portlist update
git-svn-id: file:///svn/unbound/trunk@1110 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-08 09:35:32 +00:00
Wouter Wijngaards 283f2a5edb if multiple CNAME's, use the first.
git-svn-id: file:///svn/unbound/trunk@1109 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-08 09:27:48 +00:00
Wouter Wijngaards 0db56d8a0d iana portlist updated.
git-svn-id: file:///svn/unbound/trunk@1108 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-04 10:44:20 +00:00
Wouter Wijngaards 065d2ad96f newer libtool contents.
git-svn-id: file:///svn/unbound/trunk@1107 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-04 10:37:08 +00:00
Wouter Wijngaards d7f2306161 fixup localzone nodefault issue, the trailing dot was used in comparisons.
git-svn-id: file:///svn/unbound/trunk@1106 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-03 12:32:08 +00:00
Wouter Wijngaards 66c8bd4ad1 ldns 1.3.0 release as tarball included with unbound.
git-svn-id: file:///svn/unbound/trunk@1105 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-02 13:27:44 +00:00
Wouter Wijngaards 725929734e bug184 fixed.
git-svn-id: file:///svn/unbound/trunk@1104 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-02 13:14:12 +00:00
Wouter Wijngaards 60f51c1197 ldns tarball updated.
bug 185 fixed.


git-svn-id: file:///svn/unbound/trunk@1103 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-02 12:12:13 +00:00
Wouter Wijngaards 85abd17e90 bug 177 fix.
git-svn-id: file:///svn/unbound/trunk@1102 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-06-02 10:30:16 +00:00
Jelte Jansen ef69508048 fix for bug 180
git-svn-id: file:///svn/unbound/trunk@1101 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-28 14:29:29 +00:00
Jelte Jansen 97854e6bc5 fix from bug 178, thanks for noticing, Joerg
git-svn-id: file:///svn/unbound/trunk@1100 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-27 07:41:50 +00:00
Wouter Wijngaards 01af814844 gmtime_r threadsafe.
git-svn-id: file:///svn/unbound/trunk@1099 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-23 15:43:55 +00:00
Wouter Wijngaards 6de373e04c typo fix.
git-svn-id: file:///svn/unbound/trunk@1098 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-23 14:22:11 +00:00
Wouter Wijngaards 4a6d702edf - mingw32 porting.
- test for sys/wait.h
          - WSAEWOULDBLOCK test after nonblocking TCP connect.
          - write_iov_buffer removed: unused and no struct iov on windows.
          - signed/unsigned warning fixup mini_event.
          - use ioctlsocket to set nonblocking I/O if fnctl is unavailable.
          - skip signals that are not defined
          - detect pwd.h.
          - detect getpwnam, getrlimit, setsid, sbrk, chroot.
          - default config has no chroot if chroot() unavailable.
          - if no kill() then no pidfile is read or written.
          - gmtime_r is replaced by nonthreadsafe alternative if unavail.
            used in rrsig time validation errors.


git-svn-id: file:///svn/unbound/trunk@1097 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-23 14:13:07 +00:00
Wouter Wijngaards 0bad5716d4 TODO items from suggestions by Jean-Jacques Sarton.
git-svn-id: file:///svn/unbound/trunk@1096 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-23 10:43:16 +00:00
Wouter Wijngaards 55fe583de8 comment update
git-svn-id: file:///svn/unbound/trunk@1095 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-23 07:15:55 +00:00
Wouter Wijngaards 55aefcad19 fixup
git-svn-id: file:///svn/unbound/trunk@1094 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-22 16:59:59 +00:00
Wouter Wijngaards fa07056f79 mingw port.
relabel replaced functions to avoid conflicts with library.

git-svn-id: file:///svn/unbound/trunk@1093 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-22 13:30:22 +00:00
Wouter Wijngaards 5990dde29b check removed.
git-svn-id: file:///svn/unbound/trunk@1092 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-22 10:46:57 +00:00
Wouter Wijngaards f9074eb440 no lexer warnings.
git-svn-id: file:///svn/unbound/trunk@1091 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-22 10:41:13 +00:00
Wouter Wijngaards 54318b8c35 Fix bug #175.
git-svn-id: file:///svn/unbound/trunk@1090 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-22 09:00:56 +00:00
Wouter Wijngaards 3bbe7a2e0b rpm spec updated.
git-svn-id: file:///svn/unbound/trunk@1089 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-22 08:34:11 +00:00
Wouter Wijngaards 0f56fd3042 ignore 1.2.2 if installed, use ldns builtin.
git-svn-id: file:///svn/unbound/trunk@1087 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-19 20:23:45 +00:00
Wouter Wijngaards 0d3ecd25df CREDITS fix of history.
git-svn-id: file:///svn/unbound/trunk@1086 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-19 20:12:37 +00:00
Wouter Wijngaards 96d4800692 fedora 9 configure check.
git-svn-id: file:///svn/unbound/trunk@1085 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-19 19:17:32 +00:00
Wouter Wijngaards d13686227c 1.0.0 tag.
git-svn-id: file:///svn/unbound/trunk@1084 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-16 14:42:00 +00:00
Wouter Wijngaards e60174a000 hosts file fixup for MacOSX
git-svn-id: file:///svn/unbound/trunk@1083 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-16 11:35:00 +00:00
Wouter Wijngaards 556b4efb8a - fixup version info for library.
- fixup --disable-rpath more.



git-svn-id: file:///svn/unbound/trunk@1082 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-14 07:34:02 +00:00
Wouter Wijngaards cf3d92a7a7 no unnecessary linking with librt.
git-svn-id: file:///svn/unbound/trunk@1081 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-13 14:01:23 +00:00
Wouter Wijngaards cf19737ee6 1.0.0 version number.
git-svn-id: file:///svn/unbound/trunk@1080 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-13 13:46:24 +00:00
Wouter Wijngaards 3dca36a649 port list update
git-svn-id: file:///svn/unbound/trunk@1079 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-13 13:09:20 +00:00
Wouter Wijngaards aab6da9362 IPv6 servers
TODO items


git-svn-id: file:///svn/unbound/trunk@1078 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-13 12:33:41 +00:00
Wouter Wijngaards 8d472c8cf8 fixup no-ip4 error callback.
git-svn-id: file:///svn/unbound/trunk@1077 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-05-07 07:53:57 +00:00
Wouter Wijngaards baf8056ba5 Fixup, no touch files if not needed, copy when not exists.
git-svn-id: file:///svn/unbound/trunk@1076 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-25 15:47:59 +00:00
Wouter Wijngaards 17631b6fd8 RPM specfile.
git-svn-id: file:///svn/unbound/trunk@1075 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-25 15:23:45 +00:00
Wouter Wijngaards 1b3eb34cd1 DESTDIR is honoured by make install.
git-svn-id: file:///svn/unbound/trunk@1074 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-25 13:28:07 +00:00
Wouter Wijngaards 6d3f7cc4e0 0.11 tag.
git-svn-id: file:///svn/unbound/trunk@1073 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-24 15:23:00 +00:00
Wouter Wijngaards 3f94669a88 document correct default.
git-svn-id: file:///svn/unbound/trunk@1072 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-24 13:38:58 +00:00
Wouter Wijngaards 395f328d4a nicer text.
git-svn-id: file:///svn/unbound/trunk@1071 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-24 13:29:34 +00:00
Wouter Wijngaards 4ba9161e75 Fixup.
git-svn-id: file:///svn/unbound/trunk@1070 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-24 13:03:59 +00:00
Wouter Wijngaards 8638d6c019 test fix.
git-svn-id: file:///svn/unbound/trunk@1069 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-24 13:00:38 +00:00
Wouter Wijngaards 95296a2528 Use logical dir in test.
git-svn-id: file:///svn/unbound/trunk@1068 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-24 12:49:22 +00:00
Wouter Wijngaards 9dd64e357f chroot more tests and more documentation.
git-svn-id: file:///svn/unbound/trunk@1067 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-24 12:37:01 +00:00
Wouter Wijngaards 8ef2cb4705 port update.
git-svn-id: file:///svn/unbound/trunk@1066 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-23 06:47:48 +00:00
Wouter Wijngaards 9b55215eb6 Parse stats with threads, from Kai.
git-svn-id: file:///svn/unbound/trunk@1065 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-23 06:33:12 +00:00
Wouter Wijngaards 9f104a42d0 uses TCP internally. faster and better.
git-svn-id: file:///svn/unbound/trunk@1064 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-22 12:22:35 +00:00
Wouter Wijngaards 21e851b0fb test.
git-svn-id: file:///svn/unbound/trunk@1063 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-22 12:09:38 +00:00
Wouter Wijngaards 227ae5b7a4 SIGPIPE ignore.
git-svn-id: file:///svn/unbound/trunk@1062 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-22 10:19:24 +00:00
Wouter Wijngaards 9739014da1 fixup chroot and kill-HUP reread of config file.
git-svn-id: file:///svn/unbound/trunk@1061 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-21 11:34:25 +00:00
Wouter Wijngaards c49eefba59 rfc number.
git-svn-id: file:///svn/unbound/trunk@1060 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-21 09:37:32 +00:00
Wouter Wijngaards c6bbc4ea23 Iana update
git-svn-id: file:///svn/unbound/trunk@1059 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-21 09:22:49 +00:00
Wouter Wijngaards f7d8e3f4bd *
git-svn-id: file:///svn/unbound/trunk@1058 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-21 09:12:25 +00:00
Wouter Wijngaards dd7404f467 FEATURES document.
git-svn-id: file:///svn/unbound/trunk@1057 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-21 09:08:35 +00:00
Wouter Wijngaards 30a1d557bd porting.
git-svn-id: file:///svn/unbound/trunk@1056 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-16 16:09:25 +00:00
Wouter Wijngaards a377c6a9d5 note down idea.
git-svn-id: file:///svn/unbound/trunk@1055 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-16 11:01:25 +00:00
Wouter Wijngaards f47e78c543 clean query returns.
git-svn-id: file:///svn/unbound/trunk@1054 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-16 09:33:24 +00:00
Wouter Wijngaards f9fd2676f9 DSA signature compatibility.
git-svn-id: file:///svn/unbound/trunk@1053 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-15 19:51:28 +00:00
Wouter Wijngaards c858743222 Fixup unbound. Now still a switch DSA(ldns) DSA(bind) ...
git-svn-id: file:///svn/unbound/trunk@1052 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-15 18:01:14 +00:00
Wouter Wijngaards 9ab79dc0dc DSA test
git-svn-id: file:///svn/unbound/trunk@1051 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-15 15:19:25 +00:00
Wouter Wijngaards ffed368bfc TODO item
git-svn-id: file:///svn/unbound/trunk@1050 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-15 13:06:54 +00:00
Wouter Wijngaards 5abd6c8da1 example.conf fixup after Kai Storbeck's suggestion.
git-svn-id: file:///svn/unbound/trunk@1049 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-15 11:15:52 +00:00
Wouter Wijngaards d44b91ec12 solaris FAQ entry.
git-svn-id: file:///svn/unbound/trunk@1048 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-15 09:27:04 +00:00
Wouter Wijngaards 399a165cc3 checkconf better.
git-svn-id: file:///svn/unbound/trunk@1047 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-15 08:22:17 +00:00
Wouter Wijngaards 97ebee32d0 update to be same as ldns.
git-svn-id: file:///svn/unbound/trunk@1046 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-15 08:01:30 +00:00
Wouter Wijngaards 29f4a9ab78 new IANA ports.
git-svn-id: file:///svn/unbound/trunk@1045 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-15 07:45:46 +00:00
Wouter Wijngaards b6a93eae31 pidfile location.
git-svn-id: file:///svn/unbound/trunk@1044 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-15 07:37:25 +00:00
Wouter Wijngaards 3fced109b9 Check sig type for DSA.
git-svn-id: file:///svn/unbound/trunk@1043 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-14 15:57:52 +00:00
Wouter Wijngaards 77e7e73a32 Jelte found DSA sig solution, copied from ldns to fit into unbound validator.
git-svn-id: file:///svn/unbound/trunk@1042 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-14 15:34:09 +00:00
Wouter Wijngaards adb8eda081 linux lexer.
git-svn-id: file:///svn/unbound/trunk@1041 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-14 15:01:47 +00:00
Wouter Wijngaards 0cc33e29e7 please doxygen
git-svn-id: file:///svn/unbound/trunk@1040 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-14 15:01:11 +00:00
Wouter Wijngaards 9e9d7ba0a7 fixup test for new checkconf.
git-svn-id: file:///svn/unbound/trunk@1039 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-14 14:58:01 +00:00
Wouter Wijngaards 74530fdb64 fixup test for user name.
git-svn-id: file:///svn/unbound/trunk@1038 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-14 14:50:46 +00:00
Wouter Wijngaards 2f7bd77250 0x20 document, checkconf fix.
git-svn-id: file:///svn/unbound/trunk@1037 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-14 14:48:17 +00:00
Wouter Wijngaards dccc665658 fixup ID collisions in test.
git-svn-id: file:///svn/unbound/trunk@1036 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-14 11:07:11 +00:00
Wouter Wijngaards 2139a8572c and dotests.sh (svn:NO TEST)
git-svn-id: file:///svn/unbound/trunk@1035 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-14 08:52:30 +00:00
Wouter Wijngaards e65070ce6f tests for udp wait list.
git-svn-id: file:///svn/unbound/trunk@1034 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-14 08:51:09 +00:00
Wouter Wijngaards b9bf0872c2 update to stat script in contrib.
git-svn-id: file:///svn/unbound/trunk@1033 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-14 07:15:25 +00:00
Wouter Wijngaards 2904445bd2 Fixup.
git-svn-id: file:///svn/unbound/trunk@1032 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-11 16:05:55 +00:00
Wouter Wijngaards f17580e460 fixup tests for config change.
git-svn-id: file:///svn/unbound/trunk@1031 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-11 14:41:30 +00:00
Wouter Wijngaards 0f80e5e78a - removed base_port.
- created 256-port ephemeral space for the OS, 59802 available.


git-svn-id: file:///svn/unbound/trunk@1030 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-11 14:10:16 +00:00
Wouter Wijngaards a8bf62f962 - random port selection out of the configged ports.
- fixup threadsafety for libevent-1.4.3+ (event_base_get_method).



git-svn-id: file:///svn/unbound/trunk@1029 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-11 13:24:49 +00:00
Wouter Wijngaards 234defa371 iana ports automated.
git-svn-id: file:///svn/unbound/trunk@1028 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-10 10:52:22 +00:00
Wouter Wijngaards 20ee8c10f5 log file stats parse perl script from Kai Storbeck.
git-svn-id: file:///svn/unbound/trunk@1027 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-10 10:18:44 +00:00
Wouter Wijngaards 06f41d9d84 work with latest libevent trunk.
git-svn-id: file:///svn/unbound/trunk@1026 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-10 08:16:26 +00:00
Wouter Wijngaards f0cf79146c config available ports, iana assigned ports list.
git-svn-id: file:///svn/unbound/trunk@1025 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-09 15:07:37 +00:00
Wouter Wijngaards 7eeb7cc78c statistics cumulative option.
git-svn-id: file:///svn/unbound/trunk@1024 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-09 12:29:53 +00:00
Wouter Wijngaards 46e703c989 libev can be used (but not multithreaded) and del fd unused.
git-svn-id: file:///svn/unbound/trunk@1023 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-09 11:58:53 +00:00
Wouter Wijngaards d26b183ba6 - unbound tries to set the ulimit fds when started as server.
if that does not work, it will scale back its requirements.


git-svn-id: file:///svn/unbound/trunk@1022 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-04-08 15:02:52 +00:00
Wouter Wijngaards ff8c2ed1bc FAQ entry.
git-svn-id: file:///svn/unbound/trunk@1021 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-03-27 10:01:38 +00:00
Wouter Wijngaards 8359474330 AD bit like in dnssec-updates draft from last DNSEXT meeting.
git-svn-id: file:///svn/unbound/trunk@1020 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-03-26 08:31:15 +00:00
Wouter Wijngaards 64627b1a63 RTT banding, more spoof resistance randomness.
git-svn-id: file:///svn/unbound/trunk@1019 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-03-25 15:33:24 +00:00
Wouter Wijngaards 87700fea40 Enforce presence of query section in reply.
git-svn-id: file:///svn/unbound/trunk@1018 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-03-25 14:03:31 +00:00
Wouter Wijngaards bbe801da93 harvest CNAME.
git-svn-id: file:///svn/unbound/trunk@1017 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-03-07 10:38:24 +00:00
Wouter Wijngaards f35ae11ff4 harvest opt.
git-svn-id: file:///svn/unbound/trunk@1016 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-03-07 10:16:09 +00:00
Wouter Wijngaards 677d67c29c Patch from Koji, thanks!
git-svn-id: file:///svn/unbound/trunk@1015 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-03-05 14:54:51 +00:00
Wouter Wijngaards 6adf9e1459 Default config file location.
git-svn-id: file:///svn/unbound/trunk@1014 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-03-04 14:25:53 +00:00
Wouter Wijngaards 85af59c734 Fixup trust for CNAME chains. (and also DNAME).
git-svn-id: file:///svn/unbound/trunk@1013 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-03-04 11:00:49 +00:00
Wouter Wijngaards 30478d3e17 nicer indentation.
git-svn-id: file:///svn/unbound/trunk@1012 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-03-03 10:28:12 +00:00
Wouter Wijngaards 288f022dd6 tag 0.10, version upped to 0.11 in trunk.
git-svn-id: file:///svn/unbound/trunk@1011 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-03-03 10:03:38 +00:00
Wouter Wijngaards 8a359e134b tarball update.
git-svn-id: file:///svn/unbound/trunk@1010 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-29 13:23:44 +00:00
Wouter Wijngaards c9447139c8 more portable compilation inside.
git-svn-id: file:///svn/unbound/trunk@1009 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-29 11:44:23 +00:00
Wouter Wijngaards 822422cbfb confixlexer and parser from linux are a little more portable (despite the
signed/unsigned comparison warning).


git-svn-id: file:///svn/unbound/trunk@1008 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-29 10:59:26 +00:00
Wouter Wijngaards 34da89510c Note about dependencies.
git-svn-id: file:///svn/unbound/trunk@1007 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-29 10:35:05 +00:00
Wouter Wijngaards c5ef04b7b4 lexer and parser from freebsd.
git-svn-id: file:///svn/unbound/trunk@1006 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-29 10:23:52 +00:00
Wouter Wijngaards 372b4a1c12 portability.
git-svn-id: file:///svn/unbound/trunk@1005 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-29 10:22:07 +00:00
Wouter Wijngaards 3e103c2983 doc nicer.
git-svn-id: file:///svn/unbound/trunk@1004 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-29 09:28:55 +00:00
Wouter Wijngaards 6b51790054 installed to sbin.
git-svn-id: file:///svn/unbound/trunk@1003 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-28 19:44:11 +00:00
Wouter Wijngaards 9be7d20ac6 harvest print output.
git-svn-id: file:///svn/unbound/trunk@1002 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-28 16:19:20 +00:00
Wouter Wijngaards d0da5bc14c install to sbin
git-svn-id: file:///svn/unbound/trunk@1001 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-28 13:50:34 +00:00
Wouter Wijngaards 28dfc5fc39 harvest takes input.
git-svn-id: file:///svn/unbound/trunk@1000 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-28 13:07:03 +00:00
Wouter Wijngaards bc6617cf11 lint for libunbound.
git-svn-id: file:///svn/unbound/trunk@999 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-28 12:36:50 +00:00
Wouter Wijngaards 2b95664a66 + - fixed memory leaks in libunbound (during cancellation and wait).
+       - libunbound returns the answer packet in full.
+       - snprintf compat update.
+       - harvest performs lookup.
+       - ldns-tarball update with fix for ldns_dname_label.



git-svn-id: file:///svn/unbound/trunk@998 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-28 12:29:00 +00:00
Wouter Wijngaards acb8698a3c please lin.
git-svn-id: file:///svn/unbound/trunk@997 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-27 15:12:36 +00:00
Wouter Wijngaards 7a8fa9e3de harvest
git-svn-id: file:///svn/unbound/trunk@996 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-27 15:03:25 +00:00
Wouter Wijngaards d90c162edf config file option for draft-0x20.
git-svn-id: file:///svn/unbound/trunk@995 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-27 09:39:27 +00:00
Wouter Wijngaards 130a5f2dee can use DNS-0x20 draft casing.
git-svn-id: file:///svn/unbound/trunk@994 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-27 09:21:31 +00:00
Wouter Wijngaards 39b2a21a81 Answers use same case as query does.
git-svn-id: file:///svn/unbound/trunk@993 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-26 20:45:20 +00:00
Wouter Wijngaards c00d1e02cd fixup test for nc version differences.
git-svn-id: file:///svn/unbound/trunk@992 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-26 14:25:36 +00:00
Wouter Wijngaards c2390d030d verbosity uit.
git-svn-id: file:///svn/unbound/trunk@991 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-26 14:04:02 +00:00
Wouter Wijngaards 5979bc061f delayer in TCP.
git-svn-id: file:///svn/unbound/trunk@990 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-26 13:04:05 +00:00
Wouter Wijngaards 1dc9abfb79 Delayer util.
git-svn-id: file:///svn/unbound/trunk@989 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-25 15:35:23 +00:00
Wouter Wijngaards 9071852837 delay test program.
git-svn-id: file:///svn/unbound/trunk@988 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-22 15:40:50 +00:00
Wouter Wijngaards 2f4be547bd Notes.
git-svn-id: file:///svn/unbound/trunk@987 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-22 14:27:09 +00:00
Wouter Wijngaards cc8dfa660d counting speedup.
git-svn-id: file:///svn/unbound/trunk@986 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-22 14:03:49 +00:00
Wouter Wijngaards 99dfad38b2 faster message parse.
git-svn-id: file:///svn/unbound/trunk@985 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-22 12:54:14 +00:00
Wouter Wijngaards fa368eff78 simpler ptr loop check.
git-svn-id: file:///svn/unbound/trunk@984 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-22 11:19:21 +00:00
Wouter Wijngaards fb1bdb8ee0 default to faster internal event loop.
git-svn-id: file:///svn/unbound/trunk@983 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-22 10:19:49 +00:00
Wouter Wijngaards 9c0b217980 TODO remove optimizations that won't help.
git-svn-id: file:///svn/unbound/trunk@982 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-22 09:58:23 +00:00
Wouter Wijngaards bc7d3dc192 avoid reencoding the same reply in mesh reply.
git-svn-id: file:///svn/unbound/trunk@981 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-22 09:23:42 +00:00
Wouter Wijngaards 104a7fb3ea couple percent shaved off in compress_tree_lookup and dname_lab_cmp.
git-svn-id: file:///svn/unbound/trunk@980 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-21 15:25:22 +00:00
Jelte Jansen 6591aab69f right dir?
git-svn-id: file:///svn/unbound/trunk@979 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-21 11:08:23 +00:00
Wouter Wijngaards 49fd904db2 speed up message encoding.
git-svn-id: file:///svn/unbound/trunk@976 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-21 10:25:49 +00:00
Wouter Wijngaards 57511c1114 encoding speed test.
git-svn-id: file:///svn/unbound/trunk@975 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-20 15:35:49 +00:00
Wouter Wijngaards bb1bf0505e test fix for NSEC3 new algorithms.
git-svn-id: file:///svn/unbound/trunk@974 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-20 14:20:27 +00:00
Wouter Wijngaards 0253676384 better time printout.
git-svn-id: file:///svn/unbound/trunk@973 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-20 07:28:33 +00:00
Wouter Wijngaards 0627d1a43e do-daemonize
git-svn-id: file:///svn/unbound/trunk@972 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-20 07:26:03 +00:00
Wouter Wijngaards f3cfe6ed9c - setup speec_cache for need-ldns-testns in dotests.
- check number of queued replies on incoming queries to avoid overload
         on that account.
       - fptr whitelist checks are not disabled in optimize mode.



git-svn-id: file:///svn/unbound/trunk@971 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-20 07:18:42 +00:00
Wouter Wijngaards b018f6d9f7 better text.
git-svn-id: file:///svn/unbound/trunk@970 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-19 16:25:00 +00:00
Wouter Wijngaards 7b8218b2a2 race cond found in test.
git-svn-id: file:///svn/unbound/trunk@969 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-19 15:49:22 +00:00
Wouter Wijngaards 1b403f6ee1 UDP per select speedup.
git-svn-id: file:///svn/unbound/trunk@968 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-19 14:35:40 +00:00
Wouter Wijngaards 8a7bb2c4f6 nsec3 type codes.
git-svn-id: file:///svn/unbound/trunk@967 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-19 13:58:20 +00:00
Wouter Wijngaards b2710818d4 Faster due to time-sharing.
git-svn-id: file:///svn/unbound/trunk@966 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-19 13:12:23 +00:00
Wouter Wijngaards 0866b8e60b donotq localhost default back on yes.
git-svn-id: file:///svn/unbound/trunk@965 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-19 09:12:35 +00:00
Wouter Wijngaards 8b3c553f23 And man page too.
git-svn-id: file:///svn/unbound/trunk@964 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-19 08:11:38 +00:00
Wouter Wijngaards db6178e670 profiling speedups.
git-svn-id: file:///svn/unbound/trunk@963 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-18 15:45:14 +00:00
Wouter Wijngaards dd7ffb54ee nicer code.
git-svn-id: file:///svn/unbound/trunk@962 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-18 13:20:14 +00:00
Wouter Wijngaards a0cc6dfc5a Fixed bug in RD flag setting.
perf works better with long taking queries.


git-svn-id: file:///svn/unbound/trunk@961 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-18 13:16:06 +00:00
Wouter Wijngaards ffee03db49 patch from Jan-Piet Mens.
Error checking added.


git-svn-id: file:///svn/unbound/trunk@960 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-18 08:49:11 +00:00
Wouter Wijngaards f3cdeb500c cache speed test.
git-svn-id: file:///svn/unbound/trunk@959 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-15 15:54:30 +00:00
Wouter Wijngaards a345ffccfa fixup --prefix also changes config file default paths.
git-svn-id: file:///svn/unbound/trunk@958 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-15 14:13:09 +00:00
Wouter Wijngaards c9d58a02d7 FreeBSD rc.d script for unbound.
git-svn-id: file:///svn/unbound/trunk@957 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-15 13:43:30 +00:00
Wouter Wijngaards a561a26a80 getoptargorderdifferent
git-svn-id: file:///svn/unbound/trunk@956 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-14 16:36:33 +00:00
Wouter Wijngaards 45e6964a92 fixup make in test.
git-svn-id: file:///svn/unbound/trunk@955 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-14 16:21:22 +00:00
Wouter Wijngaards 94bf5d116f perf test.
git-svn-id: file:///svn/unbound/trunk@954 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-14 16:16:39 +00:00
Wouter Wijngaards 94f8dd838c start without a config file (all default settings).
git-svn-id: file:///svn/unbound/trunk@953 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-14 10:37:32 +00:00
Wouter Wijngaards ed224e1d64 empty line fixup.
git-svn-id: file:///svn/unbound/trunk@952 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-13 15:26:09 +00:00
Wouter Wijngaards 00165cbe65 perf tool work.
git-svn-id: file:///svn/unbound/trunk@951 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-13 15:19:50 +00:00
Wouter Wijngaards 06890aaf8e print version.
git-svn-id: file:///svn/unbound/trunk@950 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-13 13:24:41 +00:00
Wouter Wijngaards 954a73f8c6 Fixup recursion.
git-svn-id: file:///svn/unbound/trunk@948 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-12 14:26:19 +00:00
Wouter Wijngaards 5d8fe6ec49 please doc, lint
git-svn-id: file:///svn/unbound/trunk@946 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-11 15:34:11 +00:00
Wouter Wijngaards d7f47f4de6 nice option interface. Nice debug output stream option.
git-svn-id: file:///svn/unbound/trunk@945 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-11 15:22:57 +00:00
Wouter Wijngaards 49d73f5f56 etc hosts handling.
git-svn-id: file:///svn/unbound/trunk@944 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-11 10:27:37 +00:00
Wouter Wijngaards 1dd130be61 stats output text nice.
git-svn-id: file:///svn/unbound/trunk@943 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-11 09:19:32 +00:00
Wouter Wijngaards 58c34b2dda ub_
git-svn-id: file:///svn/unbound/trunk@942 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-11 08:52:14 +00:00
Wouter Wijngaards 8bde1c7cb3 fixes.
git-svn-id: file:///svn/unbound/trunk@941 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-08 13:27:49 +00:00
Wouter Wijngaards 0dcf1d71dc tag 0.9
git-svn-id: file:///svn/unbound/trunk@937 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-08 12:27:41 +00:00
Wouter Wijngaards 09e18ffdbb fixup validator classification of root referrals.
git-svn-id: file:///svn/unbound/trunk@936 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-08 12:24:01 +00:00
203 changed files with 21888 additions and 4182 deletions
+80 -47
View File
@@ -22,6 +22,7 @@ srcdir=@srcdir@
prefix=@prefix@
exec_prefix=@exec_prefix@
bindir=@bindir@
sbindir=@sbindir@
mandir=@mandir@
libdir=@libdir@
# datarootdir is here to please some checkers, use datadir.
@@ -33,6 +34,7 @@ libtool=@libtool@
ldnsdir=@ldnsdir@
staticexe=@staticexe@
configfile=@ub_conf_file@
CHECKLOCK_SRC=@CHECKLOCK_SRC@
YACC=@YACC@
LEX=@LEX@
@@ -61,56 +63,63 @@ COMMON_SRC=$(patsubst $(srcdir)/%,%, $(wildcard $(srcdir)/services/*.c \
$(srcdir)/services/cache/*.c $(srcdir)/util/*.c \
$(srcdir)/util/data/*.c $(srcdir)/util/storage/*.c \
$(srcdir)/iterator/*.c $(srcdir)/validator/*.c)) \
util/configparser.c util/configlexer.c testcode/checklocks.c
COMMON_OBJ=$(addprefix $(BUILD),$(COMMON_SRC:.c=.o))
COMPAT_OBJ=$(addprefix $(BUILD)compat/,$(LIBOBJS))
util/configparser.c util/configlexer.c $(CHECKLOCK_SRC)
COMMON_OBJ=$(addprefix $(BUILD),$(COMMON_SRC:.c=.lo))
COMPAT_OBJ=$(addprefix $(BUILD)compat/,$(LIBOBJS:.o=.lo))
UNITTEST_SRC=$(patsubst $(srcdir)/%,%, \
$(wildcard $(srcdir)/testcode/unit*.c)) \
testcode/readhex.c testcode/ldns-testpkts.c smallapp/worker_cb.c \
$(COMMON_SRC)
UNITTEST_OBJ=$(addprefix $(BUILD),$(UNITTEST_SRC:.c=.o)) $(COMPAT_OBJ)
UNITTEST_OBJ=$(addprefix $(BUILD),$(UNITTEST_SRC:.c=.lo)) $(COMPAT_OBJ)
DAEMON_SRC=$(patsubst $(srcdir)/%,%, $(wildcard $(srcdir)/daemon/*.c)) \
$(COMMON_SRC)
DAEMON_OBJ=$(addprefix $(BUILD),$(DAEMON_SRC:.c=.o)) $(COMPAT_OBJ)
DAEMON_OBJ=$(addprefix $(BUILD),$(DAEMON_SRC:.c=.lo)) $(COMPAT_OBJ)
CHECKCONF_SRC=smallapp/unbound-checkconf.c smallapp/worker_cb.c $(COMMON_SRC)
CHECKCONF_OBJ=$(addprefix $(BUILD),$(CHECKCONF_SRC:.c=.o)) $(COMPAT_OBJ)
CHECKCONF_OBJ=$(addprefix $(BUILD),$(CHECKCONF_SRC:.c=.lo)) $(COMPAT_OBJ)
HOST_SRC=smallapp/unbound-host.c
HOST_OBJ=$(addprefix $(BUILD),$(HOST_SRC:.c=.o)) $(COMPAT_OBJ)
HOST_OBJ=$(addprefix $(BUILD),$(HOST_SRC:.c=.lo)) $(COMPAT_OBJ)
TESTBOUND_SRC=testcode/testbound.c testcode/ldns-testpkts.c \
daemon/worker.c daemon/acl_list.c daemon/daemon.c daemon/stats.c \
testcode/replay.c testcode/fake_event.c $(filter-out util/netevent.c \
services/listen_dnsport.c services/outside_network.c, $(COMMON_SRC))
TESTBOUND_OBJ=$(addprefix $(BUILD),$(TESTBOUND_SRC:.c=.o)) $(COMPAT_OBJ)
TESTBOUND_OBJ=$(addprefix $(BUILD),$(TESTBOUND_SRC:.c=.lo)) $(COMPAT_OBJ)
LOCKVERIFY_SRC=testcode/lock_verify.c smallapp/worker_cb.c $(COMMON_SRC)
LOCKVERIFY_OBJ=$(addprefix $(BUILD),$(LOCKVERIFY_SRC:.c=.o)) $(COMPAT_OBJ)
LOCKVERIFY_OBJ=$(addprefix $(BUILD),$(LOCKVERIFY_SRC:.c=.lo)) $(COMPAT_OBJ)
PKTVIEW_SRC=testcode/pktview.c testcode/readhex.c smallapp/worker_cb.c \
$(COMMON_SRC)
PKTVIEW_OBJ=$(addprefix $(BUILD),$(PKTVIEW_SRC:.c=.o)) $(COMPAT_OBJ)
PKTVIEW_OBJ=$(addprefix $(BUILD),$(PKTVIEW_SRC:.c=.lo)) $(COMPAT_OBJ)
SIGNIT_SRC=testcode/signit.c smallapp/worker_cb.c $(COMMON_SRC)
SIGNIT_OBJ=$(addprefix $(BUILD),$(SIGNIT_SRC:.c=.o)) $(COMPAT_OBJ)
SIGNIT_OBJ=$(addprefix $(BUILD),$(SIGNIT_SRC:.c=.lo)) $(COMPAT_OBJ)
MEMSTATS_SRC=testcode/memstats.c smallapp/worker_cb.c $(COMMON_SRC)
MEMSTATS_OBJ=$(addprefix $(BUILD),$(MEMSTATS_SRC:.c=.o)) $(COMPAT_OBJ)
MEMSTATS_OBJ=$(addprefix $(BUILD),$(MEMSTATS_SRC:.c=.lo)) $(COMPAT_OBJ)
ASYNCLOOK_SRC=testcode/asynclook.c
ASYNCLOOK_OBJ=$(addprefix $(BUILD),$(ASYNCLOOK_SRC:.c=.o)) $(COMPAT_OBJ)
ASYNCLOOK_OBJ=$(addprefix $(BUILD),$(ASYNCLOOK_SRC:.c=.lo)) $(COMPAT_OBJ)
STREAMTCP_SRC=testcode/streamtcp.c smallapp/worker_cb.c $(COMMON_SRC)
STREAMTCP_OBJ=$(addprefix $(BUILD),$(STREAMTCP_SRC:.c=.o)) $(COMPAT_OBJ)
STREAMTCP_OBJ=$(addprefix $(BUILD),$(STREAMTCP_SRC:.c=.lo)) $(COMPAT_OBJ)
PERF_SRC=testcode/perf.c smallapp/worker_cb.c $(COMMON_SRC)
PERF_OBJ=$(addprefix $(BUILD),$(PERF_SRC:.c=.lo)) $(COMPAT_OBJ)
DELAYER_SRC=testcode/delayer.c smallapp/worker_cb.c $(COMMON_SRC)
DELAYER_OBJ=$(addprefix $(BUILD),$(DELAYER_SRC:.c=.lo)) $(COMPAT_OBJ)
HARVEST_SRC=testcode/harvest.c
HARVEST_OBJ=$(addprefix $(BUILD),$(HARVEST_SRC:.c=.lo)) $(COMPAT_OBJ)
LIBUNBOUND_SRC=$(patsubst $(srcdir)/%,%, \
$(wildcard $(srcdir)/libunbound/*.c) $(COMMON_SRC))
LIBUNBOUND_OBJ=$(addprefix $(BUILD),$(LIBUNBOUND_SRC:.c=.o)) $(COMPAT_OBJ)
LIBUNBOUND_OBJ=$(addprefix $(BUILD),$(LIBUNBOUND_SRC:.c=.lo)) $(COMPAT_OBJ)
ALL_SRC=$(sort $(COMMON_SRC) $(UNITTEST_SRC) $(DAEMON_SRC) \
$(TESTBOUND_SRC) $(LOCKVERIFY_SRC) $(PKTVIEW_SRC) $(SIGNIT_SRC) \
$(MEMSTATS_SRC) $(CHECKCONF_SRC) $(LIBUNBOUND_SRC) $(HOST_SRC) \
$(ASYNCLOOK_SRC) $(STREAMTCP_SRC))
ALL_OBJ=$(addprefix $(BUILD),$(ALL_SRC:.c=.o) \
$(addprefix compat/,$(LIBOBJS))) $(COMPAT_OBJ)
$(ASYNCLOOK_SRC) $(STREAMTCP_SRC) $(PERF_SRC) $(DELAYER_SRC) \
$(HARVEST_SRC) )
ALL_OBJ=$(addprefix $(BUILD),$(ALL_SRC:.c=.lo) \
$(addprefix compat/,$(LIBOBJS:.o=.lo))) $(COMPAT_OBJ)
COMPILE=$(LIBTOOL) --tag=CC --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS)
LINK=$(LIBTOOL) --tag=CC --mode=link $(CC) $(staticexe) $(RUNTIME_PATH) $(CFLAGS) $(LDFLAGS)
LINK_LIB=$(LIBTOOL) --tag=CC --mode=link $(CC) $(RUNTIME_PATH) $(CFLAGS) $(LDFLAGS) $(staticexe) -release $(VERSION) -no-undefined
LINK_LIB=$(LIBTOOL) --tag=CC --mode=link $(CC) $(RUNTIME_PATH) $(CFLAGS) $(LDFLAGS) $(staticexe) -version-number @LIBUNBOUND_CURRENT@:@LIBUNBOUND_REVISION@:@LIBUNBOUND_AGE@ -no-undefined
.PHONY: clean realclean doc lint all install uninstall tests test download_ldns strip lib
$(BUILD)%.o: $(srcdir)/%.c
$(BUILD)%.lo: $(srcdir)/%.c
$(INFO) Build $<
@if test ! -z "$(ldnsdir)" -a ! -e $(ldnsdir)/include/ldns/ldns.h; \
then (cd $(ldnsdir); $(MAKE) copy-headers); fi
@@ -120,16 +129,16 @@ $(BUILD)%.o: $(srcdir)/%.c
all: $(COMMON_OBJ) unbound unbound-checkconf lib unbound-host
tests: all unittest testbound lock-verify pktview signit memstats \
asynclook streamtcp
asynclook streamtcp perf delayer harvest
test: tests
bash testcode/do-tests.sh
if test -x "`which bash`"; then bash testcode/do-tests.sh; else sh testcode/do-tests.sh; fi
lib: libunbound.la
libunbound.la: $(LIBUNBOUND_OBJ)
$(INFO) Link $@
$Q$(LINK_LIB) --export-symbols $(srcdir)/libunbound/ubsyms.def -o $@ $(sort $(LIBUNBOUND_OBJ:.o=.lo)) -rpath $(libdir) $(LIBS)
$Q$(LINK_LIB) --export-symbols $(srcdir)/libunbound/ubsyms.def -o $@ $(sort $(LIBUNBOUND_OBJ)) -rpath $(libdir) $(LIBS)
ifeq ($(patsubst ldns-src%,ldns-src,$(ldnsdir)),ldns-src)
ldnslib=$(ldnsdir)/lib/libldns.a
@@ -184,6 +193,18 @@ streamtcp: $(STREAMTCP_OBJ) $(ldnslib)
$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(STREAMTCP_OBJ)) $(LIBS)
perf: $(PERF_OBJ) $(ldnslib)
$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(PERF_OBJ)) $(LIBS)
delayer: $(DELAYER_OBJ) $(ldnslib)
$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(DELAYER_OBJ)) $(LIBS)
harvest: $(HARVEST_OBJ) $(ldnslib) libunbound.la
$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(HARVEST_OBJ)) $(LIBS) -L. -L.libs -lunbound
#testcode/ldns-testpkts.c: $(ldnsdir)/examples/ldns-testpkts.c \
# $(ldnsdir)/examples/ldns-testpkts.h
# cp $(ldnsdir)/examples/ldns-testpkts.c testcode/ldns-testpkts.c
@@ -207,6 +228,7 @@ util/configparser.c util/configparser.h: $(srcdir)/util/configparser.y
clean:
rm -f *.o *.d *.lo *~ tags
rm -f unbound unbound-checkconf unbound-host
rm -rf autom4te.cache .libs build doc/html
realclean: clean
@@ -237,37 +259,48 @@ strip:
strip unbound-host
install:
$(INSTALL) -m 755 -d $(bindir)
$(INSTALL) -m 755 -d $(mandir)
$(INSTALL) -m 755 -d $(mandir)/man8
$(INSTALL) -m 755 -d $(mandir)/man5
$(INSTALL) -m 755 -d $(libdir)
$(INSTALL) -m 755 -d $(includedir)
$(LIBTOOL) --mode=install cp unbound $(bindir)/unbound
$(LIBTOOL) --mode=install cp unbound-checkconf $(bindir)/unbound-checkconf
$(LIBTOOL) --mode=install cp unbound-host $(bindir)/unbound-host
$(INSTALL) -c -m 644 $(srcdir)/doc/unbound.8 $(mandir)/man8
$(INSTALL) -c -m 644 $(srcdir)/doc/unbound-checkconf.8 $(mandir)/man8
$(INSTALL) -c -m 644 $(srcdir)/doc/unbound.conf.5 $(mandir)/man5
if test ! -e $(configfile); then $(INSTALL) -d `dirname $(configfile)`; $(INSTALL) -c -m 644 $(srcdir)/doc/example.conf $(configfile); fi
$(LIBTOOL) --mode=install cp $(srcdir)/libunbound/unbound.h $(includedir)/unbound.h
$(LIBTOOL) --mode=install cp libunbound.la $(libdir)
$(LIBTOOL) --mode=finish $(libdir)
$(INSTALL) -m 755 -d $(DESTDIR)$(sbindir)
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man8
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man5
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man3
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1
$(INSTALL) -m 755 -d $(DESTDIR)$(libdir)
$(INSTALL) -m 755 -d $(DESTDIR)$(includedir)
$(LIBTOOL) --mode=install cp unbound $(DESTDIR)$(sbindir)/unbound
$(LIBTOOL) --mode=install cp unbound-checkconf $(DESTDIR)$(sbindir)/unbound-checkconf
$(LIBTOOL) --mode=install cp unbound-host $(DESTDIR)$(sbindir)/unbound-host
$(INSTALL) -c -m 644 doc/unbound.8 $(DESTDIR)$(mandir)/man8
$(INSTALL) -c -m 644 doc/unbound-checkconf.8 $(DESTDIR)$(mandir)/man8
$(INSTALL) -c -m 644 doc/unbound.conf.5 $(DESTDIR)$(mandir)/man5
$(INSTALL) -c -m 644 $(srcdir)/doc/unbound-host.1 $(DESTDIR)$(mandir)/man1
$(INSTALL) -c -m 644 doc/libunbound.3 $(DESTDIR)$(mandir)/man3
if test ! -e $(DESTDIR)$(configfile); then $(INSTALL) -d `dirname $(DESTDIR)$(configfile)`; $(INSTALL) -c -m 644 doc/example.conf $(DESTDIR)$(configfile); fi
$(LIBTOOL) --mode=install cp $(srcdir)/libunbound/unbound.h $(DESTDIR)$(includedir)/unbound.h
$(LIBTOOL) --mode=install cp libunbound.la $(DESTDIR)$(libdir)
$(LIBTOOL) --mode=finish $(DESTDIR)$(libdir)
uninstall:
rm -f -- $(bindir)/unbound $(bindir)/unbound-checkconf $(bindir)/unbound-host
rm -f -- $(mandir)/man8/unbound.8 $(mandir)/man8/unbound-checkconf.8 $(mandir)/man5/unbound.conf.5
rm -f -- $(includedir)/unbound.h
$(LIBTOOL) --mode=uninstall rm -f $(libdir)/libunbound.la
rm -f -- $(DESTDIR)$(sbindir)/unbound $(DESTDIR)$(sbindir)/unbound-checkconf $(DESTDIR)$(sbindir)/unbound-host
rm -f -- $(DESTDIR)$(mandir)/man8/unbound.8 $(DESTDIR)$(mandir)/man8/unbound-checkconf.8 $(DESTDIR)$(mandir)/man5/unbound.conf.5
rm -f -- $(DESTDIR)$(mandir)/man1/unbound-host.1 $(DESTDIR)$(mandir)/man3/libunbound.3
rm -f -- $(DESTDIR)$(includedir)/unbound.h
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/libunbound.la
@echo
@echo "You still need to remove `dirname $(configfile)` , $(configfile) by hand"
@echo "You still need to remove "`dirname $(DESTDIR)$(configfile)`" , $(DESTDIR)$(configfile) by hand"
download_ldns:
svn export https://www.nlnetlabs.nl/ldns/svn/trunk/makedist.sh ldns_makedist.sh
./ldns_makedist.sh -s -d https://www.nlnetlabs.nl/ldns/svn/trunk
svn export https://www.nlnetlabs.nl/svn/ldns/trunk/makedist.sh ldns_makedist.sh
./ldns_makedist.sh -s -d https://www.nlnetlabs.nl/svn/ldns/trunk
mv ldns-*_pre_*.tar.gz ldns-src.tar.gz
rm ldns-*_pre_*.tar.gz.sha1 ldns_makedist.sh
iana_update:
curl -o port-numbers.tmp http://www.iana.org/assignments/port-numbers
egrep -v "Unassigned|Reserved" port-numbers.tmp | awk '{ match($$0, "[0-9]+/udp"); if (RLENGTH > 0) print substr($$0, RSTART, RLENGTH - 4) ","}' | sort -nu > portslist.tmp
cat portslist.tmp > util/iana_ports.inc
rm -f port-numbers.tmp portslist.tmp
# Automatic dependencies.
$(BUILD)%.d: $(srcdir)/%.c
$(INFO) Depend $<
@@ -275,7 +308,7 @@ $(BUILD)%.d: $(srcdir)/%.c
then (cd $(ldnsdir); $(MAKE) copy-headers); fi
@-if test ! -d $(dir $@); then $(INSTALL) -d $(patsubst %/,%,$(dir $@)); fi
$Q$(SHELL) -ec '$(CC) -MM $(CPPFLAGS) $(CFLAGS) $< \
| sed '\''s!\(.*\)\.o[ :]*!$(dir $@)\1.o $@ : !g'\'' > $@; \
| sed '\''s!\(.*\)\.o[ :]*!$(dir $@)\1.lo $@ : !g'\'' > $@; \
[ -s $@ ] || rm -f $@'
ifneq ($(MAKECMDGOALS),clean)
+3 -3
View File
@@ -1,9 +1,9 @@
Unbound README
* ./configure && make && make install
* on BSDs and Solaris use gmake (GNU make).
* If it complains that no libevent can be found; libevent is useful when
using many (10000) outgoing ports. By default 16 ports are used and the
builtin alternative is equally capable.
* You can use libevent if you want. libevent is useful when using
many (10000) outgoing ports. By default 16 ports are used and the
builtin alternative is equally capable and a little faster.
* More detailed README, README.svn, README.tests in doc directory
* manual pages can be found in doc directory, and are installed, unbound(8).
* example configuration file doc/example.conf
Vendored
+370 -198
View File
File diff suppressed because it is too large Load Diff
+107
View File
@@ -0,0 +1,107 @@
/*
* Taken from FreeBSD src / lib / libc / stdtime / localtime.c 1.43 revision.
* localtime.c 7.78.
* tzfile.h 1.8
* adapted to be replacement gmtime_r.
*/
#include "config.h"
#ifdef HAVE_TIME_H
#include <time.h>
#endif
#define MONSPERYEAR 12
#define DAYSPERNYEAR 365
#define DAYSPERLYEAR 366
#define SECSPERMIN 60
#define SECSPERHOUR (60*60)
#define SECSPERDAY (24*60*60)
#define DAYSPERWEEK 7
#define TM_SUNDAY 0
#define TM_MONDAY 1
#define TM_TUESDAY 2
#define TM_WEDNESDAY 3
#define TM_THURSDAY 4
#define TM_FRIDAY 5
#define TM_SATURDAY 6
#define TM_YEAR_BASE 1900
#define EPOCH_YEAR 1970
#define EPOCH_WDAY TM_THURSDAY
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
static const int mon_lengths[2][MONSPERYEAR] = {
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};
static const int year_lengths[2] = {
DAYSPERNYEAR, DAYSPERLYEAR
};
static void
timesub(timep, offset, tmp)
const time_t * const timep;
const long offset;
struct tm * const tmp;
{
long days;
long rem;
long y;
int yleap;
const int * ip;
days = *timep / SECSPERDAY;
rem = *timep % SECSPERDAY;
rem += (offset);
while (rem < 0) {
rem += SECSPERDAY;
--days;
}
while (rem >= SECSPERDAY) {
rem -= SECSPERDAY;
++days;
}
tmp->tm_hour = (int) (rem / SECSPERHOUR);
rem = rem % SECSPERHOUR;
tmp->tm_min = (int) (rem / SECSPERMIN);
/*
** A positive leap second requires a special
** representation. This uses "... ??:59:60" et seq.
*/
tmp->tm_sec = (int) (rem % SECSPERMIN) ;
tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
if (tmp->tm_wday < 0)
tmp->tm_wday += DAYSPERWEEK;
y = EPOCH_YEAR;
#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
long newy;
newy = y + days / DAYSPERNYEAR;
if (days < 0)
--newy;
days -= (newy - y) * DAYSPERNYEAR +
LEAPS_THRU_END_OF(newy - 1) -
LEAPS_THRU_END_OF(y - 1);
y = newy;
}
tmp->tm_year = y - TM_YEAR_BASE;
tmp->tm_yday = (int) days;
ip = mon_lengths[yleap];
for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
days = days - (long) ip[tmp->tm_mon];
tmp->tm_mday = (int) (days + 1);
tmp->tm_isdst = 0;
}
/*
* Re-entrant version of gmtime.
*/
struct tm * gmtime_r(const time_t* timep, struct tm *tm)
{
timesub(timep, 0L, tm);
return tm;
}
+4
View File
@@ -56,8 +56,12 @@
#include <sys/types.h>
#include <sys/param.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include <ctype.h>
#if 0
+8
View File
@@ -23,8 +23,12 @@
#include <sys/param.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#include <string.h>
#include <errno.h>
#include <stdio.h>
@@ -62,7 +66,11 @@ inet_ntop(int af, const void *src, char *dst, size_t size)
case AF_INET6:
return (inet_ntop6(src, dst, size));
default:
#ifdef EAFNOSUPPORT
errno = EAFNOSUPPORT;
#else
errno = ENOSYS;
#endif
return (NULL);
}
/* NOTREACHED */
+4
View File
@@ -70,7 +70,11 @@ inet_pton(af, src, dst)
case AF_INET6:
return (inet_pton6(src, dst));
default:
#ifdef EAFNOSUPPORT
errno = EAFNOSUPPORT;
#else
errno = ENOSYS;
#endif
return (-1);
}
/* NOTREACHED */
+5 -5
View File
@@ -528,7 +528,7 @@ static long double abs_val (long double value)
return result;
}
static long double pow10 (int exp)
static long double compat_pow10 (int exp)
{
long double result = 1;
@@ -541,7 +541,7 @@ static long double pow10 (int exp)
return result;
}
static long round (long double value)
static long compat_round (long double value)
{
long intpart;
@@ -602,12 +602,12 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
/* We "cheat" by converting the fractional part to integer by
* multiplying by a factor of 10
*/
fracpart = round ((pow10 (max)) * (ufvalue - intpart));
fracpart = compat_round ((compat_pow10 (max)) * (ufvalue - intpart));
if (fracpart >= pow10 (max))
if (fracpart >= compat_pow10 (max))
{
intpart++;
fracpart -= pow10 (max);
fracpart -= compat_pow10 (max);
}
#ifdef DEBUG_SNPRINTF
+34
View File
@@ -0,0 +1,34 @@
/* socketpair.c - windows mingw32 replacement for socketpair.
* creates a pipe that works like a socketpair a bit
* Taken from libevent-1.4.3.stable WIN32-Code/misc.c
* License: BSD.
*/
#include "config.h"
#include <stdio.h>
#include <windows.h>
int
socketpair(int d, int type, int protocol, int *sv)
{
static int count;
char buf[64];
HANDLE fd;
DWORD dwMode;
(void)d; (void)type; (void)protocol;
sprintf(buf, "\\\\.\\pipe\\levent-%d", count++);
/* Create a duplex pipe which will behave like a socket pair */
fd = CreateNamedPipe(buf, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_NOWAIT,
PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, NULL);
if (fd == INVALID_HANDLE_VALUE)
return (-1);
sv[0] = (int)fd;
fd = CreateFile(buf, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fd == INVALID_HANDLE_VALUE)
return (-1);
dwMode = PIPE_NOWAIT;
SetNamedPipeHandleState(fd, &dwMode, NULL, NULL);
sv[1] = (int)fd;
return (0);
}
+25 -9
View File
@@ -4,7 +4,7 @@
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
# Inc.
timestamp='2006-07-02'
timestamp='2007-05-17'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -161,6 +161,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;;
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
esac
# The Operating System including object format, if it has switched
@@ -329,7 +330,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
i86pc:SunOS:5.*:*)
i86pc:SunOS:5.*:* | ix86xen:SunOS:5.*:*)
echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:6*:*)
@@ -780,7 +781,7 @@ EOF
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
exit ;;
i*:MINGW*:*)
*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
i*:windows32*:*)
@@ -790,12 +791,15 @@ EOF
i*:PW*:*)
echo ${UNAME_MACHINE}-pc-pw32
exit ;;
x86:Interix*:[3456]*)
echo i586-pc-interix${UNAME_RELEASE}
exit ;;
EM64T:Interix*:[3456]*)
echo x86_64-unknown-interix${UNAME_RELEASE}
exit ;;
*:Interix*:[3456]*)
case ${UNAME_MACHINE} in
x86)
echo i586-pc-interix${UNAME_RELEASE}
exit ;;
EM64T | authenticamd)
echo x86_64-unknown-interix${UNAME_RELEASE}
exit ;;
esac ;;
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
echo i${UNAME_MACHINE}-pc-mks
exit ;;
@@ -950,6 +954,9 @@ EOF
x86_64:Linux:*:*)
echo x86_64-unknown-linux-gnu
exit ;;
xtensa:Linux:*:*)
echo xtensa-unknown-linux-gnu
exit ;;
i*86:Linux:*:*)
# The BFD linker knows what the default object file format is, so
# first see if it will tell us. cd to the root directory to prevent
@@ -1208,6 +1215,15 @@ EOF
SX-6:SUPER-UX:*:*)
echo sx6-nec-superux${UNAME_RELEASE}
exit ;;
SX-7:SUPER-UX:*:*)
echo sx7-nec-superux${UNAME_RELEASE}
exit ;;
SX-8:SUPER-UX:*:*)
echo sx8-nec-superux${UNAME_RELEASE}
exit ;;
SX-8R:SUPER-UX:*:*)
echo sx8r-nec-superux${UNAME_RELEASE}
exit ;;
Power*:Rhapsody:*:*)
echo powerpc-apple-rhapsody${UNAME_RELEASE}
exit ;;
+161 -3
View File
@@ -1,5 +1,8 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Directory to chroot to */
#undef CHROOT_DIR
/* Pathname to the Unbound configuration file */
#undef CONFIGFILE
@@ -18,30 +21,51 @@
/* Define to 1 if your system has a working `chown' function. */
#undef HAVE_CHOWN
/* Define to 1 if you have the `chroot' function. */
#undef HAVE_CHROOT
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the `event_base_free' function. */
#undef HAVE_EVENT_BASE_FREE
/* Define to 1 if you have the `event_base_get_method' function. */
#undef HAVE_EVENT_BASE_GET_METHOD
/* Define to 1 if you have the `event_base_once' function. */
#undef HAVE_EVENT_BASE_ONCE
/* Define to 1 if you have the <event.h> header file. */
#undef HAVE_EVENT_H
/* Define to 1 if you have the `fcntl' function. */
#undef HAVE_FCNTL
/* Define to 1 if you have the `fork' function. */
#undef HAVE_FORK
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
#undef HAVE_FSEEKO
/* Define to 1 if you have the `getaddrinfo' function. */
/* Whether getaddrinfo is available */
#undef HAVE_GETADDRINFO
/* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H
/* Define to 1 if you have the `getpwnam' function. */
#undef HAVE_GETPWNAM
/* Define to 1 if you have the `getrlimit' function. */
#undef HAVE_GETRLIMIT
/* Define to 1 if you have the `gmtime_r' function. */
#undef HAVE_GMTIME_R
/* If you have HMAC_CTX_init */
#undef HAVE_HMAC_CTX_INIT
/* Define to 1 if you have the `inet_aton' function. */
#undef HAVE_INET_ATON
@@ -54,8 +78,11 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `crypto' library (-lcrypto). */
#undef HAVE_LIBCRYPTO
/* if the function 'ioctlsocket' is available */
#undef HAVE_IOCTLSOCKET
/* Define to 1 if you have the `kill' function. */
#undef HAVE_KILL
/* Define to 1 if you have the `ldns' library (-lldns). */
#undef HAVE_LIBLDNS
@@ -70,6 +97,9 @@
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
@@ -91,12 +121,42 @@
/* Define to 1 if the system has the type `pthread_spinlock_t'. */
#undef HAVE_PTHREAD_SPINLOCK_T
/* Define to 1 if you have the <pwd.h> header file. */
#undef HAVE_PWD_H
/* Define to 1 if you have the `random' function. */
#undef HAVE_RANDOM
/* Define to 1 if you have the `recvmsg' function. */
#undef HAVE_RECVMSG
/* Define to 1 if you have the `sbrk' function. */
#undef HAVE_SBRK
/* Define to 1 if you have the `sendmsg' function. */
#undef HAVE_SENDMSG
/* Define to 1 if you have the `setsid' function. */
#undef HAVE_SETSID
/* Define to 1 if you have the `sigprocmask' function. */
#undef HAVE_SIGPROCMASK
/* Define to 1 if you have the `sleep' function. */
#undef HAVE_SLEEP
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
/* Define to 1 if you have the `socketpair' function. */
#undef HAVE_SOCKETPAIR
/* Using Solaris threads */
#undef HAVE_SOLARIS_THREADS
/* Define to 1 if you have the `srandom' function. */
#undef HAVE_SRANDOM
/* Define if you have the SSL libraries installed. */
#undef HAVE_SSL
@@ -127,6 +187,9 @@
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define to 1 if you have the <sys/resource.h> header file. */
#undef HAVE_SYS_RESOURCE_H
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
@@ -139,27 +202,54 @@
/* Define to 1 if you have the <sys/uio.h> header file. */
#undef HAVE_SYS_UIO_H
/* Define to 1 if you have the <sys/wait.h> header file. */
#undef HAVE_SYS_WAIT_H
/* Define to 1 if you have the <time.h> header file. */
#undef HAVE_TIME_H
/* Define to 1 if you have the `tzset' function. */
#undef HAVE_TZSET
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `usleep' function. */
#undef HAVE_USLEEP
/* Define to 1 if you have the `vfork' function. */
#undef HAVE_VFORK
/* Define to 1 if you have the <vfork.h> header file. */
#undef HAVE_VFORK_H
/* Define to 1 if you have the <windows.h> header file. */
#undef HAVE_WINDOWS_H
/* Using Windows threads */
#undef HAVE_WINDOWS_THREADS
/* Define to 1 if you have the <winsock2.h> header file. */
#undef HAVE_WINSOCK2_H
/* Define to 1 if `fork' works. */
#undef HAVE_WORKING_FORK
/* Define to 1 if `vfork' works. */
#undef HAVE_WORKING_VFORK
/* Define to 1 if you have the `writev' function. */
#undef HAVE_WRITEV
/* Define to 1 if you have the <ws2tcpip.h> header file. */
#undef HAVE_WS2TCPIP_H
/* Define to the maximum message length to pass to syslog. */
#undef MAXSYSLOGMSGLEN
/* Define if mkdir has one argument. */
#undef MKDIR_HAS_ONE_ARG
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
@@ -175,6 +265,9 @@
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* default pidfile location */
#undef PIDFILE
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
#undef PTHREAD_CREATE_JOINABLE
@@ -182,9 +275,15 @@
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE
/* Directory to chdir to */
#undef RUN_DIR
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* default username */
#undef UB_USERNAME
/* use statistics for allocs and frees, for debug use */
#undef UNBOUND_ALLOC_STATS
@@ -194,6 +293,12 @@
/* Define if you want to use internal select based events */
#undef USE_MINI_EVENT
/* Whether the windows socket API is used */
#undef USE_WINSOCK
/* the version of the windows API enabled */
#undef WINVER
/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
`char[]'. */
#undef YYTEXT_POINTER
@@ -253,6 +358,9 @@
/* Define to `int' if <sys/types.h> does not define. */
#undef pid_t
/* Define to 'int' if not defined */
#undef rlim_t
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t
@@ -324,6 +432,14 @@
#include <arpa/inet.h>
#endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
#ifdef HAVE_WS2TCPIP_H
#include <ws2tcpip.h>
#endif
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
@@ -364,6 +480,10 @@
#define RAND_MAX 2147483647
#endif
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 256
#endif
#ifndef IPV6_MIN_MTU
#define IPV6_MIN_MTU 1280
#endif /* IPV6_MIN_MTU */
@@ -381,30 +501,68 @@
#define MAXINCLUDES 10
#ifndef HAVE_SNPRINTF
#define snprintf snprintf_unbound
#define vsnprintf vsnprintf_unbound
#include <stdarg.h>
int snprintf (char *str, size_t count, const char *fmt, ...);
int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
#endif /* HAVE_SNPRINTF */
#ifndef HAVE_INET_PTON
#define inet_pton inet_pton_unbound
int inet_pton(int af, const char* src, void* dst);
#endif /* HAVE_INET_PTON */
#ifndef HAVE_INET_NTOP
#define inet_ntop inet_ntop_unbound
const char *inet_ntop(int af, const void *src, char *dst, size_t size);
#endif
#ifndef HAVE_INET_ATON
#define inet_aton inet_aton_unbound
int inet_aton(const char *cp, struct in_addr *addr);
#endif
#ifndef HAVE_MEMMOVE
#define memmove memmove_unbound
void *memmove(void *dest, const void *src, size_t n);
#endif
#ifndef HAVE_STRLCPY
#define strlcpy strlcpy_unbound
size_t strlcpy(char *dst, const char *src, size_t siz);
#endif
#ifndef HAVE_GMTIME_R
#define gmtime_r gmtime_r_unbound
struct tm *gmtime_r(const time_t *timep, struct tm *result);
#endif
#ifndef HAVE_GETADDRINFO
#define getaddrinfo getaddrinfo_unbound
#define gai_strerror gai_strerror_unbound
#define freeaddrinfo freeaddrinfo_unbound
#define getnameinfo getnameinfo_unbound
struct sockaddr_storage;
#include "compat/fake-rfc2553.h"
#endif
#ifndef HAVE_SLEEP
#define sleep(x) Sleep((x)*1000) /* on win32 */
#endif /* HAVE_SLEEP */
#ifndef HAVE_USLEEP
#define usleep(x) Sleep((x)/1000 + 1) /* on win32 */
#endif /* HAVE_USLEEP */
#ifndef HAVE_RANDOM
#define random rand /* on win32, for tests only (bad random) */
#endif /* HAVE_RANDOM */
#ifndef HAVE_SRANDOM
#define srandom(x) srand(x) /* on win32, for tests only (bad random) */
#endif /* HAVE_SRANDOM */
#ifndef HAVE_SOCKETPAIR
int socketpair(int d, int type, int protocol, int *sv);
#endif
/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */
#ifdef HAVE_WINSOCK2_H
#define FD_SET_T (u_int)
#else
#define FD_SET_T
#endif
#include "ldns/ldns.h"
#ifdef UNBOUND_ALLOC_STATS
Vendored
+15 -5
View File
@@ -4,7 +4,7 @@
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
# Inc.
timestamp='2006-09-20'
timestamp='2007-04-29'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@@ -245,12 +245,12 @@ case $basic_machine in
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
| fr30 | frv \
| fido | fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | mcore \
| maxq | mb | microblaze | mcore | mep \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
@@ -324,7 +324,7 @@ case $basic_machine in
| clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| i*86-* | i860-* | i960-* | ia64-* \
@@ -683,6 +683,10 @@ case $basic_machine in
basic_machine=i386-pc
os=-mingw32
;;
mingw32ce)
basic_machine=arm-unknown
os=-mingw32ce
;;
miniframe)
basic_machine=m68000-convergent
;;
@@ -925,6 +929,9 @@ case $basic_machine in
basic_machine=sh-hitachi
os=-hms
;;
sh5el)
basic_machine=sh5le-unknown
;;
sh64)
basic_machine=sh64-unknown
;;
@@ -1219,7 +1226,7 @@ case $os in
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers*)
| -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1414,6 +1421,9 @@ case $basic_machine in
m68*-cisco)
os=-aout
;;
mep-*)
os=-elf
;;
mips*-cisco)
os=-elf
;;
Vendored
+2123 -836
View File
File diff suppressed because it is too large Load Diff
+339 -84
View File
@@ -1,40 +1,95 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.57)
AC_PREREQ(2.56)
AC_INIT(unbound, 0.9, unbound-bugs@nlnetlabs.nl, unbound)
AC_INIT(unbound,1.0.2, unbound-bugs@nlnetlabs.nl, unbound)
LIBUNBOUND_CURRENT=0
LIBUNBOUND_REVISION=14
LIBUNBOUND_AGE=0
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
# 1.0.2 had 0:14:0
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
# API are we supplying?
# Age -- How many previous binary API versions do we also
# support?
#
# If we release a new version that does not change the binary API,
# increment Revision.
#
# If we release a new version that changes the binary API, but does
# not break programs compiled against the old binary API, increment
# Current and Age. Set Revision to 0, since this is the first
# implementation of the new API.
#
# Otherwise, we're changing the binary API and breaking bakward
# compatibility with old binaries. Increment Current. Set Age to 0,
# since we're backward compatible with no previous APIs. Set Revision
# to 0 too.
AC_SUBST(LIBUNBOUND_CURRENT)
AC_SUBST(LIBUNBOUND_REVISION)
AC_SUBST(LIBUNBOUND_AGE)
CFLAGS=
AC_AIX
dnl
dnl By default set $sysconfdir to /etc and $localstatedir to /var
dnl By default set prefix to /usr/local
dnl
case "$prefix" in
NONE)
case "$sysconfdir" in
'${prefix}/etc')
sysconfdir=/etc
;;
esac
case "$localstatedir" in
'${prefix}/var')
localstatedir=/var
;;
esac
prefix="/usr/local"
;;
esac
#
# Determine configuration file
ub_conf_file=${sysconfdir}/unbound/unbound.conf
# the eval is to evaluate shell expansion twice
ub_conf_file=`eval echo "${sysconfdir}/unbound/unbound.conf"`
AC_ARG_WITH([conf_file],
AC_HELP_STRING([--with-conf-file=path], [Pathname to the Unbound configuration file]),
[ub_conf_file=$withval])
AC_HELP_STRING([--with-conf-file=path],
[Pathname to the Unbound configuration file]),
[ub_conf_file="$withval"])
AC_SUBST(ub_conf_file)
# the eval is to evaluate shell expansion twice, once
# for $nsd_conf_file and once for the ${prefix} within it.
AC_DEFINE_UNQUOTED(CONFIGFILE, ["`eval echo $ub_conf_file`"], [Pathname to the Unbound configuration file])
AC_DEFINE_UNQUOTED(CONFIGFILE, ["$ub_conf_file"], [Pathname to the Unbound configuration file])
# Determine run, chroot directory and pidfile locations
AC_ARG_WITH(run-dir,
AC_HELP_STRING([--with-run-dir=path],
[set default directory to chdir to (by default dir part of cfg file)]),
UNBOUND_RUN_DIR="$withval",
UNBOUND_RUN_DIR=`dirname "$ub_conf_file"`)
AC_SUBST(UNBOUND_RUN_DIR)
AC_DEFINE_UNQUOTED(RUN_DIR, ["$UNBOUND_RUN_DIR"], [Directory to chdir to])
AC_ARG_WITH(chroot-dir,
AC_HELP_STRING([--with-chroot-dir=path],
[set default directory to chroot to (by default same as run-dir)]),
UNBOUND_CHROOT_DIR="$withval",
UNBOUND_CHROOT_DIR="$UNBOUND_RUN_DIR")
AC_SUBST(UNBOUND_CHROOT_DIR)
AC_DEFINE_UNQUOTED(CHROOT_DIR, ["$UNBOUND_CHROOT_DIR"], [Directory to chroot to])
AC_ARG_WITH(pidfile,
AC_HELP_STRING([--with-pidfile=filename],
[set default pathname to unbound pidfile (default run-dir/unbound.pid)]),
UNBOUND_PIDFILE="$withval",
UNBOUND_PIDFILE="$UNBOUND_RUN_DIR/unbound.pid")
AC_SUBST(UNBOUND_PIDFILE)
AC_DEFINE_UNQUOTED(PIDFILE, ["$UNBOUND_PIDFILE"], [default pidfile location])
AC_ARG_WITH(username,
AC_HELP_STRING([--with-username=user],
[set default user that unbound changes to (default user is unbound)]),
UNBOUND_USERNAME="$withval",
UNBOUND_USERNAME="unbound")
AC_SUBST(UNBOUND_USERNAME)
AC_DEFINE_UNQUOTED(UB_USERNAME, ["$UNBOUND_USERNAME"], [default username])
AC_DEFINE(WINVER, 0x0502, [the version of the windows API enabled])
dnl routine to help check for compiler flags.
AC_DEFUN([CHECK_COMPILER_FLAG],
@@ -119,6 +174,10 @@ CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"])
AC_CHECK_HEADERS([getopt.h time.h],,, [AC_INCLUDES_DEFAULT])
# MinGW32 tests
AC_CHECK_HEADERS([winsock2.h ws2tcpip.h],,, [AC_INCLUDES_DEFAULT])
# end mingw32 tests
CHECK_COMPILER_FLAG_NEEDED(-std=c99 -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE,
[
#include "confdefs.h"
@@ -206,6 +265,17 @@ int test() {
}
], [CFLAGS="$CFLAGS -D_BSD_SOURCE"])
CHECK_COMPILER_FLAG_NEEDED(-D_GNU_SOURCE,
[
#include <netinet/in.h>
int test() {
struct in6_pktinfo inf;
int a = (int)sizeof(inf);
return a;
}
], [CFLAGS="$CFLAGS -D_GNU_SOURCE"])
CHECK_COMPILER_FLAG_NEEDED(-D_POSIX_C_SOURCE=200112,
[
#include "confdefs.h"
@@ -333,8 +403,11 @@ AC_DEFUN([AC_PROG_OBJC], [:])
AC_DEFUN([AC_PROG_OBJCCPP], [:])
AC_DEFUN([AC_LIBTOOL_CXX], [:])
AC_DEFUN([AC_LIBTOOL_F77], [:])
# Use libtool
AC_CHECK_PROGS(libtool, [glibtool libtool15 libtool], [./libtool])
# always use ./libtool unless override from commandline (libtool=mylibtool)
if test -z "$libtool"; then
libtool="./libtool"
fi
AC_SUBST(libtool)
AC_PATH_TOOL(AR, ar, [false])
if test $AR = false; then
AC_MSG_ERROR([Cannot find 'ar', please extend PATH to include it])
@@ -351,7 +424,7 @@ AC_PROG_LIBTOOL
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h sys/param.h sys/socket.h sys/uio.h arpa/inet.h syslog.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h sys/param.h sys/socket.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h],,, [AC_INCLUDES_DEFAULT])
# check for types
AC_CHECK_TYPE(int8_t, char)
@@ -369,6 +442,13 @@ AC_TYPE_PID_T
AC_TYPE_OFF_T
AC_CHECK_TYPE(u_char, unsigned char)
AC_CHECK_TYPE(rlim_t, ,
[AC_DEFINE([rlim_t], [unsigned long], [Define to 'int' if not defined])], [
AC_INCLUDES_DEFAULT
#if HAVE_SYS_RESOURCE_H
# include <sys/resource.h>
#endif
])
AC_CHECK_TYPE(socklen_t, ,
[AC_DEFINE([socklen_t], [int], [Define to 'int' if not defined])], [
AC_INCLUDES_DEFAULT
@@ -395,31 +475,19 @@ AC_INCLUDES_DEFAULT
#endif
])
# Check for yyunput
AC_DEFUN([CHECK_YYUNPUT],
[AC_MSG_CHECKING(whether lex can not generate yyunput)
AC_CACHE_VAL(ac_cv_c_yy_unput,
[ac_cv_c_yy_unput=no
if $LEX --nounput -h 2>&1 | grep "do not generate" 2>&1 >/dev/null; then
ac_cv_c_yy_unput="yes"
else
ac_cv_c_yy_unput="no"
fi
])
AC_MSG_RESULT($ac_cv_c_yy_unput)
if test $ac_cv_c_yy_unput = yes; then
LEX="$LEX --nounput"
fi
])dnl
CHECK_YYUNPUT
# add option to disable the evil rpath
dnl Check whether to use rpath or not
AC_ARG_ENABLE(rpath,
[ --disable-rpath disable hardcoded rpath (default=enabled)],
enable_rpath=$enableval, enable_rpath=yes)
if test "x$enable_rpath" = xno; then
AC_MSG_RESULT([Fixing libtool for -rpath problems.])
sed < libtool > libtool-2 \
's/^hardcode_libdir_flag_spec.*$'/'hardcode_libdir_flag_spec=" -D__LIBTOOL_RPATH_SED__ "/'
mv libtool-2 libtool
chmod 755 libtool
libtool="./libtool"
fi
# Checks for libraries.
AC_ARG_WITH(ssl, AC_HELP_STRING([--with-ssl=pathname],
@@ -451,9 +519,34 @@ AC_ARG_WITH(ssl, AC_HELP_STRING([--with-ssl=pathname],
if test "x$enable_rpath" = xyes; then
RUNTIME_PATH="$RUNTIME_PATH -R$ssldir/lib"
fi
AC_CHECK_LIB(crypto, HMAC_CTX_init,, [
AC_MSG_CHECKING([for HMAC_CTX_init in -lcrypto])
ORIGLIBS="$LIBS"
LIBS="$LIBS -lcrypto"
AC_TRY_LINK(, [
int HMAC_CTX_init(void);
(void)HMAC_CTX_init();
], [
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
[If you have HMAC_CTX_init])
], [
AC_MSG_RESULT(no)
# check if -lwsock32 or -lgdi32 are needed.
LIBS="$LIBS -lgdi32"
AC_MSG_CHECKING([if -lcrypto needs -lgdi32])
AC_TRY_LINK([], [
int HMAC_CTX_init(void);
(void)HMAC_CTX_init();
],[
AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
[If you have HMAC_CTX_init])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
])
])
])
fi
AC_SUBST(HAVE_SSL)
AC_SUBST(RUNTIME_PATH)
@@ -482,6 +575,7 @@ fi
# check solaris thread library
AC_ARG_WITH(solaris-threads, AC_HELP_STRING([--with-solaris-threads],
[use solaris native thread library.]), [ ],[ withval="no" ])
ub_have_sol_threads=no
if test x_$withval != x_no; then
if test x_$ub_have_pthreads != x_no; then
AC_WARN([Have pthreads already, ignoring --with-solaris-threads])
@@ -492,23 +586,40 @@ if test x_$withval != x_no; then
CHECK_COMPILER_FLAG(mt, [CFLAGS="$CFLAGS -mt"],
[CFLAGS="$CFLAGS -D_REENTRANT"])
ub_have_sol_threads=yes
] , [
AC_ERROR([no solaris threads found.])
])
fi
fi
# check windows threads
if test x_$ub_have_pthreads = x_no -a x_$ub_have_sol_threads = x_no; then
AC_CHECK_HEADERS([windows.h],,, [AC_INCLUDES_DEFAULT])
AC_MSG_CHECKING([for CreateThread])
AC_TRY_COMPILE([
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
], [
HANDLE t = CreateThread(NULL, 0, NULL, NULL, 0, NULL);
],
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_WINDOWS_THREADS, 1, [Using Windows threads])
,
AC_MSG_RESULT(no)
)
fi
# check to see if libraries are needed for these functions.
AC_SEARCH_LIBS([inet_pton], [nsl])
AC_SEARCH_LIBS([socket], [socket])
# check for library used by libevent after 1.3c
AC_SEARCH_LIBS([clock_gettime], [rt])
# check for libevent
AC_ARG_WITH(libevent, AC_HELP_STRING([--with-libevent=pathname],
[set path to libevent (will check /usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr)]),
[ ],[ withval="yes" ])
if test x_$withval != x_no; then
[use libevent (will check /usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr or you can specify an explicit path). Slower, but allows use of large outgoing port ranges.]),
[ ],[ withval="no" ])
if test x_$withval = x_yes -o x_$withval != x_no; then
AC_MSG_CHECKING(for libevent)
if test x_$withval = x_ -o x_$withval = x_yes; then
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
@@ -522,10 +633,10 @@ if test x_$withval != x_no; then
fi
done
if test x_$found_libevent != x_yes; then
if test -f "$dir/event.h" -a -f "$dir/libevent.la"; then
if test -f "$dir/event.h" -a \( -f "$dir/libevent.la" -o -f "$dir/libev.la" \) ; then
# libevent source directory
AC_MSG_RESULT(found in $thedir)
CPPFLAGS="$CPPFLAGS -I$thedir"
CPPFLAGS="$CPPFLAGS -I$thedir -I$thedir/include"
BAK_LDFLAGS="$LDFLAGS"
# remove evdns from linking
mkdir build >/dev/null 2>&1
@@ -537,13 +648,13 @@ if test x_$withval != x_no; then
cp $ev_files_o build/libevent
cp $ev_files_lo build/libevent
cp $ev_files_libso build/libevent/.libs
LATE_LDFLAGS="build/libevent/*.lo"
LDFLAGS="build/libevent/*.o $LDFLAGS"
LATE_LDFLAGS="build/libevent/*.lo -lm"
LDFLAGS="build/libevent/*.o $LDFLAGS -lm"
else
AC_MSG_ERROR([Cannot find the libevent library in $withval
You can restart ./configure --with-libevent=no to use a builtin alternative.
Please note that this alternative is not as capable as libevent when using
many outgoing ports. ])
large outgoing port ranges. ])
fi
else
AC_MSG_RESULT(found in $thedir)
@@ -553,10 +664,14 @@ many outgoing ports. ])
fi
fi
AC_SUBST(RUNTIME_PATH)
# check for library used by libevent after 1.3c
AC_SEARCH_LIBS([clock_gettime], [rt])
AC_SEARCH_LIBS(event_set, [event])
AC_CHECK_HEADERS([event.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_FUNCS([event_base_free]) # only in libevent 1.2 and later
AC_CHECK_FUNCS([event_base_once]) # only in libevent 1.4? and later
AC_CHECK_FUNCS([event_base_get_method]) # only in libevent 1.4.3 and later
if test -n "$BAK_LDFLAGS"; then
LDFLAGS="$BAK_LDFLAGS"
fi
@@ -580,6 +695,8 @@ AC_ARG_ENABLE(lock_checks, AC_HELP_STRING([--enable-lock-checks],
, )
if test x_$enable_lock_checks = x_yes; then
AC_DEFINE(ENABLE_LOCK_CHECKS, 1, [Define if you want to use debug lock checking (slow).])
CHECKLOCK_SRC="testcode/checklocks.c"
AC_SUBST(CHECKLOCK_SRC)
fi
# set memory allocation checking if requested
@@ -597,6 +714,116 @@ AC_FUNC_FORK
AC_TYPE_SIGNAL
AC_FUNC_FSEEKO
AC_SYS_LARGEFILE
dnl try to see if an additional _LARGEFILE_SOURCE 1 is needed to get fseeko
CHECK_COMPILER_FLAG_NEEDED(-D_LARGEFILE_SOURCE=1,
[
#include <stdio.h>
int test() {
int a = fseeko(stdin, 0, 0);
return a;
}
], [CFLAGS="$CFLAGS -D_LARGEFILE_SOURCE=1"])
AC_DEFUN([AC_CHECK_GETADDRINFO_WITH_INCLUDES],
[AC_REQUIRE([AC_PROG_CC])
AC_MSG_CHECKING(for getaddrinfo)
ac_cv_func_getaddrinfo=no
AC_LINK_IFELSE(
[
#ifdef __cplusplus
extern "C"
{
#endif
char* getaddrinfo();
char* (*f) () = getaddrinfo;
#ifdef __cplusplus
}
#endif
int main() {
;
return 0;
}
],
dnl this case on linux, solaris, bsd
[ac_cv_func_getaddrinfo="yes"],
dnl no quick getaddrinfo, try mingw32 and winsock2 library.
ORIGLIBS="$LIBS"
LIBS="$LIBS -lws2_32"
AC_LINK_IFELSE(
AC_LANG_PROGRAM(
[
#ifdef HAVE_WS2TCPIP_H
#include <ws2tcpip.h>
#endif
],
[
(void)getaddrinfo(NULL, NULL, NULL, NULL);
]
),
[
ac_cv_func_getaddrinfo="yes"
dnl already: LIBS="$LIBS -lws2_32"
AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
],
[
ac_cv_func_getaddrinfo="no"
LIBS="$ORIGLIBS"
])
)
AC_MSG_RESULT($ac_cv_func_getaddrinfo)
if test $ac_cv_func_getaddrinfo = yes; then
AC_DEFINE(HAVE_GETADDRINFO, 1, [Whether getaddrinfo is available])
fi
])dnl
AC_CHECK_GETADDRINFO_WITH_INCLUDES
if test $ac_cv_func_getaddrinfo = no; then
AC_LIBOBJ([fake-rfc2553])
fi
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam getrlimit setsid sbrk chroot kill sleep usleep random srandom recvmsg sendmsg writev])
# check mkdir
AC_MSG_CHECKING([whether mkdir has one arg])
AC_TRY_COMPILE([
#include <stdio.h>
#include <unistd.h>
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
], [
(void)mkdir("directory");
],
AC_MSG_RESULT(yes)
AC_DEFINE(MKDIR_HAS_ONE_ARG, 1, [Define if mkdir has one argument.])
,
AC_MSG_RESULT(no)
)
# check ioctlsocket
AC_MSG_CHECKING(for ioctlsocket)
AC_LINK_IFELSE(AC_LANG_PROGRAM([
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
], [
(void)ioctlsocket(0, 0, NULL);
]), [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_IOCTLSOCKET, 1, [if the function 'ioctlsocket' is available])
],[AC_MSG_RESULT(no)])
AC_REPLACE_FUNCS(inet_aton)
AC_REPLACE_FUNCS(inet_pton)
AC_REPLACE_FUNCS(inet_ntop)
AC_REPLACE_FUNCS(snprintf)
AC_REPLACE_FUNCS(strlcpy)
AC_REPLACE_FUNCS(memmove)
AC_REPLACE_FUNCS(gmtime_r)
AC_REPLACE_FUNCS(socketpair) dnl for mingw32
# check this after all other compilation checks, since the linking of the lib
# may break checks after this.
@@ -609,21 +836,9 @@ AC_ARG_WITH(ldns,
AC_SUBST(ldnsdir)
])
AC_CHECK_LIB(ldns, ldns_rr_new, [
AC_CHECK_LIB(ldns, ldns_buffer_copy, [
dnl ldns was found, check compat functions
AC_CHECK_LIB(ldns, [ldns_rr_free])
AC_REPLACE_FUNCS(inet_aton)
AC_REPLACE_FUNCS(inet_pton)
AC_REPLACE_FUNCS(inet_ntop)
AC_REPLACE_FUNCS(snprintf)
AC_REPLACE_FUNCS(strlcpy)
AC_REPLACE_FUNCS(memmove)
AC_CHECK_FUNCS([getaddrinfo])
if test $ac_cv_func_getaddrinfo = no; then
AC_LIBOBJ([fake-rfc2553])
fi
] , [
dnl use the builtin ldns-src.tar.gz file to build ldns.
if test ! -f $srcdir/ldns-src.tar.gz; then
@@ -635,24 +850,14 @@ echo "*** ldns library not found (--with-ldns= to specify by hand) ***"
echo "*** Building ldns library from package included in this one. ***"
echo "*** ***"
echo "****************************************************************"
if test -d ldns-src; then rm -rf ldns-src; fi
mkdir ldns-src; cp $srcdir/ldns-src.tar.gz ldns-src/ldns-src.tar.gz; (cd ldns-src; gzip -cd ldns-src.tar.gz | tar xf -); rm -f ldns-src/ldns-src.tar.gz
ldnsdir=`ls -d ldns-src/ldns*`
AC_MSG_NOTICE([Configure $ldnsdir])
echo "(cd $ldnsdir; ./configure)"
(cd $ldnsdir; ./configure)
AC_MSG_NOTICE([Finished $ldnsdir configure])
CPPFLAGS="$CPPFLAGS -I$ldnsdir/include"
if test -d $srcdir/ldns-src; then rm -rf $srcdir/ldns-src; fi
mkdir $srcdir/ldns-src; cp $srcdir/ldns-src.tar.gz $srcdir/ldns-src/ldns-src.tar.gz; (cd $srcdir/ldns-src; gzip -cd ldns-src.tar.gz | tar xf -); rm -f $srcdir/ldns-src/ldns-src.tar.gz; mv $srcdir/ldns-src $srcdir/ldns-srcb; mv $srcdir/ldns-srcb/ldns* $srcdir/ldns-src; rmdir $srcdir/ldns-srcb
ldnsdir="ldns-src"
AC_MSG_NOTICE([Configure $ldnsdir scheduled after config.status])
AC_CONFIG_SUBDIRS([ldns-src])
CPPFLAGS="-I$ldnsdir/include $CPPFLAGS"
LDFLAGS="$LDFLAGS $ldnsdir/*.lo"
AC_SUBST(ldnsdir)
dnl use ldns compat functions
AC_DEFINE(HAVE_INET_ATON)
AC_DEFINE(HAVE_INET_PTON)
AC_DEFINE(HAVE_INET_NTOP)
AC_DEFINE(HAVE_SNPRINTF)
AC_DEFINE(HAVE_STRLCPY)
AC_DEFINE(HAVE_MEMMOVE)
AC_DEFINE(HAVE_GETADDRINFO)
])
LDFLAGS="$LATE_LDFLAGS $LDFLAGS"
@@ -699,6 +904,14 @@ AH_BOTTOM([
#include <arpa/inet.h>
#endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
#ifdef HAVE_WS2TCPIP_H
#include <ws2tcpip.h>
#endif
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
@@ -739,6 +952,10 @@ AH_BOTTOM([
#define RAND_MAX 2147483647
#endif
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 256
#endif
#ifndef IPV6_MIN_MTU
#define IPV6_MIN_MTU 1280
#endif /* IPV6_MIN_MTU */
@@ -756,30 +973,68 @@ AH_BOTTOM([
#define MAXINCLUDES 10
#ifndef HAVE_SNPRINTF
#define snprintf snprintf_unbound
#define vsnprintf vsnprintf_unbound
#include <stdarg.h>
int snprintf (char *str, size_t count, const char *fmt, ...);
int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
#endif /* HAVE_SNPRINTF */
#ifndef HAVE_INET_PTON
#define inet_pton inet_pton_unbound
int inet_pton(int af, const char* src, void* dst);
#endif /* HAVE_INET_PTON */
#ifndef HAVE_INET_NTOP
#define inet_ntop inet_ntop_unbound
const char *inet_ntop(int af, const void *src, char *dst, size_t size);
#endif
#ifndef HAVE_INET_ATON
#define inet_aton inet_aton_unbound
int inet_aton(const char *cp, struct in_addr *addr);
#endif
#ifndef HAVE_MEMMOVE
#define memmove memmove_unbound
void *memmove(void *dest, const void *src, size_t n);
#endif
#ifndef HAVE_STRLCPY
#define strlcpy strlcpy_unbound
size_t strlcpy(char *dst, const char *src, size_t siz);
#endif
#ifndef HAVE_GMTIME_R
#define gmtime_r gmtime_r_unbound
struct tm *gmtime_r(const time_t *timep, struct tm *result);
#endif
#ifndef HAVE_GETADDRINFO
#define getaddrinfo getaddrinfo_unbound
#define gai_strerror gai_strerror_unbound
#define freeaddrinfo freeaddrinfo_unbound
#define getnameinfo getnameinfo_unbound
struct sockaddr_storage;
#include "compat/fake-rfc2553.h"
#endif
#ifndef HAVE_SLEEP
#define sleep(x) Sleep((x)*1000) /* on win32 */
#endif /* HAVE_SLEEP */
#ifndef HAVE_USLEEP
#define usleep(x) Sleep((x)/1000 + 1) /* on win32 */
#endif /* HAVE_USLEEP */
#ifndef HAVE_RANDOM
#define random rand /* on win32, for tests only (bad random) */
#endif /* HAVE_RANDOM */
#ifndef HAVE_SRANDOM
#define srandom(x) srand(x) /* on win32, for tests only (bad random) */
#endif /* HAVE_SRANDOM */
#ifndef HAVE_SOCKETPAIR
int socketpair(int d, int type, int protocol, int *sv);
#endif
/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */
#ifdef HAVE_WINSOCK2_H
#define FD_SET_T (u_int)
#else
#define FD_SET_T
#endif
#include "ldns/ldns.h"
#ifdef UNBOUND_ALLOC_STATS
@@ -805,6 +1060,6 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
#define UNBOUND_DNS_PORT 53
])
AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-checkconf.8 doc/unbound.conf.5])
AC_CONFIG_HEADER([config.h])
AC_OUTPUT
+9
View File
@@ -0,0 +1,9 @@
These files are contributed to unbound, and are not part of the official
distribution but may be helpful.
* rc_d_unbound: FreeBSD compatible /etc/rc.d script.
* parseunbound.pl: perl script to run from cron that parses statistics from
the log file and stores them.
* unbound.spec and unbound.init: RPM specfile and Linux rc.d initfile.
* update-anchor.sh: shell script that uses unbound-host to update a set
of trust anchor files. Run from cron twice a month.
+140
View File
@@ -0,0 +1,140 @@
#!/usr/local/bin/perl -w
#
# Script to parse the output from the unbound namedaemon.
# Unbound supports a threading model, and outputs a multiline log-blob for
# every thread.
#
# This script should parse all threads of the once, and store it
# in a local cached file for speedy results when queried lots.
#
use strict;
use POSIX qw(SEEK_END);
use Storable;
use FileHandle;
use Carp qw(croak carp);
use constant UNBOUND_CACHE => "/var/tmp/unbound-cache.stor";
my $run_from_cron = @ARGV && $ARGV[0] eq "--cron" && shift;
my $DEBUG = -t STDERR;
# NB. VERY IMPORTANTES: set this when running this script.
my $numthreads = 4;
### if cache exists, read it in. and is newer than 3 minutes
if ( -r UNBOUND_CACHE ) {
my $result = retrieve(UNBOUND_CACHE);
if (-M _ < 3/24/60 && !$run_from_cron ) {
print STDERR "Cached results:\n" if $DEBUG;
print join("\n", @$result), "\n";
exit;
}
}
my $logfile = shift or die "Usage: parseunbound.pl --cron unboundlogfile";
my $in = new FileHandle $logfile or die "Cannot open $logfile: $!\n";
# there is a special key 'thread' that indicates the thread. its not used, but returned anyway.
my @records = ('thread', 'queries', 'cachehits', 'recursions', 'recursionavg',
'outstandingmax', 'outstandingavg', 'outstandingexc',
'median25', 'median50', 'median75',
'us_0', 'us_1', 'us_2', 'us_4', 'us_8', 'us_16', 'us_32',
'us_64', 'us_128', 'us_256', 'us_512', 'us_1024', 'us_2048',
'us_4096', 'us_8192', 'us_16384', 'us_32768', 'us_65536',
'us_131072', 'us_262144', 'us_524288', 's_1', 's_2', 's_4',
's_8', 's_16', 's_32', 's_64', 's_128', 's_256', 's_512');
# Stats hash containing one or more keys. for every thread, 1 key.
my %allstats = (); # key="$threadid", stats={key => value}
my %startstats = (); # when we got a queries entry for this thread
my %donestats = (); # same, but only when we got a histogram entry for it
# stats hash contains name/value pairs of the actual numbers for that thread.
my $offset = 0;
my $inthread=0;
my $inpid;
# We should continue looping untill we meet these conditions:
# a) more total queries than the previous run (which defaults to 0) AND
# b) parsed all $numthreads threads in the log.
my $numqueries = $previousresult ? $previousresult->[1] : 0;
# Main loop
while ( scalar keys %startstats < $numthreads || scalar keys %donestats < $numthreads) {
$offset += 10000;
if ( $offset > -s $logfile or $offset > 10_000_000 ) {
die "Cannot find stats in $logfile\n";
}
$in->seek(-$offset, SEEK_END) or croak "cannot seek $logfile: $!\n";
for my $line ( <$in> ) {
chomp($line);
#[1208777234] unbound[6705:0]
if ($line =~ m/^\[\d+\] unbound\[\d+:(\d+)\]/) {
$inthread = $1;
if ($inthread + 1 > $numthreads) {
die "Hey. lazy. change \$numthreads in this script to ($inthread)\n";
}
}
# this line doesn't contain a pid:thread. skip.
else {
next;
}
if ( $line =~ m/info: server stats for thread \d+: (\d+) queries, (\d+) answers from cache, (\d+) recursions/ ) {
$startstats{$inthread} = 1;
$allstats{$inthread}->{thread} = $inthread;
$allstats{$inthread}->{queries} = $1;
$allstats{$inthread}->{cachehits} = $2;
$allstats{$inthread}->{recursions} = $3;
}
elsif ( $line =~ m/info: server stats for thread (\d+): requestlist max (\d+) avg ([0-9\.]+) exceeded (\d+)/ ) {
$allstats{$inthread}->{outstandingmax} = $2;
$allstats{$inthread}->{outstandingavg} = int($3); # This is a float; rrdtool only handles ints.
$allstats{$inthread}->{outstandingexc} = $4;
}
elsif ( $line =~ m/info: average recursion processing time ([0-9\.]+) sec/ ) {
$allstats{$inthread}->{recursionavg} = int($1 * 1000); # change sec to milisec.
}
elsif ( $line =~ m/info: histogram of recursion processing times/ ) {
next;
}
elsif ( $line =~ m/info: \[25%\]=([0-9\.]+) median\[50%\]=([0-9\.]+) \[75%\]=([0-9\.]+)/ ) {
$allstats{$inthread}->{median25} = int($1 * 1000000); # change seconds to usec
$allstats{$inthread}->{median50} = int($2 * 1000000);
$allstats{$inthread}->{median75} = int($3 * 1000000);
}
elsif ( $line =~ m/info: lower\(secs\) upper\(secs\) recursions/ ) {
# since after this line we're unsure if we get these numbers
# at all, we sould consider this marker as the end of the
# block. Chances that we're parsing a file halfway written
# at this stage are small. Bold statement.
$donestats{$inthread} = 1;
next;
}
elsif ( $line =~ m/info:\s+(\d+)\.(\d+)\s+(\d+)\.(\d+)\s+(\d+)/ ) {
my ($froms, $fromus, $toms, $tous, $counter) = ($1, $2, $3, $4, $5);
my $prefix = '';
if ($froms > 0) {
$allstats{$inthread}->{'s_' . int($froms)} = $counter;
} else {
$allstats{$inthread}->{'us_' . int($fromus)} = $counter;
}
}
}
}
my @result;
# loop on the records we want to store
for my $key ( @records ) {
my $sum = 0;
# these are the different threads parsed
foreach my $thread ( 0 .. $numthreads - 1 ) {
$sum += ($allstats{$thread}->{$key} || 0);
}
print STDERR "$key = " . $sum . "\n" if $DEBUG;
push @result, $sum;
}
print join("\n", @result), "\n";
store \@result, UNBOUND_CACHE;
if ($DEBUG) {
print STDERR "Threads: " . (scalar keys %allstats) . "\n";
}
+23
View File
@@ -0,0 +1,23 @@
#!/bin/sh
#
# unbound freebsd startup rc.d script, modified from the named script.
# uses the default unbound installation path and pidfile location.
# copy this to /etc/rc.d/unbound
# and put unbound_enable="YES" into rc.conf
#
# PROVIDE: unbound
# REQUIRE: SERVERS cleanvar
# KEYWORD: shutdown
. /etc/rc.subr
name="unbound"
rcvar=`set_rcvar`
command="/usr/local/sbin/unbound"
pidfile="/usr/local/etc/unbound/unbound.pid"
extra_commands="reload"
load_rc_config $name
run_rc_command "$1"
+139
View File
@@ -0,0 +1,139 @@
#!/bin/sh
#
# unbound This shell script takes care of starting and stopping
# unbound (DNS server).
#
# chkconfig: - 14 86
# description: unbound is a Domain Name Server (DNS) \
# that is used to resolve host names to IP addresses.
### BEGIN INIT INFO
# Provides: $named unbound
# Required-Start: $network $local_fs
# Required-Stop: $network $local_fs
# Should-Start: $syslog
# Should-Stop: $syslog
# Short-Description: unbound recursive Domain Name Server.
# Description: unbound is a Domain Name Server (DNS)
# that is used to resolve host names to IP addresses.
### END INIT INFO
# Source function library.
. /etc/rc.d/init.d/functions
exec="/usr/sbin/unbound"
prog="unbound"
config="/var/unbound/unbound.conf"
pidfile="/var/unbound/unbound.pid"
rootdir="/var/unbound"
[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
lockfile=/var/lock/subsys/$prog
start() {
[ -x $exec ] || exit 5
[ -f $config ] || exit 6
echo -n $"Starting $prog: "
# setup root jail
if [ -s /etc/localtime ]; then
[ -d ${rootdir}/etc ] || mkdir -p ${rootdir}/etc ;
if [ ! -e ${rootdir}/etc/localtime ] || /usr/bin/cmp -s /etc/localtime ${rootdir}/etc/localtime; then
cp -fp /etc/localtime ${rootdir}/etc/localtime
fi;
fi;
if [ -s /etc/resolv.conf ]; then
[ -d ${rootdir}/etc ] || mkdir -p ${rootdir}/etc ;
if [ ! -e ${rootdir}/etc/resolv.conf ] || /usr/bin/cmp -s /etc/resolv.conf ${rootdir}/etc/resolv.conf; then
cp -fp /etc/resolv.conf ${rootdir}/etc/resolv.conf
fi;
fi;
if ! egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
[ -d ${rootdir}/dev ] || mkdir -p ${rootdir}/dev ;
[ -e ${rootdir}/dev/log ] || touch ${rootdir}/dev/log
mount --bind -n /dev/log ${rootdir}/dev/log >/dev/null 2>&1;
fi;
if ! egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/random' /proc/mounts; then
[ -d ${rootdir}/dev ] || mkdir -p ${rootdir}/dev ;
[ -e ${rootdir}/dev/random ] || touch ${rootdir}/dev/random
mount --bind -n /dev/random ${rootdir}/dev/random >/dev/null 2>&1;
fi;
# if not running, start it up here
daemon $exec
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
stop() {
echo -n $"Stopping $prog: "
# stop it here, often "killproc $prog"
killproc -p $pidfile $prog
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
umount ${rootdir}/dev/log >/dev/null 2>&1
fi;
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/random' /proc/mounts; then
umount ${rootdir}/dev/random >/dev/null 2>&1
fi;
return $retval
}
restart() {
stop
start
}
reload() {
kill -HUP `cat $pidfile`
}
force_reload() {
restart
}
rh_status() {
# run checks to determine if the service is running or use generic status
status -p $pidfile $prog
}
rh_status_q() {
rh_status -p $pidfile >/dev/null 2>&1
}
case "$1" in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q || exit 0
restart
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
exit 2
esac
exit $?
+103
View File
@@ -0,0 +1,103 @@
Summary: Validating, recursive, and caching DNS resolver
Name: unbound
Version: 1.0.1
Release: 1%{?dist}
License: BSD
Url: http://www.nlnetlabs.nl/unbound/
Source: http://www.unbound.net/downloads/%{name}-%{version}.tar.gz
#Source1: unbound.init
Group: System Environment/Daemons
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: flex, openssl-devel
%description
Unbound is a validating, recursive, and caching DNS resolver.
The C implementation of Unbound is developed and maintained by NLnet
Labs. It is based on ideas and algorithms taken from a java prototype
developed by Verisign labs, Nominet, Kirei and ep.net.
Unbound is designed as a set of modular components, so that also
DNSSEC (secure DNS) validation and stub-resolvers (that do not run
as a server, but are linked into an application) are easily possible.
The source code is under a BSD License.
%prep
%setup -q
# configure with /var/unbound/unbound.conf so that all default chroot,
# pidfile and config file are in /var/unbound, ready for chroot jail set up.
#
# This is a build using libldns builtin version, the resulting binaries
# do not require libldns and this package does not have version dependencies.
# Could be smaller using a dependency on libldns (use --with-ldns=).
%configure --with-conf-file=%{_localstatedir}/%{name}/unbound.conf --disable-rpath
%build
#%{__make} %{?_smp_mflags}
make
%install
rm -rf %{buildroot}
%{__make} DESTDIR=%{buildroot} install
install -d 0700 %{buildroot}%{_localstatedir}/%{name}
install -d 0755 %{buildroot}%{_initrddir}
install -m 0755 contrib/unbound.init %{buildroot}%{_initrddir}/unbound
# add symbolic link from /etc/unbound.conf -> /var/unbound/unbound.conf
ln -s %{_localstatedir}/unbound/unbound.conf %{buildroot}%{_sysconfdir}/unbound.conf
# remove static library from install (fedora packaging guidelines)
rm -f %{buildroot}%{_libdir}/libunbound.a %{buildroot}%{_libdir}/libunbound.la
%clean
rm -rf ${RPM_BUILD_ROOT}
%files
%defattr(-,root,root,-)
%doc doc/README doc/CREDITS doc/LICENSE doc/FEATURES
%attr(0755,root,root) %{_initrddir}/%{name}
%attr(0700,%{name},%{name}) %dir %{_localstatedir}/%{name}
%attr(0644,%{name},%{name}) %config(noreplace) %{_localstatedir}/%{name}/unbound.conf
%attr(0644,%{name},%{name}) %config(noreplace) %{_sysconfdir}/unbound.conf
%{_sbindir}/*
%{_mandir}/*/*
%{_includedir}/*
%{_libdir}/libunbound*
%pre
getent group unbound >/dev/null || groupadd -r unbound
getent passwd unbound >/dev/null || \
useradd -r -g unbound -d /var/unbound -s /sbin/nologin \
-c "unbound name daemon" unbound
exit 0
%post
# This adds the proper /etc/rc*.d links for the script
/sbin/chkconfig --add %{name}
%preun
if [ $1 -eq 0 ]; then
/sbin/service %{name} stop >/dev/null 2>&1
/sbin/chkconfig --del %{name}
# remove root jail
rm -f /var/unbound/dev/log /var/unbound/dev/random /var/unbound/etc/localtime /var/unbound/etc/resolv.conf >/dev/null 2>&1
rmdir /var/unbound/dev >/dev/null 2>&1 || :
rmdir /var/unbound/etc >/dev/null 2>&1 || :
rmdir /var/unbound >/dev/null 2>&1 || :
fi
%postun
if [ "$1" -ge "1" ]; then
/sbin/service %{name} condrestart >/dev/null 2>&1 || :
fi
%changelog
* Thu May 22 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 1.0.0
- contrib changes from Patrick Vande Walle.
* Thu Apr 25 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 0.12
- Using parts from ports collection entry by Jaap Akkerhuis.
- Using Fedoraproject wiki guidelines.
* Wed Apr 23 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 0.11
- Initial version.
+134
View File
@@ -0,0 +1,134 @@
#!/bin/sh
# update-anchor.sh, update a trust anchor.
# this file is BSD licensed.
# which validating lookup to use.
ubhost=unbound-host
function usage()
{
echo "usage: update-anchor [-b] <zone name> <trust anchor file>"
echo " performs an update of trust anchor file"
echo " the trust anchor file is overwritten with the latest keys"
echo " the trust anchor file should contain only keys for one zone"
echo " -b causes keyfile to be made in bind format."
echo " without -b the file is made in unbound format."
echo " "
echo "alternate:"
echo " update-anchor [-b] -d directory"
echo " update all <zone>.anchor files in the directory."
echo " "
echo " name the files br.anchor se.anchor ..., and include them in"
echo " the validating resolver config file."
echo " put keys for the root in a file with the name root.anchor."
exit 1
}
if test $# -eq 0; then
usage
fi
bindformat="no"
filearg='-f'
if test X"$1" = "X-b"; then
shift
bindformat="yes"
filearg='-F'
fi
if test $# -ne 2; then
echo "arguments wrong."
usage
fi
function do_update() {
# arguments: <zonename> <keyfile>
zonename="$1"
keyfile="$2"
tmpfile="/tmp/update-anchor.$$"
$ubhost -v $filearg "$keyfile" -t DNSKEY "$zonename" >$tmpfile
if test $? -ne 0; then
rm -f $tmpfile
echo "Error: Could not update zone $zonename anchor file $keyfile"
echo "Cause: $ubhost lookup failed"
echo " (Is the domain decommissioned? Is connectivity lost?)"
return 2
fi
# has the lookup been DNSSEC validated?
if grep '(secure)$' $tmpfile >/dev/null 2>&1; then
:
else
rm -f $tmpfile
echo "Error: Could not update zone $zonename anchor file $keyfile"
echo "Cause: result of lookup was not secure"
echo " (keys too far out of date? domain changed ownership?)"
return 3
fi
if test $bindformat = "yes"; then
# are there any KSK keys on board?
echo 'trusted-keys {' > "$keyfile"
if grep ' has DNSKEY record 257' $tmpfile >/dev/null 2>&1; then
# store KSK keys in anchor file
grep '(secure)$' $tmpfile | \
grep ' has DNSKEY record 257' | \
sed -e 's/ (secure)$/";/' | \
sed -e 's/ has DNSKEY record \([0-9]*\) \([0-9]*\) \([0-9]*\) /. \1 \2 \3 "/' | \
sed -e 's/^\.\././' >> "$keyfile"
else
# store all keys in the anchor file
grep '(secure)$' $tmpfile | \
sed -e 's/ (secure)$/";/' | \
sed -e 's/ has DNSKEY record \([0-9]*\) \([0-9]*\) \([0-9]*\) /. \1 \2 \3 "/' | \
sed -e 's/^\.\././' >> "$keyfile"
fi
echo '};' >> "$keyfile"
else #not bindformat
# are there any KSK keys on board?
if grep ' has DNSKEY record 257' $tmpfile >/dev/null 2>&1; then
# store KSK keys in anchor file
grep '(secure)$' $tmpfile | \
grep ' has DNSKEY record 257' | \
sed -e 's/ (secure)$//' | \
sed -e 's/ has DNSKEY record /. IN DNSKEY /' | \
sed -e 's/^\.\././' > "$keyfile"
else
# store all keys in the anchor file
grep '(secure)$' $tmpfile | \
sed -e 's/ (secure)$//' | \
sed -e 's/ has DNSKEY record /. IN DNSKEY /' | \
sed -e 's/^\.\././' > "$keyfile"
fi
fi # endif-bindformat
echo "$zonename key file $keyfile updated."
rm -f $tmpfile
}
if test X"$1" = "X-d"; then
tdir="$2"
echo "start updating in $2"
for x in $tdir/*.anchor; do
if test `basename "$x"` = "root.anchor"; then
zname="."
else
zname=`basename "$x" .anchor`
fi
do_update "$zname" "$x"
done
echo "done updating in $2"
else
# regular invocation
if test X"$1" = "X."; then
zname="$1"
else
# strip trailing dot from zone name
zname="`echo $1 | sed -e 's/\.$//'`"
fi
kfile="$2"
do_update $zname $kfile
exit $?
fi
exit 0
+8 -6
View File
@@ -194,14 +194,16 @@ acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
/* insert defaults, with '0' to ignore them if they are duplicates */
if(!acl_list_str_cfg(acl, "0.0.0.0/0", "refuse", 0))
return 0;
if(!acl_list_str_cfg(acl, "::0/0", "refuse", 0))
return 0;
if(!acl_list_str_cfg(acl, "127.0.0.0/8", "allow", 0))
return 0;
if(!acl_list_str_cfg(acl, "::1", "allow", 0))
return 0;
if(!acl_list_str_cfg(acl, "::ffff:127.0.0.1", "allow", 0))
return 0;
if(cfg->do_ip6) {
if(!acl_list_str_cfg(acl, "::0/0", "refuse", 0))
return 0;
if(!acl_list_str_cfg(acl, "::1", "allow", 0))
return 0;
if(!acl_list_str_cfg(acl, "::ffff:127.0.0.1", "allow", 0))
return 0;
}
acl_list_init_parents(acl);
return 1;
}
+104 -6
View File
@@ -53,6 +53,7 @@
#include "services/localzone.h"
#include "services/modstack.h"
#include "util/module.h"
#include "util/random.h"
#include <signal.h>
/** How many quit requests happened. */
@@ -75,13 +76,24 @@ static RETSIGTYPE record_sigh(int sig)
switch(sig)
{
case SIGTERM:
#ifdef SIGQUIT
case SIGQUIT:
#endif
#ifdef SIGBREAK
case SIGBREAK:
#endif
case SIGINT:
sig_record_quit++;
break;
#ifdef SIGHUP
case SIGHUP:
sig_record_reload++;
break;
#endif
#ifdef SIGPIPE
case SIGPIPE:
break;
#endif
default:
log_err("ignoring signal %d", sig);
}
@@ -95,9 +107,20 @@ static void
signal_handling_record()
{
if( signal(SIGTERM, record_sigh) == SIG_ERR ||
#ifdef SIGQUIT
signal(SIGQUIT, record_sigh) == SIG_ERR ||
signal(SIGINT, record_sigh) == SIG_ERR ||
signal(SIGHUP, record_sigh) == SIG_ERR)
#endif
#ifdef SIGBREAK
signal(SIGBREAK, record_sigh) == SIG_ERR ||
#endif
#ifdef SIGHUP
signal(SIGHUP, record_sigh) == SIG_ERR ||
#endif
#ifdef SIGPIPE
signal(SIGPIPE, SIG_IGN) == SIG_ERR ||
#endif
signal(SIGINT, record_sigh) == SIG_ERR
)
log_err("install sighandler: %s", strerror(errno));
}
@@ -108,8 +131,10 @@ signal_handling_record()
static void
signal_handling_playback(struct worker* wrk)
{
#ifdef SIGHUP
if(sig_record_reload)
worker_sighandler(SIGHUP, wrk);
#endif
if(sig_record_quit)
worker_sighandler(SIGTERM, wrk);
sig_record_quit = 0;
@@ -121,11 +146,26 @@ daemon_init()
{
struct daemon* daemon = (struct daemon*)calloc(1,
sizeof(struct daemon));
#ifdef USE_WINSOCK
int r;
WSADATA wsa_data;
#endif
if(!daemon)
return NULL;
#ifdef USE_WINSOCK
r = WSAStartup(MAKEWORD(2,2), &wsa_data);
if(r != 0) {
fatal_exit("could not init winsock. WSAStartup: %s",
wsa_strerror(r));
}
#endif /* USE_WINSOCK */
signal_handling_record();
checklock_start();
ERR_load_crypto_strings();
#ifdef HAVE_TZSET
/* init timezone info while we are not chrooted yet */
tzset();
#endif
daemon->need_to_exit = 0;
modstack_init(&daemon->mods);
if(!(daemon->env = (struct module_env*)calloc(1,
@@ -172,23 +212,74 @@ static void daemon_setup_modules(struct daemon* daemon)
}
}
/**
* Obtain allowed port numbers, concatenate the list, and shuffle them
* (ready to be handed out to threads).
* @param daemon: the daemon. Uses rand and cfg.
* @param shufport: the portlist output.
* @return number of ports available.
*/
int daemon_get_shufport(struct daemon* daemon, int* shufport)
{
int i, n, k, temp;
int avail = 0;
for(i=0; i<65536; i++) {
if(daemon->cfg->outgoing_avail_ports[i]) {
shufport[avail++] = daemon->cfg->
outgoing_avail_ports[i];
}
}
if(avail == 0)
fatal_exit("no ports are permitted for UDP, add "
"with outgoing-port-permit");
/* Knuth shuffle */
n = avail;
while(--n > 0) {
k = ub_random(daemon->rand) % (n+1); /* 0<= k<= n */
temp = shufport[k];
shufport[k] = shufport[n];
shufport[n] = temp;
}
return avail;
}
/**
* Allocate empty worker structures. With backptr and thread-number,
* from 0..numthread initialised. Used as user arguments to new threads.
* Creates the daemon random generator if it does not exist yet.
* The random generator stays existing between reloads with a unique state.
* @param daemon: the daemon with (new) config settings.
*/
static void
daemon_create_workers(struct daemon* daemon)
{
int i;
int i, numport;
int* shufport;
log_assert(daemon && daemon->cfg);
if(!daemon->rand) {
unsigned int seed = (unsigned int)time(NULL) ^
(unsigned int)getpid() ^ 0x438;
daemon->rand = ub_initstate(seed, NULL);
if(!daemon->rand)
fatal_exit("could not init random generator");
}
shufport = (int*)calloc(65536, sizeof(int));
if(!shufport)
fatal_exit("out of memory during daemon init");
numport = daemon_get_shufport(daemon, shufport);
verbose(VERB_ALGO, "total of %d outgoing ports available", numport);
daemon->num = daemon->cfg->num_threads;
daemon->workers = (struct worker**)calloc((size_t)daemon->num,
sizeof(struct worker*));
for(i=0; i<daemon->num; i++) {
if(!(daemon->workers[i] = worker_create(daemon, i)))
if(!(daemon->workers[i] = worker_create(daemon, i,
shufport+numport*i/daemon->num,
numport*(i+1)/daemon->num - numport*i/daemon->num)))
/* the above is not ports/numthr, due to rounding */
fatal_exit("could not create worker");
}
free(shufport);
}
/**
@@ -223,7 +314,7 @@ thread_start(void* arg)
struct worker* worker = (struct worker*)arg;
log_thread_set(&worker->thread_num);
ub_thread_blocksigs();
#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
#ifdef THREADS_DISABLED
/* close pipe ends used by main */
close(worker->cmd_send_fd);
worker->cmd_send_fd = -1;
@@ -250,7 +341,7 @@ daemon_start_others(struct daemon* daemon)
for(i=1; i<daemon->num; i++) {
ub_thread_create(&daemon->workers[i]->thr_id,
thread_start, daemon->workers[i]);
#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
#ifdef THREADS_DISABLED
/* close pipe end of child */
close(daemon->workers[i]->cmd_recv_fd);
daemon->workers[i]->cmd_recv_fd = -1;
@@ -363,6 +454,7 @@ daemon_delete(struct daemon* daemon)
rrset_cache_delete(daemon->env->rrset_cache);
infra_delete(daemon->env->infra_cache);
}
ub_randfree(daemon->rand);
alloc_clear(&daemon->superalloc);
acl_list_delete(daemon->acl);
free(daemon->pidfile);
@@ -377,4 +469,10 @@ daemon_delete(struct daemon* daemon)
ERR_free_strings();
RAND_cleanup();
checklock_stop();
#ifdef USE_WINSOCK
if(WSACleanup() != 0) {
log_err("Could not WSACleanup: %s",
wsa_strerror(WSAGetLastError()));
}
#endif
}
+3
View File
@@ -53,6 +53,7 @@ struct module_env;
struct rrset_cache;
struct acl_list;
struct local_zones;
struct ub_randstate;
/**
* Structure holding worker list.
@@ -73,6 +74,8 @@ struct daemon {
struct worker** workers;
/** do we need to exit unbound (or is it only a reload?) */
int need_to_exit;
/** master random table ; used for port div between threads on reload*/
struct ub_randstate* rand;
/** master allocation cache */
struct alloc_cache superalloc;
/** the module environment master value, copied and changed by threads*/
+4 -2
View File
@@ -59,10 +59,12 @@ void server_stats_querymiss(struct server_stats* stats, struct worker* worker)
void server_stats_log(struct server_stats* stats, int threadnum)
{
log_info("server stats for thread %d: %u queries, %u from cache",
log_info("server stats for thread %d: %u queries, "
"%u answers from cache, %u recursions",
threadnum, (unsigned)stats->num_queries,
(unsigned)(stats->num_queries -
stats->num_queries_missed_cache));
stats->num_queries_missed_cache),
(unsigned)stats->num_queries_missed_cache);
log_info("server stats for thread %d: requestlist max %u avg %g "
"exceeded %u", threadnum, (unsigned)stats->max_query_list_size,
stats->num_queries_missed_cache?
+116 -22
View File
@@ -52,8 +52,23 @@
#include "util/module.h"
#include <signal.h>
#include <fcntl.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#ifdef USE_MINI_EVENT
# ifdef USE_WINSOCK
# include "util/winsock_event.h"
# else
# include "util/mini_event.h"
# endif
#else
# include <event.h>
#endif
/** global debug value to keep track of heap memory allocation */
void* unbound_start_brk = 0;
@@ -69,6 +84,8 @@ static void usage()
printf("-d do not fork into the background.\n");
printf("-v verbose (more times to increase verbosity)\n");
printf("Version %s\n", PACKAGE_VERSION);
printf("libevent %s, libldns %s\n",
event_get_version(), ldns_version());
printf("BSD licensed, see LICENSE in source package for details.\n");
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
}
@@ -77,23 +94,28 @@ static void usage()
static void
checkrlimits(struct config_file* cfg)
{
#ifdef HAVE_GETRLIMIT
int list = ((cfg->do_ip4?1:0) + (cfg->do_ip6?1:0)) *
((cfg->do_udp?1:0) + (cfg->do_tcp?1 +
(int)cfg->incoming_num_tcp:0));
size_t ifs = (size_t)(cfg->num_ifs==0?1:cfg->num_ifs);
size_t listen_num = list*ifs;
size_t out_ifs = (size_t)(cfg->num_out_ifs==0?1:cfg->num_out_ifs);
size_t outnum = cfg->outgoing_num_ports*out_ifs + cfg->outgoing_num_tcp;
size_t outudpnum = (size_t)cfg->outgoing_num_ports;
size_t outtcpnum = cfg->outgoing_num_tcp;
size_t misc = 4; /* logfile, pidfile, stdout... */
size_t perthread = listen_num + outnum + 2/*cmdpipe*/ + 2/*libevent*/
+ misc;
size_t perthread_noudp = listen_num + outtcpnum +
2/*cmdpipe*/ + 2/*libevent*/ + misc;
size_t perthread = perthread_noudp + outudpnum;
#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
int numthread = 1; /* it forks */
#else
int numthread = cfg->num_threads;
#endif
size_t total = numthread * perthread + misc;
size_t avail;
struct rlimit rlim;
if(getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
log_warn("getrlimit: %s", strerror(errno));
return;
@@ -101,14 +123,42 @@ checkrlimits(struct config_file* cfg)
if(rlim.rlim_cur == (rlim_t)RLIM_INFINITY)
return;
if((size_t)rlim.rlim_cur < total) {
log_err("Not enough sockets available. Increase "
"ulimit(open files).");
log_err("or decrease number of threads, outgoing num ports, "
"outgoing num tcp or number of interfaces");
log_err("estimate %u fds high mark, %u available",
(unsigned)total, (unsigned)rlim.rlim_cur);
fatal_exit("Not enough file descriptors available");
avail = (size_t)rlim.rlim_cur;
rlim.rlim_cur = (rlim_t)(total + 10);
rlim.rlim_max = (rlim_t)(total + 10);
if(setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
log_warn("setrlimit: %s", strerror(errno));
log_warn("cannot increase max open fds from %u to %u",
(unsigned)avail, (unsigned)total+10);
cfg->outgoing_num_ports = (int)((avail
- numthread*perthread_noudp
- 10 /* safety margin */) /numthread);
log_warn("continuing with less udp ports: %u",
cfg->outgoing_num_ports);
log_warn("increase ulimit or decrease threads, ports in config to remove this warning");
return;
}
log_warn("increased limit(open files) from %u to %u",
(unsigned)avail, (unsigned)total+10);
}
if(total > 1024 &&
strncmp(event_get_version(), "mini-event", 10) == 0) {
log_err("too many file descriptors requested. The builtin"
"mini-event cannot handle more than 1024. Config "
"for less fds or compile with libevent");
fatal_exit("configuration needs too many file descriptors");
}
if(perthread > 64 &&
strncmp(event_get_version(), "winsock-event", 13) == 0) {
log_err("too many file descriptors requested. The winsock"
" event handler cannot handle more than 64 per "
" thread. Config for less fds or compile with "
" libevent");
fatal_exit("configuration needs too many file descriptors");
}
#else
(void)cfg;
#endif /* HAVE_GETRLIMIT */
}
/** set verbosity, check rlimits, cache settings */
@@ -141,6 +191,7 @@ apply_settings(struct daemon* daemon, struct config_file* cfg,
checkrlimits(cfg);
}
#ifdef HAVE_KILL
/** Read existing pid from pidfile.
* @param file: file name of pid file.
* @return: the pid from the file or -1 if none.
@@ -228,11 +279,13 @@ checkoldpid(struct config_file* cfg)
(unsigned)old);
}
}
#endif /* HAVE_KILL */
/** detach from command line */
static void
detach(struct config_file* cfg)
{
#ifdef HAVE_WORKING_FORK
int fd;
/* Take off... */
switch (fork()) {
@@ -246,8 +299,10 @@ detach(struct config_file* cfg)
exit(0);
}
/* detach */
#ifdef HAVE_SETSID
if(setsid() == -1)
fatal_exit("setsid() failed: %s", strerror(errno));
#endif
if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
(void)dup2(fd, STDIN_FILENO);
(void)dup2(fd, STDOUT_FILENO);
@@ -255,12 +310,17 @@ detach(struct config_file* cfg)
if (fd > 2)
(void)close(fd);
}
#else
(void)cfg;
#endif /* HAVE_WORKING_FORK */
}
/** daemonize, drop user priviliges and chroot if needed */
static void
do_chroot(struct daemon* daemon, struct config_file* cfg, int debug_mode)
do_chroot(struct daemon* daemon, struct config_file* cfg, int debug_mode,
char** cfgfile)
{
#ifdef HAVE_GETPWNAM
uid_t uid;
gid_t gid;
/* initialize, but not to 0 (root) */
@@ -269,13 +329,6 @@ do_chroot(struct daemon* daemon, struct config_file* cfg, int debug_mode)
log_assert(cfg);
/* daemonize last to be able to print error to user */
if(cfg->directory && cfg->directory[0]) {
if(chdir(cfg->directory)) {
fatal_exit("Could not chdir to %s: %s",
cfg->directory, strerror(errno));
}
verbose(VERB_QUERY, "chdir to %s", cfg->directory);
}
if(cfg->username && cfg->username[0]) {
struct passwd *pwd;
if((pwd = getpwnam(cfg->username)) == NULL)
@@ -284,12 +337,40 @@ do_chroot(struct daemon* daemon, struct config_file* cfg, int debug_mode)
gid = pwd->pw_gid;
endpwent();
}
#endif
#ifdef HAVE_CHROOT
if(cfg->chrootdir && cfg->chrootdir[0]) {
if(chdir(cfg->chrootdir)) {
fatal_exit("unable to chdir to chroot %s: %s",
cfg->chrootdir, strerror(errno));
}
verbose(VERB_QUERY, "chdir to %s", cfg->chrootdir);
if(chroot(cfg->chrootdir))
fatal_exit("unable to chroot to %s: %s",
cfg->chrootdir, strerror(errno));
verbose(VERB_QUERY, "chroot to %s", cfg->chrootdir);
if(strncmp(*cfgfile, cfg->chrootdir,
strlen(cfg->chrootdir)) == 0)
(*cfgfile) += strlen(cfg->chrootdir);
}
#else
(void)cfgfile;
#endif
if(cfg->directory && cfg->directory[0]) {
char* dir = cfg->directory;
if(cfg->chrootdir && cfg->chrootdir[0] &&
strncmp(dir, cfg->chrootdir,
strlen(cfg->chrootdir)) == 0)
dir += strlen(cfg->chrootdir);
if(dir[0]) {
if(chdir(dir)) {
fatal_exit("Could not chdir to %s: %s",
dir, strerror(errno));
}
verbose(VERB_QUERY, "chdir to %s", dir);
}
}
#ifdef HAVE_GETPWNAM
if(cfg->username && cfg->username[0]) {
if(setgid(gid) != 0)
fatal_exit("unable to set group id of %s: %s",
@@ -300,16 +381,20 @@ do_chroot(struct daemon* daemon, struct config_file* cfg, int debug_mode)
verbose(VERB_QUERY, "drop user privileges, run as %s",
cfg->username);
}
#endif
#ifdef HAVE_KILL
/* check old pid file before forking */
if(cfg->pidfile && cfg->pidfile[0]) {
checkoldpid(cfg);
}
#endif
/* init logfile just before fork */
log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
if(!debug_mode && cfg->do_daemonize) {
detach(cfg);
}
#ifdef HAVE_KILL
if(cfg->pidfile && cfg->pidfile[0]) {
char* pf = cfg->pidfile;
if(cfg->chrootdir && cfg->chrootdir[0] &&
@@ -319,6 +404,9 @@ do_chroot(struct daemon* daemon, struct config_file* cfg, int debug_mode)
if(!(daemon->pidfile = strdup(pf)))
log_err("pidf: malloc failed");
}
#else
(void)daemon;
#endif
}
/**
@@ -345,15 +433,19 @@ run_daemon(char* cfgfile, int cmdline_verbose, int debug_mode)
/* config stuff */
if(!(cfg = config_create()))
fatal_exit("Could not alloc config defaults");
if(!config_read(cfg, cfgfile))
fatal_exit("Could not read config file: %s", cfgfile);
if(!config_read(cfg, cfgfile)) {
if(errno != ENOENT)
fatal_exit("Could not read config file: %s",
cfgfile);
log_warn("Continuing with default config settings");
}
apply_settings(daemon, cfg, cmdline_verbose);
/* prepare */
if(!daemon_open_shared_ports(daemon))
fatal_exit("could not open ports");
if(!done_chroot) {
do_chroot(daemon, cfg, debug_mode);
do_chroot(daemon, cfg, debug_mode, &cfgfile);
done_chroot = 1;
} else log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
/* work */
@@ -389,8 +481,10 @@ main(int argc, char* argv[])
int cmdline_verbose = 0;
int debug_mode = 0;
#ifdef HAVE_SBRK
/* take debug snapshot of heap */
unbound_start_brk = sbrk(0);
#endif
log_init(NULL, 0, NULL);
/* parse the options */
+76 -29
View File
@@ -67,7 +67,9 @@
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#include <signal.h>
/** Size of an UDP datagram */
@@ -102,6 +104,7 @@ debug_memleak(size_t accounted, size_t heap,
static void
debug_total_mem(size_t calctotal)
{
#ifdef HAVE_SBRK
extern void* unbound_start_brk;
extern size_t unbound_mem_alloc, unbound_mem_freed;
void* cur = sbrk(0);
@@ -111,6 +114,9 @@ debug_total_mem(size_t calctotal)
(unsigned)unbound_mem_alloc, (unsigned)unbound_mem_freed);
debug_memleak(calctotal, (size_t)total,
unbound_mem_alloc, unbound_mem_freed);
#else
(void)calctotal;
#endif /* HAVE_SBRK */
}
#endif /* UNBOUND_ALLOC_STATS */
@@ -137,7 +143,7 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
iter = 0;
val = 0;
for(i=0; i<worker->env.mesh->mods.num; i++) {
log_assert(fptr_whitelist_mod_get_mem(worker->env.mesh->
fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh->
mods.mod[i]->get_mem));
if(strcmp(worker->env.mesh->mods.mod[i]->name, "validator")==0)
val += (*worker->env.mesh->mods.mod[i]->get_mem)
@@ -169,7 +175,7 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
if(verbosity < VERB_QUERY)
return;
for(i=0; i<worker->env.mesh->mods.num; i++) {
log_assert(fptr_whitelist_mod_get_mem(worker->env.mesh->
fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh->
mods.mod[i]->get_mem));
if(strcmp(worker->env.mesh->mods.mod[i]->name, "validator")==0)
val += (*worker->env.mesh->mods.mod[i]->get_mem)
@@ -406,7 +412,7 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
*/
uint16_t udpsize = edns->udp_size;
int secure = 0;
uint32_t timenow = (uint32_t)time(0);
uint32_t timenow = *worker->env.now;
int must_validate = !(flags&BIT_CD) && worker->env.need_to_validate;
struct dns_msg *msg = NULL;
struct delegpt *dp;
@@ -505,12 +511,11 @@ all_rrsets_secure(struct reply_info* rep) {
/** answer query from the cache */
static int
answer_from_cache(struct worker* worker, struct lruhash_entry* e, uint16_t id,
uint16_t flags, struct comm_reply* repinfo, struct edns_data* edns)
answer_from_cache(struct worker* worker, struct query_info* qinfo,
struct reply_info* rep, uint16_t id, uint16_t flags,
struct comm_reply* repinfo, struct edns_data* edns)
{
struct msgreply_entry* mrentry = (struct msgreply_entry*)e->key;
struct reply_info* rep = (struct reply_info*)e->data;
uint32_t timenow = time(0);
uint32_t timenow = *worker->env.now;
uint16_t udpsize = edns->udp_size;
int secure;
int must_validate = !(flags&BIT_CD) && worker->env.need_to_validate;
@@ -547,7 +552,7 @@ answer_from_cache(struct worker* worker, struct lruhash_entry* e, uint16_t id,
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
&mrentry->key, id, flags, edns);
qinfo, id, flags, edns);
rrset_array_unlock_touch(worker->env.rrset_cache,
worker->scratchpad, rep->ref, rep->rrset_count);
regional_free_all(worker->scratchpad);
@@ -573,11 +578,11 @@ answer_from_cache(struct worker* worker, struct lruhash_entry* e, uint16_t id,
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
if(!reply_info_answer_encode(&mrentry->key, rep, id, flags,
if(!reply_info_answer_encode(qinfo, rep, id, flags,
repinfo->c->buffer, timenow, 1, worker->scratchpad,
udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
&mrentry->key, id, flags, edns);
qinfo, id, flags, edns);
}
/* cannot send the reply right now, because blocking network syscall
* is bad while holding locks. */
@@ -787,7 +792,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
h = query_info_hash(&qinfo);
if((e=slabhash_lookup(worker->env.msg_cache, h, &qinfo, 0))) {
/* answer from cache - we have acquired a readlock on it */
if(answer_from_cache(worker, e,
if(answer_from_cache(worker, &qinfo,
(struct reply_info*)e->data,
*(uint16_t*)ldns_buffer_begin(c->buffer),
ldns_buffer_read_u16_at(c->buffer, 2), repinfo,
&edns)) {
@@ -817,6 +823,12 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
worker->stats.num_query_list_exceeded++;
comm_point_drop_reply(repinfo);
return 0;
} else if(worker->env.mesh->num_reply_addrs>worker->request_size*16) {
verbose(VERB_ALGO, "Too many requests queued. "
"dropping incoming query.");
worker->stats.num_query_list_exceeded++;
comm_point_drop_reply(repinfo);
return 0;
}
mesh_new_client(worker->env.mesh, &qinfo,
ldns_buffer_read_u16_at(c->buffer, 2),
@@ -834,20 +846,24 @@ worker_sighandler(int sig, void* arg)
* in the cause for unbound to exit */
struct worker* worker = (struct worker*)arg;
switch(sig) {
#ifdef SIGHUP
case SIGHUP:
verbose(VERB_QUERY, "caught signal SIGHUP");
comm_base_exit(worker->base);
break;
#endif
case SIGINT:
verbose(VERB_QUERY, "caught signal SIGINT");
worker->need_to_exit = 1;
comm_base_exit(worker->base);
break;
#ifdef SIGQUIT
case SIGQUIT:
verbose(VERB_QUERY, "caught signal SIGQUIT");
worker->need_to_exit = 1;
comm_base_exit(worker->base);
break;
#endif
case SIGTERM:
verbose(VERB_QUERY, "caught signal SIGTERM");
worker->need_to_exit = 1;
@@ -874,22 +890,30 @@ worker_restart_timer(struct worker* worker)
void worker_stat_timer_cb(void* arg)
{
struct worker* worker = (struct worker*)arg;
mesh_stats(worker->env.mesh, "mesh has");
server_stats_log(&worker->stats, worker->thread_num);
mesh_stats(worker->env.mesh, "mesh has");
worker_mem_report(worker, NULL);
server_stats_init(&worker->stats);
mesh_stats_clear(worker->env.mesh);
if(!worker->daemon->cfg->stat_cumulative) {
server_stats_init(&worker->stats);
mesh_stats_clear(worker->env.mesh);
}
/* start next timer */
worker_restart_timer(worker);
}
struct worker*
worker_create(struct daemon* daemon, int id)
worker_create(struct daemon* daemon, int id, int* ports, int n)
{
struct worker* worker = (struct worker*)calloc(1,
sizeof(struct worker));
if(!worker)
return NULL;
worker->numports = n;
worker->ports = (int*)memdup(ports, sizeof(int)*n);
if(!worker->ports) {
free(worker);
return NULL;
}
worker->daemon = daemon;
worker->thread_num = id;
worker->cmd_send_fd = -1;
@@ -919,7 +943,6 @@ worker_init(struct worker* worker, struct config_file *cfg,
struct listen_port* ports, int do_sigs)
{
unsigned int seed;
int startport;
worker->need_to_exit = 0;
worker->base = comm_base_create();
if(!worker->base) {
@@ -928,17 +951,26 @@ worker_init(struct worker* worker, struct config_file *cfg,
return 0;
}
if(do_sigs) {
#ifdef SIGHUP
ub_thread_sig_unblock(SIGHUP);
#endif
ub_thread_sig_unblock(SIGINT);
#ifdef SIGQUIT
ub_thread_sig_unblock(SIGQUIT);
#endif
ub_thread_sig_unblock(SIGTERM);
#ifndef LIBEVENT_SIGNAL_PROBLEM
worker->comsig = comm_signal_create(worker->base,
worker_sighandler, worker);
if(!worker->comsig || !comm_signal_bind(worker->comsig, SIGHUP)
|| !comm_signal_bind(worker->comsig, SIGINT)
if(!worker->comsig
#ifdef SIGHUP
|| !comm_signal_bind(worker->comsig, SIGHUP)
#endif
#ifdef SIGQUIT
|| !comm_signal_bind(worker->comsig, SIGQUIT)
#endif
|| !comm_signal_bind(worker->comsig, SIGTERM)
|| !comm_signal_bind(worker->comsig, SIGQUIT)) {
|| !comm_signal_bind(worker->comsig, SIGINT)) {
log_err("could not create signal handlers");
worker_delete(worker);
return 0;
@@ -965,13 +997,12 @@ worker_init(struct worker* worker, struct config_file *cfg,
worker_delete(worker);
return 0;
}
startport = cfg->outgoing_base_port +
cfg->outgoing_num_ports * worker->thread_num;
worker->back = outside_network_create(worker->base,
cfg->msg_buffer_size, (size_t)cfg->outgoing_num_ports,
cfg->out_ifs, cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6,
startport, cfg->do_tcp?cfg->outgoing_num_tcp:0,
worker->daemon->env->infra_cache, worker->rndstate);
cfg->do_tcp?cfg->outgoing_num_tcp:0,
worker->daemon->env->infra_cache, worker->rndstate,
cfg->use_caps_bits_for_id, worker->ports, worker->numports);
if(!worker->back) {
log_err("could not create outgoing sockets");
worker_delete(worker);
@@ -1008,6 +1039,9 @@ worker_init(struct worker* worker, struct config_file *cfg,
worker->thread_num);
alloc_set_id_cleanup(&worker->alloc, &worker_alloc_cleanup, worker);
worker->env = *worker->daemon->env;
comm_base_timept(worker->base, &worker->env.now, &worker->env.now_tv);
if(worker->thread_num == 0)
log_set_time(worker->env.now);
worker->env.worker = worker;
worker->env.send_packet = &worker_send_packet;
worker->env.send_query = &worker_send_query;
@@ -1046,8 +1080,8 @@ worker_delete(struct worker* worker)
if(!worker)
return;
if(worker->env.mesh && verbosity >= VERB_OPS) {
mesh_stats(worker->env.mesh, "mesh has");
server_stats_log(&worker->stats, worker->thread_num);
mesh_stats(worker->env.mesh, "mesh has");
worker_mem_report(worker, NULL);
}
mesh_delete(worker->env.mesh);
@@ -1057,6 +1091,9 @@ worker_delete(struct worker* worker)
comm_signal_delete(worker->comsig);
comm_point_delete(worker->cmd_com);
comm_timer_delete(worker->stat_timer);
free(worker->ports);
if(worker->thread_num == 0)
log_set_time(NULL);
comm_base_delete(worker->base);
ub_randfree(worker->rndstate);
/* close fds after deleting commpoints, to be sure.
@@ -1079,12 +1116,10 @@ worker_send_packet(ldns_buffer* pkt, struct sockaddr_storage* addr,
struct worker* worker = q->env->worker;
if(use_tcp) {
return pending_tcp_query(worker->back, pkt, addr, addrlen,
timeout, worker_handle_reply, q,
worker->rndstate) != 0;
timeout, worker_handle_reply, q) != 0;
}
return pending_udp_query(worker->back, pkt, addr, addrlen,
timeout*1000, worker_handle_reply, q,
worker->rndstate) != 0;
timeout*1000, worker_handle_reply, q) != 0;
}
/** compare outbound entry qstates */
@@ -1169,3 +1204,15 @@ int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
log_assert(0);
return 0;
}
int order_lock_cmp(const void* ATTR_UNUSED(e1), const void* ATTR_UNUSED(e2))
{
log_assert(0);
return 0;
}
int codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
{
log_assert(0);
return 0;
}
+7 -1
View File
@@ -86,6 +86,10 @@ struct worker {
struct listen_dnsport* front;
/** the backside outside network interface to the auth servers */
struct outside_network* back;
/** ports to be used by this worker. */
int* ports;
/** number of ports for this worker */
int numports;
/** the signal handler */
struct comm_signal* comsig;
/** commpoint to listen to commands. */
@@ -116,9 +120,11 @@ struct worker {
* with backpointers only. Use worker_init on it later.
* @param daemon: the daemon that this worker thread is part of.
* @param id: the thread number from 0.. numthreads-1.
* @param ports: the ports it is allowed to use, array.
* @param n: the number of ports.
* @return: the new worker or NULL on alloc failure.
*/
struct worker* worker_create(struct daemon* daemon, int id);
struct worker* worker_create(struct daemon* daemon, int id, int* ports, int n);
/**
* Initialize worker.
+8 -4
View File
@@ -1,10 +1,14 @@
Unbound was developed at NLnet Labs by Wouter Wijngaards.
Unbound was devised by Bill Manning, David Blacka, and Matt Larson
from the University of California and from Verisign. The Java prototype
was made in further cooperation with Geoff Sisson and Roy Arends from Nominet.
Unbound was architected in January of 2004 by Jakob Schlyter of Kirei
and Roy Arends of Nominet. VeriSign and EP.Net funded development of
the prototype, which was built by David Blacka and Matt Larson of VeriSign.
Late in 2006, NLnet Labs joined the effort, writing an implementation in C
based on the existing prototype and using experience NLnet Labs gained
during the development of NSD, an authoritative DNS server.
At NLnet Labs, Jelte Jansen and Mark Santcroos reviewed the unbound C sources.
At NLnet Labs, Jelte Jansen, Mark Santcroos and Matthijs Mekking
reviewed the unbound C sources.
Jakob Schlyter - for advice on secure settings, random numbers and blacklists.
+455
View File
@@ -1,7 +1,462 @@
6 August 2008: Wouter
- patch for scrubber that removes ends of CNAMEs, no more DNAMEs
from cache. Remove more irrelevant rrsets from the message.
5 August 2008: Wouter
- fixup DS test so apex nodata works again (from trunk).
4 August 2008: Wouter
- Bug #201 fixup from trunk; fixes segfault on exit cleanup
- iana port nrs updated.
30 July 2008: Wouter
- fixup DS qtype validation bug. (fix taken from trunk).
21 July 2008: Wouter
- #198: nicer entropy warning message. manpage OS hints.
19 July 2008: Wouter
- #198: fixup manpage to suggest entropy chroot fix.
18 July 2008: Wouter
- branch for 1.0 support.
17 July 2008: Wouter
- fix bug #196, compile outside source tree.
- fix bug #195, add --with-username=user configure option.
- print error and exit if started with config that requires more
fds than the builtin minievent can handle.
16 July 2008: Wouter
- made svn tag 1.0.1, trunk now 1.0.2
- sha256 checksums enabled in makedist.sh
15 July 2008: Wouter
- Follow draft-ietf-dnsop-default-local-zones-06 added reverse
IPv6 example prefix to AS112 default blocklist.
- fixup lookup of DS records by client with trustanchor for same.
- libunbound ub_resolve, fix handling of error condition during setup.
- lowered log_hex blocksize to fit through BSD syslog linesize.
- no useless initialisation if getpwnam not available.
- iana, ldns snapshot updated.
3 July 2008: Wouter
- Matthijs fixed memory leaks in root hints file reading.
26 June 2008: Wouter
- fixup streamtcp bounds setting for udp mode, in the test framework.
- contrib item for updating trust anchors.
25 June 2008: Wouter
- fixup fwd_ancil test typos.
- Fix for newegg lameness : ok for qtype=A, but lame for others.
- fixup unit test for infra cache, test lame merging.
- porting to mingw, bind, listen, getsockopt and setsockopt error
handling.
24 June 2008: Wouter
- removed testcode/checklocks from production code compilation path.
- streamtcp can use UDP mode (connected UDP socket), for testing IPv6
on windows.
- fwd_ancil test fails if platform support is lacking.
23 June 2008: Wouter
- fixup minitpkg to cleanup on windows with its file locking troubles.
- minitpkg shows skipped tests in report.
- skip ipv6 tests on ipv4 only hosts (requires only ipv6 localhost not
ipv6 connectivity).
- winsock event handler keeps track of sticky TCP events, that have
not been fully handled yet. when interest in the event(s) resumes,
they are sent again. When WOULDBLOCK is returned events are cleared.
- skip tests that need signals when testing on mingw.
18 June 2008: Wouter
- open testbound replay files in binary mode, because fseek/ftell
do not work in ascii-mode on windows. The b does nothing on unix.
unittest and testbound tests work on windows (xp too).
- ioctlsocket prints nicer error message.
- fixed up some TCP porting for winsock.
- lack of IPv6 gives a warning, no fatal error.
- use WSAGetLastError() on windows instead of errno for some errors.
17 June 2008: Wouter
- outgoing num fds 32 by default on windows ; it supports less
fds for waiting on than unixes.
- winsock_event minievent handler for windows. (you could also
attempt to link with libevent/libev ports for windows).
- neater crypto check and gdi32 detection.
- unbound.exe works to resolve and validate www.nlnetlabs.nl on vista.
16 June 2008: Wouter
- on windows, use windows threads, mutex and thread-local-storage(Tls).
- detect if openssl needs gdi32.
- if no threading, THREADS_DISABLED is defined for use in the code.
- sets USE_WINSOCK if using ws2_32 on windows.
- wsa_strerror() function for more readable errors.
- WSA Startup and Cleanup called in unbound.exe.
13 June 2008: Wouter
- port mingw32, more signal ifdefs, detect sleep, usleep,
random, srandom (used inside the tests).
- signed or unsigned FD_SET is cast.
10 June 2008: Wouter
- fixup warnings compiling on eeepc xandros linux.
9 June 2008: Wouter
- in iteration response type code
* first check for SOA record (negative answer) before NS record
and lameness.
* check if no AA bit for non-forwarder, and thus lame zone.
In response to error report by Richard Doty for mail.opusnet.com.
- fixup unput warning from lexer on freeBSD.
- bug#183. pidfile, rundir, and chroot configure options. Also the
example.conf and manual pages get the configured defaults.
You can use: (or accept the defaults to /usr/local/etc/unbound/)
--with-conf-file=filename
--with-pidfile=filename
--with-run-dir=path
--with-chroot-dir=path
8 June 2008: Wouter
- if multiple CNAMEs, use the first one. Fixup akamai CNAME bug.
Reported by Robert Edmonds.
- iana port updated.
4 June 2008: Wouter
- updated libtool files with newer version.
- iana portlist updated.
3 June 2008: Wouter
- fixup local-zone: "30.172.in-addr.arpa." nodefault, so that the
trailing dot is not used during comparison.
2 June 2008: Wouter
- Jelte fixed bugs in my absence
- bug 178: fixed unportable shell usage in configure (relied on
bash shell).
- bug 180: fixed buffer overflow in unbound-checkconf use of strncat.
- bug 181: fixed buffer overflow in ldns (called by unbound to parse
config file parts).
- fixes by Wouter
- bug 177: fixed compilation failure on opensuse, the
--disable-static configure flag caused problems. (Patch from
Klaus Singvogel)
- bug 179: same fix as 177.
- bug 185: --disable-shared not passed along to ldns included with
unbound. Fixed so that configure parameters are passed to the
subdir configure script.
fixed that ./libtool is used always, you can still override
manually with ./configure libtool=mylibtool or set $libtool in
the environment.
- update of the ldns tarball to current ldns svn version (fix 181).
- bug 184: -r option for unbound-host, read resolv.conf for
forwarder. (Note that forwarder must support DNSSEC for validation
to succeed).
23 May 2008: Wouter
- mingw32 porting.
- test for sys/wait.h
- WSAEWOULDBLOCK test after nonblocking TCP connect.
- write_iov_buffer removed: unused and no struct iov on windows.
- signed/unsigned warning fixup mini_event.
- use ioctlsocket to set nonblocking I/O if fnctl is unavailable.
- skip signals that are not defined
- detect pwd.h.
- detect getpwnam, getrlimit, setsid, sbrk, chroot.
- default config has no chroot if chroot() unavailable.
- if no kill() then no pidfile is read or written.
- gmtime_r is replaced by nonthreadsafe alternative if unavail.
used in rrsig time validation errors.
22 May 2008: Wouter
- contrib unbound.spec from Patrick Vande Walle.
- fixup bug#175: call tzset before chroot to have correct timestamps
in system log.
- do not generate lex input and lex unput functions.
- mingw port. replacement functions labelled _unbound.
- fix bug 174 - check for tcp_sigpipe that ldns-testns is installed.
19 May 2008: Wouter
- fedora 9, check in6_pktinfo define in configure.
- CREDITS fixup of history.
- ignore ldns-1.2.2 if installed, use builtin 1.3.0-pre alternative.
16 May 2008: Wouter
- fixup for MacOSX hosts file reading (reported by John Dickinson).
- created 1.0.0 svn tag.
- trunk version 1.0.1.
14 May 2008: Wouter
- accepted patch from Ondrej Sury for library version libtool option.
- configure --disable-rpath fixes up libtool for rpath trouble.
Adapted from debian package patch file.
13 May 2008: Wouter
- Added root ipv6 addresses to builtin root hints.
- TODO modified for post 1.0 plans.
- trunk version set to 1.0.0.
- no unnecessary linking with librt (only when libevent/libev used).
7 May 2008: Wouter
- fixup no-ip4 problem with error callback in outside network.
25 April 2008: Wouter
- DESTDIR is honored by the Makefile for rpms.
- contrib files unbound.spec and unbound.init, builds working RPM
on FC7 Linux, a chrooted caching resolver, and libunbound.
- iana ports update.
24 April 2008: Wouter
- chroot checks improved. working directory relative to chroot.
checks if config file path is inside chroot. Documentation on it.
- nicer example.conf text.
- created 0.11 tag.
23 April 2008: Wouter
- parseunbound.pl contrib update from Kai Storbeck for threads.
- iana ports update
22 April 2008: Wouter
- ignore SIGPIPE.
- unit test for SIGPIPE ignore.
21 April 2008: Wouter
- FEATURES document.
- fixup reread of config file if it was given as a full path
and chroot was used.
16 April 2008: Wouter
- requirements doc, updated clean query returns.
- parseunbound.pl update from Kai Storbeck.
- sunos4 porting changes.
15 April 2008: Wouter
- fixup default rc.d pidfile location to /usr/local/etc.
- iana ports updated.
- copyright updated in ldns-testpkts to keep same as in ldns.
- fixup checkconf chroot tests a bit more, chdir must be inside
chroot dir.
- documented 'gcc: unrecognized -KPIC option' errors on Solaris.
- example.conf values changed to /usr/local/etc/unbound
- DSA test work.
- DSA signatures: unbound is compatible with both encodings found.
It will detect and convert when necessary.
14 April 2008: Wouter
- got update for parseunbound.pl statistics script from Kai Storbeck.
- tpkg tests for udp wait list.
- documented 0x20 status.
- fixup chroot and checkconf, it is much smarter now.
- fixup DSA EVP signature decoding. Solution that Jelte found copied.
- and check first sig byte for the encoding type.
11 April 2008: Wouter
- random port selection out of the configged ports.
- fixup threadsafety for libevent-1.4.3+ (event_base_get_method).
- removed base_port.
- created 256-port ephemeral space for the OS, 59802 available.
- fixup consistency of port_if out array during heavy use.
10 April 2008: Wouter
- --with-libevent works with latest libevent 1.4.99-trunk.
- added log file statistics perl script to contrib.
- automatic iana ports update from makefile. 60058 available.
9 April 2008: Wouter
- configure can detect libev(from its build directory) when passed
--with-libevent=/home/wouter/libev-3.2
libev-3.2 is a little faster than libevent-1.4.3-stable (about 5%).
- unused commpoints not listed in epoll list.
- statistics-cumulative option so that the values are not reset.
- config creates array of available ports, 61841 available,
it excludes <1024 and iana assigned numbers.
config statements to modify the available port numbers.
8 April 2008: Wouter
- unbound tries to set the ulimit fds when started as server.
if that does not work, it will scale back its requirements.
27 March 2008: Wouter
- documented /dev/random symlink from chrootdir as FAQ entry.
26 March 2008: Wouter
- implemented AD bit signaling. If a query sets AD bit (but not DO)
then the AD bit is set in the reply if the answer validated.
Without including DNSSEC signatures. Useful if you have a trusted
path from the client to the resolver. Follows dnssec-updates draft.
25 March 2008: Wouter
- implemented check that for NXDOMAIN and NOERROR answers a query
section must be present in the reply (by the scrubber). And it must
be equal to the question sent, at least lowercase folded.
Previously this feature happened because the cache code refused
to store such messages. However blocking by the scrubber makes
sure nothing gets into the RRset cache. Also, this looks like a
timeout (instead of an allocation failure) and this retries are
done (which is useful in a spoofing situation).
- RTT banding. Band size 400 msec, this makes band around zero (fast)
include unknown servers. This makes unbound explore unknown servers.
7 March 2008: Wouter
- -C config feature for harvest program.
- harvest handles CNAMEs too.
5 March 2008: Wouter
- patch from Hugo Koji Kobayashi for iterator logs spelling.
4 March 2008: Wouter
- From report by Jinmei Tatuya, rfc2181 trust value for remainder
of a cname trust chain is lower; not full answer_AA.
- test for this fix.
- default config file location is /usr/local/etc/unbound.
Thus prefix is used to determine the location. This is also the
chroot and pidfile default location.
3 March 2008: Wouter
- Create 0.10 svn tag.
- 0.11 version in trunk.
- indentation nicer.
29 February 2008: Wouter
- documentation update.
- fixup port to Solaris of perf test tool.
- updated ldns-tarball with decl-after-statement fixes.
28 February 2008: Wouter
- fixed memory leaks in libunbound (during cancellation and wait).
- libunbound returns the answer packet in full.
- snprintf compat update.
- harvest performs lookup.
- ldns-tarball update with fix for ldns_dname_label.
- installs to sbin by default.
- install all manual pages (unbound-host and libunbound too).
27 February 2008: Wouter
- option to use caps for id randomness.
- config file option use-caps-for-id: yes
- harvest debug tool
26 February 2008: Wouter
- delay utility delays TCP as well. If the server that is forwarded
to has a TCP error, the delay utility closes the connection.
- delay does REUSE_ADDR, and can handle a server that closes its end.
- answers use casing from query.
25 February 2008: Wouter
- delay utility works. Gets decent thoughput too (>20000).
22 February 2008: Wouter
- +2% for recursions, if identical queries (except for destination
and query ID) in the reply list, avoid re-encoding the answer.
- removed TODO items for optimizations that do not show up in
profile reports.
- default is now minievent - not libevent. As its faster and
not needed for regular installs, only for very large port ranges.
- loop check different speedup pkt-dname-reading, 1% faster for
nocache-recursion check.
- less hashing during msg parse, 4% for recursion.
- small speed fix for dname_count_size_labels, +1 or +2% recursion.
- some speed results noted:
optimization resulted in +40% for recursion (cache miss) and
+70 to +80 for cache hits, and +96% for version.bind.
zone nsec3 example, 100 NXDOMAIN queries, NSD 35182.8 Ub 36048.4
www.nlnetlabs.nl from cache: BIND 8987.99 Ub 31218.3
www with DO bit set : BIND 8269.31 Ub 28735.6 qps.
So, unbound can be about equal qps to NSD in cache hits.
And about 3.4x faster than BIND in cache performance.
- delay utility for testing.
21 February 2008: Wouter
- speedup of root-delegation message encoding by 15%.
- minor speedup of compress tree_lookup, maybe 1%.
- speedup of dname_lab_cmp and memlowercmp - the top functions in
profiler output, maybe a couple percent when it matters.
20 February 2008: Wouter
- setup speec_cache for need-ldns-testns in dotests.
- check number of queued replies on incoming queries to avoid overload
on that account.
- fptr whitelist checks are not disabled in optimize mode.
- do-daemonize config file option.
- minievent time share initializes time at start.
- updated testdata for nsec3 new algorithm numbers (6, 7).
- small performance test of packet encoding (root delegation).
19 February 2008: Wouter
- applied patch to unbound-host man page from Jan-Piet Mens.
- fix donotquery-localhost: yes default (it erroneously was switched
to default 'no').
- time is only gotten once and the value is shared across unbound.
- unittest cleans up crypto, so that it has no memory leaks.
- mini_event shares the time value with unbound this results in
+3% speed for cache responses and +9% for recursions.
- ldns tarball update with new NSEC3 sign code numbers.
- perform several reads per UDP operation. This improves performance
in DoS conditions, and costs very little in normal conditions.
improves cache response +50%, and recursions +10%.
- modified asynclook test. because the callback from async is not
in any sort of lock (and thus can use all library functions freely),
this causes a tiny race condition window when the last lock is
released for a callback and a new cancel() for that callback.
The only way to remove this is by putting callbacks into some
lock window. I'd rather have the small possibility of a callback
for a cancelled function then no use of library functions in
callbacks. Could be possible to only outlaw process(), wait(),
cancel() from callbacks, by adding another lock, but I'd rather not.
18 February 2008: Wouter
- patch to unbound-host from Jan-Piet Mens.
- unbound host prints errors if fails to configure context.
- fixup perf to resend faster, so that long waiting requests do
not hold up the queue, they become lost packets or SERVFAILs,
or can be sent a little while later (i.e. processing time may
take long, but throughput has to be high).
- fixup iterator operating in no cache conditions (RD flag unset
after a CNAME).
- streamlined code for RD flag setting.
- profiled code and changed dname compares to be faster.
The speedup is about +3% to +8% (depending on the test).
- minievent tests for eintr and eagain.
15 February 2008: Wouter
- added FreeBSD rc.d script to contrib.
- --prefix option for configure also changes directory: pidfile:
and chroot: defaults in config file.
- added cache speed test, for cache size OK and cache too small.
14 February 2008: Wouter
- start without a config file (will complain, but start with
defaults).
- perf test program works.
13 February 2008: Wouter
- 0.9 released.
- 1.0 development. Printout ldns version on unbound -h.
- start of perf tool.
- bugfix to read empty lines from /etc/hosts.
12 February 2008: Wouter
- fixup problem with configure calling itself if ldns-src tarball
is not present.
11 February 2008: Wouter
- changed library to use ub_ instead of ub_val_ as prefix.
- statistics output text nice.
- etc/hosts handling.
- library function to put logging to a stream.
- set any option interface.
8 February 2008: Wouter
- test program for multiple queries over a TCP channel.
- tpkg test for stream tcp queries.
- unbound replies to multiple TCP queries on a TCP channel.
- fixup misclassification of root referral with NS in answer
when validating a nonrec query.
- tag 0.9
- layout of manpages, spelling fix in header, manpages process by
makedist, list asynclook and tcpstream tests as ldns-testns
required.
7 February 2008: Wouter
- moved up all current level 2 to be level 3. And 3 to 4.
+91
View File
@@ -0,0 +1,91 @@
Unbound Features
(C) Copyright 2008, Wouter Wijngaards, NLnet Labs.
This document describes the features and RFCs that unbound
adheres to, and which ones are decided to be out of scope.
Big Features
------------
Recursive service.
Caching service.
Forwarding and stub zones.
No authoritative service.
DNSSEC Validation options.
EDNS0, NSEC3, Unknown-RR-types.
Details
-------
Processing support
RFC 1034-1035: as a recursive, caching server. Not authoritative.
including CNAMEs, referrals, wildcards, classes, ...
RFC 4033-4035: as a validating caching server (unbound daemon).
as a validating stub (libunbound).
RFC 1918.
RFC 2181: completely, including the trust model, keeping rrsets together.
RFC 2672: DNAME support.
RFC 3597: Unknown RR type support.
RFC 2671: EDNS0 support, default advertisement 4Kb size.
RFC 5155: NSEC3, NSEC3PARAM types
AAAA type. and IP6 dual stack support.
type ANY queries are supported.
RFC 2308: TTL directive, and the rest of the RFC too.
RFC 4592: wildcards.
RFC 1995, 1996, 2136: not authoritative, so no AXFR, IXFR, NOTIFY or
dynamic update services are appropriate.
chroot and drop-root-privileges support, default enabled in config file.
AD bit in query can be used to request AD bit in response (w/o using DO bit).
CD bit in query can be used to request bogus data.
UDP and TCP service is provided downstream.
UDP and TCP are used to request from upstream servers.
Multiple queries can be made over a TCP stream.
No TSIG support at this time.
No SIG0 support at this time.
No dTLS support at this time.
This is not a DNS statistics package, but some operationally useful
values are provided.
TXT RRs from the Chaos class (id.server, hostname.bind, ...) supported.
draft-forgery-resilience: all recommendations followed.
draft-0x20: experimental implementation (incomplete).
implements bitwise echo of the query to support downstream 0x20.
draft-ietf-dnsop-default-local-zones is fully supported (-04).
It is possible to block zones or return an address for localhost.
This is a very limited authoritative service. Defaults as in draft.
draft-ietf-dnsop-resolver-priming(-00): can prime and can fallback to
a safety belt list.
draft-ietf-dnsop-dnssec-trust-anchor(-01): DS records can be configured
as trust anchors. Also DNSKEYs are allowed, by the way.
draft-ietf-dnsop-reflectors-are-evil: access control list for recursive
service. In fact for all DNS service so cache snooping is halted.
Record type syntax support, extensive, from lib ldns.
For these types only syntax and parsing support is needed.
RFC 1034-1035: basic RR types.
RFC 1183: RP, AFSDB, X25, ISDN, RT
RFC 1706: NSAP
RFC 2535: KEY, SIG, NXT: treated as unknown data, syntax is parsed (obsolete).
2163: PX
AAAA type
1876: LOC type
2782: SRV type
2915: NAPTR type.
2230: KX type.
2538: CERT type.
2672: DNAME type.
OPT type
3123: APL
SSHFP type
4025: IPSECKEY
4033-4035: DS, RRSIG, NSEC, DNSKEY
4701: DHCID
5155: NSEC3, NSEC3PARAM
4408: SPF
+29 -9
View File
@@ -4,18 +4,16 @@ http://unbound.net
This software is under BSD license, see LICENSE for details.
* Download the latest version of this software from
* Download the latest release version of this software from
http://unbound.net
or get a beta version from the svn repository at
http://unbound.net/svn/
* Uses the following libraries;
* ldns http://www.nlnetlabs.nl/ldns/ (BSD license)
(required) can use tarball from source directory.
* libevent http://www.monkey.org/~provos/libevent/ (BSD license)
* Create build environment
* run libtoolize -c if config.sub is missing, or run glibtoolize.
* autoreconf (autoheader && autoconf), if ./configure is missing.
(optional) can use builtin alternative instead.
* Make and install: ./configure; make; make install
* Use GNU make; default on linux, often called 'gmake' on BSD and Solaris.
@@ -25,10 +23,11 @@ This software is under BSD license, see LICENSE for details.
If detected on the system, it will dynamically link against it.
* --with-libevent=/path/to/libevent
Can be set to either the system install or the build directory.
--with-libevent=no gives a builtin alternative implementation.
libevent is useful when having many (thousands) of outgoing ports.
This improves randomization and spoof resistance. For the default
of 16 ports the builtin alternative works well.
--with-libevent=no (default) gives a builtin alternative
implementation. libevent is useful when having many (thousands)
of outgoing ports. This improves randomization and spoof
resistance. For the default of 16 ports the builtin alternative
works well and is a little faster.
* --without-pthreads
This disables pthreads. Without this option the pthreads library
is detected automatically. Use this option to disable threading
@@ -44,6 +43,21 @@ This software is under BSD license, see LICENSE for details.
The server periodically checks if the amount of memory used fits with
the amount of memory it thinks it should be using, and reports
memory usage in detail.
* --with-conf-file=filename
Set default location of config file,
the default is /usr/local/etc/unbound/unbound.conf.
* --with-pidfile=filename
Set default location of pidfile,
the default is /usr/local/etc/unbound/unbound.pid.
* --with-run-dir=path
Set default working directory,
the default is /usr/local/etc/unbound.
* --with-chroot-dir=path
Set default chroot directory,
the default is /usr/local/etc/unbound.
* --with-username=user
Set default user name to change to,
the default is the "unbound" user.
* 'make test' attempts to run a series of tests, depending on the support
programs that are installed.
@@ -68,9 +82,15 @@ o If you are not receiving the correct source IP address on replies (e.g.
source IP address on UDP replies. Listing all IP addresses explicitly in
the config file is an alternative. The interface-automatic option uses
non portable socket options, Linux and FreeBSD should work fine.
o The warning 'openssl has no entropy, seeding with time', with chroot
enabled, may be solved with a symbolic link to /dev/random from <chrootdir>.
o On Solaris 5.10 some libtool packages from repositories do not work with
gcc, showing errors gcc: unrecognized option `-KPIC'
To solve this do ./configure libtool=./libtool [your options...].
Acknowledgements
----------------
o Unbound was written in portable C by Wouter Wijngaards (NLnet Labs).
o Thanks to David Blacka and Matt Larson (Verisign) for the unbound-java
prototype. Design and code from that prototype has been used to create
this program. Such as the iterator state machine and the cache design.
+5 -3
View File
@@ -1,11 +1,13 @@
README.svn
For a svn checkout
* Create build environment - see README.
* possibly copy aclocal.m4 from your autoconf/libtool setup.
* configure script, aclocal.m4, as well as yacc/lex output files are
committed to the repository.
* use --enable-debug flag for configure to enable dependency tracking and
assertions, otherwise, use make clean; make after svn update.
* Note changes in the Changelog.
* Every checking a postcommit hook is run
* Every check-in a postcommit hook is run
(the postcommit hook is in the svn/unbound/hooks directory).
* generates commit email with your changes and comment.
* compiles and runs the tests (with testcode/do-tests.sh).
+12 -1
View File
@@ -3,7 +3,18 @@ README unbound tests
There is a test setup for unbound. Use
make test
To make and run the tests. The results are summarized at the end.
You can also run ./unittest by hand, if the system lacks other debug tools.
You need to have the following programs installed and in your PATH.
* dig - from the bind-tools package. Used to send DNS queries.
* splint (optional) - for lint test
* doxygen (optional) - for doc completeness test
* ldns-testns (optional) - from ldns examples. Used as DNS auth server.
* xxd and nc (optional) - for (malformed) packet transmission.
The optional programs are detected and can be omitted.
Without any support programs, unittest and testbound can still be used.
(cd testdata; ../testcode/mini_tpkg.sh exe 02-unittest.tpkg)
(cd testdata; ../testcode/mini_tpkg.sh exe 03-testbound.tpkg)
testdata/ contains the data for tests.
testcode/ contains scripts and c code for the tests.
+50 -29
View File
@@ -1,57 +1,78 @@
TODO items.
o #define BIT_... different on bigendian and smallendian systems so that
the htons on flags is not needed to send a message from the cache.
o speed up pkt domain name decompression loop detection using counter perhaps.
o detect OS/400 pthreads implementation that allows upgrading to writelock
on pthreads rwlocks and use it to examine-rd before storing-wr rrset cache.
TODO items. These are interesting todo items.
o understand synthesized DNAMEs, so those TTL=0 packets are cached properly.
o understand NSEC/NSEC3, aggressive negative caching, so that updates to
NSEC/NSEC3 will result in proper negative responses.
o scrubber has slow pkt_subdomain and pkt_strict_subdomain functions.
o NSEC/NSEC3 aggressive negative caching, so that updates to NSEC/NSEC3
will result in proper negative responses.
o get serverselection algorithm out of local optimum.
make subtargets to get rtt info for a couple of targets, like fetch-policy.
or send out multiple queries to multiple servers.
o configuration option where port 53 is used for send and receive, no other
ports are used.
o (option) where port 53 is used for send and receive, no other ports are used.
o (option) to not send replies to clients after a timeout of (say 5 secs) has
passed, but keep task active for later retries by client.
o private TTL feature
o pretend-dnssec-unaware, and pretend-edns-unaware modes for debug/workshops.
o (option) private TTL feature (always report TTL x in answers).
o (option) pretend-dnssec-unaware, and pretend-edns-unaware modes for workshops.
o delegpt use rbtree for ns-list, to avoid slowdown for very large NS sets.
o reprime and refresh oft used data before timeout.
o retain prime results in a overlaid roothints file.
o store primed key data in a overlaid keyhints file (sort of like drafttimers).
o (option) reprime and refresh oft used data before timeout.
o (option) retain prime results in a overlaid roothints file.
o (option) store primed key data in a overlaid keyhints file (sort of like drafttimers).
o windows version, auto update feature, a query to check for the version.
o autoreport of problems
o command the server with TSIG inband. get-config, clearcache,
get stats, get memstats, get ..., reload, clear one zone from cache
o watch for spoof nearmisses. Keep counter of nearmisses and print that
in the stats lines, operator can determine what level is a redalert.
o improve compression of DNS packets by first puttig uncompressible rrs, then
compress to their rdata.
o NSID rfc 5001 support.
o timers rfc 5011 support.
o Treat YXDOMAIN from a DNAME properly, in iterator (not throwaway), validator.
o grab ports nonconsequtive and change the set after a while (change within
a given range). Could be bad for OS if wrong port. unsure if it helps secure.
o make timeout backoffs randomized (a couple percent random) to spread traffic.
o inspect date on executable, then warn user in log if its more than 1 year.
o proactively prime root, stubs and trust anchors, feature.
o (option) proactively prime root, stubs and trust anchors, feature.
early failure, faster on first query, but more traffic.
o use privilege separation, to change privilege options during reload securely
not needed.
o On Windows use CryptGenRandom() to get random seed for arc4random.
o Think about intermediate firewalls dropping EDNS UDP & handling that.
detect nonEDNS middlebox by timeout on edns queries, and fallback to
nonEDNS when appropriate.
o library add convenience functions for A, AAAA, PTR, getaddrinfo, libresolve.
o library add function to get signature data (or whole reply message).
o library add function to validate input from app that is signed.
o add dynamic-update requests (making a dynupd request) to libunbound api.
o in an ipv6 connected only environment unbound cannot use outgoing IP6
to send to ip4to6 mapped hosts, need ip4to6map of NS and disable
V6ONLY socket option.
o support multiple dns messages in a TCP query stream for the unbound server.
o SIG(0) and TSIG.
o support OPT record placement on recv anywhere in the additional section.
o add local-file: config with authority features.
o (option) to make local-data answers be secure for libunbound (default=no)
o (option) to make chroot: copy all needed files into jail (or make jail)
perhaps also print reminder to link /dev/random and sysloghack.
o (option) for extended statistics. If enabled (not by default) collect print
rcode, uptime, spoofnearmisses, cache size, qtype,
bits(RD, CD, DO, EDNS-present, AD)query, (Secure, Bogus)reply.
perhaps also see which slow auth servers cause >1sec values.
stats-file possible with key: value or key=value lines in it.
stats on SIGUSR1. addup stats over threads.
o overhaul outside-network servicedquery to merge with udpwait and tcpwait,
to make timers in servicedquery independent of udpwait queues.
o 0x20 fallback so it can be enabled without trouble.
o check into rebinding ports for efficiency, configure time test.
o DLV is considered.
o EVP hardware crypto support.
Features soon after 1.0.
o EDNS fallback after timeout (firewall drops all edns traffic problem).
o IPv6 reverse, IP4 reverse local-data shorthand for PTR records (?).
cumbersome to reverse notate by hand for the operator.
o zone name appending for local-data. Perhaps read zonefiles. Perhaps it is
too much authority feature creep.
o option to disable cache snooping from the clients (the nonRD queries),
with allow, refused, drop choices.
For 1.x; features that have been requested during the beta test.
o command channel for couple of tasks. Like rndc.
o see delegation; what servers would be used to get data for a name.
o force stats display; easier than parsing logfiles.
stats display added over threads, displayed in rddtool easy format.
o flush names or domains (all under a name) from the cache. Include NSes.
And the A, AAAA for its NSes.
o add/del static preload data to change the domain redirections.
o and maybe also start, stop, reload.
o on windows version, libunbound uses a NamedPipe, examine security status
make sure the OS makes it safe like on unix.
o on windows version, implement that OS ancillary data capabilities for
interface-automatic. IPPKTINFO, IP6PKTINFO for WSARecvMsg, WSASendMsg.
+52 -15
View File
@@ -18,6 +18,9 @@ server:
# print statistics to the log (for every thread) every N seconds.
# Set to "" or 0 to disable. Default is disabled.
# statistics-interval: 0
# enable cumulative statistics, without clearing them after printing.
# statistics-cumulative: no
# number of threads to create. 1 disables threading.
# num-threads: 1
@@ -45,16 +48,20 @@ server:
# outgoing-interface: 2001:DB8::5
# outgoing-interface: 2001:DB8::6
# unbound needs to send packets to authoritative nameservers.
# it uses a range of ports for that.
# the start number of the port range
# outgoing-port: 1053
# number of ports to allocate per thread, determines the size of the
# port range that can be open simultaneously.
# outgoing-range: 256
# permit unbound to use this port number or port range for
# making outgoing queries, using an outgoing interface.
# outgoing-port-permit: 32768
# number of port to allocate per thread, determines the size of the
# port range. A larger port range gives more resistance to certain
# spoof attacks, as it gets harder to guess which port is used.
# But also takes more system resources (for open sockets).
# outgoing-range: 16
# deny unbound the use this of port number or port range for
# making outgoing queries, using an outgoing interface.
# Use this to make sure unbound does not grab a UDP port that some
# other server on this computer needs. The default is to avoid
# IANA-assigned port numbers.
# outgoing-port-avoid: "3200-3208"
# number of outgoing simultaneous tcp buffers to hold per thread.
# outgoing-num-tcp: 10
@@ -121,6 +128,9 @@ server:
# Enable TCP, "yes" or "no".
# do-tcp: yes
# Detach from the terminal, run in background, "yes" or "no".
# do-daemonize: yes
# control which clients are allowed to make (recursive) queries
# to this server. Specify classless netblocks with /size and action.
# By default everything is refused, except for localhost.
@@ -134,16 +144,35 @@ server:
# if given, a chroot(2) is done to the given directory.
# i.e. you can chroot to the working directory, for example,
# for extra security, but make sure all files are in that directory.
# If you give "" no chroot is performed.
# chroot: "/etc/unbound"
#
# If chroot is enabled, you should pass the configfile (from the
# commandline) as a full path from the original root. After the
# chroot has been performed the now defunct portion of the config
# file path is removed to be able to reread the config after a reload.
#
# All other file paths (working dir, pidfile, logfile, roothints,
# key files) can be specified in several ways:
# o as an absolute path relative to the new root.
# o as a relative path to the working directory.
# o as an absolute path relative to the original root.
# In the last case the path is adjusted to remove the unused portion.
#
# Additionally, unbound may need to access /dev/random (for entropy)
# and to /dev/log (if you use syslog) from inside the chroot.
# How to do this is specific to your OS.
#
# If you give "" no chroot is performed. The path must not end in a /.
# chroot: "@UNBOUND_CHROOT_DIR@"
# if given, user privileges are dropped (after binding port),
# and the given username is assumed. Default is user "unbound".
# If you give "" no privileges are dropped.
# username: "unbound"
# username: "@UNBOUND_USERNAME@"
# the working directory.
# directory: "/etc/unbound"
# the working directory. The relative files in this config are
# relative to this directory. If you give "" the working directory
# is not changed.
# directory: "@UNBOUND_RUN_DIR@"
# the log file, "" means log to stderr.
# Use of this option sets use-syslog to "no".
@@ -154,7 +183,7 @@ server:
# use-syslog: yes
# the pid file.
# pidfile: "/etc/unbound/unbound.pid"
# pidfile: "@UNBOUND_PIDFILE@"
# file to read root hints from.
# get one from ftp://FTP.INTERNIC.NET/domain/named.cache
@@ -197,6 +226,14 @@ server:
# Default on, which insists on dnssec data for trust-anchored zones.
# harden-dnssec-stripped: yes
# Use 0x20-encoded random bits in the query to foil spoof attempts.
# Disabled by default, because some caching forwarders may not
# support this (if you have forward-zones). Most authority servers do.
# This feature is an experimental implementation of draft dns-0x20.
# It is known that some authority servers do not support 0x20, and
# resolution will fail for them. A solution is on the TODO list.
# use-caps-for-id: no
# Do not query the following addresses. No DNS queries are sent there.
# List one address per entry. List classless netblocks with /size,
# do-not-query-address: 127.0.0.1/8
+119 -85
View File
@@ -11,101 +11,109 @@
.LP
.B libunbound,
.B unbound.h,
.B ub_val_ctx,
.B ub_val_result,
.B ub_val_callback_t,
.B ub_val_ctx_create,
.B ub_val_ctx_delete,
.B ub_val_ctx_config,
.B ub_val_ctx_set_fwd,
.B ub_val_ctx_resolvconf,
.B ub_val_ctx_add_ta,
.B ub_val_ctx_add_ta_file,
.B ub_val_ctx_trustedkeys,
.B ub_val_ctx_debuglevel,
.B ub_val_ctx_async,
.B ub_val_poll,
.B ub_val_wait,
.B ub_val_fd,
.B ub_val_process,
.B ub_val_resolve,
.B ub_val_resolve_async,
.B ub_val_cancel,
.B ub_val_resolve_free,
.B ub_val_strerror
.B ub_ctx,
.B ub_result,
.B ub_callback_t,
.B ub_ctx_create,
.B ub_ctx_delete,
.B ub_ctx_set_option,
.B ub_ctx_config,
.B ub_ctx_set_fwd,
.B ub_ctx_resolvconf,
.B ub_ctx_hosts,
.B ub_ctx_add_ta,
.B ub_ctx_add_ta_file,
.B ub_ctx_trustedkeys,
.B ub_ctx_debugout,
.B ub_ctx_debuglevel,
.B ub_ctx_async,
.B ub_poll,
.B ub_wait,
.B ub_fd,
.B ub_process,
.B ub_resolve,
.B ub_resolve_async,
.B ub_cancel,
.B ub_resolve_free,
.B ub_strerror
\- Unbound DNS validating resolver @version@ functions.
.SH "SYNOPSIS"
.LP
.B #include <unbound.h>
.LP
\fIstruct ub_val_ctx *\fR
\fBub_val_ctx_create\fR(\fIvoid\fR);
\fIstruct ub_ctx *\fR
\fBub_ctx_create\fR(\fIvoid\fR);
.LP
\fIvoid\fR
\fBub_val_ctx_delete\fR(\fIstruct ub_val_ctx*\fR ctx);
\fBub_ctx_delete\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\fBub_val_ctx_config\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR fname);
\fBub_ctx_set_option\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR opt, \fIchar*\fR val);
.LP
\fIint\fR
\fBub_val_ctx_set_fwd\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR addr);
\fBub_ctx_config\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_val_ctx_resolvconf\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR fname);
\fBub_ctx_set_fwd\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR addr);
.LP
\fIint\fR
\fBub_val_ctx_add_ta\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR ta);
\fBub_ctx_resolvconf\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_val_ctx_add_ta_file\fR(\fIstruct ub_val_ctx*\fR ctx,
.br
\fIchar*\fR fname);
\fBub_ctx_hosts\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_val_ctx_trustedkeys\fR(\fIstruct ub_val_ctx*\fR ctx,
.br
\fIchar*\fR fname);
\fBub_ctx_add_ta\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR ta);
.LP
\fIint\fR
\fBub_val_ctx_debuglevel\fR(\fIstruct ub_val_ctx*\fR ctx, \fIint\fR d);
\fBub_ctx_add_ta_file\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_val_ctx_async\fR(\fIstruct ub_val_ctx*\fR ctx, \fIint\fR dothread);
\fBub_ctx_trustedkeys\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_val_poll\fR(\fIstruct ub_val_ctx*\fR ctx);
\fBub_ctx_debugout\fR(\fIstruct ub_ctx*\fR ctx, \fIFILE*\fR out);
.LP
\fIint\fR
\fBub_val_wait\fR(\fIstruct ub_val_ctx*\fR ctx);
\fBub_ctx_debuglevel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR d);
.LP
\fIint\fR
\fBub_val_fd\fR(\fIstruct ub_val_ctx*\fR ctx);
\fBub_ctx_async\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR dothread);
.LP
\fIint\fR
\fBub_val_process\fR(\fIstruct ub_val_ctx*\fR ctx);
\fBub_poll\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\fBub_val_resolve\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR name,
\fBub_wait\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\fBub_fd\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\fBub_process\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\fBub_resolve\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR name,
.br
\fIint\fR rrtype, \fIint\fR rrclass, \fIint*\fR secure,
.br
\fIint*\fR data, \fIstruct ub_val_result**\fR result);
\fIint*\fR data, \fIstruct ub_result**\fR result);
.LP
\fIint\fR
\fBub_val_resolve_async\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR name,
\fBub_resolve_async\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR name,
.br
\fIint\fR rrtype, \fIint\fR rrclass, \fIvoid*\fR mydata,
.br
\fIub_val_callback_t\fR callback, \fIint*\fR async_id);
\fIub_callback_t\fR callback, \fIint*\fR async_id);
.LP
\fIint\fR
\fBub_val_cancel\fR(\fIstruct ub_val_ctx*\fR ctx, \fIint\fR async_id);
\fBub_cancel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR async_id);
.LP
\fIvoid\fR
\fBub_val_resolve_free\fR(\fIstruct ub_val_result*\fR result);
\fBub_resolve_free\fR(\fIstruct ub_result*\fR result);
.LP
\fIconst char *\fR
\fBub_val_strerror\fR(\fIint\fR err);
\fBub_strerror\fR(\fIint\fR err);
.SH "DESCRIPTION"
.LP
.B Unbound
@@ -116,11 +124,11 @@ The library can be used to convert hostnames to ip addresses, and back,
and obtain other information from the DNS. The library performs public\-key
validation of results with DNSSEC.
.P
The library uses a variable of type \fIstruct ub_val_ctx\fR to keep context
The library uses a variable of type \fIstruct ub_ctx\fR to keep context
between calls. The user must maintain it, creating it with
.B ub_val_ctx_create
.B ub_ctx_create
and deleting it with
.B ub_val_ctx_delete\fR.
.B ub_ctx_delete\fR.
It can be created and deleted at any time. Creating it anew removes any
previous configuration (such as trusted keys) and clears any cached results.
.P
@@ -133,20 +141,32 @@ can go on, while the results become available later.
The functions are discussed in turn below.
.SH "FUNCTIONS"
.TP
.B ub_val_ctx_create
.B ub_ctx_create
Create a new context, initialised with defaults.
The information from /etc/resolv.conf and /etc/hosts is not utilised
by default. Use
.B ub_ctx_resolvconf
and
.B ub_ctx_hosts
to read them.
.TP
.B ub_val_ctx_delete
.B ub_ctx_delete
Delete validation context and free associated resources.
Outstanding async queries are killed and callbacks are not called for them.
.TP
.B ub_val_ctx_config
.B ub_ctx_set_option
A power\-user interface that lets you specify one of the options from the
config file format, see \fIunbound.conf\fR(5). Not all options are
relevant. For some specific options, such as adding trust anchors, special
routines exist. Pass the option name with the trailing ':'.
.TP
.B ub_ctx_config
A power\-user interface that lets you specify an unbound config file, see
\fIunbound.conf\fR(5), which is read for configuration. Not all options are
relevant. For some specific options, such as adding trust anchors, special
routines exist.
.TP
.B ub_val_ctx_set_fwd
.B ub_ctx_set_fwd
Set machine to forward DNS queries to, the caching resolver to use.
IP4 or IP6 address. Forwards all DNS requests to that machine, which
is expected to run a recursive resolver. If the proxy is not
@@ -155,7 +175,7 @@ that case the addresses are used as backup servers.
At this time it is only possible to set configuration before the
first resolve is done.
.TP
.B ub_val_ctx_resolvconf
.B ub_ctx_resolvconf
Read list of nameservers to use from the filename given.
Usually "/etc/resolv.conf". Uses those nameservers as caching proxies.
If they do not support DNSSEC, validation may fail.
@@ -165,67 +185,79 @@ If fname NULL is passed, "/etc/resolv.conf" is used.
At this time it is only possible to set configuration before the
first resolve is done.
.TP
.B ub_ctx_hosts
Read list of hosts from the filename given.
Usually "/etc/hosts". When queried for, these addresses are not marked
DNSSEC secure. If fname NULL is passed, "/etc/hosts" is used.
At this time it is only possible to set configuration before the
first resolve is done.
.TP
.B
ub_val_ctx_add_ta
ub_ctx_add_ta
Add a trust anchor to the given context.
At this time it is only possible to add trusted keys before the
first resolve is done.
The format is a string, similar to the zone-file format,
[domainname] [type] [rdata contents]. Both DS and DNSKEY records are accepted.
.TP
.B ub_val_ctx_add_ta_file
.B ub_ctx_add_ta_file
Add trust anchors to the given context.
Pass name of a file with DS and DNSKEY records in zone file format.
At this time it is only possible to add trusted keys before the
first resolve is done.
.TP
.B ub_val_ctx_trustedkeys
.B ub_ctx_trustedkeys
Add trust anchors to the given context.
Pass the name of a bind-style config file with trusted-keys{}.
At this time it is only possible to add trusted keys before the
first resolve is done.
.TP
.B ub_val_ctx_debuglevel
.B ub_ctx_debugout
Set debug and error log output to the given stream. Pass NULL to disable
output. Default is stderr. File-names or using syslog can be enabled
using config options, this routine is for using your own stream.
.TP
.B ub_ctx_debuglevel
Set debug verbosity for the context. Output is directed to stderr.
Higher debug level gives more output.
.TP
.B ub_val_ctx_async
.B ub_ctx_async
Set a context behaviour for asynchronous action.
if set to true, enables threading and a call to
.B ub_val_resolve_async
.B ub_resolve_async
creates a thread to handle work in the background.
If false, a process is forked to handle work in the background.
Changes to this setting after
.B ub_val_resolve_async
.B ub_resolve_async
calls have been made have no effect (delete and re\-create the context
to change).
.TP
.B ub_val_poll
.B ub_poll
Poll a context to see if it has any new results.
Do not poll in a loop, instead extract the fd below to poll for readiness,
and then check, or wait using the wait routine.
Returns 0 if nothing to read, or nonzero if a result is available.
If nonzero, call
.B ub_val_process
.B ub_process
to do callbacks.
.TP
.B ub_val_wait
.B ub_wait
Wait for a context to finish with results. Calls
.B ub_val_process
.B ub_process
after the wait for you. After the wait, there are no more outstanding
asynchronous queries.
.TP
.B ub_val_fd
.B ub_fd
Get file descriptor. Wait for it to become readable, at this point
answers are returned from the asynchronous validating resolver.
Then call the \fBub_val_process\fR to continue processing.
Then call the \fBub_process\fR to continue processing.
.TP
.B ub_val_process
.B ub_process
Call this routine to continue processing results from the validating
resolver (when the fd becomes readable).
Will perform necessary callbacks.
.TP
.B ub_val_resolve
.B ub_resolve
Perform resolution and validation of the target name.
The name is a domain name in a zero terminated text string.
The rrtype and rrclass are DNS type and class codes.
@@ -233,9 +265,9 @@ The value secure returns true if the answer validated securely.
The value data returns true if there was data.
The result structure is newly allocated with the resulting data.
.TP
.B ub_val_resolve_async
.B ub_resolve_async
Perform asynchronous resolution and validation of the target name.
Arguments mean the same as for \fBub_val_resolve\fR except no
Arguments mean the same as for \fBub_resolve\fR except no
data is returned immediately, instead a callback is called later.
The callback receives a copy of the mydata pointer, that you can use to pass
information to the callback. The callback type is a function pointer to
@@ -243,27 +275,27 @@ a function declared as
.IP
void my_callback_function(void* my_arg, int err,
.br
struct ub_val_result* result);
struct ub_result* result);
.IP
The async_id is returned so you can (at your option) decide to track it
and cancel the request if needed.
.TP
.B ub_val_cancel
.B ub_cancel
Cancel an async query in progress.
.TP
.B ub_val_resolve_free
Free struct ub_val_result contents after use.
.B ub_resolve_free
Free struct ub_result contents after use.
.TP
.B ub_val_strerror
.B ub_strerror
Convert error value from one of the unbound library functions
to a human readable string.
.SH "RESULT DATA STRUCTURE"
.LP
The result of the DNS resolution and validation is returned as
\fIstruct ub_val_result\fR. The result structure contains the following entries.
\fIstruct ub_result\fR. The result structure contains the following entries.
.P
.nf
struct ub_val_result {
struct ub_result {
char* qname; /* text string, original question */
int qtype; /* type code asked for */
int qclass; /* class code asked for */
@@ -271,6 +303,8 @@ The result of the DNS resolution and validation is returned as
int* len; /* array with lengths of rdata items */
char* canonname; /* canonical name of result */
int rcode; /* additional error code in case of no data */
void* answer_packet; /* full network format answer packet */
int answer_len; /* length of packet in octets */
int havedata; /* true if there is data */
int nxdomain; /* true if nodata because name does not exist */
int secure; /* true if result is secure */
@@ -283,15 +317,15 @@ domain of the query.
.SH "RETURN VALUES"
Many routines return an error code. The value 0 (zero) denotes no error
happened. Other values can be passed to
.B ub_val_strerror
.B ub_strerror
to obtain a readable error string.
.B ub_val_strerror
.B ub_strerror
returns a zero terminated string.
.B ub_val_ctx_create
.B ub_ctx_create
returns NULL on an error (a malloc failure).
.B ub_val_poll
.B ub_poll
returns true if some information may be available, false otherwise.
.B ub_val_fd
.B ub_fd
returns a file descriptor or -1 on error.
.SH "SEE ALSO"
\fIunbound.conf\fR(5),
+2 -2
View File
@@ -203,6 +203,6 @@ o If a client makes a query without RD bit, in the case of a returned
o Case preservation
Unbound preserves the casing received from authority servers as best
as possible. It compresses without case, so case can get lost there.
The casing from the authority server is used in preference to the casing
of the query name. This is different from BIND. RFC4343 allows either
The casing from the query name is used in preference to the casing
of the authority server. This is the same as BIND. RFC4343 allows either
behaviour.
@@ -36,7 +36,7 @@ The unbound-checkconf program exits with status code 1 on error,
0 for a correct config file.
.SH "FILES"
.TP
.I /etc/unbound/unbound.conf
.I @ub_conf_file@
unbound configuration file.
.SH "SEE ALSO"
\fIunbound.conf\fR(5),
+15 -2
View File
@@ -14,7 +14,7 @@
.SH "SYNOPSIS"
.LP
.B unbound\-host
.RB [ \-vdh ]
.RB [ \-vdhr ]
.RB [ \-c
.IR class ]
.RB [ \-t
@@ -26,6 +26,8 @@
.IR keyfile ]
.RB [ \-F
.IR namedkeyfile ]
.RB [ \-C
.IR configfile ]
.SH "DESCRIPTION"
.LP
.B Unbound\-host
@@ -75,9 +77,20 @@ as for \-y. The zone file format, the same as dig and drill produce.
.B \-F \fInamedkeyfile
Reads keys from a BIND\-style named.conf file. Only the trusted\-key {}; entries
are read.
.TP
.B \-C \fIconfigfile
Uses the specified unbound.conf to prime
.IR libunbound (3).
.TP
.B \-r
Read /etc/resolv.conf, and use the forward DNS servers from there (those could
have been set by DHCP). More info in
.IR resolv.conf (5).
Breaks validation if those servers do not support DNSSEC.
.SH "EXAMPLES"
.LP
Some examples of use.
Some examples of use. The keys shown below are fakes, thus a security failure
is encountered.
.P
$ unbound\-host www.example.com
.P
+2 -2
View File
@@ -31,8 +31,8 @@ The available options are:
Show the version and commandline option help.
.TP
.B \-c\fI cfgfile
Set the config file with settings for unbound to read instead of the
file at default location /etc/unbound/unbound.conf. The syntax is
Set the config file with settings for unbound to read instead of reading the
file at the default location, @ub_conf_file@. The syntax is
described in \fIunbound.conf\fR(5).
.TP
.B \-d
+102 -34
View File
@@ -50,6 +50,10 @@ example.conf file with all the options.
server:
directory: "/etc/unbound"
username: unbound # make sure it can write to pidfile.
# make sure unbound can access entropy from inside the chroot.
# e.g. on linux the use these commands (on BSD, devfs(8) is used):
# mount --bind -n /dev/random /etc/unbound/dev/random
# and mount --bind -n /dev/log /etc/unbound/dev/log
chroot: "/etc/unbound"
# logfile: "/etc/unbound/unbound.log" #uncomment to use logfile.
pidfile: "/etc/unbound/unbound.pid"
@@ -88,6 +92,10 @@ see
The number of seconds between printing statistics to the log for every thread.
Disable with value 0 or "". Default is disabled.
.TP
.B statistics-cumulative: \fI<yes or no>
If enabled, statistics are cumulative since starting unbound, without clearing
the statistics counters after logging the statistics. Default is no.
.TP
.B num\-threads: \fI<number>
The number of threads to create to serve clients. Use 1 for no threading.
.TP
@@ -118,15 +126,24 @@ and
lines, the interfaces are then used for both purposes. Outgoing queries are
sent via a random outgoing interface to counter spoofing.
.TP
.B outgoing\-port: \fI<port number>
The starting port number where the outgoing query port range is allocated.
Default is 1053.
.TP
.B outgoing\-range: \fI<number>
Number of ports to open. This number is opened per thread for every outgoing
query interface. Must be at least 1. Default is 16.
Larger numbers give more protection against spoofing attempts, but need
extra resources from the operating system.
Number of ports to open. This number of file descriptors can be opened per
thread. Must be at least 1. Default is 256. Larger numbers need extra
resources from the operating system.
.TP
.B outgoing\-port\-permit: \fI<port number or range>
Permit unbound to open this port or range of ports for use to send queries.
A larger number of permitted outgoing ports increases resilience against
spoofing attempts. Make sure these ports are not needed by other daemons.
By default only ports above 1024 that have not been assigned by IANA are used.
Give a port number or a range of the form "low-high", without spaces.
.TP
.B outgoing\-port\-avoid: \fI<port number or range>
Do not permit unbound to open this port or range of ports for use to send
queries. Use this to make sure unbound does not grab a port that another
daemon needs. The port is avoided on all outgoing interfaces, both IP4 and IP6.
By default only ports above 1024 that have not been assigned by IANA are used.
Give a port number or a range of the form "low-high", without spaces.
.TP
.B outgoing\-num\-tcp: \fI<number>
Number of outgoing TCP buffers to allocate per thread. Default is 10. If set
@@ -209,6 +226,10 @@ Enable or disable whether UDP queries are answered or issued. Default is yes.
.B do\-tcp: \fI<yes or no>
Enable or disable whether TCP queries are answered or issued. Default is yes.
.TP
.B do\-daemonize: \fI<yes or no>
Enable or disable whether the unbound server forks into the background as
a daemon. Default is yes.
.TP
.B access\-control: \fI<IP netblock> <action>
The netblock is given as an IP4 or IP6 address with /size appended for a
classless network block. The action can be deny, refuse or allow.
@@ -221,12 +242,27 @@ is not designed to handle dropped packets due to policy, and dropping may
result in (possibly excessive) retried queries.
.TP
.B chroot: \fI<directory>
If chroot is enabled, you should pass the configfile (from the
commandline) as a full path from the original root. After the
chroot has been performed the now defunct portion of the config
file path is removed to be able to reread the config after a reload.
.IP
All other file paths (working dir, pidfile, logfile, roothints,
key files) can be specified in several ways:
as an absolute path relative to the new root,
as a relative path to the working directory, or
as an absolute path relative to the original root.
In the last case the path is adjusted to remove the unused portion.
.IP
Additionally, unbound may need to access /dev/random (for entropy)
and to /dev/log (if you use syslog) from inside the chroot.
.IP
If given a chroot is done to the given directory. The default is
"/etc/unbound". If you give "" no chroot is performed.
"@UNBOUND_CHROOT_DIR@". If you give "" no chroot is performed.
.TP
.B username: \fI<name>
If given, after binding the port the user privileges are dropped. Default is
"unbound". If you give username: "" no user change is performed.
"@UNBOUND_USERNAME@". If you give username: "" no user change is performed.
.IP
If this user is not capable of binding the
port, reloads (by signal HUP) will still retain the opened ports.
@@ -234,7 +270,7 @@ If you change the port number in the config file, and that new port number
requires privileges, then a reload will fail; a restart is needed.
.TP
.B directory: \fI<directory>
Sets the working directory for the program.
Sets the working directory for the program. Default is "@UNBOUND_RUN_DIR@".
.TP
.B logfile: \fI<filename>
If "" is given, logging goes to stderr, or nowhere once daemonized.
@@ -254,14 +290,14 @@ The logfile setting is overridden when use\-syslog is turned on.
The default is to log to syslog.
.TP
.B pidfile: \fI<filename>
The process id is written to the file. Default is "/etc/unbound/unbound.pid".
The process id is written to the file. Default is "@UNBOUND_PIDFILE@".
So,
.nf
kill \-HUP `cat /etc/unbound/unbound.pid`
kill \-HUP `cat @UNBOUND_PIDFILE@`
.fi
triggers a reload,
.nf
kill \-QUIT `cat /etc/unbound/unbound.pid`
kill \-QUIT `cat @UNBOUND_PIDFILE@`
.fi
gracefully terminates.
.TP
@@ -324,6 +360,15 @@ removes DNSSEC data from packets, or a zone changes from signed to
unsigned to badly signed often. If turned off you run the risk of a
downgrade attack that disables security for a zone. Default is on.
.TP
.B use\-caps\-for\-id: \fI<yes or no>
Use 0x20-encoded random bits in the query to foil spoof attempts.
This perturbs the lowercase and uppercase of query names sent to
authority servers and checks if the reply still has the correct casing.
Disabled by default, because some caching forwarders may not
support this. It is known that some authority servers do not support 0x20,
and resolution will fail for them. A solution is on the TODO list.
This feature is an experimental implementation of draft dns\-0x20.
.TP
.B do\-not\-query\-address: \fI<IP address>
Do not query the given IP address. Can be IP4 or IP6. Append /num to
indicate a classless delegation netblock, for example like
@@ -467,7 +512,8 @@ for completeness and to satisfy some DNS update tools. Default content:
.nf
local\-zone: "localhost." static
local\-data: "localhost. 10800 IN NS localhost."
local\-data: "localhost. 10800 IN SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
local\-data: "localhost. 10800 IN
SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
local\-data: "localhost. 10800 IN A 127.0.0.1"
local\-data: "localhost. 10800 IN AAAA ::1"
.fi
@@ -477,17 +523,26 @@ Default content:
.nf
local\-zone: "127.in\-addr.arpa." static
local\-data: "127.in\-addr.arpa. 10800 IN NS localhost."
local\-data: "127.in\-addr.arpa. 10800 IN SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
local\-data: "1.0.0.127.in\-addr.arpa. 10800 IN PTR localhost."
local\-data: "127.in\-addr.arpa. 10800 IN
SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
local\-data: "1.0.0.127.in\-addr.arpa. 10800 IN
PTR localhost."
.fi
.TP 10
\h'5'\fIreverse IPv6 loopback\fR
Default content:
.nf
local\-zone: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." static
local\-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN NS localhost."
local\-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
local\-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN PTR localhost."
local\-zone: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." static
local\-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN
NS localhost."
local\-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN
SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
local\-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN
PTR localhost."
.fi
.TP 10
\h'5'\fIreverse RFC1918 local use zones\fR
@@ -503,7 +558,8 @@ Reverse data for zones 0.in\-addr.arpa, 254.169.in\-addr.arpa,
\h'5'\fIreverse RFC4291 IP6 unspecified\fR
Reverse data for zone
.nf
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.
.fi
.TP 10
\h'5'\fIreverse RFC4193 IPv6 Locally Assigned Local Addresses\fR
@@ -511,6 +567,14 @@ Reverse data for zone D.F.ip6.arpa.
.TP 10
\h'5'\fIreverse RFC4291 IPv6 Link Local Addresses\fR
Reverse data for zones 8.E.F.ip6.arpa to B.E.F.ip6.arpa.
.TP 10
\h'5'\fIreverse IPv6 Example Prefix\fR
Reverse data for zone 8.B.D.0.1.0.0.2.ip6.arpa. This zone is used for
tutorials and examples. You can remove the block on this zone with:
.nf
local-zone: 8.B.D.0.1.0.0.2.ip6.arpa. nodefault
.fi
This also works with the other default zones.
.\" End of local-zone listing.
.TP 5
.B local\-data: \fI"<resource record string>"
@@ -583,8 +647,9 @@ In the example config settings below memory usage is reduced. Some service
levels are lower, notable very large data and a high TCP load are no longer
supported. Very large data and high TCP loads are exceptional for the DNS.
DNSSEC validation is enabled, just add trust anchors.
If you do not have to worry about programs using more than 1 meg of memory,
the below example is not for you. Use the defaults to receive full service.
If you do not have to worry about programs using more than 3 Mb of memory,
the below example is not for you. Use the defaults to receive full service,
which on BSD-32bit tops out at 30-40 Mb after heavy usage.
.P
.nf
# example settings that reduce memory usage
@@ -592,33 +657,36 @@ server:
num\-threads: 1
outgoing\-num\-tcp: 1 # this limits TCP service, uses less buffers.
incoming\-num\-tcp: 1
outgoing\-range: 1 # uses less memory, but less port randomness.
outgoing\-range: 16 # uses less memory, but less performance.
msg\-buffer\-size: 8192 # note this limits service, 'no huge stuff'.
msg\-cache\-size: 102400 # 100 Kb.
msg\-cache\-size: 100k
msg\-cache\-slabs: 1
rrset\-cache\-size: 102400 # 100 Kb.
rrset\-cache\-size: 100k
rrset\-cache\-slabs: 1
infra\-cache\-numhosts: 200
infra\-cache\-numlame: 10
key\-cache\-size: 102400 # 100 Kb.
infra\-cache\-slabs: 1
infra\-cache\-lame\-size: 1k
key\-cache\-size: 100k
key\-cache\-slabs: 1
num\-queries\-per\-thread: 30
target\-fetch\-policy: "2 1 0 0 0 0"
harden\-large\-queries: "yes"
harden\-short\-bufsize: "yes"
do\-ip6: no # save a bit of memory if not used.
.fi
.SH "FILES"
.TP
.I /etc/unbound
default unbound working directory and default
.I @UNBOUND_RUN_DIR@
default unbound working directory.
.TP
.I @UNBOUND_CHROOT_DIR@
default
\fIchroot\fR(2)
location.
.TP
.I unbound.conf
.I @ub_conf_file@
unbound configuration file.
.TP
.I unbound.pid
.I @UNBOUND_PIDFILE@
default unbound pidfile with process ID of the running daemon.
.TP
.I unbound.log
+2
View File
@@ -106,6 +106,8 @@ struct delegpt_addr {
socklen_t addrlen;
/** number of attempts for this addr */
int attempts;
/** rtt stored here in the selection algorithm */
int sel_rtt;
};
/**
+5 -2
View File
@@ -115,6 +115,7 @@ donotq_str_cfg(struct iter_donotq* dq, const char* str)
struct sockaddr_storage addr;
int net;
socklen_t addrlen;
verbose(VERB_ALGO, "donotq: %s", str);
if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
log_err("cannot parse donotquery netblock: %s", str);
return 0;
@@ -179,8 +180,10 @@ donotq_apply_cfg(struct iter_donotq* dq, struct config_file* cfg)
if(cfg->donotquery_localhost) {
if(!donotq_str_cfg(dq, "127.0.0.0/8"))
return 0;
if(!donotq_str_cfg(dq, "::1"))
return 0;
if(cfg->do_ip6) {
if(!donotq_str_cfg(dq, "::1"))
return 0;
}
}
donotq_init_parents(dq);
return 1;
+32 -14
View File
@@ -112,7 +112,7 @@ ah(struct delegpt* dp, struct regional* r, const char* sv, const char* ip)
/** obtain compiletime provided root hints */
static struct delegpt*
compile_time_root_prime(struct regional* r)
compile_time_root_prime(struct regional* r, int do_ip4, int do_ip6)
{
/* from:
; This file is made available by InterNIC
@@ -121,14 +121,14 @@ compile_time_root_prime(struct regional* r)
; on server FTP.INTERNIC.NET
; -OR- RS.INTERNIC.NET
;
; last update: Jan 29, 2004
; related version of root zone: 2004012900
; related version of root zone: 2008051300
*/
struct delegpt* dp = delegpt_create(r);
if(!dp)
return NULL;
if(!delegpt_set_name(dp, r, (uint8_t*)"\000"))
return NULL;
if(do_ip4) {
if(!ah(dp, r, "A.ROOT-SERVERS.NET.", "198.41.0.4")) return 0;
if(!ah(dp, r, "B.ROOT-SERVERS.NET.", "192.228.79.201")) return 0;
if(!ah(dp, r, "C.ROOT-SERVERS.NET.", "192.33.4.12")) return 0;
@@ -142,6 +142,15 @@ compile_time_root_prime(struct regional* r)
if(!ah(dp, r, "K.ROOT-SERVERS.NET.", "193.0.14.129")) return 0;
if(!ah(dp, r, "L.ROOT-SERVERS.NET.", "199.7.83.42")) return 0;
if(!ah(dp, r, "M.ROOT-SERVERS.NET.", "202.12.27.33")) return 0;
}
if(do_ip6) {
if(!ah(dp, r, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) return 0;
if(!ah(dp, r, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) return 0;
if(!ah(dp, r, "H.ROOT-SERVERS.NET.", "2001:500:1::803f:235")) return 0;
if(!ah(dp, r, "J.ROOT-SERVERS.NET.", "2001:503:c27::2:30")) return 0;
if(!ah(dp, r, "K.ROOT-SERVERS.NET.", "2001:7fd::1")) return 0;
if(!ah(dp, r, "M.ROOT-SERVERS.NET.", "2001:dc3::35")) return 0;
}
return dp;
}
@@ -325,23 +334,20 @@ read_root_hints(struct iter_hints* hints, char* fname)
if(status != LDNS_STATUS_OK) {
log_err("reading root hints %s %d: %s", fname,
lineno, ldns_get_errorstr_by_id(status));
fclose(f);
return 0;
goto stop_read;
}
if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_NS) {
if(!delegpt_add_ns(dp, hints->region,
ldns_rdf_data(ldns_rr_rdf(rr, 0)))) {
log_err("out of memory reading root hints");
fclose(f);
return 0;
goto stop_read;
}
c = ldns_rr_get_class(rr);
if(!dp->name) {
if(!delegpt_set_name(dp, hints->region,
ldns_rdf_data(ldns_rr_owner(rr)))){
log_err("out of memory.");
fclose(f);
return 0;
goto stop_read;
}
}
} else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_A) {
@@ -357,8 +363,7 @@ read_root_hints(struct iter_hints* hints, char* fname)
ldns_rdf_size(ldns_rr_owner(rr)),
(struct sockaddr_storage*)&sa, len)) {
log_err("out of memory reading root hints");
fclose(f);
return 0;
goto stop_read;
}
} else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) {
struct sockaddr_in6 sa;
@@ -373,8 +378,7 @@ read_root_hints(struct iter_hints* hints, char* fname)
ldns_rdf_size(ldns_rr_owner(rr)),
(struct sockaddr_storage*)&sa, len)) {
log_err("out of memory reading root hints");
fclose(f);
return 0;
goto stop_read;
}
} else {
log_warn("root hints %s:%d skipping type %d",
@@ -383,6 +387,11 @@ read_root_hints(struct iter_hints* hints, char* fname)
ldns_rr_free(rr);
}
if (origin)
ldns_rdf_deep_free(origin);
if (prev_rr)
ldns_rdf_deep_free(prev_rr);
fclose(f);
if(!dp->name) {
log_warn("root hints %s: no NS content", fname);
@@ -393,6 +402,14 @@ read_root_hints(struct iter_hints* hints, char* fname)
}
delegpt_log(VERB_QUERY, dp);
return 1;
stop_read:
if (origin)
ldns_rdf_deep_free(origin);
if (prev_rr)
ldns_rdf_deep_free(prev_rr);
fclose(f);
return 0;
}
/** read root hints list */
@@ -433,7 +450,8 @@ hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
/* use fallback compiletime root hints */
if(!hints_lookup_root(hints, LDNS_RR_CLASS_IN)) {
struct delegpt* dp = compile_time_root_prime(hints->region);
struct delegpt* dp = compile_time_root_prime(hints->region,
cfg->do_ip4, cfg->do_ip6);
verbose(VERB_ALGO, "no config, using builtin root hints.");
if(!dp)
return 0;
+17 -5
View File
@@ -104,6 +104,7 @@ response_type_from_server(int rdset,
struct dns_msg* msg, struct query_info* request, struct delegpt* dp)
{
uint8_t* origzone = (uint8_t*)"\000"; /* the default */
struct ub_packed_rrset_key* s;
size_t origzonelen = 1;
size_t i;
@@ -188,12 +189,10 @@ response_type_from_server(int rdset,
}
/* Looking at the authority section, we just look and see if
* there is a delegation NS set, turning it into a delegation.
* Otherwise, we will have to conclude ANSWER (either it is
* NOERROR/NODATA, or an non-authoritative answer). */
* there is a SOA record, that means a NOERROR/NODATA */
for(i = msg->rep->an_numrrsets; i < (msg->rep->an_numrrsets +
msg->rep->ns_numrrsets); i++) {
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
s = msg->rep->rrsets[i];
/* The normal way of detecting NOERROR/NODATA. */
if(ntohs(s->rk.type) == LDNS_RR_TYPE_SOA &&
@@ -204,19 +203,32 @@ response_type_from_server(int rdset,
return RESPONSE_TYPE_LAME;
return RESPONSE_TYPE_ANSWER;
}
}
/* Looking at the authority section, we just look and see if
* there is a delegation NS set, turning it into a delegation.
* Otherwise, we will have to conclude ANSWER (either it is
* NOERROR/NODATA, or an non-authoritative answer). */
for(i = msg->rep->an_numrrsets; i < (msg->rep->an_numrrsets +
msg->rep->ns_numrrsets); i++) {
s = msg->rep->rrsets[i];
/* Detect REFERRAL/LAME/ANSWER based on the relationship
* of the NS set to the originating zone name. */
if(ntohs(s->rk.type) == LDNS_RR_TYPE_NS) {
/* If we are getting an NS set for the zone we
* thought we were contacting, then it is an answer.*/
/* FIXME: is this correct? */
if(query_dname_compare(s->rk.dname, origzone) == 0) {
/* see if mistakenly a recursive server was
* deployed and is responding nonAA */
if( (msg->rep->flags&BIT_RA) &&
!(msg->rep->flags&BIT_AA) && !rdset)
return RESPONSE_TYPE_LAME;
/* Or if a lame server is deployed,
* which gives ns==zone delegation from cache
* without AA bit as well, with nodata nosoa*/
if(msg->rep->an_numrrsets==0 &&
!(msg->rep->flags&BIT_AA) && !rdset)
return RESPONSE_TYPE_LAME;
return RESPONSE_TYPE_ANSWER;
}
/* If we are getting a referral upwards (or to
+78 -7
View File
@@ -189,7 +189,11 @@ parse_get_cname_target(struct rrset_parse* rrset, uint8_t** sname,
if(rrset->rr_count != 1) {
verbose(VERB_ALGO, "Found CNAME rrset with "
"size > 1: %u", (unsigned)rrset->rr_count);
return 0;
/* use the first CNAME! */
rrset->rr_count = 1;
rrset->size = rrset->rr_first->size;
rrset->rr_last = rrset->rr_first;
rrset->rr_first->next = NULL;
}
if(rrset->rr_first->size < sizeof(uint16_t)+1)
return 0; /* CNAME rdata too small */
@@ -316,7 +320,7 @@ scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg,
{
uint8_t* sname = qinfo->qname;
size_t snamelen = qinfo->qname_len;
struct rrset_parse* rrset, *prev;
struct rrset_parse* rrset, *prev, *nsset=NULL;
if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR &&
FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN)
@@ -412,7 +416,10 @@ scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg,
}
/* Mark the additional names from relevant rrset as OK. */
mark_additional_rrset(pkt, msg, rrset);
/* only for RRsets that match the query name, other ones
* will be removed by sanitize, so no additional for them */
if(dname_pkt_compare(pkt, qinfo->qname, rrset->dname) == 0)
mark_additional_rrset(pkt, msg, rrset);
prev = rrset;
rrset = rrset->rrset_all_next;
@@ -420,6 +427,24 @@ scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg,
/* Mark additional names from AUTHORITY */
while(rrset && rrset->section == LDNS_SECTION_AUTHORITY) {
if(rrset->type==LDNS_RR_TYPE_DNAME ||
rrset->type==LDNS_RR_TYPE_CNAME ||
rrset->type==LDNS_RR_TYPE_A ||
rrset->type==LDNS_RR_TYPE_AAAA) {
remove_rrset("normalize: removing irrelevant "
"RRset:", pkt, msg, prev, &rrset);
continue;
}
/* only one NS set allowed in authority section */
if(rrset->type==LDNS_RR_TYPE_NS) {
if(nsset == NULL) {
nsset = rrset;
} else {
remove_rrset("normalize: removing irrelevant "
"RRset:", pkt, msg, prev, &rrset);
continue;
}
}
mark_additional_rrset(pkt, msg, rrset);
prev = rrset;
rrset = rrset->rrset_all_next;
@@ -443,6 +468,13 @@ scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg,
continue;
}
}
if(rrset->type==LDNS_RR_TYPE_DNAME ||
rrset->type==LDNS_RR_TYPE_CNAME ||
rrset->type==LDNS_RR_TYPE_NS) {
remove_rrset("normalize: removing irrelevant "
"RRset:", pkt, msg, prev, &rrset);
continue;
}
prev = rrset;
rrset = rrset->rrset_all_next;
}
@@ -467,7 +499,7 @@ store_rrset(ldns_buffer* pkt, struct msg_parse* msg, struct module_env* env,
struct ub_packed_rrset_key* k;
struct packed_rrset_data* d;
struct rrset_ref ref;
uint32_t now = time(NULL);
uint32_t now = *env->now;
k = alloc_special_obtain(env->alloc);
if(!k)
@@ -494,18 +526,47 @@ store_rrset(ldns_buffer* pkt, struct msg_parse* msg, struct module_env* env,
*
* @param pkt: packet.
* @param msg: msg to normalize.
* @param qinfo: the question originally asked.
* @param zonename: name of server zone.
* @param env: module environment with config and cache.
* @return 0 on error.
*/
static int
scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg, uint8_t* zonename,
struct module_env* env)
scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg,
struct query_info* qinfo, uint8_t* zonename, struct module_env* env)
{
struct rrset_parse* rrset, *prev;
prev = NULL;
rrset = msg->rrset_first;
/* the first DNAME is allowed to stay. It needs checking before
* it can be used from the cache. After normalization, an initial
* DNAME will have a correctly synthesized CNAME after it. */
if(rrset && rrset->type == LDNS_RR_TYPE_DNAME &&
rrset->section == LDNS_SECTION_ANSWER &&
pkt_strict_sub(pkt, qinfo->qname, rrset->dname) &&
pkt_sub(pkt, rrset->dname, zonename)) {
prev = rrset; /* DNAME allowed to stay in answer section */
rrset = rrset->rrset_all_next;
}
/* remove all records from the answer section that are
* not the same domain name as the query domain name.
* The answer section should contain rrsets with the same name
* as the question. For DNAMEs a CNAME has been synthesized.
* Wildcards have the query name in answer section.
* ANY queries get query name in answer section.
* Remainders of CNAME chains are cut off and resolved by iterator. */
while(rrset && rrset->section == LDNS_SECTION_ANSWER) {
if(dname_pkt_compare(pkt, qinfo->qname, rrset->dname) != 0) {
remove_rrset("sanitize: removing extraneous answer "
"RRset:", pkt, msg, prev, &rrset);
continue;
}
prev = rrset;
rrset = rrset->rrset_all_next;
}
/* At this point, we brutally remove ALL rrsets that aren't
* children of the originating zone. The idea here is that,
* as far as we know, the server that we contacted is ONLY
@@ -513,6 +574,8 @@ scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg, uint8_t* zonename,
* be authoriative for any other zones, and of course, MAY
* NOT be authoritative for some subdomains of the originating
* zone. */
prev = NULL;
rrset = msg->rrset_first;
while(rrset) {
/* skip DNAME records -- they will always be followed by a
@@ -564,6 +627,14 @@ scrub_message(ldns_buffer* pkt, struct msg_parse* msg,
if( !(msg->flags&BIT_QR) )
return 0;
/* make sure that a query is echoed back when NOERROR or NXDOMAIN */
/* this is not required for basic operation but is a forgery
* resistance (security) feature */
if((FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR ||
FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NXDOMAIN) &&
msg->qdcount == 0)
return 0;
/* if a query is echoed back, make sure it is correct. Otherwise,
* this may be not a reply to our query. */
if(msg->qdcount == 1) {
@@ -577,7 +648,7 @@ scrub_message(ldns_buffer* pkt, struct msg_parse* msg,
if(!scrub_normalize(pkt, msg, qinfo, region))
return 0;
/* delete all out-of-zone information */
if(!scrub_sanitize(pkt, msg, zonename, env))
if(!scrub_sanitize(pkt, msg, qinfo, zonename, env))
return 0;
return 1;
}
+46 -23
View File
@@ -130,7 +130,8 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
/** filter out unsuitable targets, return rtt or -1 */
static int
iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
uint8_t* name, size_t namelen, time_t now, struct delegpt_addr* a)
uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now,
struct delegpt_addr* a)
{
int rtt;
int lame;
@@ -143,7 +144,7 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
}
/* check lameness - need zone , class info */
if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen,
name, namelen, &lame, &dnsseclame, &rtt, now)) {
name, namelen, qtype, &lame, &dnsseclame, &rtt, now)) {
if(lame)
return -1; /* server is lame */
else if(rtt >= USEFUL_SERVER_TOP_TIMEOUT)
@@ -156,38 +157,61 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
return UNKNOWN_SERVER_NICENESS;
}
/** lookup RTT information, and also store fastest rtt (if any) */
static int
iter_fill_rtt(struct iter_env* iter_env, struct module_env* env,
uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now,
struct delegpt* dp, int* best_rtt)
{
int got_it = 0;
struct delegpt_addr* a;
for(a=dp->result_list; a; a = a->next_result) {
a->sel_rtt = iter_filter_unsuitable(iter_env, env,
name, namelen, qtype, now, a);
if(a->sel_rtt != -1) {
if(!got_it) {
*best_rtt = a->sel_rtt;
got_it = 1;
} else if(a->sel_rtt < *best_rtt) {
*best_rtt = a->sel_rtt;
}
}
}
return got_it;
}
/** filter the addres list, putting best targets at front,
* returns number of best targets (or 0, no suitable targets) */
static int
iter_filter_order(struct iter_env* iter_env, struct module_env* env,
uint8_t* name, size_t namelen, time_t now, struct delegpt* dp,
int* best_rtt)
uint8_t* name, size_t namelen, uint16_t qtype, uint32_t now,
struct delegpt* dp, int* selected_rtt)
{
int got_num = 0, got_rtt = 0, thisrtt, swap_to_front;
int got_num = 0, low_rtt = 0, swap_to_front;
struct delegpt_addr* a, *n, *prev=NULL;
/* fillup sel_rtt and find best rtt in the bunch */
got_num = iter_fill_rtt(iter_env, env, name, namelen, qtype, now, dp,
&low_rtt);
if(got_num == 0)
return 0;
got_num = 0;
a = dp->result_list;
while(a) {
/* filter out unsuitable targets */
thisrtt = iter_filter_unsuitable(iter_env, env, name, namelen,
now, a);
if(thisrtt == -1) {
/* skip unsuitable targets */
if(a->sel_rtt == -1) {
prev = a;
a = a->next_result;
continue;
}
/* classify the server address and determine what to do */
swap_to_front = 0;
if(got_num == 0) {
got_rtt = thisrtt;
got_num = 1;
swap_to_front = 1;
} else if(thisrtt == got_rtt) {
if(a->sel_rtt >= low_rtt && a->sel_rtt - low_rtt <= RTT_BAND) {
got_num++;
swap_to_front = 1;
} else if(thisrtt < got_rtt) {
got_rtt = thisrtt;
got_num = 1; /* start back at count of 1 */
} else if(a->sel_rtt<low_rtt && low_rtt-a->sel_rtt<=RTT_BAND) {
got_num++;
swap_to_front = 1;
}
/* swap to front if necessary, or move to next result */
@@ -202,21 +226,20 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
a = a->next_result;
}
}
*best_rtt = got_rtt;
*selected_rtt = low_rtt;
return got_num;
}
struct delegpt_addr*
iter_server_selection(struct iter_env* iter_env,
struct module_env* env, struct delegpt* dp,
uint8_t* name, size_t namelen, int* dnssec_expected)
uint8_t* name, size_t namelen, uint16_t qtype, int* dnssec_expected)
{
time_t now = time(NULL);
int sel;
int selrtt;
struct delegpt_addr* a, *prev;
int num = iter_filter_order(iter_env, env, name, namelen, now, dp,
&selrtt);
int num = iter_filter_order(iter_env, env, name, namelen, qtype,
*env->now, dp, &selrtt);
if(num == 0)
return NULL;
@@ -313,7 +336,7 @@ causes_cycle(struct module_qstate* qstate, uint8_t* name, size_t namelen,
qinf.qname_len = namelen;
qinf.qtype = t;
qinf.qclass = c;
log_assert(fptr_whitelist_modenv_detect_cycle(
fptr_ok(fptr_whitelist_modenv_detect_cycle(
qstate->env->detect_cycle));
return (*qstate->env->detect_cycle)(qstate, &qinf,
(uint16_t)(BIT_RD|BIT_CD), qstate->is_priming);
+2 -1
View File
@@ -74,6 +74,7 @@ int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg);
* @param dp: delegation point with result list.
* @param name: zone name (for lameness check).
* @param namelen: length of name.
* @param qtype: query type that we want to send.
* @param dnssec_expected: set to 0, if a known dnssec-lame server is selected
* these are not preferred, but are used as a last resort.
* @return best target or NULL if no target.
@@ -81,7 +82,7 @@ int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg);
*/
struct delegpt_addr* iter_server_selection(struct iter_env* iter_env,
struct module_env* env, struct delegpt* dp, uint8_t* name,
size_t namelen, int* dnssec_expected);
size_t namelen, uint16_t qtype, int* dnssec_expected);
/**
* Allocate dns_msg from parsed msg, in regional.
+20 -29
View File
@@ -456,7 +456,7 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
qflags |= BIT_CD;
/* attach subquery, lookup existing or make a new one */
log_assert(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, &subq)) {
return 0;
}
@@ -469,7 +469,7 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
sizeof(struct iter_qstate));
if(!subq->minfo[id]) {
log_err("init subq: out of memory");
log_assert(fptr_whitelist_modenv_kill_sub(
fptr_ok(fptr_whitelist_modenv_kill_sub(
qstate->env->kill_sub));
(*qstate->env->kill_sub)(subq);
return 0;
@@ -587,7 +587,7 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq,
subiq->dp = delegpt_copy(stub_dp, subq->region);
if(!subiq->dp) {
log_err("out of memory priming stub, copydp");
log_assert(fptr_whitelist_modenv_kill_sub(
fptr_ok(fptr_whitelist_modenv_kill_sub(
qstate->env->kill_sub));
(*qstate->env->kill_sub)(subq);
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
@@ -759,7 +759,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
* cache needs to be primed for the qclass. */
iq->dp = dns_cache_find_delegation(qstate->env, delname,
delnamelen, iq->qchase.qtype, iq->qchase.qclass,
qstate->region, &iq->deleg_msg, (uint32_t)time(NULL));
qstate->region, &iq->deleg_msg, *qstate->env->now);
/* If the cache has returned nothing, then we have a
* root priming situation. */
@@ -825,17 +825,6 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
verbose(VERB_ALGO, "cache delegation returns delegpt");
delegpt_log(VERB_ALGO, iq->dp);
/* if the cache reply dp equals a validation anchor or msg has DS,
* then DNSSEC RRSIGs are expected in the reply */
iq->dnssec_expected = iter_indicates_dnssec(qstate->env, iq->dp,
iq->deleg_msg, iq->qchase.qclass);
/* Reset the RD flag. If this is a query restart, then the RD
* will have been turned off. */
if(qstate->query_flags & BIT_RD)
iq->chase_flags |= BIT_RD;
else iq->chase_flags &= ~BIT_RD;
/* Otherwise, set the current delegation point and move on to the
* next state. */
return next_state(iq, INIT_REQUEST_2_STATE);
@@ -890,9 +879,14 @@ processInitRequest3(struct module_qstate* qstate, struct iter_qstate* iq)
{
log_query_info(VERB_QUERY, "resolving (init part 3): ",
&qstate->qinfo);
/* if the cache reply dp equals a validation anchor or msg has DS,
* then DNSSEC RRSIGs are expected in the reply */
iq->dnssec_expected = iter_indicates_dnssec(qstate->env, iq->dp,
iq->deleg_msg, iq->qchase.qclass);
/* If the RD flag wasn't set, then we just finish with the
* cached referral as the response. */
if(!(iq->chase_flags & BIT_RD)) {
if(!(qstate->query_flags & BIT_RD)) {
iq->response = iq->deleg_msg;
if(verbosity >= VERB_ALGO)
log_dns_msg("no RD requested, using delegation msg",
@@ -1106,7 +1100,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
/* Select the next usable target, filtering out unsuitable targets. */
target = iter_server_selection(ie, qstate->env, iq->dp,
iq->dp->name, iq->dp->namelen, &iq->dnssec_expected);
iq->dp->name, iq->dp->namelen, iq->qchase.qtype,
&iq->dnssec_expected);
/* If no usable target was selected... */
if(!target) {
@@ -1167,7 +1162,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
log_query_info(VERB_QUERY, "sending query:", &iq->qchase);
log_name_addr(VERB_QUERY, "sending to target:", iq->dp->name,
&target->addr, target->addrlen);
log_assert(fptr_whitelist_modenv_send_query(qstate->env->send_query));
fptr_ok(fptr_whitelist_modenv_send_query(qstate->env->send_query));
outq = (*qstate->env->send_query)(
iq->qchase.qname, iq->qchase.qname_len,
iq->qchase.qtype, iq->qchase.qclass,
@@ -1246,7 +1241,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
/* close down outstanding requests to be discarded */
outbound_list_clear(&iq->outlist);
iq->num_current_queries = 0;
log_assert(fptr_whitelist_modenv_detach_subs(
fptr_ok(fptr_whitelist_modenv_detach_subs(
qstate->env->detach_subs));
(*qstate->env->detach_subs)(qstate);
iq->num_target_queries = 0;
@@ -1284,7 +1279,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
*/
outbound_list_clear(&iq->outlist);
iq->num_current_queries = 0;
log_assert(fptr_whitelist_modenv_detach_subs(
fptr_ok(fptr_whitelist_modenv_detach_subs(
qstate->env->detach_subs));
(*qstate->env->detach_subs)(qstate);
iq->num_target_queries = 0;
@@ -1326,7 +1321,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
*/
outbound_list_clear(&iq->outlist);
iq->num_current_queries = 0;
log_assert(fptr_whitelist_modenv_detach_subs(
fptr_ok(fptr_whitelist_modenv_detach_subs(
qstate->env->detach_subs));
(*qstate->env->detach_subs)(qstate);
iq->num_target_queries = 0;
@@ -1342,8 +1337,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
* gotten this from cache, so test to be sure */
if(!infra_set_lame(qstate->env->infra_cache,
&qstate->reply->addr, qstate->reply->addrlen,
iq->dp->name, iq->dp->namelen, time(NULL),
dnsseclame))
iq->dp->name, iq->dp->namelen,
*qstate->env->now, dnsseclame,
iq->qchase.qtype))
log_err("mark host lame: out of memory");
} else log_err("%slame response from cache",
dnsseclame?"DNSSEC ":"");
@@ -1572,11 +1568,6 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
LDNS_RCODE_SERVFAIL);
}
}
if(query_dname_compare(qstate->qinfo.qname,
iq->response->qinfo.qname) == 0) {
/* use server supplied upper/lower case */
qstate->qinfo.qname = iq->response->qinfo.qname;
}
qstate->return_rcode = LDNS_RCODE_NOERROR;
qstate->return_msg = iq->response;
return 0;
@@ -1728,7 +1719,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
iq->response = dns_alloc_msg(pkt, prs, qstate->region);
if(!iq->response)
goto handle_it;
log_query_info(VERB_DETAIL, "reponse for", &qstate->qinfo);
log_query_info(VERB_DETAIL, "response for", &qstate->qinfo);
log_name_addr(VERB_DETAIL, "reply from", iq->dp->name,
&qstate->reply->addr, qstate->reply->addrlen);
if(verbosity >= VERB_ALGO)
+4
View File
@@ -66,6 +66,10 @@ struct iter_prep_list;
#define USEFUL_SERVER_TOP_TIMEOUT 120000
/** number of retries on outgoing queries */
#define OUTBOUND_MSG_RETRY 4
/** RTT band, within this amount from the best, servers are chosen randomly.
* Chosen so that the UNKNOWN_SERVER_NICENESS falls within the band of a
* fast server, this causes server exploration as a side benefit. msec. */
#define RTT_BAND 400
/**
* Global state for the iterator.
BIN
View File
Binary file not shown.
+16 -14
View File
@@ -51,11 +51,13 @@
#include "util/storage/slabhash.h"
int
context_finalize(struct ub_val_ctx* ctx)
context_finalize(struct ub_ctx* ctx)
{
struct config_file* cfg = ctx->env->cfg;
verbosity = cfg->verbosity;
log_init(cfg->logfile, cfg->use_syslog, NULL);
if(ctx->logfile_override)
log_file(ctx->log_out);
else log_init(cfg->logfile, cfg->use_syslog, NULL);
config_apply(cfg);
if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env))
return UB_INITFAIL;
@@ -99,7 +101,7 @@ void
context_query_delete(struct ctx_query* q)
{
if(!q) return;
ub_val_resolve_free(q->res);
ub_resolve_free(q->res);
free(q->msg);
free(q);
}
@@ -108,7 +110,7 @@ context_query_delete(struct ctx_query* q)
#define NUM_ID_TRIES 100000
/** find next useful id number of 0 on error */
static int
find_id(struct ub_val_ctx* ctx, int* id)
find_id(struct ub_ctx* ctx, int* id)
{
size_t tries = 0;
ctx->next_querynum++;
@@ -122,8 +124,8 @@ find_id(struct ub_val_ctx* ctx, int* id)
}
struct ctx_query*
context_new(struct ub_val_ctx* ctx, char* name, int rrtype, int rrclass,
ub_val_callback_t cb, void* cbarg)
context_new(struct ub_ctx* ctx, char* name, int rrtype, int rrclass,
ub_callback_t cb, void* cbarg)
{
struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q));
if(!q) return NULL;
@@ -138,7 +140,7 @@ context_new(struct ub_val_ctx* ctx, char* name, int rrtype, int rrclass,
q->async = (cb != NULL);
q->cb = cb;
q->cb_arg = cbarg;
q->res = (struct ub_val_result*)calloc(1, sizeof(*q->res));
q->res = (struct ub_result*)calloc(1, sizeof(*q->res));
if(!q->res) {
free(q);
return NULL;
@@ -162,7 +164,7 @@ context_new(struct ub_val_ctx* ctx, char* name, int rrtype, int rrclass,
}
struct alloc_cache*
context_obtain_alloc(struct ub_val_ctx* ctx, int locking)
context_obtain_alloc(struct ub_ctx* ctx, int locking)
{
struct alloc_cache* a;
int tnum = 0;
@@ -188,7 +190,7 @@ context_obtain_alloc(struct ub_val_ctx* ctx, int locking)
}
void
context_release_alloc(struct ub_val_ctx* ctx, struct alloc_cache* alloc,
context_release_alloc(struct ub_ctx* ctx, struct alloc_cache* alloc,
int locking)
{
if(!ctx || !alloc)
@@ -227,7 +229,7 @@ context_serialize_new_query(struct ctx_query* q, uint32_t* len)
}
struct ctx_query*
context_deserialize_new_query(struct ub_val_ctx* ctx, uint8_t* p, uint32_t len)
context_deserialize_new_query(struct ub_ctx* ctx, uint8_t* p, uint32_t len)
{
struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q));
if(!q) return NULL;
@@ -239,7 +241,7 @@ context_deserialize_new_query(struct ub_val_ctx* ctx, uint8_t* p, uint32_t len)
q->querynum = (int)ldns_read_uint32(p+sizeof(uint32_t));
q->node.key = &q->querynum;
q->async = 1;
q->res = (struct ub_val_result*)calloc(1, sizeof(*q->res));
q->res = (struct ub_result*)calloc(1, sizeof(*q->res));
if(!q->res) {
free(q);
return NULL;
@@ -260,7 +262,7 @@ context_deserialize_new_query(struct ub_val_ctx* ctx, uint8_t* p, uint32_t len)
}
struct ctx_query*
context_lookup_new_query(struct ub_val_ctx* ctx, uint8_t* p, uint32_t len)
context_lookup_new_query(struct ub_ctx* ctx, uint8_t* p, uint32_t len)
{
struct ctx_query* q;
int querynum;
@@ -304,7 +306,7 @@ context_serialize_answer(struct ctx_query* q, int err, ldns_buffer* pkt,
}
struct ctx_query*
context_deserialize_answer(struct ub_val_ctx* ctx,
context_deserialize_answer(struct ub_ctx* ctx,
uint8_t* p, uint32_t len, int* err)
{
struct ctx_query* q = NULL ;
@@ -343,7 +345,7 @@ context_serialize_cancel(struct ctx_query* q, uint32_t* len)
return p;
}
struct ctx_query* context_deserialize_cancel(struct ub_val_ctx* ctx,
struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx,
uint8_t* p, uint32_t len)
{
struct ctx_query* q;
+16 -12
View File
@@ -55,7 +55,7 @@ struct libworker;
* qq : write queries to the async service pid/tid.
* rr : read results from the async service pid/tid.
*/
struct ub_val_ctx {
struct ub_ctx {
/* --- pipes --- */
/** mutex on query write pipe */
lock_basic_t qqpipe_lock;
@@ -87,6 +87,10 @@ struct ub_val_ctx {
int dothread;
/** next thread number for new threads */
int thr_next_num;
/** if logfile is overriden */
int logfile_override;
/** what logfile to use instead */
FILE* log_out;
/**
* List of alloc-cache-id points per threadnum for notinuse threads.
* Simply the entire struct alloc_cache with the 'super' member used
@@ -137,7 +141,7 @@ struct ctx_query {
int cancelled;
/** for async query, the callback function */
ub_val_callback_t cb;
ub_callback_t cb;
/** for async query, the callback user arg */
void* cb_arg;
@@ -152,7 +156,7 @@ struct ctx_query {
/** result structure, also contains original query, type, class.
* malloced ptr ready to hand to the client. */
struct ub_val_result* res;
struct ub_result* res;
};
/**
@@ -206,7 +210,7 @@ enum ub_ctx_cmd {
* @param ctx: context to finalize. creates shared data.
* @return 0 if OK, or errcode.
*/
int context_finalize(struct ub_val_ctx* ctx);
int context_finalize(struct ub_ctx* ctx);
/** compare two ctx_query elements */
int context_query_cmp(const void* a, const void* b);
@@ -227,8 +231,8 @@ void context_query_delete(struct ctx_query* q);
* @param cbarg: user arg for async queries.
* @return new ctx_query or NULL for malloc failure.
*/
struct ctx_query* context_new(struct ub_val_ctx* ctx, char* name, int rrtype,
int rrclass, ub_val_callback_t cb, void* cbarg);
struct ctx_query* context_new(struct ub_ctx* ctx, char* name, int rrtype,
int rrclass, ub_callback_t cb, void* cbarg);
/**
* Get a new alloc. Creates a new one or uses a cached one.
@@ -236,7 +240,7 @@ struct ctx_query* context_new(struct ub_val_ctx* ctx, char* name, int rrtype,
* @param locking: if true, cfglock is locked while getting alloc.
* @return an alloc, or NULL on mem error.
*/
struct alloc_cache* context_obtain_alloc(struct ub_val_ctx* ctx, int locking);
struct alloc_cache* context_obtain_alloc(struct ub_ctx* ctx, int locking);
/**
* Release an alloc. Puts it into the cache.
@@ -244,7 +248,7 @@ struct alloc_cache* context_obtain_alloc(struct ub_val_ctx* ctx, int locking);
* @param locking: if true, cfglock is locked while releasing alloc.
* @param alloc: alloc to relinquish.
*/
void context_release_alloc(struct ub_val_ctx* ctx, struct alloc_cache* alloc,
void context_release_alloc(struct ub_ctx* ctx, struct alloc_cache* alloc,
int locking);
/**
@@ -301,7 +305,7 @@ enum ub_ctx_cmd context_serial_getcmd(uint8_t* p, uint32_t len);
* @param len: length of buffer.
* @return looked up ctx_query or NULL for malloc failure.
*/
struct ctx_query* context_lookup_new_query(struct ub_val_ctx* ctx,
struct ctx_query* context_lookup_new_query(struct ub_ctx* ctx,
uint8_t* p, uint32_t len);
/**
@@ -311,7 +315,7 @@ struct ctx_query* context_lookup_new_query(struct ub_val_ctx* ctx,
* @param len: length of buffer.
* @return new ctx_query or NULL for malloc failure.
*/
struct ctx_query* context_deserialize_new_query(struct ub_val_ctx* ctx,
struct ctx_query* context_deserialize_new_query(struct ub_ctx* ctx,
uint8_t* p, uint32_t len);
/**
@@ -322,7 +326,7 @@ struct ctx_query* context_deserialize_new_query(struct ub_val_ctx* ctx,
* @param err: error code to be returned to client is passed.
* @return ctx_query with answer added or NULL for malloc failure.
*/
struct ctx_query* context_deserialize_answer(struct ub_val_ctx* ctx,
struct ctx_query* context_deserialize_answer(struct ub_ctx* ctx,
uint8_t* p, uint32_t len, int* err);
/**
@@ -332,7 +336,7 @@ struct ctx_query* context_deserialize_answer(struct ub_val_ctx* ctx,
* @param len: length of buffer.
* @return ctx_query to cancel or NULL for failure.
*/
struct ctx_query* context_deserialize_cancel(struct ub_val_ctx* ctx,
struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx,
uint8_t* p, uint32_t len);
#endif /* LIBUNBOUND_CONTEXT_H */
+173 -41
View File
@@ -59,16 +59,28 @@
#include "services/cache/infra.h"
#include "services/cache/rrset.h"
struct ub_val_ctx*
ub_val_ctx_create()
struct ub_ctx*
ub_ctx_create()
{
struct ub_val_ctx* ctx;
struct ub_ctx* ctx;
unsigned int seed;
#ifdef USE_WINSOCK
int r;
WSADATA wsa_data;
#endif
log_init(NULL, 0, NULL); /* logs to stderr */
log_ident_set("libunbound");
#ifdef USE_WINSOCK
if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) {
log_err("could not init winsock. WSAStartup: %s",
wsa_strerror(r));
return NULL;
}
#endif
verbosity = 0; /* errors only */
checklock_start();
ctx = (struct ub_val_ctx*)calloc(1, sizeof(*ctx));
ctx = (struct ub_ctx*)calloc(1, sizeof(*ctx));
if(!ctx) {
errno = ENOMEM;
return NULL;
@@ -97,6 +109,7 @@ ub_val_ctx_create()
errno = e;
return NULL;
}
#ifndef USE_WINSOCK
if(!fd_set_nonblock(ctx->rrpipe[0]) ||
!fd_set_nonblock(ctx->rrpipe[1]) ||
!fd_set_nonblock(ctx->qqpipe[0]) ||
@@ -111,6 +124,7 @@ ub_val_ctx_create()
errno = e;
return NULL;
}
#endif /* !USE_WINSOCK - it is a pipe(nonsocket) on windows) */
lock_basic_init(&ctx->qqpipe_lock);
lock_basic_init(&ctx->rrpipe_lock);
lock_basic_init(&ctx->cfglock);
@@ -154,7 +168,7 @@ delq(rbnode_t* n, void* ATTR_UNUSED(arg))
}
void
ub_val_ctx_delete(struct ub_val_ctx* ctx)
ub_ctx_delete(struct ub_ctx* ctx)
{
struct alloc_cache* a, *na;
if(!ctx) return;
@@ -231,10 +245,29 @@ ub_val_ctx_delete(struct ub_val_ctx* ctx)
alloc_clear(&ctx->superalloc);
traverse_postorder(&ctx->queries, delq, NULL);
free(ctx);
#ifdef USE_WINSOCK
WSACleanup();
#endif
}
int
ub_val_ctx_config(struct ub_val_ctx* ctx, char* fname)
ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val)
{
lock_basic_lock(&ctx->cfglock);
if(ctx->finalized) {
lock_basic_unlock(&ctx->cfglock);
return UB_AFTERFINAL;
}
if(!config_set_option(ctx->env->cfg, opt, val)) {
lock_basic_unlock(&ctx->cfglock);
return UB_SYNTAX;
}
lock_basic_unlock(&ctx->cfglock);
return UB_NOERROR;
}
int
ub_ctx_config(struct ub_ctx* ctx, char* fname)
{
lock_basic_lock(&ctx->cfglock);
if(ctx->finalized) {
@@ -250,7 +283,7 @@ ub_val_ctx_config(struct ub_val_ctx* ctx, char* fname)
}
int
ub_val_ctx_add_ta(struct ub_val_ctx* ctx, char* ta)
ub_ctx_add_ta(struct ub_ctx* ctx, char* ta)
{
char* dup = strdup(ta);
if(!dup) return UB_NOMEM;
@@ -269,7 +302,7 @@ ub_val_ctx_add_ta(struct ub_val_ctx* ctx, char* ta)
}
int
ub_val_ctx_add_ta_file(struct ub_val_ctx* ctx, char* fname)
ub_ctx_add_ta_file(struct ub_ctx* ctx, char* fname)
{
char* dup = strdup(fname);
if(!dup) return UB_NOMEM;
@@ -288,7 +321,7 @@ ub_val_ctx_add_ta_file(struct ub_val_ctx* ctx, char* fname)
}
int
ub_val_ctx_trustedkeys(struct ub_val_ctx* ctx, char* fname)
ub_ctx_trustedkeys(struct ub_ctx* ctx, char* fname)
{
char* dup = strdup(fname);
if(!dup) return UB_NOMEM;
@@ -307,7 +340,7 @@ ub_val_ctx_trustedkeys(struct ub_val_ctx* ctx, char* fname)
}
int
ub_val_ctx_debuglevel(struct ub_val_ctx* ctx, int d)
ub_ctx_debuglevel(struct ub_ctx* ctx, int d)
{
lock_basic_lock(&ctx->cfglock);
verbosity = d;
@@ -316,10 +349,20 @@ ub_val_ctx_debuglevel(struct ub_val_ctx* ctx, int d)
return UB_NOERROR;
}
int
ub_val_ctx_async(struct ub_val_ctx* ctx, int dothread)
int ub_ctx_debugout(struct ub_ctx* ctx, void* out)
{
#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
lock_basic_lock(&ctx->cfglock);
log_file((FILE*)out);
ctx->logfile_override = 1;
ctx->log_out = out;
lock_basic_unlock(&ctx->cfglock);
return UB_NOERROR;
}
int
ub_ctx_async(struct ub_ctx* ctx, int dothread)
{
#ifdef THREADS_DISABLED
if(dothread) /* cannot do threading */
return UB_NOERROR;
#endif
@@ -335,12 +378,12 @@ ub_val_ctx_async(struct ub_val_ctx* ctx, int dothread)
/** perform a select() on the result read pipe */
static int
pollit(struct ub_val_ctx* ctx, struct timeval* t)
pollit(struct ub_ctx* ctx, struct timeval* t)
{
fd_set r;
#ifndef S_SPLINT_S
FD_ZERO(&r);
FD_SET(ctx->rrpipe[0], &r);
FD_SET(FD_SET_T ctx->rrpipe[0], &r);
#endif
if(select(ctx->rrpipe[0]+1, &r, NULL, NULL, t) == -1) {
return 0;
@@ -350,7 +393,7 @@ pollit(struct ub_val_ctx* ctx, struct timeval* t)
}
int
ub_val_poll(struct ub_val_ctx* ctx)
ub_poll(struct ub_ctx* ctx)
{
struct timeval t;
memset(&t, 0, sizeof(t));
@@ -359,16 +402,16 @@ ub_val_poll(struct ub_val_ctx* ctx)
}
int
ub_val_fd(struct ub_val_ctx* ctx)
ub_fd(struct ub_ctx* ctx)
{
return ctx->rrpipe[0];
}
/** process answer from bg worker */
static int
process_answer_detail(struct ub_val_ctx* ctx, uint8_t* msg, uint32_t len,
ub_val_callback_t* cb, void** cbarg, int* err,
struct ub_val_result** res)
process_answer_detail(struct ub_ctx* ctx, uint8_t* msg, uint32_t len,
ub_callback_t* cb, void** cbarg, int* err,
struct ub_result** res)
{
struct ctx_query* q;
if(context_serial_getcmd(msg, len) != UB_LIBCMD_ANSWER) {
@@ -397,7 +440,7 @@ process_answer_detail(struct ub_val_ctx* ctx, uint8_t* msg, uint32_t len,
}
if(*err) {
*res = NULL;
ub_val_resolve_free(q->res);
ub_resolve_free(q->res);
} else {
/* parse the message, extract rcode, fill result */
ldns_buffer* buf = ldns_buffer_new(q->msg_len);
@@ -411,6 +454,9 @@ process_answer_detail(struct ub_val_ctx* ctx, uint8_t* msg, uint32_t len,
libworker_enter_result(*res, buf, region,
q->msg_security);
}
(*res)->answer_packet = q->msg;
(*res)->answer_len = (int)q->msg_len;
q->msg = NULL;
ldns_buffer_free(buf);
regional_destroy(region);
}
@@ -422,17 +468,18 @@ process_answer_detail(struct ub_val_ctx* ctx, uint8_t* msg, uint32_t len,
lock_basic_unlock(&ctx->cfglock);
if(*cb) return 2;
ub_resolve_free(*res);
return 1;
}
/** process answer from bg worker */
static int
process_answer(struct ub_val_ctx* ctx, uint8_t* msg, uint32_t len)
process_answer(struct ub_ctx* ctx, uint8_t* msg, uint32_t len)
{
int err;
ub_val_callback_t cb;
ub_callback_t cb;
void* cbarg;
struct ub_val_result* res;
struct ub_result* res;
int r;
r = process_answer_detail(ctx, msg, len, &cb, &cbarg, &err, &res);
@@ -446,7 +493,7 @@ process_answer(struct ub_val_ctx* ctx, uint8_t* msg, uint32_t len)
}
int
ub_val_process(struct ub_val_ctx* ctx)
ub_process(struct ub_ctx* ctx)
{
int r;
uint8_t* msg;
@@ -470,12 +517,12 @@ ub_val_process(struct ub_val_ctx* ctx)
}
int
ub_val_wait(struct ub_val_ctx* ctx)
ub_wait(struct ub_ctx* ctx)
{
int err;
ub_val_callback_t cb;
ub_callback_t cb;
void* cbarg;
struct ub_val_result* res;
struct ub_result* res;
int r;
uint8_t* msg;
uint32_t len;
@@ -511,6 +558,7 @@ ub_val_wait(struct ub_val_ctx* ctx)
r = process_answer_detail(ctx, msg, len,
&cb, &cbarg, &err, &res);
lock_basic_unlock(&ctx->rrpipe_lock);
free(msg);
if(r == 0)
return UB_PIPE;
if(r == 2)
@@ -523,11 +571,12 @@ ub_val_wait(struct ub_val_ctx* ctx)
}
int
ub_val_resolve(struct ub_val_ctx* ctx, char* name, int rrtype,
int rrclass, struct ub_val_result** result)
ub_resolve(struct ub_ctx* ctx, char* name, int rrtype,
int rrclass, struct ub_result** result)
{
struct ctx_query* q;
int r;
*result = NULL;
lock_basic_lock(&ctx->cfglock);
if(!ctx->finalized) {
@@ -543,7 +592,6 @@ ub_val_resolve(struct ub_val_ctx* ctx, char* name, int rrtype,
if(!q)
return UB_NOMEM;
/* become a resolver thread for a bit */
*result = NULL;
r = libworker_fg(ctx, q);
if(r) {
@@ -553,6 +601,9 @@ ub_val_resolve(struct ub_val_ctx* ctx, char* name, int rrtype,
lock_basic_unlock(&ctx->cfglock);
return r;
}
q->res->answer_packet = q->msg;
q->res->answer_len = (int)q->msg_len;
q->msg = NULL;
*result = q->res;
q->res = NULL;
@@ -564,8 +615,8 @@ ub_val_resolve(struct ub_val_ctx* ctx, char* name, int rrtype,
}
int
ub_val_resolve_async(struct ub_val_ctx* ctx, char* name, int rrtype,
int rrclass, void* mydata, ub_val_callback_t callback, int* async_id)
ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype,
int rrclass, void* mydata, ub_callback_t callback, int* async_id)
{
struct ctx_query* q;
uint8_t* msg = NULL;
@@ -627,7 +678,7 @@ ub_val_resolve_async(struct ub_val_ctx* ctx, char* name, int rrtype,
}
int
ub_val_cancel(struct ub_val_ctx* ctx, int async_id)
ub_cancel(struct ub_ctx* ctx, int async_id)
{
struct ctx_query* q;
uint8_t* msg = NULL;
@@ -646,8 +697,8 @@ ub_val_cancel(struct ub_val_ctx* ctx, int async_id)
if(!ctx->dothread) { /* if forked */
(void)rbtree_delete(&ctx->queries, q->node.key);
ctx->num_async--;
context_query_delete(q);
msg = context_serialize_cancel(q, &len);
context_query_delete(q);
lock_basic_unlock(&ctx->cfglock);
if(!msg) {
return UB_NOMEM;
@@ -668,7 +719,7 @@ ub_val_cancel(struct ub_val_ctx* ctx, int async_id)
}
void
ub_val_resolve_free(struct ub_val_result* result)
ub_resolve_free(struct ub_result* result)
{
char** p;
if(!result) return;
@@ -680,11 +731,12 @@ ub_val_resolve_free(struct ub_val_result* result)
free(*p);
free(result->data);
free(result->len);
free(result->answer_packet);
free(result);
}
const char*
ub_val_strerror(int err)
ub_strerror(int err)
{
switch(err) {
case UB_NOERROR: return "no error";
@@ -702,7 +754,7 @@ ub_val_strerror(int err)
}
int
ub_val_ctx_set_fwd(struct ub_val_ctx* ctx, char* addr)
ub_ctx_set_fwd(struct ub_ctx* ctx, char* addr)
{
struct sockaddr_storage storage;
socklen_t stlen;
@@ -774,7 +826,7 @@ ub_val_ctx_set_fwd(struct ub_val_ctx* ctx, char* addr)
}
int
ub_val_ctx_resolvconf(struct ub_val_ctx* ctx, char* fname)
ub_ctx_resolvconf(struct ub_ctx* ctx, char* fname)
{
FILE* in;
int numserv = 0;
@@ -806,7 +858,7 @@ ub_val_ctx_resolvconf(struct ub_val_ctx* ctx, char* fname)
/* terminate after the address, remove newline */
*parse = 0;
if((r = ub_val_ctx_set_fwd(ctx, addr)) != UB_NOERROR) {
if((r = ub_ctx_set_fwd(ctx, addr)) != UB_NOERROR) {
fclose(in);
return r;
}
@@ -815,7 +867,87 @@ ub_val_ctx_resolvconf(struct ub_val_ctx* ctx, char* fname)
fclose(in);
if(numserv == 0) {
/* from resolv.conf(5) if none given, use localhost */
return ub_val_ctx_set_fwd(ctx, "127.0.0.1");
return ub_ctx_set_fwd(ctx, "127.0.0.1");
}
return UB_NOERROR;
}
int
ub_ctx_hosts(struct ub_ctx* ctx, char* fname)
{
FILE* in;
char buf[1024], ldata[1024];
char* parse, *addr, *name, *ins;
lock_basic_lock(&ctx->cfglock);
if(ctx->finalized) {
lock_basic_unlock(&ctx->cfglock);
errno=EINVAL;
return UB_AFTERFINAL;
}
lock_basic_unlock(&ctx->cfglock);
if(fname == NULL)
fname = "/etc/hosts";
in = fopen(fname, "r");
if(!in) {
/* error in errno! perror(fname) */
return UB_READFILE;
}
while(fgets(buf, (int)sizeof(buf), in)) {
buf[sizeof(buf)-1] = 0;
parse=buf;
while(*parse == ' ' || *parse == '\t')
parse++;
if(*parse == '#')
continue; /* skip comment */
/* format: <addr> spaces <name> spaces <name> ... */
addr = parse;
/* skip addr */
while(isxdigit(*parse) || *parse == '.' || *parse == ':')
parse++;
if(*parse == '\n' || *parse == 0)
continue;
if(*parse == '%')
continue; /* ignore macOSX fe80::1%lo0 localhost */
if(*parse != ' ' && *parse != '\t') {
/* must have whitespace after address */
fclose(in);
errno=EINVAL;
return UB_SYNTAX;
}
*parse++ = 0; /* end delimiter for addr ... */
/* go to names and add them */
while(*parse) {
while(*parse == ' ' || *parse == '\t' || *parse=='\n')
parse++;
if(*parse == 0 || *parse == '#')
break;
/* skip name, allows (too) many printable characters */
name = parse;
while('!' <= *parse && *parse <= '~')
parse++;
if(*parse)
*parse++ = 0; /* end delimiter for name */
snprintf(ldata, sizeof(ldata), "%s %s %s",
name, str_is_ip6(addr)?"AAAA":"A", addr);
ins = strdup(ldata);
if(!ins) {
/* out of memory */
fclose(in);
errno=ENOMEM;
return UB_NOMEM;
}
lock_basic_lock(&ctx->cfglock);
if(!cfg_strlist_insert(&ctx->env->cfg->local_data,
ins)) {
lock_basic_unlock(&ctx->cfglock);
fclose(in);
free(ins);
errno=ENOMEM;
return UB_NOMEM;
}
lock_basic_unlock(&ctx->cfglock);
}
}
fclose(in);
return UB_NOERROR;
}
+47 -16
View File
@@ -88,11 +88,13 @@ libworker_delete(struct libworker* w)
/** setup fresh libworker struct */
static struct libworker*
libworker_setup(struct ub_val_ctx* ctx, int is_bg)
libworker_setup(struct ub_ctx* ctx, int is_bg)
{
unsigned int seed;
struct libworker* w = (struct libworker*)calloc(1, sizeof(*w));
struct config_file* cfg = ctx->env->cfg;
int* ports;
int numports;
if(!w) return NULL;
w->is_bg = is_bg;
w->ctx = ctx;
@@ -149,14 +151,21 @@ libworker_setup(struct ub_val_ctx* ctx, int is_bg)
if(!w->is_bg || w->is_bg_thread) {
lock_basic_lock(&ctx->cfglock);
}
numports = cfg_condense_ports(cfg, &ports);
if(numports == 0) {
libworker_delete(w);
return NULL;
}
w->back = outside_network_create(w->base, cfg->msg_buffer_size,
(size_t)cfg->outgoing_num_ports, cfg->out_ifs,
cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6, -1,
cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6,
cfg->do_tcp?cfg->outgoing_num_tcp:0,
w->env->infra_cache, w->env->rnd);
w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id,
ports, numports);
if(!w->is_bg || w->is_bg_thread) {
lock_basic_unlock(&ctx->cfglock);
}
free(ports);
if(!w->back) {
libworker_delete(w);
return NULL;
@@ -172,6 +181,7 @@ libworker_setup(struct ub_val_ctx* ctx, int is_bg)
w->env->attach_sub = &mesh_attach_sub;
w->env->kill_sub = &mesh_state_delete;
w->env->detect_cycle = &mesh_detect_cycle;
comm_base_timept(w->base, &w->env->now, &w->env->now_tv);
return w;
}
@@ -354,9 +364,9 @@ libworker_dobg(void* arg)
uint32_t m;
int fd;
struct libworker* w = (struct libworker*)arg;
struct ub_val_ctx* ctx = w->ctx;
struct ub_ctx* ctx = w->ctx;
log_thread_set(&w->thread_num);
#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
#ifdef THREADS_DISABLED
/* we are forked */
w->is_bg_thread = 0;
/* close non-used parts of the pipes */
@@ -399,7 +409,7 @@ libworker_dobg(void* arg)
return NULL;
}
int libworker_bg(struct ub_val_ctx* ctx)
int libworker_bg(struct ub_ctx* ctx)
{
struct libworker* w;
/* fork or threadcreate */
@@ -415,6 +425,10 @@ int libworker_bg(struct ub_val_ctx* ctx)
ub_thread_create(&ctx->bg_tid, libworker_dobg, w);
} else {
lock_basic_unlock(&ctx->cfglock);
#ifndef HAVE_FORK
/* no fork on windows */
return UB_FORKFAIL;
#else /* HAVE_FORK */
switch((ctx->bg_pid=fork())) {
case 0:
w = libworker_setup(ctx, 1);
@@ -432,6 +446,7 @@ int libworker_bg(struct ub_val_ctx* ctx)
default:
break;
}
#endif /* HAVE_FORK */
}
return UB_NOERROR;
}
@@ -457,7 +472,7 @@ parse_reply(ldns_buffer* pkt, struct regional* region, struct query_info* qi)
/** insert canonname */
static int
fill_canon(struct ub_val_result* res, uint8_t* s)
fill_canon(struct ub_result* res, uint8_t* s)
{
char buf[255+2];
dname_str(s, buf);
@@ -467,7 +482,7 @@ fill_canon(struct ub_val_result* res, uint8_t* s)
/** fill data into result */
static int
fill_res(struct ub_val_result* res, struct ub_packed_rrset_key* answer,
fill_res(struct ub_result* res, struct ub_packed_rrset_key* answer,
uint8_t* finalcname, struct query_info* rq)
{
size_t i;
@@ -504,7 +519,7 @@ fill_res(struct ub_val_result* res, struct ub_packed_rrset_key* answer,
/** fill result from parsed message, on error fills servfail */
void
libworker_enter_result(struct ub_val_result* res, ldns_buffer* buf,
libworker_enter_result(struct ub_result* res, ldns_buffer* buf,
struct regional* temp, enum sec_status msg_security)
{
struct query_info rq;
@@ -591,7 +606,7 @@ setup_qinfo_edns(struct libworker* w, struct ctx_query* q,
return 1;
}
int libworker_fg(struct ub_val_ctx* ctx, struct ctx_query* q)
int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
{
struct libworker* w = libworker_setup(ctx, 0);
uint16_t qflags, qid;
@@ -690,7 +705,7 @@ libworker_bg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s)
if(q->cancelled) {
if(q->w->is_bg_thread) {
/* delete it now */
struct ub_val_ctx* ctx = q->w->ctx;
struct ub_ctx* ctx = q->w->ctx;
lock_basic_lock(&ctx->cfglock);
(void)rbtree_delete(&ctx->queries, q->node.key);
ctx->num_async--;
@@ -766,12 +781,10 @@ int libworker_send_packet(ldns_buffer* pkt, struct sockaddr_storage* addr,
struct libworker* w = (struct libworker*)q->env->worker;
if(use_tcp) {
return pending_tcp_query(w->back, pkt, addr, addrlen,
timeout, libworker_handle_reply, q,
q->env->rnd) != 0;
timeout, libworker_handle_reply, q) != 0;
}
return pending_udp_query(w->back, pkt, addr, addrlen,
timeout*1000, libworker_handle_reply, q,
q->env->rnd) != 0;
timeout*1000, libworker_handle_reply, q) != 0;
}
/** compare outbound entry qstates */
@@ -934,14 +947,18 @@ libworker_read_msg(int fd, uint8_t** buf, uint32_t* len, int nonblock)
if((r=read(fd, *buf, *len)) == -1) {
log_err("msg read failed: %s", strerror(errno));
(void)fd_set_nonblock(fd);
free(*buf);
return 0;
}
if(r == 0) { /* EOF */
(void)fd_set_nonblock(fd);
free(*buf);
return 0;
}
if(!fd_set_nonblock(fd))
if(!fd_set_nonblock(fd)) {
free(*buf);
return 0;
}
return 1;
}
@@ -1019,3 +1036,17 @@ void worker_stat_timer_cb(void* ATTR_UNUSED(arg))
{
log_assert(0);
}
int order_lock_cmp(const void* ATTR_UNUSED(e1), const void* ATTR_UNUSED(e2))
{
log_assert(0);
return 0;
}
int
codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
{
log_assert(0);
return 0;
}
+6 -6
View File
@@ -44,8 +44,8 @@
#ifndef LIBUNBOUND_WORKER_H
#define LIBUNBOUND_WORKER_H
#include "util/data/packed_rrset.h"
struct ub_val_ctx;
struct ub_val_result;
struct ub_ctx;
struct ub_result;
struct module_env;
struct comm_base;
struct outside_network;
@@ -66,7 +66,7 @@ struct libworker {
/** every worker has a unique thread_num. (first in struct) */
int thread_num;
/** context we are operating under */
struct ub_val_ctx* ctx;
struct ub_ctx* ctx;
/** is this the bg worker? */
int is_bg;
@@ -122,7 +122,7 @@ struct libworker_res_list {
* @return 0 if OK, else error.
* Further communication is done via the pipes in ctx.
*/
int libworker_bg(struct ub_val_ctx* ctx);
int libworker_bg(struct ub_ctx* ctx);
/**
* Create a foreground worker.
@@ -133,7 +133,7 @@ int libworker_bg(struct ub_val_ctx* ctx);
* @param q: query (result is stored in here).
* @return 0 if finished OK, else error.
*/
int libworker_fg(struct ub_val_ctx* ctx, struct ctx_query* q);
int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q);
/** cleanup the cache to remove all rrset IDs from it, arg is libworker */
void libworker_alloc_cleanup(void* arg);
@@ -230,7 +230,7 @@ int libworker_read_msg(int fd, uint8_t** buf, uint32_t* len, int nonblock);
* On error, the res may contain a different status
* (out of memory is not secure, not bogus).
*/
void libworker_enter_result(struct ub_val_result* res, ldns_buffer* buf,
void libworker_enter_result(struct ub_result* res, ldns_buffer* buf,
struct regional* temp, enum sec_status msg_security);
#endif /* LIBUNBOUND_WORKER_H */
+22 -19
View File
@@ -1,19 +1,22 @@
ub_val_ctx_create
ub_val_ctx_delete
ub_val_ctx_config
ub_val_ctx_set_fwd
ub_val_ctx_resolvconf
ub_val_ctx_add_ta
ub_val_ctx_add_ta_file
ub_val_ctx_trustedkeys
ub_val_ctx_debuglevel
ub_val_ctx_async
ub_val_poll
ub_val_wait
ub_val_fd
ub_val_process
ub_val_resolve
ub_val_resolve_async
ub_val_cancel
ub_val_resolve_free
ub_val_strerror
ub_ctx_create
ub_ctx_delete
ub_ctx_set_option
ub_ctx_config
ub_ctx_set_fwd
ub_ctx_resolvconf
ub_ctx_hosts
ub_ctx_add_ta
ub_ctx_add_ta_file
ub_ctx_trustedkeys
ub_ctx_debugout
ub_ctx_debuglevel
ub_ctx_async
ub_poll
ub_wait
ub_fd
ub_process
ub_resolve
ub_resolve_async
ub_cancel
ub_resolve_free
ub_strerror
+91 -44
View File
@@ -43,29 +43,29 @@
* to perform (validated) DNS lookups.
*
* All start with
* ctx = ub_val_ctx_create();
* err = ub_val_ctx_add_ta(ctx, "...");
* err = ub_val_ctx_add_ta(ctx, "...");
* ctx = ub_ctx_create();
* err = ub_ctx_add_ta(ctx, "...");
* err = ub_ctx_add_ta(ctx, "...");
* ... some lookups
* ... call ub_val_ctx_delete(ctx); when you want to stop.
* ... call ub_ctx_delete(ctx); when you want to stop.
*
* Application not threaded. Blocking.
* int err = ub_val_resolve(ctx, "www.example.com", ...
* if(err) fprintf(stderr, "lookup error: %s\n", ub_val_strerror(err));
* int err = ub_resolve(ctx, "www.example.com", ...
* if(err) fprintf(stderr, "lookup error: %s\n", ub_strerror(err));
* ... use the answer
*
* Application not threaded. Non-blocking ('asynchronous').
* err = ub_val_resolve_async(ctx, "www.example.com", ... my_callback);
* err = ub_resolve_async(ctx, "www.example.com", ... my_callback);
* ... application resumes processing ...
* ... and when either ub_val_poll(ctx) is true
* ... or when the file descriptor ub_val_fd(ctx) is readable,
* ... and when either ub_poll(ctx) is true
* ... or when the file descriptor ub_fd(ctx) is readable,
* ... or whenever, the app calls ...
* ub_val_process(ctx);
* ub_process(ctx);
* ... if no result is ready, the app resumes processing above,
* ... or process() calls my_callback() with results.
*
* ... if the application has nothing more to do, wait for answer
* ub_val_wait(ctx);
* ub_wait(ctx);
*
* Application threaded. Blocking.
* Blocking, same as above. The current thread does the work.
@@ -74,7 +74,7 @@
*
* Application threaded. Non-blocking ('asynchronous').
* ... setup threaded-asynchronous config option
* err = ub_val_ctx_async(ctx, 1);
* err = ub_ctx_async(ctx, 1);
* ... same as async for non-threaded
* ... the callbacks are called in the thread that calls process(ctx)
*
@@ -84,7 +84,7 @@
* Otherwise, for asynchronous with threading, a worker thread is created.
*
* The blocking calls use shared ctx-cache when threaded. Thus
* ub_val_resolve() and ub_val_resolve_async() && ub_val_wait() are
* ub_resolve() and ub_resolve_async() && ub_wait() are
* not the same. The first makes the current thread do the work, setting
* up buffers, etc, to perform the work (but using shared cache data).
* The second calls another worker thread (or process) to perform the work.
@@ -100,14 +100,14 @@
*
* Its contents are internally defined.
*/
struct ub_val_ctx;
struct ub_ctx;
/**
* The validation and resolution results.
* Allocated by the resolver, and need to be freed by the application
* with ub_val_resolve_free().
* with ub_resolve_free().
*/
struct ub_val_result {
struct ub_result {
/** The original question, name text string. */
char* qname;
/** the type asked for */
@@ -139,6 +139,13 @@ struct ub_val_result {
*/
int rcode;
/**
* The DNS answer packet. Network formatted. Can contain DNSSEC types.
*/
void* answer_packet;
/** length of the answer packet in octets. */
int answer_len;
/**
* If there is any data, this is true.
* If false, there was no data (nxdomain may be true, rcode can be set).
@@ -179,7 +186,7 @@ struct ub_val_result {
/**
* Callback for results of async queries.
* The readable function definition looks like:
* void my_callback(void* my_arg, int err, struct ub_val_result* result);
* void my_callback(void* my_arg, int err, struct ub_result* result);
* It is called with
* void* my_arg: your pointer to a (struct of) data of your choice,
* or NULL.
@@ -187,23 +194,40 @@ struct ub_val_result {
* are forthcoming.
* struct result: pointer to more detailed result structure.
* This structure is allocated on the heap and needs to be
* freed with ub_val_resolve_free(result);
* freed with ub_resolve_free(result);
*/
typedef void (*ub_val_callback_t)(void*, int, struct ub_val_result*);
typedef void (*ub_callback_t)(void*, int, struct ub_result*);
/**
* Create a resolving and validation context.
* The information from /etc/resolv.conf and /etc/hosts is not utilised by
* default. Use ub_ctx_resolvconf and ub_ctx_hosts to read them.
* @return a new context. default initialisation.
* returns NULL on error.
*/
struct ub_val_ctx* ub_val_ctx_create(void);
struct ub_ctx* ub_ctx_create(void);
/**
* Destroy a validation context and free all its resources.
* Outstanding async queries are killed and callbacks are not called for them.
* @param ctx: context to delete.
*/
void ub_val_ctx_delete(struct ub_val_ctx* ctx);
void ub_ctx_delete(struct ub_ctx* ctx);
/**
* Set an option for the context.
* @param ctx: context.
* @param opt: option name from the unbound.conf config file format.
* (not all settings applicable). The name includes the trailing ':'
* for example ub_ctx_set_option("logfile:", "mylog.txt");
* This is a power-users interface that lets you specify all sorts
* of options.
* For some specific options, such as adding trust anchors, special
* routines exist.
* @param val: value of the option.
* @return: 0 if OK, else error.
*/
int ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val);
/**
* setup configuration for the given context.
@@ -215,7 +239,7 @@ void ub_val_ctx_delete(struct ub_val_ctx* ctx);
* routines exist.
* @return: 0 if OK, else error.
*/
int ub_val_ctx_config(struct ub_val_ctx* ctx, char* fname);
int ub_ctx_config(struct ub_ctx* ctx, char* fname);
/**
* Set machine to forward DNS queries to, the caching resolver to use.
@@ -225,7 +249,7 @@ int ub_val_ctx_config(struct ub_val_ctx* ctx, char* fname);
* that case the addresses are used as backup servers.
*
* To read the list of nameservers from /etc/resolv.conf (from DHCP or so),
* use the call ub_val_ctx_resolvconf.
* use the call ub_ctx_resolvconf.
*
* @param ctx: context.
* At this time it is only possible to set configuration before the
@@ -234,7 +258,7 @@ int ub_val_ctx_config(struct ub_val_ctx* ctx, char* fname);
* If the addr is NULL, forwarding is disabled.
* @return 0 if OK, else error.
*/
int ub_val_ctx_set_fwd(struct ub_val_ctx* ctx, char* addr);
int ub_ctx_set_fwd(struct ub_ctx* ctx, char* addr);
/**
* Read list of nameservers to use from the filename given.
@@ -250,7 +274,20 @@ int ub_val_ctx_set_fwd(struct ub_val_ctx* ctx, char* addr);
* @param fname: file name string. If NULL "/etc/resolv.conf" is used.
* @return 0 if OK, else error.
*/
int ub_val_ctx_resolvconf(struct ub_val_ctx* ctx, char* fname);
int ub_ctx_resolvconf(struct ub_ctx* ctx, char* fname);
/**
* Read list of hosts from the filename given.
* Usually "/etc/hosts".
* These addresses are not flagged as DNSSEC secure when queried for.
*
* @param ctx: context.
* At this time it is only possible to set configuration before the
* first resolve is done.
* @param fname: file name string. If NULL "/etc/hosts" is used.
* @return 0 if OK, else error.
*/
int ub_ctx_hosts(struct ub_ctx* ctx, char* fname);
/**
* Add a trust anchor to the given context.
@@ -263,7 +300,7 @@ int ub_val_ctx_resolvconf(struct ub_val_ctx* ctx, char* fname);
* [domainname] [TTL optional] [type] [class optional] [rdata contents]
* @return 0 if OK, else error.
*/
int ub_val_ctx_add_ta(struct ub_val_ctx* ctx, char* ta);
int ub_ctx_add_ta(struct ub_ctx* ctx, char* ta);
/**
* Add trust anchors to the given context.
@@ -274,7 +311,7 @@ int ub_val_ctx_add_ta(struct ub_val_ctx* ctx, char* ta);
* @param fname: filename of file with keyfile with trust anchors.
* @return 0 if OK, else error.
*/
int ub_val_ctx_add_ta_file(struct ub_val_ctx* ctx, char* fname);
int ub_ctx_add_ta_file(struct ub_ctx* ctx, char* fname);
/**
* Add trust anchors to the given context.
@@ -286,7 +323,17 @@ int ub_val_ctx_add_ta_file(struct ub_val_ctx* ctx, char* fname);
* anchors.
* @return 0 if OK, else error.
*/
int ub_val_ctx_trustedkeys(struct ub_val_ctx* ctx, char* fname);
int ub_ctx_trustedkeys(struct ub_ctx* ctx, char* fname);
/**
* Set debug output (and error output) to the specified stream.
* Pass NULL to disable. Default is stderr.
* @param ctx: context.
* @param out: FILE* out file stream to log to.
* Type void* to avoid stdio dependency of this header file.
* @return 0 if OK, else error.
*/
int ub_ctx_debugout(struct ub_ctx* ctx, void* out);
/**
* Set debug verbosity for the context
@@ -296,7 +343,7 @@ int ub_val_ctx_trustedkeys(struct ub_val_ctx* ctx, char* fname);
* and 3 is lots.
* @return 0 if OK, else error.
*/
int ub_val_ctx_debuglevel(struct ub_val_ctx* ctx, int d);
int ub_ctx_debuglevel(struct ub_ctx* ctx, int d);
/**
* Set a context behaviour for asynchronous action.
@@ -308,7 +355,7 @@ int ub_val_ctx_debuglevel(struct ub_val_ctx* ctx, int d);
* no effect (delete and re-create the context to change).
* @return 0 if OK, else error.
*/
int ub_val_ctx_async(struct ub_val_ctx* ctx, int dothread);
int ub_ctx_async(struct ub_ctx* ctx, int dothread);
/**
* Poll a context to see if it has any new results
@@ -318,27 +365,27 @@ int ub_val_ctx_async(struct ub_val_ctx* ctx, int dothread);
* @return: 0 if nothing to read, or nonzero if a result is available.
* If nonzero, call ctx_process() to do callbacks.
*/
int ub_val_poll(struct ub_val_ctx* ctx);
int ub_poll(struct ub_ctx* ctx);
/**
* Wait for a context to finish with results. Calls ub_val_process() after
* Wait for a context to finish with results. Calls ub_process() after
* the wait for you. After the wait, there are no more outstanding
* asynchronous queries.
* @param ctx: context.
* @return: 0 if OK, else error.
*/
int ub_val_wait(struct ub_val_ctx* ctx);
int ub_wait(struct ub_ctx* ctx);
/**
* Get file descriptor. Wait for it to become readable, at this point
* answers are returned from the asynchronous validating resolver.
* Then call the ub_val_process to continue processing.
* Then call the ub_process to continue processing.
* This routine works immediately after context creation, the fd
* does not change.
* @param ctx: context.
* @return: -1 on error, or file descriptor to use select(2) with.
*/
int ub_val_fd(struct ub_val_ctx* ctx);
int ub_fd(struct ub_ctx* ctx);
/**
* Call this routine to continue processing results from the validating
@@ -347,7 +394,7 @@ int ub_val_fd(struct ub_val_ctx* ctx);
* @param ctx: context
* @return: 0 if OK, else error.
*/
int ub_val_process(struct ub_val_ctx* ctx);
int ub_process(struct ub_ctx* ctx);
/**
* Perform resolution and validation of the target name.
@@ -361,8 +408,8 @@ int ub_val_process(struct ub_val_ctx* ctx);
* in that case (out of memory).
* @return 0 if OK, else error.
*/
int ub_val_resolve(struct ub_val_ctx* ctx, char* name, int rrtype,
int rrclass, struct ub_val_result** result);
int ub_resolve(struct ub_ctx* ctx, char* name, int rrtype,
int rrclass, struct ub_result** result);
/**
* Perform resolution and validation of the target name.
@@ -379,7 +426,7 @@ int ub_val_resolve(struct ub_val_ctx* ctx, char* name, int rrtype,
* and is passed on to the callback function.
* @param callback: this is called on completion of the resolution.
* It is called as:
* void callback(void* mydata, int err, struct ub_val_result* result)
* void callback(void* mydata, int err, struct ub_result* result)
* with mydata: the same as passed here, you may pass NULL,
* with err: is 0 when a result has been found.
* with result: a newly allocated result structure.
@@ -392,8 +439,8 @@ int ub_val_resolve(struct ub_val_ctx* ctx, char* name, int rrtype,
* cancel the query.
* @return 0 if OK, else error.
*/
int ub_val_resolve_async(struct ub_val_ctx* ctx, char* name, int rrtype,
int rrclass, void* mydata, ub_val_callback_t callback, int* async_id);
int ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype,
int rrclass, void* mydata, ub_callback_t callback, int* async_id);
/**
* Cancel an async query in progress.
@@ -403,19 +450,19 @@ int ub_val_resolve_async(struct ub_val_ctx* ctx, char* name, int rrtype,
* @param async_id: which query to cancel.
* @return 0 if OK, else error.
*/
int ub_val_cancel(struct ub_val_ctx* ctx, int async_id);
int ub_cancel(struct ub_ctx* ctx, int async_id);
/**
* Free storage associated with a result structure.
* @param result: to free
*/
void ub_val_resolve_free(struct ub_val_result* result);
void ub_resolve_free(struct ub_result* result);
/**
* Convert error value to a human readable string.
* @param err: error code from one of the ub_val* functions.
* @return pointer to constant text string, zero terminated.
*/
const char* ub_val_strerror(int err);
const char* ub_strerror(int err);
#endif /* _UB_UNBOUND_H */
+79 -58
View File
@@ -1,8 +1,8 @@
# ltmain.sh - Provide generalized library-building support services.
# NOTE: Changing this file will not affect anything until you rerun configure.
#
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
# Free Software Foundation, Inc.
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
# 2007 Free Software Foundation, Inc.
# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
#
# This program is free software; you can redistribute it and/or modify
@@ -43,8 +43,8 @@ EXIT_FAILURE=1
PROGRAM=ltmain.sh
PACKAGE=libtool
VERSION=1.5.22
TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)"
VERSION=1.5.24
TIMESTAMP=" (1.1220.2.456 2007/06/24 02:25:32)"
# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
@@ -57,6 +57,8 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
else
case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
fi
BIN_SH=xpg4; export BIN_SH # for Tru64
DUALCASE=1; export DUALCASE # for MKS sh
# Check that we have a working $echo.
if test "X$1" = X--no-reexec; then
@@ -114,10 +116,10 @@ esac
for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
do
eval "if test \"\${$lt_var+set}\" = set; then
save_$lt_var=\$$lt_var
$lt_var=C
export $lt_var
fi"
save_$lt_var=\$$lt_var
$lt_var=C
export $lt_var
fi"
done
# Make sure IFS has a sensible default
@@ -206,7 +208,13 @@ func_win32_libid ()
if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
$EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
win32_nmres=`eval $NM -f posix -A $1 | \
$SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'`
$SED -n -e '1,100{
/ I /{
s,.*,import,
p
q
}
}'`
case $win32_nmres in
import*) win32_libid_type="x86 archive import";;
*) win32_libid_type="x86 archive static";;
@@ -340,11 +348,11 @@ func_extract_archives ()
my_xlib_u=$my_xlib
while :; do
case " $extracted_archives " in
*" $my_xlib_u "*)
extracted_serial=`expr $extracted_serial + 1`
my_xlib_u=lt$extracted_serial-$my_xlib ;;
*) break ;;
esac
*" $my_xlib_u "*)
extracted_serial=`expr $extracted_serial + 1`
my_xlib_u=lt$extracted_serial-$my_xlib ;;
*) break ;;
esac
done
extracted_archives="$extracted_archives $my_xlib_u"
my_xdir="$my_gentop/$my_xlib_u"
@@ -474,11 +482,12 @@ do
;;
--version)
$echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
$echo
$echo "Copyright (C) 2005 Free Software Foundation, Inc."
$echo "This is free software; see the source for copying conditions. There is NO"
$echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
echo "\
$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
exit $?
;;
@@ -775,7 +784,7 @@ if test -z "$show_help"; then
*.class) xform=class ;;
*.cpp) xform=cpp ;;
*.cxx) xform=cxx ;;
*.f90) xform=f90 ;;
*.[fF][09]?) xform=[fF][09]. ;;
*.for) xform=for ;;
*.java) xform=java ;;
*.obj) xform=obj ;;
@@ -1160,8 +1169,8 @@ EOF
do
case $arg in
-all-static | -static | -static-libtool-libs)
case $arg in
-all-static)
case $arg in
-all-static)
if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
$echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
fi
@@ -1170,19 +1179,19 @@ EOF
fi
prefer_static_libs=yes
;;
-static)
-static)
if test -z "$pic_flag" && test -n "$link_static_flag"; then
dlopen_self=$dlopen_self_static
fi
prefer_static_libs=built
;;
-static-libtool-libs)
if test -z "$pic_flag" && test -n "$link_static_flag"; then
dlopen_self=$dlopen_self_static
fi
prefer_static_libs=yes
;;
esac
-static-libtool-libs)
if test -z "$pic_flag" && test -n "$link_static_flag"; then
dlopen_self=$dlopen_self_static
fi
prefer_static_libs=yes
;;
esac
build_libtool_libs=no
build_old_libs=yes
break
@@ -1630,7 +1639,7 @@ EOF
continue
;;
-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
compiler_flags="$compiler_flags $arg"
compile_command="$compile_command $arg"
finalize_command="$finalize_command $arg"
@@ -1650,10 +1659,11 @@ EOF
# -m* pass through architecture-specific compiler args for GCC
# -m*, -t[45]*, -txscale* pass through architecture-specific
# compiler args for GCC
# -pg pass through profiling flag for GCC
# -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC
# -F/path gives path to uninstalled frameworks, gcc on darwin
# @file GCC response files
-64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \
-t[45]*|-txscale*|@*)
-64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
-t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*)
# Unknown arguments in both finalize_command and compile_command need
# to be aesthetically quoted because they are evaled later.
@@ -1681,9 +1691,9 @@ EOF
-no-install)
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin*)
# The PATH hackery in wrapper scripts is required on Windows
# in order for the loader to find any dlls it needs.
# and Darwin in order for the loader to find any dlls it needs.
$echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2
$echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2
fast_install=no
@@ -2124,7 +2134,7 @@ EOF
lib=
found=no
case $deplib in
-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
if test "$linkmode,$pass" = "prog,link"; then
compile_deplibs="$deplib $compile_deplibs"
finalize_deplibs="$deplib $finalize_deplibs"
@@ -2520,9 +2530,9 @@ EOF
if test "$linkmode,$pass" = "prog,link"; then
if test -n "$library_names" &&
{ { test "$prefer_static_libs" = no ||
test "$prefer_static_libs,$installed" = "built,yes"; } ||
test -z "$old_library"; }; then
{ { test "$prefer_static_libs" = no ||
test "$prefer_static_libs,$installed" = "built,yes"; } ||
test -z "$old_library"; }; then
# We need to hardcode the library path
if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
# Make sure the rpath contains only unique directories.
@@ -3229,9 +3239,10 @@ EOF
age="0"
;;
irix|nonstopux)
current=`expr $number_major + $number_minor - 1`
current=`expr $number_major + $number_minor`
age="$number_minor"
revision="$number_minor"
lt_irix_increment=no
;;
esac
;;
@@ -3290,7 +3301,8 @@ EOF
versuffix="$major.$age.$revision"
# Darwin ld doesn't like 0 for these options...
minor_current=`expr $current + 1`
verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
;;
freebsd-aout)
@@ -3304,8 +3316,11 @@ EOF
;;
irix | nonstopux)
major=`expr $current - $age + 1`
if test "X$lt_irix_increment" = "Xno"; then
major=`expr $current - $age`
else
major=`expr $current - $age + 1`
fi
case $version_type in
nonstopux) verstring_prefix=nonstopux ;;
*) verstring_prefix=sgi ;;
@@ -3442,11 +3457,11 @@ EOF
fi
# Eliminate all temporary directories.
# for path in $notinst_path; do
# lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"`
# deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"`
# dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"`
# done
#for path in $notinst_path; do
# lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"`
# deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"`
# dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"`
#done
if test -n "$xrpath"; then
# If the user specified any rpath flags, then add them.
@@ -3547,7 +3562,7 @@ EOF
int main() { return 0; }
EOF
$rm conftest
if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
ldd_output=`ldd conftest`
for i in $deplibs; do
name=`expr $i : '-l\(.*\)'`
@@ -3909,7 +3924,10 @@ EOF
test -n "$hardcode_libdirs"; then
libdir="$hardcode_libdirs"
if test -n "$hardcode_libdir_flag_spec_ld"; then
eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
case $archive_cmds in
*\$LD*) eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" ;;
*) eval dep_rpath=\"$hardcode_libdir_flag_spec\" ;;
esac
else
eval dep_rpath=\"$hardcode_libdir_flag_spec\"
fi
@@ -4275,7 +4293,7 @@ EOF
if test -n "$convenience"; then
if test -n "$whole_archive_flag_spec"; then
eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
reload_conv_objs=$reload_objs\ `$echo "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'`
reload_conv_objs=$reload_objs\ `$echo "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'`
else
gentop="$output_objdir/${obj}x"
generated="$generated $gentop"
@@ -5295,6 +5313,8 @@ if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
else
case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
fi
BIN_SH=xpg4; export BIN_SH # for Tru64
DUALCASE=1; export DUALCASE # for MKS sh
# The HP-UX ksh and POSIX shell print the target directory to stdout
# if CDPATH is set.
@@ -6391,8 +6411,10 @@ relink_command=\"$relink_command\""
if test -f "$dir/$objdir/$dlname"; then
dir="$dir/$objdir"
else
$echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
exit $EXIT_FAILURE
if test ! -f "$dir/$dlname"; then
$echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
exit $EXIT_FAILURE
fi
fi
;;
@@ -6458,12 +6480,11 @@ relink_command=\"$relink_command\""
# Restore saved environment variables
for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
do
eval "if test \"\${save_$lt_var+set}\" = set; then
$lt_var=\$save_$lt_var; export $lt_var
fi"
eval "if test \"\${save_$lt_var+set}\" = set; then
$lt_var=\$save_$lt_var; export $lt_var
fi"
done
# Now prepare to actually exec the command.
exec_cmd="\$cmd$args"
else
+9 -1
View File
@@ -212,7 +212,11 @@ if [ "$SNAPSHOT" = "yes" ]; then
fi
replace_all doc/README
replace_all doc/unbound.8
replace_all doc/unbound.8.in
replace_all doc/unbound.conf.5.in
replace_all doc/unbound-checkconf.8.in
replace_all doc/unbound-host.1
replace_all doc/libunbound.3.in
info "Renaming Unbound directory to unbound-$version."
cd ..
@@ -233,15 +237,19 @@ cleanup
case $OSTYPE in
linux*)
sha=`sha1sum unbound-$version.tar.gz | awk '{ print $1 }'`
sha256=`sha256sum unbound-$version.tar.gz | awk '{ print $1 }'`
;;
freebsd*)
sha=`sha1 unbound-$version.tar.gz | awk '{ print $5 }'`
sha256=`sha256 unbound-$version.tar.gz | awk '{ print $5 }'`
;;
*)
sha=`sha1sum unbound-$version.tar.gz | awk '{ print $1 }'`
sha256=`sha256sum unbound-$version.tar.gz | awk '{ print $1 }'`
;;
esac
echo $sha > unbound-$version.tar.gz.sha1
echo $sha256 > unbound-$version.tar.gz.sha256
info "Unbound distribution created successfully."
info "SHA1sum: $sha"
+12 -9
View File
@@ -52,7 +52,7 @@
/** store rrsets in the rrset cache.
* @param env: module environment with caches.
* @param rep: contains list of rrsets to store.
* @param now: current time(NULL).
* @param now: current time.
*/
static void
store_rrsets(struct module_env* env, struct reply_info* rep, uint32_t now)
@@ -73,7 +73,7 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
hashvalue_t hash, struct reply_info* rep)
{
struct msgreply_entry* e;
uint32_t now = time(NULL), ttl = rep->ttl;
uint32_t ttl = rep->ttl;
size_t i;
/* store RRsets */
@@ -82,8 +82,8 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
rep->ref[i].id = rep->rrsets[i]->id;
}
reply_info_sortref(rep);
reply_info_set_ttls(rep, now);
store_rrsets(env, rep, now);
reply_info_set_ttls(rep, *env->now);
store_rrsets(env, rep, *env->now);
if(ttl == 0) {
/* we do not store the message, but we did store the RRs,
* which could be useful for delegation information */
@@ -219,7 +219,7 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
{
struct delegpt_ns* ns;
struct ub_packed_rrset_key* akey;
uint32_t now = time(NULL);
uint32_t now = *env->now;
for(ns = dp->nslist; ns; ns = ns->next) {
if(ns->resolved)
continue;
@@ -465,6 +465,10 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
size_t newlen, dtarglen;
if(now > d->ttl)
return NULL;
/* only allow validated (with DNSSEC) DNAMEs used from cache
* for insecure DNAMEs, query again. */
if(d->security != sec_status_secure)
return NULL;
msg = gen_dns_msg(region, q, 2); /* DNAME + CNAME RRset */
if(!msg)
return NULL;
@@ -543,7 +547,7 @@ dns_cache_lookup(struct module_env* env,
struct lruhash_entry* e;
struct query_info k;
hashvalue_t h;
uint32_t now = (uint32_t)time(NULL);
uint32_t now = *env->now;
struct ub_packed_rrset_key* rrset;
/* lookup first, this has both NXdomains and ANSWER responses */
@@ -630,16 +634,15 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
if(is_referral) {
/* store rrsets */
struct rrset_ref ref;
uint32_t now = time(NULL);
size_t i;
for(i=0; i<rep->rrset_count; i++) {
packed_rrset_ttl_add((struct packed_rrset_data*)
rep->rrsets[i]->entry.data, now);
rep->rrsets[i]->entry.data, *env->now);
ref.key = rep->rrsets[i];
ref.id = rep->rrsets[i]->id;
/*ignore ret: it was in the cache, ref updated */
(void)rrset_cache_update(env->rrset_cache, &ref,
env->alloc, now);
env->alloc, *env->now);
}
free(rep);
return 1;
+42 -18
View File
@@ -158,7 +158,7 @@ infra_lookup_host_nottl(struct infra_cache* infra,
struct infra_host_data*
infra_lookup_host(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, int wr,
time_t timenow, struct infra_host_key** key)
uint32_t timenow, struct infra_host_key** key)
{
struct infra_host_data* data;
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
@@ -186,7 +186,7 @@ infra_lookup_host(struct infra_cache* infra,
*/
static struct lruhash_entry*
new_host_entry(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, time_t tm)
socklen_t addrlen, uint32_t tm)
{
struct infra_host_data* data;
struct infra_host_key* key = (struct infra_host_key*)malloc(
@@ -214,7 +214,7 @@ new_host_entry(struct infra_cache* infra, struct sockaddr_storage* addr,
int
infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, time_t timenow, int* edns_vs, int* to)
socklen_t addrlen, uint32_t timenow, int* edns_vs, int* to)
{
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
addrlen, 0);
@@ -260,12 +260,12 @@ hash_lameness(uint8_t* name, size_t namelen)
int
infra_lookup_lame(struct infra_host_data* host,
uint8_t* name, size_t namelen, time_t timenow)
uint8_t* name, size_t namelen, uint32_t timenow,
int* dlame, int* alame, int* olame)
{
struct lruhash_entry* e;
struct infra_lame_key k;
struct infra_lame_data *d;
int dl;
if(!host->lameness)
return 0;
k.entry.hash = hash_lameness(name, namelen);
@@ -281,9 +281,11 @@ infra_lookup_lame(struct infra_host_data* host,
lock_rw_unlock(&e->lock);
return 0;
}
dl = d->isdnsseclame;
*dlame = d->isdnsseclame;
*alame = d->lame_type_A;
*olame = d->lame_other;
lock_rw_unlock(&e->lock);
return dl?2:1;
return *dlame || *alame || *olame;
}
size_t
@@ -329,7 +331,8 @@ infra_lame_deldatafunc(void* d, void* ATTR_UNUSED(arg))
int
infra_set_lame(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* name, size_t namelen, time_t timenow, int dnsseclame)
uint8_t* name, size_t namelen, uint32_t timenow, int dnsseclame,
uint16_t qtype)
{
struct infra_host_data* data;
struct lruhash_entry* e;
@@ -361,6 +364,8 @@ infra_set_lame(struct infra_cache* infra,
k->entry.data = (void*)d;
d->ttl = timenow + infra->lame_ttl;
d->isdnsseclame = dnsseclame;
d->lame_type_A = (!dnsseclame && qtype == LDNS_RR_TYPE_A);
d->lame_other = (!dnsseclame && qtype != LDNS_RR_TYPE_A);
k->namelen = namelen;
e = infra_lookup_host_nottl(infra, addr, addrlen, 1);
if(!e) {
@@ -392,7 +397,18 @@ infra_set_lame(struct infra_cache* infra,
free(d);
return 0;
}
} else {
/* lookup existing lameness entry (if any) and merge data */
int dlame, alame, olame;
if(infra_lookup_lame(data, name, namelen, timenow,
&dlame, &alame, &olame)) {
/* merge data into new structure */
if(dlame) d->isdnsseclame = 1;
if(alame) d->lame_type_A = 1;
if(olame) d->lame_other = 1;
}
}
/* inserts new entry, or updates TTL of older entry */
lruhash_insert(data->lameness, k->entry.hash, &k->entry, d, NULL);
@@ -422,7 +438,7 @@ infra_update_tcp_works(struct infra_cache* infra,
int
infra_rtt_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
int roundtrip, time_t timenow)
int roundtrip, uint32_t timenow)
{
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
addrlen, 1);
@@ -452,7 +468,7 @@ infra_rtt_update(struct infra_cache* infra,
int
infra_edns_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
int edns_version, time_t timenow)
int edns_version, uint32_t timenow)
{
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
addrlen, 1);
@@ -477,28 +493,36 @@ infra_edns_update(struct infra_cache* infra,
int
infra_get_lame_rtt(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* name, size_t namelen, int* lame, int* dnsseclame,
int* rtt, time_t timenow)
uint8_t* name, size_t namelen, uint16_t qtype,
int* lame, int* dnsseclame, int* rtt, uint32_t timenow)
{
struct infra_host_data* host;
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
addrlen, 0);
int lm;
int dlm, alm, olm;
if(!e)
return 0;
host = (struct infra_host_data*)e->data;
*rtt = rtt_unclamped(&host->rtt);
/* check lameness first, if so, ttl on host does not matter anymore */
if((lm=infra_lookup_lame(host, name, namelen, timenow))) {
lock_rw_unlock(&e->lock);
if(lm == 1) {
if(infra_lookup_lame(host, name, namelen, timenow, &dlm, &alm, &olm)) {
if(alm && qtype == LDNS_RR_TYPE_A) {
lock_rw_unlock(&e->lock);
*lame = 1;
*dnsseclame = 0;
} else {
return 1;
} else if(olm && qtype != LDNS_RR_TYPE_A) {
lock_rw_unlock(&e->lock);
*lame = 1;
*dnsseclame = 0;
return 1;
} else if(dlm) {
lock_rw_unlock(&e->lock);
*lame = 0;
*dnsseclame = 1;
return 1;
}
return 1;
/* no lameness for this type of query */
}
*lame = 0;
*dnsseclame = 0;
+22 -11
View File
@@ -63,7 +63,7 @@ struct infra_host_key {
*/
struct infra_host_data {
/** TTL value for this entry. absolute time. */
time_t ttl;
uint32_t ttl;
/** round trip times for timeout calculation */
struct rtt_info rtt;
/** Names of the zones that are lame. NULL=no lame zones. */
@@ -90,10 +90,14 @@ struct infra_lame_key {
*/
struct infra_lame_data {
/** TTL of this entry. absolute time. */
time_t ttl;
uint32_t ttl;
/** is the host lame (does not serve the zone authoritatively),
* or is the host dnssec lame (does not serve DNSSEC data) */
int isdnsseclame;
/** the host is lame (not authoritative) for A records */
int lame_type_A;
/** the host is lame (not authoritative) for other query types */
int lame_other;
};
/**
@@ -151,7 +155,7 @@ struct infra_cache* infra_adjust(struct infra_cache* infra,
*/
struct infra_host_data* infra_lookup_host(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, int wr,
time_t timenow, struct infra_host_key** key);
uint32_t timenow, struct infra_host_key** key);
/**
* Find host information to send a packet. Creates new entry if not found.
@@ -166,7 +170,7 @@ struct infra_host_data* infra_lookup_host(struct infra_cache* infra,
* @return: 0 on error.
*/
int infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, time_t timenow, int* edns_vs, int* to);
socklen_t addrlen, uint32_t timenow, int* edns_vs, int* to);
/**
* Check for lameness of this server for a particular zone.
@@ -175,10 +179,14 @@ int infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
* @param name: domain name of zone apex.
* @param namelen: length of domain name.
* @param timenow: what time it is now.
* @return: 0 if not lame or unknown or timed out, 1 if lame, 2 if dnsseclame.
* @param dlame: if the function returns true, is set true if dnssec lame.
* @param alame: if the function returns true, is set true if qtype A lame.
* @param olame: if the function returns true, is set true if qtype other lame.
* @return: 0 if not lame or unknown or timed out, 1 if lame
*/
int infra_lookup_lame(struct infra_host_data* host,
uint8_t* name, size_t namelen, time_t timenow);
uint8_t* name, size_t namelen, uint32_t timenow,
int* dlame, int* alame, int* olame);
/**
* Set a host to be lame for the given zone.
@@ -190,11 +198,13 @@ int infra_lookup_lame(struct infra_host_data* host,
* @param timenow: what time it is now.
* @param dnsseclame: if true the host is set dnssec lame.
* if false, the host is marked lame (not serving the zone).
* @param qtype: the query type for which it is lame.
* @return: 0 on error.
*/
int infra_set_lame(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* name, size_t namelen, time_t timenow, int dnsseclame);
uint8_t* name, size_t namelen, uint32_t timenow, int dnsseclame,
uint16_t qtype);
/**
* Update rtt information for the host.
@@ -208,7 +218,7 @@ int infra_set_lame(struct infra_cache* infra,
*/
int infra_rtt_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
int roundtrip, time_t timenow);
int roundtrip, uint32_t timenow);
/**
* Update information for the host, store that a TCP transaction works.
@@ -230,7 +240,7 @@ void infra_update_tcp_works(struct infra_cache* infra,
*/
int infra_edns_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
int edns_version, time_t timenow);
int edns_version, uint32_t timenow);
/**
* Get Lameness information and average RTT if host is in the cache.
@@ -239,6 +249,7 @@ int infra_edns_update(struct infra_cache* infra,
* @param addrlen: length of addr.
* @param name: zone name.
* @param namelen: zone name length.
* @param qtype: the query to be made.
* @param lame: if function returns true, this returns lameness of the zone.
* @param dnsseclame: if function returns true, this returns if the zone
* is dnssec-lame.
@@ -249,8 +260,8 @@ int infra_edns_update(struct infra_cache* infra,
*/
int infra_get_lame_rtt(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* name, size_t namelen, int* lame, int* dnsseclame,
int* rtt, time_t timenow);
uint8_t* name, size_t namelen, uint16_t qtype,
int* lame, int* dnsseclame, int* rtt, uint32_t timenow);
/**
* Get memory used by the infra cache.
+2 -4
View File
@@ -309,9 +309,8 @@ rrset_array_unlock_touch(struct rrset_cache* r, struct regional* scratch,
void
rrset_update_sec_status(struct rrset_cache* r,
struct ub_packed_rrset_key* rrset)
struct ub_packed_rrset_key* rrset, uint32_t now)
{
uint32_t now = (uint32_t)time(0);
struct packed_rrset_data* updata =
(struct packed_rrset_data*)rrset->entry.data;
struct lruhash_entry* e;
@@ -339,9 +338,8 @@ rrset_update_sec_status(struct rrset_cache* r,
void
rrset_check_sec_status(struct rrset_cache* r,
struct ub_packed_rrset_key* rrset)
struct ub_packed_rrset_key* rrset, uint32_t now)
{
uint32_t now = (uint32_t)time(0);
struct packed_rrset_data* updata =
(struct packed_rrset_data*)rrset->entry.data;
struct lruhash_entry* e;
+4 -2
View File
@@ -192,9 +192,10 @@ void rrset_array_unlock_touch(struct rrset_cache* r, struct regional* scratch,
* @param r: the rrset cache.
* @param rrset: which rrset to attempt to update. This rrset is left
* untouched. The rrset in the cache is updated in-place.
* @param now: current time.
*/
void rrset_update_sec_status(struct rrset_cache* r,
struct ub_packed_rrset_key* rrset);
struct ub_packed_rrset_key* rrset, uint32_t now);
/**
* Looks up security status of an rrset. Looks up the rrset.
@@ -203,9 +204,10 @@ void rrset_update_sec_status(struct rrset_cache* r,
* @param r: the rrset cache.
* @param rrset: This rrset may change security status due to the cache.
* But its status will only improve, towards secure.
* @param now: current time.
*/
void rrset_check_sec_status(struct rrset_cache* r,
struct ub_packed_rrset_key* rrset);
struct ub_packed_rrset_key* rrset, uint32_t now);
/** mark rrset to be deleted, set id=0 */
void rrset_markdel(void* key);
+157 -35
View File
@@ -49,7 +49,9 @@
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#include <fcntl.h>
/** number of queued TCP connections for listen() */
@@ -86,7 +88,8 @@ verbose_print_addr(struct addrinfo *addr)
}
int
create_udp_sock(struct addrinfo *addr, int v6only)
create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t addrlen, int v6only, int* inuse, int* noproto)
{
int s;
# if defined(IPV6_USE_MIN_MTU)
@@ -94,19 +97,43 @@ create_udp_sock(struct addrinfo *addr, int v6only)
# else
(void)v6only;
# endif
verbose_print_addr(addr);
if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) {
if((s = socket(family, socktype, 0)) == -1) {
*inuse = 0;
#ifndef USE_WINSOCK
if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
*noproto = 1;
return -1;
}
log_err("can't create socket: %s", strerror(errno));
#else
if(WSAGetLastError() == WSAEAFNOSUPPORT ||
WSAGetLastError() == WSAEPROTONOSUPPORT) {
*noproto = 1;
return -1;
}
log_err("can't create socket: %s",
wsa_strerror(WSAGetLastError()));
#endif
*noproto = 0;
return -1;
}
if(addr->ai_family == AF_INET6) {
if(family == AF_INET6) {
# if defined(IPV6_V6ONLY)
if(v6only) {
int val=(v6only==2)?0:1;
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
&val, (socklen_t)sizeof(val)) < 0) {
(void*)&val, (socklen_t)sizeof(val)) < 0) {
#ifndef USE_WINSOCK
log_err("setsockopt(..., IPV6_V6ONLY"
", ...) failed: %s", strerror(errno));
#else
log_err("setsockopt(..., IPV6_V6ONLY"
", ...) failed: %s",
wsa_strerror(WSAGetLastError()));
#endif
close(s);
*noproto = 0;
*inuse = 0;
return -1;
}
}
@@ -121,19 +148,45 @@ create_udp_sock(struct addrinfo *addr, int v6only)
* network stack supports IPV6_USE_MIN_MTU.
*/
if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
&on, (socklen_t)sizeof(on)) < 0) {
(void*)&on, (socklen_t)sizeof(on)) < 0) {
#ifndef USE_WINSOCK
log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
"...) failed: %s", strerror(errno));
#else
log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
"...) failed: %s",
wsa_strerror(WSAGetLastError()));
#endif
close(s);
*noproto = 0;
*inuse = 0;
return -1;
}
# endif
}
if(bind(s, (struct sockaddr*)addr->ai_addr, addr->ai_addrlen) != 0) {
log_err("can't bind socket: %s", strerror(errno));
if(bind(s, (struct sockaddr*)addr, addrlen) != 0) {
*noproto = 0;
#ifndef USE_WINSOCK
#ifdef EADDRINUSE
*inuse = (errno == EADDRINUSE);
if(errno != EADDRINUSE)
log_err("can't bind socket: %s", strerror(errno));
#endif
#else /* USE_WINSOCK */
if(WSAGetLastError() != WSAEADDRINUSE &&
WSAGetLastError() != WSAEADDRNOTAVAIL)
log_err("can't bind socket: %s",
wsa_strerror(WSAGetLastError()));
#endif
close(s);
return -1;
}
if(!fd_set_nonblock(s))
if(!fd_set_nonblock(s)) {
*noproto = 0;
*inuse = 0;
close(s);
return -1;
}
return s;
}
@@ -141,55 +194,84 @@ create_udp_sock(struct addrinfo *addr, int v6only)
* Create and bind TCP listening socket
* @param addr: address info ready to make socket.
* @param v6only: enable ip6 only flag on ip6 sockets.
* @param noproto: if error caused by lack of protocol support.
* @return: the socket. -1 on error.
*/
static int
create_tcp_accept_sock(struct addrinfo *addr, int v6only)
create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto)
{
int s, flag;
int s;
#if defined(SO_REUSEADDR) || defined(IPV6_V6ONLY)
int on = 1;
#endif /* SO_REUSEADDR || IPV6_V6ONLY */
verbose_print_addr(addr);
*noproto = 0;
if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) {
#ifndef USE_WINSOCK
if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
*noproto = 1;
return -1;
}
log_err("can't create socket: %s", strerror(errno));
#else
if(WSAGetLastError() == WSAEAFNOSUPPORT ||
WSAGetLastError() == WSAEPROTONOSUPPORT) {
*noproto = 1;
return -1;
}
log_err("can't create socket: %s",
wsa_strerror(WSAGetLastError()));
#endif
return -1;
}
#ifdef SO_REUSEADDR
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on,
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
(socklen_t)sizeof(on)) < 0) {
#ifndef USE_WINSOCK
log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
strerror(errno));
#else
log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
wsa_strerror(WSAGetLastError()));
#endif
return -1;
}
#endif /* SO_REUSEADDR */
#if defined(IPV6_V6ONLY)
if(addr->ai_family == AF_INET6 && v6only) {
if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
&on, (socklen_t)sizeof(on)) < 0) {
(void*)&on, (socklen_t)sizeof(on)) < 0) {
#ifndef USE_WINSOCK
log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
strerror(errno));
#else
log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
wsa_strerror(WSAGetLastError()));
#endif
return -1;
}
}
#else
(void)v6only;
#endif /* IPV6_V6ONLY */
if(bind(s, (struct sockaddr*)addr->ai_addr, addr->ai_addrlen) != 0) {
if(bind(s, addr->ai_addr, addr->ai_addrlen) != 0) {
#ifndef USE_WINSOCK
log_err("can't bind socket: %s", strerror(errno));
#else
log_err("can't bind socket: %s",
wsa_strerror(WSAGetLastError()));
#endif
return -1;
}
if((flag = fcntl(s, F_GETFL)) == -1) {
log_err("can't fcntl F_GETFL: %s", strerror(errno));
flag = 0;
}
flag |= O_NONBLOCK;
if(fcntl(s, F_SETFL, flag) == -1) {
log_err("can't fcntl F_SETFL: %s", strerror(errno));
if(!fd_set_nonblock(s)) {
return -1;
}
if(listen(s, TCP_BACKLOG) == -1) {
#ifndef USE_WINSOCK
log_err("can't listen: %s", strerror(errno));
#else
log_err("can't listen: %s", wsa_strerror(WSAGetLastError()));
#endif
return -1;
}
return s;
@@ -200,20 +282,39 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only)
*/
static int
make_sock(int stype, const char* ifname, const char* port,
struct addrinfo *hints, int v6only)
struct addrinfo *hints, int v6only, int* noip6)
{
struct addrinfo *res = NULL;
int r, s;
int r, s, inuse, noproto;
hints->ai_socktype = stype;
*noip6 = 0;
if((r=getaddrinfo(ifname, port, hints, &res)) != 0 || !res) {
log_err("node %s:%s getaddrinfo: %s %s",
ifname?ifname:"default", port, gai_strerror(r),
r==EAI_SYSTEM?(char*)strerror(errno):"");
#ifdef EAI_SYSTEM
r==EAI_SYSTEM?(char*)strerror(errno):""
#else
""
#endif
);
return -1;
}
if(stype == SOCK_DGRAM)
s = create_udp_sock(res, v6only);
else s = create_tcp_accept_sock(res, v6only);
if(stype == SOCK_DGRAM) {
verbose_print_addr(res);
s = create_udp_sock(res->ai_family, res->ai_socktype,
(struct sockaddr*)res->ai_addr,
res->ai_addrlen, v6only, &inuse, &noproto);
if(s == -1 && inuse) {
log_err("bind: address already in use");
} else if(s == -1 && noproto && hints->ai_family == AF_INET6){
*noip6 = 1;
}
} else {
s = create_tcp_accept_sock(res, v6only, &noproto);
if(s == -1 && noproto && hints->ai_family == AF_INET6){
*noip6 = 1;
}
}
freeaddrinfo(res);
return s;
}
@@ -243,18 +344,22 @@ port_insert(struct listen_port** list, int s, enum listen_type ftype)
static int
set_recvpktinfo(int s, int family)
{
#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) || defined(IP_RECVDSTADDR) || defined(IP_PKTINFO)
int on = 1;
#else
(void)s;
#endif
if(family == AF_INET6) {
# ifdef IPV6_RECVPKTINFO
if(setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
&on, (socklen_t)sizeof(on)) < 0) {
(void*)&on, (socklen_t)sizeof(on)) < 0) {
log_err("setsockopt(..., IPV6_RECVPKTINFO, ...) failed: %s",
strerror(errno));
return 0;
}
# elif defined(IPV6_PKTINFO)
if(setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO,
&on, (socklen_t)sizeof(on)) < 0) {
(void*)&on, (socklen_t)sizeof(on)) < 0) {
log_err("setsockopt(..., IPV6_PKTINFO, ...) failed: %s",
strerror(errno));
return 0;
@@ -268,14 +373,14 @@ set_recvpktinfo(int s, int family)
} else if(family == AF_INET) {
# ifdef IP_RECVDSTADDR
if(setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
&on, (socklen_t)sizeof(on)) < 0) {
(void*)&on, (socklen_t)sizeof(on)) < 0) {
log_err("setsockopt(..., IP_RECVDSTADDR, ...) failed: %s",
strerror(errno));
return 0;
}
# elif defined(IP_PKTINFO)
if(setsockopt(s, IPPROTO_IP, IP_PKTINFO,
&on, (socklen_t)sizeof(on)) < 0) {
(void*)&on, (socklen_t)sizeof(on)) < 0) {
log_err("setsockopt(..., IP_PKTINFO, ...) failed: %s",
strerror(errno));
return 0;
@@ -306,12 +411,18 @@ static int
ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
struct addrinfo *hints, const char* port, struct listen_port** list)
{
int s;
int s, noip6=0;
if(!do_udp && !do_tcp)
return 0;
if(do_auto) {
if((s = make_sock(SOCK_DGRAM, ifname, port, hints, 1)) == -1)
if((s = make_sock(SOCK_DGRAM, ifname, port, hints, 1,
&noip6)) == -1) {
if(noip6) {
log_warn("IPv6 protocol not available");
return 1;
}
return 0;
}
/* getting source addr packet info is highly non-portable */
if(!set_recvpktinfo(s, hints->ai_family))
return 0;
@@ -321,15 +432,26 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
}
} else if(do_udp) {
/* regular udp socket */
if((s = make_sock(SOCK_DGRAM, ifname, port, hints, 1)) == -1)
if((s = make_sock(SOCK_DGRAM, ifname, port, hints, 1,
&noip6)) == -1) {
if(noip6) {
log_warn("IPv6 protocol not available");
return 1;
}
return 0;
}
if(!port_insert(list, s, listen_type_udp)) {
close(s);
return 0;
}
}
if(do_tcp) {
if((s = make_sock(SOCK_STREAM, ifname, port, hints, 1)) == -1) {
if((s = make_sock(SOCK_STREAM, ifname, port, hints, 1,
&noip6)) == -1) {
if(noip6) {
/*log_warn("IPv6 protocol not available");*/
return 1;
}
return 0;
}
if(!port_insert(list, s, listen_type_tcp)) {
+9 -3
View File
@@ -45,7 +45,6 @@
#include "config.h"
#include "util/netevent.h"
struct listen_list;
struct addrinfo;
struct config_file;
/**
@@ -165,11 +164,18 @@ size_t listen_get_mem(struct listen_dnsport* listen);
/**
* Create and bind nonblocking UDP socket
* @param addr: address info ready to make socket.
* @param family: for socket call.
* @param socktype: for socket call.
* @param addr: for bind call.
* @param addrlen: for bind call.
* @param v6only: if enabled, IP6 sockets get IP6ONLY option set.
* if enabled with value 2 IP6ONLY option is disabled.
* @param inuse: on error, this is set true if the port was in use.
* @param noproto: on error, this is set true if cause is that the
IPv6 proto (family) is not available.
* @return: the socket. -1 on error.
*/
int create_udp_sock(struct addrinfo* addr, int v6only);
int create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t addrlen, int v6only, int* inuse, int* noproto);
#endif /* LISTEN_DNSPORT_H */
+32 -25
View File
@@ -528,9 +528,15 @@ static int
lz_nodefault(struct config_file* cfg, const char* name)
{
struct config_strlist* p;
size_t len = strlen(name);
if(len == 0) return 0;
if(name[len-1] == '.') len--;
for(p = cfg->local_zones_nodefault; p; p = p->next) {
/* compare zone name, lowercase */
if(strcasecmp(p->str, name) == 0)
/* compare zone name, lowercase, compare without ending . */
if(strncasecmp(p->str, name, len) == 0 &&
(strlen(p->str) == len || (strlen(p->str)==len+1 &&
p->str[len] == '.')))
return 1;
}
return 0;
@@ -614,34 +620,35 @@ lz_enter_defaults(struct local_zones* zones, struct config_file* cfg,
return 0;
}
}
if ( !add_as112_default(zones, cfg, buf, "10.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "16.172.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "17.172.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "18.172.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "19.172.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "20.172.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "21.172.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "22.172.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "23.172.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "24.172.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "25.172.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "26.172.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "27.172.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "28.172.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "29.172.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "30.172.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "31.172.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "168.192.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "0.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "254.169.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "2.0.192.in-addr.arpa") ||
!add_as112_default(zones, cfg, buf, "255.255.255.255.in-addr.arpa") ||
if ( !add_as112_default(zones, cfg, buf, "10.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "16.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "17.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "18.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "19.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "20.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "21.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "22.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "23.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "24.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "25.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "26.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "27.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "28.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "29.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "30.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "31.172.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "168.192.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "0.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "254.169.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "2.0.192.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "255.255.255.255.in-addr.arpa.") ||
!add_as112_default(zones, cfg, buf, "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.") ||
!add_as112_default(zones, cfg, buf, "d.f.ip6.arpa.") ||
!add_as112_default(zones, cfg, buf, "8.e.f.ip6.arpa.") ||
!add_as112_default(zones, cfg, buf, "9.e.f.ip6.arpa.") ||
!add_as112_default(zones, cfg, buf, "a.e.f.ip6.arpa.") ||
!add_as112_default(zones, cfg, buf, "b.e.f.ip6.arpa.")) {
!add_as112_default(zones, cfg, buf, "b.e.f.ip6.arpa.") ||
!add_as112_default(zones, cfg, buf, "8.b.d.0.1.0.0.2.ip6.arpa.")) {
log_err("out of memory adding default zone");
return 0;
}
+48 -32
View File
@@ -160,7 +160,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
if(!s->reply_list && !s->cb_list)
was_noreply = 1;
/* add reply to s */
if(!mesh_state_add_reply(s, edns, rep, qid, qflags)) {
if(!mesh_state_add_reply(s, edns, rep, qid, qflags, qinfo->qname)) {
log_err("mesh_new_client: out of memory; SERVFAIL");
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
@@ -298,7 +298,7 @@ mesh_state_cleanup(struct mesh_state* mstate)
/* de-init modules */
mesh = mstate->s.env->mesh;
for(i=0; i<mesh->mods.num; i++) {
log_assert(fptr_whitelist_mod_clear(mesh->mods.mod[i]->clear));
fptr_ok(fptr_whitelist_mod_clear(mesh->mods.mod[i]->clear));
(*mesh->mods.mod[i]->clear)(&mstate->s, i);
mstate->s.minfo[i] = NULL;
mstate->s.ext_state[i] = module_finished;
@@ -510,12 +510,14 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
* @param rcode: if not 0, error code.
* @param rep: reply to send (or NULL if rcode is set).
* @param r: reply entry
* @param prev: previous reply, already has its answer encoded in buffer.
*/
static void
mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
struct mesh_reply* r)
struct mesh_reply* r, struct mesh_reply* prev)
{
struct timeval end_time;
struct timeval duration;
int secure;
/* examine security status */
if(m->s.env->need_to_validate && !(r->qflags&BIT_CD) && rep &&
@@ -528,7 +530,21 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
if(!rep && rcode == LDNS_RCODE_NOERROR)
rcode = LDNS_RCODE_SERVFAIL;
/* send the reply */
if(rcode) {
if(prev && prev->qflags == r->qflags &&
prev->edns.edns_present == r->edns.edns_present &&
prev->edns.bits == r->edns.bits &&
prev->edns.udp_size == r->edns.udp_size) {
/* if the previous reply is identical to this one, fix ID */
if(prev->query_reply.c->buffer != r->query_reply.c->buffer)
ldns_buffer_copy(r->query_reply.c->buffer,
prev->query_reply.c->buffer);
ldns_buffer_write_at(r->query_reply.c->buffer, 0,
&r->qid, sizeof(uint16_t));
ldns_buffer_write_at(r->query_reply.c->buffer, 12,
r->qname, m->s.qinfo.qname_len);
comm_point_send_reply(&r->query_reply);
} else if(rcode) {
m->s.qinfo.qname = r->qname;
error_encode(r->query_reply.c->buffer, rcode, &m->s.qinfo,
r->qid, r->qflags, &r->edns);
comm_point_send_reply(&r->query_reply);
@@ -538,6 +554,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
r->edns.udp_size = EDNS_ADVERTISED_SIZE;
r->edns.ext_rcode = 0;
r->edns.bits &= EDNS_DO;
m->s.qinfo.qname = r->qname;
if(!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
r->qflags, r->query_reply.c->buffer, 0, 1,
m->s.env->scratch, udp_size, &r->edns,
@@ -551,28 +568,25 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
}
/* account */
m->s.env->mesh->num_reply_addrs--;
if(gettimeofday(&end_time, NULL) < 0) {
log_err("gettimeofday: %s", strerror(errno));
return;
} else {
struct timeval duration;
timeval_subtract(&duration, &end_time, &r->start_time);
verbose(VERB_ALGO, "query took %d.%6.6d sec",
(int)duration.tv_sec, (int)duration.tv_usec);
m->s.env->mesh->replies_sent++;
timeval_add(&m->s.env->mesh->replies_sum_wait, &duration);
timehist_insert(m->s.env->mesh->histogram, &duration);
}
end_time = *m->s.env->now_tv;
timeval_subtract(&duration, &end_time, &r->start_time);
verbose(VERB_ALGO, "query took %d.%6.6d sec",
(int)duration.tv_sec, (int)duration.tv_usec);
m->s.env->mesh->replies_sent++;
timeval_add(&m->s.env->mesh->replies_sum_wait, &duration);
timehist_insert(m->s.env->mesh->histogram, &duration);
}
void mesh_query_done(struct mesh_state* mstate)
{
struct mesh_reply* r;
struct mesh_reply* prev = NULL;
struct mesh_cb* c;
struct reply_info* rep = (mstate->s.return_msg?
mstate->s.return_msg->rep:NULL);
for(r = mstate->reply_list; r; r = r->next) {
mesh_send_reply(mstate, mstate->s.return_rcode, rep, r);
mesh_send_reply(mstate, mstate->s.return_rcode, rep, r, prev);
prev = r;
}
for(c = mstate->cb_list; c; c = c->next) {
mesh_do_callback(mstate, mstate->s.return_rcode, rep, c);
@@ -587,7 +601,7 @@ void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate)
/* make super runnable */
(void)rbtree_insert(&mesh->run, &ref->s->run_node);
/* callback the function to inform super of result */
log_assert(fptr_whitelist_mod_inform_super(
fptr_ok(fptr_whitelist_mod_inform_super(
mesh->mods.mod[ref->s->s.curmod]->inform_super));
(*mesh->mods.mod[ref->s->s.curmod]->inform_super)(&mstate->s,
ref->s->s.curmod, &ref->s->s);
@@ -630,7 +644,7 @@ int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,
}
int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
struct comm_reply* rep, uint16_t qid, uint16_t qflags)
struct comm_reply* rep, uint16_t qid, uint16_t qflags, uint8_t* qname)
{
struct mesh_reply* r = regional_alloc(s->s.region,
sizeof(struct mesh_reply));
@@ -640,11 +654,12 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
r->edns = *edns;
r->qid = qid;
r->qflags = qflags;
if(gettimeofday(&r->start_time, NULL) < 0) {
log_err("addrep: gettimeofday: %s", strerror(errno));
memset(&r->start_time, 0, sizeof(r->start_time));
}
r->start_time = *s->s.env->now_tv;
r->next = s->reply_list;
r->qname = regional_alloc_init(s->s.region, qname,
s->s.qinfo.qname_len);
if(!r->qname)
return 0;
s->reply_list = r;
return 1;
@@ -716,7 +731,7 @@ void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
verbose(VERB_ALGO, "mesh_run: start");
while(mstate) {
/* run the module */
log_assert(fptr_whitelist_mod_operate(
fptr_ok(fptr_whitelist_mod_operate(
mesh->mods.mod[mstate->s.curmod]->operate));
(*mesh->mods.mod[mstate->s.curmod]->operate)
(&mstate->s, ev, mstate->s.curmod, e);
@@ -768,20 +783,21 @@ mesh_log_list(struct mesh_area* mesh)
void
mesh_stats(struct mesh_area* mesh, const char* str)
{
log_info("%s %u states (%u with reply, %u detached), "
"%u waiting replies", str, (unsigned)mesh->all.count,
verbose(VERB_DETAIL, "%s %u recursion states (%u with reply, "
"%u detached), %u waiting replies, %u recursion replies "
"sent", str, (unsigned)mesh->all.count,
(unsigned)mesh->num_reply_states,
(unsigned)mesh->num_detached_states,
(unsigned)mesh->num_reply_addrs);
(unsigned)mesh->num_reply_addrs,
(unsigned)mesh->replies_sent);
if(mesh->replies_sent > 0) {
struct timeval avg;
timeval_divide(&avg, &mesh->replies_sum_wait,
mesh->replies_sent);
log_info("sent %u replies, with average wait "
"of %d.%6.6d sec", (unsigned)mesh->replies_sent,
(int)avg.tv_sec, (int)avg.tv_usec);
log_info("histogram of reply wait times");
timehist_log(mesh->histogram);
log_info("average recursion processing time "
"%d.%6.6d sec", (int)avg.tv_sec, (int)avg.tv_usec);
log_info("histogram of recursion processing times");
timehist_log(mesh->histogram, "recursions");
}
}
+4 -1
View File
@@ -156,6 +156,8 @@ struct mesh_reply {
uint16_t qid;
/** flags of query, for reply flags */
uint16_t qflags;
/** qname from this query. len same as mesh qinfo. */
uint8_t* qname;
};
/**
@@ -375,10 +377,11 @@ int mesh_state_attachment(struct mesh_state* super, struct mesh_state* sub);
* @param rep: comm point reply info.
* @param qid: ID of reply.
* @param qflags: original query flags.
* @param qname: original query name.
* @return: 0 on alloc error.
*/
int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
struct comm_reply* rep, uint16_t qid, uint16_t qflags);
struct comm_reply* rep, uint16_t qid, uint16_t qflags, uint8_t* qname);
/**
* Create new callback structure and attach it to a mesh state.
+2 -2
View File
@@ -143,7 +143,7 @@ modstack_setup(struct module_stack* stack, const char* module_conf,
for(i=0; i<stack->num; i++) {
verbose(VERB_OPS, "init module %d: %s",
i, stack->mod[i]->name);
log_assert(fptr_whitelist_mod_init(stack->mod[i]->init));
fptr_ok(fptr_whitelist_mod_init(stack->mod[i]->init));
if(!(*stack->mod[i]->init)(env, i)) {
log_err("module init for module %s failed",
stack->mod[i]->name);
@@ -158,7 +158,7 @@ modstack_desetup(struct module_stack* stack, struct module_env* env)
{
int i;
for(i=0; i<stack->num; i++) {
log_assert(fptr_whitelist_mod_deinit(stack->mod[i]->deinit));
fptr_ok(fptr_whitelist_mod_deinit(stack->mod[i]->deinit));
(*stack->mod[i]->deinit)(env, i);
}
stack->num = 0;
+596 -265
View File
File diff suppressed because it is too large Load Diff
+92 -24
View File
@@ -51,7 +51,10 @@ struct pending_timeout;
struct ub_randstate;
struct pending_tcp;
struct waiting_tcp;
struct waiting_udp;
struct infra_cache;
struct port_comm;
struct port_if;
/**
* Send queries to outside servers and wait for answers from servers.
@@ -60,6 +63,10 @@ struct infra_cache;
struct outside_network {
/** Base for select calls */
struct comm_base* base;
/** pointer to time in seconds */
uint32_t* now_secs;
/** pointer to time in microseconds */
struct timeval* now_tv;
/** buffer shared by UDP connections, since there is only one
datagram at any time. */
@@ -67,21 +74,27 @@ struct outside_network {
/** serviced_callbacks malloc overhead when processing multiple
* identical serviced queries to the same server. */
size_t svcd_overhead;
/** use x20 bits to encode additional ID random bits */
int use_caps_for_id;
/**
* Array of udp comm point* that are used to listen to pending events.
* Each is on a different port. This is for ip4 ports.
*/
struct comm_point** udp4_ports;
/** number of udp4 ports */
size_t num_udp4;
/** linked list of available commpoints, unused file descriptors,
* for use as outgoing UDP ports. cp.fd=-1 in them. */
struct port_comm* unused_fds;
/**
* The opened ip6 ports.
*/
struct comm_point** udp6_ports;
/** number of udp6 ports */
size_t num_udp6;
/** array of outgoing IP4 interfaces */
struct port_if* ip4_ifs;
/** number of outgoing IP4 interfaces */
int num_ip4;
/** array of outgoing IP6 interfaces */
struct port_if* ip6_ifs;
/** number of outgoing IP6 interfaces */
int num_ip6;
/** pending udp queries waiting to be sent out, waiting for fd */
struct pending* udp_wait_first;
/** last pending udp query in list */
struct pending* udp_wait_last;
/** pending udp answers. sorted by id, addr */
rbtree_t* pending;
@@ -109,20 +122,65 @@ struct outside_network {
struct waiting_tcp* tcp_wait_last;
};
/**
* Outgoing interface. Ports available and currently used are tracked
* per interface
*/
struct port_if {
/** address ready to allocate new socket (except port no). */
struct sockaddr_storage addr;
/** length of addr field */
socklen_t addrlen;
/** the available ports array. These are unused.
* Only the first total-inuse part is filled. */
int* avail_ports;
/** the total number of available ports (size of the array) */
int avail_total;
/** array of the commpoints currently in use.
* allocated for max number of fds, first part in use. */
struct port_comm** out;
/** max number of fds, size of out array */
int maxout;
/** number of commpoints (and thus also ports) in use */
int inuse;
};
/**
* Outgoing commpoint for UDP port.
*/
struct port_comm {
/** next in free list */
struct port_comm* next;
/** which port number (when in use) */
int number;
/** interface it is used in */
struct port_if* pif;
/** index in the out array of the interface */
int index;
/** number of outstanding queries on this port */
int num_outstanding;
/** UDP commpoint, fd=-1 if not in use */
struct comm_point* cp;
};
/**
* A query that has an answer pending for it.
*/
struct pending {
/** redblacktree entry, key is the pending struct(id, addr). */
rbnode_t node;
/** the ID for the query */
uint16_t id;
/** the ID for the query. int so that a value out of range can
* be used to signify a pending that is for certain not present in
* the rbtree. (and for which deletion is safe). */
unsigned int id;
/** remote address. */
struct sockaddr_storage addr;
/** length of addr field in use. */
socklen_t addrlen;
/** comm point it was sent on (and reply must come back on). */
struct comm_point* c;
struct port_comm* pc;
/** timeout event */
struct comm_timer* timer;
/** callback for the timeout, error or reply to the message */
@@ -131,6 +189,16 @@ struct pending {
void* cb_arg;
/** the outside network it is part of */
struct outside_network* outnet;
/*---- filled if udp pending is waiting -----*/
/** next in waiting list. */
struct pending* next_waiting;
/** timeout in msec */
int timeout;
/** The query itself, the query packet to send. */
uint8_t* pkt;
/** length of query packet. */
size_t pkt_len;
};
/**
@@ -252,17 +320,19 @@ struct serviced_query {
* @param num_ifs: number of names in array ifs.
* @param do_ip4: service IP4.
* @param do_ip6: service IP6.
* @param port_base: if -1 system assigns ports, otherwise try to get
* the ports numbered from this starting number.
* @param num_tcp: number of outgoing tcp buffers to preallocate.
* @param infra: pointer to infra cached used for serviced queries.
* @param rnd: stored to create random numbers for serviced queries.
* @param use_caps_for_id: enable to use 0x20 bits to encode id randomness.
* @param availports: array of available ports.
* @param numavailports: number of available ports in array.
* @return: the new structure (with no pending answers) or NULL on error.
*/
struct outside_network* outside_network_create(struct comm_base* base,
size_t bufsize, size_t num_ports, char** ifs, int num_ifs,
int do_ip4, int do_ip6, int port_base, size_t num_tcp,
struct infra_cache* infra, struct ub_randstate* rnd);
int do_ip4, int do_ip6, size_t num_tcp, struct infra_cache* infra,
struct ub_randstate* rnd, int use_caps_for_id, int* availports,
int numavailports);
/**
* Delete outside_network structure.
@@ -280,13 +350,12 @@ void outside_network_delete(struct outside_network* outnet);
* @param timeout: in milliseconds from now.
* @param callback: function to call on error, timeout or reply.
* @param callback_arg: user argument for callback function.
* @param rnd: random state for generating ID and port.
* @return: NULL on error for malloc or socket. Else the pending query object.
*/
struct pending* pending_udp_query(struct outside_network* outnet,
ldns_buffer* packet, struct sockaddr_storage* addr,
socklen_t addrlen, int timeout, comm_point_callback_t* callback,
void* callback_arg, struct ub_randstate* rnd);
void* callback_arg);
/**
* Send TCP query. May wait for TCP buffer. Selects ID to be random, and
@@ -300,13 +369,12 @@ struct pending* pending_udp_query(struct outside_network* outnet,
* without any query been sent to the server yet.
* @param callback: function to call on error, timeout or reply.
* @param callback_arg: user argument for callback function.
* @param rnd: random state for generating ID.
* @return: false on error for malloc or socket. Else the pending TCP object.
*/
struct waiting_tcp* pending_tcp_query(struct outside_network* outnet,
ldns_buffer* packet, struct sockaddr_storage* addr,
socklen_t addrlen, int timeout, comm_point_callback_t* callback,
void* callback_arg, struct ub_randstate* rnd);
void* callback_arg);
/**
* Delete pending answer.
+161 -25
View File
@@ -51,7 +51,12 @@
#include "iterator/iterator.h"
#include "validator/validator.h"
#include "services/localzone.h"
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
/** Give checkconf usage, and exit (1). */
static void
@@ -171,25 +176,130 @@ aclchecks(struct config_file* cfg)
}
}
/** true if fname is a file */
static int
is_file(const char* fname)
{
struct stat buf;
if(stat(fname, &buf) < 0) {
if(errno==EACCES) {
printf("warning: no search permission for one of the directories in path: %s\n", fname);
return 1;
}
perror(fname);
return 0;
}
if(S_ISDIR(buf.st_mode)) {
printf("%s is not a file\n", fname);
return 0;
}
return 1;
}
/** true if fname is a directory */
static int
is_dir(const char* fname)
{
struct stat buf;
if(stat(fname, &buf) < 0) {
if(errno==EACCES) {
printf("warning: no search permission for one of the directories in path: %s\n", fname);
return 1;
}
perror(fname);
return 0;
}
if(!(S_ISDIR(buf.st_mode))) {
printf("%s is not a directory\n", fname);
return 0;
}
return 1;
}
/** convert a filename to full pathname in original filesys
* @param fname: the path name to convert.
* Must not be null or empty.
* @param cfg: config struct for chroot and chdir (if set).
* @param use_chdir: if false, only chroot is applied.
* @return pointer to static buffer which is: [chroot][chdir]fname
*/
static char*
fname_after_chroot(const char* fname, struct config_file* cfg, int use_chdir)
{
static char buf[1024];
int slashit = 0;
buf[0] = 0;
if(cfg->chrootdir && cfg->chrootdir[0] &&
strncmp(cfg->chrootdir, fname, strlen(cfg->chrootdir)) == 0) {
/* already full pathname, return it */
strncpy(buf, fname, sizeof(buf)-1);
buf[sizeof(buf)-1] = 0;
return buf;
}
/* chroot */
if(cfg->chrootdir && cfg->chrootdir[0]) {
/* start with chrootdir */
strncpy(buf, cfg->chrootdir, sizeof(buf)-1);
slashit = 1;
}
/* chdir */
if(fname[0] == '/' || !use_chdir) {
/* full path, no chdir */
} else if(cfg->directory && cfg->directory[0]) {
/* prepend chdir */
if(slashit && cfg->directory[0] != '/')
strncat(buf, "/", sizeof(buf)-strlen(buf)-1);
if(strncmp(cfg->chrootdir, cfg->directory,
strlen(cfg->chrootdir)) == 0)
strncat(buf, cfg->directory+strlen(cfg->chrootdir),
sizeof(buf)-strlen(buf)-1);
else strncat(buf, cfg->directory, sizeof(buf)-strlen(buf)-1);
slashit = 1;
}
/* fname */
if(slashit && fname[0] != '/')
strncat(buf, "/", sizeof(buf)-strlen(buf)-1);
strncat(buf, fname, sizeof(buf)-strlen(buf)-1);
buf[sizeof(buf)-1] = 0;
return buf;
}
/** get base dir of a fname */
static char*
basedir(const char* fname, struct config_file* cfg)
{
char* d = fname_after_chroot(fname, cfg, 1);
char* rev = strrchr(d, '/');
if(!rev) return NULL;
if(d == rev) return NULL;
rev[0] = 0;
return d;
}
/** check file list, every file must be inside the chroot location */
static void
check_chroot_filelist(const char* desc, struct config_strlist* list,
const char* chrootdir)
const char* chrootdir, struct config_file* cfg)
{
struct config_strlist* p;
if(!chrootdir) return;
char* old;
for(p=list; p; p=p->next) {
if(p->str && p->str[0] && strncmp(chrootdir, p->str,
strlen(chrootdir)) != 0) {
fatal_exit("%s: \"%s\" not in chrootdir %s",
desc, p->str, chrootdir);
if(p->str && p->str[0]) {
if(!is_file(fname_after_chroot(p->str, cfg, 1))) {
fatal_exit("%s: \"%s\" does not exist in chrootdir %s",
desc, p->str, chrootdir);
}
old = p->str;
/* put in a new full path for continued checking */
p->str = strdup(fname_after_chroot(p->str, cfg, 1));
free(old);
}
}
}
/** check configuration for errors */
static void
morechecks(struct config_file* cfg)
morechecks(struct config_file* cfg, char* fname)
{
warn_hosts("stub-host", cfg->stubs);
warn_hosts("forward-host", cfg->forwards);
@@ -209,26 +319,50 @@ morechecks(struct config_file* cfg)
cfg->chrootdir[strlen(cfg->chrootdir)-1] == '/')
fatal_exit("chootdir %s has trailing slash '/' please remove.",
cfg->chrootdir);
if(cfg->chrootdir && strncmp(cfg->chrootdir, cfg->directory,
strlen(cfg->chrootdir)) != 0)
fatal_exit("working directory %s not in chrootdir %s",
cfg->directory, cfg->chrootdir);
if(cfg->chrootdir && cfg->pidfile && cfg->pidfile[0] &&
strncmp(cfg->chrootdir, cfg->pidfile,
strlen(cfg->chrootdir)) != 0)
fatal_exit("pid file %s not in chrootdir %s",
cfg->pidfile, cfg->chrootdir);
if(cfg->chrootdir && cfg->logfile && cfg->logfile[0] &&
strncmp(cfg->chrootdir, cfg->logfile,
strlen(cfg->chrootdir)) != 0)
fatal_exit("log file %s not in chrootdir %s",
cfg->logfile, cfg->chrootdir);
if(cfg->chrootdir && cfg->chrootdir[0] &&
!is_dir(cfg->chrootdir)) {
fatal_exit("bad chroot directory");
}
if(cfg->chrootdir && cfg->chrootdir[0]) {
char buf[10240];
buf[0] = 0;
if(fname[0] != '/') {
if(getcwd(buf, sizeof(buf)) == NULL)
fatal_exit("getcwd: %s", strerror(errno));
strncat(buf, "/", sizeof(buf)-strlen(buf)-1);
}
strncat(buf, fname, sizeof(buf)-strlen(buf)-1);
if(strncmp(buf, cfg->chrootdir, strlen(cfg->chrootdir)) != 0)
fatal_exit("config file %s is not inside chroot %s",
buf, cfg->chrootdir);
}
if(cfg->directory && cfg->directory[0] && !is_dir(
fname_after_chroot(cfg->directory, cfg, 0))) {
fatal_exit("bad chdir directory");
}
if( (cfg->chrootdir && cfg->chrootdir[0]) ||
(cfg->directory && cfg->directory[0])) {
if(cfg->pidfile && cfg->pidfile[0] &&
basedir(cfg->pidfile, cfg) &&
!is_dir(basedir(cfg->pidfile, cfg))) {
fatal_exit("pidfile directory does not exist");
}
if(cfg->logfile && cfg->logfile[0] &&
basedir(cfg->logfile, cfg) &&
!is_dir(basedir(cfg->logfile, cfg))) {
fatal_exit("logfile directory does not exist");
}
}
check_chroot_filelist("file with root-hints",
cfg->root_hints, cfg->chrootdir);
cfg->root_hints, cfg->chrootdir, cfg);
check_chroot_filelist("trust-anchor-file",
cfg->trust_anchor_file_list, cfg->chrootdir);
cfg->trust_anchor_file_list, cfg->chrootdir, cfg);
check_chroot_filelist("trusted-keys-file",
cfg->trusted_keys_file_list, cfg->chrootdir);
cfg->trusted_keys_file_list, cfg->chrootdir, cfg);
/* remove chroot setting so that modules are not stripping pathnames*/
free(cfg->chrootdir);
cfg->chrootdir = NULL;
if(strcmp(cfg->module_conf, "iterator") != 0 &&
strcmp(cfg->module_conf, "validator iterator") != 0) {
@@ -236,11 +370,13 @@ morechecks(struct config_file* cfg)
cfg->module_conf);
}
#ifdef HAVE_GETPWNAM
if(cfg->username && cfg->username[0]) {
if(getpwnam(cfg->username) == NULL)
fatal_exit("user '%s' does not exist.", cfg->username);
endpwent();
}
#endif
localzonechecks(cfg);
}
@@ -257,7 +393,7 @@ checkconf(char* cfgfile)
config_delete(cfg);
exit(1);
}
morechecks(cfg);
morechecks(cfg, cfgfile);
check_mod(cfg, iter_get_funcblock());
check_mod(cfg, val_get_funcblock());
config_delete(cfg);
+37 -17
View File
@@ -51,8 +51,9 @@ static int verb = 0;
static void
usage()
{
printf("Usage: unbound-host [-vdh] [-c class] [-t type] hostname\n");
printf("Usage: unbound-host [-vdhr] [-c class] [-t type] hostname\n");
printf(" [-y key] [-f keyfile] [-F namedkeyfile]\n");
printf(" [-C configfile]\n");
printf(" Queries the DNS for information.\n");
printf(" The hostname is looked up for IP4, IP6 and mail.\n");
printf(" If an ip-address is given a reverse lookup is done.\n");
@@ -63,6 +64,9 @@ usage()
printf(" -y 'example.com DS 31560 5 1 1CFED8478...'\n");
printf(" -f keyfile read trust anchors from file, with lines as -y.\n");
printf(" -F keyfile read named.conf-style trust anchors.\n");
printf(" -C config use the specified unbound.conf\n");
printf(" -r read forwarder information from /etc/resolv.conf\n");
printf(" breaks validation if the fwder does not do DNSSEC.\n");
printf(" -v be more verbose, shows nodata and security.\n");
printf(" -d debug, traces the action, -d -d shows more.\n");
printf(" -h show this usage help.\n");
@@ -176,7 +180,7 @@ massage_class(const char* c)
/** nice security status string */
static const char*
secure_str(struct ub_val_result* result)
secure_str(struct ub_result* result)
{
if(result->secure) return "(secure)";
if(result->bogus) return "(BOGUS (security failure))";
@@ -274,7 +278,7 @@ pretty_rdata(char* q, char* cstr, char* tstr, int t, const char* sec,
/** pretty line of output for results */
static void
pretty_output(char* q, int t, int c, struct ub_val_result* result, int docname)
pretty_output(char* q, int t, int c, struct ub_result* result, int docname)
{
int i;
const char *secstatus = secure_str(result);
@@ -337,25 +341,25 @@ pretty_output(char* q, int t, int c, struct ub_val_result* result, int docname)
/** perform a lookup and printout return if domain existed */
static int
dnslook(struct ub_val_ctx* ctx, char* q, int t, int c, int docname)
dnslook(struct ub_ctx* ctx, char* q, int t, int c, int docname)
{
int ret;
struct ub_val_result* result;
struct ub_result* result;
ret = ub_val_resolve(ctx, q, t, c, &result);
ret = ub_resolve(ctx, q, t, c, &result);
if(ret != 0) {
fprintf(stderr, "resolve error: %s\n", ub_val_strerror(ret));
fprintf(stderr, "resolve error: %s\n", ub_strerror(ret));
exit(1);
}
pretty_output(q, t, c, result, docname);
ret = result->nxdomain;
ub_val_resolve_free(result);
ub_resolve_free(result);
return ret;
}
/** perform host lookup */
static void
lookup(struct ub_val_ctx* ctx, const char* nm, const char* qt, const char* qc)
lookup(struct ub_ctx* ctx, const char* nm, const char* qt, const char* qc)
{
/* massage input into a query name, type and class */
int multi = 0; /* no type, so do A, AAAA, MX */
@@ -374,10 +378,20 @@ lookup(struct ub_val_ctx* ctx, const char* nm, const char* qt, const char* qc)
} else {
(void)dnslook(ctx, realq, t, c, 1);
}
ub_val_ctx_delete(ctx);
ub_ctx_delete(ctx);
free(realq);
}
/** print error if any */
static void
check_ub_res(int r)
{
if(r != 0) {
fprintf(stderr, "error: %s\n", ub_strerror(r));
exit(1);
}
}
/** getopt global, in case header files fail to declare it. */
extern int optind;
/** getopt global, in case header files fail to declare it. */
@@ -389,26 +403,32 @@ int main(int argc, char* argv[])
int c;
char* qclass = NULL;
char* qtype = NULL;
struct ub_val_ctx* ctx = NULL;
struct ub_ctx* ctx = NULL;
int debuglevel = 0;
ctx = ub_val_ctx_create();
ctx = ub_ctx_create();
if(!ctx) {
fprintf(stderr, "error: out of memory\n");
exit(1);
}
/* parse the options */
while( (c=getopt(argc, argv, "F:c:df:ht:vy:")) != -1) {
while( (c=getopt(argc, argv, "F:c:df:hrt:vy:C:")) != -1) {
switch(c) {
case 'c':
qclass = optarg;
break;
case 'C':
check_ub_res(ub_ctx_config(ctx, optarg));
break;
case 'd':
debuglevel++;
if(debuglevel < 2)
debuglevel = 2; /* at least VERB_DETAIL */
ub_val_ctx_debuglevel(ctx, debuglevel);
check_ub_res(ub_ctx_debuglevel(ctx, debuglevel));
break;
case 'r':
check_ub_res(ub_ctx_resolvconf(ctx, "/etc/resolv.conf"));
break;
case 't':
qtype = optarg;
@@ -417,13 +437,13 @@ int main(int argc, char* argv[])
verb++;
break;
case 'y':
ub_val_ctx_add_ta(ctx, optarg);
check_ub_res(ub_ctx_add_ta(ctx, optarg));
break;
case 'f':
ub_val_ctx_add_ta_file(ctx, optarg);
check_ub_res(ub_ctx_add_ta_file(ctx, optarg));
break;
case 'F':
ub_val_ctx_trustedkeys(ctx, optarg);
check_ub_res(ub_ctx_trustedkeys(ctx, optarg));
break;
case '?':
case 'h':
+25
View File
@@ -160,3 +160,28 @@ void worker_stat_timer_cb(void* ATTR_UNUSED(arg))
{
log_assert(0);
}
/** keep track of lock id in lock-verify application */
struct order_id {
/** the thread id that created it */
int thr;
/** the instance number of creation */
int instance;
};
int order_lock_cmp(const void* e1, const void* e2)
{
struct order_id* o1 = (struct order_id*)e1;
struct order_id* o2 = (struct order_id*)e2;
if(o1->thr < o2->thr) return -1;
if(o1->thr > o2->thr) return 1;
if(o1->instance < o2->instance) return -1;
if(o1->instance > o2->instance) return 1;
return 0;
}
int
codeline_cmp(const void* a, const void* b)
{
return strcmp((const char*)a, (const char*)b);
}
+71 -47
View File
@@ -56,7 +56,7 @@ struct lookinfo {
/** error code from libunbound */
int err;
/** result from lookup */
struct ub_val_result* result;
struct ub_result* result;
};
/** global variable to see how many queries we have left */
@@ -72,6 +72,7 @@ void usage(char* argv[])
printf(" -d : enable debug output\n");
printf(" -f addr : use addr, forward to that server\n");
printf(" -h : this help message\n");
printf(" -H fname : read hosts from fname\n");
printf(" -r fname : read resolv.conf from fname\n");
printf(" -t : use a resolver thread instead of forking a process\n");
printf(" -x : perform extended threaded test\n");
@@ -85,7 +86,7 @@ print_result(struct lookinfo* info)
char buf[100];
if(info->err) /* error (from libunbound) */
printf("%s: error %s\n", info->name,
ub_val_strerror(info->err));
ub_strerror(info->err));
else if(!info->result)
printf("%s: cancelled\n", info->name);
else if(info->result->havedata)
@@ -105,9 +106,9 @@ print_result(struct lookinfo* info)
}
}
/** this is a function of type ub_val_callback_t */
/** this is a function of type ub_callback_t */
static void
lookup_is_done(void* mydata, int err, struct ub_val_result* result)
lookup_is_done(void* mydata, int err, struct ub_result* result)
{
/* cast mydata back to the correct type */
struct lookinfo* info = (struct lookinfo*)mydata;
@@ -123,12 +124,12 @@ static void
checkerr(const char* desc, int err)
{
if(err != 0) {
printf("%s error: %s\n", desc, ub_val_strerror(err));
printf("%s error: %s\n", desc, ub_strerror(err));
exit(1);
}
}
#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
#ifdef THREADS_DISABLED
/** only one process can communicate with async worker */
#define NUMTHR 1
#else /* have threads */
@@ -143,7 +144,7 @@ struct ext_thr_info {
/** thread id */
ub_thread_t tid;
/** context */
struct ub_val_ctx* ctx;
struct ub_ctx* ctx;
/** size of array to query */
int argc;
/** array of names to query */
@@ -157,7 +158,7 @@ static int q_is_localhost = 0;
/** check result structure for the 'correct' answer */
static void
ext_check_result(const char* desc, int err, struct ub_val_result* result)
ext_check_result(const char* desc, int err, struct ub_result* result)
{
checkerr(desc, err);
if(result == NULL) {
@@ -215,12 +216,22 @@ ext_check_result(const char* desc, int err, struct ub_val_result* result)
"wrong.\n", desc);
exit(1);
}
if(result->answer_packet == NULL) {
printf("%s: error result->answer_packet is NULL.\n",
desc);
exit(1);
}
if(result->answer_len != 54) {
printf("%s: error result->answer_len is wrong.\n",
desc);
exit(1);
}
}
}
/** extended bg result callback, this function is ub_val_callback_t */
/** extended bg result callback, this function is ub_callback_t */
static void
ext_callback(void* mydata, int err, struct ub_val_result* result)
ext_callback(void* mydata, int err, struct ub_result* result)
{
int* my_id = (int*)mydata;
int doprint = 0;
@@ -243,7 +254,7 @@ ext_callback(void* mydata, int err, struct ub_val_result* result)
pi.err = 0;
print_result(&pi);
}
ub_val_resolve_free(result);
ub_resolve_free(result);
}
/** extended thread worker */
@@ -252,7 +263,7 @@ ext_thread(void* arg)
{
struct ext_thr_info* inf = (struct ext_thr_info*)arg;
int i, r;
struct ub_val_result* result;
struct ub_result* result;
int* async_ids = NULL;
log_thread_set(&inf->thread_num);
if(inf->thread_num > NUMTHR*2/3) {
@@ -264,32 +275,35 @@ ext_thread(void* arg)
}
for(i=0; i<inf->numq; i++) {
if(async_ids) {
r = ub_val_resolve_async(inf->ctx,
r = ub_resolve_async(inf->ctx,
inf->argv[i%inf->argc], LDNS_RR_TYPE_A,
LDNS_RR_CLASS_IN, &async_ids[i], ext_callback,
&async_ids[i]);
checkerr("ub_val_resolve_async", r);
checkerr("ub_resolve_async", r);
if(i > 100) {
r = ub_val_cancel(inf->ctx, async_ids[i-100]);
checkerr("ub_val_cancel", r);
async_ids[i-100]=0;
r = ub_cancel(inf->ctx, async_ids[i-100]);
checkerr("ub_cancel", r);
}
if(i > 200) {
async_ids[i-200]=0;
}
} else if(inf->thread_num > NUMTHR/2) {
/* async */
r = ub_val_resolve_async(inf->ctx,
r = ub_resolve_async(inf->ctx,
inf->argv[i%inf->argc], LDNS_RR_TYPE_A,
LDNS_RR_CLASS_IN, NULL, ext_callback, NULL);
checkerr("ub_val_resolve_async", r);
checkerr("ub_resolve_async", r);
} else {
/* blocking */
r = ub_val_resolve(inf->ctx, inf->argv[i%inf->argc],
r = ub_resolve(inf->ctx, inf->argv[i%inf->argc],
LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, &result);
ext_check_result("ub_val_resolve", r, result);
ext_check_result("ub_resolve", r, result);
ub_resolve_free(result);
}
}
if(inf->thread_num > NUMTHR/2) {
r = ub_val_wait(inf->ctx);
checkerr("ub_val_ctx_wait", r);
r = ub_wait(inf->ctx);
checkerr("ub_ctx_wait", r);
}
free(async_ids);
@@ -298,7 +312,7 @@ ext_thread(void* arg)
/** perform extended threaded test */
static int
ext_test(struct ub_val_ctx* ctx, int argc, char** argv)
ext_test(struct ub_ctx* ctx, int argc, char** argv)
{
struct ext_thr_info inf[NUMTHR];
int i;
@@ -319,7 +333,7 @@ ext_test(struct ub_val_ctx* ctx, int argc, char** argv)
ub_thread_join(inf[i].tid);
}
printf("extended test end\n");
ub_val_ctx_delete(ctx);
ub_ctx_delete(ctx);
checklock_stop();
return 0;
}
@@ -333,7 +347,7 @@ extern char* optarg;
int main(int argc, char** argv)
{
int c;
struct ub_val_ctx* ctx;
struct ub_ctx* ctx;
struct lookinfo* lookups;
int i, r, cancel=0, blocking=0, ext=0;
@@ -341,7 +355,7 @@ int main(int argc, char** argv)
checklock_start();
/* create context */
ctx = ub_val_ctx_create();
ctx = ub_ctx_create();
if(!ctx) {
printf("could not create context, %s\n", strerror(errno));
return 1;
@@ -351,15 +365,15 @@ int main(int argc, char** argv)
if(argc == 1) {
usage(argv);
}
while( (c=getopt(argc, argv, "bcdf:hr:tx")) != -1) {
while( (c=getopt(argc, argv, "bcdf:hH:r:tx")) != -1) {
switch(c) {
case 'd':
r = ub_val_ctx_debuglevel(ctx, 3);
checkerr("ub_val_ctx_debuglevel", r);
r = ub_ctx_debuglevel(ctx, 3);
checkerr("ub_ctx_debuglevel", r);
break;
case 't':
r = ub_val_ctx_async(ctx, 1);
checkerr("ub_val_ctx_async", r);
r = ub_ctx_async(ctx, 1);
checkerr("ub_ctx_async", r);
break;
case 'c':
cancel = 1;
@@ -368,18 +382,28 @@ int main(int argc, char** argv)
blocking = 1;
break;
case 'r':
r = ub_val_ctx_resolvconf(ctx, optarg);
r = ub_ctx_resolvconf(ctx, optarg);
if(r != 0) {
printf("ub_val_ctx_resolvconf "
printf("ub_ctx_resolvconf "
"error: %s : %s\n",
ub_val_strerror(r),
ub_strerror(r),
strerror(errno));
return 1;
}
break;
case 'H':
r = ub_ctx_hosts(ctx, optarg);
if(r != 0) {
printf("ub_ctx_hosts "
"error: %s : %s\n",
ub_strerror(r),
strerror(errno));
return 1;
}
break;
case 'f':
r = ub_val_ctx_set_fwd(ctx, optarg);
checkerr("ub_val_ctx_set_fwd", r);
r = ub_ctx_set_fwd(ctx, optarg);
checkerr("ub_ctx_set_fwd", r);
break;
case 'x':
ext = 1;
@@ -410,15 +434,15 @@ int main(int argc, char** argv)
lookups[i].name = argv[i];
if(blocking) {
fprintf(stderr, "lookup %s\n", argv[i]);
r = ub_val_resolve(ctx, argv[i], LDNS_RR_TYPE_A,
r = ub_resolve(ctx, argv[i], LDNS_RR_TYPE_A,
LDNS_RR_CLASS_IN, &lookups[i].result);
checkerr("ub_val_resolve", r);
checkerr("ub_resolve", r);
} else {
fprintf(stderr, "start async lookup %s\n", argv[i]);
r = ub_val_resolve_async(ctx, argv[i], LDNS_RR_TYPE_A,
r = ub_resolve_async(ctx, argv[i], LDNS_RR_TYPE_A,
LDNS_RR_CLASS_IN, &lookups[i], &lookup_is_done,
&lookups[i].async_id);
checkerr("ub_val_resolve_async", r);
checkerr("ub_resolve_async", r);
}
}
if(blocking)
@@ -426,8 +450,8 @@ int main(int argc, char** argv)
else if(cancel) {
for(i=0; i<argc; i++) {
fprintf(stderr, "cancel %s\n", argv[i]);
r = ub_val_cancel(ctx, lookups[i].async_id);
checkerr("ub_val_cancel", r);
r = ub_cancel(ctx, lookups[i].async_id);
checkerr("ub_cancel", r);
}
num_wait = 0;
}
@@ -437,8 +461,8 @@ int main(int argc, char** argv)
for(i=0; i<1000; i++) {
usleep(100000);
fprintf(stderr, "%g seconds passed\n", 0.1*(double)i);
r = ub_val_process(ctx);
checkerr("ub_val_process", r);
r = ub_process(ctx);
checkerr("ub_process", r);
if(num_wait == 0)
break;
}
@@ -451,10 +475,10 @@ int main(int argc, char** argv)
/* print lookup results */
for(i=0; i<argc; i++) {
print_result(&lookups[i]);
ub_val_resolve_free(lookups[i].result);
ub_resolve_free(lookups[i].result);
}
ub_val_ctx_delete(ctx);
ub_ctx_delete(ctx);
free(lookups);
checklock_stop();
return 0;
-17
View File
@@ -832,20 +832,3 @@ checklock_thrjoin(pthread_t thread)
}
#endif /* USE_THREAD_DEBUG */
int order_lock_cmp(const void* e1, const void* e2)
{
struct order_id* o1 = (struct order_id*)e1;
struct order_id* o2 = (struct order_id*)e2;
if(o1->thr < o2->thr) return -1;
if(o1->thr > o2->thr) return 1;
if(o1->instance < o2->instance) return -1;
if(o1->instance > o2->instance) return 1;
return 0;
}
int
codeline_cmp(const void* a, const void* b)
{
return strcmp((const char*)a, (const char*)b);
}
-13
View File
@@ -340,17 +340,4 @@ typedef pthread_key_t ub_thread_key_t;
#define ub_thread_key_get(key) pthread_getspecific(key)
#endif /* USE_THREAD_DEBUG */
/** keep track of lock id in lock-verify application */
struct order_id {
/** the thread id that created it */
int thr;
/** the instance number of creation */
int instance;
};
/** compare two order_ids */
int order_lock_cmp(const void* e1, const void* e2);
/** compare two codeline structs for rbtree */
int codeline_cmp(const void* a, const void* b);
#endif /* TESTCODE_CHECK_LOCKS_H */
+1155
View File
File diff suppressed because it is too large Load Diff
+41 -1
View File
@@ -2,12 +2,31 @@
NEED_SPLINT='00-lint.tpkg'
NEED_DOXYGEN='01-doc.tpkg'
NEED_LDNS_TESTNS='fwd_no_edns.tpkg fwd_tcp_tc.tpkg fwd_tcp.tpkg fwd_three_service.tpkg fwd_three.tpkg fwd_ttlexpire.tpkg fwd_udp.tpkg fwd_tcp_tc6.tpkg fwd_compress_c00c.tpkg fwd_ancil.tpkg stat_timer.tpkg'
NEED_LDNS_TESTNS='fwd_no_edns.tpkg fwd_tcp_tc.tpkg fwd_tcp.tpkg fwd_three_service.tpkg fwd_three.tpkg fwd_ttlexpire.tpkg fwd_udp.tpkg fwd_tcp_tc6.tpkg fwd_compress_c00c.tpkg fwd_ancil.tpkg stat_timer.tpkg 05-asynclook.tpkg stream_tcp.tpkg speed_cache.tpkg fwd_oneport.tpkg fwd_udptmout.tpkg fwd_waitudp.tpkg tcp_sigpipe.tpkg hostsfileosx.tpkg local_nodefault.tpkg'
NEED_XXD='fwd_compress_c00c.tpkg'
NEED_NC='fwd_compress_c00c.tpkg'
NEED_CURL='06-ianaports.tpkg'
NEED_WHOAMI='07-confroot.tpkg'
NEED_IPV6='fwd_ancil.tpkg fwd_tcp_tc6.tpkg'
NEED_JOBCONTROL='tcp_sigpipe.tpkg'
# test if job control - and also signals - are available (not on mingw).
if wait %% 2>&1 | grep "job control not enabled" >/dev/null 2>&1; then
JOBCONTROL=no
else
JOBCONTROL=yes
fi
# test for ipv6, uses streamptcp peculiarity.
if ./streamtcp -f ::1 2>&1 | grep "not supported" >/dev/null 2>&1; then
HAVE_IPV6=no
else
HAVE_IPV6=yes
fi
cd testdata;
sh ../testcode/mini_tpkg.sh clean
rm -f .perfstats.txt
for test in `ls *.tpkg`; do
SKIP=0
if echo $NEED_SPLINT | grep $test >/dev/null; then
@@ -20,6 +39,11 @@ for test in `ls *.tpkg`; do
SKIP=1;
fi
fi
if echo $NEED_CURL | grep $test >/dev/null; then
if test ! -x "`which curl`"; then
SKIP=1;
fi
fi
if echo $NEED_LDNS_TESTNS | grep $test >/dev/null; then
if test ! -x "`which ldns-testns`"; then
SKIP=1;
@@ -35,6 +59,21 @@ for test in `ls *.tpkg`; do
SKIP=1;
fi
fi
if echo $NEED_WHOAMI | grep $test >/dev/null; then
if test ! -x "`which whoami`"; then
SKIP=1;
fi
fi
if echo $NEED_IPV6 | grep $test >/dev/null; then
if test "$HAVE_IPV6" = no; then
SKIP=1;
fi
fi
if echo $NEED_JOBCONTROL | grep $test >/dev/null; then
if test "$JOBCONTROL" = no; then
SKIP=1;
fi
fi
if test $SKIP -eq 0; then
echo $test
sh ../testcode/mini_tpkg.sh -a ../.. exe $test
@@ -43,3 +82,4 @@ for test in `ls *.tpkg`; do
fi
done
sh ../testcode/mini_tpkg.sh report
cat .perfstats.txt
+15 -7
View File
@@ -592,6 +592,14 @@ comm_base_delete(struct comm_base* b)
free(runtime);
}
void
comm_base_timept(struct comm_base* b, uint32_t** tt, struct timeval** tv)
{
struct replay_runtime* runtime = (struct replay_runtime*)b;
*tt = &runtime->now_secs;
*tv = &runtime->now_tv;
}
void
comm_base_dispatch(struct comm_base* b)
{
@@ -676,9 +684,11 @@ struct outside_network*
outside_network_create(struct comm_base* base, size_t bufsize,
size_t ATTR_UNUSED(num_ports), char** ATTR_UNUSED(ifs),
int ATTR_UNUSED(num_ifs), int ATTR_UNUSED(do_ip4),
int ATTR_UNUSED(do_ip6), int ATTR_UNUSED(port_base),
size_t ATTR_UNUSED(num_tcp), struct infra_cache* ATTR_UNUSED(infra),
struct ub_randstate* ATTR_UNUSED(rnd))
int ATTR_UNUSED(do_ip6), size_t ATTR_UNUSED(num_tcp),
struct infra_cache* ATTR_UNUSED(infra),
struct ub_randstate* ATTR_UNUSED(rnd),
int ATTR_UNUSED(use_caps_for_id), int* ATTR_UNUSED(availports),
int ATTR_UNUSED(numavailports))
{
struct outside_network* outnet = calloc(1,
sizeof(struct outside_network));
@@ -703,8 +713,7 @@ outside_network_delete(struct outside_network* outnet)
struct pending*
pending_udp_query(struct outside_network* outnet, ldns_buffer* packet,
struct sockaddr_storage* addr, socklen_t addrlen, int timeout,
comm_point_callback_t* callback, void* callback_arg,
struct ub_randstate* ATTR_UNUSED(rnd))
comm_point_callback_t* callback, void* callback_arg)
{
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
struct fake_pending* pend = (struct fake_pending*)calloc(1,
@@ -756,8 +765,7 @@ pending_udp_query(struct outside_network* outnet, ldns_buffer* packet,
struct waiting_tcp*
pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet,
struct sockaddr_storage* addr, socklen_t addrlen, int timeout,
comm_point_callback_t* callback, void* callback_arg,
struct ub_randstate* ATTR_UNUSED(rnd))
comm_point_callback_t* callback, void* callback_arg)
{
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
struct fake_pending* pend = (struct fake_pending*)calloc(1,
+845
View File
@@ -0,0 +1,845 @@
/*
* testcode/harvest.c - debug program to get relevant data to a set of queries.
*
* Copyright (c) 2008, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This program downloads relevant DNS data to a set of queries.
* This means that the queries are asked to root, TLD, SLD servers and
* the results stored per zone.
* The following data is pertinent:
*
* At each label:
* SOA
* NS
* DNSKEY
* DS
* For the whole query:
* the result.
* For NS-records:
* their label data
* and the A and AAAA records for it.
* (as if the name, with A and AAAA query type is in the list,
* referred to as recursion depth+1)
* Any NSEC, NSEC3, SOA records or additional data found in answers.
*
* All of this is data that would be encountered during an iterative lookup
* for the queries in the list. It is saved to enable a replay of iterative
* lookups for performance testing.
*
* A number of assumptions are made.
* 1) configuration is correct.
* The parent has the same NS records as the child.
* All nameservers carry the same data.
* 2) EDNS/nonEDNS responses and other behaviour is ignored.
* Only the data is saved.
* This creates a snapshot that represents the data as this resolver saw it.
*/
#include "config.h"
#include <signal.h>
#include "libunbound/unbound.h"
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
struct todo_item;
struct labdata;
/** this represents the data that has been collected
* as well as a todo list and some settings */
struct harvest_data {
/** the unbound context */
struct ub_ctx* ctx;
/** a tree per label; thus this first one is one root entry,
* that has a tree of TLD labels. Those have trees of SLD labels. */
struct labdata* root;
/** the original query list */
struct todo_item* orig_list;
/** the query list todo */
struct todo_item* todo_list;
/** last item in todo list */
struct todo_item* todo_last;
/** number of todo items */
int numtodo;
/** where to store the results */
char* resultdir;
/** maximum recursion depth */
int maxdepth;
/** current recursion depth */
int curdepth;
/** max depth of labels */
int maxlabels;
/** number of RRs stored */
int num_rrs;
/** number of zones written */
int num_zones;
};
/**
* Todo item
*/
struct todo_item {
/** the next item */
struct todo_item* next;
/** query as rdf */
ldns_rdf* qname;
/** the query type */
int qtype;
/** query class */
int qclass;
/** recursion depth of todo item (orig list is 0) */
int depth;
/** the label associated with the query */
struct labdata* lab;
};
/**
* Every label has a sest of sublabels, that have sets of sublabels ...
* Per label is stored also a set of data items, and todo information
*/
struct labdata {
/** node in ldns rbtree */
ldns_rbnode_t node;
/** the name of this label */
ldns_rdf* label;
/** full name of point in domain tree */
ldns_rdf* name;
/** parent in label tree (NULL for root) */
struct labdata* parent;
/** tree of sublabels (if any) */
ldns_rbtree_t* sublabels;
/** list of RRs for this label */
ldns_rr_list* rrlist;
/** have queries for this label been queued */
int done;
};
/** usage information for harvest */
static void usage(char* nm)
{
printf("usage: %s [options]\n", nm);
printf("-f fnm query list to read from file\n");
printf(" every line has format: qname qclass qtype\n");
printf("-v verbose (-v -v even more)\n");
printf("-C cfg config file with resolver options\n");
exit(1);
}
/** verbosity for harvest */
static int hverb = 0;
/** exit with error */
static void error_exit(char* str)
{
printf("error: %s\n", str);
exit(1);
}
/** read a query file */
static void
qlist_read_file(struct harvest_data* data, char* fname)
{
char buf[1024];
char nm[1024], cl[1024], tp[1024];
int r;
int num = 0;
FILE* in = fopen(fname, "r");
struct todo_item* t;
if(!in) {
perror(fname);
error_exit("could not open file");
}
while(fgets(buf, (int)sizeof(buf), in)) {
if(buf[0] == 0) continue;
if(buf[0] == '\n') continue;
/* allow some comments */
if(buf[0] == ';') continue;
if(buf[0] == '#') continue;
nm[0] = 0; cl[0] = 0; tp[0] = 0;
r = sscanf(buf, " %1023s %1023s %1023s", nm, cl, tp);
if(r == 0) continue;
t = (struct todo_item*)calloc(1, sizeof(*t));
if(!t) error_exit("out of memory");
t->qname = ldns_dname_new_frm_str(nm);
if(!t->qname) {
printf("parse error: %s\n", nm);
error_exit("bad qname");
}
t->depth = 0;
t->qtype = LDNS_RR_TYPE_A;
t->qclass = LDNS_RR_CLASS_IN;
if(r >= 2) {
if(strcmp(cl, "IN") == 0 || strcmp(cl, "CH") == 0)
t->qclass = ldns_get_rr_class_by_name(cl);
else t->qtype = ldns_get_rr_type_by_name(cl);
}
if(r >= 3) {
if(strcmp(tp, "IN") == 0 || strcmp(tp, "CH") == 0)
t->qclass = ldns_get_rr_class_by_name(tp);
else t->qtype = ldns_get_rr_type_by_name(tp);
}
num++;
t->next = data->orig_list;
data->orig_list = t;
}
printf("read %s: %d queries\n", fname, num);
fclose(in);
}
/** compare two labels */
static int
lab_cmp(const void *x, const void *y)
{
return ldns_dname_compare((const ldns_rdf*)x, (const ldns_rdf*)y);
}
/** create label entry */
static struct labdata*
lab_create(char* name)
{
struct labdata* lab = (struct labdata*)calloc(1, sizeof(*lab));
if(!lab) error_exit("out of memory");
lab->label = ldns_dname_new_frm_str(name);
if(!lab->label) error_exit("out of memory");
lab->name = ldns_dname_new_frm_str(name);
if(!lab->name) error_exit("out of memory");
lab->node.key = lab->label;
lab->node.data = lab;
lab->sublabels = ldns_rbtree_create(lab_cmp);
if(!lab->sublabels) error_exit("out of memory");
lab->rrlist = ldns_rr_list_new();
if(!lab->rrlist) error_exit("out of memory");
return lab;
}
/** for this name, lookup the label, create if does not exist */
static struct labdata*
find_create_lab(struct harvest_data* data, ldns_rdf* name)
{
struct labdata* lab = data->root;
struct labdata* nextlab;
ldns_rdf* next;
uint8_t numlab = ldns_dname_label_count(name);
if((int)numlab > data->maxlabels)
data->maxlabels = (int)numlab;
while(numlab--) {
next = ldns_dname_label(name, numlab);
if(!next) error_exit("ldns_dname_label");
nextlab = (struct labdata*)
ldns_rbtree_search(lab->sublabels, next);
if(!nextlab) {
/* create it */
nextlab = (struct labdata*)calloc(1, sizeof(*lab));
if(!nextlab) error_exit("out of memory");
nextlab->label = ldns_rdf_clone(next);
if(!nextlab->label) error_exit("out of memory");
nextlab->node.key = nextlab->label;
nextlab->node.data = nextlab;
nextlab->sublabels = ldns_rbtree_create(lab_cmp);
if(!nextlab->sublabels) error_exit("out of memory");
nextlab->parent = lab;
nextlab->name = ldns_rdf_clone(next);
if(!nextlab->name) error_exit("out of memory");
if(ldns_dname_cat(nextlab->name, lab->name)
!= LDNS_STATUS_OK) error_exit("outofmem");
nextlab->rrlist = ldns_rr_list_new();
if(!nextlab->rrlist) error_exit("out of memory");
(void)ldns_rbtree_insert(lab->sublabels,
&nextlab->node);
if(hverb) {
printf("new label: ");
ldns_rdf_print(stdout, nextlab->name);
printf("\n");
}
}
lab = nextlab;
ldns_rdf_deep_free(next);
}
return lab;
}
/** for given query, create todo items, and labels if needed */
static void
new_todo_item(struct harvest_data* data, ldns_rdf* qname, int qtype,
int qclass, int depth)
{
struct labdata* lab = find_create_lab(data, qname);
struct todo_item* it;
if(!lab) error_exit("out of memory creating new label");
it = (struct todo_item*)calloc(1, sizeof(*it));
it->qname = ldns_rdf_clone(qname);
it->qtype = qtype;
it->qclass = qclass;
it->depth = depth;
it->lab = lab;
it->next = NULL;
if(data->todo_last)
data->todo_last->next = it;
else data->todo_list = it;
data->todo_last = it;
data->numtodo ++;
if(hverb >= 2) {
printf("new todo: ");
ldns_rdf_print(stdout, it->qname);
if(ldns_rr_descript((uint16_t)it->qtype) &&
ldns_rr_descript((uint16_t)it->qtype)->_name)
printf(" %s", ldns_rr_descript((uint16_t)
it->qtype)->_name);
if(ldns_lookup_by_id(ldns_rr_classes, it->qclass) &&
ldns_lookup_by_id(ldns_rr_classes, it->qclass)->name)
printf(" %s", ldns_lookup_by_id(ldns_rr_classes,
it->qclass)->name);
printf("\n");
}
}
/** add infra todo items for this query */
static void
new_todo_infra(struct harvest_data* data, struct labdata* startlab, int depth)
{
struct labdata* lab;
for(lab = startlab; lab; lab = lab->parent) {
if(lab->done)
return;
new_todo_item(data, lab->name, LDNS_RR_TYPE_NS,
LDNS_RR_CLASS_IN, depth);
new_todo_item(data, lab->name, LDNS_RR_TYPE_SOA,
LDNS_RR_CLASS_IN, depth);
new_todo_item(data, lab->name, LDNS_RR_TYPE_DNSKEY,
LDNS_RR_CLASS_IN, depth);
new_todo_item(data, lab->name, LDNS_RR_TYPE_DS,
LDNS_RR_CLASS_IN, depth);
new_todo_item(data, lab->name, LDNS_RR_TYPE_A,
LDNS_RR_CLASS_IN, depth);
new_todo_item(data, lab->name, LDNS_RR_TYPE_AAAA,
LDNS_RR_CLASS_IN, depth);
lab->done = 1;
}
}
/** make todo items for initial data */
static void
make_todo(struct harvest_data* data)
{
struct todo_item* it;
for(it=data->orig_list; it; it = it->next) {
/* create todo item for this query itself */
new_todo_item(data, it->qname, it->qtype, it->qclass, 0);
/* create todo items for infra queries to support it */
new_todo_infra(data, data->todo_list->lab,
data->todo_list->depth);
}
}
/** store RR and make new work items for it if needed */
static void
process_rr(struct harvest_data* data, ldns_rr* rr, int depth)
{
/* must free or store rr */
struct labdata* lab = find_create_lab(data, ldns_rr_owner(rr));
if(!lab) error_exit("cannot find/create label");
/* generate extra queries */
if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_NS) {
new_todo_infra(data, find_create_lab(data,
ldns_rr_ns_nsdname(rr)), depth+1);
} else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_MX) {
new_todo_infra(data, find_create_lab(data,
ldns_rr_mx_exchange(rr)), depth+1);
} else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
new_todo_infra(data, find_create_lab(data,
ldns_rr_rdf(rr, 0)), depth+1);
} else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_CNAME) {
int t = ldns_rr_get_type(rr);
if(t!=LDNS_RR_TYPE_A && t!=LDNS_RR_TYPE_AAAA &&
t!=LDNS_RR_TYPE_SOA && t!=LDNS_RR_TYPE_NS &&
t!=LDNS_RR_TYPE_DS && t!=LDNS_RR_TYPE_DNSKEY)
new_todo_item(data, ldns_rr_rdf(rr, 0), t,
ldns_rr_get_class(rr), depth+1);
/* can get caught in CNAME loop, but depth will
* catch that; unbound cache helps too(servfails on
* a cname loop) */
new_todo_infra(data, find_create_lab(data,
ldns_rr_rdf(rr, 0)), depth+1);
}
/* store it */
if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC) {
/* find correct zone to store NSEC in (for delegation zones) */
if(ldns_dname_compare(ldns_rr_rdf(rr, 0), ldns_rr_owner(rr))
== 0) {
/* store at the single name = apex */
} else if(!ldns_dname_is_subdomain(ldns_rr_rdf(rr, 0),
ldns_rr_owner(rr)) && lab->parent) {
/* if owner NSEC subdomain-of-owner then
* store at owner (owner is apex or empty nonterminal).
* Otherwise at owner parent. */
lab = lab->parent;
}
} else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_DS) {
/* store DSes in parent zone */
if(lab->parent)
lab = lab->parent;
} else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3) {
/* store NSEC3s one label up at zone apex */
if(lab->parent)
lab = lab->parent;
}
/* we assume NS set is equal across parent-child border. */
if(!ldns_rr_list_contains_rr(lab->rrlist, rr)) {
if(hverb >= 2) {
printf("store RR ");
ldns_rr_print(stdout, rr);
printf("\n");
}
if(!ldns_rr_list_push_rr(lab->rrlist, rr))
error_exit("outofmem ldns_rr_list_push_rr");
data->num_rrs++;
} else {
if(hverb >= 2) {
printf("duplicate RR ");
ldns_rr_print(stdout, rr);
printf("\n");
}
ldns_rr_free(rr);
}
}
/** store RRs and make new work items if needed */
static void
process_pkt(struct harvest_data* data, ldns_pkt* pkt, int depth)
{
size_t i;
ldns_rr_list* list;
list = ldns_pkt_get_section_clone(pkt, LDNS_SECTION_ANY_NOQUESTION);
if(!list) error_exit("outofmemory");
for(i=0; i<ldns_rr_list_rr_count(list); i++) {
process_rr(data, ldns_rr_list_rr(list, i), depth);
}
ldns_rr_list_free(list);
}
/** process a todo item */
static void
process(struct harvest_data* data, struct todo_item* it)
{
int r;
char* nm;
struct ub_result* result = NULL;
ldns_pkt* pkt = NULL;
ldns_status s;
if(hverb) {
printf("process: ");
ldns_rdf_print(stdout, it->qname);
if(ldns_rr_descript((uint16_t)it->qtype) &&
ldns_rr_descript((uint16_t)it->qtype)->_name)
printf(" %s", ldns_rr_descript((uint16_t)
it->qtype)->_name);
if(ldns_lookup_by_id(ldns_rr_classes, it->qclass) &&
ldns_lookup_by_id(ldns_rr_classes, it->qclass)->name)
printf(" %s", ldns_lookup_by_id(ldns_rr_classes,
it->qclass)->name);
printf("\n");
}
/* do lookup */
nm = ldns_rdf2str(it->qname);
if(!nm) error_exit("ldns_rdf2str");
r = ub_resolve(data->ctx, nm, it->qtype, it->qclass, &result);
if(r != 0) {
printf("ub_resolve(%s, %d, %d): %s\n", nm, it->qtype,
it->qclass, ub_strerror(r));
free(nm);
return;
}
if(result->rcode == LDNS_RCODE_SERVFAIL) {
free(nm);
return;
}
/* even if result is a negative, try to store resulting SOA/NSEC */
/* create ldns pkt */
s = ldns_wire2pkt(&pkt, result->answer_packet,
(size_t)result->answer_len);
if(s != LDNS_STATUS_OK) {
printf("ldns_wire2pkt failed! %s %d %d %s %d\n", nm,
it->qtype, it->qclass, ldns_get_errorstr_by_id(s),
result->answer_len);
free(nm);
return;
}
if(hverb >= 2) {
printf("answer: ");
ldns_pkt_print(stdout, pkt);
printf("\n");
}
/* process results */
process_pkt(data, pkt, it->depth);
ldns_pkt_free(pkt);
free(nm);
ub_resolve_free(result);
}
/** perform main harvesting */
static void
harvest_main(struct harvest_data* data)
{
struct todo_item* it;
int numdone = 0;
/* register todo queries for all original queries */
make_todo(data);
printf("depth 0: done %d todo %d\n", 0, data->numtodo);
/* pick up a todo item and process it */
while(data->todo_list) {
numdone++;
it = data->todo_list;
data->todo_list = it->next;
if(!data->todo_list) data->todo_last = NULL;
if(numdone%1000==0 || it->depth > data->curdepth) {
data->curdepth = it->depth;
printf("depth %d: done %d todo %d, %d rrs\n",
it->depth, numdone, data->numtodo,
data->num_rrs);
}
if(it->depth >= data->maxdepth) {
printf("obtained %d rrs to a max of %d labels.\n",
data->num_rrs, data->maxlabels);
return;
}
data->numtodo--;
process(data, it);
usleep(1000000/100);
}
}
/** create directory if it does not exist */
static void
hv_mkdir(char* dir)
{
#ifdef MKDIR_HAS_ONE_ARG
if(mkdir(dir) == -1) {
#else
if(mkdir(dir, 0755) == -1) {
#endif
if(errno == EEXIST)
return;
perror(dir);
error_exit("mkdir failed");
}
}
/** see if rrlist contains a SOA record */
static ldns_rr*
has_SOA(ldns_rr_list* list)
{
size_t i;
for(i=0; i<ldns_rr_list_rr_count(list); i++) {
if(ldns_rr_get_type(ldns_rr_list_rr(list, i))
== LDNS_RR_TYPE_SOA)
return ldns_rr_list_rr(list, i);
}
return NULL;
}
/** write moredata for a zone*/
static void
write_moredata(struct harvest_data* data, struct labdata* zone,
FILE *f, struct labdata* thislab, ldns_rr* nslist)
{
struct labdata* lab;
size_t i;
ldns_rr* ns;
LDNS_RBTREE_FOR(lab, struct labdata*, thislab->sublabels) {
if(has_SOA(lab->rrlist)) {
/* copy only NS glue */
for(i=0; i<ldns_rr_list_rr_count(lab->rrlist); i++) {
ns = ldns_rr_list_rr(lab->rrlist, i);
if(ldns_rr_get_type(ns) == LDNS_RR_TYPE_NS) {
ldns_rr_print(f, ns);
if(ldns_dname_is_subdomain(
ldns_rr_ns_nsdname(ns),
lab->name)) {
ldns_rr_push_rdf(nslist,
ldns_rdf_clone(
ldns_rr_ns_nsdname(ns)));
}
}
}
} else {
/* copy all, recurse */
for(i=0; i<ldns_rr_list_rr_count(lab->rrlist); i++) {
ldns_rr_print(f,
ldns_rr_list_rr(lab->rrlist, i));
}
write_moredata(data, zone, f, lab, nslist);
}
}
}
/** find and write glue into zone file */
static void
write_glue(struct harvest_data* data, struct labdata* thislab, FILE* f,
ldns_rdf* name, int dep)
{
size_t i;
struct labdata* lab;
ldns_rr* rr;
if(ldns_dname_compare(name, thislab->name) == 0) {
/* this is it! Did we go outside the zone? */
if(dep == 0)
return;
/* find A and AAAA */
for(i=0; i<ldns_rr_list_rr_count(thislab->rrlist); i++) {
rr = ldns_rr_list_rr(thislab->rrlist, i);
if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_A ||
ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) {
ldns_rr_print(f, rr);
}
}
return;
}
/* recurse deeper */
LDNS_RBTREE_FOR(lab, struct labdata*, thislab->sublabels) {
if(has_SOA(lab->rrlist)) {
write_glue(data, lab, f, name, dep+1);
} else {
write_glue(data, lab, f, name, dep);
}
}
}
/** write zonefile for zone at this apex */
static void
write_zonefile(struct harvest_data* data, int dep, FILE* zlist,
struct labdata* apex, ldns_rr* soa)
{
FILE *f;
char fname[1024];
char* zname = ldns_rdf2str(apex->name);
time_t tm = time(NULL);
size_t i;
ldns_rr* nslist;
if(!zname) error_exit("out of mem ldns_rdf2str");
if(strcmp(zname, ".") == 0)
snprintf(fname, sizeof(fname), "l%d/root.zone", dep);
else snprintf(fname, sizeof(fname), "l%d/%szone", dep, zname);
fprintf(zlist, "zone: name: \"%s\" %s%szonefile: \"%s\"\n",
zname,
strlen(zname)/8<1?"\t":"",
strlen(zname)/8<2?"\t":"",
fname);
if(hverb) printf("writing %s\n", fname);
f = fopen(fname, "w");
if(!f) {
perror(fname);
error_exit("cannot open zone file");
}
fprintf(f, "; %s - generated by harvest program.\n", fname);
fprintf(f, "; zone name %s - this is a partial snapshot of "
"data relevant to the query list.\n", zname);
fprintf(f, "; created %u - date %s\n", (unsigned)tm, ctime(&tm));
ldns_rr_print(f, soa);
fprintf(f, "\n");
for(i=0; i<ldns_rr_list_rr_count(apex->rrlist); i++) {
if(ldns_rr_get_type(ldns_rr_list_rr(apex->rrlist, i))
== LDNS_RR_TYPE_SOA) continue;
ldns_rr_print(f, ldns_rr_list_rr(apex->rrlist, i));
}
/* search for more data - subdomains inside the zone, NS glue */
nslist = ldns_rr_new();
if(!nslist) error_exit("out of memory");
fprintf(f, "; end of apex, more data follows\n");
write_moredata(data, apex, f, apex, nslist);
/* add NS from apex that need glue too */
for(i=0; i<ldns_rr_list_rr_count(apex->rrlist); i++) {
if(ldns_rr_get_type(ldns_rr_list_rr(apex->rrlist, i)) !=
LDNS_RR_TYPE_NS)
continue;
/* these are only added again if in a subzone */
if(ldns_dname_is_subdomain(ldns_rr_ns_nsdname(
ldns_rr_list_rr(apex->rrlist, i)), apex->name)) {
ldns_rr_push_rdf(nslist, ldns_rdf_clone(
ldns_rr_ns_nsdname(ldns_rr_list_rr(
apex->rrlist, i))));
}
}
fprintf(f, "; glue data follows\n");
/* lookup and add glue (if not already in zone) */
for(i=0; i<ldns_rr_rd_count(nslist); i++) {
write_glue(data, apex, f, ldns_rr_rdf(nslist, i), 0);
}
fclose(f);
ldns_rr_free(nslist);
free(zname);
}
/** create zones at depth d in label tree */
static void
create_zones(struct harvest_data* data, int dep, FILE* zlist,
struct labdata* labnow, int depnow)
{
struct labdata* s;
ldns_rr* soa;
if(depnow == dep) {
/* see if this is a zone start - a SOA */
if((soa=has_SOA(labnow->rrlist))) {
write_zonefile(data, dep, zlist, labnow, soa);
data->num_zones++;
}
return;
}
/* recurse */
LDNS_RBTREE_FOR(s, struct labdata*, labnow->sublabels) {
create_zones(data, dep, zlist, s, depnow+1);
}
}
/** sort rrlists */
static void
harvest_sort(struct labdata* lab)
{
struct labdata* s;
/* prettier output if sorted here */
ldns_rr_list_sort(lab->rrlist);
/* and recurse */
LDNS_RBTREE_FOR(s, struct labdata*, lab->sublabels) {
harvest_sort(s);
}
}
/** output harvested results */
static void
harvest_output(struct harvest_data* data)
{
int d;
char buf[20];
FILE* zlist;
int lastzones;
hv_mkdir(data->resultdir);
if(chdir(data->resultdir) == -1) {
perror(data->resultdir);
error_exit("cannot chdir");
}
harvest_sort(data->root);
/* create zones */
for(d = 0; d<data->maxlabels; d++) {
lastzones = data->num_zones;
printf("creating zones %d\n", d);
snprintf(buf, sizeof(buf), "l%d", d);
hv_mkdir(buf);
snprintf(buf, sizeof(buf), "l%d.zones", d);
zlist = fopen(buf, "w");
if(!zlist) {
perror(buf);
error_exit("cannot write zonelist file");
}
fprintf(zlist, "# partial zones at depth %d\n", d);
create_zones(data, d, zlist, data->root, 0);
fclose(zlist);
printf("creating zones %d - %d zones written\n", d,
data->num_zones - lastzones);
}
}
/** getopt global, in case header files fail to declare it. */
extern int optind;
/** getopt global, in case header files fail to declare it. */
extern char* optarg;
/** main program for harvest */
int main(int argc, char* argv[])
{
struct harvest_data data;
char* nm = argv[0];
int c;
/* defaults */
memset(&data, 0, sizeof(data));
data.ctx = ub_ctx_create();
data.resultdir = strdup("harvested_zones");
if(!data.resultdir) error_exit("out of memory");
data.maxdepth = 2;
/* parse the options */
while( (c=getopt(argc, argv, "hf:vC:")) != -1) {
switch(c) {
case 'C':
if(ub_ctx_config(data.ctx, optarg) != 0)
error_exit("config read failed");
break;
case 'f':
qlist_read_file(&data, optarg);
break;
case 'v':
hverb++;
break;
case '?':
case 'h':
default:
usage(nm);
}
}
argc -= optind;
argv += optind;
if(argc != 0)
usage(nm);
if(data.orig_list == NULL)
error_exit("No queries to make, use -f (help with -h).");
data.root = lab_create(".");
if(!data.root) error_exit("out of memory");
/* harvest the data */
harvest_main(&data);
harvest_output(&data);
/* no cleanup except the context (to close open sockets) */
ub_ctx_delete(data.ctx);
return 0;
}
+9 -1
View File
@@ -3,7 +3,7 @@
*
* Data storage for specially crafted replies for testing purposes.
*
* (c) NLnet Labs, 2005, 2006, 2007
* (c) NLnet Labs, 2005, 2006, 2007, 2008
* See the file LICENSE for the license
*/
@@ -708,7 +708,11 @@ adjust_packet(struct entry* match, ldns_pkt* answer_pkt, ldns_pkt* query_pkt)
}
if(match->sleeptime > 0) {
verbose(3, "sleeping for %d seconds\n", match->sleeptime);
#ifdef HAVE_SLEEP
sleep(match->sleeptime);
#else
Sleep(match->sleeptime * 1000);
#endif
}
}
@@ -808,7 +812,11 @@ handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, int* count,
if(p->packet_sleep) {
verbose(3, "sleeping for next packet %d secs\n",
p->packet_sleep);
#ifdef HAVE_SLEEP
sleep(p->packet_sleep);
#else
Sleep(p->packet_sleep * 1000);
#endif
verbose(3, "wakeup for next packet "
"(slept %d secs)\n", p->packet_sleep);
}
+11 -1
View File
@@ -47,11 +47,21 @@
#include "util/log.h"
#include "util/rbtree.h"
#include "util/locks.h"
#include "testcode/checklocks.h"
#include "util/fptr_wlist.h"
/* --- data structures --- */
struct lock_ref;
/** keep track of lock id in lock-verify application
* Also defined in smallapp/worker_cb.c for fptr_wlist encapsulation
* breakage (the security tests break encapsulation for this test app) */
struct order_id {
/** the thread id that created it */
int thr;
/** the instance number of creation */
int instance;
};
/** a lock */
struct order_lock {
/** rbnode in all tree */
+1 -1
View File
@@ -43,7 +43,7 @@
#include "util/log.h"
#include "util/rbtree.h"
#include "util/locks.h"
#include "testcode/checklocks.h"
#include "util/fptr_wlist.h"
#include <sys/stat.h>
/**
+19 -4
View File
@@ -18,14 +18,18 @@ if test "$1" = "fake"; then
fi
if test "$1" = "report" || test "$2" = "report"; then
echo "Minitpkg Report"
for result in result.*; do
name=`echo $result | sed -e 's/result\.//'`
for result in *.tpkg; do
name=`basename $result .tpkg`
if test -f ".done-$name"; then
if test "$1" != "-q"; then
echo "** PASSED ** : $name"
fi
else
echo "!! FAILED !! : $name"
if test -f "result.$name"; then
echo "!! FAILED !! : $name"
else
echo ">> SKIPPED<< : $name"
fi
fi
done
exit 0
@@ -56,7 +60,11 @@ dir=$name.$$
result=result.$name
done=.done-$name
success="no"
shell="bash"
if test -x "`which bash`"; then
shell="bash"
else
shell="sh"
fi
# check already done
if test -f .done-$name; then
@@ -109,3 +117,10 @@ fi
mv $result ..
cd ..
rm -rf $dir
# compat for windows where deletion may not succeed initially (files locked
# by processes that still have to exit).
if test $? -eq 1; then
echo "minitpkg waiting for processes to terminate"
sleep 2 # some time to exit, and try again
rm -rf $dir
fi
+646
View File
@@ -0,0 +1,646 @@
/*
* testcode/perf.c - debug program to estimate name server performance.
*
* Copyright (c) 2008, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This program estimates DNS name server performance.
*/
#include "config.h"
#include <signal.h>
#include "util/log.h"
#include "util/locks.h"
#include "util/net_help.h"
#include "util/data/msgencode.h"
#include "util/data/msgreply.h"
#include "util/data/msgparse.h"
/** usage information for perf */
static void usage(char* nm)
{
printf("usage: %s [options] server\n", nm);
printf("server: ip address of server, IP4 or IP6.\n");
printf(" If not on port %d add @port.\n", UNBOUND_DNS_PORT);
printf("-d sec duration of test in whole seconds (0: wait for ^C)\n");
printf("-a str query to ask, interpreted as a line from qfile\n");
printf("-f fnm query list to read from file\n");
printf(" every line has format: qname qclass qtype [+-]{E}\n");
printf(" where + means RD set, E means EDNS enabled\n");
printf("-q quiet mode, print only final qps\n");
exit(1);
}
struct perfinfo;
struct perfio;
/** Global info for perf */
struct perfinfo {
/** need to exit */
volatile int exit;
/** all purpose buffer (for UDP send and receive) */
ldns_buffer* buf;
/** destination */
struct sockaddr_storage dest;
/** length of dest socket addr */
socklen_t destlen;
/** when did this time slice start */
struct timeval since;
/** number of queries received in that time */
size_t numrecv;
/** number of queries sent out in that time */
size_t numsent;
/** duration of test in seconds */
int duration;
/** quiet mode? */
int quiet;
/** when did the total test start */
struct timeval start;
/** total number recvd */
size_t total_recv;
/** total number sent */
size_t total_sent;
/** numbers by rcode */
size_t by_rcode[32];
/** number of I/O ports */
size_t io_num;
/** I/O ports array */
struct perfio* io;
/** max fd value in io ports */
int maxfd;
/** readset */
fd_set rset;
/** size of querylist */
size_t qlist_size;
/** allocated size of qlist array */
size_t qlist_capacity;
/** list of query packets (data) */
uint8_t** qlist_data;
/** list of query packets (length of a packet) */
size_t* qlist_len;
/** index into querylist, for walking the list */
size_t qlist_idx;
};
/** I/O port for perf */
struct perfio {
/** id number */
size_t id;
/** file descriptor of socket */
int fd;
/** timeout value */
struct timeval timeout;
/** ptr back to perfinfo */
struct perfinfo* info;
};
/** number of msec between starting io ports */
#define START_IO_INTERVAL 10
/** number of msec timeout on io ports */
#define IO_TIMEOUT 10
/** signal handler global info */
static struct perfinfo* sig_info;
/** signal handler for user quit */
static RETSIGTYPE perf_sigh(int sig)
{
log_assert(sig_info);
if(!sig_info->quiet)
printf("exit on signal %d\n", sig);
sig_info->exit = 1;
}
/** timeval compare, t1 < t2 */
static int
perf_tv_smaller(struct timeval* t1, struct timeval* t2)
{
#ifndef S_SPLINT_S
if(t1->tv_sec < t2->tv_sec)
return 1;
if(t1->tv_sec == t2->tv_sec &&
t1->tv_usec < t2->tv_usec)
return 1;
#endif
return 0;
}
/** timeval add, t1 += t2 */
static void
perf_tv_add(struct timeval* t1, struct timeval* t2)
{
#ifndef S_SPLINT_S
t1->tv_sec += t2->tv_sec;
t1->tv_usec += t2->tv_usec;
while(t1->tv_usec > 1000000) {
t1->tv_usec -= 1000000;
t1->tv_sec++;
}
#endif
}
/** timeval subtract, t1 -= t2 */
static void
perf_tv_subtract(struct timeval* t1, struct timeval* t2)
{
#ifndef S_SPLINT_S
t1->tv_sec -= t2->tv_sec;
if(t1->tv_usec >= t2->tv_usec) {
t1->tv_usec -= t2->tv_usec;
} else {
t1->tv_sec--;
t1->tv_usec = 1000000-(t2->tv_usec-t1->tv_usec);
}
#endif
}
/** setup perf test environment */
static void
perfsetup(struct perfinfo* info)
{
size_t i;
if(gettimeofday(&info->start, NULL) < 0)
fatal_exit("gettimeofday: %s", strerror(errno));
sig_info = info;
if( signal(SIGINT, perf_sigh) == SIG_ERR ||
#ifdef SIGQUIT
signal(SIGQUIT, perf_sigh) == SIG_ERR ||
#endif
#ifdef SIGHUP
signal(SIGHUP, perf_sigh) == SIG_ERR ||
#endif
#ifdef SIGBREAK
signal(SIGBREAK, perf_sigh) == SIG_ERR ||
#endif
signal(SIGTERM, perf_sigh) == SIG_ERR)
fatal_exit("could not bind to signal");
info->io = (struct perfio*)calloc(sizeof(struct perfio), info->io_num);
if(!info->io) fatal_exit("out of memory");
#ifndef S_SPLINT_S
FD_ZERO(&info->rset);
#endif
info->since = info->start;
for(i=0; i<info->io_num; i++) {
info->io[i].id = i;
info->io[i].info = info;
info->io[i].fd = socket(
addr_is_ip6(&info->dest, info->destlen)?
AF_INET6:AF_INET, SOCK_DGRAM, 0);
if(info->io[i].fd == -1) {
#ifndef USE_WINSOCK
fatal_exit("socket: %s", strerror(errno));
#else
fatal_exit("socket: %s",
wsa_strerror(WSAGetLastError()));
#endif
}
if(info->io[i].fd > info->maxfd)
info->maxfd = info->io[i].fd;
#ifndef S_SPLINT_S
FD_SET(FD_SET_T info->io[i].fd, &info->rset);
info->io[i].timeout.tv_usec = ((START_IO_INTERVAL*i)%1000)
*1000;
info->io[i].timeout.tv_sec = (START_IO_INTERVAL*i)/1000;
perf_tv_add(&info->io[i].timeout, &info->since);
#endif
}
}
/** cleanup perf test environment */
static void
perffree(struct perfinfo* info)
{
size_t i;
if(!info) return;
if(info->io) {
for(i=0; i<info->io_num; i++) {
close(info->io[i].fd);
}
free(info->io);
}
for(i=0; i<info->qlist_size; i++)
free(info->qlist_data[i]);
free(info->qlist_data);
free(info->qlist_len);
}
/** send new query for io */
static void
perfsend(struct perfinfo* info, size_t n, struct timeval* now)
{
ssize_t r;
r = sendto(info->io[n].fd, info->qlist_data[info->qlist_idx],
info->qlist_len[info->qlist_idx], 0,
(struct sockaddr*)&info->dest, info->destlen);
/*log_hex("send", info->qlist_data[info->qlist_idx],
info->qlist_len[info->qlist_idx]);*/
if(r == -1) {
#ifndef USE_WINSOCK
log_err("sendto: %s", strerror(errno));
#else
log_err("sendto: %s", wsa_strerror(WSAGetLastError()));
#endif
} else if(r != (ssize_t)info->qlist_len[info->qlist_idx]) {
log_err("partial sendto");
}
info->qlist_idx = (info->qlist_idx+1) % info->qlist_size;
info->numsent++;
info->io[n].timeout.tv_sec = IO_TIMEOUT/1000;
info->io[n].timeout.tv_usec = (IO_TIMEOUT%1000)*1000;
perf_tv_add(&info->io[n].timeout, now);
}
/** got reply for io */
static void
perfreply(struct perfinfo* info, size_t n, struct timeval* now)
{
ssize_t r;
r = recv(info->io[n].fd, ldns_buffer_begin(info->buf),
ldns_buffer_capacity(info->buf), 0);
if(r == -1) {
#ifndef USE_WINSOCK
log_err("recv: %s", strerror(errno));
#else
log_err("recv: %s", wsa_strerror(WSAGetLastError()));
#endif
} else {
info->by_rcode[LDNS_RCODE_WIRE(ldns_buffer_begin(
info->buf))]++;
info->numrecv++;
}
/*ldns_buffer_set_limit(info->buf, r);
log_buf(0, "reply", info->buf);*/
perfsend(info, n, now);
}
/** got timeout for io */
static void
perftimeout(struct perfinfo* info, size_t n, struct timeval* now)
{
/* may not be a dropped packet, this is also used to start
* up the sending IOs */
perfsend(info, n, now);
}
/** print nice stats about qps */
static void
stat_printout(struct perfinfo* info, struct timeval* now,
struct timeval* elapsed)
{
/* calculate qps */
double dt, qps = 0;
#ifndef S_SPLINT_S
dt = (double)(elapsed->tv_sec*1000000 + elapsed->tv_usec) / 1000000;
#endif
if(dt > 0.001)
qps = (double)(info->numrecv) / dt;
if(!info->quiet)
printf("qps: %g\n", qps);
/* setup next slice */
info->since = *now;
info->total_sent += info->numsent;
info->total_recv += info->numrecv;
info->numrecv = 0;
info->numsent = 0;
}
/** wait for new events for performance test */
static void
perfselect(struct perfinfo* info)
{
fd_set rset = info->rset;
struct timeval timeout, now;
int num;
size_t i;
if(gettimeofday(&now, NULL) < 0)
fatal_exit("gettimeofday: %s", strerror(errno));
/* time to exit? */
if(info->duration > 0) {
timeout = now;
perf_tv_subtract(&timeout, &info->start);
if((int)timeout.tv_sec >= info->duration) {
info->exit = 1;
return;
}
}
/* time for stats printout? */
timeout = now;
perf_tv_subtract(&timeout, &info->since);
if(timeout.tv_sec > 0) {
stat_printout(info, &now, &timeout);
}
/* see what is closest port to timeout; or if there is a timeout */
timeout = info->io[0].timeout;
for(i=0; i<info->io_num; i++) {
if(perf_tv_smaller(&info->io[i].timeout, &now)) {
perftimeout(info, i, &now);
return;
}
if(perf_tv_smaller(&info->io[i].timeout, &timeout)) {
timeout = info->io[i].timeout;
}
}
perf_tv_subtract(&timeout, &now);
num = select(info->maxfd+1, &rset, NULL, NULL, &timeout);
if(num == -1) {
if(errno == EAGAIN || errno == EINTR)
return;
log_err("select: %s", strerror(errno));
}
/* handle new events */
for(i=0; num && i<info->io_num; i++) {
if(FD_ISSET(info->io[i].fd, &rset)) {
perfreply(info, i, &now);
num--;
}
}
}
/** show end stats */
static void
perfendstats(struct perfinfo* info)
{
double dt, qps;
struct timeval timeout, now;
int i, lost;
if(gettimeofday(&now, NULL) < 0)
fatal_exit("gettimeofday: %s", strerror(errno));
timeout = now;
perf_tv_subtract(&timeout, &info->since);
stat_printout(info, &now, &timeout);
timeout = now;
perf_tv_subtract(&timeout, &info->start);
dt = (double)(timeout.tv_sec*1000000 + timeout.tv_usec) / 1000000.0;
qps = (double)(info->total_recv) / dt;
lost = (int)(info->total_sent - info->total_recv) - (int)info->io_num;
if(!info->quiet) {
printf("overall time: %g sec\n",
(double)timeout.tv_sec +
(double)timeout.tv_usec/1000000.);
if(lost > 0)
printf("Packets lost: %d\n", (int)lost);
for(i=0; i<(int)(sizeof(info->by_rcode)/sizeof(size_t)); i++)
{
if(info->by_rcode[i] > 0) {
printf("%d(%5s): %u replies\n",
i, ldns_lookup_by_id(ldns_rcodes, i)?
ldns_lookup_by_id(ldns_rcodes,
i)->name:"??",
(unsigned)info->by_rcode[i]);
}
}
}
printf("average qps: %g\n", qps);
}
/** perform the performance test */
static void
perfmain(struct perfinfo* info)
{
perfsetup(info);
while(!info->exit) {
perfselect(info);
}
perfendstats(info);
perffree(info);
}
/** parse a query line to a packet into buffer */
static int
qlist_parse_line(ldns_buffer* buf, char* p)
{
char nm[1024], cl[1024], tp[1024], fl[1024];
int r;
int rec = 1, edns = 0;
struct query_info qinfo;
ldns_rdf* rdf;
nm[0] = 0; cl[0] = 0; tp[0] = 0; fl[0] = 0;
r = sscanf(p, " %1023s %1023s %1023s %1023s", nm, cl, tp, fl);
if(r != 3 && r != 4)
return 0;
/*printf("nm='%s', cl='%s', tp='%s', fl='%s'\n", nm, cl, tp, fl);*/
if(strcmp(tp, "IN") == 0 || strcmp(tp, "CH") == 0) {
qinfo.qtype = ldns_get_rr_type_by_name(cl);
qinfo.qclass = ldns_get_rr_class_by_name(tp);
} else {
qinfo.qtype = ldns_get_rr_type_by_name(tp);
qinfo.qclass = ldns_get_rr_class_by_name(cl);
}
if(fl[0] == '+') rec = 1;
else if(fl[0] == '-') rec = 0;
else if(fl[0] == 'E') edns = 1;
if((fl[0] == '+' || fl[0] == '-') && fl[1] == 'E')
edns = 1;
rdf = ldns_dname_new_frm_str(nm);
if(!rdf)
return 0;
qinfo.qname = ldns_rdf_data(rdf);
qinfo.qname_len = ldns_rdf_size(rdf);
qinfo_query_encode(buf, &qinfo);
ldns_buffer_write_u16_at(buf, 0, 0); /* zero ID */
if(rec) LDNS_RD_SET(ldns_buffer_begin(buf));
if(edns) {
struct edns_data edns;
memset(&edns, 0, sizeof(edns));
edns.edns_present = 1;
edns.udp_size = EDNS_ADVERTISED_SIZE;
/* Set DO bit in all EDNS datagrams ... */
edns.bits = EDNS_DO;
attach_edns_record(buf, &edns);
}
ldns_rdf_deep_free(rdf);
return 1;
}
/** grow query list capacity */
static void
qlist_grow_capacity(struct perfinfo* info)
{
size_t newcap = (size_t)((info->qlist_capacity==0)?16:
info->qlist_capacity*2);
uint8_t** d = (uint8_t**)calloc(sizeof(uint8_t*), newcap);
size_t* l = (size_t*)calloc(sizeof(size_t), newcap);
if(!d || !l) fatal_exit("out of memory");
memcpy(d, info->qlist_data, sizeof(uint8_t*)*
info->qlist_capacity);
memcpy(l, info->qlist_len, sizeof(size_t)*
info->qlist_capacity);
free(info->qlist_data);
free(info->qlist_len);
info->qlist_data = d;
info->qlist_len = l;
info->qlist_capacity = newcap;
}
/** setup query list in info */
static void
qlist_add_line(struct perfinfo* info, char* line, int no)
{
if(!qlist_parse_line(info->buf, line)) {
printf("error parsing query %d: %s\n", no, line);
exit(1);
}
ldns_buffer_write_u16_at(info->buf, 0, (uint16_t)info->qlist_size);
if(info->qlist_size + 1 > info->qlist_capacity) {
qlist_grow_capacity(info);
}
info->qlist_len[info->qlist_size] = ldns_buffer_limit(info->buf);
info->qlist_data[info->qlist_size] = memdup(
ldns_buffer_begin(info->buf), ldns_buffer_limit(info->buf));
if(!info->qlist_data[info->qlist_size])
fatal_exit("out of memory");
info->qlist_size ++;
}
/** setup query list in info */
static void
qlist_read_file(struct perfinfo* info, char* fname)
{
char buf[1024];
char *p;
FILE* in = fopen(fname, "r");
int lineno = 0;
if(!in) {
perror(fname);
exit(1);
}
while(fgets(buf, (int)sizeof(buf), in)) {
lineno++;
buf[sizeof(buf)-1] = 0;
p = buf;
while(*p == ' ' || *p == '\t')
p++;
if(p[0] == 0 || p[0] == '\n' || p[0] == ';' || p[0] == '#')
continue;
qlist_add_line(info, p, lineno);
}
printf("Read %s, got %u queries\n", fname, (unsigned)info->qlist_size);
fclose(in);
}
/** getopt global, in case header files fail to declare it. */
extern int optind;
/** getopt global, in case header files fail to declare it. */
extern char* optarg;
/** main program for perf */
int main(int argc, char* argv[])
{
char* nm = argv[0];
int c;
struct perfinfo info;
#ifdef USE_WINSOCK
int r;
WSADATA wsa_data;
#endif
/* defaults */
memset(&info, 0, sizeof(info));
info.io_num = 16;
log_init(NULL, 0, NULL);
log_ident_set("perf");
checklock_start();
#ifdef USE_WINSOCK
if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0)
fatal_exit("WSAStartup failed: %s", wsa_strerror(r));
#endif
info.buf = ldns_buffer_new(65553);
if(!info.buf) fatal_exit("out of memory");
/* parse the options */
while( (c=getopt(argc, argv, "d:ha:f:q")) != -1) {
switch(c) {
case 'q':
info.quiet = 1;
break;
case 'd':
if(atoi(optarg)==0 && strcmp(optarg, "0")!=0) {
printf("-d not a number %s", optarg);
return 1;
}
info.duration = atoi(optarg);
break;
case 'a':
qlist_add_line(&info, optarg, 0);
break;
case 'f':
qlist_read_file(&info, optarg);
break;
case '?':
case 'h':
default:
usage(nm);
}
}
argc -= optind;
argv += optind;
if(argc != 1) {
printf("error: pass server IP address on commandline.\n");
usage(nm);
}
if(!extstrtoaddr(argv[0], &info.dest, &info.destlen)) {
printf("Could not parse ip: %s\n", argv[0]);
return 1;
}
if(info.qlist_size == 0) {
printf("No queries to make, use -f or -a.\n");
return 1;
}
/* do the performance test */
perfmain(&info);
ldns_buffer_free(info.buf);
#ifdef USE_WINSOCK
WSACleanup();
#endif
checklock_stop();
return 0;
}
-1
View File
@@ -235,7 +235,6 @@ replay_moment_read(char* remain, FILE* in, const char* name, int* lineno,
remain++;
if(strlen(remain) > 0) /* remove \n */
remain[strlen(remain)-1] = 0;
printf("remain '%s'\n", remain);
if(!extstrtoaddr(remain, &mom->addr, &mom->addrlen)) {
log_err("line %d: could not parse ADDRESS: %s",
*lineno, remain);
+5
View File
@@ -226,6 +226,11 @@ struct replay_runtime {
/** user argument for incoming query callback */
void *cb_arg;
/** the current time in seconds */
uint32_t now_secs;
/** the current time in microseconds */
struct timeval now_tv;
/** signal handler callback */
void (*sig_cb)(int, void*);
/** signal handler user arg */
+99 -27
View File
@@ -54,13 +54,15 @@ void usage(char* argv[])
printf("usage: %s [options] name type class ...\n", argv[0]);
printf(" sends the name-type-class queries over TCP.\n");
printf("-f server what ipaddr@portnr to send the queries to\n");
printf("-u use UDP. No retries are attempted.\n");
printf("-n do not wait for an answer.\n");
printf("-h this help text\n");
exit(1);
}
/** open TCP socket to svr */
static int
open_svr(char* svr)
open_svr(char* svr, int udp)
{
struct sockaddr_storage addr;
socklen_t addrlen;
@@ -71,13 +73,21 @@ open_svr(char* svr)
exit(1);
}
fd = socket(addr_is_ip6(&addr, addrlen)?PF_INET6:PF_INET,
SOCK_STREAM, 0);
udp?SOCK_DGRAM:SOCK_STREAM, 0);
if(fd == -1) {
#ifndef USE_WINSOCK
perror("socket() error");
#else
printf("socket: %s\n", wsa_strerror(WSAGetLastError()));
#endif
exit(1);
}
if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) {
#ifndef USE_WINSOCK
perror("connect() error");
#else
printf("connect: %s\n", wsa_strerror(WSAGetLastError()));
#endif
exit(1);
}
return fd;
@@ -85,7 +95,7 @@ open_svr(char* svr)
/** write a query over the TCP fd */
static void
write_q(int fd, ldns_buffer* buf, int id,
write_q(int fd, int udp, ldns_buffer* buf, int id,
char* strname, char* strtype, char* strclass)
{
struct query_info qinfo;
@@ -113,15 +123,26 @@ write_q(int fd, ldns_buffer* buf, int id,
ldns_buffer_write_u16_at(buf, 2, BIT_RD);
/* send it */
len = (uint16_t)ldns_buffer_limit(buf);
len = htons(len);
if(write(fd, &len, sizeof(len)) < (ssize_t)sizeof(len)) {
perror("write() len failed");
exit(1);
if(!udp) {
len = (uint16_t)ldns_buffer_limit(buf);
len = htons(len);
if(send(fd, (void*)&len, sizeof(len), 0)<(ssize_t)sizeof(len)){
#ifndef USE_WINSOCK
perror("send() len failed");
#else
printf("send len: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
}
}
if(write(fd, ldns_buffer_begin(buf), ldns_buffer_limit(buf)) <
if(send(fd, ldns_buffer_begin(buf), ldns_buffer_limit(buf), 0) <
(ssize_t)ldns_buffer_limit(buf)) {
perror("write() data failed");
#ifndef USE_WINSOCK
perror("send() data failed");
#else
printf("send data: %s\n", wsa_strerror(WSAGetLastError()));
#endif
exit(1);
}
@@ -130,21 +151,48 @@ write_q(int fd, ldns_buffer* buf, int id,
/** receive DNS datagram over TCP and print it */
static void
recv_one(int fd, ldns_buffer* buf)
recv_one(int fd, int udp, ldns_buffer* buf)
{
uint16_t len;
ldns_pkt* pkt;
ldns_status status;
if(read(fd, &len, sizeof(len)) < (ssize_t)sizeof(len)) {
perror("read() len failed");
exit(1);
}
len = ntohs(len);
ldns_buffer_clear(buf);
ldns_buffer_set_limit(buf, len);
if(read(fd, ldns_buffer_begin(buf), len) < (ssize_t)len) {
perror("read() data failed");
exit(1);
if(!udp) {
if(recv(fd, (void*)&len, sizeof(len), 0)<(ssize_t)sizeof(len)){
#ifndef USE_WINSOCK
perror("read() len failed");
#else
printf("read len: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
}
len = ntohs(len);
ldns_buffer_clear(buf);
ldns_buffer_set_limit(buf, len);
if(recv(fd, ldns_buffer_begin(buf), len, 0) < (ssize_t)len) {
#ifndef USE_WINSOCK
perror("read() data failed");
#else
printf("read data: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
}
} else {
ssize_t l;
ldns_buffer_clear(buf);
if((l=recv(fd, ldns_buffer_begin(buf),
ldns_buffer_capacity(buf), 0)) < 0) {
#ifndef USE_WINSOCK
perror("read() data failed");
#else
printf("read data: %s\n",
wsa_strerror(WSAGetLastError()));
#endif
exit(1);
}
ldns_buffer_set_limit(buf, (size_t)l);
len = (size_t)l;
}
printf("\nnext received packet\n");
log_buf(0, "data", buf);
@@ -162,17 +210,18 @@ recv_one(int fd, ldns_buffer* buf)
/** send the TCP queries and print answers */
static void
send_em(char* svr, int num, char** qs)
send_em(char* svr, int udp, int noanswer, int num, char** qs)
{
ldns_buffer* buf = ldns_buffer_new(65553);
int fd = open_svr(svr);
int fd = open_svr(svr, udp);
int i;
if(!buf) fatal_exit("out of memory");
for(i=0; i<num; i+=3) {
printf("\nNext query is %s %s %s\n", qs[i], qs[i+1], qs[i+2]);
write_q(fd, buf, i, qs[i], qs[i+1], qs[i+2]);
write_q(fd, udp, buf, i, qs[i], qs[i+1], qs[i+2]);
/* print at least one result */
recv_one(fd, buf);
if(!noanswer)
recv_one(fd, udp, buf);
}
close(fd);
@@ -180,6 +229,7 @@ send_em(char* svr, int num, char** qs)
printf("orderly exit\n");
}
#ifdef SIGPIPE
/** SIGPIPE handler */
static RETSIGTYPE sigh(int sig)
{
@@ -190,6 +240,7 @@ static RETSIGTYPE sigh(int sig)
printf("Got unhandled signal %d\n", sig);
exit(1);
}
#endif /* SIGPIPE */
/** getopt global, in case header files fail to declare it. */
extern int optind;
@@ -201,25 +252,43 @@ int main(int argc, char** argv)
{
int c;
char* svr = "127.0.0.1";
int udp = 0;
int noanswer = 0;
#ifdef USE_WINSOCK
WSADATA wsa_data;
if(WSAStartup(MAKEWORD(2,2), &wsa_data) != 0) {
printf("WSAStartup failed\n");
return 1;
}
#endif
/* lock debug start (if any) */
log_init(0, 0, 0);
checklock_start();
#ifdef SIGPIPE
if(signal(SIGPIPE, &sigh) == SIG_ERR) {
perror("could not install signal handler");
return 1;
}
#endif
/* command line options */
if(argc == 1) {
usage(argv);
}
while( (c=getopt(argc, argv, "f:h")) != -1) {
while( (c=getopt(argc, argv, "f:hnu")) != -1) {
switch(c) {
case 'f':
svr = optarg;
break;
case 'n':
noanswer = 1;
break;
case 'u':
udp = 1;
break;
case 'h':
case '?':
default:
@@ -233,7 +302,10 @@ int main(int argc, char** argv)
printf("queries must be multiples of name,type,class\n");
return 1;
}
send_em(svr, argc, argv);
send_em(svr, udp, noanswer, argc, argv);
checklock_stop();
#ifdef USE_WINSOCK
WSACleanup();
#endif
return 0;
}
+6 -1
View File
@@ -127,8 +127,13 @@ setup_config(FILE* in, char* configfile, int* lineno,
char line[MAX_LINE_LEN];
char* parse;
FILE* cfg;
#ifdef USE_WINSOCK
snprintf(configfile, MAX_LINE_LEN, "testbound_cfg_%u.tmp",
(unsigned)getpid());
#else
snprintf(configfile, MAX_LINE_LEN, "/tmp/testbound_cfg_%u.tmp",
(unsigned)getpid());
#endif
add_opts("-c", pass_argc, pass_argv);
add_opts(configfile, pass_argc, pass_argv);
cfg = fopen(configfile, "w");
@@ -172,7 +177,7 @@ setup_playback(const char* filename, char* configfile,
int lineno = 0;
if(filename) {
FILE *in = fopen(filename, "r");
FILE *in = fopen(filename, "rb");
if(!in) {
perror(filename);
exit(1);
+26 -5
View File
@@ -314,11 +314,12 @@ infra_test()
size_t zonelen = 13;
struct infra_cache* slab;
struct config_file* cfg = config_create();
time_t now = 0;
uint32_t now = 0;
int vs, to;
struct infra_host_key* k;
struct infra_host_data* d;
int init = 376;
int dlame, alame, olame;
slab = infra_create(cfg);
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
@@ -343,15 +344,30 @@ infra_test()
unit_assert( vs == 0 && to == init );
unit_assert( infra_set_lame(slab, (struct sockaddr_storage*)&one,
(socklen_t)sizeof(int), zone, zonelen, now, 0) );
(socklen_t)sizeof(int), zone, zonelen, now, 0,
LDNS_RR_TYPE_A) );
unit_assert( (d=infra_lookup_host(slab, (struct sockaddr_storage*)&one,
(socklen_t)sizeof(int), 0, now, &k)) );
unit_assert( d->ttl == now+cfg->host_ttl );
unit_assert( d->edns_version == 0 );
unit_assert( infra_lookup_lame(d, zone, zonelen, now)==1 );
unit_assert( infra_lookup_lame(d, zone, zonelen, now,
&dlame, &alame, &olame) );
unit_assert(!dlame && alame && !olame);
unit_assert( !infra_lookup_lame(d, zone, zonelen,
now+cfg->lame_ttl+10) );
unit_assert( !infra_lookup_lame(d, (uint8_t*)"\000", 1, now) );
now+cfg->lame_ttl+10, &dlame, &alame, &olame) );
unit_assert( !infra_lookup_lame(d, (uint8_t*)"\000", 1, now,
&dlame, &alame, &olame) );
lock_rw_unlock(&k->entry.lock);
/* test merge of data */
unit_assert( infra_set_lame(slab, (struct sockaddr_storage*)&one,
(socklen_t)sizeof(int), zone, zonelen, now, 0,
LDNS_RR_TYPE_AAAA) );
unit_assert( (d=infra_lookup_host(slab, (struct sockaddr_storage*)&one,
(socklen_t)sizeof(int), 0, now, &k)) );
unit_assert( infra_lookup_lame(d, zone, zonelen, now,
&dlame, &alame, &olame) );
unit_assert(!dlame && alame && olame);
lock_rw_unlock(&k->entry.lock);
infra_delete(slab);
@@ -394,6 +410,7 @@ main(int argc, char* argv[])
return 1;
}
printf("Start of %s unit test.\n", PACKAGE_STRING);
ERR_load_crypto_strings();
checklock_start();
rnd_test();
verify_test();
@@ -409,5 +426,9 @@ main(int argc, char* argv[])
msgparse_test();
checklock_stop();
printf("%d checks ok.\n", testcount);
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
ERR_remove_state(0);
ERR_free_strings();
return 0;
}
+76
View File
@@ -247,6 +247,76 @@ checkformerr(ldns_buffer* pkt)
unit_assert(status != LDNS_STATUS_OK);
}
/** performance test message encoding */
static void
perf_encode(struct query_info* qi, struct reply_info* rep, uint16_t id,
uint16_t flags, ldns_buffer* out, uint32_t timenow,
struct edns_data* edns)
{
static int num = 0;
int ret;
size_t max = 10000;
size_t i;
struct timeval start, end;
double dt;
struct regional* r2 = regional_create();
if(gettimeofday(&start, NULL) < 0)
fatal_exit("gettimeofday: %s", strerror(errno));
/* encode a couple times */
for(i=0; i<max; i++) {
ret = reply_info_encode(qi, rep, id, flags, out, timenow,
r2, 65535, (int)(edns->bits & EDNS_DO) );
unit_assert(ret != 0); /* udp packets should fit */
attach_edns_record(out, edns);
regional_free_all(r2);
}
if(gettimeofday(&end, NULL) < 0)
fatal_exit("gettimeofday: %s", strerror(errno));
/* time in millisec */
dt = (double)(end.tv_sec - start.tv_sec)*1000. +
((double)end.tv_usec - (double)start.tv_usec)/1000.;
printf("[%d] did %u in %g msec for %f encode/sec size %d\n", num++,
(unsigned)max, dt, (double)max / (dt/1000.),
(int)ldns_buffer_limit(out));
regional_destroy(r2);
}
/** perf test a packet */
static void
perftestpkt(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out,
const char* hex)
{
struct query_info qi;
struct reply_info* rep = 0;
int ret;
uint16_t id;
uint16_t flags;
uint32_t timenow = 0;
struct regional* region = regional_create();
struct edns_data edns;
hex_to_buf(pkt, hex);
memmove(&id, ldns_buffer_begin(pkt), sizeof(id));
if(ldns_buffer_limit(pkt) < 2)
flags = 0;
else memmove(&flags, ldns_buffer_at(pkt, 2), sizeof(flags));
flags = ntohs(flags);
ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns);
if(ret != 0) {
if(vbmp) printf("parse code %d: %s\n", ret,
ldns_lookup_by_id(ldns_rcodes, ret)->name);
if(ret == LDNS_RCODE_FORMERR)
checkformerr(pkt);
unit_assert(ret != LDNS_RCODE_SERVFAIL);
} else {
perf_encode(&qi, rep, id, flags, out, timenow, &edns);
}
query_info_clear(&qi);
reply_info_parsedelete(rep, alloc);
regional_destroy(region);
}
/** test a packet */
static void
testpkt(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out,
@@ -359,6 +429,12 @@ simpletest(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out)
" 00 01 00 01 00 02 64 b9 00 04 c6 29 00 04 01 4a 0c 52 4f 4f ; 441- 460\n"
" 54 2d 53 45 52 56 45 52 53 03 4e 45 54 00 00 01 00 01 00 02 ; 461- 480\n"
" 64 b9 00 04 c0 3a 80 1e ");
/* root delegation from unbound trace with new AAAA glue */
perftestpkt(pkt, alloc, out,
"55BC84000001000D00000014000002000100000200010007E900001401610C726F6F742D73657276657273036E65740000000200010007E90000040162C01E00000200010007E90000040163C01E00000200010007E90000040164C01E00000200010007E90000040165C01E00000200010007E90000040166C01E00000200010007E90000040167C01E00000200010007E90000040168C01E00000200010007E90000040169C01E00000200010007E9000004016AC01E00000200010007E9000004016BC01E00000200010007E9000004016CC01E00000200010007E9000004016DC01EC01C000100010007E9000004C6290004C03B000100010007E9000004C0E44FC9C04A000100010007E9000004C021040CC059000100010007E900000480080A5AC068000100010007E9000004C0CBE60AC077000100010007E9000004C00505F1C086000100010007E9000004C0702404C095000100010007E9000004803F0235C0A4000100010007E9000004C0249411C0B3000100010007E9000004C03A801EC0C2000100010007E9000004C1000E81C0D1000100010007E9000004C707532AC0E0000100010007E9000004CA0C1B21C01C001C00010007E900001020010503BA3E00000000000000020030C077001C00010007E900001020010500002F0000000000000000000FC095001C00010007E90000102001050000010000"
"00000000803F0235C0B3001C00010007E9000010200105030C2700000000000000020030C0C2001C00010007E9000010200107FD000000000000000000000001C0E0001C00010007E900001020010DC30000000000000000000000350000291000000000000000"
);
}
/** simple test of parsing, pcat file */
+9
View File
@@ -263,6 +263,7 @@ verifytest_file(const char* fname, const char* at_date)
struct entry* list = read_datafile(fname);
struct module_env env;
struct val_env ve;
uint32_t now = time(NULL);
if(!list)
fatal_exit("could not read %s: %s", fname, strerror(errno));
@@ -271,6 +272,7 @@ verifytest_file(const char* fname, const char* at_date)
memset(&ve, 0, sizeof(ve));
env.scratch = region;
env.scratch_buffer = buf;
env.now = &now;
ve.date_override = cfg_convert_timeval(at_date);
unit_assert(region && buf);
dnskey = extract_keys(list, &alloc, region, buf);
@@ -459,6 +461,13 @@ verify_test()
{
printf("verify test\n");
verifytest_file("testdata/test_signatures.1", "20070818005004");
verifytest_file("testdata/test_signatures.2", "20080414005004");
verifytest_file("testdata/test_signatures.3", "20080416005004");
verifytest_file("testdata/test_signatures.4", "20080416005004");
verifytest_file("testdata/test_signatures.5", "20080416005004");
verifytest_file("testdata/test_signatures.6", "20080416005004");
verifytest_file("testdata/test_signatures.7", "20070829144150");
verifytest_file("testdata/test_signatures.8", "20070829144150");
dstest_file("testdata/test_ds_sig.1");
nsectest();
nsec3_hash_test("testdata/test_nsec3_hash.1");
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More