Compare commits

...
Author SHA1 Message Date
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
Wouter Wijngaards 04edbb68b7 do multiple queries over TCP.
git-svn-id: file:///svn/unbound/trunk@935 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-08 10:59:18 +00:00
Wouter Wijngaards 2884751446 and log entry for the portability fix.
git-svn-id: file:///svn/unbound/trunk@934 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-07 15:35:04 +00:00
Wouter Wijngaards c8982075c5 unsigned cast for prints.
git-svn-id: file:///svn/unbound/trunk@933 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-07 14:55:27 +00:00
Wouter Wijngaards 0c8d24b653 Fixes.
git-svn-id: file:///svn/unbound/trunk@932 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-07 14:13:03 +00:00
Wouter Wijngaards d2b3e464ac Fixup for solaris and libevent brokenness.
git-svn-id: file:///svn/unbound/trunk@931 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-07 14:09:24 +00:00
Wouter Wijngaards f3525b2081 log level 2.
git-svn-id: file:///svn/unbound/trunk@930 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-07 11:04:56 +00:00
Wouter Wijngaards 849026931b move around debug levels.
git-svn-id: file:///svn/unbound/trunk@929 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-07 09:46:49 +00:00
Wouter Wijngaards da073cfc3e fallback EDNS on NOTIMPL.
git-svn-id: file:///svn/unbound/trunk@928 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-06 15:08:38 +00:00
Wouter Wijngaards caaad8b810 TODO fixups.
Memory free is needed for HUP handling anyway.
interface separation already implemented.
better idea about nearmiss handling.


git-svn-id: file:///svn/unbound/trunk@927 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-06 15:00:59 +00:00
Wouter Wijngaards 0fe0251c8d Low pop statistics are not good.
git-svn-id: file:///svn/unbound/trunk@926 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-06 13:34:59 +00:00
Wouter Wijngaards 9be27227a1 rename files.
git-svn-id: file:///svn/unbound/trunk@925 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-06 13:18:24 +00:00
Wouter Wijngaards a9a47f8b41 result_free to resolve_free (thanks Benno).
git-svn-id: file:///svn/unbound/trunk@924 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-06 13:10:40 +00:00
Wouter Wijngaards 46f7dc4d08 nicer printout.
git-svn-id: file:///svn/unbound/trunk@923 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-06 10:13:26 +00:00
Wouter Wijngaards 0e5b4105d1 Fix for nothreading.
git-svn-id: file:///svn/unbound/trunk@922 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-06 10:09:54 +00:00
Wouter Wijngaards 9b31997a4c Clearer explanation how to get solaris threads.
git-svn-id: file:///svn/unbound/trunk@921 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-06 10:03:55 +00:00
Wouter Wijngaards 98552115d0 fixup typos
git-svn-id: file:///svn/unbound/trunk@920 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-05 15:22:10 +00:00
Wouter Wijngaards d58327876f Make parallel builds fixup.
git-svn-id: file:///svn/unbound/trunk@919 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-05 14:45:19 +00:00
Wouter Wijngaards 8b048a8229 Statistics test.
git-svn-id: file:///svn/unbound/trunk@918 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-05 13:53:05 +00:00
Wouter Wijngaards 967793aad3 statistics-interval config setting.
git-svn-id: file:///svn/unbound/trunk@917 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-05 10:23:44 +00:00
Wouter Wijngaards 6ffe218762 Fix for libevent 1.2 versions.
git-svn-id: file:///svn/unbound/trunk@916 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-01 12:53:02 +00:00
Wouter Wijngaards da8ae735ce Fixup getmem.
git-svn-id: file:///svn/unbound/trunk@915 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-31 15:09:24 +00:00
Wouter Wijngaards 8cdb815df6 ordering for alloc checks.
git-svn-id: file:///svn/unbound/trunk@914 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-31 14:45:10 +00:00
Wouter Wijngaards e48ecb0e15 nonblock bg pipes.
git-svn-id: file:///svn/unbound/trunk@913 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-31 10:40:58 +00:00
Wouter Wijngaards 635c65f4ed remove DEBUG
git-svn-id: file:///svn/unbound/trunk@912 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-30 16:35:34 +00:00
Wouter Wijngaards 2b4ef794b9 logging nicer, removal of reply_iov.
git-svn-id: file:///svn/unbound/trunk@911 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-30 14:46:01 +00:00
Wouter Wijngaards 0e1b3fb3e0 chroot checks for roothints and anchor files.
git-svn-id: file:///svn/unbound/trunk@910 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-30 11:21:20 +00:00
Wouter Wijngaards be483a3bfb libevent compatibility.
git-svn-id: file:///svn/unbound/trunk@909 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-28 15:57:27 +00:00
Wouter Wijngaards 6ef599255d protect config access. fix test.
git-svn-id: file:///svn/unbound/trunk@908 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-28 14:45:20 +00:00
Wouter Wijngaards c8f2bf0333 fixes for random number badness (lack of entropy and SIGFPE from RAND_cleanup
too early).


git-svn-id: file:///svn/unbound/trunk@907 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-28 14:34:53 +00:00
Wouter Wijngaards e5196b25ae more locks.
git-svn-id: file:///svn/unbound/trunk@906 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-28 13:42:55 +00:00
Wouter Wijngaards 193892e52d Two small fixes.
git-svn-id: file:///svn/unbound/trunk@905 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-28 09:31:29 +00:00
Wouter Wijngaards a6c543362d smaller fixes.
git-svn-id: file:///svn/unbound/trunk@904 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-25 16:17:36 +00:00
Wouter Wijngaards 32396dc677 more fixes, more tests.
git-svn-id: file:///svn/unbound/trunk@903 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-25 15:45:54 +00:00
Wouter Wijngaards ed57c4de4c - fixup race problems from opensll in rand init from library, with
a mutex around the rand init.
       - fix pass async_id=NULL to _async resolve().
       - rewrote _wait() routine, so that it is threadsafe.
       - cancelation is threadsafe.


git-svn-id: file:///svn/unbound/trunk@902 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-25 15:13:39 +00:00
Wouter Wijngaards bfe329e34d credits for testing.
git-svn-id: file:///svn/unbound/trunk@901 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-25 11:20:54 +00:00
Wouter Wijngaards 9e30587b1e refactor asynclook.
git-svn-id: file:///svn/unbound/trunk@900 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-25 11:17:48 +00:00
Wouter Wijngaards cf9837bf7f asynclook blocking mode.
git-svn-id: file:///svn/unbound/trunk@899 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-25 10:49:58 +00:00
Wouter Wijngaards 0bdfbccbdc please doxygen.
git-svn-id: file:///svn/unbound/trunk@898 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-25 10:41:17 +00:00
Wouter Wijngaards 3bb9aaafca Fixup race.
git-svn-id: file:///svn/unbound/trunk@897 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-25 10:23:57 +00:00
Wouter Wijngaards 7bfaf07981 test for async.
git-svn-id: file:///svn/unbound/trunk@896 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-25 09:53:04 +00:00
Wouter Wijngaards 2e28288b1d forwarder mode options for library.
git-svn-id: file:///svn/unbound/trunk@895 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-24 14:58:51 +00:00
Wouter Wijngaards 452b7cc069 Makefile fix.
git-svn-id: file:///svn/unbound/trunk@894 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-24 11:06:10 +00:00
Wouter Wijngaards 4d194ac2fa fwd_ancil needs ldns-testns.
git-svn-id: file:///svn/unbound/trunk@893 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-24 11:05:24 +00:00
Wouter Wijngaards f041511951 caution when retry, not excessively.
git-svn-id: file:///svn/unbound/trunk@892 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-24 10:53:40 +00:00
Wouter Wijngaards 0e4bda4c55 cancel().
git-svn-id: file:///svn/unbound/trunk@891 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-24 09:14:07 +00:00
Wouter Wijngaards e56a3a60ef bg resolution works.
git-svn-id: file:///svn/unbound/trunk@890 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-23 15:15:37 +00:00
Wouter Wijngaards faa7ad14c6 no more debug prints for auto ifs.
git-svn-id: file:///svn/unbound/trunk@889 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-23 08:49:57 +00:00
Wouter Wijngaards c87fe76e47 OPT.
git-svn-id: file:///svn/unbound/trunk@888 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-23 07:54:43 +00:00
Wouter Wijngaards a18af6d1e1 test program for bg lookups.
git-svn-id: file:///svn/unbound/trunk@887 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-22 16:28:41 +00:00
Wouter Wijngaards 3adebc8721 bg query and result code.
git-svn-id: file:///svn/unbound/trunk@886 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-22 14:17:44 +00:00
Wouter Wijngaards 1a4fadaf00 fix quit on timeout, and printing trailing dots.
git-svn-id: file:///svn/unbound/trunk@885 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-22 12:01:13 +00:00
Wouter Wijngaards b26f289ccc fix link testbound.
git-svn-id: file:///svn/unbound/trunk@884 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-22 11:28:07 +00:00
Wouter Wijngaards 0e000a8587 unbound.c pipe code.
git-svn-id: file:///svn/unbound/trunk@883 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-22 11:10:49 +00:00
Wouter Wijngaards 84ae5c8e79 Only causes either a spurious log_err or a spuriously dropped TCP DNS
transfer. 


git-svn-id: file:///svn/unbound/trunk@882 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-21 16:07:42 +00:00
Wouter Wijngaards 05f9d35f00 serialize, deserialize, raw commpoints.
case preserve note.


git-svn-id: file:///svn/unbound/trunk@881 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-21 16:03:59 +00:00
Wouter Wijngaards c7ad292438 unbound lib work.
git-svn-id: file:///svn/unbound/trunk@880 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-18 13:52:22 +00:00
Wouter Wijngaards b63db13e72 makedist fixup
git-svn-id: file:///svn/unbound/trunk@879 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-18 11:01:00 +00:00
Wouter Wijngaards 6ee18c6824 update ldns-testpkts.
git-svn-id: file:///svn/unbound/trunk@878 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-18 10:57:52 +00:00
Wouter Wijngaards e8f4ac9b1a Fix for Solaris 9.
git-svn-id: file:///svn/unbound/trunk@877 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-18 09:50:59 +00:00
Wouter Wijngaards 5e420a8275 manpage fixup, no more 6to4 mapping.
git-svn-id: file:///svn/unbound/trunk@876 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-18 09:18:12 +00:00
Wouter Wijngaards bb3a1178b6 BSD fix for ip4.
git-svn-id: file:///svn/unbound/trunk@875 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-18 09:09:55 +00:00
Wouter Wijngaards 306db56f1f support for IP_RECVDSTADDR.
git-svn-id: file:///svn/unbound/trunk@874 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-18 08:51:19 +00:00
Wouter Wijngaards 95b0a129e2 manual and pktinfo.
git-svn-id: file:///svn/unbound/trunk@873 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-17 15:35:34 +00:00
Wouter Wijngaards c4e1a83be5 TODO update.
git-svn-id: file:///svn/unbound/trunk@872 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-17 09:19:34 +00:00
Wouter Wijngaards fec9e1d262 if auto fix more.
git-svn-id: file:///svn/unbound/trunk@871 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-17 08:40:08 +00:00
Wouter Wijngaards c854c57c6f please doxygen.
git-svn-id: file:///svn/unbound/trunk@870 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-17 08:26:15 +00:00
Wouter Wijngaards ee6e142192 configure fixes.
git-svn-id: file:///svn/unbound/trunk@869 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-17 08:17:24 +00:00
Wouter Wijngaards ac74d176cc fix for localhost queries in automatic interface mode.
git-svn-id: file:///svn/unbound/trunk@868 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-16 12:47:44 +00:00
Wouter Wijngaards 8343901c0f TODO item for RFC compliance.
git-svn-id: file:///svn/unbound/trunk@867 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-16 09:32:28 +00:00
Wouter Wijngaards b7745a2e53 TC bit is formerr.
git-svn-id: file:///svn/unbound/trunk@866 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-16 08:53:56 +00:00
Wouter Wijngaards 82cab3f855 makedist fixup.
git-svn-id: file:///svn/unbound/trunk@865 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 15:47:16 +00:00
Wouter Wijngaards 6ce08cf242 fix for MacOS/X.
git-svn-id: file:///svn/unbound/trunk@864 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 15:13:40 +00:00
Wouter Wijngaards 877038b6d9 fix for solaris 10.
git-svn-id: file:///svn/unbound/trunk@863 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 14:53:32 +00:00
Wouter Wijngaards a2227517ed no problem with sysctl.
git-svn-id: file:///svn/unbound/trunk@862 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 14:20:13 +00:00
Wouter Wijngaards 04a896098e ancil test working on *BSD.
git-svn-id: file:///svn/unbound/trunk@861 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 14:11:47 +00:00
Wouter Wijngaards 7e84653485 better v6only disable code.
git-svn-id: file:///svn/unbound/trunk@860 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 14:07:49 +00:00
Wouter Wijngaards 71723c6276 fixup for -levent.
git-svn-id: file:///svn/unbound/trunk@859 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 13:19:59 +00:00
Wouter Wijngaards 219d0c70dd Remove warnings on Solaris 9.
git-svn-id: file:///svn/unbound/trunk@858 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 13:10:21 +00:00
Wouter Wijngaards 85c88707ca configure fixes.
git-svn-id: file:///svn/unbound/trunk@857 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 13:04:27 +00:00
Wouter Wijngaards e7d64c7eac fixy.
git-svn-id: file:///svn/unbound/trunk@856 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 12:58:17 +00:00
Wouter Wijngaards d7d8e117ef set ldflags during levent test.
git-svn-id: file:///svn/unbound/trunk@855 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 12:54:11 +00:00
Wouter Wijngaards d9e9a31562 regen configure.
git-svn-id: file:///svn/unbound/trunk@854 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 12:48:24 +00:00
Wouter Wijngaards 5d594b301f extra define for solaris ancillary data.
git-svn-id: file:///svn/unbound/trunk@853 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 12:47:44 +00:00
Wouter Wijngaards 648a776493 late flags.
git-svn-id: file:///svn/unbound/trunk@852 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 12:45:53 +00:00
Wouter Wijngaards 8404701a09 fixup test for BSD.
git-svn-id: file:///svn/unbound/trunk@851 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 11:54:15 +00:00
Wouter Wijngaards 4b065a443c nicer error msgs.
git-svn-id: file:///svn/unbound/trunk@850 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 10:39:32 +00:00
Wouter Wijngaards 0b04728785 lint more.
git-svn-id: file:///svn/unbound/trunk@849 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 10:18:36 +00:00
Wouter Wijngaards 76a31aacd3 test for ancillary data and fixes for lint and doxygen.
git-svn-id: file:///svn/unbound/trunk@848 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 10:10:22 +00:00
Wouter Wijngaards 179273a13a interface-automatic (IP6mapped, good for anycast service and so on).
git-svn-id: file:///svn/unbound/trunk@847 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-15 09:45:30 +00:00
Wouter Wijngaards 7f8b84d0e5 lint, optimize fix.
git-svn-id: file:///svn/unbound/trunk@846 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-14 10:21:09 +00:00
Wouter Wijngaards 2b08436c4c - in no debug sets NDEBUG to remove asserts.
- configure --enable-debug is needed for dependency generation
         for assertions and for compiler warnings.
       - ldns.tgz updated with ldns-trunk (where buffer.h is updated).


git-svn-id: file:///svn/unbound/trunk@845 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-14 09:51:20 +00:00
Wouter Wijngaards 5cc518f114 inverse.
git-svn-id: file:///svn/unbound/trunk@844 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-11 13:49:59 +00:00
Wouter Wijngaards 1315edc5e9 Nicer sizes possible in config file.
git-svn-id: file:///svn/unbound/trunk@843 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-11 13:20:22 +00:00
Wouter Wijngaards 97f5d3d28e more checks by checkconf.
git-svn-id: file:///svn/unbound/trunk@842 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-11 11:24:30 +00:00
Wouter Wijngaards ad78119e19 stubzone text.
git-svn-id: file:///svn/unbound/trunk@841 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-11 10:18:48 +00:00
Wouter Wijngaards 2756924a44 remove man page nroff warning.
git-svn-id: file:///svn/unbound/trunk@840 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-11 09:03:56 +00:00
Wouter Wijngaards 3fd809d537 TODO
git-svn-id: file:///svn/unbound/trunk@839 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-10 16:24:07 +00:00
Wouter Wijngaards 22b8057cca man page fixes for Solaris.
git-svn-id: file:///svn/unbound/trunk@838 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-10 15:46:55 +00:00
Wouter Wijngaards fe6f28ddc5 libevent .lo file linking.
git-svn-id: file:///svn/unbound/trunk@837 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-10 14:00:07 +00:00
Wouter Wijngaards 1e4dc049eb doc fix.
git-svn-id: file:///svn/unbound/trunk@836 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-10 13:40:12 +00:00
Wouter Wijngaards 1a4d24816b more portable libtool linking of included ldns package.
git-svn-id: file:///svn/unbound/trunk@835 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-10 11:47:07 +00:00
Wouter Wijngaards 1f47306af9 typo.
git-svn-id: file:///svn/unbound/trunk@834 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-10 09:25:14 +00:00
Wouter Wijngaards f1a3c9b646 quartile prints.
git-svn-id: file:///svn/unbound/trunk@833 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-10 09:02:18 +00:00
Wouter Wijngaards a67e62dd40 seeding bigger to make openssl happy.
git-svn-id: file:///svn/unbound/trunk@831 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-09 12:48:03 +00:00
Wouter Wijngaards 1b6d254224 warning about entropy.
git-svn-id: file:///svn/unbound/trunk@828 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-09 12:04:20 +00:00
Wouter Wijngaards a0e442eb32 rng fixup (trunk).
git-svn-id: file:///svn/unbound/trunk@827 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-09 10:55:37 +00:00
Wouter Wijngaards 7eaceaab2f text.
git-svn-id: file:///svn/unbound/trunk@825 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-04 18:00:45 +00:00
Wouter Wijngaards 2ba3ff9f7d document misconfiguration.
git-svn-id: file:///svn/unbound/trunk@824 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-04 13:13:50 +00:00
Wouter Wijngaards e7cb0f27cc refused stops retries.
git-svn-id: file:///svn/unbound/trunk@823 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-02 13:48:19 +00:00
Wouter Wijngaards 317938efba typo.
git-svn-id: file:///svn/unbound/trunk@822 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-01-02 13:24:35 +00:00
Wouter Wijngaards d6ce1f426d small fries.
git-svn-id: file:///svn/unbound/trunk@821 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-07 14:54:10 +00:00
Wouter Wijngaards 9f97c4ac44 fix bogus flag.
git-svn-id: file:///svn/unbound/trunk@820 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-07 14:25:18 +00:00
Wouter Wijngaards 6a5f5e652a lint.
git-svn-id: file:///svn/unbound/trunk@819 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-07 14:09:25 +00:00
Wouter Wijngaards 61b42edaef portability of header file.
git-svn-id: file:///svn/unbound/trunk@818 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-07 14:07:38 +00:00
Wouter Wijngaards 060d4740c2 ldns update.
git-svn-id: file:///svn/unbound/trunk@817 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-07 12:12:51 +00:00
Wouter Wijngaards 5a198e0b4c small improvements.
git-svn-id: file:///svn/unbound/trunk@816 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-07 11:01:04 +00:00
Wouter Wijngaards abf85e9270 cname handling improved.
git-svn-id: file:///svn/unbound/trunk@815 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-07 10:43:10 +00:00
Wouter Wijngaards ab4b9aa250 manpage for unbound-host.
git-svn-id: file:///svn/unbound/trunk@814 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-07 09:03:29 +00:00
Wouter Wijngaards a2f143cfcc debug option.
git-svn-id: file:///svn/unbound/trunk@813 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-07 08:29:09 +00:00
Wouter Wijngaards e297886386 abort gone
git-svn-id: file:///svn/unbound/trunk@812 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-06 17:38:15 +00:00
Wouter Wijngaards cdf334528f unbound-host shows security info.
git-svn-id: file:///svn/unbound/trunk@811 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-06 17:05:21 +00:00
Wouter Wijngaards 1f9ad9e66e unbound-host works.
git-svn-id: file:///svn/unbound/trunk@810 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-06 16:35:36 +00:00
Wouter Wijngaards 75073cefea library resolution working.
git-svn-id: file:///svn/unbound/trunk@809 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-06 15:11:07 +00:00
Wouter Wijngaards 9374c1465a libworker.
git-svn-id: file:///svn/unbound/trunk@808 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-05 11:06:56 +00:00
Wouter Wijngaards a2311972e7 locking diff.
git-svn-id: file:///svn/unbound/trunk@807 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-05 06:41:39 +00:00
Wouter Wijngaards 11a764a82f moved unlock to please.
git-svn-id: file:///svn/unbound/trunk@806 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-04 21:53:19 +00:00
Wouter Wijngaards f187e1da7e fptrwlist and remove oldhack with islocked param.
git-svn-id: file:///svn/unbound/trunk@805 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-04 21:34:53 +00:00
Wouter Wijngaards 2dbc83d5ae markdelfunc for lock order problem in lruhash reclaim().
git-svn-id: file:///svn/unbound/trunk@804 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-04 21:18:25 +00:00
Wouter Wijngaards fcac316d63 coverity run fixes.
git-svn-id: file:///svn/unbound/trunk@803 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-04 17:54:14 +00:00
Wouter Wijngaards 43a2640a9c libunbound work.
git-svn-id: file:///svn/unbound/trunk@802 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-04 16:14:09 +00:00
Wouter Wijngaards 8892d4b63c makefile nit and modstack.
git-svn-id: file:///svn/unbound/trunk@801 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-04 13:23:41 +00:00
Wouter Wijngaards 1c33240c16 Small edits, work on design to make it work.
git-svn-id: file:///svn/unbound/trunk@800 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-03 18:45:56 +00:00
Wouter Wijngaards b97a63aa95 Link fix.
git-svn-id: file:///svn/unbound/trunk@799 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-03 18:11:42 +00:00
Wouter Wijngaards 2ef042ef0e move runtime path.
git-svn-id: file:///svn/unbound/trunk@798 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-03 17:46:18 +00:00
Wouter Wijngaards 185c6f76b1 Fix for build in subdir.
git-svn-id: file:///svn/unbound/trunk@796 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-03 17:33:12 +00:00
Wouter Wijngaards 87fe7013a0 test app, and hopefully useful tool.
git-svn-id: file:///svn/unbound/trunk@795 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-03 11:02:31 +00:00
Wouter Wijngaards 77019eeb5e - changed checkconf/ to smallapp/ to make room for more support tools.
(such as unbound-host).
       - install dirs created with -m 755 because they need to be accessible.
       - library extensive featurelist added to TODO.
       - please doxygen, lint.


git-svn-id: file:///svn/unbound/trunk@794 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-12-03 08:24:36 +00:00
Wouter Wijngaards 1152a4c5e8 don't forget to lock it.
git-svn-id: file:///svn/unbound/trunk@793 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-30 18:14:48 +00:00
Wouter Wijngaards 83f8775d5a More api work, makefile links library.
git-svn-id: file:///svn/unbound/trunk@792 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-30 14:53:57 +00:00
Wouter Wijngaards d9907b118f more.
git-svn-id: file:///svn/unbound/trunk@791 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-29 15:55:26 +00:00
Wouter Wijngaards 6ccdaf41e5 public API start.
git-svn-id: file:///svn/unbound/trunk@790 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-29 15:02:15 +00:00
Wouter Wijngaards eb4ba518f1 configure regenerated for 0.9
git-svn-id: file:///svn/unbound/trunk@789 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-28 16:10:55 +00:00
Wouter Wijngaards 6a355b37fe 0.8 tag.
git-svn-id: file:///svn/unbound/trunk@788 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-28 15:49:35 +00:00
Wouter Wijngaards e12d274954 fixup for duplication of NSECs / NSEC3s after following CNAMEs
(esp. wildcard CNAMEs and in-zone CNAMEs that then include nodata or
nxdomain proofs) where the CNAME is followed again to include more NSECs.


git-svn-id: file:///svn/unbound/trunk@787 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-28 13:41:31 +00:00
Wouter Wijngaards 9ade3e4811 nonRD fix.
git-svn-id: file:///svn/unbound/trunk@786 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-28 12:06:32 +00:00
Wouter Wijngaards 2c2eaecc6c nonRD fix.
git-svn-id: file:///svn/unbound/trunk@785 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-28 11:02:01 +00:00
Wouter Wijngaards 16906c53e6 log verbosity
git-svn-id: file:///svn/unbound/trunk@784 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-28 09:34:06 +00:00
Wouter Wijngaards b6d9b4bfcc CNAME chain marked as NXDOMAIN normalized to unbound preferred format.
git-svn-id: file:///svn/unbound/trunk@783 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-28 09:13:56 +00:00
Wouter Wijngaards 6bb12a5776 show it.
git-svn-id: file:///svn/unbound/trunk@782 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-28 08:41:41 +00:00
Wouter Wijngaards bce6c3405b nodefault test.
git-svn-id: file:///svn/unbound/trunk@781 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-28 08:26:57 +00:00
Wouter Wijngaards aa0c26ddec - tests for localdata multiple RR, and implicit zones.
- can specify TXT records for local data.



git-svn-id: file:///svn/unbound/trunk@780 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-28 08:10:45 +00:00
Wouter Wijngaards a1cbd214a5 Reduced operation sensitivity of message.
git-svn-id: file:///svn/unbound/trunk@779 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-27 16:18:09 +00:00
Wouter Wijngaards f64778a893 memory footprint improvements.
git-svn-id: file:///svn/unbound/trunk@778 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-27 15:52:41 +00:00
Wouter Wijngaards 9d3b5fa30d rfc2308 compliance.
git-svn-id: file:///svn/unbound/trunk@777 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-27 13:25:11 +00:00
Wouter Wijngaards 99590f93bd test and fixes.
git-svn-id: file:///svn/unbound/trunk@776 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-22 16:13:16 +00:00
Wouter Wijngaards b72563dcb7 local zone answers.
git-svn-id: file:///svn/unbound/trunk@775 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-22 13:48:58 +00:00
Wouter Wijngaards 6b0cf42b32 defaults.
git-svn-id: file:///svn/unbound/trunk@774 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-22 09:30:44 +00:00
Wouter Wijngaards 8df2959959 localzone internal data structures.
git-svn-id: file:///svn/unbound/trunk@773 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-21 16:19:31 +00:00
Wouter Wijngaards 1cda904545 localzon setup.
git-svn-id: file:///svn/unbound/trunk@772 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-20 16:38:41 +00:00
Wouter Wijngaards 416129dedb localzone and localdata configuration setup.
git-svn-id: file:///svn/unbound/trunk@771 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-20 14:48:33 +00:00
Wouter Wijngaards b9c417481b keep tcp address around for acl.
git-svn-id: file:///svn/unbound/trunk@770 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-19 16:31:22 +00:00
Wouter Wijngaards eda6528c14 access-control
git-svn-id: file:///svn/unbound/trunk@769 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-19 15:32:55 +00:00
Wouter Wijngaards fc8657c421 unit test for addr_in_common.
git-svn-id: file:///svn/unbound/trunk@767 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-19 13:21:30 +00:00
Wouter Wijngaards 5f50f5d2b4 unit test for addr_mask.
git-svn-id: file:///svn/unbound/trunk@766 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-19 13:02:15 +00:00
Wouter Wijngaards 31f803201d port from beta-0.7.1
git-svn-id: file:///svn/unbound/trunk@763 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-19 11:04:05 +00:00
Wouter Wijngaards ff975871ab fixup leaking unbound daemons.
git-svn-id: file:///svn/unbound/trunk@755 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-19 09:06:56 +00:00
Wouter Wijngaards 99a9914605 No downcasing for NSEC and RRSIG
git-svn-id: file:///svn/unbound/trunk@754 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-19 08:55:19 +00:00
Wouter Wijngaards 435fbd1794 acl list setup. 8 to tab in net_help.
git-svn-id: file:///svn/unbound/trunk@753 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-16 16:25:37 +00:00
Wouter Wijngaards fe09abe4e6 0.8 in trunk for auth features development.
git-svn-id: file:///svn/unbound/trunk@752 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-16 13:03:04 +00:00
Wouter Wijngaards e900e44f9f todo item is not needed at this time.
git-svn-id: file:///svn/unbound/trunk@750 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-16 12:53:57 +00:00
Wouter Wijngaards bfbac6bb36 Jakob in Credits.
git-svn-id: file:///svn/unbound/trunk@749 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-15 15:42:10 +00:00
Wouter Wijngaards cc21a1ca9a review fixups.
git-svn-id: file:///svn/unbound/trunk@748 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-15 14:27:47 +00:00
Wouter Wijngaards 919b1ab1b6 authority choices.
git-svn-id: file:///svn/unbound/trunk@747 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-14 15:07:54 +00:00
Wouter Wijngaards ad69492495 to 0.7
git-svn-id: file:///svn/unbound/trunk@745 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-14 13:38:13 +00:00
Wouter Wijngaards 2b2cfd7e4b fixup test for new default.
git-svn-id: file:///svn/unbound/trunk@744 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-14 09:51:22 +00:00
Wouter Wijngaards 84a3dbe660 testbed update.
git-svn-id: file:///svn/unbound/trunk@743 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-14 09:03:51 +00:00
Wouter Wijngaards d7b0d86b09 libevent signal problem has different signal handler registrations, and thus
needs handling in testbound, so that on a good exit, it does the exit.


git-svn-id: file:///svn/unbound/trunk@742 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-13 16:15:04 +00:00
Wouter Wijngaards bce5467f59 remove debug print.
git-svn-id: file:///svn/unbound/trunk@741 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-13 15:53:25 +00:00
Wouter Wijngaards a6ae1d6194 - bugreports to unbound-bugs@nlnetlabs.nl
- fixup testbound so it exits cleanly.
       - cleanup the caches on a reload, so that rrsetID numbers won't clash.


git-svn-id: file:///svn/unbound/trunk@740 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-12 13:58:34 +00:00
Wouter Wijngaards 0ee5532396 Fixup for signal handling. No more dangling unbound processes after
test suite.


git-svn-id: file:///svn/unbound/trunk@739 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-12 11:10:11 +00:00
Wouter Wijngaards 7c5182d3fd review.
git-svn-id: file:///svn/unbound/trunk@738 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-09 22:54:54 +00:00
Wouter Wijngaards d41f40b028 safer default interfaces.
git-svn-id: file:///svn/unbound/trunk@737 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-09 14:15:21 +00:00
Wouter Wijngaards 518e7511d7 default config file location, example conf installed.
git-svn-id: file:///svn/unbound/trunk@736 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-09 13:52:13 +00:00
Wouter Wijngaards 6048ba67fa Ldns fixup.
git-svn-id: file:///svn/unbound/trunk@735 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-09 09:50:48 +00:00
Wouter Wijngaards 0eddfd7528 new L root.
git-svn-id: file:///svn/unbound/trunk@734 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-08 13:02:02 +00:00
Wouter Wijngaards 3ed2f28b76 Fixup chroot (Thanks Jakob).
git-svn-id: file:///svn/unbound/trunk@733 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-08 10:44:30 +00:00
Wouter Wijngaards e9277fc201 harden off has more consequences.
git-svn-id: file:///svn/unbound/trunk@732 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-01 16:05:55 +00:00
Wouter Wijngaards 5d5f08e4fd fixup test.
git-svn-id: file:///svn/unbound/trunk@731 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-01 15:45:31 +00:00
Wouter Wijngaards a06131872d Harden dnssec stripped zones.
git-svn-id: file:///svn/unbound/trunk@730 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-01 15:32:27 +00:00
Wouter Wijngaards d2892aa5ab alloc id overflow handling.
git-svn-id: file:///svn/unbound/trunk@729 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-01 14:39:50 +00:00
Wouter Wijngaards 27c8952a2c touch up clear and verbose.
git-svn-id: file:///svn/unbound/trunk@728 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-01 13:22:12 +00:00
Wouter Wijngaards 5b966557cc chroot fixup.
git-svn-id: file:///svn/unbound/trunk@727 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-01 12:48:37 +00:00
Wouter Wijngaards 734abf9323 Fixup of reload bug.
git-svn-id: file:///svn/unbound/trunk@726 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-11-01 09:48:20 +00:00
Wouter Wijngaards 2725ad55fc hash clear function.
git-svn-id: file:///svn/unbound/trunk@725 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-31 16:15:44 +00:00
Wouter Wijngaards f79c387f3f - fix horrible oversight in sorting rrset references in a message,
sort per reference key pointer, not on referencepointer itself.
        - pidfile: "/etc/unbound/unbound.pid" is now the default.
        - tests changed to reflect the updated default.


git-svn-id: file:///svn/unbound/trunk@724 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-31 14:46:05 +00:00
Wouter Wijngaards 2e9785cfb5 better chroot support, and also default chroot and userchange.
git-svn-id: file:///svn/unbound/trunk@723 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-31 10:56:31 +00:00
Wouter Wijngaards 75c30382ba Build fix outside sourcedir.
git-svn-id: file:///svn/unbound/trunk@722 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-31 08:30:47 +00:00
Wouter Wijngaards fe44f5918a max ttl option.
git-svn-id: file:///svn/unbound/trunk@721 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-31 07:46:30 +00:00
Wouter Wijngaards 63dc8ffde2 ttl not greedy.
git-svn-id: file:///svn/unbound/trunk@720 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-30 21:40:16 +00:00
Wouter Wijngaards 2bb408e2aa Quieter low verbosity logging.
git-svn-id: file:///svn/unbound/trunk@719 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-30 14:59:01 +00:00
Wouter Wijngaards 0eb3149af5 Assertion incorrect. Compressed packets can be larger.
git-svn-id: file:///svn/unbound/trunk@718 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-30 13:40:43 +00:00
Wouter Wijngaards 298e1fd688 overload mode: too many queries situation is detected and queries are dropped.
git-svn-id: file:///svn/unbound/trunk@717 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-23 14:44:51 +00:00
Wouter Wijngaards 861483ac82 dnssec lame servers are used as last effort.
git-svn-id: file:///svn/unbound/trunk@716 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-23 12:37:18 +00:00
Wouter Wijngaards f92d51b3fe dnssec lameness detection improved to disable detection when not sure.
git-svn-id: file:///svn/unbound/trunk@715 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-23 08:30:21 +00:00
Wouter Wijngaards 633daf4bc7 dnssec lame detection.
git-svn-id: file:///svn/unbound/trunk@714 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-22 15:25:37 +00:00
Wouter Wijngaards b247774236 Detect recursion-lameness.
git-svn-id: file:///svn/unbound/trunk@713 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-22 12:05:46 +00:00
Wouter Wijngaards 63aa7463e8 ISO C
git-svn-id: file:///svn/unbound/trunk@712 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-22 09:14:29 +00:00
Wouter Wijngaards 280352760c Fixup tests.
git-svn-id: file:///svn/unbound/trunk@711 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-22 06:25:46 +00:00
Wouter Wijngaards f8dcdf6e3a And manual entry.
git-svn-id: file:///svn/unbound/trunk@710 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-19 18:11:04 +00:00
Wouter Wijngaards 2885210384 Donotquery for netblocks.
git-svn-id: file:///svn/unbound/trunk@709 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-19 18:09:11 +00:00
Wouter Wijngaards 253a6e0143 root-hints can be read from file.
git-svn-id: file:///svn/unbound/trunk@708 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-19 14:02:53 +00:00
Wouter Wijngaards 90df76f931 nicer error, random() improved.
git-svn-id: file:///svn/unbound/trunk@707 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-19 12:10:13 +00:00
Wouter Wijngaards 391504fd03 rework ldns-src inclusion.
git-svn-id: file:///svn/unbound/trunk@706 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-19 10:38:27 +00:00
Jelte Jansen da79cd57d9 hit me baby one more time
git-svn-id: file:///svn/unbound/trunk@705 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-19 08:37:27 +00:00
Wouter Wijngaards c8c099960a outgoing interfaces setting possible.
git-svn-id: file:///svn/unbound/trunk@704 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-19 08:32:36 +00:00
Jelte Jansen 3a84f02606 bsd-generated configlexer
git-svn-id: file:///svn/unbound/trunk@703 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-19 08:11:57 +00:00
Wouter Wijngaards 086b257b1d - lex fix
- unsecure validation neater
- const cast warning removal


git-svn-id: file:///svn/unbound/trunk@702 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-19 08:03:08 +00:00
Wouter Wijngaards f22716c237 Added yacc and lex files.
git-svn-id: file:///svn/unbound/trunk@701 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-18 22:49:08 +00:00
Wouter Wijngaards c74ae3212b and config.h.in.
git-svn-id: file:///svn/unbound/trunk@700 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-18 22:40:10 +00:00
Wouter Wijngaards b40163446e configure, ready to go.
git-svn-id: file:///svn/unbound/trunk@699 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-18 22:38:15 +00:00
Wouter Wijngaards ce11690aa1 keep cache of prealloced blocks.
git-svn-id: file:///svn/unbound/trunk@698 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-18 22:17:02 +00:00
Wouter Wijngaards 6f49c2fe55 regional nicer, remove region-allocator.
git-svn-id: file:///svn/unbound/trunk@697 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-18 20:31:43 +00:00
Wouter Wijngaards 63bef95aac regional.
git-svn-id: file:///svn/unbound/trunk@696 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-18 15:40:31 +00:00
Wouter Wijngaards f768fc1148 Ldns included.
git-svn-id: file:///svn/unbound/trunk@695 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-18 13:05:41 +00:00
Wouter Wijngaards 8e54424abc Fixup test with shorter timeout values.
git-svn-id: file:///svn/unbound/trunk@694 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-18 09:33:37 +00:00
Wouter Wijngaards c41d12bb94 Tests update.
git-svn-id: file:///svn/unbound/trunk@693 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-18 09:24:57 +00:00
Wouter Wijngaards 268ada0d33 errors have addresses with them.
git-svn-id: file:///svn/unbound/trunk@692 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-18 09:04:55 +00:00
Wouter Wijngaards 907ab3d99a failover to next server.
git-svn-id: file:///svn/unbound/trunk@691 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-17 19:23:01 +00:00
Wouter Wijngaards f12875c910 unit test fix.
git-svn-id: file:///svn/unbound/trunk@690 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-17 17:43:00 +00:00
Wouter Wijngaards 482658b1cc Faster timeouts, based on extracts of our logs.
git-svn-id: file:///svn/unbound/trunk@689 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-17 17:40:35 +00:00
Wouter Wijngaards 75792c34dc fixup insecure glue on referrals.
git-svn-id: file:///svn/unbound/trunk@688 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-17 15:48:54 +00:00
Wouter Wijngaards be0bdf0260 fixup test, less logging.
git-svn-id: file:///svn/unbound/trunk@687 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-17 14:49:12 +00:00
Wouter Wijngaards 08549c7610 remove warning.
git-svn-id: file:///svn/unbound/trunk@686 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-17 14:27:45 +00:00
Wouter Wijngaards 108539c94c fixup crashy.
git-svn-id: file:///svn/unbound/trunk@685 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-17 14:22:14 +00:00
Wouter Wijngaards a4d4d0fe3a no debug on low verbosity.
git-svn-id: file:///svn/unbound/trunk@684 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-17 14:10:46 +00:00
Wouter Wijngaards 9e732da50b Arc4random.
git-svn-id: file:///svn/unbound/trunk@683 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-17 12:08:34 +00:00
Wouter Wijngaards fe33f7c72c resolution fix.
git-svn-id: file:///svn/unbound/trunk@682 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-17 07:34:13 +00:00
Wouter Wijngaards 631ccb58bf size_t no underflow.
git-svn-id: file:///svn/unbound/trunk@681 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-16 14:39:27 +00:00
Wouter Wijngaards 189fafa1da buffer overflow code audit.
git-svn-id: file:///svn/unbound/trunk@680 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-16 13:03:57 +00:00
Wouter Wijngaards 4260a18fb1 assertions, zero termination for gethostname, log_hex without malloc.
git-svn-id: file:///svn/unbound/trunk@679 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-16 12:26:09 +00:00
Wouter Wijngaards 79f840acd4 require ldns-testns.
git-svn-id: file:///svn/unbound/trunk@678 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-15 14:47:22 +00:00
Wouter Wijngaards fed59bca84 fixup addr6 check.
git-svn-id: file:///svn/unbound/trunk@677 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-15 14:42:37 +00:00
Wouter Wijngaards aecdb781fc Fixup compression, and test for byteformat compression results.
git-svn-id: file:///svn/unbound/trunk@676 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-15 14:19:17 +00:00
Wouter Wijngaards bef17e9e7c fixup ip6 tcp.
git-svn-id: file:///svn/unbound/trunk@675 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-15 09:10:26 +00:00
Wouter Wijngaards 25da698bf1 disable rpath option.
git-svn-id: file:///svn/unbound/trunk@674 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-11 07:34:44 +00:00
Wouter Wijngaards 3aea7c2630 Fixup tests.
git-svn-id: file:///svn/unbound/trunk@673 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-10 09:33:27 +00:00
Wouter Wijngaards d4424931f4 no more AD bits, except when DO is set.
git-svn-id: file:///svn/unbound/trunk@672 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-09 15:33:40 +00:00
Wouter Wijngaards a5ac86f410 Fixup event callback checks.
git-svn-id: file:///svn/unbound/trunk@671 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-09 12:04:13 +00:00
Wouter Wijngaards aed61e4d8a whitelist does not work on events, due to deletions.
git-svn-id: file:///svn/unbound/trunk@670 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-09 11:58:58 +00:00
Wouter Wijngaards c46e1a1ee8 cleaner.
git-svn-id: file:///svn/unbound/trunk@669 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-09 07:53:35 +00:00
Wouter Wijngaards 2bfe2d5fe3 plan changes.
git-svn-id: file:///svn/unbound/trunk@668 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-09 07:46:57 +00:00
Wouter Wijngaards 75bfcb8c91 No early logfile open.
git-svn-id: file:///svn/unbound/trunk@667 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-09 07:43:32 +00:00
Wouter Wijngaards f4049b54c4 logfile first open bad permissions.
git-svn-id: file:///svn/unbound/trunk@666 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-09 07:11:14 +00:00
Wouter Wijngaards 9fec5d86d3 forgot whitelist entry.
git-svn-id: file:///svn/unbound/trunk@665 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-08 09:00:13 +00:00
Wouter Wijngaards f856eef411 fix warning on solaris.
git-svn-id: file:///svn/unbound/trunk@664 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-05 13:13:48 +00:00
Wouter Wijngaards 24d1ed15c4 please gcc more.
git-svn-id: file:///svn/unbound/trunk@663 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-05 13:02:50 +00:00
Wouter Wijngaards 26c4e7a182 please gcc on BSD.
git-svn-id: file:///svn/unbound/trunk@662 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-05 12:57:24 +00:00
Wouter Wijngaards 8e55996b7c function pointer whitelist for module operations. completing fptr work.
git-svn-id: file:///svn/unbound/trunk@661 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-05 12:42:25 +00:00
Wouter Wijngaards 2a547a35a7 function pointer whitelists on data types.
git-svn-id: file:///svn/unbound/trunk@660 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-05 11:41:12 +00:00
Wouter Wijngaards 9a60182c86 fptr whitelist network code callbacks.
git-svn-id: file:///svn/unbound/trunk@659 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-05 08:05:06 +00:00
Wouter Wijngaards 107a915c67 unbreak trunk.
git-svn-id: file:///svn/unbound/trunk@658 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-04 15:24:20 +00:00
Wouter Wijngaards 41e847df18 security audit changes.
git-svn-id: file:///svn/unbound/trunk@657 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-04 15:10:11 +00:00
Wouter Wijngaards 7ccfb10392 fixup nasty cache overwriting bug.
git-svn-id: file:///svn/unbound/trunk@656 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-03 19:11:50 +00:00
Wouter Wijngaards d4614cf1ce fixup cname out of unsec zone.
git-svn-id: file:///svn/unbound/trunk@655 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-03 13:33:23 +00:00
Wouter Wijngaards a740dfe195 Fixup and test.
git-svn-id: file:///svn/unbound/trunk@654 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-03 12:20:55 +00:00
Wouter Wijngaards a73089c5f0 loopfix.
git-svn-id: file:///svn/unbound/trunk@653 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-03 08:36:47 +00:00
Wouter Wijngaards 759f666177 regress test for CNAMEd address for nameserver.
git-svn-id: file:///svn/unbound/trunk@652 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-03 06:46:26 +00:00
Wouter Wijngaards e7883b13f4 crash fixup.
git-svn-id: file:///svn/unbound/trunk@651 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-01 14:55:08 +00:00
Wouter Wijngaards f0015b8919 skip unused tests.
git-svn-id: file:///svn/unbound/trunk@650 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-10-01 12:16:19 +00:00
Wouter Wijngaards 1115d50dce unbound-checkconf test.
git-svn-id: file:///svn/unbound/trunk@649 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-28 14:33:35 +00:00
Wouter Wijngaards dc34bb36b3 do lint, depend.
git-svn-id: file:///svn/unbound/trunk@648 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-26 15:01:22 +00:00
Wouter Wijngaards 8f8627a0c3 unbound-checkconf.
git-svn-id: file:///svn/unbound/trunk@647 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-26 13:39:49 +00:00
Wouter Wijngaards c2f8d43f9d fixup tests.
git-svn-id: file:///svn/unbound/trunk@646 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-26 11:29:37 +00:00
Wouter Wijngaards 6a482dc7f2 fixup test.
git-svn-id: file:///svn/unbound/trunk@645 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-26 11:15:42 +00:00
Wouter Wijngaards bc9f482b2a syslog feature.
git-svn-id: file:///svn/unbound/trunk@644 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-26 10:19:28 +00:00
Wouter Wijngaards 8659118a5e done items.
git-svn-id: file:///svn/unbound/trunk@643 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-25 14:01:30 +00:00
Wouter Wijngaards 01db268dff 0.5 release tag.
git-svn-id: file:///svn/unbound/trunk@642 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-25 13:00:26 +00:00
Wouter Wijngaards 6cb2b251c5 fixup exit status post test.
git-svn-id: file:///svn/unbound/trunk@641 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-25 12:29:24 +00:00
Wouter Wijngaards 41e1ffe1c4 no overload mode yet.
git-svn-id: file:///svn/unbound/trunk@640 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-25 12:25:37 +00:00
Wouter Wijngaards 5a6638fed0 test fixup.
git-svn-id: file:///svn/unbound/trunk@639 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-25 11:47:45 +00:00
Wouter Wijngaards fd3293a0ee NSEC3 tests, and fixup for qtype ANY wildcard proof.
git-svn-id: file:///svn/unbound/trunk@638 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-25 09:39:32 +00:00
Wouter Wijngaards 0f7ced491e NSEC3 test and fix for bitmap protection code.
git-svn-id: file:///svn/unbound/trunk@637 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-25 08:33:14 +00:00
Wouter Wijngaards 52e48a90ea NSEC3 tests.
git-svn-id: file:///svn/unbound/trunk@636 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-24 13:32:40 +00:00
Wouter Wijngaards 2a5bcffcc2 Make test command.
git-svn-id: file:///svn/unbound/trunk@635 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-24 08:04:05 +00:00
Wouter Wijngaards 931efbbaa0 Fixup and test for nonrec loop case.
git-svn-id: file:///svn/unbound/trunk@634 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-21 20:30:04 +00:00
Wouter Wijngaards 74468b2edb debug
git-svn-id: file:///svn/unbound/trunk@633 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-21 15:45:32 +00:00
Wouter Wijngaards f2ba9e985b overload mode is a TODO.
git-svn-id: file:///svn/unbound/trunk@632 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-21 15:12:31 +00:00
Wouter Wijngaards 553ebaf7a9 argument format.
git-svn-id: file:///svn/unbound/trunk@631 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-21 14:35:07 +00:00
Wouter Wijngaards 5043992159 remove subscript char warnings.
git-svn-id: file:///svn/unbound/trunk@630 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-21 14:15:05 +00:00
Wouter Wijngaards 463bd32b26 fixup locking in test code.
git-svn-id: file:///svn/unbound/trunk@629 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-21 13:55:07 +00:00
Wouter Wijngaards a81e19a6eb Fixup alloc in wrong region.
git-svn-id: file:///svn/unbound/trunk@628 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-21 13:34:44 +00:00
Wouter Wijngaards db695709e6 plans.
git-svn-id: file:///svn/unbound/trunk@627 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-20 14:39:22 +00:00
Wouter Wijngaards 62e37fe3ee quick fixup
git-svn-id: file:///svn/unbound/trunk@626 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-20 12:46:19 +00:00
Wouter Wijngaards c6e92c19b2 more liberal for ANS ENT bug. Fixup DS ENT handling too.
git-svn-id: file:///svn/unbound/trunk@625 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-20 12:31:35 +00:00
Wouter Wijngaards 9865f38f69 Fixup for a wildcarded NSEC with empty nonterminal query.
git-svn-id: file:///svn/unbound/trunk@624 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-20 11:37:15 +00:00
Wouter Wijngaards 8959cd47a8 NSEC rdata not lowercased.
git-svn-id: file:///svn/unbound/trunk@623 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-19 12:34:42 +00:00
Wouter Wijngaards c968fc7581 fixup glue timeout problems, and priming with safety belt.
git-svn-id: file:///svn/unbound/trunk@622 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-19 12:17:42 +00:00
Wouter Wijngaards cbd9764601 plan and comments.
git-svn-id: file:///svn/unbound/trunk@621 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-19 09:20:24 +00:00
Wouter Wijngaards 9c1f6e2df5 test ideas.
git-svn-id: file:///svn/unbound/trunk@620 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-18 14:24:41 +00:00
Wouter Wijngaards e8bcec4529 print validator classification type.
update plan items.


git-svn-id: file:///svn/unbound/trunk@619 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-18 12:33:51 +00:00
Wouter Wijngaards c4392dd54c wildcard nsec3 tests.
git-svn-id: file:///svn/unbound/trunk@618 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-18 08:28:35 +00:00
Wouter Wijngaards 748bfb0b0e more nsec3 tests.
git-svn-id: file:///svn/unbound/trunk@617 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-17 14:52:14 +00:00
Wouter Wijngaards 6510d8f20a namerror nsec3 proof works.
git-svn-id: file:///svn/unbound/trunk@616 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-17 14:03:35 +00:00
Wouter Wijngaards c7d15770c1 nsec3 hash function unit test.
git-svn-id: file:///svn/unbound/trunk@615 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-17 09:25:54 +00:00
Wouter Wijngaards 48aec18ef7 Fixup qname after prepend.
git-svn-id: file:///svn/unbound/trunk@614 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-14 14:05:52 +00:00
Wouter Wijngaards 7987b687dc NSEC3.
git-svn-id: file:///svn/unbound/trunk@613 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-14 11:15:42 +00:00
Wouter Wijngaards b22e1d4273 Use nsec3s_seen flag for speedup.
git-svn-id: file:///svn/unbound/trunk@612 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-13 15:11:25 +00:00
Wouter Wijngaards 92198b3624 if no NSEC3 present, skip validation.
git-svn-id: file:///svn/unbound/trunk@611 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-13 15:09:58 +00:00
Wouter Wijngaards facde2ca10 nsec3 work, prove name error.
git-svn-id: file:///svn/unbound/trunk@610 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-13 15:02:33 +00:00
Wouter Wijngaards d85debfae4 nsec3 work.
git-svn-id: file:///svn/unbound/trunk@609 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-12 14:16:46 +00:00
Wouter Wijngaards db452ffc16 manual page warning fix.
git-svn-id: file:///svn/unbound/trunk@608 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-12 05:59:45 +00:00
Wouter Wijngaards 26f9ea8942 nsec3 work.
git-svn-id: file:///svn/unbound/trunk@607 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-11 18:18:16 +00:00
Wouter Wijngaards b0b9193603 rwlock optional.
git-svn-id: file:///svn/unbound/trunk@606 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-07 13:28:23 +00:00
Wouter Wijngaards d2bf27acd7 search order.
git-svn-id: file:///svn/unbound/trunk@605 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-06 09:29:15 +00:00
Wouter Wijngaards 149ff1cd5a please older gcc.
git-svn-id: file:///svn/unbound/trunk@604 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-06 09:16:43 +00:00
Wouter Wijngaards 08bf892be6 port.
git-svn-id: file:///svn/unbound/trunk@603 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-06 09:14:13 +00:00
Wouter Wijngaards ab316be813 Find libevent on mac port.
git-svn-id: file:///svn/unbound/trunk@602 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-06 09:00:46 +00:00
Wouter Wijngaards 5134e8e1ae Fixup unused warnings when running without threads.
git-svn-id: file:///svn/unbound/trunk@601 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-05 14:56:38 +00:00
Wouter Wijngaards 4736eaf80d fixup memdebug option on solaris.
git-svn-id: file:///svn/unbound/trunk@600 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-05 14:07:53 +00:00
Wouter Wijngaards a404373112 and documentation.
git-svn-id: file:///svn/unbound/trunk@599 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-05 13:52:23 +00:00
Wouter Wijngaards 5f9e30aacb configure option for memory allocation debugging.
git-svn-id: file:///svn/unbound/trunk@598 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-05 13:47:23 +00:00
Wouter Wijngaards 7b76e85956 todo item.
git-svn-id: file:///svn/unbound/trunk@597 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-05 13:26:16 +00:00
Wouter Wijngaards cb3044c09d wildcard NSECs.
git-svn-id: file:///svn/unbound/trunk@596 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-05 12:58:25 +00:00
Wouter Wijngaards 009a68a795 QTYPE CNAME test.
git-svn-id: file:///svn/unbound/trunk@595 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-05 11:58:45 +00:00
Wouter Wijngaards f52b202747 trust anchor denial test.
git-svn-id: file:///svn/unbound/trunk@594 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-05 11:47:09 +00:00
Wouter Wijngaards a9ea07cbb3 test for referral with and without a DS.
git-svn-id: file:///svn/unbound/trunk@593 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-05 11:06:42 +00:00
Wouter Wijngaards e384cdaf70 any with DNAME record (test for synthesis of CNAME).
git-svn-id: file:///svn/unbound/trunk@592 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-05 09:54:18 +00:00
Wouter Wijngaards 18a5fb1fc5 ANY response validation test.
git-svn-id: file:///svn/unbound/trunk@591 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-05 09:50:02 +00:00
Wouter Wijngaards bf02cdbf5c nxdomain tests.
git-svn-id: file:///svn/unbound/trunk@590 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-05 09:04:51 +00:00
Wouter Wijngaards 4d473bd618 cname and dname tests.
git-svn-id: file:///svn/unbound/trunk@589 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-05 08:54:27 +00:00
Wouter Wijngaards 496c91c250 signature validation of different parts of a CNAME'd message works.
git-svn-id: file:///svn/unbound/trunk@588 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-04 15:29:28 +00:00
Wouter Wijngaards 91786f4cc6 fixup AUTH prepend list.
git-svn-id: file:///svn/unbound/trunk@587 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-04 14:06:43 +00:00
Wouter Wijngaards 359d9ec426 test for dname wildcard.
git-svn-id: file:///svn/unbound/trunk@586 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-04 13:10:06 +00:00
Wouter Wijngaards d45774fe03 wildcard DNAME detect
git-svn-id: file:///svn/unbound/trunk@585 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-04 12:57:40 +00:00
Wouter Wijngaards 0e11cd160d DNAME synthesis and validation fixups.
git-svn-id: file:///svn/unbound/trunk@584 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-04 12:44:43 +00:00
Wouter Wijngaards bb67a404fb tests, cleanup tmp when testbound fails, fixup referral glue cleanup.
git-svn-id: file:///svn/unbound/trunk@583 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-04 11:31:29 +00:00
Wouter Wijngaards 4016aa755e No leakage warning for double serviced callback.
git-svn-id: file:///svn/unbound/trunk@582 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-04 07:57:06 +00:00
Wouter Wijngaards b33c39334b please lint.
git-svn-id: file:///svn/unbound/trunk@581 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-03 14:05:38 +00:00
Wouter Wijngaards 6fe044de03 debug tool for mem stats.
git-svn-id: file:///svn/unbound/trunk@580 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-03 13:40:17 +00:00
Wouter Wijngaards 81fe98956c lame cache in bytes.
git-svn-id: file:///svn/unbound/trunk@579 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-03 10:19:10 +00:00
Wouter Wijngaards ab143fd1f8 fixup lameness cache memory accounting leak.
git-svn-id: file:///svn/unbound/trunk@578 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-03 10:08:16 +00:00
Wouter Wijngaards eb0deb1301 spurious memory leak (+364 bytes) removed during tcp timeout callback.
git-svn-id: file:///svn/unbound/trunk@577 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-03 09:45:18 +00:00
Wouter Wijngaards 8351afe61a cname nxdomain fixup.
git-svn-id: file:///svn/unbound/trunk@576 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-09-03 09:13:27 +00:00
Wouter Wijngaards edbbacecf9 referral test, sig removal.
git-svn-id: file:///svn/unbound/trunk@575 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-31 13:15:25 +00:00
Wouter Wijngaards 1e5a3fb786 fixup test
git-svn-id: file:///svn/unbound/trunk@574 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-31 12:58:23 +00:00
Wouter Wijngaards 7f4a12c652 positive check.
git-svn-id: file:///svn/unbound/trunk@573 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-31 12:49:17 +00:00
Wouter Wijngaards 49bb418691 Nodata tests.
git-svn-id: file:///svn/unbound/trunk@572 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-31 12:35:41 +00:00
Wouter Wijngaards 2540d6c511 iterator works better with failing hosts.
git-svn-id: file:///svn/unbound/trunk@571 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-31 09:38:55 +00:00
Wouter Wijngaards fd7af10ff6 please lint.
git-svn-id: file:///svn/unbound/trunk@570 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-31 07:56:00 +00:00
Wouter Wijngaards f304a2a459 can read bind-style config files for trust anchor information.
git-svn-id: file:///svn/unbound/trunk@569 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-31 07:44:16 +00:00
Wouter Wijngaards fceea2bcd5 bind config trusted keys read work.
git-svn-id: file:///svn/unbound/trunk@568 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-30 15:36:23 +00:00
Wouter Wijngaards 45297772c9 crypto cleanups at exit.
git-svn-id: file:///svn/unbound/trunk@567 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-30 13:38:52 +00:00
Wouter Wijngaards a22a3b1669 Memory cleanup.
- caught bad free of un-alloced data in worker_send error case.
       - memory accounting for key cache (trust anchors and temporary cache).
       - memory accounting fixup for outside network tcp pending waits.
       - memory accounting fixup for outside network tcp callbacks.
       - memory accounting for iterator fixed storage.
       - key cache size and slabs config options.


git-svn-id: file:///svn/unbound/trunk@566 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-30 12:45:19 +00:00
Wouter Wijngaards 341492391e support extremely small memory footprints.
git-svn-id: file:///svn/unbound/trunk@565 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-30 08:36:41 +00:00
Wouter Wijngaards de6d807e3d no convert to der for DSA signatures
signature test.


git-svn-id: file:///svn/unbound/trunk@564 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-29 14:27:04 +00:00
Wouter Wijngaards 134db23ea8 validate by default.
git-svn-id: file:///svn/unbound/trunk@563 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-29 13:27:21 +00:00
Wouter Wijngaards e8a709a315 please lint.
git-svn-id: file:///svn/unbound/trunk@562 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-29 12:20:25 +00:00
Wouter Wijngaards dd9da95c70 sign test tool.
git-svn-id: file:///svn/unbound/trunk@561 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-29 12:09:14 +00:00
Wouter Wijngaards 824ceffedb verbosity detail gives validation failures, but not boring algorithm logs.
git-svn-id: file:///svn/unbound/trunk@560 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-28 15:07:52 +00:00
Wouter Wijngaards e839035a7a doc fixup.
git-svn-id: file:///svn/unbound/trunk@559 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-28 14:14:20 +00:00
Wouter Wijngaards 3d832f5dca Small speedup.
git-svn-id: file:///svn/unbound/trunk@558 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-28 14:13:32 +00:00
Wouter Wijngaards 459039cf08 Faster verification.
git-svn-id: file:///svn/unbound/trunk@557 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-28 13:54:55 +00:00
Wouter Wijngaards 60470b186e permissive mode feature.
git-svn-id: file:///svn/unbound/trunk@556 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-28 11:53:27 +00:00
Wouter Wijngaards c988905aa4 enforce signature TTLs
git-svn-id: file:///svn/unbound/trunk@555 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-28 10:26:16 +00:00
Wouter Wijngaards af2b300529 No offtree signing.
git-svn-id: file:///svn/unbound/trunk@554 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-28 09:47:17 +00:00
Wouter Wijngaards 0e90c03e95 Referral validation.
git-svn-id: file:///svn/unbound/trunk@553 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-28 09:39:43 +00:00
Wouter Wijngaards f293924be8 No double use of buffers.
git-svn-id: file:///svn/unbound/trunk@552 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-28 08:03:45 +00:00
Wouter Wijngaards f9cc9481e2 validator also computes insecure and indeterminate for rrsets and stores
that.


git-svn-id: file:///svn/unbound/trunk@551 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-27 14:55:06 +00:00
Wouter Wijngaards 542b812690 do not cache nonRD replies in msg cache, the rrset cache is used for that.
store verification status in rrset cache to enable security for nonRD
replies and also speed up processing.


git-svn-id: file:///svn/unbound/trunk@550 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-27 13:46:05 +00:00
Wouter Wijngaards 674fdd5e39 send recursive queries to test cache drop off.
git-svn-id: file:///svn/unbound/trunk@549 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-27 11:26:03 +00:00
Wouter Wijngaards c9107bfb1a answer non-recursive straight from cache, if possible.
git-svn-id: file:///svn/unbound/trunk@548 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-27 09:53:16 +00:00
Wouter Wijngaards 5a62edfc26 larger default infra cache.
git-svn-id: file:///svn/unbound/trunk@547 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-24 14:58:36 +00:00
Wouter Wijngaards 87fafec48a DS and DNSKEY not from additional synthesis. Nicer signature expiration errors.
git-svn-id: file:///svn/unbound/trunk@546 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-24 13:14:23 +00:00
Wouter Wijngaards a490e8777f Fixup.
git-svn-id: file:///svn/unbound/trunk@545 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-24 12:24:07 +00:00
Wouter Wijngaards 3a422ba496 prettier proof routines.
git-svn-id: file:///svn/unbound/trunk@544 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-24 10:36:15 +00:00
Wouter Wijngaards 6890f55d17 refuse unsigned authority section. clean additional section as option.
git-svn-id: file:///svn/unbound/trunk@543 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-24 09:44:29 +00:00
Wouter Wijngaards b54a0400ab CNAME validation.
git-svn-id: file:///svn/unbound/trunk@542 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-23 15:23:45 +00:00
Wouter Wijngaards a7001366a1 review change.
git-svn-id: file:///svn/unbound/trunk@541 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-22 14:29:24 +00:00
Wouter Wijngaards a084af819c bogus ttl fixed value, config item.
git-svn-id: file:///svn/unbound/trunk@540 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-22 12:13:52 +00:00
Wouter Wijngaards 5c9f7c00ba manpage entry.
git-svn-id: file:///svn/unbound/trunk@539 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-21 20:45:31 +00:00
Wouter Wijngaards cf4ef6fbaf construct DS and DNSKEY from cache.
git-svn-id: file:///svn/unbound/trunk@538 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-21 14:05:10 +00:00
Wouter Wijngaards 9c8fd98719 Fixup.
git-svn-id: file:///svn/unbound/trunk@537 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-21 13:27:04 +00:00
Wouter Wijngaards 272096d611 Returns and caches validated replies.
git-svn-id: file:///svn/unbound/trunk@536 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-21 13:12:10 +00:00
Wouter Wijngaards 834a8fc30f any response validation.
git-svn-id: file:///svn/unbound/trunk@535 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-21 07:58:55 +00:00
Wouter Wijngaards 0f9ae7acd8 nxdomain validation.
git-svn-id: file:///svn/unbound/trunk@534 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-20 14:27:11 +00:00
Wouter Wijngaards 5605f8d003 nodata validation.
git-svn-id: file:///svn/unbound/trunk@533 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-20 13:39:58 +00:00
Wouter Wijngaards 1b42a51048 VALIDATE state and positive response validation.
git-svn-id: file:///svn/unbound/trunk@532 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-20 12:31:12 +00:00
Wouter Wijngaards 3f8b0b1cfe handle DNSKEY response state.
git-svn-id: file:///svn/unbound/trunk@531 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-20 08:10:57 +00:00
Wouter Wijngaards 453df0c66c nsec work, canonical compare routine and tests.
git-svn-id: file:///svn/unbound/trunk@530 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-17 14:25:42 +00:00
Wouter Wijngaards cedeaa8316 ds2ke and nsec work.
git-svn-id: file:///svn/unbound/trunk@529 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-17 11:41:49 +00:00
Wouter Wijngaards 9ddbb430ef findkey state.
git-svn-id: file:///svn/unbound/trunk@528 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-16 15:06:40 +00:00
Wouter Wijngaards 568f0699dc Fixup bug in response type calculation.
git-svn-id: file:///svn/unbound/trunk@527 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-16 13:35:37 +00:00
Wouter Wijngaards 24aad68487 fixup canon compare. Include full AXFR data in signature test.
git-svn-id: file:///svn/unbound/trunk@526 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-16 10:05:52 +00:00
Wouter Wijngaards e4aa70b4c5 key prime, DS test.
git-svn-id: file:///svn/unbound/trunk@525 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-16 09:33:35 +00:00
Wouter Wijngaards f6371f11a4 updated after resign.
git-svn-id: file:///svn/unbound/trunk@524 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-15 14:20:54 +00:00
Wouter Wijngaards ce290651d0 unit test will fail, but this fixes canonical order in unbound, waiting
for ldns fix.


git-svn-id: file:///svn/unbound/trunk@523 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-15 14:09:00 +00:00
Wouter Wijngaards 1d29f79974 verify unit test.
git-svn-id: file:///svn/unbound/trunk@522 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-15 13:18:32 +00:00
Wouter Wijngaards 927af50c81 please lint.
git-svn-id: file:///svn/unbound/trunk@521 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-15 09:04:44 +00:00
Wouter Wijngaards f06b1e8ef3 crypto verify routines.
git-svn-id: file:///svn/unbound/trunk@520 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-15 08:39:00 +00:00
Wouter Wijngaards c2b1ad1418 please lint.
git-svn-id: file:///svn/unbound/trunk@519 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-14 20:07:35 +00:00
Wouter Wijngaards 9db2d3fa78 cycle detection fix.
git-svn-id: file:///svn/unbound/trunk@518 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-14 19:42:36 +00:00
Wouter Wijngaards 8a290f6a16 Fixup parser, new test.
git-svn-id: file:///svn/unbound/trunk@517 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-14 15:33:07 +00:00
Wouter Wijngaards 016f27739d header fix.
git-svn-id: file:///svn/unbound/trunk@516 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-14 13:42:33 +00:00
Wouter Wijngaards c49a3af953 please lint.
git-svn-id: file:///svn/unbound/trunk@515 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-14 13:37:31 +00:00
Wouter Wijngaards 7d07e1b9c3 enable for lock checks.
git-svn-id: file:///svn/unbound/trunk@514 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-14 13:33:41 +00:00
Wouter Wijngaards f8719c1aa1 please lint and doxygen.
git-svn-id: file:///svn/unbound/trunk@513 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-14 13:18:50 +00:00
Wouter Wijngaards 448a9f414f fixups for memory.
git-svn-id: file:///svn/unbound/trunk@512 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-14 13:15:36 +00:00
Wouter Wijngaards 86723bd032 More logging.
git-svn-id: file:///svn/unbound/trunk@511 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-13 12:23:49 +00:00
Wouter Wijngaards 0374d468c8 hinfo treatment.
git-svn-id: file:///svn/unbound/trunk@510 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-13 11:53:24 +00:00
Wouter Wijngaards 2157540f35 makefile nicer in case flex is missing.
canonical compare.


git-svn-id: file:///svn/unbound/trunk@509 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-13 10:27:44 +00:00
Wouter Wijngaards 749ee526e8 canonical sort.
git-svn-id: file:///svn/unbound/trunk@508 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-10 15:12:06 +00:00
Wouter Wijngaards b12ae95d1d total allocation tracking.
git-svn-id: file:///svn/unbound/trunk@507 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-10 09:07:19 +00:00
Wouter Wijngaards 1dd6ef9f24 doc fixup for mac users.
git-svn-id: file:///svn/unbound/trunk@506 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-09 15:23:36 +00:00
Wouter Wijngaards 5166d65ea2 debug override date config option.
git-svn-id: file:///svn/unbound/trunk@505 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-09 15:16:25 +00:00
Wouter Wijngaards 9ada9f1093 -R ssl.
git-svn-id: file:///svn/unbound/trunk@504 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-09 11:52:24 +00:00
Wouter Wijngaards d5e4fa21de memory indication.
typo fix.


git-svn-id: file:///svn/unbound/trunk@503 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-09 10:14:32 +00:00
Wouter Wijngaards 45f95a18af rrsig checks.
git-svn-id: file:///svn/unbound/trunk@502 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-09 09:58:04 +00:00
Wouter Wijngaards 8f58908f45 sigcrypt keyset processing
git-svn-id: file:///svn/unbound/trunk@501 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-08 13:59:57 +00:00
Wouter Wijngaards bdb519c5c1 use sigcrypt.
git-svn-id: file:///svn/unbound/trunk@500 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-08 13:02:53 +00:00
Wouter Wijngaards 7726691af9 sigcrypt work.
git-svn-id: file:///svn/unbound/trunk@499 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-08 11:45:54 +00:00
Wouter Wijngaards eb5ab1f8e6 sigcrypt.
git-svn-id: file:///svn/unbound/trunk@498 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-07 15:18:25 +00:00
Wouter Wijngaards b2639ba961 val_util work.
git-svn-id: file:///svn/unbound/trunk@497 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-07 14:30:01 +00:00
Wouter Wijngaards c3a5bcb8d4 id number change
git-svn-id: file:///svn/unbound/trunk@496 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-07 09:24:20 +00:00
Wouter Wijngaards ff4f04de2a security status.
git-svn-id: file:///svn/unbound/trunk@495 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-07 08:27:23 +00:00
Wouter Wijngaards b24aac895f prime work.
git-svn-id: file:///svn/unbound/trunk@494 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-06 15:56:12 +00:00
Wouter Wijngaards 188bfacd05 validator work.
git-svn-id: file:///svn/unbound/trunk@493 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-06 12:57:29 +00:00
Wouter Wijngaards 4eaa855db9 dname isroot and dellabel
git-svn-id: file:///svn/unbound/trunk@492 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-06 11:06:00 +00:00
Wouter Wijngaards 44560e40ea key cache.
git-svn-id: file:///svn/unbound/trunk@491 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-06 09:34:58 +00:00
Wouter Wijngaards 1d83bb84ed key entry.
git-svn-id: file:///svn/unbound/trunk@490 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-03 14:56:24 +00:00
Wouter Wijngaards 9ebbdbabd3 create rrsets for verification later.
git-svn-id: file:///svn/unbound/trunk@489 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-03 14:12:28 +00:00
Wouter Wijngaards 6d8e67e7f9 oops.
git-svn-id: file:///svn/unbound/trunk@488 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-03 13:15:30 +00:00
Wouter Wijngaards eb1b1e6044 unit test trust anchor storage.
git-svn-id: file:///svn/unbound/trunk@487 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-03 13:15:16 +00:00
Wouter Wijngaards d48e17e1dd trust anchor storage and config.
git-svn-id: file:///svn/unbound/trunk@486 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-03 11:51:20 +00:00
Wouter Wijngaards 669a20084c check section.
git-svn-id: file:///svn/unbound/trunk@485 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-03 09:16:16 +00:00
Wouter Wijngaards 6b8f7df843 explanation for harden-glue.
git-svn-id: file:///svn/unbound/trunk@484 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-03 09:13:54 +00:00
Wouter Wijngaards 37a906991e replan
git-svn-id: file:///svn/unbound/trunk@483 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-03 08:45:06 +00:00
Wouter Wijngaards fd3e3ed05b validator, trust anchors.
git-svn-id: file:///svn/unbound/trunk@482 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-02 15:45:32 +00:00
Wouter Wijngaards ce12d59957 validator work.
git-svn-id: file:///svn/unbound/trunk@481 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-02 14:36:20 +00:00
Wouter Wijngaards c70c747c04 nicer walk_supers.
git-svn-id: file:///svn/unbound/trunk@480 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-02 12:22:29 +00:00
Wouter Wijngaards 6849c1030b passing of control between modules.
git-svn-id: file:///svn/unbound/trunk@479 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-02 12:13:08 +00:00
Wouter Wijngaards 947bd1ab91 Fixup scrubber and lameness.
git-svn-id: file:///svn/unbound/trunk@478 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-02 11:44:17 +00:00
Wouter Wijngaards c9a1cdec68 For test ldns.
git-svn-id: file:///svn/unbound/trunk@477 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-02 09:58:24 +00:00
Wouter Wijngaards dba780a00c Fixup duplicate delegations.
git-svn-id: file:///svn/unbound/trunk@476 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-02 09:21:58 +00:00
Wouter Wijngaards 4f8f9f2f74 choice.
git-svn-id: file:///svn/unbound/trunk@475 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-02 09:13:32 +00:00
Wouter Wijngaards 630d9dbc94 remove done and supers module interface calls.
git-svn-id: file:///svn/unbound/trunk@474 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-02 08:07:50 +00:00
Wouter Wijngaards c3f6bcb89a config change for libevent (newest).
git-svn-id: file:///svn/unbound/trunk@473 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-02 07:25:55 +00:00
Wouter Wijngaards 62b02dc911 don't fall through the if
git-svn-id: file:///svn/unbound/trunk@472 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-01 14:10:51 +00:00
Wouter Wijngaards 2122b961d3 callbacks via module specific function for walk_supers.
part of a move towards multiple modules for meshes.


git-svn-id: file:///svn/unbound/trunk@471 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-01 14:01:34 +00:00
Wouter Wijngaards 56916e48fb prime flag moved.
git-svn-id: file:///svn/unbound/trunk@470 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-01 12:59:37 +00:00
Wouter Wijngaards ec4878be75 query flags for detect cycle.
git-svn-id: file:///svn/unbound/trunk@469 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-01 11:29:12 +00:00
Wouter Wijngaards ac895c6d35 module configuration option.
git-svn-id: file:///svn/unbound/trunk@468 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-08-01 11:17:30 +00:00
Wouter Wijngaards 39e8652152 release 0.4 tag
git-svn-id: file:///svn/unbound/trunk@467 be551aaa-1e26-0410-a405-d3ace91eadb9
2007-07-31 14:41:43 +00:00
349 changed files with 104635 additions and 4353 deletions
+202 -61
View File
@@ -1,9 +1,13 @@
# Copyright 2007 NLnet Labs
# See the file LICENSE for the license
#
# Standard installation pathnames
QUIET=yes
debug_enabled=@debug_enabled@
ifeq ($(debug_enabled),yes)
QUIET=yes
else
QUIET=no
endif
ifeq "$(QUIET)" "yes"
Q=@
INFO=@echo
@@ -18,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.
@@ -28,12 +33,14 @@ doxygen=@doxygen@
libtool=@libtool@
ldnsdir=@ldnsdir@
staticexe=@staticexe@
configfile=@ub_conf_file@
CHECKLOCK_SRC=@CHECKLOCK_SRC@
YACC=@YACC@
LEX=@LEX@
CC=@CC@
CPPFLAGS=-I. @CPPFLAGS@ @DEFS@
CFLAGS=-I. @CFLAGS@
CPPFLAGS=-I$(srcdir) -I. @CPPFLAGS@ @DEFS@
CFLAGS=@CFLAGS@
LDFLAGS=@LDFLAGS@
LIBS=@LIBS@
LIBOBJS=@LIBOBJS@
@@ -46,67 +53,157 @@ endif
BUILD=build/
LINT=splint
LINTFLAGS=+quiet -weak -warnposix -unrecog -Din_addr_t=uint32_t -Du_int=unsigned -Du_char=uint8_t -preproc -Drlimit=rlimit64
LINTFLAGS=+quiet -weak -warnposix -unrecog -Din_addr_t=uint32_t -Du_int=unsigned -Du_char=uint8_t -preproc -Drlimit=rlimit64 -D__gnuc_va_list=va_list
# compat with openssl linux edition.
LINTFLAGS+="-DBN_ULONG=unsigned long" -Dkrb5_int32=int "-Dkrb5_ui_4=unsigned int" -DPQ_64BIT=uint64_t
LINTFLAGS+="-DBN_ULONG=unsigned long" -Dkrb5_int32=int "-Dkrb5_ui_4=unsigned int" -DPQ_64BIT=uint64_t -DRC4_INT=unsigned
INSTALL=$(srcdir)/install-sh
COMMON_SRC=$(wildcard services/*.c services/cache/*.c util/*.c \
util/data/*.c util/storage/*.c iterator/*.c) util/configparser.c \
util/configlexer.c testcode/checklocks.c
COMMON_OBJ=$(addprefix $(BUILD),$(COMMON_SRC:.c=.o))
COMPAT_OBJ=$(addprefix $(BUILD)compat/,$(LIBOBJS))
UNITTEST_SRC=$(wildcard testcode/unit*.c) testcode/readhex.c $(COMMON_SRC)
UNITTEST_OBJ=$(addprefix $(BUILD),$(UNITTEST_SRC:.c=.o)) $(COMPAT_OBJ)
DAEMON_SRC=$(wildcard daemon/*.c) $(COMMON_SRC)
DAEMON_OBJ=$(addprefix $(BUILD),$(DAEMON_SRC:.c=.o)) $(COMPAT_OBJ)
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 $(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=.lo)) $(COMPAT_OBJ)
DAEMON_SRC=$(patsubst $(srcdir)/%,%, $(wildcard $(srcdir)/daemon/*.c)) \
$(COMMON_SRC)
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=.lo)) $(COMPAT_OBJ)
HOST_SRC=smallapp/unbound-host.c
HOST_OBJ=$(addprefix $(BUILD),$(HOST_SRC:.c=.lo)) $(COMPAT_OBJ)
TESTBOUND_SRC=testcode/testbound.c testcode/ldns-testpkts.c \
daemon/worker.c daemon/daemon.c daemon/stats.c testcode/replay.c \
testcode/fake_event.c $(filter-out util/netevent.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)
LOCKVERIFY_SRC=testcode/lock_verify.c $(COMMON_SRC)
LOCKVERIFY_OBJ=$(addprefix $(BUILD),$(LOCKVERIFY_SRC:.c=.o)) $(COMPAT_OBJ)
PKTVIEW_SRC=testcode/pktview.c testcode/readhex.c $(COMMON_SRC)
PKTVIEW_OBJ=$(addprefix $(BUILD),$(PKTVIEW_SRC:.c=.o)) $(COMPAT_OBJ)
ALL_SRC=$(COMMON_SRC) $(UNITTEST_SRC) $(DAEMON_SRC) \
$(TESTBOUND_SRC) $(LOCKVERIFY_SRC)
ALL_OBJ=$(addprefix $(BUILD),$(ALL_SRC:.c=.o) \
$(addprefix compat/,$(LIBOBJS))) $(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=.lo)) $(COMPAT_OBJ)
PKTVIEW_SRC=testcode/pktview.c testcode/readhex.c smallapp/worker_cb.c \
$(COMMON_SRC)
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=.lo)) $(COMPAT_OBJ)
MEMSTATS_SRC=testcode/memstats.c smallapp/worker_cb.c $(COMMON_SRC)
MEMSTATS_OBJ=$(addprefix $(BUILD),$(MEMSTATS_SRC:.c=.lo)) $(COMPAT_OBJ)
ASYNCLOOK_SRC=testcode/asynclook.c
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=.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=.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) $(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) $(CFLAGS) $(LDFLAGS)
LINK_LIB=$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -release $(VERSION)
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) -version-number @LIBUNBOUND_CURRENT@:@LIBUNBOUND_REVISION@:@LIBUNBOUND_AGE@ -no-undefined
$(BUILD)%.o: $(srcdir)/%.c
.PHONY: clean realclean doc lint all install uninstall tests test download_ldns strip lib
$(BUILD)%.lo: $(srcdir)/%.c
$(INFO) Build $<
@if test ! -d $(dir $@); then $(INSTALL) -d $(patsubst %/,%,$(dir $@)); fi
@if test ! -z "$(ldnsdir)" -a ! -e $(ldnsdir)/include/ldns/ldns.h; \
then (cd $(ldnsdir); $(MAKE) copy-headers); fi
@-if test ! -d $(dir $@); then $(INSTALL) -d $(patsubst %/,%,$(dir $@)); fi
$Q$(COMPILE) -c $< -o $@
.PHONY: clean realclean doc lint all install uninstall
all: $(COMMON_OBJ) unbound unbound-checkconf lib unbound-host
all: $(COMMON_OBJ) unbound unittest testbound lock-verify pktview
tests: all unittest testbound lock-verify pktview signit memstats \
asynclook streamtcp perf delayer harvest
unbound: $(DAEMON_OBJ)
test: tests
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) -o $@ $^ $(LIBS)
$Q$(LINK_LIB) --export-symbols $(srcdir)/libunbound/ubsyms.def -o $@ $(sort $(LIBUNBOUND_OBJ)) -rpath $(libdir) $(LIBS)
unittest: $(UNITTEST_OBJ)
$(INFO) Link $@
$Q$(LINK) -o $@ $^ $(LIBS)
ifeq ($(patsubst ldns-src%,ldns-src,$(ldnsdir)),ldns-src)
ldnslib=$(ldnsdir)/lib/libldns.a
$(ldnslib):
@if test ! -z "$(ldnsdir)"; \
then (cd $(ldnsdir) && $(MAKE)); fi
else
ldnslib=
endif
testbound: $(TESTBOUND_OBJ)
unbound: $(DAEMON_OBJ) $(ldnslib)
$(INFO) Link $@
$Q$(LINK) -o $@ $^ $(LIBS)
$Q$(LINK) -o $@ $(sort $(DAEMON_OBJ)) $(LIBS)
lock-verify: $(LOCKVERIFY_OBJ)
unbound-checkconf: $(CHECKCONF_OBJ) $(ldnslib)
$(INFO) Link $@
$Q$(LINK) -o $@ $^ $(LIBS)
$Q$(LINK) -o $@ $(sort $(CHECKCONF_OBJ)) $(LIBS)
pktview: $(PKTVIEW_OBJ)
unbound-host: $(HOST_OBJ) libunbound.la $(ldnslib)
$(INFO) Link $@
$Q$(LINK) -o $@ $^ $(LIBS)
$Q$(LINK) -o $@ $(sort $(HOST_OBJ)) -L. -L.libs -lunbound $(LIBS)
unittest: $(UNITTEST_OBJ) $(ldnslib)
$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(UNITTEST_OBJ)) $(LIBS)
testbound: $(TESTBOUND_OBJ) $(ldnslib)
$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(TESTBOUND_OBJ)) $(LIBS)
lock-verify: $(LOCKVERIFY_OBJ) $(ldnslib)
$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(LOCKVERIFY_OBJ)) $(LIBS)
pktview: $(PKTVIEW_OBJ) $(ldnslib)
$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(PKTVIEW_OBJ)) $(LIBS)
signit: $(SIGNIT_OBJ) $(ldnslib)
$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(SIGNIT_OBJ)) $(LIBS)
memstats: $(MEMSTATS_OBJ) $(ldnslib)
$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(MEMSTATS_OBJ)) $(LIBS)
asynclook: $(ASYNCLOOK_OBJ) $(ldnslib) libunbound.la
$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(ASYNCLOOK_OBJ)) $(LIBS) -L. -L.libs -lunbound
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
@@ -116,28 +213,34 @@ pktview: $(PKTVIEW_OBJ)
util/config_file.c: util/configparser.h
util/configlexer.c: $(srcdir)/util/configlexer.lex util/configparser.h
$(INFO) Lex $<
@if test ! -d util; then $(INSTALL) -d util; fi
ifeq "$(strip $(LEX))" ":"
$Qecho "rebuild lexer, but no lex program, skipped"
else
@-if test ! -d util; then $(INSTALL) -d util; fi
$Qecho "#include \"util/configyyrename.h\"" > $@
$Q$(LEX) -t $< >> $@
endif
util/configparser.c util/configparser.h: $(srcdir)/util/configparser.y
$(INFO) Yacc $<
@if test ! -d util; then $(INSTALL) -d util; fi
@-if test ! -d util; then $(INSTALL) -d util; fi
$Q$(YACC) -d -o util/configparser.c $<
clean:
rm -f *.o *.d *.lo *~ tags
rm -f unbound unbound-checkconf unbound-host
rm -rf autom4te.cache .libs build doc/html
realclean: clean
rm -f config.status config.log config.h.in config.h
rm -f configure config.sub config.guess ltmain.sh aclocal.m4 libtool
rm -f util/configlexer.c util/configparser.c util/configparser.h
if test -d ldns-src; then rm -rf ldns-src; fi
rm -f Makefile
$(BUILD)%.lint: $(srcdir)/%.c
$(INFO) Lint $<
@if test ! -d $(dir $@); then $(INSTALL) -d $(patsubst %/,%,$(dir $@)); fi
@-if test ! -d $(dir $@); then $(INSTALL) -d $(patsubst %/,%,$(dir $@)); fi
$Q$(LINT) $(LINTFLAGS) -I. -I$(srcdir) -I$(ldnsdir)/include $<
$Qtouch $@
@@ -147,33 +250,71 @@ tags: $(srcdir)/*.[ch] $(srcdir)/*/*.[ch]
ctags -f $(srcdir)/tags $(srcdir)/*.[ch] $(srcdir)/*/*.[ch]
doc:
ifdef doxygen
$(doxygen) $(srcdir)/doc/unbound.doxygen
endif
if test -n "$(doxygen)"; then \
$(doxygen) $(srcdir)/doc/unbound.doxygen; fi
strip:
strip unbound
strip unbound-checkconf
strip unbound-host
install:
$(INSTALL) -d $(bindir)
$(INSTALL) -d $(mandir)
$(INSTALL) -d $(mandir)/man8
$(INSTALL) -d $(mandir)/man5
$(LIBTOOL) --mode=install cp unbound $(bindir)/unbound
$(INSTALL) -c -m 644 $(srcdir)/doc/unbound.8 $(mandir)/man8
$(INSTALL) -c -m 644 $(srcdir)/doc/unbound.conf.5 $(mandir)/man5
$(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 $(srcdir)/doc/unbound.8 $(DESTDIR)$(mandir)/man8
$(INSTALL) -c -m 644 $(srcdir)/doc/unbound-checkconf.8 $(DESTDIR)$(mandir)/man8
$(INSTALL) -c -m 644 $(srcdir)/doc/unbound.conf.5 $(DESTDIR)$(mandir)/man5
$(INSTALL) -c -m 644 $(srcdir)/doc/unbound-host.1 $(DESTDIR)$(mandir)/man1
$(INSTALL) -c -m 644 $(srcdir)/doc/libunbound.3 $(DESTDIR)$(mandir)/man3
if test ! -e $(DESTDIR)$(configfile); then $(INSTALL) -d `dirname $(DESTDIR)$(configfile)`; $(INSTALL) -c -m 644 $(srcdir)/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
rm -f -- $(mandir)/man8/unbound.8 $(mandir)/man5/unbound.conf.5
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 $(DESTDIR)$(configfile)`" , $(DESTDIR)$(configfile) by hand"
download_ldns:
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 $<
@if test ! -d $(dir $@); then $(INSTALL) -d $(patsubst %/,%,$(dir $@)); fi
@if test ! -z "$(ldnsdir)" -a ! -e $(ldnsdir)/include/ldns/ldns.h; \
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)
ifneq ($(MAKECMDGOALS),realclean)
ifeq ($(debug_enabled),yes)
-include $(addprefix $(BUILD),$(ALL_SRC:.c=.d))
endif
endif
endif
+10
View File
@@ -0,0 +1,10 @@
Unbound README
* ./configure && make && make install
* on BSDs and Solaris use gmake (GNU make).
* 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);
}
Vendored Executable
+1516
View File
File diff suppressed because it is too large Load Diff
+586
View File
@@ -0,0 +1,586 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Directory to chroot to */
#undef CHROOT_DIR
/* Pathname to the Unbound configuration file */
#undef CONFIGFILE
/* Define if you want to use debug lock checking (slow). */
#undef ENABLE_LOCK_CHECKS
/* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Whether the C compiler accepts the "format" attribute */
#undef HAVE_ATTR_FORMAT
/* Whether the C compiler accepts the "unused" attribute */
#undef HAVE_ATTR_UNUSED
/* 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
/* 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
/* Define to 1 if you have the `inet_ntop' function. */
#undef HAVE_INET_NTOP
/* Define to 1 if you have the `inet_pton' function. */
#undef HAVE_INET_PTON
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* 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
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#undef HAVE_MALLOC
/* Define to 1 if you have the `memmove' function. */
#undef HAVE_MEMMOVE
/* 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
/* Define to 1 if you have the <openssl/err.h> header file. */
#undef HAVE_OPENSSL_ERR_H
/* Define to 1 if you have the <openssl/rand.h> header file. */
#undef HAVE_OPENSSL_RAND_H
/* Define to 1 if you have the <openssl/ssl.h> header file. */
#undef HAVE_OPENSSL_SSL_H
/* Define if you have POSIX threads libraries and header files. */
#undef HAVE_PTHREAD
/* Define to 1 if the system has the type `pthread_rwlock_t'. */
#undef HAVE_PTHREAD_RWLOCK_T
/* 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
/* Define to 1 if you have the <stdarg.h> header file. */
#undef HAVE_STDARG_H
/* Define to 1 if you have the <stdbool.h> header file. */
#undef HAVE_STDBOOL_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strlcpy' function. */
#undef HAVE_STRLCPY
/* Define to 1 if you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H
/* 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
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* 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
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* 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
/* 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
/* use statistics for allocs and frees, for debug use */
#undef UNBOUND_ALLOC_STATS
/* define this to enable debug checks. */
#undef UNBOUND_DEBUG
/* 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
/* Define to 1 if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
#undef _LARGEFILE_SOURCE
/* Define for large files, on AIX-style hosts. */
#undef _LARGE_FILES
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `int' if <sys/types.h> doesn't define. */
#undef gid_t
/* in_addr_t */
#undef in_addr_t
/* in_port_t */
#undef in_port_t
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to `short' if <sys/types.h> does not define. */
#undef int16_t
/* Define to `int' if <sys/types.h> does not define. */
#undef int32_t
/* Define to `long long' if <sys/types.h> does not define. */
#undef int64_t
/* Define to `char' if <sys/types.h> does not define. */
#undef int8_t
/* Define to rpl_malloc if the replacement function should be used. */
#undef malloc
/* Define to `long int' if <sys/types.h> does not define. */
#undef off_t
/* 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
/* Define to 'int' if not defined */
#undef socklen_t
/* Define to `int' if <sys/types.h> does not define. */
#undef ssize_t
/* Define to `unsigned char' if <sys/types.h> does not define. */
#undef u_char
/* Define to `int' if <sys/types.h> doesn't define. */
#undef uid_t
/* Define to `unsigned short' if <sys/types.h> does not define. */
#undef uint16_t
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef uint32_t
/* Define to `unsigned long long' if <sys/types.h> does not define. */
#undef uint64_t
/* Define to `unsigned char' if <sys/types.h> does not define. */
#undef uint8_t
/* Define as `fork' if `vfork' does not work. */
#undef vfork
#ifndef UNBOUND_DEBUG
# define NDEBUG
#endif
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#if STDC_HEADERS
#include <stdlib.h>
#include <stddef.h>
#endif
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <errno.h>
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#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
#ifdef HAVE_OPENSSL_ERR_H
#include <openssl/err.h>
#endif
#ifdef HAVE_OPENSSL_RAND_H
#include <openssl/rand.h>
#endif
#ifdef HAVE_ATTR_FORMAT
# define ATTR_FORMAT(archetype, string_index, first_to_check) \
__attribute__ ((format (archetype, string_index, first_to_check)))
#else /* !HAVE_ATTR_FORMAT */
# define ATTR_FORMAT(archetype, string_index, first_to_check) /* empty */
#endif /* !HAVE_ATTR_FORMAT */
#if defined(DOXYGEN)
# define ATTR_UNUSED(x) x
#elif defined(__cplusplus)
# define ATTR_UNUSED(x)
#elif defined(HAVE_ATTR_UNUSED)
# define ATTR_UNUSED(x) x __attribute__((unused))
#else /* !HAVE_ATTR_UNUSED */
# define ATTR_UNUSED(x) x
#endif /* !HAVE_ATTR_UNUSED */
#ifndef HAVE_FSEEKO
#define fseeko fseek
#define ftello ftell
#endif /* HAVE_FSEEKO */
#if defined(HAVE_EVENT_H) && !defined(HAVE_EVENT_BASE_ONCE) && (defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS))
/* using version of libevent that is not threadsafe. */
# define LIBEVENT_SIGNAL_PROBLEM 1
#endif
#ifndef RAND_MAX
#define RAND_MAX 2147483647
#endif
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 256
#endif
#ifndef IPV6_MIN_MTU
#define IPV6_MIN_MTU 1280
#endif /* IPV6_MIN_MTU */
#ifndef CHECKED_INET6
# define CHECKED_INET6
# ifdef AF_INET6
# define INET6
# else
# define AF_INET6 28
# endif
#endif /* CHECKED_INET6 */
/* maximum nesting of included files */
#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
# define malloc(s) unbound_stat_malloc_log(s, __FILE__, __LINE__, __func__)
# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__)
# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__)
# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__)
void *unbound_stat_malloc(size_t size);
void *unbound_stat_calloc(size_t nmemb, size_t size);
void unbound_stat_free(void *ptr);
void *unbound_stat_realloc(void *ptr, size_t size);
void *unbound_stat_malloc_log(size_t size, const char* file, int line,
const char* func);
void *unbound_stat_calloc_log(size_t nmemb, size_t size, const char* file,
int line, const char* func);
void unbound_stat_free_log(void *ptr, const char* file, int line,
const char* func);
void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
int line, const char* func);
#endif /* UNBOUND_ALLOC_STATS */
/** default port for DNS traffic. */
#define UNBOUND_DNS_PORT 53
Vendored Executable
+1626
View File
File diff suppressed because it is too large Load Diff
Vendored Executable
+27187
View File
File diff suppressed because it is too large Load Diff
+503 -85
View File
@@ -1,12 +1,87 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.57)
AC_PREREQ(2.56)
AC_INIT(unbound, 0.4, wouter@nlnetlabs.nl, unbound)
AC_INIT(unbound,1.0.1, unbound-bugs@nlnetlabs.nl, unbound)
LIBUNBOUND_CURRENT=0
LIBUNBOUND_REVISION=13
LIBUNBOUND_AGE=0
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13: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 prefix to /usr/local
dnl
case "$prefix" in
NONE)
prefix="/usr/local"
;;
esac
#
# Determine configuration file
# 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_SUBST(ub_conf_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_DEFINE(WINVER, 0x0502, [the version of the windows API enabled])
dnl routine to help check for compiler flags.
AC_DEFUN([CHECK_COMPILER_FLAG],
[
@@ -90,6 +165,43 @@ 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"
#include <stdlib.h>
#include <ctype.h>
#include <sys/time.h>
#ifdef HAVE_TIME_H
#include <time.h>
#endif
#include <unistd.h>
#include <netdb.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
int test() {
int a;
char **opts = NULL;
struct timeval tv;
char *t;
time_t time = 0;
char *buf = NULL;
const char* str = NULL;
t = ctime_r(&time, buf);
tv.tv_usec = 10;
srandom(32);
a = getopt(2, opts, "a");
a = isascii(32);
str = gai_strerror(0);
return a;
}
], [CFLAGS="$CFLAGS -std=c99 -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE"])
CHECK_COMPILER_FLAG_NEEDED(-std=c99 -D__EXTENSIONS__ -D_BSD_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE,
[
#include "confdefs.h"
@@ -144,6 +256,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"
@@ -194,10 +317,21 @@ int test() {
CHECK_COMPILER_FLAG(xO4, [CFLAGS="$CFLAGS -xO4"])
CHECK_COMPILER_FLAG(xtarget=generic, [CFLAGS="$CFLAGS -xtarget=generic"])
# flag warnings.
CHECK_COMPILER_FLAG(W, [CFLAGS="$CFLAGS -W"])
CHECK_COMPILER_FLAG(Wall, [CFLAGS="$CFLAGS -Wall"])
CHECK_COMPILER_FLAG(Wextra, [CFLAGS="$CFLAGS -Wextra"])
CHECK_COMPILER_FLAG(Wdeclaration-after-statement, [CFLAGS="$CFLAGS -Wdeclaration-after-statement"])
AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [Enable debug warnings, asserts, makefile-dependencies]))
debug_enabled="$enable_debug"
AC_SUBST(debug_enabled)
case "$enable_debug" in
yes)
CHECK_COMPILER_FLAG(W, [CFLAGS="$CFLAGS -W"])
CHECK_COMPILER_FLAG(Wall, [CFLAGS="$CFLAGS -Wall"])
CHECK_COMPILER_FLAG(Wextra, [CFLAGS="$CFLAGS -Wextra"])
CHECK_COMPILER_FLAG(Wdeclaration-after-statement, [CFLAGS="$CFLAGS -Wdeclaration-after-statement"])
AC_DEFINE([UNBOUND_DEBUG], [], [define this to enable debug checks.])
;;
no|*)
# nothing to do.
;;
esac
AC_C_INLINE
@@ -248,11 +382,23 @@ AC_CHECK_FORMAT_ATTRIBUTE
AC_CHECK_UNUSED_ATTRIBUTE
if test "$srcdir" != "."; then
CPPFLAGS="$CPPFLAGS -I$srcdir";
CPPFLAGS="$CPPFLAGS -I$srcdir"
fi
# Use libtool
AC_CHECK_PROGS(libtool, [glibtool libtool15 libtool], [./libtool])
# skip these tests, we do not need them.
AC_DEFUN([AC_PROG_F77], [:])
AC_DEFUN([AC_PROG_FC], [:])
AC_DEFUN([AC_PROG_CXX], [:])
AC_DEFUN([AC_PROG_CXXCPP], [:])
AC_DEFUN([AC_PROG_OBJC], [:])
AC_DEFUN([AC_PROG_OBJCCPP], [:])
AC_DEFUN([AC_LIBTOOL_CXX], [:])
AC_DEFUN([AC_LIBTOOL_F77], [:])
# 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])
@@ -269,7 +415,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],,, [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)
@@ -287,6 +433,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
@@ -313,67 +466,38 @@ AC_INCLUDES_DEFAULT
#endif
])
# Check the type of struct msghdr msg_iovlen.
AC_MSG_CHECKING([sign of struct msghdr.msg_iovlen])
AC_RUN_IFELSE([
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
int main()
{
struct msghdr h;
h.msg_iovlen = -1;
if(10/h.msg_iovlen == 0) return 0; /* unsigned */
return 1; /* signed */
}
], [
# if compiled and exit status 0
cv_msgiovlen_type="unsigned" ], [
# not compiled or bad exit status
cv_msgiovlen_type="int" ],
# when cross compiling
[ cv_msgiovlen_type="int" ])
AC_MSG_RESULT($cv_msgiovlen_type)
AC_DEFINE_UNQUOTED([TYPE_MSGIOVLEN], $cv_msgiovlen_type, [Define to 'int' or type of struct msghdr.msg_iovlen.])
# 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"
# 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
])
AC_MSG_RESULT($ac_cv_c_yy_unput)
if test $ac_cv_c_yy_unput = yes; then
LEX="$LEX --nounput"
fi
])dnl
CHECK_YYUNPUT
# Checks for libraries.
AC_ARG_WITH(ssl, AC_HELP_STRING([--with-ssl=pathname],
[enable SSL (will check /usr/local/ssl
/usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr/sfw /usr)]),[
/usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr)]),[
],[
withval="yes"
])
if test x_$withval != x_no; then
AC_MSG_CHECKING(for SSL)
if test x_$withval = x_ -o x_$withval = x_yes; then
withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr/sfw /usr"
withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr"
fi
for dir in $withval; do
ssldir="$dir"
if test -f "$dir/include/openssl/ssl.h"; then
found_ssl="yes";
found_ssl="yes"
AC_DEFINE_UNQUOTED([HAVE_SSL], [], [Define if you have the SSL libraries installed.])
CPPFLAGS="$CPPFLAGS -I$ssldir/include";
CPPFLAGS="$CPPFLAGS -I$ssldir/include"
break;
fi
done
@@ -382,20 +506,49 @@ AC_ARG_WITH(ssl, AC_HELP_STRING([--with-ssl=pathname],
else
AC_MSG_RESULT(found in $ssldir)
HAVE_SSL=yes
LDFLAGS="$LDFLAGS -L$ssldir/lib";
RUNTIME_PATH="$RUNTIME_PATH -R$ssldir/lib"
AC_CHECK_LIB(crypto, HMAC_CTX_init,, [
LDFLAGS="$LDFLAGS -L$ssldir/lib"
if test "x$enable_rpath" = xyes; then
RUNTIME_PATH="$RUNTIME_PATH -R$ssldir/lib"
fi
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)
fi
AC_CHECK_HEADERS([openssl/ssl.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/err.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT])
# check for thread library.
AC_ARG_WITH(pthreads, AC_HELP_STRING([--with-pthreads],
[use pthreads library, or --without--pthreads to disable threading support.]),
[use pthreads library, or --without-pthreads to disable threading support.]),
[ ],[ withval="yes" ])
ub_have_pthreads=no
if test x_$withval != x_no; then
@@ -406,13 +559,14 @@ if test x_$withval != x_no; then
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
CC="$PTHREAD_CC"
ub_have_pthreads=yes
AC_CHECK_TYPES(pthread_spinlock_t,,,[#include <pthread.h>])
AC_CHECK_TYPES([pthread_spinlock_t, pthread_rwlock_t],,,[#include <pthread.h>])
])
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])
@@ -423,48 +577,95 @@ 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 libevent
AC_ARG_WITH(libevent, AC_HELP_STRING([--with-libevent=pathname],
[set path to libevent (will check /usr/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 /usr/lib /usr/pkg /usr/sfw /usr";
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
fi
for dir in $withval; do
thedir="$dir"
if test -f "$dir/include/event.h"; then
found_libevent="yes";
CPPFLAGS="$CPPFLAGS -I$thedir/include";
found_libevent="yes"
CPPFLAGS="$CPPFLAGS -I$thedir/include"
break;
fi
done
if test x_$found_libevent != x_yes; then
if test -f "$dir/event.h" -a -f "$dir/.libs/libevent.a"; 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";
LDFLAGS="$thedir/.libs/*.o $LDFLAGS";
CPPFLAGS="$CPPFLAGS -I$thedir -I$thedir/include"
BAK_LDFLAGS="$LDFLAGS"
# remove evdns from linking
mkdir build >/dev/null 2>&1
mkdir build/libevent >/dev/null 2>&1
mkdir build/libevent/.libs >/dev/null 2>&1
ev_files_o=`ls $thedir/*.o | grep -v evdns\.o`
ev_files_lo=`ls $thedir/*.lo | grep -v evdns\.lo`
ev_files_libso=`ls $thedir/.libs/*.o | grep -v evdns\.o`
cp $ev_files_o build/libevent
cp $ev_files_lo build/libevent
cp $ev_files_libso build/libevent/.libs
LATE_LDFLAGS="build/libevent/*.lo -lm"
LDFLAGS="build/libevent/*.o $LDFLAGS -lm"
else
AC_MSG_ERROR(Cannot find the libevent library in $withval)
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
large outgoing port ranges. ])
fi
else
AC_MSG_RESULT(found in $thedir)
LDFLAGS="$LDFLAGS -L$thedir/lib";
RUNTIME_PATH="$RUNTIME_PATH -R$thedir/lib"
LDFLAGS="$LDFLAGS -L$thedir/lib"
if test "x$enable_rpath" = xyes; then
RUNTIME_PATH="$RUNTIME_PATH -R$thedir/lib"
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
else
AC_DEFINE(USE_MINI_EVENT, 1, [Define if you want to use internal select based events])
fi
@@ -479,16 +680,132 @@ if test x_$enable_static_exe = x_yes; then
staticexe="-static"
fi
# check to see if libraries are needed for these functions.
AC_CHECK_LIB(socket, socket)
AC_CHECK_LIB(nsl, inet_pton)
# set lock checking if requested
AC_ARG_ENABLE(lock_checks, AC_HELP_STRING([--enable-lock-checks],
[ enable to check lock and unlock calls, for debug purposes ]),
, )
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
AC_ARG_ENABLE(alloc-checks, AC_HELP_STRING([--enable-alloc-checks],
[ enable to check memory allocation, for debug purposes ]),
, )
if test x_$enable_alloc_checks = x_yes; then
AC_DEFINE(UNBOUND_ALLOC_STATS, 1, [use statistics for allocs and frees, for debug use])
else
AC_FUNC_MALLOC
fi
AC_FUNC_CHOWN
AC_FUNC_FORK
AC_FUNC_MALLOC
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)
@@ -496,11 +813,8 @@ 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
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.
@@ -513,11 +827,38 @@ AC_ARG_WITH(ldns,
AC_SUBST(ldnsdir)
])
AC_CHECK_LIB(ldns, ldns_rr_new,, [AC_MSG_ERROR([Can't find ldns library])])
AC_CHECK_LIB(ldns, ldns_buffer_copy, [
dnl ldns was found, check compat functions
AC_CHECK_LIB(ldns, [ldns_rr_free])
] , [
dnl use the builtin ldns-src.tar.gz file to build ldns.
if test ! -f $srcdir/ldns-src.tar.gz; then
AC_MSG_ERROR([No ldns library found and no ldns-src.tar.gz, use --with-ldns=path.])
fi
echo "****************************************************************"
echo "*** ***"
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 scheduled after config.status])
AC_CONFIG_SUBDIRS([ldns-src/ldns*])
CPPFLAGS="-I$ldnsdir/include $CPPFLAGS"
LDFLAGS="$LDFLAGS $ldnsdir/*.lo"
AC_SUBST(ldnsdir)
])
LDFLAGS="$LATE_LDFLAGS $LDFLAGS"
AC_DEFINE_UNQUOTED([MAXSYSLOGMSGLEN], [512], [Define to the maximum message length to pass to syslog.])
AC_DEFINE_UNQUOTED([MAXSYSLOGMSGLEN], [5120], [Define to the maximum message length to pass to syslog.])
AH_BOTTOM([
#ifndef UNBOUND_DEBUG
# define NDEBUG
#endif
#include <stdio.h>
#include <string.h>
#include <unistd.h>
@@ -554,10 +895,26 @@ 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
#ifdef HAVE_OPENSSL_ERR_H
#include <openssl/err.h>
#endif
#ifdef HAVE_OPENSSL_RAND_H
#include <openssl/rand.h>
#endif
#ifdef HAVE_ATTR_FORMAT
# define ATTR_FORMAT(archetype, string_index, first_to_check) \
__attribute__ ((format (archetype, string_index, first_to_check)))
@@ -586,6 +943,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 */
@@ -603,36 +964,93 @@ 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
# define malloc(s) unbound_stat_malloc_log(s, __FILE__, __LINE__, __func__)
# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__)
# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__)
# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__)
void *unbound_stat_malloc(size_t size);
void *unbound_stat_calloc(size_t nmemb, size_t size);
void unbound_stat_free(void *ptr);
void *unbound_stat_realloc(void *ptr, size_t size);
void *unbound_stat_malloc_log(size_t size, const char* file, int line,
const char* func);
void *unbound_stat_calloc_log(size_t nmemb, size_t size, const char* file,
int line, const char* func);
void unbound_stat_free_log(void *ptr, const char* file, int line,
const char* func);
void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
int line, const char* func);
#endif /* UNBOUND_ALLOC_STATS */
/** default port for DNS traffic. */
#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
+250
View File
@@ -0,0 +1,250 @@
/*
* daemon/acl_list.h - client access control storage for the server.
*
* Copyright (c) 2007, 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 file helps the server keep out queries from outside sources, that
* should not be answered.
*/
#include "config.h"
#include "daemon/acl_list.h"
#include "util/regional.h"
#include "util/log.h"
#include "util/config_file.h"
#include "util/net_help.h"
int
acl_list_cmp(const void* k1, const void* k2)
{
struct acl_addr* n1 = (struct acl_addr*)k1;
struct acl_addr* n2 = (struct acl_addr*)k2;
int r = sockaddr_cmp_addr(&n1->addr, n1->addrlen, &n2->addr,
n2->addrlen);
if(r != 0) return r;
if(n1->net < n2->net)
return -1;
if(n1->net > n2->net)
return 1;
return 0;
}
struct acl_list*
acl_list_create()
{
struct acl_list* acl = (struct acl_list*)calloc(1,
sizeof(struct acl_list));
if(!acl)
return NULL;
acl->region = regional_create();
if(!acl->region) {
acl_list_delete(acl);
return NULL;
}
return acl;
}
void
acl_list_delete(struct acl_list* acl)
{
if(!acl)
return;
regional_destroy(acl->region);
free(acl->tree);
free(acl);
}
/** insert new address into acl_list structure */
static int
acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr,
socklen_t addrlen, int net, enum acl_access control,
int complain_duplicates)
{
struct acl_addr* node = regional_alloc(acl->region,
sizeof(struct acl_addr));
if(!node)
return 0;
node->node.key = node;
memcpy(&node->addr, addr, addrlen);
node->addrlen = addrlen;
node->net = net;
node->parent = NULL;
node->control = control;
if(!rbtree_insert(acl->tree, &node->node)) {
if(complain_duplicates)
verbose(VERB_QUERY, "duplicate acl address ignored.");
}
return 1;
}
/** apply acl_list string */
static int
acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
int complain_duplicates)
{
struct sockaddr_storage addr;
int net;
socklen_t addrlen;
enum acl_access control;
if(strcmp(s2, "allow") == 0)
control = acl_allow;
else if(strcmp(s2, "deny") == 0)
control = acl_deny;
else if(strcmp(s2, "refuse") == 0)
control = acl_refuse;
else {
log_err("access control type %s unknown", str);
return 0;
}
if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
log_err("cannot parse access control: %s %s", str, s2);
return 0;
}
if(!acl_list_insert(acl, &addr, addrlen, net, control,
complain_duplicates)) {
log_err("out of memory");
return 0;
}
return 1;
}
/** read acl_list config */
static int
read_acl_list(struct acl_list* acl, struct config_file* cfg)
{
struct config_str2list* p;
for(p = cfg->acls; p; p = p->next) {
log_assert(p->str && p->str2);
if(!acl_list_str_cfg(acl, p->str, p->str2, 1))
return 0;
}
return 1;
}
/** initialise parent pointers in the tree */
static void
acl_list_init_parents(struct acl_list* acl)
{
struct acl_addr* node, *prev = NULL, *p;
int m;
RBTREE_FOR(node, struct acl_addr*, acl->tree) {
node->parent = NULL;
if(!prev || prev->addrlen != node->addrlen) {
prev = node;
continue;
}
m = addr_in_common(&prev->addr, prev->net, &node->addr,
node->net, node->addrlen);
/* sort order like: ::/0, 1::/2, 1::/4, ... 2::/2 */
/* find the previous, or parent-parent-parent */
for(p = prev; p; p = p->parent)
if(p->net <= m) {
/* ==: since prev matched m, this is closest*/
/* <: prev matches more, but is not a parent,
* this one is a (grand)parent */
node->parent = p;
break;
}
prev = node;
}
}
int
acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
{
regional_free_all(acl->region);
free(acl->tree);
acl->tree = rbtree_create(acl_list_cmp);
if(!acl->tree)
return 0;
if(!read_acl_list(acl, cfg))
return 0;
/* 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, "127.0.0.0/8", "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;
}
enum acl_access
acl_list_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
socklen_t addrlen)
{
/* lookup in the tree */
rbnode_t* res = NULL;
struct acl_addr* result;
struct acl_addr key;
key.node.key = &key;
memcpy(&key.addr, addr, addrlen);
key.addrlen = addrlen;
key.net = (addr_is_ip6(addr, addrlen)?128:32);
if(rbtree_find_less_equal(acl->tree, &key, &res)) {
/* exact */
result = (struct acl_addr*)res;
return result->control;
} else {
/* smaller element (or no element) */
int m;
result = (struct acl_addr*)res;
if(!result || result->addrlen != addrlen)
return acl_deny;
/* count number of bits matched */
m = addr_in_common(&result->addr, result->net, addr,
key.net, addrlen);
while(result) { /* go up until addr is inside netblock */
if(result->net <= m)
return result->control;
result = result->parent;
}
}
return acl_deny;
}
size_t
acl_list_get_mem(struct acl_list* acl)
{
if(!acl) return 0;
return sizeof(*acl) + regional_get_mem(acl->region);
}
+134
View File
@@ -0,0 +1,134 @@
/*
* daemon/acl_list.h - client access control storage for the server.
*
* Copyright (c) 2007, 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 file keeps track of the list of clients that are allowed to
* access the server.
*/
#ifndef DAEMON_ACL_LIST_H
#define DAEMON_ACL_LIST_H
#include "util/rbtree.h"
struct config_file;
struct regional;
/**
* Enumeration of access control options for an address range.
* Allow or deny access.
*/
enum acl_access {
/** disallow any access whatsoever, drop it */
acl_deny = 0,
/** disallow access, send a polite 'REFUSED' reply */
acl_refuse,
/** allow full access */
acl_allow
};
/**
* Access control storage structure
*/
struct acl_list {
/** regional for allocation */
struct regional* region;
/**
* Tree of the addresses that are allowed/blocked.
* contents of type acl_addr.
*/
rbtree_t* tree;
};
/**
*
* An address span with access control information
*/
struct acl_addr {
/** redblacktree node, key is this structure: addr and addrlen, net */
rbnode_t node;
/** parent node in acl tree that encompasses this entry */
struct acl_addr* parent;
/** address */
struct sockaddr_storage addr;
/** length of addr */
socklen_t addrlen;
/** netblock size */
int net;
/** access control on this netblock */
enum acl_access control;
};
/**
* Create acl structure
* @return new structure or NULL on error.
*/
struct acl_list* acl_list_create();
/**
* Delete acl structure.
* @param acl: to delete.
*/
void acl_list_delete(struct acl_list* acl);
/**
* Process access control config.
* @param acl: where to store.
* @param cfg: config options.
* @return 0 on error.
*/
int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg);
/**
* Lookup address to see its access control status.
* @param acl: structure for address storage.
* @param addr: address to check
* @param addrlen: length of addr.
* @return: what to do with message from this address.
*/
enum acl_access acl_list_lookup(struct acl_list* acl,
struct sockaddr_storage* addr, socklen_t addrlen);
/**
* Get memory used by acl structure.
* @param acl: structure for address storage.
* @return bytes in use.
*/
size_t acl_list_get_mem(struct acl_list* acl);
/** compare two acl list entries */
int acl_list_cmp(const void* k1, const void* k2);
#endif /* DAEMON_ACL_LIST_H */
+153 -58
View File
@@ -39,12 +39,10 @@
* The daemon consists of global settings and a number of workers.
*/
/** buffer size for network connections */
#define BUFSZ 65552
#include "config.h"
#include "daemon/daemon.h"
#include "daemon/worker.h"
#include "daemon/acl_list.h"
#include "util/log.h"
#include "util/config_file.h"
#include "util/data/msgreply.h"
@@ -52,8 +50,10 @@
#include "services/listen_dnsport.h"
#include "services/cache/rrset.h"
#include "services/cache/infra.h"
#include "services/localzone.h"
#include "services/modstack.h"
#include "util/module.h"
#include "iterator/iterator.h"
#include "util/random.h"
#include <signal.h>
/** How many quit requests happened. */
@@ -69,18 +69,31 @@ static int sig_record_reload = 0;
static RETSIGTYPE record_sigh(int sig)
{
#ifdef LIBEVENT_SIGNAL_PROBLEM
verbose(VERB_OPS, "quit on signal, no cleanup and statistics, "
"because installed libevent version is not threadsafe");
exit(0);
#endif
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);
}
@@ -94,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));
}
@@ -107,10 +131,12 @@ signal_handling_record()
static void
signal_handling_playback(struct worker* wrk)
{
if(sig_record_quit)
worker_sighandler(SIGTERM, wrk);
#ifdef SIGHUP
if(sig_record_reload)
worker_sighandler(SIGHUP, wrk);
#endif
if(sig_record_quit)
worker_sighandler(SIGTERM, wrk);
sig_record_quit = 0;
sig_record_reload = 0;
}
@@ -120,18 +146,40 @@ 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;
daemon->num_modules = 0;
modstack_init(&daemon->mods);
if(!(daemon->env = (struct module_env*)calloc(1,
sizeof(*daemon->env)))) {
free(daemon);
return NULL;
}
alloc_init(&daemon->superalloc, NULL, 0);
daemon->acl = acl_list_create();
if(!daemon->acl) {
free(daemon->env);
free(daemon);
return NULL;
}
return daemon;
}
@@ -149,69 +197,89 @@ daemon_open_shared_ports(struct daemon* daemon)
}
/**
* Desetup the modules, deinit, delete.
* @param daemon: the daemon.
*/
static void
daemon_desetup_modules(struct daemon* daemon)
{
int i;
for(i=0; i<daemon->num_modules; i++) {
(*daemon->modfunc[i]->deinit)(daemon->env, i);
}
daemon->num_modules = 0;
free(daemon->modfunc);
daemon->modfunc = 0;
}
/**
* Setup modules. Assigns ids and calls module_init.
* Setup modules. setup module stack.
* @param daemon: the daemon
*/
static void daemon_setup_modules(struct daemon* daemon)
{
int i;
if(daemon->num_modules != 0)
daemon_desetup_modules(daemon);
/* fixed setup of the modules */
daemon->num_modules = 1;
daemon->modfunc = (struct module_func_block**)calloc((size_t)
daemon->num_modules, sizeof(struct module_func_block*));
if(!daemon->modfunc) {
fatal_exit("malloc failure allocating function callbacks");
}
daemon->modfunc[0] = iter_get_funcblock();
daemon->env->cfg = daemon->cfg;
daemon->env->alloc = &daemon->superalloc;
daemon->env->worker = NULL;
daemon->env->send_packet = &worker_send_packet;
daemon->env->send_query = &worker_send_query;
for(i=0; i<daemon->num_modules; i++) {
log_info("init module %d: %s", i, daemon->modfunc[i]->name);
if(!(*daemon->modfunc[i]->init)(daemon->env, i)) {
fatal_exit("module init for module %s failed",
daemon->modfunc[i]->name);
daemon->env->need_to_validate = 0; /* set by module init below */
if(!modstack_setup(&daemon->mods, daemon->cfg->module_conf,
daemon->env)) {
fatal_exit("failed to setup modules");
}
}
/**
* 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);
}
/**
@@ -246,14 +314,13 @@ 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;
close_other_pipes(worker->daemon, worker->thread_num);
#endif
if(!worker_init(worker, worker->daemon->cfg, worker->daemon->ports,
BUFSZ, 0))
if(!worker_init(worker, worker->daemon->cfg, worker->daemon->ports, 0))
fatal_exit("Could not initialize thread");
worker_work(worker);
@@ -274,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;
@@ -298,7 +365,7 @@ daemon_stop_others(struct daemon* daemon)
worker_send_cmd(daemon->workers[i],
daemon->workers[0]->front->udp_buff, worker_cmd_quit);
}
/** wait for them to quit */
/* wait for them to quit */
for(i=1; i<daemon->num; i++) {
/* join it to make sure its dead */
verbose(VERB_ALGO, "join %d", i);
@@ -311,6 +378,12 @@ void
daemon_fork(struct daemon* daemon)
{
log_assert(daemon);
if(!acl_list_apply_cfg(daemon->acl, daemon->cfg))
fatal_exit("Could not setup access control list");
if(!(daemon->local_zones = local_zones_create()))
fatal_exit("Could not create local zones: out of memory");
if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg))
fatal_exit("Could not set up local zones");
/* setup modules */
daemon_setup_modules(daemon);
@@ -328,21 +401,19 @@ daemon_fork(struct daemon* daemon)
/* Special handling for the main thread. This is the thread
* that handles signals.
*/
if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports,
BUFSZ, 1))
if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports, 1))
fatal_exit("Could not initialize main thread");
signal_handling_playback(daemon->workers[0]);
/* Start resolver service on main thread. */
log_info("start of service (%s).", PACKAGE_STRING);
worker_work(daemon->workers[0]);
log_info("service stopped (%s).", PACKAGE_STRING);
/* we exited! a signal happened! Stop other threads */
daemon_stop_others(daemon);
if(daemon->workers[0]->need_to_restart)
daemon->need_to_exit = 0;
else daemon->need_to_exit = 1;
daemon->need_to_exit = daemon->workers[0]->need_to_exit;
}
void
@@ -354,6 +425,15 @@ daemon_cleanup(struct daemon* daemon)
don't die on multiple reload signals for example. */
signal_handling_record();
log_thread_set(NULL);
/* clean up caches because
* a) RRset IDs will be recycled after a reload, causing collisions
* b) validation config can change, thus rrset, msg, keycache clear
* The infra cache is kept, the timing and edns info is still valid */
slabhash_clear(&daemon->env->rrset_cache->table);
slabhash_clear(daemon->env->msg_cache);
local_zones_delete(daemon->local_zones);
daemon->local_zones = NULL;
/* key cache is cleared by module desetup during next daemon_init() */
for(i=0; i<daemon->num; i++)
worker_delete(daemon->workers[i]);
free(daemon->workers);
@@ -367,17 +447,32 @@ daemon_delete(struct daemon* daemon)
{
if(!daemon)
return;
daemon_desetup_modules(daemon);
modstack_desetup(&daemon->mods, daemon->env);
listening_ports_free(daemon->ports);
if(daemon->env) {
slabhash_delete(daemon->env->msg_cache);
rrset_cache_delete(daemon->env->rrset_cache);
infra_delete(daemon->env->infra_cache);
}
ub_randfree(daemon->rand);
alloc_clear(&daemon->superalloc);
free(daemon->cwd);
acl_list_delete(daemon->acl);
free(daemon->pidfile);
free(daemon->env);
free(daemon);
/* libcrypto cleanup */
/* CONF_modules_unload(1); */
EVP_cleanup();
/* ENGINE_cleanup(); */
CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */
ERR_remove_state(0);
ERR_free_strings();
RAND_cleanup();
checklock_stop();
#ifdef USE_WINSOCK
if(WSACleanup() != 0) {
log_err("Could not WSACleanup: %s",
wsa_strerror(WSAGetLastError()));
}
#endif
}
+12 -6
View File
@@ -44,12 +44,16 @@
#include "util/locks.h"
#include "util/alloc.h"
#include "services/modstack.h"
struct config_file;
struct worker;
struct listen_port;
struct slabhash;
struct module_env;
struct rrset_cache;
struct acl_list;
struct local_zones;
struct ub_randstate;
/**
* Structure holding worker list.
@@ -58,8 +62,6 @@ struct rrset_cache;
struct daemon {
/** The config settings */
struct config_file* cfg;
/** current working directory */
char* cwd;
/** pidfile that is used */
char* pidfile;
/** port number that has ports opened. */
@@ -72,14 +74,18 @@ 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*/
struct module_env* env;
/** number of modules active, ids from 0 to num-1. */
int num_modules;
/** the module callbacks, array of num_modules length */
struct module_func_block** modfunc;
/** stack of module callbacks */
struct module_stack mods;
/** access control, which client IPs are allowed to connect */
struct acl_list* acl;
/** local authority zones */
struct local_zones* local_zones;
};
/**
+5 -3
View File
@@ -46,7 +46,7 @@
void server_stats_init(struct server_stats* stats)
{
memset(stats, 0, sizeof(stats));
memset(stats, 0, sizeof(*stats));
}
void server_stats_querymiss(struct server_stats* stats, struct worker* worker)
@@ -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?
+163 -50
View File
@@ -52,19 +52,40 @@
#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;
/** print usage. */
static void usage()
{
printf("usage: unbound [options]\n");
printf("usage: unbound [options]\n");
printf(" start unbound daemon DNS resolver.\n");
printf("-h this help\n");
printf("-c file config file to read, unbound.conf(5).\n");
printf("-c file config file to read instead of %s\n", CONFIGFILE);
printf(" file format is described in unbound.conf(5).\n");
printf("-d do not fork into the background.\n");
printf("-v verbose (multiple times increase verbosity)\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);
}
@@ -73,21 +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 + TCP_ACCEPT_COUNT: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 outnum = cfg->outgoing_num_ports*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;
@@ -95,34 +123,38 @@ 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);
}
#else
(void)cfg;
#endif /* HAVE_GETRLIMIT */
}
/** to changedir, logfile */
/** set verbosity, check rlimits, cache settings */
static void
apply_dir(struct daemon* daemon, struct config_file* cfg, int cmdline_verbose)
apply_settings(struct daemon* daemon, struct config_file* cfg,
int cmdline_verbose)
{
/* apply if they have changed */
daemon->cfg = cfg;
verbosity = cmdline_verbose + cfg->verbosity;
if(cfg->directory && cfg->directory[0]) {
if(!daemon->cwd || strcmp(daemon->cwd, cfg->directory) != 0) {
if(chdir(cfg->directory)) {
log_err("Could not chdir to %s: %s",
cfg->directory, strerror(errno));
}
free(daemon->cwd);
if(!(daemon->cwd = strdup(cfg->directory)))
log_err("cwd: malloc failed");
}
}
config_apply(cfg);
if(!daemon->env->msg_cache ||
cfg->msg_cache_size != slabhash_get_size(daemon->env->msg_cache) ||
cfg->msg_cache_slabs != daemon->env->msg_cache->size) {
@@ -144,6 +176,7 @@ apply_dir(struct daemon* daemon, struct config_file* cfg, int cmdline_verbose)
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.
@@ -179,7 +212,8 @@ readpid (const char* file)
return -1;
}
pid = strtol(pidbuf, &t, 10);
pidbuf[sizeof(pidbuf)-1] = 0;
pid = (pid_t)strtol(pidbuf, &t, 10);
if (*t && *t != '\n') {
return -1;
@@ -216,7 +250,12 @@ static void
checkoldpid(struct config_file* cfg)
{
pid_t old;
if((old = readpid(cfg->pidfile)) != -1) {
char* file = cfg->pidfile;
if(cfg->chrootdir && cfg->chrootdir[0] &&
strncmp(file, cfg->chrootdir, strlen(cfg->chrootdir))==0) {
file += strlen(cfg->chrootdir);
}
if((old = readpid(file)) != -1) {
/* see if it is still alive */
if(kill(old, 0) == 0 || errno == EPERM)
log_warn("unbound is already running as pid %u.",
@@ -225,11 +264,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()) {
@@ -243,8 +284,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);
@@ -252,43 +295,103 @@ 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) */
memset(&uid, 112, sizeof(uid));
memset(&gid, 112, sizeof(gid));
log_assert(cfg);
/* daemonize last to be able to print error to user */
if(cfg->chrootdir && cfg->chrootdir[0])
if(chroot(cfg->chrootdir))
fatal_exit("unable to chroot: %s", strerror(errno));
if(cfg->username && cfg->username[0]) {
struct passwd *pwd;
if((pwd = getpwnam(cfg->username)) == NULL)
fatal_exit("user '%s' does not exist.", cfg->username);
if(setgid(pwd->pw_gid) != 0)
fatal_exit("unable to set group id: %s", strerror(errno));
if(setuid(pwd->pw_uid) != 0)
fatal_exit("unable to set user id: %s", strerror(errno));
uid = pwd->pw_uid;
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",
cfg->username, strerror(errno));
if(setuid(uid) != 0)
fatal_exit("unable to set user id of %s: %s",
cfg->username, strerror(errno));
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);
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]) {
writepid(cfg->pidfile, getpid());
if(!(daemon->pidfile = strdup(cfg->pidfile)))
char* pf = cfg->pidfile;
if(cfg->chrootdir && cfg->chrootdir[0] &&
strncmp(pf, cfg->chrootdir, strlen(cfg->chrootdir))==0)
pf += strlen(cfg->chrootdir);
writepid(pf, getpid());
if(!(daemon->pidfile = strdup(pf)))
log_err("pidf: malloc failed");
}
#else
(void)daemon;
#endif
}
/**
@@ -299,7 +402,7 @@ do_chroot(struct daemon* daemon, struct config_file* cfg, int debug_mode)
* @param debug_mode: if set, do not daemonize.
*/
static void
run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode)
run_daemon(char* cfgfile, int cmdline_verbose, int debug_mode)
{
struct config_file* cfg = NULL;
struct daemon* daemon = NULL;
@@ -309,23 +412,27 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode)
fatal_exit("alloc failure");
while(!daemon->need_to_exit) {
if(done_chroot)
log_info("Restart of %s.", PACKAGE_STRING);
else log_info("Start of %s.", PACKAGE_STRING);
verbose(VERB_OPS, "Restart of %s.", PACKAGE_STRING);
else verbose(VERB_OPS, "Start of %s.", PACKAGE_STRING);
/* 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);
apply_dir(daemon, cfg, cmdline_verbose);
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 */
daemon_fork(daemon);
@@ -355,11 +462,16 @@ int
main(int argc, char* argv[])
{
int c;
const char* cfgfile = NULL;
char* cfgfile = CONFIGFILE;
int cmdline_verbose = 0;
int debug_mode = 0;
log_init(NULL);
#ifdef HAVE_SBRK
/* take debug snapshot of heap */
unbound_start_brk = sbrk(0);
#endif
log_init(NULL, 0, NULL);
/* parse the options */
while( (c=getopt(argc, argv, "c:dhv")) != -1) {
switch(c) {
@@ -389,5 +501,6 @@ main(int argc, char* argv[])
}
run_daemon(cfgfile, cmdline_verbose, debug_mode);
log_init(NULL, 0, NULL); /* close logfile */
return 0;
}
+540 -128
View File
File diff suppressed because it is too large Load Diff
+43 -11
View File
@@ -57,10 +57,7 @@ struct config_file;
struct daemon;
struct listen_port;
struct ub_randstate;
struct region;
/** size of table used for random numbers. large to be more secure. */
#define RND_STATE_SIZE 256
struct regional;
/** worker commands */
enum worker_commands {
@@ -89,24 +86,30 @@ 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. */
struct comm_point* cmd_com;
/** timer for statistics */
struct comm_timer* stat_timer;
/** number of requests that can be handled by this worker */
size_t request_size;
/** random() table for this worker. */
struct ub_randstate* rndstate;
/** do we need to restart (instead of exit) ? */
int need_to_restart;
/** do we need to restart or quit (on signal) */
int need_to_exit;
/** allocation cache for this thread */
struct alloc_cache alloc;
/** per thread statistics */
struct server_stats stats;
/** thread scratch region */
struct region* scratchpad;
/** thread scratch regional */
struct regional* scratchpad;
/** module environment passed to modules, changed for this thread */
struct module_env env;
@@ -117,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.
@@ -127,12 +132,11 @@ struct worker* worker_create(struct daemon* daemon, int id);
* @param worker: worker to initialize, created with worker_create.
* @param cfg: configuration settings.
* @param ports: list of shared query ports.
* @param buffer_size: size of datagram buffer.
* @param do_sigs: if true, worker installs signal handlers.
* @return: false on error.
*/
int worker_init(struct worker* worker, struct config_file *cfg,
struct listen_port* ports, size_t buffer_size, int do_sigs);
struct listen_port* ports, int do_sigs);
/**
* Make worker work.
@@ -193,4 +197,32 @@ struct outbound_entry* worker_send_query(uint8_t* qname, size_t qnamelen,
struct sockaddr_storage* addr, socklen_t addrlen,
struct module_qstate* q);
/**
* process control messages from the main thread.
* @param c: comm point to read from.
* @param arg: worker.
* @param error: error status of comm point.
* @param reply_info: not used.
*/
int worker_handle_control_cmd(struct comm_point* c, void* arg, int error,
struct comm_reply* reply_info);
/** handles callbacks from listening event interface */
int worker_handle_request(struct comm_point* c, void* arg, int error,
struct comm_reply* repinfo);
/** process incoming replies from the network */
int worker_handle_reply(struct comm_point* c, void* arg, int error,
struct comm_reply* reply_info);
/** process incoming serviced query replies from the network */
int worker_handle_service_reply(struct comm_point* c, void* arg, int error,
struct comm_reply* reply_info);
/** cleanup the cache to remove all rrset IDs from it, arg is worker */
void worker_alloc_cleanup(void* arg);
/** statistics timer callback handler */
void worker_stat_timer_cb(void* arg);
#endif /* DAEMON_WORKER_H */
+13 -4
View File
@@ -1,7 +1,16 @@
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.
Ondřej Surý - running coverity analysis tool on 0.9 dev version.
Alexander Gall - multihomed, anycast testing of unbound resolver server.
+1282
View File
File diff suppressed because it is too large Load Diff
+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
+61 -11
View File
@@ -4,40 +4,90 @@ 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/
* Needs the following libraries
* 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.
* 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.
* --with-ldns=/path/to/ldns
If ldns is not detected on the system, a prepackaged tarball
of the ldns library is used to compile and statically link against.
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.
--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, and uses Solaris thr library or no threading.
Without this option the pthreads library is detected automatically.
This disables pthreads. Without this option the pthreads library
is detected automatically. Use this option to disable threading
altogether, or, on Solaris, also use --with(out)-solaris-threads.
* --enable-static-exe
This enables a debug option to statically link, against ldns and
libevent libraries.
* --enable-lock-checks
This enables a debug option to check lock and unlock calls. It needs
a recent pthreads library to work.
* --enable-alloc-checks
This enables a debug option to check malloc (calloc, realloc, free).
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.
* 'make test' attempts to run a series of tests, depending on the support
programs that are installed.
Known issues
------------
o If libevent is older (1.3 and before), unbound will exit instead of reload
o If libevent is older (before 1.3c), unbound will exit instead of reload
on sighup. On a restart 'did not exit gracefully last time' warning is
printed. Perform ./configure --with-libevent=no or update libevent, rerun
configure and recompile unbound to make sighup work correctly.
It is strongly suggested to use the latest version of libevent (1.4 or more)
on Solaris, because of fixes in the solaris event port code in libevent.
o If you receive no answers deploying unbound on a private network.
Check that the zone you configure as a stub zone is correct, listing working
ip-addresses. Check that the NS data in the zone, those hostnames, are
in fact those same, working, ip-addresses. Unbound will fetch the NS data
from the zone and use that information in preference to the config
information.
o If you are not receiving the correct source IP address on replies (e.g.
you are running a multihomed, anycast server), the interface-automatic
option can be enabled to set socket options to achieve the correct
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.
@@ -45,4 +95,4 @@ o Other code origins are from the NSD (NLnet Labs) and LDNS (NLnet Labs)
projects. Such as buffer, region-allocator and red-black tree code.
o See Credits file for contributors.
* mailto:wouter@nlnetlabs.nl
* mailto:unbound-bugs@nlnetlabs.nl
+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).
+16 -2
View File
@@ -1,6 +1,20 @@
README unbound tests
There is a test setup for unbound.
There is a test setup for unbound. Use
make test
To make and run the tests. The results are summarized at the end.
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.
@@ -8,4 +22,4 @@ testcode/ contains scripts and c code for the tests.
do-tests.sh : runs all the tests in the testdata directory.
testbed.sh : compiles on a set of (user specific) hosts and runs do-tests.
Tests are run using tpkg.
Tests are run using testcode/mini_tpkg.sh.
+70 -24
View File
@@ -1,30 +1,76 @@
TODO items.
o use real entropy to make random (ID, port) numbers more random.
o in production mode, do not free memory on exit. In debug mode, test leaks.
o profile memory allocation, and if performance issues, use special memory
allocator. For example, with caches per thread.
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 fallback without EDNS if result is NOTIMPL, now only on FORMERR like in java.
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 donotqueryaddresses allow specification of subnets, use trie to store.
extend default list to contain illegal ip4 and ip6 addresses.
o memory profile; and if needed put serviced queries under qstate->region
and special purpose region code, reuse blocks, shrink if too big.
o check query, option to enforce presence of qdsection in noerror answers.
o configuration option where port 53 is used for send and receive, no other
ports are used.
o prime sequence in multiple queries, if glue missing from prime sequence.
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 (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 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 NSID rfc 5001 support.
o timers rfc 5011 support.
o Treat YXDOMAIN from a DNAME properly, in iterator (not throwaway), validator.
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 (option) proactively prime root, stubs and trust anchors, feature.
early failure, faster on first query, but more traffic.
o On Windows use CryptGenRandom() to get random seed for arc4random.
o library add convenience functions for A, AAAA, PTR, getaddrinfo, libresolve.
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 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.
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.
-173
View File
@@ -1,173 +0,0 @@
#
# Example configuration file.
#
# See unbound.conf(5) man page.
#
# this is a comment.
#Use this to include other text into the file.
#include: "otherfile.conf"
# The server clause sets the main parameters.
server:
# whitespace is not necessary, but looks cleaner.
# verbosity number, 0 is least verbose. 1 is default.
verbosity: 2
# number of threads to create. 1 disables threading.
# num-threads: 1
# specify the interfaces to answer queries from by ip-address.
# If you give none the default (all) interface is used.
# specify every interface on a new 'interface:' labelled line.
# interface: 192.0.2.153
# interface: 192.0.2.154
# interface: 2001:DB8::5
# port to answer queries from
# port: 53
# 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 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
# number of outgoing simultaneous tcp buffers to hold per thread.
# outgoing-num-tcp: 10
# the amount of memory to use for the message cache.
# in bytes. default is 4 Mb
# msg-cache-size: 4194304
# the number of slabs to use for the message cache.
# the number of slabs must be a power of 2.
# more slabs reduce lock contention, but fragment memory usage.
# msg-cache-slabs: 4
# the number of queries that a thread gets to service.
# num-queries-per-thread: 1024
# the amount of memory to use for the RRset cache.
# in bytes. default is 4 Mb
# rrset-cache-size: 4194304
# the number of slabs to use for the RRset cache.
# the number of slabs must be a power of 2.
# more slabs reduce lock contention, but fragment memory usage.
# rrset-cache-slabs: 4
# the time to live (TTL) value for cached roundtrip times and
# EDNS version information for hosts. In seconds.
# infra-host-ttl: 900
# the time to live (TTL) value for cached lame delegations. In sec.
# infra-lame-ttl: 900
# the number of slabs to use for the Infrastructure cache.
# the number of slabs must be a power of 2.
# more slabs reduce lock contention, but fragment memory usage.
# infra-cache-slabs: 4
# the maximum number of hosts that are cached (roundtrip times, EDNS).
# infra-cache-numhosts: 1000
# the maximum number of lame zones per host that are cached.
# infra-cache-numlame: 1000
# Enable IPv4, "yes" or "no".
# do-ip4: yes
# Enable IPv6, "yes" or "no".
# do-ip6: yes
# Enable UDP, "yes" or "no".
# do-udp: yes
# Enable TCP, "yes" or "no".
# do-tcp: yes
# 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.
# chroot: "/some/directory"
# if given, user privileges are dropped (after binding port),
# and the given username is assumed. Default is nothing "".
# username: "unbound"
# the working directory.
# directory: "/etc/unbound"
# the log file, "" means log to stderr.
# logfile: ""
# the pid file.
# pidfile: "unbound.pid"
# enable to not answer id.server and hostname.bind queries.
# hide-identity: no
# enable to not answer version.server and version.bind queries.
# hide-version: no
# the identity to report. Leave "" or default to return hostname.
# identity: ""
# the version to report. Leave "" or default to return package version.
# version: ""
# the target fetch policy.
# series of integers describing the policy per dependency depth.
# The number of values in the list determines the maximum dependency
# depth the recursor will pursue before giving up. Each integer means:
# -1 : fetch all targets opportunistically,
# 0: fetch on demand,
# positive value: fetch that many targets opportunistically.
# Enclose the list of numbers between quotes ("").
# target-fetch-policy: "3 2 1 0 0"
# Harden against very small EDNS buffer sizes.
# harden-short-bufsize: no
# Harden against unseemly large queries.
# harden-large-queries: no
# Harden against out of zone rrsets, to avoid spoofing attempts.
# harden-glue: yes
# Do not query the following addresses. No DNS queries are sent there.
# List one address per entry. To block other ports than the default
# DNS port, use "1.2.3.4@123" to block port 123 for 1.2.3.4.
# do-not-query-address: 127.0.0.1
# do-not-query-address: ::1
# Stub zones.
# Create entries like below, to make all queries for 'example.com' and
# 'example.org' go to the given list of nameservers. list zero or more
# nameservers by hostname or by ipaddress.
# stub-zone:
# name: "example.com"
# stub-addr: 192.0.2.68
# stub-zone:
# name: "example.org"
# stub-host: ns.example.com.
# Forward zones
# Create entries like below, to make all queries for 'example.com' and
# 'example.org' go to the given list of servers. These servers have to handle
# recursion to other nameservers. List zero or more nameservers by hostname
# or by ipaddress. Use an entry with name "." to forward all queries.
# forward-zone:
# name: "example.com"
# forward-addr: 192.0.2.68
# forward-addr: 192.0.2.73@5355 # forward to port 5355.
# forward-zone:
# name: "example.org"
# forward-host: fwd.example.com
+357
View File
@@ -0,0 +1,357 @@
#
# Example configuration file.
#
# See unbound.conf(5) man page.
#
# this is a comment.
#Use this to include other text into the file.
#include: "otherfile.conf"
# The server clause sets the main parameters.
server:
# whitespace is not necessary, but looks cleaner.
# verbosity number, 0 is least verbose. 1 is default.
verbosity: 1
# 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
# specify the interfaces to answer queries from by ip-address.
# The default is to listen to localhost (127.0.0.1 and ::1).
# specify 0.0.0.0 and ::0 to bind to all available interfaces.
# specify every interface on a new 'interface:' labelled line.
# The listen interfaces are not changed on reload, only on restart.
# interface: 192.0.2.153
# interface: 192.0.2.154
# interface: 2001:DB8::5
# enable this feature to copy the source address of queries to reply.
# Socket options not be supported on all platforms. experimental.
# interface-automatic: no
# port to answer queries from
# port: 53
# specify the interfaces to send outgoing queries to authoritative
# server from by ip-address. If none, the default (all) interface
# is used. Specify every interface on a 'outgoing-interface:' line.
# outgoing-interface: 192.0.2.153
# outgoing-interface: 2001:DB8::5
# outgoing-interface: 2001:DB8::6
# 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
# 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
# number of incoming simultaneous tcp buffers to hold per thread.
# incoming-num-tcp: 10
# buffer size for handling DNS data. No messages larger than this
# size can be sent or received, by UDP or TCP. In bytes.
# msg-buffer-size: 65552
# the amount of memory to use for the message cache.
# plain value in bytes or you can append k, m or G. default is "4Mb".
# msg-cache-size: 4m
# the number of slabs to use for the message cache.
# the number of slabs must be a power of 2.
# more slabs reduce lock contention, but fragment memory usage.
# msg-cache-slabs: 4
# the number of queries that a thread gets to service.
# num-queries-per-thread: 1024
# the amount of memory to use for the RRset cache.
# plain value in bytes or you can append k, m or G. default is "4Mb".
# rrset-cache-size: 4m
# the number of slabs to use for the RRset cache.
# the number of slabs must be a power of 2.
# more slabs reduce lock contention, but fragment memory usage.
# rrset-cache-slabs: 4
# the time to live (TTL) value cap for RRsets and messages in the
# cache. Items are not cached for longer. In seconds.
# cache-max-ttl: 86400
# the time to live (TTL) value for cached roundtrip times and
# EDNS version information for hosts. In seconds.
# infra-host-ttl: 900
# the time to live (TTL) value for cached lame delegations. In sec.
# infra-lame-ttl: 900
# the number of slabs to use for the Infrastructure cache.
# the number of slabs must be a power of 2.
# more slabs reduce lock contention, but fragment memory usage.
# infra-cache-slabs: 4
# the maximum number of hosts that are cached (roundtrip times, EDNS).
# infra-cache-numhosts: 10000
# the maximum size of the lame zones cached per host. in bytes.
# infra-cache-lame-size: 10k
# Enable IPv4, "yes" or "no".
# do-ip4: yes
# Enable IPv6, "yes" or "no".
# do-ip6: yes
# Enable UDP, "yes" or "no".
# do-udp: yes
# 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.
# Choose deny (drop message), refuse (polite error reply), allow.
# access-control: 0.0.0.0/0 refuse
# access-control: 127.0.0.0/8 allow
# access-control: ::0/0 refuse
# access-control: ::1 allow
# access-control: ::ffff:127.0.0.1 allow
# 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 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"
# 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".
# logfile: ""
# Log to syslog(3) if yes. The log facility LOG_DAEMON is used to
# log to, with identity "unbound". If yes, it overrides the logfile.
# use-syslog: yes
# the pid file.
# pidfile: "@UNBOUND_PIDFILE@"
# file to read root hints from.
# get one from ftp://FTP.INTERNIC.NET/domain/named.cache
# root-hints: ""
# enable to not answer id.server and hostname.bind queries.
# hide-identity: no
# enable to not answer version.server and version.bind queries.
# hide-version: no
# the identity to report. Leave "" or default to return hostname.
# identity: ""
# the version to report. Leave "" or default to return package version.
# version: ""
# the target fetch policy.
# series of integers describing the policy per dependency depth.
# The number of values in the list determines the maximum dependency
# depth the recursor will pursue before giving up. Each integer means:
# -1 : fetch all targets opportunistically,
# 0: fetch on demand,
# positive value: fetch that many targets opportunistically.
# Enclose the list of numbers between quotes ("").
# target-fetch-policy: "3 2 1 0 0"
# Harden against very small EDNS buffer sizes.
# harden-short-bufsize: no
# Harden against unseemly large queries.
# harden-large-queries: no
# Harden against out of zone rrsets, to avoid spoofing attempts.
# harden-glue: yes
# Harden against receiving dnssec-stripped data. If you turn it
# off, failing to validate dnskey data for a trustanchor will
# trigger insecure mode for that zone (like without a trustanchor).
# 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
# do-not-query-address: ::1
# if yes, the above default do-not-query-address entries are present.
# if no, localhost can be queried (for testing and debugging).
# do-not-query-localhost: yes
# module configuration of the server. A string with identifiers
# separated by spaces. "iterator" or "validator iterator"
# module-config: "validator iterator"
# File with trusted keys for validation. Specify more than one file
# with several entries, one file per entry.
# Zone file format, with DS and DNSKEY entries.
# trust-anchor-file: ""
# Trusted key for validation. DS or DNSKEY. specify the RR on a
# single line, surrounded by "". TTL is ignored. class is IN default.
# (These examples are from August 2007 and may not be valid anymore).
# trust-anchor: "nlnetlabs.nl. DNSKEY 257 3 5 AQPzzTWMz8qSWIQlfRnPckx2BiVmkVN6LPupO3mbz7FhLSnm26n6iG9N Lby97Ji453aWZY3M5/xJBSOS2vWtco2t8C0+xeO1bc/d6ZTy32DHchpW 6rDH1vp86Ll+ha0tmwyy9QP7y2bVw5zSbFCrefk8qCUBgfHm9bHzMG1U BYtEIQ=="
# trust-anchor: "jelte.nlnetlabs.nl. DS 42860 5 1 14D739EB566D2B1A5E216A0BA4D17FA9B038BE4A"
# File with trusted keys for validation. Specify more than one file
# with several entries, one file per entry. Like trust-anchor-file
# but has a different file format. Format is BIND-9 style format,
# the trusted-keys { name flag proto algo "key"; }; clauses are read.
# trusted-keys-file: ""
# Override the date for validation with a specific fixed date.
# Do not set this unless you are debugging signature inception
# and expiration. "" or "0" turns the feature off.
# val-override-date: ""
# The time to live for bogus data, rrsets and messages. This avoids
# some of the revalidation, until the time interval expires. in secs.
# val-bogus-ttl: 900
# Should additional section of secure message also be kept clean of
# unsecure data. Useful to shield the users of this validator from
# potential bogus data in the additional section. All unsigned data
# in the additional section is removed from secure messages.
# val-clean-additional: yes
# Turn permissive mode on to permit bogus messages. Thus, messages
# for which security checks failed will be returned to clients,
# instead of SERVFAIL. It still performs the security checks, which
# result in interesting log files and possibly the AD bit in
# replies if the message is found secure. The default is off.
# val-permissive-mode: no
# It is possible to configure NSEC3 maximum iteration counts per
# keysize. Keep this table very short, as linear search is done.
# A message with an NSEC3 with larger count is marked insecure.
# List in ascending order the keysize and count values.
# val-nsec3-keysize-iterations: "1024 150 2048 500 4096 2500"
# the amount of memory to use for the key cache.
# plain value in bytes or you can append k, m or G. default is "4Mb".
# key-cache-size: 4m
# the number of slabs to use for the key cache.
# the number of slabs must be a power of 2.
# more slabs reduce lock contention, but fragment memory usage.
# key-cache-slabs: 4
# a number of locally served zones can be configured.
# local-zone: <zone> <type>
# local-data: "<resource record string>"
# o deny serves local data (if any), else, drops queries.
# o refuse serves local data (if any), else, replies with error.
# o static serves local data, else, nxdomain or nodata answer.
# o transparent serves local data, else, resolves normally .
# o redirect serves the zone data for any subdomain in the zone.
# o nodefault can be used to normally resolve AS112 zones.
#
# defaults are localhost address, reverse for 127.0.0.1 and ::1
# and nxdomain for AS112 zones. If you configure one of these zones
# the default content is omitted, or you can omit it with 'nodefault'.
#
# If you configure local-data without specifying local-zone, by
# default a transparent local-zone is created for the data.
#
# You can add locally served data with
# local-zone: "local." static
# local-data: "mycomputer.local. IN A 192.0.2.51"
# local-data: 'mytext.local TXT "content of text record"'
#
# You can override certain queries with
# local-data: "adserver.example.com A 127.0.0.1"
#
# You can redirect a domain to a fixed address with
# (this makes example.com, www.example.com, etc, all go to 192.0.2.3)
# local-zone: "example.com" redirect
# local-data: "example.com A 192.0.2.3"
# Stub zones.
# Create entries like below, to make all queries for 'example.com' and
# 'example.org' go to the given list of nameservers. list zero or more
# nameservers by hostname or by ipaddress.
# stub-zone:
# name: "example.com"
# stub-addr: 192.0.2.68
# stub-zone:
# name: "example.org"
# stub-host: ns.example.com.
# Forward zones
# Create entries like below, to make all queries for 'example.com' and
# 'example.org' go to the given list of servers. These servers have to handle
# recursion to other nameservers. List zero or more nameservers by hostname
# or by ipaddress. Use an entry with name "." to forward all queries.
# forward-zone:
# name: "example.com"
# forward-addr: 192.0.2.68
# forward-addr: 192.0.2.73@5355 # forward to port 5355.
# forward-zone:
# name: "example.org"
# forward-host: fwd.example.com
+335
View File
@@ -0,0 +1,335 @@
.TH "libunbound" "3" "@date@" "NLnet Labs" "unbound @version@"
.\"
.\" libunbound.3 -- unbound library functions manual
.\"
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
.\"
.\" See LICENSE for the license.
.\"
.\"
.SH "NAME"
.LP
.B libunbound,
.B unbound.h,
.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_ctx *\fR
\fBub_ctx_create\fR(\fIvoid\fR);
.LP
\fIvoid\fR
\fBub_ctx_delete\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\fBub_ctx_set_option\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR opt, \fIchar*\fR val);
.LP
\fIint\fR
\fBub_ctx_config\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_ctx_set_fwd\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR addr);
.LP
\fIint\fR
\fBub_ctx_resolvconf\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_ctx_hosts\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_ctx_add_ta\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR ta);
.LP
\fIint\fR
\fBub_ctx_add_ta_file\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_ctx_trustedkeys\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_ctx_debugout\fR(\fIstruct ub_ctx*\fR ctx, \fIFILE*\fR out);
.LP
\fIint\fR
\fBub_ctx_debuglevel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR d);
.LP
\fIint\fR
\fBub_ctx_async\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR dothread);
.LP
\fIint\fR
\fBub_poll\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\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_result**\fR result);
.LP
\fIint\fR
\fBub_resolve_async\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR name,
.br
\fIint\fR rrtype, \fIint\fR rrclass, \fIvoid*\fR mydata,
.br
\fIub_callback_t\fR callback, \fIint*\fR async_id);
.LP
\fIint\fR
\fBub_cancel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR async_id);
.LP
\fIvoid\fR
\fBub_resolve_free\fR(\fIstruct ub_result*\fR result);
.LP
\fIconst char *\fR
\fBub_strerror\fR(\fIint\fR err);
.SH "DESCRIPTION"
.LP
.B Unbound
is an implementation of a DNS resolver, that does caching and
DNSSEC validation. This is the library API, for using the \-lunbound library.
The server daemon is described in \fIunbound\fR(8).
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_ctx\fR to keep context
between calls. The user must maintain it, creating it with
.B ub_ctx_create
and deleting it with
.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
The functions are thread\-safe, and a context an be used in a threaded (as
well as in a non\-threaded) environment. Also resolution (and validation)
can be performed blocking and non\-blocking (also called asynchronous).
The async method returns from the call immediately, so that processing
can go on, while the results become available later.
.P
The functions are discussed in turn below.
.SH "FUNCTIONS"
.TP
.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_ctx_delete
Delete validation context and free associated resources.
Outstanding async queries are killed and callbacks are not called for them.
.TP
.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_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
DNSSEC capable, validation may fail. Can be called several times, in
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_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.
Only nameservers are picked up, the searchdomain, ndots and other
settings from \fIresolv.conf\fR(5) are ignored.
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_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_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_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_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_ctx_async
Set a context behaviour for asynchronous action.
if set to true, enables threading and a call to
.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_resolve_async
calls have been made have no effect (delete and re\-create the context
to change).
.TP
.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_process
to do callbacks.
.TP
.B ub_wait
Wait for a context to finish with results. Calls
.B ub_process
after the wait for you. After the wait, there are no more outstanding
asynchronous queries.
.TP
.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_process\fR to continue processing.
.TP
.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_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.
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_resolve_async
Perform asynchronous resolution and validation of the target name.
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
a function declared as
.IP
void my_callback_function(void* my_arg, int err,
.br
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_cancel
Cancel an async query in progress.
.TP
.B ub_resolve_free
Free struct ub_result contents after use.
.TP
.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_result\fR. The result structure contains the following entries.
.P
.nf
struct ub_result {
char* qname; /* text string, original question */
int qtype; /* type code asked for */
int qclass; /* class code asked for */
char** data; /* array of rdata items, NULL terminated*/
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 */
int bogus; /* true if a security failure happened */
};
.fi
.P
If both secure and bogus are false, security was not enabled for the
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_strerror
to obtain a readable error string.
.B ub_strerror
returns a zero terminated string.
.B ub_ctx_create
returns NULL on an error (a malloc failure).
.B ub_poll
returns true if some information may be available, false otherwise.
.B ub_fd
returns a file descriptor or -1 on error.
.SH "SEE ALSO"
\fIunbound.conf\fR(5),
\fIunbound\fR(8).
.SH "AUTHORS"
.B Unbound
developers are mentioned in the CREDITS file in the distribution.
+71 -16
View File
@@ -30,16 +30,19 @@ Roughly the boxes are as follows:
Twice as long; one box for module layout, one box for iterator module.
0.5 Validator - validator module.
0.6 Bigger and better - Operational useful features (config, log, memory)
0.7 Local zones feature - localzones stubzones fwdzones, no leak rfc1918.
0.7 Put to a limited audience.
gamma/alpha core functionality test release, to a small audience.
partial functionality. For more extensive use and testing.
0.8 Local zones feature - localzones stubzones fwdzones, no leak rfc1918.
views support; for selective recursive service.
0.8 Library use - resolver validator lib (and test apps)
0.9 Corner cases - be able to resolve in the wild. Run fuzzers.
0.9 Library use - resolver validator lib (and test apps)
0.10 Corner cases - be able to resolve in the wild. Run fuzzers.
Run as many tests as we can think of.
Go through logs and check for long, unresolved cases
Use profiler.
0.10 Beta release. Run shadow for a resolver in production for several
0.11 Beta release. Run shadow for a resolver in production for several
weeks.
0.11 Features features
0.12 Features features
aggressive negative caching for NSEC, NSEC3.
multiple queries per question, server exploration, server selection.
option to use real entropy for randomness (mix it in once in a while).
@@ -142,28 +145,76 @@ Styleguide:
* Test resolver.
* Speed test.
*** Put to a limited audience
* The alpha/gamma core functionality, svn access to limited audience.
* Support features and requests as they arise.
* Provide real-world experiences.
*** Bigger and Better
* Config file syntax checker program. Tests on checker.
* Logging first class feature with config options.
X with logfile turnover to avoid Gbs of logs.
* use syslog optional.
* donotqueryaddresses with trie for blocking entire netblocks.
* Memory overhaul, special allocators for hashtable caches, and mesh qstates.
* keep a preallocated list of region-chunks per worker thread.
* allocate region struct and cleanup list in region itself; use
linked list cleanup list. unit test on this. do not call region
to avoid name-collision with nsd regions, 'regional'.
* read root hints from file.
* failover to next server in 1 second, instead of 100 seconds on one server.
X failure to return answer, w. reason (donotq, noanswer servers, cannot
find servers, validationfail w.classification, error),
with threadno, starttime and endtime and qname/type/class, prime/qflags,
from-clients, from-internal, has-subrequests, a nice error report,
so that an excerpt from those times can be made from the logs.
logfileparsing tool that makes these excerpts and emails them.
Not done; user can change verbosity and kill -HUP.
* clear cache as a callback from the new-rrset-id routine.
X make overload mode work; phase 0 all ok, phase 1 some threads close ports,
to let other threads pick up work. phase 2, all threads closed, so all open
the ports again and drop all non-cache-reply queries.
Keep mutexed num-overloaded-threads counter. thread incs it when it hits
max number of user queries serviced in mesh. threads decs it when it
falls below 90% of the max. if incs, and not all threads closed, phase 1,
else, phase 2 start is broadcast over command pipes. if decs, open ports
if phase 1, start servicing, phase is 0 again. Make robust against delays.
readme: max about 1 second worth of incoming queries, 10k perhaps,
or 1/number of seconds it takes start up of 10k.
Not done. Implement drop when full.
* the source includes a copy of the ldns lib for ease of building by
new users. Detect system installed ldns, if installed ldns is OK; use
dynamic linking against it, otherwise static linking against packaged ldns.
* no greedy TTL algo (and test).
* maximum TTL, cap incoming values, and config option.
*** Local zones feature.
* Build in local zone features. First the total stop for1912.
* Then 'local content' for minimal serving of localhost.localdomain,
and so on.
* Remember jakob's diagram.
* views support, selective recursive service
* Remember jakob's diagram. views support, selective recursive service:
* acl for allowed recursion (RD=1), then drop or refused query.
like 10.0.0.0/8 allow, 0.0.0.0/0 refuse, ... in-order.
perhaps also, same list to disallow RD=0 access, like;
allow_recursion, drop_recursion, refuse_recursion, drop_all
* static answers for queries, fixed RRs from cfg, option
query for that RR returns answer with that RR.
* blacklist (return fixed nxdomain for domain and below), option
can be used to block AS112 traffic, option to unblock a zone.
* after checking acl, do iter: static, blacklist, forwards, recurse.
* Forward-local-zone to NSD.
- include in package, autoforkexec on localhost to do so.
- in package, autoforkexec on localhost to do so.
- not included. Not necessary for localhost and AS112 service.
* forward local zone to remote server.
- not included. Not necessary for localhost and AS112 service.
* stub zones - send queries for a zone to configged nameserver.
- Can be used for complicated setups. So, run auth server on a
different port or pc, and stub it on the resolver. Resolver is
not auth for zones, but resolution works. This enforces the split
of recursive and auth servers.
* test local zones
* for speed
* for correctness on corner cases
* for validation
* in case you get data on localzone in an answer (from rootserver).
*** Library use
* Create library that can do:
@@ -181,6 +232,9 @@ Styleguide:
* read a file with cache contents and settings, provide fake
environment for module-handle-state-X functions, then check
resulting module state structure to correct answer.
* speed test cache responses.
* using two servers, compare answer differences between bind and unbound.
this gives false differences due to changes in the rest of internet.
*** Beta release.
* Run shadow for a resolver in production for several weeks.
@@ -190,14 +244,15 @@ Styleguide:
*** Features features
* aggressive negative caching for NSEC, NSEC3.
* multiple queries per question, server exploration, server selection.
* option to use real entropy for randomness (mix it in once in a while).
* check query, enforce qdsection, checking for forgery-resilience.
* NSID support.
* support TSIG on queries, for validating resolver deployment.
* Be able to prime roots using several queries (like, get only NS first).
* Nicer statistics
* private TTL, dTLS features.
* retry-mode, where a bogus result triggers a retry-mode query, where a list
of responses over a time interval is collected, and each is validated.
or try in TCP mode. Do not 'try all servers several times', since we must
not create packet storms with operator errors.
* draft-timers, DLV features.
treeshrew/
validator/ *.c *.h
@@ -254,10 +309,10 @@ treeshrew/
unbound.c for validating caching recursive dns server.
scheduler.c for the modules.
libunbound-all/
libunbound/
app linkable. Can be configged to do whatever,
validator, iterator, validating iterator, forwarding stub.
libunbound-fwd/
libforwardbound/
app linkable forwarding stub. Small lib.
ask_cachor/ *.c *.h
+128 -1
View File
@@ -34,7 +34,7 @@ then interface with the modules to perform the necessary processing.
In Section 2 the origins of the Unbound project are documented. Section
3 lists the goals, while Section 4 lists the explicit non-goals of the
project.
project. Section 5 discusses choices made during development.
2. History
@@ -79,3 +79,130 @@ o An authoritative name server.
o Too many Features.
5. Choices
----------
o rfc2181 decourages duplicates RRs in RRsets. unbound does not create
duplicates, but when presented with duplicates on the wire from the
authoritative servers, does not perform duplicate removal.
It does do some rrsig duplicate removal, in the msgparser, for dnssec qtype
rrsig and any, because of special rrsig processing in the msgparser.
o The harden-glue feature, when yes all out of zone glue is deleted, when
no out of zone glue is used for further resolving, is more complicated
than that, see below.
Main points:
* rfc2182 trust handling is used.
* data is let through only in very specific cases
* spoofability remains possible.
Not all glue is let through (despite the name of the option). Only glue
which is present in a delegation, of type A and AAAA, where the name is
present in the NS record in the authority section is let through.
The glue that is let through is stored in the cache (marked as 'from the
additional section'). And will then be used for sending queries to. It
will not be present in the reply to the client (if RD is off).
A direct query for that name will attempt to get a msg into the message
cache. Since A and AAAA queries are not synthesized by the unbound cache,
this query will be (eventually) sent to the authoritative server and its
answer will be put in the cache, marked as 'from the answer section' and
thus remove the 'from the additional section' data, and this record is
returned to the client.
The message has a TTL smaller or equal to the TTL of the answer RR.
If the cache memory is low; the answer RR may be dropped, and a glue
RR may be inserted, within the message TTL time, and thus return the
spoofed glue to a client. When the message expires, it is refetched and
the cached RR is updated with the correct content.
The server can be spoofed by getting it to visit a especially prepared
domain. This domain then inserts an address for another authoritative
server into the cache, when visiting that other domain, this address may
then be used to send queries to. And fake answers may be returned.
If the other domain is signed by DNSSEC, the fakes will be detected.
In summary, the harden glue feature presents a security risk if
disabled. Disabling the feature leads to possible better performance
as more glue is present for the recursive service to use. The feature
is implemented so as to minimise the security risk, while trying to
keep this performance gain.
o The method by which dnssec-lameness is detected is not secure. DNSSEC lame
is when a server has the zone in question, but lacks dnssec data, such as
signatures. The method to detect dnssec lameness looks at nonvalidated
data from the parent of a zone. This can be used, by spoofing the parent,
to create a false sense of dnssec-lameness in the child, or a false sense
or dnssec-non-lameness in the child. The first results in the server marked
lame, and not used for 900 seconds, and the second will result in a
validator failure (SERVFAIL again), when the query is validated later on.
Concluding, a spoof of the parent delegation can be used for many cases
of denial of service. I.e. a completely different NS set could be returned,
or the information withheld. All of these alterations can be caught by
the validator if the parent is signed, and result in 900 seconds bogus.
The dnssec-lameness detection is used to detect operator failures,
before the validator will properly verify the messages.
Also for zones for which no chain of trust exists, but a DS is given by the
parent, dnssec-lameness detection enables. This delivers dnssec to our
clients when possible (for client validators).
The following issue needs to be resolved:
a server that serves both a parent and child zone, where
parent is signed, but child is not. The server must not be marked
lame for the parent zone, because the child answer is not signed.
Instead of a false positive, we want false negatives; failure to
detect dnssec-lameness is less of a problem than marking honest
servers lame. dnssec-lameness is a config error and deserves the trouble.
So, only messages that identify the zone are used to mark the zone
lame. The zone is identified by SOA or NS RRsets in the answer/auth.
That includes almost all negative responses and also A, AAAA qtypes.
That would be most responses from servers.
For referrals, delegations that add a single label can be checked to be
from their zone, this covers most delegation-centric zones.
So possibly, for complicated setups, with multiple (parent-child) zones
on a server, dnssec-lameness detection does not work - no dnssec-lameness
is detected. Instead the zone that is dnssec-lame becomes bogus.
o authority features.
This is a recursive server, and authority features are out of scope.
However, some authority features are expected in a recursor. Things like
localhost, reverse lookup for 127.0.0.1, or blocking AS112 traffic.
Also redirection of domain names with fixed data is needed by service
providers. Limited support is added specifically to address this.
Adding full authority support, requires much more code, and more complex
maintenance.
The limited support allows adding some static data (for localhost and so),
and to respond with a fixed rcode (NXDOMAIN) for domains (such as AS112).
You can put authority data on a separate server, and set the server in
unbound.conf as stub for those zones, this allows clients to access data
from the server without making unbound authoritative for the zones.
o the access control denies queries before any other processing.
This denies queries that are not authoritative, or version.bind, or any.
And thus prevents cache-snooping (denied hosts cannot make non-recursive
queries and get answers from the cache).
o If a client makes a query without RD bit, in the case of a returned
message from cache which is:
answer section: empty
auth section: NS record present, no SOA record, no DS record,
maybe NSEC or NSEC3 records present.
additional: A records or other relevant records.
A SOA record would indicate that this was a NODATA answer.
A DS records would indicate a referral.
Absence of NS record would indicate a NODATA answer as well.
Then the receiver does not know whether this was a referral
with attempt at no-DS proof) or a nodata answer with attempt
at no-data proof. It could be determined by attempting to prove
either condition; and looking if only one is valid, but both
proofs could be valid, or neither could be valid, which creates
doubt. This case is validated by unbound as a 'referral' which
ascertains that RRSIGs are OK (and not omitted), but does not
check NSEC/NSEC3.
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 query name is used in preference to the casing
of the authority server. This is the same as BIND. RFC4343 allows either
behaviour.
+43
View File
@@ -0,0 +1,43 @@
.TH "unbound-checkconf" "8" "@date@" "NLnet Labs" "unbound @version@"
.\"
.\" unbound-checkconf.8 -- unbound configuration checker manual
.\"
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
.\"
.\" See LICENSE for the license.
.\"
.\"
.SH "NAME"
.LP
unbound-checkconf
\- Check unbound configuration file for errors.
.SH "SYNOPSIS"
.B unbound-checkconf
.RB [ \-h ]
.IR cfgfile
.SH "DESCRIPTION"
.B Unbound-checkconf
checks the configuration file for the
\fIunbound\fR(8)
DNS resolver for syntax and other errors.
The config file syntax is described in
\fIunbound.conf\fR(5).
.P
The available options are:
.TP
.B \-h
Show the version and commandline option help.
.TP
.I cfgfile
The config file to read with settings for unbound. It is checked.
If omitted, the config file at the default location is checked.
.SH "EXIT CODE"
The unbound-checkconf program exits with status code 1 on error,
0 for a correct config file.
.SH "FILES"
.TP
.I @ub_conf_file@
unbound configuration file.
.SH "SEE ALSO"
\fIunbound.conf\fR(5),
\fIunbound\fR(8).
+106
View File
@@ -0,0 +1,106 @@
.TH "unbound\-host" "1" "@date@" "NLnet Labs" "unbound @version@"
.\"
.\" unbound-host.1 -- unbound DNS lookup utility
.\"
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
.\"
.\" See LICENSE for the license.
.\"
.\"
.SH "NAME"
.LP
.B unbound\-host
\- unbound DNS lookup utility
.SH "SYNOPSIS"
.LP
.B unbound\-host
.RB [ \-vdhr ]
.RB [ \-c
.IR class ]
.RB [ \-t
.IR type ]
.I hostname
.RB [ \-y
.IR key ]
.RB [ \-f
.IR keyfile ]
.RB [ \-F
.IR namedkeyfile ]
.RB [ \-C
.IR configfile ]
.SH "DESCRIPTION"
.LP
.B Unbound\-host
uses the unbound validating resolver to query for the hostname and display
results. With the \fB\-v\fR option it displays validation
status: secure, insecure, bogus (security failure).
.P
The available options are:
.TP
.I hostname
This name is resolved (looked up in the DNS).
If a IPv4 or IPv6 address is given, a reverse lookup is performed.
.TP
.B \-h
Show the version and commandline option help.
.TP
.B \-v
Enable verbose output and it shows validation results, on every line.
Secure means that the NXDOMAIN (no such domain name), nodata (no such data)
or positive data response validated correctly with one of the keys.
Insecure means that that domain name has no security set up for it.
Bogus (security failure) means that the response failed one or more checks,
it is likely wrong, outdated, tampered with, or broken.
.TP
.B \-d
Enable debug output to stderr. One \-d shows what the resolver and validator
are doing and may tell you what is going on. More times, \-d \-d, gives a
lot of output, with every packet sent and received.
.TP
.B \-c \fIclass
Specify the class to lookup for, the default is IN the internet class.
.TP
.B \-t \fItype
Specify the type of data to lookup. The default looks for IPv4, IPv6 and
mail handler data, or domain name pointers for reverse queries.
.TP
.B \-y \fIkey
Specify a public key to use as trust anchor. This is the base for a chain
of trust that is built up from the trust anchor to the response, in order
to validate the response message. Can be given as a DS or DNSKEY record.
For example \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD".
.TP
.B \-f \fIkeyfile
Reads keys from a file. Every line has a DS or DNSKEY record, in the format
as for \-y. The zone file format, the same as dig and drill produce.
.TP
.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. The keys shown below are fakes, thus a security failure
is encountered.
.P
$ unbound\-host www.example.com
.P
$ unbound\-host \-v \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD" www.example.com
.P
$ unbound\-host \-v \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD" 192.0.2.153
.SH "EXIT CODE"
The unbound\-host program exits with status code 1 on error,
0 on no error. The data may not be available on exit code 0, exit code 1
means the lookup encountered a fatal error.
.SH "SEE ALSO"
\fIunbound.conf\fR(5),
\fIunbound\fR(8).
-51
View File
@@ -1,51 +0,0 @@
.\"
.\" unbound.8 -- unbound manual
.\"
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
.\"
.\" See LICENSE for the license.
.\"
.\"
.Dd @date@
.Dt unbound 8
.Sh NAME
unbound
.Nd Unbound DNS validating resolver @version@.
.Sh SYNOPSIS
.Nm unbound
.Op Fl h
.Op Fl d
.Op Fl v
.Op Fl c Ar cfgfile
.Sh DESCRIPTION
.Ic Unbound
is an implementation of a DNS resolver, that does caching and
DNSSEC validation.
.Pp
The available options are:
.Bl -tag -width indent
.It Fl h
Show the version and commandline option help.
.It Fl c Ar cfgfile
Set the config file to read with settings for unbound. The syntax is
described in
.Xr unbound.conf 5 .
.It Fl d
Debug flag, do not fork into the background, but stay attached to the
console.
.It Fl v
Increase verbosity. If given multiple times, more information is logged.
This is in addition to the verbosity (if any) from the config file.
.El
.Sh SEE ALSO
.Xr unbound.conf 5 .
.Sh AUTHORS
.Ic Unbound
developers are mentioned in the CREDITS file in the distribution.
+51
View File
@@ -0,0 +1,51 @@
.TH "unbound" "8" "@date@" "NLnet Labs" "unbound @version@"
.\"
.\" unbound.8 -- unbound manual
.\"
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
.\"
.\" See LICENSE for the license.
.\"
.\"
.SH "NAME"
.LP
.B unbound
\- Unbound DNS validating resolver @version@.
.SH "SYNOPSIS"
.LP
.B unbound
.RB [ \-h ]
.RB [ \-d ]
.RB [ \-v ]
.RB [ \-c
.IR cfgfile ]
.SH "DESCRIPTION"
.LP
.B Unbound
is an implementation of a DNS resolver, that does caching and
DNSSEC validation.
.P
The available options are:
.TP
.B \-h
Show the version and commandline option help.
.TP
.B \-c\fI cfgfile
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
Debug flag, do not fork into the background, but stay attached to the
console. This flag will also delay writing to the logfile until the
thread\-spawn time. So that most config and setup errors appear on stderr.
.TP
.B \-v
Increase verbosity. If given multiple times, more information is logged.
This is in addition to the verbosity (if any) from the config file.
.SH "SEE ALSO"
\fIunbound.conf\fR(5),
\fIunbound\-checkconf\fR(8).
.SH "AUTHORS"
.B Unbound
developers are mentioned in the CREDITS file in the distribution.
-237
View File
@@ -1,237 +0,0 @@
.\"
.\" unbound.conf.5 -- unbound.conf manual
.\"
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
.\"
.\" See LICENSE for the license.
.\"
.\"
.Dd @date@
.Os FreeBSD
.Dt unbound.conf 5
.Sh NAME
.Nm unbound.conf
.Nd Unbound configuration file.
.Sh SYNOPSIS
.Nm unbound.conf
.Sh DESCRIPTION
.Ic unbound.conf
is used to configure
.Xr unbound 8 .
The file format has attributes and values. Some attributes have attributes inside them.
The notation is: attribute: value.
Comments start with # and last to the end of line. Empty lines are
ignored as is whitespace at the beginning of a line.
.El
.Sh EXAMPLE
An example config file is shown below. Copy this to /etc/unbound/unbound.conf
and start the server with:
.nf
$ unbound -c /etc/unbound/unbound.conf
.fi
Most settings are the defaults. Stop the server with:
.nf
$ kill `cat /etc/unbound/unbound.pid`
.fi
Below is a minimal config file. The source distribution contains an extensive
example.conf file with all the options.
.nf
# unbound.conf(5) config file for unbound(8).
server:
directory: "/etc/unbound"
username: unbound # make sure it can write to pidfile, logfile.
chroot: "/etc/unbound"
logfile: "/etc/unbound/unbound.log"
pidfile: "/etc/unbound/unbound.pid"
# verbosity: 1 # uncomment and increase to get more logging.
.fi
.El
.Sh FILE FORMAT
There must be whitespace between keywords. Attribute keywords end with a colon ':'. An attribute
is followed by its containing attributes, or a value.
.Pp
Files can be included using the
.Ic include:
directive. It can appear anywhere, and takes a single filename as an argument.
Processing continues as if the text from the included file was copied into
the config file at that point.
.Ss Server Options
There may only be one
.Ic server:
clause.
.Bl -tag -width indent
.It \fBverbosity:\fR <number>
The verbosity number, level 0 means no verbosity, only errors. Level 1
gives operational information. Level 2 gives query level information,
output per query. Level 3 gives algorithm level information.
Default is level 1. The verbosity can also be increased from the commandline,
see
.Xr unbound 8 .
.It \fBnum-threads:\fR <number>
The number of threads to create to serve clients. Use 1 for no threading.
.It \fBport:\fR <port number>
The port number, default 53, on which the server responds to queries.
.It \fBinterface:\fR <ip address>
Interface to use to connect to the network. Can be given multiple times to
work on several interfaces. If none are given the default (all) is used.
.It \fBoutgoing-port:\fR <port number>
The starting port number where the outgoing query port range is allocated.
Default is 1053.
.It \fBoutgoing-range:\fR <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.
.It \fBoutgoing-num-tcp:\fR <number>
Number of outgoing TCP buffers to allocate per thread. Default is 10. If set
to 0, or if do_tcp is "no", no TCP queries to authoritative servers are done.
.It \fBmsg-cache-size:\fR <number>
Number of bytes size of the message cache. Default is 4 megabytes.
.It \fBmsg-cache-slabs:\fR <number>
Number of slabs in the message cache. Slabs reduce lock contention by threads.
Must be set to a power of 2. Setting (close) to the number of cpus is a
reasonable guess.
.It \fBnum-queries-per-thread:\fR <number>
The number of queries that every thread will service simultaneously.
.It \fBrrset-cache-size:\fR <number>
Number of bytes size of the RRset cache. Default is 4 megabytes.
.It \fBrrset-cache-slabs:\fR <number>
Number of slabs in the RRset cache. Slabs reduce lock contention by threads.
Must be set to a power of 2.
.It \fBinfra-host-ttl:\fR <seconds>
Time to live for entries in the host cache. The host cache contains
roundtrip timing and EDNS support information. Default is 900.
.It \fBinfra-lame-ttl:\fR <seconds>
The time to live when a delegation is discovered to be lame. Default is 900.
.It \fBinfra-cache-slabs:\fR <number>
Number of slabs in the infrastructure cache. Slabs reduce lock contention
by threads. Must be set to a power of 2.
.It \fBinfra-cache-numhosts:\fR <number>
Number of hosts for which information is cached. Default is 1000.
.It \fBinfra-cache-numlame:\fR <number>
Number of zones per host for which lameness is cached. Default is 1000.
.It \fBdo-ip4:\fR <yes or no>
Enable or disable whether ip4 queries are answered. Default is yes.
.It \fBdo-ip6:\fR <yes or no>
Enable or disable whether ip6 queries are answered. Default is yes.
.It \fBdo-udp:\fR <yes or no>
Enable or disable whether UDP queries are answered. Default is yes.
.It \fBdo-tcp:\fR <yes or no>
Enable or disable whether TCP queries are answered. Default is yes.
.It \fBchroot:\fR <directory>
If given a chroot is done to the given directory. The default is none ("").
.It \fBusername:\fR <name>
If given, after binding the port the user privileges are dropped. Default is
not to change user, username: "".
If this user is not capable of binding the
port, reloads (by signal HUP) will still retain the opened ports.
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.
.It \fBdirectory:\fR <directory>
Sets the working directory for the program.
.It \fBlogfile:\fR <filename>
If "" is given, logging goes to stderr, or nowhere once daemonized.
The logfile is appended to, in the following format:
[seconds since 1970] unbound[pid:tid]: type: message.
.It \fBpidfile:\fR <filename>
The process id is written to the file. Default is "unbound.pid". So,
kill -HUP `cat /etc/unbound/unbound.pid` will trigger a reload,
kill -QUIT `cat /etc/unbound/unbound.pid` will gracefully terminate.
.It \fBhide-identity:\fR <yes or no>
If enabled id.server and hostname.bind queries are refused.
.It \fBidentity:\fR <string>
Set the identity to report. If set to "", the default, then the hostname
of the server is returned.
.It \fBhide-version:\fR <yes or no>
If enabled version.server and version.bind queries are refused.
.It \fBversion:\fR <string>
Set the version to report. If set to "", the default, then the package
version is returned.
.It \fBtarget-fetch-policy:\fR <"list of numbers">
Set the target fetch policy used by unbound to determine if it should fetch
nameserver target addresses opportunistically. The policy is described per
dependency depth.
The number of values determines the maximum dependency depth
that unbound will pursue in answering a query.
A value of -1 means to fetch all targets opportunistically for that dependency
depth. A value of 0 means to fetch on demand only. A positive value fetches
that many targets opportunistically.
Enclose the list between quotes ("") and put spaces between numbers.
The default is "3 2 1 0 0". Setting all zeroes, "0 0 0 0 0" gives behaviour
closer to that of BIND 9, while setting "-1 -1 -1 -1 -1" gives behaviour
rumoured to be closer to that of BIND 8.
.It \fBharden-short-bufsize:\fR <yes or no>
Very small EDNS buffer sizes from queries are ignored. Default is off, since
it is legal protocol wise to send these, and unbound tries to give very
small answers to these queries, where possible.
.It \fBharden-large-queries:\fR <yes or no>
Very large queries are ignored. Default is off, since it is legal protocol
wise to send these, and could be necessary for operation if TSIG or EDNS
payload is very large.
.It \fBharden-glue:\fR <yes or no>
Will trust glue only if it is within the servers authority. Default is on.
.It \fBdo-not-query-address:\fR <IP address>
Do not query the given IP address. Can be IP4 or IP6. By default the
DNS port is blocked for that address. Appending the character '@' and then
the portnumber will block other port numbers.
.El
.Ss Stub Zone Options
There may be multiple
.Ic stub-zone:
clauses. Each with a name: and zero or more hostnames or IP addresses.
For the stub zone this list of nameservers is used. Class IN is assumed.
.Bl -tag -width indent
.It \fBname:\fR <domain name>
Name of the stub zone.
.It \fBstub-host:\fR <domain name>
Name of stub zone nameserver. Is itself resolved before it is used.
.It \fBstub-addr:\fR <IP address>
IP address of stub zone nameserver. Can be IP 4 or IP 6.
To use a nondefault port for DNS communication append '@' with the port number.
.El
.Ss Forward Zone Options
There may be multiple
.Ic forward-zone:
clauses. Each with a name: and zero or more hostnames or IP addresses.
For the forward zone this list of nameservers is used to forward the queries
to. The servers have to handle further recursion for the query. Class IN is
assumed. A forward-zone entry with name "." and a forward-addr target will
forward all queries to that other server (unless it can answer from the cache).
.Bl -tag -width indent
.It \fBname:\fR <domain name>
Name of the forward zone.
.It \fBforward-host:\fR <domain name>
Name of server to forward to. Is itself resolved before it is used.
.It \fBforward-addr:\fR <IP address>
IP address of server to forward to. Can be IP 4 or IP 6.
To use a nondefault port for DNS communication append '@' with the port number.
.El
.Sh FILES
.Bl -tag -width indent
.It Pa /etc/unbound
default unbound working directory
.It Pa unbound.conf
unbound configuration file.
.It Pa unbound.pid
default unbound pidfile with process ID of the running daemon.
.It Pa unbound.log
unbound log file.
.El
.Sh SEE ALSO
.Xr unbound 8
.Sh AUTHORS
.Ic Unbound
was written by NLnet Labs. Please see CREDITS file
in the distribution for further details.
+697
View File
@@ -0,0 +1,697 @@
.TH "unbound.conf" "5" "@date@" "NLnet Labs" "unbound @version@"
.\"
.\" unbound.conf.5 -- unbound.conf manual
.\"
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
.\"
.\" See LICENSE for the license.
.\"
.\"
.SH "NAME"
.LP
.B unbound.conf
\- Unbound configuration file.
.SH "SYNOPSIS"
.LP
.B unbound.conf
.SH "DESCRIPTION"
.LP
.B unbound.conf
is used to configure
\fIunbound\fR(8).
The file format has attributes and values. Some attributes have attributes inside them.
The notation is: attribute: value.
.P
Comments start with # and last to the end of line. Empty lines are
ignored as is whitespace at the beginning of a line.
.P
The utility
\fIunbound\-checkconf\fR(8)
can be used to check unbound.conf prior to usage.
.SH "EXAMPLE"
An example config file is shown below. Copy this to /etc/unbound/unbound.conf
and start the server with:
.P
.nf
$ unbound \-c /etc/unbound/unbound.conf
.fi
.P
Most settings are the defaults. Stop the server with:
.P
.nf
$ kill `cat /etc/unbound/unbound.pid`
.fi
.P
Below is a minimal config file. The source distribution contains an extensive
example.conf file with all the options.
.P
.nf
# unbound.conf(5) config file for unbound(8).
server:
directory: "/etc/unbound"
username: unbound # make sure it can write to pidfile.
chroot: "/etc/unbound"
# logfile: "/etc/unbound/unbound.log" #uncomment to use logfile.
pidfile: "/etc/unbound/unbound.pid"
# verbosity: 1 # uncomment and increase to get more logging.
# listen on all interfaces, answer queries from the local subnet.
interface: 0.0.0.0
interface: ::0
access\-control: 10.0.0.0/8 allow
access\-control: 2001:DB8::/64 allow
.fi
.SH "FILE FORMAT"
.LP
There must be whitespace between keywords. Attribute keywords end with a colon ':'. An attribute
is followed by its containing attributes, or a value.
.P
Files can be included using the
.B include:
directive. It can appear anywhere, and takes a single filename as an argument.
Processing continues as if the text from the included file was copied into
the config file at that point.
.SS "Server Options"
These options are part of the
.B server:
clause.
.TP
.B verbosity: \fI<number>
The verbosity number, level 0 means no verbosity, only errors. Level 1
gives operational information. Level 2 gives detailed operational
information. Level 3 gives query level information, output per query.
Level 4 gives algorithm level information.
Default is level 1. The verbosity can also be increased from the commandline,
see
\fIunbound\fR(8).
.TP
.B statistics-interval: \fI<seconds>
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
.B port: \fI<port number>
The port number, default 53, on which the server responds to queries.
.TP
.B interface: \fI<ip address>
Interface to use to connect to the network. This interface is listened to
for queries from clients, and answers to clients are given from it.
Can be given multiple times to work on several interfaces. If none are
given the default is to listen to localhost.
The interfaces are not changed on a reload (kill \-HUP) but only on restart.
.TP
.B interface-automatic: \fI<yes or no>
Detect source interface on UDP queries and copy them to replies. This
feature is experimental, and needs support in your OS for IPv6
(and its socket options) and IPv4 (and have source-interface socket options).
Default value is no.
.TP
.B outgoing\-interface: \fI<ip address>
Interface to use to connect to the network. This interface is used to send
queries to authoritative servers and receive their replies. Can be given
multiple times to work on several interfaces. If none are given the
default (all) is used. You can specify the same interfaces in
.B interface:
and
.B outgoing\-interface:
lines, the interfaces are then used for both purposes. Outgoing queries are
sent via a random outgoing interface to counter spoofing.
.TP
.B outgoing\-range: \fI<number>
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
to 0, or if do_tcp is "no", no TCP queries to authoritative servers are done.
.TP
.B incoming\-num\-tcp: \fI<number>
Number of incoming TCP buffers to allocate per thread. Default is 10. If set
to 0, or if do_tcp is "no", no TCP queries from clients are accepted.
.TP
.B msg\-buffer\-size: \fI<number>
Number of bytes size of the message buffers. Default is 65552 bytes, enough
for 64 Kb packets, the maximum DNS message size. No message larger than this
can be sent or received. Can be reduced to use less memory, but some requests
for DNS data, such as for huge resource records, will result in a SERVFAIL
reply to the client.
.TP
.B msg\-cache\-size: \fI<number>
Number of bytes size of the message cache. Default is 4 megabytes.
A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes
or gigabytes (1024*1024 bytes in a megabyte).
.TP
.B msg\-cache\-slabs: \fI<number>
Number of slabs in the message cache. Slabs reduce lock contention by threads.
Must be set to a power of 2. Setting (close) to the number of cpus is a
reasonable guess.
.TP
.B num\-queries\-per\-thread: \fI<number>
The number of queries that every thread will service simultaneously.
If more queries arrive that need servicing, they are dropped. This forces
the client to resend after a timeout; allowing the server time to work on
the existing queries. Default 1024.
.TP
.B rrset\-cache\-size: \fI<number>
Number of bytes size of the RRset cache. Default is 4 megabytes.
A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes
or gigabytes (1024*1024 bytes in a megabyte).
.TP
.B rrset\-cache\-slabs: \fI<number>
Number of slabs in the RRset cache. Slabs reduce lock contention by threads.
Must be set to a power of 2.
.TP
.B cache\-max\-ttl: \fI<seconds>
Time to live maximum for RRsets and messages in the cache. Default is
86400 seconds (1 day). If the maximum kicks in, responses to clients
still get decrementing TTLs based on the original (larger) values.
When the internal TTL expires, the cache item has expired.
Can be set lower to force the resolver to query for data often, and not
trust (very large) TTL values.
.TP
.B infra\-host\-ttl: \fI<seconds>
Time to live for entries in the host cache. The host cache contains
roundtrip timing and EDNS support information. Default is 900.
.TP
.B infra\-lame\-ttl: \fI<seconds>
The time to live when a delegation is discovered to be lame. Default is 900.
.TP
.B infra\-cache\-slabs: \fI<number>
Number of slabs in the infrastructure cache. Slabs reduce lock contention
by threads. Must be set to a power of 2.
.TP
.B infra\-cache\-numhosts: \fI<number>
Number of hosts for which information is cached. Default is 10000.
.TP
.B infra\-cache\-lame\-size: \fI<number>
Number of bytes that the lameness cache per host is allowed to use. Default
is 10 kb, which gives maximum storage for a couple score zones, depending on
the lame zone name lengths.
.TP
.B do\-ip4: \fI<yes or no>
Enable or disable whether ip4 queries are answered or issued. Default is yes.
.TP
.B do\-ip6: \fI<yes or no>
Enable or disable whether ip6 queries are answered or issued. Default is yes.
If disabled, queries are not answered on IPv6, and queries are not sent on
IPv6 to the internet nameservers.
.TP
.B do\-udp: \fI<yes or no>
Enable or disable whether UDP queries are answered or issued. Default is yes.
.TP
.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.
Deny stops queries from hosts from that netblock.
Refuse stops queries too, but sends a DNS rcode REFUSED error message back.
Allow gives access to clients from that netblock.
By default only localhost is allowed, the rest is refused.
The default is refused, because that is protocol\-friendly. The DNS protocol
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
"@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.
.IP
If this user is not capable of binding the
port, reloads (by signal HUP) will still retain the opened ports.
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. Default is "@UNBOUND_RUN_DIR@".
.TP
.B logfile: \fI<filename>
If "" is given, logging goes to stderr, or nowhere once daemonized.
The logfile is appended to, in the following format:
.nf
[seconds since 1970] unbound[pid:tid]: type: message.
.fi
If this option is given, the use\-syslog is option is set to "no".
The logfile is reopened (for append) when the config file is reread, on
SIGHUP.
.TP
.B use\-syslog: \fI<yes or no>
Sets unbound to send log messages to the syslogd, using
\fIsyslog\fR(3).
The log facility LOG_DAEMON is used, with identity "unbound".
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 "@UNBOUND_PIDFILE@".
So,
.nf
kill \-HUP `cat @UNBOUND_PIDFILE@`
.fi
triggers a reload,
.nf
kill \-QUIT `cat @UNBOUND_PIDFILE@`
.fi
gracefully terminates.
.TP
.B root\-hints: \fI<filename>
Read the root hints from this file. Default is nothing, using builtin hints
for the IN class. The file has the format of zone files, with root
nameserver names and addresses only. The default may become outdated,
when servers change, therefore it is good practice to use a root\-hints file.
.TP
.B hide\-identity: \fI<yes or no>
If enabled id.server and hostname.bind queries are refused.
.TP
.B identity: \fI<string>
Set the identity to report. If set to "", the default, then the hostname
of the server is returned.
.TP
.B hide\-version: \fI<yes or no>
If enabled version.server and version.bind queries are refused.
.TP
.B version: \fI<string>
Set the version to report. If set to "", the default, then the package
version is returned.
.TP
.B target\-fetch\-policy: \fI<"list of numbers">
Set the target fetch policy used by unbound to determine if it should fetch
nameserver target addresses opportunistically. The policy is described per
dependency depth.
.IP
The number of values determines the maximum dependency depth
that unbound will pursue in answering a query.
A value of \-1 means to fetch all targets opportunistically for that dependency
depth. A value of 0 means to fetch on demand only. A positive value fetches
that many targets opportunistically.
.IP
Enclose the list between quotes ("") and put spaces between numbers.
The default is "3 2 1 0 0". Setting all zeroes, "0 0 0 0 0" gives behaviour
closer to that of BIND 9, while setting "\-1 \-1 \-1 \-1 \-1" gives behaviour
rumoured to be closer to that of BIND 8.
.TP
.B harden\-short\-bufsize: \fI<yes or no>
Very small EDNS buffer sizes from queries are ignored. Default is off, since
it is legal protocol wise to send these, and unbound tries to give very
small answers to these queries, where possible.
.TP
.B harden\-large\-queries: \fI<yes or no>
Very large queries are ignored. Default is off, since it is legal protocol
wise to send these, and could be necessary for operation if TSIG or EDNS
payload is very large.
.TP
.B harden\-glue: \fI<yes or no>
Will trust glue only if it is within the servers authority. Default is on.
.TP
.B harden\-dnssec\-stripped: \fI<yes or no>
Require DNSSEC data for trust\-anchored zones, if such data is absent,
the zone becomes bogus. If turned off, and no DNSSEC data is received
(or the DNSKEY data fails to validate), then the zone is made insecure,
this behaves like there is no trust anchor. You could turn this off if
you are sometimes behind an intrusive firewall (of some sort) that
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
10.2.3.4/24 or 2001::11/64.
.TP
.B do\-not\-query\-localhost: \fI<yes or no>
If yes, localhost is added to the do\-not\-query\-address entries, both
IP6 ::1 and IP4 127.0.0.1/8. If no, then localhost can be used to send
queries to. Default is yes.
.TP
.B module\-config: \fI<"module names">
Module configuration, a list of module names separated by spaces, surround
the string with quotes (""). The modules can be validator, iterator.
Setting this to "iterator" will result in a non\-validating server.
Setting this to "validator iterator" will turn on DNSSEC validation.
You must also set trust\-anchors for validation to be useful.
.TP
.B trust\-anchor\-file: \fI<filename>
File with trusted keys for validation. Both DS and DNSKEY entries can appear
in the file. The format of the file is the standard DNS Zone file format.
Default is "", or no trust anchor file.
.TP
.B trust\-anchor: \fI<"Resource Record">
A DS or DNSKEY RR for a key to use for validation. Multiple entries can be
given to specify multiple trusted keys, in addition to the trust\-anchor\-files.
The resource record is entered in the same format as 'dig' or 'drill' prints
them, the same format as in the zone file. Has to be on a single line, with
"" around it. A TTL can be specified for ease of cut and paste, but is ignored.
A class can be specified, but class IN is default.
.TP
.B trusted\-keys\-file: \fI<filename>
File with trusted keys for validation. Specify more than one file
with several entries, one file per entry. Like \fBtrust\-anchor\-file\fR
but has a different file format. Format is BIND\-9 style format,
the trusted\-keys { name flag proto algo "key"; }; clauses are read.
.TP
.B val\-override\-date: \fI<rrsig\-style date spec>
Default is "" or "0", which disables this debugging feature. If enabled by
giving a RRSIG style date, that date is used for verifying RRSIG inception
and expiration dates, instead of the current date. Do not set this unless
you are debugging signature inception and expiration.
.TP
.B val\-bogus\-ttl: \fI<number>
The time to live for bogus data. This is data that has failed validation;
due to invalid signatures or other checks. The TTL from that data cannot be
trusted, and this value is used instead. The value is in seconds, default 900.
The time interval prevents repeated revalidation of bogus data.
.TP
.B val\-clean\-additional: \fI<yes or no>
Instruct the validator to remove data from the additional section of secure
messages that are not signed properly. Messages that are insecure, bogus,
indeterminate or unchecked are not affected. Default is yes. Use this setting
to protect the users that rely on this validator for authentication from
protentially bad data in the additional section.
.TP
.B val\-permissive\-mode: \fI<yes or no>
Instruct the validator to mark bogus messages as indeterminate. The security
checks are performed, but if the result is bogus (failed security), the
reply is not withheld from the client with SERVFAIL as usual. The client
receives the bogus data. For messages that are found to be secure the AD bit
is set in replies. Also logging is performed as for full validation.
The default value is "no".
.TP
.B val\-nsec3\-keysize\-iterations: \fI<"list of values">
List of keysize and iteration count values, separated by spaces, surrounded
by quotes. Default is "1024 150 2048 500 4096 2500". This determines the
maximum allowed NSEC3 iteration count before a message is simply marked
insecure instead of performing the many hashing iterations. The list must
be in ascending order and have at least one entry. If you set it to
"1024 65535" there is no restriction to NSEC3 iteration values.
This table must be kept short; a very long list could cause slower operation.
.TP
.B key\-cache\-size: \fI<number>
Number of bytes size of the key cache. Default is 4 megabytes.
A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes
or gigabytes (1024*1024 bytes in a megabyte).
.TP
.B key\-cache\-slabs: \fI<number>
Number of slabs in the key cache. Slabs reduce lock contention by threads.
Must be set to a power of 2. Setting (close) to the number of cpus is a
reasonable guess.
.TP
.B local\-zone: \fI<zone> <type>
Configure a local zone. The type determines the answer to give if there is
no match from local\-data. The types are deny, refuse, static, transparent,
redirect, nodefault, and are explained below. After that the default settings
are listed. Use local\-data: to enter data into the local zone. Answers for
local zones are authoritative DNS answers. By default the zones are class IN.
.IP
If you need more complicated authoritative data, with referrals, wildcards,
CNAME/DNAME support, or DNSSEC authoritative service, setup a stub\-zone for
it as detailed in the stub zone section below.
.TP 10
\h'5'\fIdeny\fR
Do not send an answer, drop the query.
If there is a match from local data, the query is answered.
.TP 10
\h'5'\fIrefuse\fR
Send an error message reply, with rcode REFUSED.
If there is a match from local data, the query is answered.
.TP 10
\h'5'\fIstatic\fR
If there is a match from local data, the query is answered.
Otherwise, the query is answered with nodata or nxdomain.
For a negative answer a SOA is included in the answer if present
as local\-data for the zone apex domain.
.TP 10
\h'5'\fItransparent\fR
If there is a match from local data, the query is answered.
Otherwise, the query is resolved normally.
If no local\-zone is given local\-data causes a transparent zone
to be created by default.
.TP 10
\h'5'\fIredirect\fR
The query is answered from the local data for the zone name.
There may be no local data beneath the zone name.
This answers queries for the zone, and all subdomains of the zone
with the local data for the zone.
It can be used to redirect a domain to a different address, with
local\-zone: "example.com." redirect and
local\-data: "example.com. A 127.0.0.1"
queries for www.example.com and www.foo.example.com are redirected.
.TP 10
\h'5'\fInodefault\fR
Used to turn off default contents for AS112 zones. The other types
also turn off default contents for the zone. The 'nodefault' option
has no other effect than turning off default contents for the
given zone.
.P
The default zones are localhost, reverse 127.0.0.1 and ::1, and the AS112
zones. The AS112 zones are reverse DNS zones for private use and reserved
IP addresses for which the servers on the internet cannot provide correct
answers. They are configured by default to give nxdomain (no reverse
information) answers. The defaults can be turned off by specifying your
own local\-zone of that name, or using the 'nodefault' type. Below is a
list of the default zone contents.
.TP 10
\h'5'\fIlocalhost\fR
The IP4 and IP6 localhost information is given. NS and SOA records are provided
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 A 127.0.0.1"
local\-data: "localhost. 10800 IN AAAA ::1"
.fi
.TP 10
\h'5'\fIreverse IPv4 loopback\fR
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."
.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."
.fi
.TP 10
\h'5'\fIreverse RFC1918 local use zones\fR
Reverse data for zones 10.in\-addr.arpa, 16.172.in\-addr.arpa to
31.172.in\-addr.arpa, 168.192.in\-addr.arpa.
The \fBlocal\-zone:\fR is set static and as \fBlocal\-data:\fR SOA and NS
records are provided.
.TP 10
\h'5'\fIreverse RFC3330 IP4 this, link\-local, testnet and broadcast\fR
Reverse data for zones 0.in\-addr.arpa, 254.169.in\-addr.arpa,
2.0.192.in\-addr.arpa, 255.255.255.255.in\-addr.arpa.
.TP 10
\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.
.fi
.TP 10
\h'5'\fIreverse RFC4193 IPv6 Locally Assigned Local Addresses\fR
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>"
Configure local data, which is served in reply to queries for it.
The query has to match exactly unless you configure the local\-zone as
redirect. If not matched exactly, the local\-zone type determines
further processing. If local\-data is configured that is not a subdomain of
a local\-zone, a transparent local\-zone is configured.
For record types such as TXT, use single quotes, as in
local\-data: 'example. TXT "text"'.
.IP
If you need more complicated authoritative data, with referrals, wildcards,
CNAME/DNAME support, or DNSSEC authoritative service, setup a stub\-zone for
it as detailed in the stub zone section below.
.SS "Stub Zone Options"
.LP
There may be multiple
.B stub\-zone:
clauses. Each with a name: and zero or more hostnames or IP addresses.
For the stub zone this list of nameservers is used. Class IN is assumed.
.P
The stub zone can be used to configure authoritative data to be used
by the resolver that cannot be accessed using the public internet servers.
This is useful for company\-local data or private zones. Setup an
authoritative server on a different host (or different port). Enter a config
entry for unbound with
.B stub\-addr:
<ip address of host[@port]>.
The unbound resolver can then access the data, without referring to the
public internet for it.
.P
This setup allows DNSSEC signed zones to be served by that
authoritative server, in which case a trusted key entry with the public key
can be put in config, so that unbound can validate the data and set the AD
bit on replies for the private zone (authoritative servers do not set the
AD bit). This setup makes unbound capable of answering queries for the
private zone, and can even set the AD bit ('authentic'), but the AA
('authoritative') bit is not set on these replies.
.TP
.B name: \fI<domain name>
Name of the stub zone.
.TP
.B stub\-host: \fI<domain name>
Name of stub zone nameserver. Is itself resolved before it is used.
.TP
.B stub\-addr: \fI<IP address>
IP address of stub zone nameserver. Can be IP 4 or IP 6.
To use a nondefault port for DNS communication append '@' with the port number.
.SS "Forward Zone Options"
.LP
There may be multiple
.B forward\-zone:
clauses. Each with a name: and zero or more hostnames or IP addresses.
For the forward zone this list of nameservers is used to forward the queries
to. The servers have to handle further recursion for the query. Class IN is
assumed. A forward\-zone entry with name "." and a forward\-addr target will
forward all queries to that other server (unless it can answer from the cache).
.TP
.B name: \fI<domain name>
Name of the forward zone.
.TP
.B forward\-host: \fI<domain name>
Name of server to forward to. Is itself resolved before it is used.
.TP
.B forward\-addr: \fI<IP address>
IP address of server to forward to. Can be IP 4 or IP 6.
To use a nondefault port for DNS communication append '@' with the port number.
.SH "MEMORY CONTROL EXAMPLE"
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 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
server:
num\-threads: 1
outgoing\-num\-tcp: 1 # this limits TCP service, uses less buffers.
incoming\-num\-tcp: 1
outgoing\-range: 16 # uses less memory, but less performance.
msg\-buffer\-size: 8192 # note this limits service, 'no huge stuff'.
msg\-cache\-size: 100k
msg\-cache\-slabs: 1
rrset\-cache\-size: 100k
rrset\-cache\-slabs: 1
infra\-cache\-numhosts: 200
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"
.fi
.SH "FILES"
.TP
.I @UNBOUND_RUN_DIR@
default unbound working directory.
.TP
.I @UNBOUND_CHROOT_DIR@
default
\fIchroot\fR(2)
location.
.TP
.I @ub_conf_file@
unbound configuration file.
.TP
.I @UNBOUND_PIDFILE@
default unbound pidfile with process ID of the running daemon.
.TP
.I unbound.log
unbound log file. default is to log to
\fIsyslog\fR(3).
.SH "SEE ALSO"
\fIunbound\fR(8),
\fIunbound\-checkconf\fR(8).
.SH "AUTHORS"
.B Unbound
was written by NLnet Labs. Please see CREDITS file
in the distribution for further details.
+2 -1
View File
@@ -495,7 +495,8 @@ EXCLUDE = ./build \
util/configparser.c \
util/configparser.h \
util/configlexer.c \
util/locks.h
util/locks.h \
./ldns-src
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
# directories that are symbolic links (a Unix filesystem feature) are excluded
+31 -20
View File
@@ -42,23 +42,24 @@
#include "config.h"
#include "iterator/iter_delegpt.h"
#include "services/cache/dns.h"
#include "util/region-allocator.h"
#include "util/regional.h"
#include "util/data/dname.h"
#include "util/data/packed_rrset.h"
#include "util/data/msgreply.h"
#include "util/net_help.h"
struct delegpt*
delegpt_create(struct region* region)
delegpt_create(struct regional* region)
{
struct delegpt* dp=(struct delegpt*)region_alloc(region, sizeof(*dp));
struct delegpt* dp=(struct delegpt*)regional_alloc(
region, sizeof(*dp));
if(!dp)
return NULL;
memset(dp, 0, sizeof(*dp));
return dp;
}
struct delegpt* delegpt_copy(struct delegpt* dp, struct region* region)
struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
{
struct delegpt* copy = delegpt_create(region);
struct delegpt_ns* ns;
@@ -80,24 +81,31 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct region* region)
}
int
delegpt_set_name(struct delegpt* dp, struct region* region, uint8_t* name)
delegpt_set_name(struct delegpt* dp, struct regional* region, uint8_t* name)
{
dp->namelabs = dname_count_size_labels(name, &dp->namelen);
dp->name = region_alloc_init(region, name, dp->namelen);
dp->name = regional_alloc_init(region, name, dp->namelen);
return dp->name != 0;
}
int
delegpt_add_ns(struct delegpt* dp, struct region* region, uint8_t* name)
delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name)
{
struct delegpt_ns* ns = (struct delegpt_ns*)region_alloc(region,
struct delegpt_ns* ns;
size_t len;
(void)dname_count_size_labels(name, &len);
/* slow check for duplicates to avoid counting failures when
* adding the same server as a dependency twice */
if(delegpt_find_ns(dp, name, len))
return 1;
ns = (struct delegpt_ns*)regional_alloc(region,
sizeof(struct delegpt_ns));
if(!ns)
return 0;
ns->next = dp->nslist;
ns->namelen = len;
dp->nslist = ns;
(void)dname_count_size_labels(name, &ns->namelen);
ns->name = region_alloc_init(region, name, ns->namelen);
ns->name = regional_alloc_init(region, name, ns->namelen);
ns->resolved = 0;
return 1;
}
@@ -117,7 +125,7 @@ delegpt_find_ns(struct delegpt* dp, uint8_t* name, size_t namelen)
}
int
delegpt_add_target(struct delegpt* dp, struct region* region,
delegpt_add_target(struct delegpt* dp, struct regional* region,
uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
socklen_t addrlen)
{
@@ -131,10 +139,10 @@ delegpt_add_target(struct delegpt* dp, struct region* region,
}
int
delegpt_add_addr(struct delegpt* dp, struct region* region,
delegpt_add_addr(struct delegpt* dp, struct regional* region,
struct sockaddr_storage* addr, socklen_t addrlen)
{
struct delegpt_addr* a = (struct delegpt_addr*)region_alloc(region,
struct delegpt_addr* a = (struct delegpt_addr*)regional_alloc(region,
sizeof(struct delegpt_addr));
if(!a)
return 0;
@@ -145,6 +153,7 @@ delegpt_add_addr(struct delegpt* dp, struct region* region,
dp->usable_list = a;
memcpy(&a->addr, addr, addrlen);
a->addrlen = addrlen;
a->attempts = 0;
return 1;
}
@@ -182,12 +191,14 @@ delegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres,
}
}
void delegpt_log(struct delegpt* dp)
void delegpt_log(enum verbosity_value v, struct delegpt* dp)
{
char buf[LDNS_MAX_DOMAINLEN+1];
struct delegpt_ns* ns;
struct delegpt_addr* a;
size_t missing=0, numns=0, numaddr=0, numres=0, numavail=0;
if(verbosity < v)
return;
dname_str(dp->name, buf);
if(dp->nslist == NULL && dp->target_list == NULL) {
log_info("DelegationPoint<%s>: empty", buf);
@@ -205,7 +216,7 @@ void delegpt_log(struct delegpt* dp)
log_info(" %s%s", buf, (ns->resolved?"*":""));
}
for(a = dp->target_list; a; a = a->next_target) {
log_addr(" ", &a->addr, a->addrlen);
log_addr(VERB_ALGO, " ", &a->addr, a->addrlen);
}
}
}
@@ -246,7 +257,7 @@ find_NS(struct reply_info* rep, size_t from, size_t to)
}
struct delegpt*
delegpt_from_message(struct dns_msg* msg, struct region* region)
delegpt_from_message(struct dns_msg* msg, struct regional* region)
{
struct ub_packed_rrset_key* ns_rrset = NULL;
struct delegpt* dp;
@@ -295,7 +306,7 @@ delegpt_from_message(struct dns_msg* msg, struct region* region)
}
int
delegpt_rrset_add_ns(struct delegpt* dp, struct region* region,
delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region,
struct ub_packed_rrset_key* ns_rrset)
{
struct packed_rrset_data* nsdata = (struct packed_rrset_data*)
@@ -314,7 +325,7 @@ delegpt_rrset_add_ns(struct delegpt* dp, struct region* region,
}
int
delegpt_add_rrset_A(struct delegpt* dp, struct region* region,
delegpt_add_rrset_A(struct delegpt* dp, struct regional* region,
struct ub_packed_rrset_key* ak)
{
struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;
@@ -337,7 +348,7 @@ delegpt_add_rrset_A(struct delegpt* dp, struct region* region,
}
int
delegpt_add_rrset_AAAA(struct delegpt* dp, struct region* region,
delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region,
struct ub_packed_rrset_key* ak)
{
struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;
@@ -360,7 +371,7 @@ delegpt_add_rrset_AAAA(struct delegpt* dp, struct region* region,
}
int
delegpt_add_rrset(struct delegpt* dp, struct region* region,
delegpt_add_rrset(struct delegpt* dp, struct regional* region,
struct ub_packed_rrset_key* rrset)
{
if(!rrset)
+32 -24
View File
@@ -42,7 +42,8 @@
#ifndef ITERATOR_ITER_DELEGPT_H
#define ITERATOR_ITER_DELEGPT_H
struct region;
#include "util/log.h"
struct regional;
struct delegpt_ns;
struct delegpt_addr;
struct dns_msg;
@@ -103,55 +104,61 @@ struct delegpt_addr {
struct sockaddr_storage addr;
/** length of addr */
socklen_t addrlen;
/** number of attempts for this addr */
int attempts;
/** rtt stored here in the selection algorithm */
int sel_rtt;
};
/**
* Create new delegation point.
* @param region: where to allocate it.
* @param regional: where to allocate it.
* @return new delegation point or NULL on error.
*/
struct delegpt* delegpt_create(struct region* region);
struct delegpt* delegpt_create(struct regional* regional);
/**
* Create a copy of a delegation point.
* @param dp: delegation point to copy.
* @param region: where to allocate it.
* @param regional: where to allocate it.
* @return new delegation point or NULL on error.
*/
struct delegpt* delegpt_copy(struct delegpt* dp, struct region* region);
struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* regional);
/**
* Set name of delegation point.
* @param dp: delegation point.
* @param region: where to allocate the name copy.
* @param regional: where to allocate the name copy.
* @param name: name to use.
* @return false on error.
*/
int delegpt_set_name(struct delegpt* dp, struct region* region, uint8_t* name);
int delegpt_set_name(struct delegpt* dp, struct regional* regional,
uint8_t* name);
/**
* Add a name to the delegation point.
* @param dp: delegation point.
* @param region: where to allocate the info.
* @param regional: where to allocate the info.
* @param name: domain name in wire format.
* @return false on error.
*/
int delegpt_add_ns(struct delegpt* dp, struct region* region, uint8_t* name);
int delegpt_add_ns(struct delegpt* dp, struct regional* regional,
uint8_t* name);
/**
* Add NS rrset; calls add_ns repeatedly.
* @param dp: delegation point.
* @param region: where to allocate the info.
* @param regional: where to allocate the info.
* @param ns_rrset: NS rrset.
* return 0 on alloc error.
*/
int delegpt_rrset_add_ns(struct delegpt* dp, struct region* region,
int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* regional,
struct ub_packed_rrset_key* ns_rrset);
/**
* Add target address to the delegation point.
* @param dp: delegation point.
* @param region: where to allocate the info.
* @param regional: where to allocate the info.
* @param name: name for which target was found (must be in nslist).
* This name is marked resolved.
* @param namelen: length of name.
@@ -159,49 +166,49 @@ int delegpt_rrset_add_ns(struct delegpt* dp, struct region* region,
* @param addrlen: the length of addr.
* @return false on error.
*/
int delegpt_add_target(struct delegpt* dp, struct region* region,
int delegpt_add_target(struct delegpt* dp, struct regional* regional,
uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
socklen_t addrlen);
/**
* Add A RRset to delegpt.
* @param dp: delegation point.
* @param region: where to allocate the info.
* @param regional: where to allocate the info.
* @param rrset: RRset A to add.
* @return 0 on alloc error.
*/
int delegpt_add_rrset_A(struct delegpt* dp, struct region* region,
int delegpt_add_rrset_A(struct delegpt* dp, struct regional* regional,
struct ub_packed_rrset_key* rrset);
/**
* Add AAAA RRset to delegpt.
* @param dp: delegation point.
* @param region: where to allocate the info.
* @param regional: where to allocate the info.
* @param rrset: RRset AAAA to add.
* @return 0 on alloc error.
*/
int delegpt_add_rrset_AAAA(struct delegpt* dp, struct region* region,
int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* regional,
struct ub_packed_rrset_key* rrset);
/**
* Add any RRset to delegpt.
* @param dp: delegation point.
* @param region: where to allocate the info.
* @param regional: where to allocate the info.
* @param rrset: RRset to add, NS, A, AAAA.
* @return 0 on alloc error.
*/
int delegpt_add_rrset(struct delegpt* dp, struct region* region,
int delegpt_add_rrset(struct delegpt* dp, struct regional* regional,
struct ub_packed_rrset_key* rrset);
/**
* Add address to the delegation point. No servername is associated or checked.
* @param dp: delegation point.
* @param region: where to allocate the info.
* @param regional: where to allocate the info.
* @param addr: the address.
* @param addrlen: the length of addr.
* @return false on error.
*/
int delegpt_add_addr(struct delegpt* dp, struct region* region,
int delegpt_add_addr(struct delegpt* dp, struct regional* regional,
struct sockaddr_storage* addr, socklen_t addrlen);
/**
@@ -216,9 +223,10 @@ struct delegpt_ns* delegpt_find_ns(struct delegpt* dp, uint8_t* name,
/**
* Print the delegation point to the log. For debugging.
* @param v: verbosity value that is needed to emit to log.
* @param dp: delegation point.
*/
void delegpt_log(struct delegpt* dp);
void delegpt_log(enum verbosity_value v, struct delegpt* dp);
/**
* Add all usable targets to the result list.
@@ -247,11 +255,11 @@ size_t delegpt_count_missing_targets(struct delegpt* dp);
* find "glue" in either the ADDITIONAL section or the ANSWER section.
*
* @param msg: the dns message, referral.
* @param region: where to allocate delegation point.
* @param regional: where to allocate delegation point.
* @return new delegation point or NULL on alloc error, or if the
* message was not appropriate.
*/
struct delegpt* delegpt_from_message(struct dns_msg* msg,
struct region* region);
struct regional* regional);
#endif /* ITERATOR_ITER_DELEGPT_H */
+101 -20
View File
@@ -43,18 +43,24 @@
*/
#include "config.h"
#include "iterator/iter_donotq.h"
#include "util/region-allocator.h"
#include "util/regional.h"
#include "util/log.h"
#include "util/config_file.h"
#include "util/net_help.h"
/** compare two donotq entries */
static int
int
donotq_cmp(const void* k1, const void* k2)
{
struct iter_donotq_addr* n1 = (struct iter_donotq_addr*)k1;
struct iter_donotq_addr* n2 = (struct iter_donotq_addr*)k2;
return sockaddr_cmp(&n1->addr, n1->addrlen, &n2->addr, n2->addrlen);
int r = sockaddr_cmp_addr(&n1->addr, n1->addrlen, &n2->addr,
n2->addrlen);
if(r != 0) return r;
if(n1->net < n2->net)
return -1;
if(n1->net > n2->net)
return 1;
return 0;
}
struct iter_donotq*
@@ -64,7 +70,7 @@ donotq_create()
sizeof(struct iter_donotq));
if(!dq)
return NULL;
dq->region = region_create(malloc, free);
dq->region = regional_create();
if(!dq->region) {
donotq_delete(dq);
return NULL;
@@ -77,7 +83,7 @@ donotq_delete(struct iter_donotq* dq)
{
if(!dq)
return;
region_destroy(dq->region);
regional_destroy(dq->region);
free(dq->tree);
free(dq);
}
@@ -85,17 +91,38 @@ donotq_delete(struct iter_donotq* dq)
/** insert new address into donotq structure */
static int
donotq_insert(struct iter_donotq* dq, struct sockaddr_storage* addr,
socklen_t addrlen)
socklen_t addrlen, int net)
{
struct iter_donotq_addr* node = region_alloc(dq->region,
struct iter_donotq_addr* node = regional_alloc(dq->region,
sizeof(struct iter_donotq_addr));
if(!node)
return 0;
node->node.key = node;
memcpy(&node->addr, addr, addrlen);
node->addrlen = addrlen;
node->net = net;
node->parent = NULL;
if(!rbtree_insert(dq->tree, &node->node)) {
log_warn("duplicate donotquery address ignored.");
verbose(VERB_QUERY, "duplicate donotquery address ignored.");
}
return 1;
}
/** apply donotq string */
static int
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;
}
if(!donotq_insert(dq, &addr, addrlen, net)) {
log_err("out of memory");
return 0;
}
return 1;
}
@@ -105,23 +132,42 @@ static int
read_donotq(struct iter_donotq* dq, struct config_file* cfg)
{
struct config_strlist* p;
struct sockaddr_storage addr;
socklen_t addrlen;
for(p = cfg->donotqueryaddrs; p; p = p->next) {
log_assert(p->str);
if(!extstrtoaddr(p->str, &addr, &addrlen)) {
log_err("cannot parse donotquery ip address: '%s'",
p->str);
if(!donotq_str_cfg(dq, p->str))
return 0;
}
if(!donotq_insert(dq, &addr, addrlen)) {
log_err("out of memory");
return 0;
}
}
return 1;
}
/** initialise parent pointers in the tree */
static void
donotq_init_parents(struct iter_donotq* donotq)
{
struct iter_donotq_addr* node, *prev = NULL, *p;
int m;
RBTREE_FOR(node, struct iter_donotq_addr*, donotq->tree) {
node->parent = NULL;
if(!prev || prev->addrlen != node->addrlen) {
prev = node;
continue;
}
m = addr_in_common(&prev->addr, prev->net, &node->addr,
node->net, node->addrlen);
/* sort order like: ::/0, 1::/2, 1::/4, ... 2::/2 */
/* find the previous, or parent-parent-parent */
for(p = prev; p; p = p->parent)
if(p->net <= m) {
/* ==: since prev matched m, this is closest*/
/* <: prev matches more, but is not a parent,
* this one is a (grand)parent */
node->parent = p;
break;
}
prev = node;
}
}
int
donotq_apply_cfg(struct iter_donotq* dq, struct config_file* cfg)
{
@@ -131,6 +177,15 @@ donotq_apply_cfg(struct iter_donotq* dq, struct config_file* cfg)
return 0;
if(!read_donotq(dq, cfg))
return 0;
if(cfg->donotquery_localhost) {
if(!donotq_str_cfg(dq, "127.0.0.0/8"))
return 0;
if(cfg->do_ip6) {
if(!donotq_str_cfg(dq, "::1"))
return 0;
}
}
donotq_init_parents(dq);
return 1;
}
@@ -139,11 +194,37 @@ donotq_lookup(struct iter_donotq* donotq, struct sockaddr_storage* addr,
socklen_t addrlen)
{
/* lookup in the tree */
rbnode_t* res = NULL;
struct iter_donotq_addr* result;
struct iter_donotq_addr key;
key.node.key = &key;
memcpy(&key.addr, addr, addrlen);
key.addrlen = addrlen;
if(rbtree_search(donotq->tree, &key))
key.net = (addr_is_ip6(addr, addrlen)?128:32);
if(rbtree_find_less_equal(donotq->tree, &key, &res)) {
/* exact */
return 1;
} else {
/* smaller element (or no element) */
int m;
result = (struct iter_donotq_addr*)res;
if(!result || result->addrlen != addrlen)
return 0;
/* count number of bits matched */
m = addr_in_common(&result->addr, result->net, addr,
key.net, addrlen);
while(result) { /* go up until addr is inside netblock */
if(result->net <= m)
return 1;
result = result->parent;
}
}
return 0;
}
size_t
donotq_get_mem(struct iter_donotq* donotq)
{
if(!donotq) return 0;
return sizeof(*donotq) + regional_get_mem(donotq->region);
}
+20 -6
View File
@@ -45,16 +45,16 @@
#include "util/rbtree.h"
struct iter_env;
struct config_file;
struct region;
struct regional;
/**
* Iterator donotqueryaddresses structure
*/
struct iter_donotq {
/** region for allocation */
struct region* region;
/** regional for allocation */
struct regional* region;
/**
* Tree of the single addresses that are blocked.
* Tree of the address spans that are blocked.
* contents of type iter_donotq_addr.
*/
rbtree_t* tree;
@@ -62,15 +62,19 @@ struct iter_donotq {
/**
* Iterator donotquery address.
* A single address that must not be used to send queries to.
* An address span that must not be used to send queries to.
*/
struct iter_donotq_addr {
/** redblacktree node, key is this structure: addr and addrlen */
/** redblacktree node, key is this structure: addr and addrlen, net */
rbnode_t node;
/** address */
struct sockaddr_storage addr;
/** length of addr */
socklen_t addrlen;
/** netblock size */
int net;
/** parent node in donotq tree that encompasses this entry */
struct iter_donotq_addr* parent;
};
/**
@@ -103,4 +107,14 @@ int donotq_apply_cfg(struct iter_donotq* donotq, struct config_file* cfg);
int donotq_lookup(struct iter_donotq* donotq, struct sockaddr_storage* addr,
socklen_t addrlen);
/**
* Get memory used by donotqueryaddresses structure.
* @param donotq: structure for address storage.
* @return bytes in use.
*/
size_t donotq_get_mem(struct iter_donotq* donotq);
/** compare two donotq entries */
int donotq_cmp(const void* k1, const void* k2);
#endif /* ITERATOR_ITER_DONOTQ_H */
+16 -9
View File
@@ -42,14 +42,13 @@
#include "config.h"
#include "iterator/iter_fwd.h"
#include "iterator/iter_delegpt.h"
#include "util/region-allocator.h"
#include "util/regional.h"
#include "util/log.h"
#include "util/config_file.h"
#include "util/net_help.h"
#include "util/data/dname.h"
/** compare two fwd entries */
static int
int
fwd_cmp(const void* k1, const void* k2)
{
int m;
@@ -71,7 +70,7 @@ forwards_create()
sizeof(struct iter_forwards));
if(!fwd)
return NULL;
fwd->region = region_create(malloc, free);
fwd->region = regional_create();
if(!fwd->region) {
forwards_delete(fwd);
return NULL;
@@ -84,7 +83,7 @@ forwards_delete(struct iter_forwards* fwd)
{
if(!fwd)
return;
region_destroy(fwd->region);
regional_destroy(fwd->region);
free(fwd->tree);
free(fwd);
}
@@ -93,13 +92,13 @@ forwards_delete(struct iter_forwards* fwd)
static int
forwards_insert(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
{
struct iter_forward_zone* node = region_alloc(fwd->region,
struct iter_forward_zone* node = regional_alloc(fwd->region,
sizeof(struct iter_forward_zone));
if(!node)
return 0;
node->node.key = node;
node->dclass = c;
node->name = region_alloc_init(fwd->region, dp->name, dp->namelen);
node->name = regional_alloc_init(fwd->region, dp->name, dp->namelen);
if(!node->name)
return 0;
node->namelen = dp->namelen;
@@ -229,8 +228,8 @@ read_forwards(struct iter_forwards* fwd, struct config_file* cfg)
return 0;
if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp))
return 0;
log_info("Forward zone server list:");
delegpt_log(dp);
verbose(VERB_QUERY, "Forward zone server list:");
delegpt_log(VERB_QUERY, dp);
}
return 1;
}
@@ -283,3 +282,11 @@ forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
return result->dp;
return NULL;
}
size_t
forwards_get_mem(struct iter_forwards* fwd)
{
if(!fwd)
return 0;
return sizeof(*fwd) + regional_get_mem(fwd->region);
}
+13 -3
View File
@@ -46,14 +46,14 @@
struct iter_env;
struct config_file;
struct delegpt;
struct region;
struct regional;
/**
* Iterator forward zones structure
*/
struct iter_forwards {
/** region where forward zone server addresses are allocated */
struct region* region;
/** regional where forward zone server addresses are allocated */
struct regional* region;
/**
* Zones are stored in this tree. Sort order is specially chosen.
* first sorted on qtype. Then on dname in nsec-like order, so that
@@ -118,4 +118,14 @@ int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg);
struct delegpt* forwards_lookup(struct iter_forwards* fwd,
uint8_t* qname, uint16_t qclass);
/**
* Get memory in use by forward storage
* @param fwd: forward storage.
* @return bytes in use
*/
size_t forwards_get_mem(struct iter_forwards* fwd);
/** compare two fwd entries */
int fwd_cmp(const void* k1, const void* k2);
#endif /* ITERATOR_ITER_FWD_H */
+167 -16
View File
@@ -42,14 +42,13 @@
#include "config.h"
#include "iterator/iter_hints.h"
#include "iterator/iter_delegpt.h"
#include "util/region-allocator.h"
#include "util/regional.h"
#include "util/log.h"
#include "util/config_file.h"
#include "util/net_help.h"
#include "util/data/dname.h"
/** compare two hint entries */
static int
int
stub_cmp(const void* k1, const void* k2)
{
int m;
@@ -71,7 +70,7 @@ hints_create()
sizeof(struct iter_hints));
if(!hints)
return NULL;
hints->region = region_create(malloc, free);
hints->region = regional_create();
if(!hints->region) {
hints_delete(hints);
return NULL;
@@ -84,14 +83,14 @@ hints_delete(struct iter_hints* hints)
{
if(!hints)
return;
region_destroy(hints->region);
regional_destroy(hints->region);
free(hints->tree);
free(hints);
}
/** add hint to delegation hints */
static int
ah(struct delegpt* dp, struct region* r, const char* sv, const char* ip)
ah(struct delegpt* dp, struct regional* r, const char* sv, const char* ip)
{
struct sockaddr_storage addr;
socklen_t addrlen;
@@ -113,7 +112,7 @@ ah(struct delegpt* dp, struct region* r, const char* sv, const char* ip)
/** obtain compiletime provided root hints */
static struct delegpt*
compile_time_root_prime(struct region* r)
compile_time_root_prime(struct regional* r, int do_ip4, int do_ip6)
{
/* from:
; This file is made available by InterNIC
@@ -122,14 +121,14 @@ compile_time_root_prime(struct region* 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;
@@ -141,8 +140,17 @@ compile_time_root_prime(struct region* r)
if(!ah(dp, r, "I.ROOT-SERVERS.NET.", "192.36.148.17")) return 0;
if(!ah(dp, r, "J.ROOT-SERVERS.NET.", "192.58.128.30")) return 0;
if(!ah(dp, r, "K.ROOT-SERVERS.NET.", "193.0.14.129")) return 0;
if(!ah(dp, r, "L.ROOT-SERVERS.NET.", "198.32.64.12")) 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;
}
@@ -150,13 +158,13 @@ compile_time_root_prime(struct region* r)
static int
hints_insert(struct iter_hints* hints, uint16_t c, struct delegpt* dp)
{
struct iter_hints_stub* node = region_alloc(hints->region,
struct iter_hints_stub* node = regional_alloc(hints->region,
sizeof(struct iter_hints_stub));
if(!node)
return 0;
node->node.key = node;
node->hint_class = c;
node->name = region_alloc_init(hints->region, dp->name, dp->namelen);
node->name = regional_alloc_init(hints->region, dp->name, dp->namelen);
if(!node->name)
return 0;
node->namelen = dp->namelen;
@@ -286,7 +294,140 @@ read_stubs(struct iter_hints* hints, struct config_file* cfg)
return 0;
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp))
return 0;
delegpt_log(dp);
delegpt_log(VERB_QUERY, dp);
}
return 1;
}
/** read root hints from file */
static int
read_root_hints(struct iter_hints* hints, char* fname)
{
int lineno = 0;
uint32_t default_ttl = 0;
ldns_rdf* origin = NULL;
ldns_rdf* prev_rr = NULL;
struct delegpt* dp;
ldns_rr* rr = NULL;
ldns_status status;
uint16_t c = LDNS_RR_CLASS_IN;
FILE* f = fopen(fname, "r");
if(!f) {
log_err("could not read root hints %s: %s",
fname, strerror(errno));
return 0;
}
dp = delegpt_create(hints->region);
if(!dp) {
log_err("out of memory reading root hints");
fclose(f);
return 0;
}
verbose(VERB_QUERY, "Reading root hints from %s", fname);
while(!feof(f)) {
status = ldns_rr_new_frm_fp_l(&rr, f,
&default_ttl, &origin, &prev_rr, &lineno);
if(status == LDNS_STATUS_SYNTAX_EMPTY ||
status == LDNS_STATUS_SYNTAX_TTL ||
status == LDNS_STATUS_SYNTAX_ORIGIN)
continue;
if(status != LDNS_STATUS_OK) {
log_err("reading root hints %s %d: %s", fname,
lineno, ldns_get_errorstr_by_id(status));
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");
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.");
goto stop_read;
}
}
} else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_A) {
struct sockaddr_in sa;
socklen_t len = (socklen_t)sizeof(sa);
memset(&sa, 0, len);
sa.sin_family = AF_INET;
sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
memmove(&sa.sin_addr,
ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET_SIZE);
if(!delegpt_add_target(dp, hints->region,
ldns_rdf_data(ldns_rr_owner(rr)),
ldns_rdf_size(ldns_rr_owner(rr)),
(struct sockaddr_storage*)&sa, len)) {
log_err("out of memory reading root hints");
goto stop_read;
}
} else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) {
struct sockaddr_in6 sa;
socklen_t len = (socklen_t)sizeof(sa);
memset(&sa, 0, len);
sa.sin6_family = AF_INET6;
sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
memmove(&sa.sin6_addr,
ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET6_SIZE);
if(!delegpt_add_target(dp, hints->region,
ldns_rdf_data(ldns_rr_owner(rr)),
ldns_rdf_size(ldns_rr_owner(rr)),
(struct sockaddr_storage*)&sa, len)) {
log_err("out of memory reading root hints");
goto stop_read;
}
} else {
log_warn("root hints %s:%d skipping type %d",
fname, lineno, ldns_rr_get_type(rr));
}
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);
return 1;
}
if(!hints_insert(hints, c, dp)) {
return 0;
}
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 */
static int
read_root_hints_list(struct iter_hints* hints, struct config_file* cfg)
{
struct config_strlist* p;
for(p = cfg->root_hints; p; p = p->next) {
log_assert(p->str);
if(p->str && p->str[0]) {
char* f = p->str;
if(cfg->chrootdir && cfg->chrootdir[0] &&
strncmp(p->str, cfg->chrootdir,
strlen(cfg->chrootdir)) == 0)
f += strlen(cfg->chrootdir);
if(!read_root_hints(hints, f))
return 0;
}
}
return 1;
}
@@ -298,7 +439,10 @@ hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
hints->tree = rbtree_create(stub_cmp);
if(!hints->tree)
return 0;
/* TODO: read root hints from file named in cfg */
/* read root hints */
if(!read_root_hints_list(hints, cfg))
return 0;
/* read stub hints */
if(!read_stubs(hints, cfg))
@@ -306,13 +450,13 @@ 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;
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp))
return 0;
delegpt_log(dp);
}
init_parents(hints);
@@ -375,3 +519,10 @@ hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
return result->dp; /* need to prime this stub */
return NULL;
}
size_t
hints_get_mem(struct iter_hints* hints)
{
if(!hints) return 0;
return sizeof(*hints) + regional_get_mem(hints->region);
}
+13 -3
View File
@@ -46,14 +46,14 @@
struct iter_env;
struct config_file;
struct delegpt;
struct region;
struct regional;
/**
* Iterator hints structure
*/
struct iter_hints {
/** region where hints are allocated */
struct region* region;
/** regional where hints are allocated */
struct regional* region;
/**
* Hints are stored in this tree. Sort order is specially chosen.
* first sorted on qtype. Then on dname in nsec-like order, so that
@@ -127,4 +127,14 @@ struct delegpt* hints_lookup_root(struct iter_hints* hints, uint16_t qclass);
struct delegpt* hints_lookup_stub(struct iter_hints* hints,
uint8_t* qname, uint16_t qclass, struct delegpt* dp);
/**
* Get memory in use by hints
* @param hints: hint storage.
* @return bytes in use
*/
size_t hints_get_mem(struct iter_hints* hints);
/** compare two hint entries */
int stub_cmp(const void* k1, const void* k2);
#endif /* ITERATOR_ITER_HINTS_H */
+52 -11
View File
@@ -100,10 +100,11 @@ response_type_from_cache(struct dns_msg* msg,
}
enum response_type
response_type_from_server(struct dns_msg* msg, struct query_info* request,
struct delegpt* dp)
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;
@@ -111,8 +112,13 @@ response_type_from_server(struct dns_msg* msg, struct query_info* request,
return RESPONSE_TYPE_THROWAWAY;
/* If the message is NXDOMAIN, then it answers the question. */
if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NXDOMAIN)
if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NXDOMAIN) {
/* make sure its not recursive when we don't want it to */
if( (msg->rep->flags&BIT_RA) &&
!(msg->rep->flags&BIT_AA) && !rdset)
return RESPONSE_TYPE_LAME;
return RESPONSE_TYPE_ANSWER;
}
/* Other response codes mean (so far) to throw the response away as
* meaningless and move on to the next nameserver. */
@@ -138,6 +144,18 @@ response_type_from_server(struct dns_msg* msg, struct query_info* request,
for(i=0; i<msg->rep->an_numrrsets; i++) {
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
/* if the answer section has NS rrset, and qtype ANY
* and the delegation is lower, and no CNAMEs followed,
* this is a referral where the NS went to AN section */
if((request->qtype == LDNS_RR_TYPE_ANY ||
request->qtype == LDNS_RR_TYPE_NS) &&
ntohs(s->rk.type) == LDNS_RR_TYPE_NS &&
ntohs(s->rk.rrset_class) == request->qclass &&
dname_strict_subdomain_c(s->rk.dname,
origzone)) {
return RESPONSE_TYPE_REFERRAL;
}
/* If we have encountered an answer (before or
* after a CNAME), then we are done! Note that
* if qtype == CNAME then this will be noted as an
@@ -170,27 +188,47 @@ response_type_from_server(struct dns_msg* msg, struct query_info* request,
}
}
/* Looking at the authority section, we just look and see if
* 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++) {
s = msg->rep->rrsets[i];
/* The normal way of detecting NOERROR/NODATA. */
if(ntohs(s->rk.type) == LDNS_RR_TYPE_SOA &&
dname_subdomain_c(request->qname, s->rk.dname)) {
/* we do our own recursion, thank you */
if( (msg->rep->flags&BIT_RA) &&
!(msg->rep->flags&BIT_AA) && !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++) {
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
/* The normal way of detecting NOERROR/NODATA. */
if(ntohs(s->rk.type) == LDNS_RR_TYPE_SOA &&
dname_subdomain_c(request->qname, s->rk.dname)) {
return RESPONSE_TYPE_ANSWER;
}
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
@@ -219,5 +257,8 @@ response_type_from_server(struct dns_msg* msg, struct query_info* request,
/* If we've gotten this far, this is NOERROR/NODATA (which could
* be an entirely empty message) */
/* check if recursive answer; saying it has empty cache */
if( (msg->rep->flags&BIT_RA) && !(msg->rep->flags&BIT_AA) && !rdset)
return RESPONSE_TYPE_LAME;
return RESPONSE_TYPE_ANSWER;
}
+3 -2
View File
@@ -107,13 +107,14 @@ enum response_type response_type_from_cache(struct dns_msg* msg,
* relies somewhat on the originating zone to be accurate (for lameness
* detection, mostly).
*
* @param rdset: if RD bit was sent in query sent by unbound.
* @param msg: the message from the cache.
* @param request: the request that generated the response.
* @param dp: The delegation point that was being queried
* when the response was returned.
* @return the response type (CNAME or ANSWER).
*/
enum response_type response_type_from_server(struct dns_msg* msg,
struct query_info* request, struct delegpt* dp);
enum response_type response_type_from_server(int rdset,
struct dns_msg* msg, struct query_info* request, struct delegpt* dp);
#endif /* ITERATOR_ITER_RESPTYPE_H */
+45 -15
View File
@@ -44,7 +44,7 @@
#include "services/cache/rrset.h"
#include "util/log.h"
#include "util/net_help.h"
#include "util/region-allocator.h"
#include "util/regional.h"
#include "util/config_file.h"
#include "util/module.h"
#include "util/data/msgparse.h"
@@ -60,11 +60,11 @@ static void
remove_rrset(const char* str, ldns_buffer* pkt, struct msg_parse* msg,
struct rrset_parse* prev, struct rrset_parse** rrset)
{
if(verbosity >= VERB_DETAIL
if(verbosity >= VERB_QUERY
&& (*rrset)->dname_len <= LDNS_MAX_DOMAINLEN) {
uint8_t buf[LDNS_MAX_DOMAINLEN+1];
dname_pkt_copy(pkt, buf, (*rrset)->dname);
log_nametypeclass(VERB_DETAIL, str, buf,
log_nametypeclass(VERB_QUERY, str, buf,
(*rrset)->type, ntohs((*rrset)->rrset_class));
}
if(prev)
@@ -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 */
@@ -224,22 +228,22 @@ synth_cname(uint8_t* qname, size_t qnamelen, struct rrset_parse* dname_rrset,
/** synthesize a CNAME rrset */
static struct rrset_parse*
synth_cname_rrset(uint8_t** sname, size_t* snamelen, uint8_t* alias,
size_t aliaslen, struct region* region, struct msg_parse* msg,
size_t aliaslen, struct regional* region, struct msg_parse* msg,
struct rrset_parse* rrset, struct rrset_parse* prev,
struct rrset_parse* nx, ldns_buffer* pkt)
{
struct rrset_parse* cn = (struct rrset_parse*)region_alloc(region,
struct rrset_parse* cn = (struct rrset_parse*)regional_alloc(region,
sizeof(struct rrset_parse));
if(!cn)
return NULL;
memset(cn, 0, sizeof(*cn));
cn->rr_first = (struct rr_parse*)region_alloc(region,
cn->rr_first = (struct rr_parse*)regional_alloc(region,
sizeof(struct rr_parse));
if(!cn->rr_first)
return NULL;
cn->rr_last = cn->rr_first;
/* CNAME from sname to alias */
cn->dname = (uint8_t*)region_alloc(region, *snamelen);
cn->dname = (uint8_t*)regional_alloc(region, *snamelen);
if(!cn->dname)
return NULL;
dname_pkt_copy(pkt, cn->dname, *sname);
@@ -253,7 +257,7 @@ synth_cname_rrset(uint8_t** sname, size_t* snamelen, uint8_t* alias,
/* allocate TTL + rdatalen + uncompressed dname */
memset(cn->rr_first, 0, sizeof(struct rr_parse));
cn->rr_first->outside_packet = 1;
cn->rr_first->ttl_data = (uint8_t*)region_alloc(region,
cn->rr_first->ttl_data = (uint8_t*)regional_alloc(region,
sizeof(uint32_t)+sizeof(uint16_t)+aliaslen);
if(!cn->rr_first->ttl_data)
return NULL;
@@ -312,7 +316,7 @@ pkt_sub(ldns_buffer* pkt, uint8_t* comprname, uint8_t* zone)
*/
static int
scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg,
struct query_info* qinfo, struct region* region)
struct query_info* qinfo, struct regional* region)
{
uint8_t* sname = qinfo->qname;
size_t snamelen = qinfo->qname_len;
@@ -350,6 +354,10 @@ scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg,
"too long");
return 0;
}
/* internally we have CNAME'd/DNAME'd chains ending
* in nxdomain with NOERROR rcode, change rcode
* to reflect this (if needed) */
FLAGS_SET_RCODE(msg->flags, LDNS_RCODE_NOERROR);
if(nx && nx->type == LDNS_RR_TYPE_CNAME &&
dname_pkt_compare(pkt, sname, nx->dname) == 0) {
/* check next cname */
@@ -392,6 +400,10 @@ scrub_normalize(ldns_buffer* pkt, struct msg_parse* msg,
return 0;
prev = rrset;
rrset = rrset->rrset_all_next;
/* internally we have CNAME'd/DNAME'd chains ending
* in nxdomain with NOERROR rcode, change rcode
* to reflect this (if needed) */
FLAGS_SET_RCODE(msg->flags, LDNS_RCODE_NOERROR);
continue;
}
@@ -459,7 +471,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)
@@ -515,17 +527,27 @@ scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg, uint8_t* zonename,
* same check can be used */
if(!pkt_sub(pkt, rrset->dname, zonename)) {
if(!env->cfg->harden_glue) {
if(msg->an_rrsets == 0 &&
rrset->type == LDNS_RR_TYPE_NS &&
rrset->section == LDNS_SECTION_AUTHORITY &&
FLAGS_GET_RCODE(msg->flags) ==
LDNS_RCODE_NOERROR) {
/* noerror, nodata and this NS rrset is above
* the zone. This is LAME!
* Leave in the NS for lame classification. */
} else if(!env->cfg->harden_glue) {
/* store in cache! Since it is relevant
* (from normalize) it will be picked up
* from the cache to be used later */
store_rrset(pkt, msg, env, rrset);
remove_rrset("sanitize: storing potential "
"poison RRset:", pkt, msg, prev, &rrset);
} else
continue;
} else {
remove_rrset("sanitize: removing potential "
"poison RRset:", pkt, msg, prev, &rrset);
continue;
continue;
}
}
prev = rrset;
rrset = rrset->rrset_all_next;
@@ -535,7 +557,7 @@ scrub_sanitize(ldns_buffer* pkt, struct msg_parse* msg, uint8_t* zonename,
int
scrub_message(ldns_buffer* pkt, struct msg_parse* msg,
struct query_info* qinfo, uint8_t* zonename, struct region* region,
struct query_info* qinfo, uint8_t* zonename, struct regional* region,
struct module_env* env)
{
/* basic sanity checks */
@@ -546,6 +568,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) {
+3 -3
View File
@@ -44,7 +44,7 @@
#define ITERATOR_ITER_SCRUB_H
struct msg_parse;
struct query_info;
struct region;
struct regional;
struct module_env;
/**
@@ -55,12 +55,12 @@ struct module_env;
* @param qinfo: the query info that was sent to the server. Checked.
* @param zonename: the name of the last delegation point.
* Used to determine out of bailiwick information.
* @param region: where to allocate (new) parts of the message.
* @param regional: where to allocate (new) parts of the message.
* @param env: module environment with config settings and cache.
* @return: false if the message is total waste. true if scrubbed with success.
*/
int scrub_message(ldns_buffer* pkt, struct msg_parse* msg,
struct query_info* qinfo, uint8_t* zonename, struct region* region,
struct query_info* qinfo, uint8_t* zonename, struct regional* regional,
struct module_env* env);
#endif /* ITERATOR_ITER_SCRUB_H */
+191 -103
View File
@@ -53,35 +53,12 @@
#include "util/module.h"
#include "util/log.h"
#include "util/config_file.h"
#include "util/region-allocator.h"
#include "util/regional.h"
#include "util/data/msgparse.h"
#include "util/data/dname.h"
#include "util/random.h"
/** count number of integers in fetch policy string */
static int
fetch_count(const char* s)
{
/* format ::= (sp num)+ sp */
/* num ::= [-](0-9)+ */
/* sp ::= (space|tab)* */
int num = 0;
while(*s) {
while(*s && isspace(*s))
s++;
if(!*s) /* end of string */
break;
if(*s == '-')
s++;
if(!*s) /* only - not allowed */
return 0;
if(!isdigit(*s)) /* bad character */
return 0;
while(*s && isdigit(*s))
s++;
num++;
}
return num;
}
#include "util/fptr_wlist.h"
#include "validator/val_anchor.h"
/** fillup fetch policy array */
static void
@@ -91,7 +68,8 @@ fetch_fill(struct iter_env* ie, const char* str)
int i;
for(i=0; i<ie->max_dependency_depth+1; i++) {
ie->target_fetch_policy[i] = strtol(s, &e, 10);
log_assert(s != e); /* parsed syntax already */
if(s == e)
fatal_exit("cannot parse fetch policy number %s", s);
s = e;
}
}
@@ -100,7 +78,7 @@ fetch_fill(struct iter_env* ie, const char* str)
static int
read_fetch_policy(struct iter_env* ie, const char* str)
{
int count = fetch_count(str);
int count = cfg_count_numbers(str);
if(count < 1) {
log_err("Cannot parse target fetch policy: \"%s\"", str);
return 0;
@@ -124,7 +102,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
if(!read_fetch_policy(iter_env, cfg->target_fetch_policy))
return 0;
for(i=0; i<iter_env->max_dependency_depth+1; i++)
verbose(VERB_DETAIL, "target fetch policy for level %d is %d",
verbose(VERB_QUERY, "target fetch policy for level %d is %d",
i, iter_env->target_fetch_policy[i]);
if(!iter_env->hints)
@@ -152,60 +130,88 @@ 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;
int dnsseclame;
if(donotq_lookup(iter_env->donotq, &a->addr, a->addrlen)) {
return -1; /* server is on the donotquery list */
}
if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr)) {
if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr, a->addrlen)) {
return -1; /* there is no ip6 available */
}
/* check lameness - need zone , class info */
if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen,
name, namelen, &lame, &rtt, now)) {
name, namelen, qtype, &lame, &dnsseclame, &rtt, now)) {
if(lame)
return -1; /* server is lame */
else if(rtt >= USEFUL_SERVER_TOP_TIMEOUT)
return -1; /* server is unresponsive */
else if(dnsseclame)
return rtt+USEFUL_SERVER_TOP_TIMEOUT; /* nonpref */
else return rtt;
}
/* no server information present */
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)
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 */
@@ -220,23 +226,29 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
a = a->next_result;
}
}
*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)
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);
int num = iter_filter_order(iter_env, env, name, namelen, qtype,
*env->now, dp, &selrtt);
if(num == 0)
return NULL;
if(selrtt >= USEFUL_SERVER_TOP_TIMEOUT)
*dnssec_expected = 0;
if(num == 1) {
a = dp->result_list;
if(++a->attempts < OUTBOUND_MSG_RETRY)
return a;
dp->result_list = a->next_result;
return a;
}
@@ -254,6 +266,8 @@ iter_server_selection(struct iter_env* iter_env,
}
if(!a) /* robustness */
return NULL;
if(++a->attempts < OUTBOUND_MSG_RETRY)
return a;
/* remove it from the delegation point result list */
if(prev)
prev->next_result = a->next_result;
@@ -262,9 +276,10 @@ iter_server_selection(struct iter_env* iter_env,
}
struct dns_msg*
dns_alloc_msg(ldns_buffer* pkt, struct msg_parse* msg, struct region* region)
dns_alloc_msg(ldns_buffer* pkt, struct msg_parse* msg,
struct regional* region)
{
struct dns_msg* m = (struct dns_msg*)region_alloc(region,
struct dns_msg* m = (struct dns_msg*)regional_alloc(region,
sizeof(struct dns_msg));
if(!m)
return NULL;
@@ -277,14 +292,14 @@ dns_alloc_msg(ldns_buffer* pkt, struct msg_parse* msg, struct region* region)
}
struct dns_msg*
dns_copy_msg(struct dns_msg* from, struct region* region)
dns_copy_msg(struct dns_msg* from, struct regional* region)
{
struct dns_msg* m = (struct dns_msg*)region_alloc(region,
struct dns_msg* m = (struct dns_msg*)regional_alloc(region,
sizeof(struct dns_msg));
if(!m)
return NULL;
m->qinfo = from->qinfo;
if(!(m->qinfo.qname = region_alloc_init(region, from->qinfo.qname,
if(!(m->qinfo.qname = regional_alloc_init(region, from->qinfo.qname,
from->qinfo.qname_len)))
return NULL;
if(!(m->rep = reply_info_copy(from->rep, NULL, region)))
@@ -296,51 +311,7 @@ int
iter_dns_store(struct module_env* env, struct query_info* msgqinf,
struct reply_info* msgrep, int is_referral)
{
struct reply_info* rep = NULL;
/* alloc, malloc properly (not in region, like msg is) */
rep = reply_info_copy(msgrep, env->alloc, NULL);
if(!rep)
return 0;
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);
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);
}
free(rep);
return 1;
} else {
/* store msg, and rrsets */
struct query_info qinf;
hashvalue_t h;
qinf = *msgqinf;
qinf.qname = memdup(msgqinf->qname, msgqinf->qname_len);
if(!qinf.qname) {
reply_info_parsedelete(rep, env->alloc);
return 0;
}
/* fixup flags to be sensible for a reply based on the cache */
/* this module means that RA is available. It is an answer QR.
* Not AA from cache. Not CD in cache (depends on client bit). */
rep->flags |= (BIT_RA | BIT_QR);
rep->flags &= ~(BIT_AA | BIT_CD);
h = query_info_hash(&qinf);
dns_cache_store_msg(env, &qinf, h, rep);
/* qname is used inside query_info_entrysetup, and set to
* NULL. If it has not been used, free it. free(0) is safe. */
free(qinf.qname);
}
return 1;
return dns_cache_store(env, msgqinf, msgrep, is_referral);
}
int
@@ -365,7 +336,10 @@ causes_cycle(struct module_qstate* qstate, uint8_t* name, size_t namelen,
qinf.qname_len = namelen;
qinf.qtype = t;
qinf.qclass = c;
return (*qstate->env->detect_cycle)(qstate, &qinf);
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);
}
void
@@ -380,11 +354,125 @@ iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp)
LDNS_RR_TYPE_AAAA, qstate->qinfo.qclass) ||
causes_cycle(qstate, ns->name, ns->namelen,
LDNS_RR_TYPE_A, qstate->qinfo.qclass)) {
log_nametypeclass(VERB_DETAIL, "skipping target due "
log_nametypeclass(VERB_QUERY, "skipping target due "
"to dependency cycle (harden-glue: no may "
"fix this)", ns->name, LDNS_RR_TYPE_A,
"fix some of the cycles)",
ns->name, LDNS_RR_TYPE_A,
qstate->qinfo.qclass);
ns->resolved = 1;
}
}
}
int
iter_dp_is_useless(struct module_qstate* qstate, struct delegpt* dp)
{
struct delegpt_ns* ns;
/* check:
* o all NS items are required glue.
* o no addresses are provided.
* o RD qflag is on.
* OR
* o no addresses are provided.
* o RD qflag is on.
* o the query is for one of the nameservers in dp,
* and that nameserver is a glue-name for this dp.
*/
if(!(qstate->query_flags&BIT_RD))
return 0;
/* either available or unused targets */
if(dp->usable_list || dp->result_list)
return 0;
/* see if query is for one of the nameservers, which is glue */
if( (qstate->qinfo.qtype == LDNS_RR_TYPE_A ||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) &&
dname_subdomain_c(qstate->qinfo.qname, dp->name) &&
delegpt_find_ns(dp, qstate->qinfo.qname,
qstate->qinfo.qname_len))
return 1;
for(ns = dp->nslist; ns; ns = ns->next) {
if(ns->resolved) /* skip failed targets */
continue;
if(!dname_subdomain_c(ns->name, dp->name))
return 0; /* one address is not required glue */
}
return 1;
}
int
iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
struct dns_msg* msg, uint16_t dclass)
{
/* information not available, !env->anchors can be common */
if(!env || !env->anchors || !dp || !dp->name || !msg || !msg->rep)
return 0;
/* a trust anchor exists with this name, RRSIGs expected */
if(anchor_find(env->anchors, dp->name, dp->namelabs, dp->namelen,
dclass))
return 1;
/* see if DS rrset was given, in AUTH section */
if(reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen,
LDNS_RR_TYPE_DS, dclass))
return 1;
return 0;
}
int
iter_msg_has_dnssec(struct dns_msg* msg)
{
size_t i;
if(!msg || !msg->rep)
return 0;
for(i=0; i<msg->rep->an_numrrsets + msg->rep->ns_numrrsets; i++) {
if(((struct packed_rrset_data*)msg->rep->rrsets[i]->
entry.data)->rrsig_count > 0)
return 1;
}
/* empty message has no DNSSEC info, with DNSSEC the reply is
* not empty (NSEC) */
return 0;
}
int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp,
enum response_type type, uint16_t dclass)
{
if(!msg || !dp || !msg->rep || !dp->name)
return 0;
/* SOA RRset - always from reply zone */
if(reply_find_rrset_section_an(msg->rep, dp->name, dp->namelen,
LDNS_RR_TYPE_SOA, dclass) ||
reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen,
LDNS_RR_TYPE_SOA, dclass))
return 1;
if(type == RESPONSE_TYPE_REFERRAL) {
size_t i;
/* if it adds a single label, i.e. we expect .com,
* and referral to example.com. NS ... , then origin zone
* is .com. For a referral to sub.example.com. NS ... then
* we do not know, since example.com. may be in between. */
for(i=0; i<msg->rep->an_numrrsets+msg->rep->ns_numrrsets;
i++) {
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
if(ntohs(s->rk.type) == LDNS_RR_TYPE_NS &&
ntohs(s->rk.rrset_class) == dclass) {
int l = dname_count_labels(s->rk.dname);
if(l == dp->namelabs + 1 &&
dname_strict_subdomain(s->rk.dname,
l, dp->name, dp->namelabs))
return 1;
}
}
return 0;
}
log_assert(type==RESPONSE_TYPE_ANSWER || type==RESPONSE_TYPE_CNAME);
/* not a referral, and not lame delegation (upwards), so,
* any NS rrset must be from the zone itself */
if(reply_find_rrset_section_an(msg->rep, dp->name, dp->namelen,
LDNS_RR_TYPE_NS, dclass) ||
reply_find_rrset_section_ns(msg->rep, dp->name, dp->namelen,
LDNS_RR_TYPE_NS, dclass))
return 1;
return 0;
}
+60 -10
View File
@@ -42,12 +42,13 @@
#ifndef ITERATOR_ITER_UTILS_H
#define ITERATOR_ITER_UTILS_H
#include "iterator/iter_resptype.h"
struct iter_env;
struct config_file;
struct module_env;
struct delegpt_addr;
struct delegpt;
struct region;
struct regional;
struct msg_parse;
struct ub_randstate;
struct query_info;
@@ -73,30 +74,33 @@ 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.
* if not null, that target is removed from the result list in the dp.
*/
struct delegpt_addr* iter_server_selection(struct iter_env* iter_env,
struct module_env* env, struct delegpt* dp, uint8_t* name,
size_t namelen);
size_t namelen, uint16_t qtype, int* dnssec_expected);
/**
* Allocate dns_msg from parsed msg, in region.
* Allocate dns_msg from parsed msg, in regional.
* @param pkt: packet.
* @param msg: parsed message (cleaned and ready for region allocation).
* @param region: region to use for allocation.
* @param msg: parsed message (cleaned and ready for regional allocation).
* @param regional: regional to use for allocation.
* @return newly allocated dns_msg, or NULL on memory error.
*/
struct dns_msg* dns_alloc_msg(ldns_buffer* pkt, struct msg_parse* msg,
struct region* region);
struct regional* regional);
/**
* Copy a dns_msg to this region.
* @param from: dns message, also in region.
* @param region: region to use for allocation.
* Copy a dns_msg to this regional.
* @param from: dns message, also in regional.
* @param regional: regional to use for allocation.
* @return newly allocated dns_msg, or NULL on memory error.
*/
struct dns_msg* dns_copy_msg(struct dns_msg* from, struct region* region);
struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);
/**
* Allocate a dns_msg with malloc/alloc structure and store in dns cache.
@@ -128,4 +132,50 @@ int iter_ns_probability(struct ub_randstate* rnd, int n, int m);
*/
void iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp);
/**
* See if delegation is useful or offers immediately no targets for
* further recursion.
* @param qstate: query state with RD flag and query name.
* @param dp: delegpt to check.
*/
int iter_dp_is_useless(struct module_qstate* qstate, struct delegpt* dp);
/**
* See if delegation is expected to have DNSSEC information (RRSIGs) in
* its answers, or not. Inspects delegation point (name), trust anchors,
* and delegation message (DS RRset) to determine this.
* @param env: module env with trust anchors.
* @param dp: delegation point.
* @param msg: delegation message, with DS if a secure referral.
* @param dclass: class of query.
* @return 1 if dnssec is expected, 0 if not.
*/
int iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
struct dns_msg* msg, uint16_t dclass);
/**
* See if a message contains DNSSEC.
* This is examined by looking for RRSIGs. With DNSSEC a valid answer,
* nxdomain, nodata, referral or cname reply has RRSIGs in answer or auth
* sections, sigs on answer data, SOA, DS, or NSEC/NSEC3 records.
* @param msg: message to examine.
* @return true if DNSSEC information was found.
*/
int iter_msg_has_dnssec(struct dns_msg* msg);
/**
* See if a message is known to be from a certain zone.
* This looks for SOA or NS rrsets, for answers.
* For referrals, when one label is delegated, the zone is detected.
* Does not look at signatures.
* @param msg: the message to inspect.
* @param dp: delegation point with zone name to look for.
* @param type: type of message.
* @param dclass: class of query.
* @return true if message is certain to be from zone in dp->name.
* false if not sure (empty msg), or not from the zone.
*/
int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp,
enum response_type type, uint16_t dclass);
#endif /* ITERATOR_ITER_UTILS_H */
+391 -157
View File
File diff suppressed because it is too large Load Diff
+54 -11
View File
@@ -44,7 +44,7 @@
#define ITERATOR_ITERATOR_H
#include "services/outbound_list.h"
#include "util/data/msgreply.h"
struct module_func_block;
#include "util/module.h"
struct delegpt;
struct iter_hints;
struct iter_forwards;
@@ -58,12 +58,18 @@ struct iter_prep_list;
/** how nice is a server without further information, in msec
* Equals rtt initial timeout value.
*/
#define UNKNOWN_SERVER_NICENESS 3000
#define UNKNOWN_SERVER_NICENESS 376
/** maximum timeout before a host is deemed unsuitable, in msec.
* After host_ttl this will be timed out and the host will be tried again.
* Equals RTT_MAX_TIMEOUT
*/
#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.
@@ -182,9 +188,17 @@ struct iter_qstate {
* This is a list of RRsets that must be prepended to the
* ANSWER section of a response before being sent upstream.
*/
struct iter_prep_list* prepend_list;
struct iter_prep_list* an_prepend_list;
/** Last element of the prepend list */
struct iter_prep_list* prepend_last;
struct iter_prep_list* an_prepend_last;
/**
* This is the list of RRsets that must be prepended to the
* AUTHORITY section of the response before being sent upstream.
*/
struct iter_prep_list* ns_prepend_list;
/** Last element of the authority prepend list */
struct iter_prep_list* ns_prepend_last;
/** query name used for chasing the results. Initially the same as
* the state qinfo, but after CNAMEs this will be different.
@@ -215,18 +229,18 @@ struct iter_qstate {
/** the number of times this query as followed a referral. */
int referral_count;
/**
* This flag, if true, means that this event is a priming query.
* In that case priming stub may be set as well.
/**
* expected dnssec information for this iteration step.
* If dnssec rrsigs are expected and not given, the server is marked
* lame (dnssec-lame).
*/
int priming;
int dnssec_expected;
/**
* This is flag that, if true, means that this event is
* representing a stub priming query. It is meaningless unless
* the finalState is the PRIMING_RESP_STATE.
* waiting for a stub priming query.
*/
int priming_stub;
int wait_priming_stub;
/**
* This is a flag that, if true, means that this query is
@@ -272,4 +286,33 @@ const char* iter_state_to_string(enum iter_state state);
*/
int iter_state_is_responsestate(enum iter_state s);
/** iterator init */
int iter_init(struct module_env* env, int id);
/** iterator deinit */
void iter_deinit(struct module_env* env, int id);
/** iterator operate on a query */
void iter_operate(struct module_qstate* qstate, enum module_ev event, int id,
struct outbound_entry* outbound);
/**
* Return priming query results to interestes super querystates.
*
* Sets the delegation point and delegation message (not nonRD queries).
* This is a callback from walk_supers.
*
* @param qstate: query state that finished.
* @param id: module id.
* @param super: the qstate to inform.
*/
void iter_inform_super(struct module_qstate* qstate, int id,
struct module_qstate* super);
/** iterator cleanup query state */
void iter_clear(struct module_qstate* qstate, int id);
/** iterator alloc size routine */
size_t iter_get_mem(struct module_env* env, int id);
#endif /* ITERATOR_ITERATOR_H */
BIN
View File
Binary file not shown.
+378
View File
@@ -0,0 +1,378 @@
/*
* libunbound/context.c - validating context for unbound internal use
*
* Copyright (c) 2007, 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 file contains the validator context structure.
*/
#include "config.h"
#include "libunbound/context.h"
#include "util/module.h"
#include "util/config_file.h"
#include "util/net_help.h"
#include "services/modstack.h"
#include "services/localzone.h"
#include "services/cache/rrset.h"
#include "services/cache/infra.h"
#include "util/data/msgreply.h"
#include "util/storage/slabhash.h"
int
context_finalize(struct ub_ctx* ctx)
{
struct config_file* cfg = ctx->env->cfg;
verbosity = cfg->verbosity;
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;
ctx->local_zones = local_zones_create();
if(!ctx->local_zones)
return UB_NOMEM;
if(!local_zones_apply_cfg(ctx->local_zones, cfg))
return UB_INITFAIL;
if(!ctx->env->msg_cache ||
cfg->msg_cache_size != slabhash_get_size(ctx->env->msg_cache) ||
cfg->msg_cache_slabs != ctx->env->msg_cache->size) {
slabhash_delete(ctx->env->msg_cache);
ctx->env->msg_cache = slabhash_create(cfg->msg_cache_slabs,
HASH_DEFAULT_STARTARRAY, cfg->msg_cache_size,
msgreply_sizefunc, query_info_compare,
query_entry_delete, reply_info_delete, NULL);
if(!ctx->env->msg_cache)
return UB_NOMEM;
}
ctx->env->rrset_cache = rrset_cache_adjust(ctx->env->rrset_cache,
ctx->env->cfg, ctx->env->alloc);
if(!ctx->env->rrset_cache)
return UB_NOMEM;
ctx->env->infra_cache = infra_adjust(ctx->env->infra_cache, cfg);
if(!ctx->env->infra_cache)
return UB_NOMEM;
ctx->finalized = 1;
return UB_NOERROR;
}
int context_query_cmp(const void* a, const void* b)
{
if( *(int*)a < *(int*)b )
return -1;
if( *(int*)a > *(int*)b )
return 1;
return 0;
}
void
context_query_delete(struct ctx_query* q)
{
if(!q) return;
ub_resolve_free(q->res);
free(q->msg);
free(q);
}
/** How many times to try to find an unused query-id-number for async */
#define NUM_ID_TRIES 100000
/** find next useful id number of 0 on error */
static int
find_id(struct ub_ctx* ctx, int* id)
{
size_t tries = 0;
ctx->next_querynum++;
while(rbtree_search(&ctx->queries, &ctx->next_querynum)) {
ctx->next_querynum++; /* numerical wraparound is fine */
if(tries++ > NUM_ID_TRIES)
return 0;
}
*id = ctx->next_querynum;
return 1;
}
struct ctx_query*
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;
lock_basic_lock(&ctx->cfglock);
if(!find_id(ctx, &q->querynum)) {
lock_basic_unlock(&ctx->cfglock);
free(q);
return NULL;
}
lock_basic_unlock(&ctx->cfglock);
q->node.key = &q->querynum;
q->async = (cb != NULL);
q->cb = cb;
q->cb_arg = cbarg;
q->res = (struct ub_result*)calloc(1, sizeof(*q->res));
if(!q->res) {
free(q);
return NULL;
}
q->res->qname = strdup(name);
if(!q->res->qname) {
free(q->res);
free(q);
return NULL;
}
q->res->qtype = rrtype;
q->res->qclass = rrclass;
/* add to query list */
lock_basic_lock(&ctx->cfglock);
if(q->async)
ctx->num_async ++;
(void)rbtree_insert(&ctx->queries, &q->node);
lock_basic_unlock(&ctx->cfglock);
return q;
}
struct alloc_cache*
context_obtain_alloc(struct ub_ctx* ctx, int locking)
{
struct alloc_cache* a;
int tnum = 0;
if(locking) {
lock_basic_lock(&ctx->cfglock);
}
a = ctx->alloc_list;
if(a)
ctx->alloc_list = a->super; /* snip off list */
else tnum = ctx->thr_next_num++;
if(locking) {
lock_basic_unlock(&ctx->cfglock);
}
if(a) {
a->super = &ctx->superalloc;
return a;
}
a = (struct alloc_cache*)calloc(1, sizeof(*a));
if(!a)
return NULL;
alloc_init(a, &ctx->superalloc, tnum);
return a;
}
void
context_release_alloc(struct ub_ctx* ctx, struct alloc_cache* alloc,
int locking)
{
if(!ctx || !alloc)
return;
if(locking) {
lock_basic_lock(&ctx->cfglock);
}
alloc->super = ctx->alloc_list;
ctx->alloc_list = alloc;
if(locking) {
lock_basic_unlock(&ctx->cfglock);
}
}
uint8_t*
context_serialize_new_query(struct ctx_query* q, uint32_t* len)
{
/* format for new query is
* o uint32 cmd
* o uint32 id
* o uint32 type
* o uint32 class
* o rest queryname (string)
*/
uint8_t* p;
size_t slen = strlen(q->res->qname) + 1/*end of string*/;
*len = sizeof(uint32_t)*4 + slen;
p = (uint8_t*)malloc(*len);
if(!p) return NULL;
ldns_write_uint32(p, UB_LIBCMD_NEWQUERY);
ldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum);
ldns_write_uint32(p+2*sizeof(uint32_t), (uint32_t)q->res->qtype);
ldns_write_uint32(p+3*sizeof(uint32_t), (uint32_t)q->res->qclass);
memmove(p+4*sizeof(uint32_t), q->res->qname, slen);
return p;
}
struct ctx_query*
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;
if(len < 4*sizeof(uint32_t)+1) {
free(q);
return NULL;
}
log_assert( ldns_read_uint32(p) == UB_LIBCMD_NEWQUERY);
q->querynum = (int)ldns_read_uint32(p+sizeof(uint32_t));
q->node.key = &q->querynum;
q->async = 1;
q->res = (struct ub_result*)calloc(1, sizeof(*q->res));
if(!q->res) {
free(q);
return NULL;
}
q->res->qtype = (int)ldns_read_uint32(p+2*sizeof(uint32_t));
q->res->qclass = (int)ldns_read_uint32(p+3*sizeof(uint32_t));
q->res->qname = strdup((char*)(p+4*sizeof(uint32_t)));
if(!q->res->qname) {
free(q->res);
free(q);
return NULL;
}
/** add to query list */
ctx->num_async++;
(void)rbtree_insert(&ctx->queries, &q->node);
return q;
}
struct ctx_query*
context_lookup_new_query(struct ub_ctx* ctx, uint8_t* p, uint32_t len)
{
struct ctx_query* q;
int querynum;
if(len < 4*sizeof(uint32_t)+1) {
return NULL;
}
log_assert( ldns_read_uint32(p) == UB_LIBCMD_NEWQUERY);
querynum = (int)ldns_read_uint32(p+sizeof(uint32_t));
q = (struct ctx_query*)rbtree_search(&ctx->queries, &querynum);
if(!q) {
return NULL;
}
log_assert(q->async);
return q;
}
uint8_t*
context_serialize_answer(struct ctx_query* q, int err, ldns_buffer* pkt,
uint32_t* len)
{
/* answer format
* o uint32 cmd
* o uint32 id
* o uint32 error_code
* o uint32 msg_security
* o the remainder is the answer msg from resolver lookup.
* remainder can be length 0.
*/
size_t pkt_len = pkt?ldns_buffer_remaining(pkt):0;
uint8_t* p;
*len = sizeof(uint32_t)*4 + pkt_len;
p = (uint8_t*)malloc(*len);
if(!p) return NULL;
ldns_write_uint32(p, UB_LIBCMD_ANSWER);
ldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum);
ldns_write_uint32(p+2*sizeof(uint32_t), (uint32_t)err);
ldns_write_uint32(p+3*sizeof(uint32_t), (uint32_t)q->msg_security);
if(pkt_len > 0)
memmove(p+4*sizeof(uint32_t), ldns_buffer_begin(pkt), pkt_len);
return p;
}
struct ctx_query*
context_deserialize_answer(struct ub_ctx* ctx,
uint8_t* p, uint32_t len, int* err)
{
struct ctx_query* q = NULL ;
int id;
if(len < 4*sizeof(uint32_t)) return NULL;
log_assert( ldns_read_uint32(p) == UB_LIBCMD_ANSWER);
id = (int)ldns_read_uint32(p+sizeof(uint32_t));
q = (struct ctx_query*)rbtree_search(&ctx->queries, &id);
if(!q) return NULL;
*err = (int)ldns_read_uint32(p+2*sizeof(uint32_t));
q->msg_security = ldns_read_uint32(p+3*sizeof(uint32_t));
if(len > 4*sizeof(uint32_t)) {
q->msg_len = len - 4*sizeof(uint32_t);
q->msg = (uint8_t*)memdup(p+4*sizeof(uint32_t), q->msg_len);
if(!q->msg) {
/* pass malloc failure to the user callback */
q->msg_len = 0;
*err = UB_NOMEM;
return q;
}
}
return q;
}
uint8_t*
context_serialize_cancel(struct ctx_query* q, uint32_t* len)
{
/* format of cancel:
* o uint32 cmd
* o uint32 async-id */
uint8_t* p = (uint8_t*)malloc(2*sizeof(uint32_t));
if(!p) return NULL;
*len = 2*sizeof(uint32_t);
ldns_write_uint32(p, UB_LIBCMD_CANCEL);
ldns_write_uint32(p+sizeof(uint32_t), (uint32_t)q->querynum);
return p;
}
struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx,
uint8_t* p, uint32_t len)
{
struct ctx_query* q;
int id;
if(len != 2*sizeof(uint32_t)) return NULL;
log_assert( ldns_read_uint32(p) == UB_LIBCMD_CANCEL);
id = (int)ldns_read_uint32(p+sizeof(uint32_t));
q = (struct ctx_query*)rbtree_search(&ctx->queries, &id);
return q;
}
uint8_t*
context_serialize_quit(uint32_t* len)
{
uint8_t* p = (uint8_t*)malloc(sizeof(uint32_t));
if(!p)
return NULL;
*len = sizeof(uint32_t);
ldns_write_uint32(p, UB_LIBCMD_QUIT);
return p;
}
enum ub_ctx_cmd context_serial_getcmd(uint8_t* p, uint32_t len)
{
uint32_t v;
if((size_t)len < sizeof(v))
return UB_LIBCMD_QUIT;
v = ldns_read_uint32(p);
return v;
}
+342
View File
@@ -0,0 +1,342 @@
/*
* libunbound/context.h - validating context for unbound internal use
*
* Copyright (c) 2007, 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 file contains the validator context structure.
*/
#ifndef LIBUNBOUND_CONTEXT_H
#define LIBUNBOUND_CONTEXT_H
#include "util/locks.h"
#include "util/alloc.h"
#include "util/rbtree.h"
#include "services/modstack.h"
#include "libunbound/unbound.h"
#include "util/data/packed_rrset.h"
struct libworker;
/**
* The context structure
*
* Contains two pipes for async service
* qq : write queries to the async service pid/tid.
* rr : read results from the async service pid/tid.
*/
struct ub_ctx {
/* --- pipes --- */
/** mutex on query write pipe */
lock_basic_t qqpipe_lock;
/** the query write pipe, [0] read from, [1] write on */
int qqpipe[2];
/** mutex on result read pipe */
lock_basic_t rrpipe_lock;
/** the result read pipe, [0] read from, [1] write on */
int rrpipe[2];
/* --- shared data --- */
/** mutex for access to env.cfg, finalized and dothread */
lock_basic_t cfglock;
/**
* The context has been finalized
* This is after config when the first resolve is done.
* The modules are inited (module-init()) and shared caches created.
*/
int finalized;
/** is bg worker created yet ? */
int created_bg;
/** pid of bg worker process */
pid_t bg_pid;
/** tid of bg worker thread */
ub_thread_t bg_tid;
/** do threading (instead of forking) for async resolution */
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
* to link a simply linked list. Reset super member to the superalloc
* before use.
*/
struct alloc_cache* alloc_list;
/** shared caches, and so on */
struct alloc_cache superalloc;
/** module env master value */
struct module_env* env;
/** module stack */
struct module_stack mods;
/** local authority zones */
struct local_zones* local_zones;
/** random state used to seed new random state structures */
struct ub_randstate* seed_rnd;
/** next query number (to try) to use */
int next_querynum;
/** number of async queries outstanding */
size_t num_async;
/**
* Tree of outstanding queries. Indexed by querynum
* Used when results come in for async to lookup.
* Used when cancel is done for lookup (and delete).
* Used to see if querynum is free for use.
* Content of type ctx_query.
*/
rbtree_t queries;
};
/**
* The queries outstanding for the libunbound resolver.
* These are outstanding for async resolution.
* But also, outstanding for sync resolution by one of the threads that
* has joined the threadpool.
*/
struct ctx_query {
/** node in rbtree, must be first entry, key is ptr to the querynum */
struct rbnode_t node;
/** query id number, key for node */
int querynum;
/** was this an async query? */
int async;
/** was this query cancelled (for bg worker) */
int cancelled;
/** for async query, the callback function */
ub_callback_t cb;
/** for async query, the callback user arg */
void* cb_arg;
/** answer message, result from resolver lookup. */
uint8_t* msg;
/** resulting message length. */
size_t msg_len;
/** validation status on security */
enum sec_status msg_security;
/** store libworker that is handling this query */
struct libworker* w;
/** result structure, also contains original query, type, class.
* malloced ptr ready to hand to the client. */
struct ub_result* res;
};
/**
* The error constants
*/
enum ub_ctx_err {
/** no error */
UB_NOERROR = 0,
/** socket operation. Set to -1, so that if an error from _fd() is
* passed (-1) it gives a socket error. */
UB_SOCKET = -1,
/** alloc failure */
UB_NOMEM = -2,
/** syntax error */
UB_SYNTAX = -3,
/** DNS service failed */
UB_SERVFAIL = -4,
/** fork() failed */
UB_FORKFAIL = -5,
/** cfg change after finalize() */
UB_AFTERFINAL = -6,
/** initialization failed (bad settings) */
UB_INITFAIL = -7,
/** error in pipe communication with async bg worker */
UB_PIPE = -8,
/** error reading from file (resolv.conf) */
UB_READFILE = -9
};
/**
* Command codes for libunbound pipe.
*
* Serialization looks like this:
* o length (of remainder) uint32.
* o uint32 command code.
* o per command format.
*/
enum ub_ctx_cmd {
/** QUIT */
UB_LIBCMD_QUIT = 0,
/** New query, sent to bg worker */
UB_LIBCMD_NEWQUERY,
/** Cancel query, sent to bg worker */
UB_LIBCMD_CANCEL,
/** Query result, originates from bg worker */
UB_LIBCMD_ANSWER
};
/**
* finalize a context.
* @param ctx: context to finalize. creates shared data.
* @return 0 if OK, or errcode.
*/
int context_finalize(struct ub_ctx* ctx);
/** compare two ctx_query elements */
int context_query_cmp(const void* a, const void* b);
/**
* delete context query
* @param q: query to delete, including message packet and prealloc result
*/
void context_query_delete(struct ctx_query* q);
/**
* Create new query in context, add to querynum list.
* @param ctx: context
* @param name: query name
* @param rrtype: type
* @param rrclass: class
* @param cb: callback for async, or NULL for sync.
* @param cbarg: user arg for async queries.
* @return new ctx_query or NULL for malloc failure.
*/
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.
* @param ctx: context
* @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_ctx* ctx, int locking);
/**
* Release an alloc. Puts it into the cache.
* @param ctx: context
* @param locking: if true, cfglock is locked while releasing alloc.
* @param alloc: alloc to relinquish.
*/
void context_release_alloc(struct ub_ctx* ctx, struct alloc_cache* alloc,
int locking);
/**
* Serialize a context query that questions data.
* This serializes the query name, type, ...
* As well as command code 'new_query'.
* @param q: context query
* @param len: the length of the allocation is returned.
* @return: an alloc, or NULL on mem error.
*/
uint8_t* context_serialize_new_query(struct ctx_query* q, uint32_t* len);
/**
* Serialize a context_query result to hand back to user.
* This serializes the query name, type, ..., and result.
* As well as command code 'answer'.
* @param q: context query
* @param err: error code to pass to client.
* @param pkt: the packet to add, can be NULL.
* @param len: the length of the allocation is returned.
* @return: an alloc, or NULL on mem error.
*/
uint8_t* context_serialize_answer(struct ctx_query* q, int err,
ldns_buffer* pkt, uint32_t* len);
/**
* Serialize a query cancellation. Serializes query async id
* as well as command code 'cancel'
* @param q: context query
* @param len: the length of the allocation is returned.
* @return: an alloc, or NULL on mem error.
*/
uint8_t* context_serialize_cancel(struct ctx_query* q, uint32_t* len);
/**
* Serialize a 'quit' command.
* @param len: the length of the allocation is returned.
* @return: an alloc, or NULL on mem error.
*/
uint8_t* context_serialize_quit(uint32_t* len);
/**
* Obtain command code from serialized buffer
* @param p: buffer serialized.
* @param len: length of buffer.
* @return command code or QUIT on error.
*/
enum ub_ctx_cmd context_serial_getcmd(uint8_t* p, uint32_t len);
/**
* Lookup query from new_query buffer.
* @param ctx: context
* @param p: buffer serialized.
* @param len: length of buffer.
* @return looked up ctx_query or NULL for malloc failure.
*/
struct ctx_query* context_lookup_new_query(struct ub_ctx* ctx,
uint8_t* p, uint32_t len);
/**
* Deserialize a new_query buffer.
* @param ctx: context
* @param p: buffer serialized.
* @param len: length of buffer.
* @return new ctx_query or NULL for malloc failure.
*/
struct ctx_query* context_deserialize_new_query(struct ub_ctx* ctx,
uint8_t* p, uint32_t len);
/**
* Deserialize an answer buffer.
* @param ctx: context
* @param p: buffer serialized.
* @param len: length of buffer.
* @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_ctx* ctx,
uint8_t* p, uint32_t len, int* err);
/**
* Deserialize a cancel buffer.
* @param ctx: context
* @param p: buffer serialized.
* @param len: length of buffer.
* @return ctx_query to cancel or NULL for failure.
*/
struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx,
uint8_t* p, uint32_t len);
#endif /* LIBUNBOUND_CONTEXT_H */
+953
View File
@@ -0,0 +1,953 @@
/*
* unbound.c - unbound validating resolver public API implementation
*
* Copyright (c) 2007, 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 file contains functions to resolve DNS queries and
* validate the answers. Synchonously and asynchronously.
*
*/
/* include the public api first, it should be able to stand alone */
#include "libunbound/unbound.h"
#include "config.h"
#include "libunbound/context.h"
#include "libunbound/libworker.h"
#include "util/locks.h"
#include "util/config_file.h"
#include "util/alloc.h"
#include "util/module.h"
#include "util/regional.h"
#include "util/log.h"
#include "util/random.h"
#include "util/net_help.h"
#include "services/modstack.h"
#include "services/localzone.h"
#include "services/cache/infra.h"
#include "services/cache/rrset.h"
struct ub_ctx*
ub_ctx_create()
{
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_ctx*)calloc(1, sizeof(*ctx));
if(!ctx) {
errno = ENOMEM;
return NULL;
}
alloc_init(&ctx->superalloc, NULL, 0);
seed = (unsigned int)time(NULL) ^ (unsigned int)getpid();
if(!(ctx->seed_rnd = ub_initstate(seed, NULL))) {
seed = 0;
ub_randfree(ctx->seed_rnd);
free(ctx);
errno = ENOMEM;
return NULL;
}
seed = 0;
if(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx->qqpipe) == -1) {
ub_randfree(ctx->seed_rnd);
free(ctx);
return NULL;
}
if(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx->rrpipe) == -1) {
int e = errno;
close(ctx->qqpipe[0]);
close(ctx->qqpipe[1]);
ub_randfree(ctx->seed_rnd);
free(ctx);
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]) ||
!fd_set_nonblock(ctx->qqpipe[1])) {
int e = errno;
close(ctx->rrpipe[0]);
close(ctx->rrpipe[1]);
close(ctx->qqpipe[0]);
close(ctx->qqpipe[1]);
ub_randfree(ctx->seed_rnd);
free(ctx);
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);
ctx->env = (struct module_env*)calloc(1, sizeof(*ctx->env));
if(!ctx->env) {
close(ctx->rrpipe[0]);
close(ctx->rrpipe[1]);
close(ctx->qqpipe[0]);
close(ctx->qqpipe[1]);
ub_randfree(ctx->seed_rnd);
free(ctx);
errno = ENOMEM;
return NULL;
}
ctx->env->cfg = config_create_forlib();
if(!ctx->env->cfg) {
close(ctx->rrpipe[0]);
close(ctx->rrpipe[1]);
close(ctx->qqpipe[0]);
close(ctx->qqpipe[1]);
free(ctx->env);
ub_randfree(ctx->seed_rnd);
free(ctx);
errno = ENOMEM;
return NULL;
}
ctx->env->alloc = &ctx->superalloc;
ctx->env->worker = NULL;
ctx->env->need_to_validate = 0;
modstack_init(&ctx->mods);
rbtree_init(&ctx->queries, &context_query_cmp);
return ctx;
}
/** delete q */
static void
delq(rbnode_t* n, void* ATTR_UNUSED(arg))
{
struct ctx_query* q = (struct ctx_query*)n;
context_query_delete(q);
}
void
ub_ctx_delete(struct ub_ctx* ctx)
{
struct alloc_cache* a, *na;
if(!ctx) return;
/* stop the bg thread */
lock_basic_lock(&ctx->cfglock);
if(ctx->created_bg) {
uint8_t* msg;
uint32_t len;
uint32_t cmd = UB_LIBCMD_QUIT;
lock_basic_unlock(&ctx->cfglock);
lock_basic_lock(&ctx->qqpipe_lock);
(void)libworker_write_msg(ctx->qqpipe[1], (uint8_t*)&cmd,
(uint32_t)sizeof(cmd), 0);
lock_basic_unlock(&ctx->qqpipe_lock);
lock_basic_lock(&ctx->rrpipe_lock);
while(libworker_read_msg(ctx->rrpipe[0], &msg, &len, 0)) {
/* discard all results except a quit confirm */
if(context_serial_getcmd(msg, len) == UB_LIBCMD_QUIT) {
free(msg);
break;
}
free(msg);
}
lock_basic_unlock(&ctx->rrpipe_lock);
/* if bg worker is a thread, wait for it to exit, so that all
* resources are really gone. */
lock_basic_lock(&ctx->cfglock);
if(ctx->dothread) {
lock_basic_unlock(&ctx->cfglock);
ub_thread_join(ctx->bg_tid);
} else {
lock_basic_unlock(&ctx->cfglock);
}
}
else {
lock_basic_unlock(&ctx->cfglock);
}
modstack_desetup(&ctx->mods, ctx->env);
a = ctx->alloc_list;
while(a) {
na = a->super;
a->super = &ctx->superalloc;
alloc_clear(a);
free(a);
a = na;
}
local_zones_delete(ctx->local_zones);
lock_basic_destroy(&ctx->qqpipe_lock);
lock_basic_destroy(&ctx->rrpipe_lock);
lock_basic_destroy(&ctx->cfglock);
if(ctx->qqpipe[0] != -1)
close(ctx->qqpipe[0]);
if(ctx->qqpipe[1] != -1)
close(ctx->qqpipe[1]);
if(ctx->rrpipe[0] != -1)
close(ctx->rrpipe[0]);
if(ctx->rrpipe[1] != -1)
close(ctx->rrpipe[1]);
ctx->qqpipe[0] = -1;
ctx->qqpipe[1] = -1;
ctx->rrpipe[0] = -1;
ctx->rrpipe[1] = -1;
if(ctx->env) {
slabhash_delete(ctx->env->msg_cache);
rrset_cache_delete(ctx->env->rrset_cache);
infra_delete(ctx->env->infra_cache);
config_delete(ctx->env->cfg);
free(ctx->env);
}
ub_randfree(ctx->seed_rnd);
alloc_clear(&ctx->superalloc);
traverse_postorder(&ctx->queries, delq, NULL);
free(ctx);
#ifdef USE_WINSOCK
WSACleanup();
#endif
}
int
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) {
lock_basic_unlock(&ctx->cfglock);
return UB_AFTERFINAL;
}
if(!config_read(ctx->env->cfg, fname)) {
lock_basic_unlock(&ctx->cfglock);
return UB_SYNTAX;
}
lock_basic_unlock(&ctx->cfglock);
return UB_NOERROR;
}
int
ub_ctx_add_ta(struct ub_ctx* ctx, char* ta)
{
char* dup = strdup(ta);
if(!dup) return UB_NOMEM;
lock_basic_lock(&ctx->cfglock);
if(ctx->finalized) {
lock_basic_unlock(&ctx->cfglock);
return UB_AFTERFINAL;
}
if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_list, dup)) {
lock_basic_unlock(&ctx->cfglock);
free(dup);
return UB_NOMEM;
}
lock_basic_unlock(&ctx->cfglock);
return UB_NOERROR;
}
int
ub_ctx_add_ta_file(struct ub_ctx* ctx, char* fname)
{
char* dup = strdup(fname);
if(!dup) return UB_NOMEM;
lock_basic_lock(&ctx->cfglock);
if(ctx->finalized) {
lock_basic_unlock(&ctx->cfglock);
return UB_AFTERFINAL;
}
if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_file_list, dup)) {
lock_basic_unlock(&ctx->cfglock);
free(dup);
return UB_NOMEM;
}
lock_basic_unlock(&ctx->cfglock);
return UB_NOERROR;
}
int
ub_ctx_trustedkeys(struct ub_ctx* ctx, char* fname)
{
char* dup = strdup(fname);
if(!dup) return UB_NOMEM;
lock_basic_lock(&ctx->cfglock);
if(ctx->finalized) {
lock_basic_unlock(&ctx->cfglock);
return UB_AFTERFINAL;
}
if(!cfg_strlist_insert(&ctx->env->cfg->trusted_keys_file_list, dup)) {
lock_basic_unlock(&ctx->cfglock);
free(dup);
return UB_NOMEM;
}
lock_basic_unlock(&ctx->cfglock);
return UB_NOERROR;
}
int
ub_ctx_debuglevel(struct ub_ctx* ctx, int d)
{
lock_basic_lock(&ctx->cfglock);
verbosity = d;
ctx->env->cfg->verbosity = d;
lock_basic_unlock(&ctx->cfglock);
return UB_NOERROR;
}
int ub_ctx_debugout(struct ub_ctx* ctx, void* out)
{
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
lock_basic_lock(&ctx->cfglock);
if(ctx->finalized) {
lock_basic_unlock(&ctx->cfglock);
return UB_AFTERFINAL;
}
ctx->dothread = dothread;
lock_basic_unlock(&ctx->cfglock);
return UB_NOERROR;
}
/** perform a select() on the result read pipe */
static int
pollit(struct ub_ctx* ctx, struct timeval* t)
{
fd_set r;
#ifndef S_SPLINT_S
FD_ZERO(&r);
FD_SET(FD_SET_T ctx->rrpipe[0], &r);
#endif
if(select(ctx->rrpipe[0]+1, &r, NULL, NULL, t) == -1) {
return 0;
}
errno = 0;
return FD_ISSET(ctx->rrpipe[0], &r);
}
int
ub_poll(struct ub_ctx* ctx)
{
struct timeval t;
memset(&t, 0, sizeof(t));
/* no need to hold lock while testing for readability. */
return pollit(ctx, &t);
}
int
ub_fd(struct ub_ctx* ctx)
{
return ctx->rrpipe[0];
}
/** process answer from bg worker */
static int
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) {
log_err("error: bad data from bg worker %d",
(int)context_serial_getcmd(msg, len));
return 0;
}
lock_basic_lock(&ctx->cfglock);
q = context_deserialize_answer(ctx, msg, len, err);
if(!q) {
lock_basic_unlock(&ctx->cfglock);
/* probably simply the lookup that failed, i.e.
* response returned before cancel was sent out, so noerror */
return 1;
}
log_assert(q->async);
/* grab cb while locked */
if(q->cancelled) {
*cb = NULL;
*cbarg = NULL;
} else {
*cb = q->cb;
*cbarg = q->cb_arg;
}
if(*err) {
*res = NULL;
ub_resolve_free(q->res);
} else {
/* parse the message, extract rcode, fill result */
ldns_buffer* buf = ldns_buffer_new(q->msg_len);
struct regional* region = regional_create();
*res = q->res;
(*res)->rcode = LDNS_RCODE_SERVFAIL;
if(region && buf) {
ldns_buffer_clear(buf);
ldns_buffer_write(buf, q->msg, q->msg_len);
ldns_buffer_flip(buf);
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);
}
q->res = NULL;
/* delete the q from list */
(void)rbtree_delete(&ctx->queries, q->node.key);
ctx->num_async--;
context_query_delete(q);
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_ctx* ctx, uint8_t* msg, uint32_t len)
{
int err;
ub_callback_t cb;
void* cbarg;
struct ub_result* res;
int r;
r = process_answer_detail(ctx, msg, len, &cb, &cbarg, &err, &res);
/* no locks held while calling callback, so that library is
* re-entrant. */
if(r == 2)
(*cb)(cbarg, err, res);
return r;
}
int
ub_process(struct ub_ctx* ctx)
{
int r;
uint8_t* msg;
uint32_t len;
while(1) {
msg = NULL;
lock_basic_lock(&ctx->rrpipe_lock);
r = libworker_read_msg(ctx->rrpipe[0], &msg, &len, 1);
lock_basic_unlock(&ctx->rrpipe_lock);
if(r == 0)
return UB_PIPE;
else if(r == -1)
return UB_NOERROR;
if(!process_answer(ctx, msg, len)) {
free(msg);
return UB_PIPE;
}
free(msg);
}
return UB_NOERROR;
}
int
ub_wait(struct ub_ctx* ctx)
{
int err;
ub_callback_t cb;
void* cbarg;
struct ub_result* res;
int r;
uint8_t* msg;
uint32_t len;
/* this is basically the same loop as _process(), but with changes.
* holds the rrpipe lock and waits with pollit */
while(1) {
lock_basic_lock(&ctx->rrpipe_lock);
lock_basic_lock(&ctx->cfglock);
if(ctx->num_async == 0) {
lock_basic_unlock(&ctx->cfglock);
lock_basic_unlock(&ctx->rrpipe_lock);
break;
}
lock_basic_unlock(&ctx->cfglock);
/* keep rrpipe locked, while
* o waiting for pipe readable
* o parsing message
* o possibly decrementing num_async
* do callback without lock
*/
r = pollit(ctx, NULL);
if(r) {
r = libworker_read_msg(ctx->rrpipe[0], &msg, &len, 1);
if(r == 0) {
lock_basic_unlock(&ctx->rrpipe_lock);
return UB_PIPE;
}
if(r == -1) {
lock_basic_unlock(&ctx->rrpipe_lock);
continue;
}
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)
(*cb)(cbarg, err, res);
} else {
lock_basic_unlock(&ctx->rrpipe_lock);
}
}
return UB_NOERROR;
}
int
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) {
r = context_finalize(ctx);
if(r) {
lock_basic_unlock(&ctx->cfglock);
return r;
}
}
/* create new ctx_query and attempt to add to the list */
lock_basic_unlock(&ctx->cfglock);
q = context_new(ctx, name, rrtype, rrclass, NULL, NULL);
if(!q)
return UB_NOMEM;
/* become a resolver thread for a bit */
r = libworker_fg(ctx, q);
if(r) {
lock_basic_lock(&ctx->cfglock);
(void)rbtree_delete(&ctx->queries, q->node.key);
context_query_delete(q);
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;
lock_basic_lock(&ctx->cfglock);
(void)rbtree_delete(&ctx->queries, q->node.key);
context_query_delete(q);
lock_basic_unlock(&ctx->cfglock);
return UB_NOERROR;
}
int
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;
uint32_t len = 0;
if(async_id)
*async_id = 0;
lock_basic_lock(&ctx->cfglock);
if(!ctx->finalized) {
int r = context_finalize(ctx);
if(r) {
lock_basic_unlock(&ctx->cfglock);
return r;
}
}
if(!ctx->created_bg) {
int r;
ctx->created_bg = 1;
lock_basic_unlock(&ctx->cfglock);
r = libworker_bg(ctx);
if(r) {
lock_basic_lock(&ctx->cfglock);
ctx->created_bg = 0;
lock_basic_unlock(&ctx->cfglock);
return r;
}
} else {
lock_basic_unlock(&ctx->cfglock);
}
/* create new ctx_query and attempt to add to the list */
q = context_new(ctx, name, rrtype, rrclass, callback, mydata);
if(!q)
return UB_NOMEM;
/* write over pipe to background worker */
lock_basic_lock(&ctx->cfglock);
msg = context_serialize_new_query(q, &len);
if(!msg) {
(void)rbtree_delete(&ctx->queries, q->node.key);
ctx->num_async--;
context_query_delete(q);
lock_basic_unlock(&ctx->cfglock);
return UB_NOMEM;
}
if(async_id)
*async_id = q->querynum;
lock_basic_unlock(&ctx->cfglock);
lock_basic_lock(&ctx->qqpipe_lock);
if(!libworker_write_msg(ctx->qqpipe[1], msg, len, 0)) {
lock_basic_unlock(&ctx->qqpipe_lock);
free(msg);
return UB_PIPE;
}
lock_basic_unlock(&ctx->qqpipe_lock);
free(msg);
return UB_NOERROR;
}
int
ub_cancel(struct ub_ctx* ctx, int async_id)
{
struct ctx_query* q;
uint8_t* msg = NULL;
uint32_t len = 0;
lock_basic_lock(&ctx->cfglock);
q = (struct ctx_query*)rbtree_search(&ctx->queries, &async_id);
if(!q || !q->async) {
/* it is not there, so nothing to do */
lock_basic_unlock(&ctx->cfglock);
return UB_NOERROR;
}
log_assert(q->async);
q->cancelled = 1;
/* delete it */
if(!ctx->dothread) { /* if forked */
(void)rbtree_delete(&ctx->queries, q->node.key);
ctx->num_async--;
msg = context_serialize_cancel(q, &len);
context_query_delete(q);
lock_basic_unlock(&ctx->cfglock);
if(!msg) {
return UB_NOMEM;
}
/* send cancel to background worker */
lock_basic_lock(&ctx->qqpipe_lock);
if(!libworker_write_msg(ctx->qqpipe[1], msg, len, 0)) {
lock_basic_unlock(&ctx->qqpipe_lock);
free(msg);
return UB_PIPE;
}
lock_basic_unlock(&ctx->qqpipe_lock);
free(msg);
} else {
lock_basic_unlock(&ctx->cfglock);
}
return UB_NOERROR;
}
void
ub_resolve_free(struct ub_result* result)
{
char** p;
if(!result) return;
free(result->qname);
if(result->canonname != result->qname)
free(result->canonname);
if(result->data)
for(p = result->data; *p; p++)
free(*p);
free(result->data);
free(result->len);
free(result->answer_packet);
free(result);
}
const char*
ub_strerror(int err)
{
switch(err) {
case UB_NOERROR: return "no error";
case UB_SOCKET: return "socket io error";
case UB_NOMEM: return "out of memory";
case UB_SYNTAX: return "syntax error";
case UB_SERVFAIL: return "server failure";
case UB_FORKFAIL: return "could not fork";
case UB_INITFAIL: return "initialization failure";
case UB_AFTERFINAL: return "setting change after finalize";
case UB_PIPE: return "error in pipe communication with async";
case UB_READFILE: return "error reading file";
default: return "unknown error";
}
}
int
ub_ctx_set_fwd(struct ub_ctx* ctx, char* addr)
{
struct sockaddr_storage storage;
socklen_t stlen;
struct config_stub* s;
char* dupl;
lock_basic_lock(&ctx->cfglock);
if(ctx->finalized) {
lock_basic_unlock(&ctx->cfglock);
errno=EINVAL;
return UB_AFTERFINAL;
}
if(!addr) {
/* disable fwd mode - the root stub should be first. */
if(ctx->env->cfg->forwards &&
strcmp(ctx->env->cfg->forwards->name, ".") == 0) {
s = ctx->env->cfg->forwards;
ctx->env->cfg->forwards = s->next;
s->next = NULL;
config_delstubs(s);
}
lock_basic_unlock(&ctx->cfglock);
return UB_NOERROR;
}
lock_basic_unlock(&ctx->cfglock);
/* check syntax for addr */
if(!extstrtoaddr(addr, &storage, &stlen)) {
errno=EINVAL;
return UB_SYNTAX;
}
/* it parses, add root stub in front of list */
lock_basic_lock(&ctx->cfglock);
if(!ctx->env->cfg->forwards ||
strcmp(ctx->env->cfg->forwards->name, ".") != 0) {
s = calloc(1, sizeof(*s));
if(!s) {
lock_basic_unlock(&ctx->cfglock);
errno=ENOMEM;
return UB_NOMEM;
}
s->name = strdup(".");
if(!s->name) {
free(s);
lock_basic_unlock(&ctx->cfglock);
errno=ENOMEM;
return UB_NOMEM;
}
s->next = ctx->env->cfg->forwards;
ctx->env->cfg->forwards = s;
} else {
log_assert(ctx->env->cfg->forwards);
s = ctx->env->cfg->forwards;
}
dupl = strdup(addr);
if(!dupl) {
lock_basic_unlock(&ctx->cfglock);
errno=ENOMEM;
return UB_NOMEM;
}
if(!cfg_strlist_insert(&s->addrs, dupl)) {
free(dupl);
lock_basic_unlock(&ctx->cfglock);
errno=ENOMEM;
return UB_NOMEM;
}
lock_basic_unlock(&ctx->cfglock);
return UB_NOERROR;
}
int
ub_ctx_resolvconf(struct ub_ctx* ctx, char* fname)
{
FILE* in;
int numserv = 0;
char buf[1024];
char* parse, *addr;
int r;
if(fname == NULL)
fname = "/etc/resolv.conf";
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(strncmp(parse, "nameserver", 10) == 0) {
numserv++;
parse += 10; /* skip 'nameserver' */
/* skip whitespace */
while(*parse == ' ' || *parse == '\t')
parse++;
addr = parse;
/* skip [0-9a-fA-F.:]*, i.e. IP4 and IP6 address */
while(isxdigit(*parse) || *parse=='.' || *parse==':')
parse++;
/* terminate after the address, remove newline */
*parse = 0;
if((r = ub_ctx_set_fwd(ctx, addr)) != UB_NOERROR) {
fclose(in);
return r;
}
}
}
fclose(in);
if(numserv == 0) {
/* from resolv.conf(5) if none given, use localhost */
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;
}
File diff suppressed because it is too large Load Diff
+236
View File
@@ -0,0 +1,236 @@
/*
* libunbound/worker.h - worker thread or process that resolves
*
* Copyright (c) 2007, 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 file contains the worker process or thread that performs
* the DNS resolving and validation. The worker is called by a procedure
* and if in the background continues until exit, if in the foreground
* returns from the procedure when done.
*/
#ifndef LIBUNBOUND_WORKER_H
#define LIBUNBOUND_WORKER_H
#include "util/data/packed_rrset.h"
struct ub_ctx;
struct ub_result;
struct module_env;
struct comm_base;
struct outside_network;
struct ub_randstate;
struct ctx_query;
struct outbound_entry;
struct module_qstate;
struct comm_point;
struct comm_reply;
struct libworker_res_list;
struct regional;
/**
* The library-worker status structure
* Internal to the worker.
*/
struct libworker {
/** every worker has a unique thread_num. (first in struct) */
int thread_num;
/** context we are operating under */
struct ub_ctx* ctx;
/** is this the bg worker? */
int is_bg;
/** is this a bg worker that is threaded (not forked)? */
int is_bg_thread;
/** copy of the module environment with worker local entries. */
struct module_env* env;
/** the event base this worker works with */
struct comm_base* base;
/** the backside outside network interface to the auth servers */
struct outside_network* back;
/** random() table for this worker. */
struct ub_randstate* rndstate;
/** commpoint to listen to commands */
struct comm_point* cmd_com;
/** are we currently reading a command, 0 if not, else bytecount */
size_t cmd_read;
/** size of current read command, may be partially read */
uint32_t cmd_len;
/** the current read command content, malloced, can be partially read*/
uint8_t* cmd_msg;
/** commpoint to write results back */
struct comm_point* res_com;
/** are we curently writing a result, 0 if not, else bytecount into
* the res_list first entry. */
size_t res_write;
/** list of outstanding results to be written back */
struct libworker_res_list* res_list;
/** last in list */
struct libworker_res_list* res_last;
};
/**
* List of results (arbitrary command serializations) to write back
*/
struct libworker_res_list {
/** next in list */
struct libworker_res_list* next;
/** serialized buffer to write */
uint8_t* buf;
/** length to write */
uint32_t len;
};
/**
* Create a background worker
* @param ctx: is updated with pid/tid of the background worker.
* a new allocation cache is obtained from ctx. It contains the
* threadnumber and unique id for further (shared) cache insertions.
* @return 0 if OK, else error.
* Further communication is done via the pipes in ctx.
*/
int libworker_bg(struct ub_ctx* ctx);
/**
* Create a foreground worker.
* This worker will join the threadpool of resolver threads.
* It exits when the query answer has been obtained (or error).
* This routine blocks until the worker is finished.
* @param ctx: new allocation cache obtained and returned to it.
* @param q: query (result is stored in here).
* @return 0 if finished OK, else error.
*/
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);
/**
* Worker service routine to send udp messages for modules.
* @param pkt: packet to send.
* @param addr: where to.
* @param addrlen: length of addr.
* @param timeout: seconds to wait until timeout.
* @param q: wich query state to reactivate upon return.
* @param use_tcp: true to use TCP, false for UDP.
* @return: false on failure (memory or socket related). no query was
* sent.
*/
int libworker_send_packet(ldns_buffer* pkt, struct sockaddr_storage* addr,
socklen_t addrlen, int timeout, struct module_qstate* q, int use_tcp);
/**
* Worker service routine to send serviced queries to authoritative servers.
* @param qname: query name. (host order)
* @param qnamelen: length in bytes of qname, including trailing 0.
* @param qtype: query type. (host order)
* @param qclass: query class. (host order)
* @param flags: host order flags word, with opcode and CD bit.
* @param dnssec: if set, EDNS record will have DO bit set.
* @param addr: where to.
* @param addrlen: length of addr.
* @param q: wich query state to reactivate upon return.
* @return: false on failure (memory or socket related). no query was
* sent.
*/
struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
struct sockaddr_storage* addr, socklen_t addrlen,
struct module_qstate* q);
/** process incoming replies from the network */
int libworker_handle_reply(struct comm_point* c, void* arg, int error,
struct comm_reply* reply_info);
/** process incoming serviced query replies from the network */
int libworker_handle_service_reply(struct comm_point* c, void* arg, int error,
struct comm_reply* reply_info);
/** handle control command coming into server */
int libworker_handle_control_cmd(struct comm_point* c, void* arg,
int err, struct comm_reply* rep);
/** handle opportunity to write result back */
int libworker_handle_result_write(struct comm_point* c, void* arg,
int err, struct comm_reply* rep);
/**
* Write length bytes followed by message.
* @param fd: the socket to write on. Is nonblocking.
* Set to blocking by the function,
* and back to non-blocking at exit of function.
* @param buf: the message.
* @param len: length of message.
* @param nonblock: if set to true, the first write is nonblocking.
* If the first write fails the function returns -1.
* If set false, the first write is blocking.
* @return: all remainder writes are nonblocking.
* return 0 on error, in that case blocking/nonblocking of socket is
* unknown.
* return 1 if all OK.
*/
int libworker_write_msg(int fd, uint8_t* buf, uint32_t len, int nonblock);
/**
* Read length bytes followed by message.
* @param fd: the socket to write on. Is nonblocking.
* Set to blocking by the function,
* and back to non-blocking at exit of function.
* @param buf: the message, malloced.
* @param len: length of message, returned.
* @param nonblock: if set to true, the first read is nonblocking.
* If the first read fails the function returns -1.
* If set false, the first read is blocking.
* @return: all remainder reads are nonblocking.
* return 0 on error, in that case blocking/nonblocking of socket is
* unknown. On EOF 0 is returned.
* return 1 if all OK.
*/
int libworker_read_msg(int fd, uint8_t** buf, uint32_t* len, int nonblock);
/**
* fill result from parsed message, on error fills servfail
* @param res: is clear at start, filled in at end.
* @param buf: contains DNS message.
* @param temp: temporary buffer for parse.
* @param msg_security: security status of the DNS message.
* On error, the res may contain a different status
* (out of memory is not secure, not bogus).
*/
void libworker_enter_result(struct ub_result* res, ldns_buffer* buf,
struct regional* temp, enum sec_status msg_security);
#endif /* LIBUNBOUND_WORKER_H */
+22
View File
@@ -0,0 +1,22 @@
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
+468
View File
@@ -0,0 +1,468 @@
/*
* unbound.h - unbound validating resolver public API
*
* Copyright (c) 2007, 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 file contains functions to resolve DNS queries and
* validate the answers. Synchonously and asynchronously.
*
* Several ways to use this interface from an application wishing
* to perform (validated) DNS lookups.
*
* All start with
* ctx = ub_ctx_create();
* err = ub_ctx_add_ta(ctx, "...");
* err = ub_ctx_add_ta(ctx, "...");
* ... some lookups
* ... call ub_ctx_delete(ctx); when you want to stop.
*
* Application not threaded. Blocking.
* 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_resolve_async(ctx, "www.example.com", ... my_callback);
* ... application resumes processing ...
* ... and when either ub_poll(ctx) is true
* ... or when the file descriptor ub_fd(ctx) is readable,
* ... or whenever, the app calls ...
* 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_wait(ctx);
*
* Application threaded. Blocking.
* Blocking, same as above. The current thread does the work.
* Multiple threads can use the *same context*, each does work and uses
* shared cache data from the context.
*
* Application threaded. Non-blocking ('asynchronous').
* ... setup threaded-asynchronous config option
* err = ub_ctx_async(ctx, 1);
* ... same as async for non-threaded
* ... the callbacks are called in the thread that calls process(ctx)
*
* If no threading is compiled in, the above async example uses fork(2) to
* create a process to perform the work. The forked process exits when the
* calling process exits, or ctx_delete() is called.
* Otherwise, for asynchronous with threading, a worker thread is created.
*
* The blocking calls use shared ctx-cache when threaded. Thus
* 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.
* And no buffers need to be set up, but a context-switch happens.
*/
#ifndef _UB_UNBOUND_H
#define _UB_UNBOUND_H
/**
* The validation context is created to hold the resolver status,
* validation keys and a small cache (containing messages, rrsets,
* roundtrip times, trusted keys, lameness information).
*
* Its contents are internally defined.
*/
struct ub_ctx;
/**
* The validation and resolution results.
* Allocated by the resolver, and need to be freed by the application
* with ub_resolve_free().
*/
struct ub_result {
/** The original question, name text string. */
char* qname;
/** the type asked for */
int qtype;
/** the class asked for */
int qclass;
/**
* a list of network order DNS rdata items, terminated with a
* NULL pointer, so that data[0] is the first result entry,
* data[1] the second, and the last entry is NULL.
* If there was no data, data[0] is NULL.
*/
char** data;
/** the length in bytes of the data items, len[i] for data[i] */
int* len;
/**
* canonical name for the result (the final cname).
* zero terminated string.
* May be NULL if no canonical name exists.
*/
char* canonname;
/**
* DNS RCODE for the result. May contain additional error code if
* there was no data due to an error. 0 (NOERROR) if okay.
*/
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).
*/
int havedata;
/**
* If there was no data, and the domain did not exist, this is true.
* If it is false, and there was no data, then the domain name
* is purported to exist, but the requested data type is not available.
*/
int nxdomain;
/**
* True, if the result is validated securely.
* False, if validation failed or domain queried has no security info.
*
* It is possible to get a result with no data (havedata is false),
* and secure is true. This means that the non-existance of the data
* was cryptographically proven (with signatures).
*/
int secure;
/**
* If the result was not secure (secure==0), and this result is due
* to a security failure, bogus is true.
* This means the data has been actively tampered with, signatures
* failed, expected signatures were not present, timestamps on
* signatures were out of date and so on.
*
* If !secure and !bogus, this can happen if the data is not secure
* because security is disabled for that domain name.
* This means the data is from a domain where data is not signed.
*/
int bogus;
};
/**
* Callback for results of async queries.
* The readable function definition looks like:
* 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.
* int err: if 0 all is OK, otherwise an error occured and no results
* are forthcoming.
* struct result: pointer to more detailed result structure.
* This structure is allocated on the heap and needs to be
* freed with ub_resolve_free(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_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_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.
* @param ctx: context.
* @param fname: unbound config file (not all settings applicable).
* 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.
* @return: 0 if OK, else error.
*/
int ub_ctx_config(struct ub_ctx* ctx, char* fname);
/**
* 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
* DNSSEC-capable, validation may fail. Can be called several times, in
* 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_ctx_resolvconf.
*
* @param ctx: context.
* At this time it is only possible to set configuration before the
* first resolve is done.
* @param addr: address, IP4 or IP6 in string format.
* If the addr is NULL, forwarding is disabled.
* @return 0 if OK, else error.
*/
int ub_ctx_set_fwd(struct ub_ctx* ctx, char* addr);
/**
* 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.
*
* Only nameservers are picked up, the searchdomain, ndots and other
* settings from resolv.conf(5) are ignored.
*
* @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/resolv.conf" is used.
* @return 0 if OK, else error.
*/
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.
* The trust anchor is a string, on one line, that holds a valid DNSKEY or
* DS RR.
* @param ctx: context.
* At this time it is only possible to add trusted keys before the
* first resolve is done.
* @param ta: string, with zone-format RR on one line.
* [domainname] [TTL optional] [type] [class optional] [rdata contents]
* @return 0 if OK, else error.
*/
int ub_ctx_add_ta(struct ub_ctx* ctx, char* ta);
/**
* Add trust anchors to the given context.
* Pass name of a file with DS and DNSKEY records (like from dig or drill).
* @param ctx: context.
* At this time it is only possible to add trusted keys before the
* first resolve is done.
* @param fname: filename of file with keyfile with trust anchors.
* @return 0 if OK, else error.
*/
int ub_ctx_add_ta_file(struct ub_ctx* ctx, char* fname);
/**
* Add trust anchors to the given context.
* Pass the name of a bind-style config file with trusted-keys{}.
* @param ctx: context.
* At this time it is only possible to add trusted keys before the
* first resolve is done.
* @param fname: filename of file with bind-style config entries with trust
* anchors.
* @return 0 if OK, else error.
*/
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
* Output is directed to stderr.
* @param ctx: context.
* @param d: debug level, 0 is off, 1 is very minimal, 2 is detailed,
* and 3 is lots.
* @return 0 if OK, else error.
*/
int ub_ctx_debuglevel(struct ub_ctx* ctx, int d);
/**
* Set a context behaviour for asynchronous action.
* @param ctx: context.
* @param dothread: if true, enables threading and a call to 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 async() calls have been made have
* no effect (delete and re-create the context to change).
* @return 0 if OK, else error.
*/
int ub_ctx_async(struct ub_ctx* ctx, int dothread);
/**
* 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.
* @param ctx: context.
* @return: 0 if nothing to read, or nonzero if a result is available.
* If nonzero, call ctx_process() to do callbacks.
*/
int ub_poll(struct ub_ctx* ctx);
/**
* 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_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_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_fd(struct ub_ctx* ctx);
/**
* Call this routine to continue processing results from the validating
* resolver (when the fd becomes readable).
* Will perform necessary callbacks.
* @param ctx: context
* @return: 0 if OK, else error.
*/
int ub_process(struct ub_ctx* ctx);
/**
* Perform resolution and validation of the target name.
* @param ctx: context.
* The context is finalized, and can no longer accept config changes.
* @param name: domain name in text format (a zero terminated text string).
* @param rrtype: type of RR in host order, 1 is A (address).
* @param rrclass: class of RR in host order, 1 is IN (for internet).
* @param result: the result data is returned in a newly allocated result
* structure. May be NULL on return, return value is set to an error
* in that case (out of memory).
* @return 0 if OK, else error.
*/
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.
* Asynchronous, after a while, the callback will be called with your
* data and the result.
* @param ctx: context.
* If no thread or process has been created yet to perform the
* work in the background, it is created now.
* The context is finalized, and can no longer accept config changes.
* @param name: domain name in text format (a string).
* @param rrtype: type of RR in host order, 1 is A.
* @param rrclass: class of RR in host order, 1 is IN (for internet).
* @param mydata: this data is your own data (you can pass NULL),
* 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_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.
* The result may be NULL, in that case err is set.
*
* If an error happens during processing, your callback will be called
* with error set to a nonzero value (and result==NULL).
* @param async_id: if you pass a non-NULL value, an identifier number is
* returned for the query as it is in progress. It can be used to
* cancel the query.
* @return 0 if OK, else error.
*/
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.
* Its callback will not be called.
*
* @param ctx: context.
* @param async_id: which query to cancel.
* @return 0 if OK, else error.
*/
int ub_cancel(struct ub_ctx* ctx, int async_id);
/**
* Free storage associated with a result structure.
* @param result: to free
*/
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_strerror(int err);
#endif /* _UB_UNBOUND_H */
+6930
View File
File diff suppressed because it is too large Load Diff
+20 -10
View File
@@ -134,7 +134,7 @@ done
# Check if SVNROOT is specified.
if [ -z "$SVNROOT" ]; then
if test -f .svn/entries; then
eval `grep 'url=' .svn/entries | head -1`
eval `svn info | grep 'URL:' | sed -e 's/URL: /url=/' | head -1`
SVNROOT="$url"
fi
if test -z "$SVNROOT"; then
@@ -146,17 +146,15 @@ if test -z "$LDNSDIR"; then
# try to autodetect from Makefile (if present)
if test -f Makefile; then
eval `grep 'ldnsdir=' Makefile`
LDNSDIR="$ldnsdir"
fi
if test -z "$LDNSDIR"; then
error "LDNSDIR not detected in Makefile, specify manually (using -l)"
if echo "$ldnsdir" | grep -v ldns-src/ >/dev/null 2>&1; then
LDNSDIR="$ldnsdir"
fi
fi
fi
# Start the packaging process.
info "SVNROOT is $SVNROOT"
info "SNAPSHOT is $SNAPSHOT"
info "LDNSDIR is $LDNSDIR"
#question "Do you wish to continue with these settings?" || error "User abort."
@@ -185,9 +183,17 @@ echo "#include \"util/configyyrename.h\"" > util/configlexer.c || error_cleanup
flex -i -t util/configlexer.lex >> util/configlexer.c || error_cleanup "Failed to create configlexer"
bison -y -d -o util/configparser.c util/configparser.y || error_cleanup "Failed to create configparser"
# copy ldns-testpkts from ldns examples
#cp $LDNSDIR/examples/ldns-testpkts.c testcode/ldns-testpkts.c || error_cleanup "copy ldns/examples/.. failed"
#cp $LDNSDIR/examples/ldns-testpkts.h testcode/ldns-testpkts.h || error_cleanup "copy ldns/examples/.. failed"
# check shared code, ldns-testpkts from ldns examples, if possible.
cd ../..
if test ! -z "$LDNSDIR"; then
if diff -q $LDNSDIR/examples/ldns-testpkts.c testcode/ldns-testpkts.c &&
diff -q $LDNSDIR/examples/ldns-testpkts.h testcode/ldns-testpkts.h; then
info "ldns-testpkts.c and ldns-testpkts.h are OK"
else
error_cleanup "ldns-testpkts is different in ldns and unbound"
fi
fi
cd $temp_dir/unbound
find . -name .c-mode-rc.el -exec rm {} \;
find . -name .cvsignore -exec rm {} \;
@@ -206,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 ..
+127 -46
View File
@@ -47,12 +47,12 @@
#include "util/data/dname.h"
#include "util/module.h"
#include "util/net_help.h"
#include "util/region-allocator.h"
#include "util/regional.h"
/** 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 */
@@ -103,10 +103,10 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
/** allocate rrset in region - no more locks needed */
static struct ub_packed_rrset_key*
copy_rrset(struct ub_packed_rrset_key* key, struct region* region,
copy_rrset(struct ub_packed_rrset_key* key, struct regional* region,
uint32_t now)
{
struct ub_packed_rrset_key* ck = region_alloc(region,
struct ub_packed_rrset_key* ck = regional_alloc(region,
sizeof(struct ub_packed_rrset_key));
struct packed_rrset_data* d;
struct packed_rrset_data* data = (struct packed_rrset_data*)
@@ -119,12 +119,12 @@ copy_rrset(struct ub_packed_rrset_key* key, struct region* region,
ck->entry.hash = key->entry.hash;
ck->entry.key = ck;
ck->rk = key->rk;
ck->rk.dname = region_alloc_init(region, key->rk.dname,
ck->rk.dname = regional_alloc_init(region, key->rk.dname,
key->rk.dname_len);
if(!ck->rk.dname)
return NULL;
dsize = packed_rrset_sizeof(data);
d = (struct packed_rrset_data*)region_alloc_init(region, data, dsize);
d = (struct packed_rrset_data*)regional_alloc_init(region, data, dsize);
if(!d)
return NULL;
ck->entry.data = d;
@@ -139,11 +139,18 @@ copy_rrset(struct ub_packed_rrset_key* key, struct region* region,
/** find closest NS or DNAME and returns the rrset (locked) */
static struct ub_packed_rrset_key*
find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
uint16_t qclass, uint32_t now, uint16_t searchtype)
uint16_t qclass, uint32_t now, uint16_t searchtype, int stripfront)
{
struct ub_packed_rrset_key *rrset;
uint8_t lablen;
if(stripfront) {
/* strip off so that DNAMEs have strict subdomain match */
lablen = *qname;
qname += lablen + 1;
qnamelen -= lablen + 1;
}
/* snip off front part of qname until the type is found */
while(qnamelen > 0) {
if((rrset = rrset_cache_lookup(env->rrset_cache, qname,
@@ -160,7 +167,7 @@ find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
/** add addr to additional section */
static void
addr_to_additional(struct ub_packed_rrset_key* rrset, struct region* region,
addr_to_additional(struct ub_packed_rrset_key* rrset, struct regional* region,
struct dns_msg* msg, uint32_t now)
{
if((msg->rep->rrsets[msg->rep->rrset_count] =
@@ -172,8 +179,9 @@ addr_to_additional(struct ub_packed_rrset_key* rrset, struct region* region,
/** find and add A and AAAA records for nameservers in delegpt */
static int
find_add_addrs(struct module_env* env, uint16_t qclass, struct region* region,
struct delegpt* dp, uint32_t now, struct dns_msg** msg)
find_add_addrs(struct module_env* env, uint16_t qclass,
struct regional* region, struct delegpt* dp, uint32_t now,
struct dns_msg** msg)
{
struct delegpt_ns* ns;
struct ub_packed_rrset_key* akey;
@@ -207,11 +215,11 @@ find_add_addrs(struct module_env* env, uint16_t qclass, struct region* region,
/** find and add A and AAAA records for missing nameservers in delegpt */
int
cache_fill_missing(struct module_env* env, uint16_t qclass,
struct region* region, struct delegpt* dp)
struct regional* region, struct delegpt* dp)
{
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;
@@ -243,7 +251,7 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
/** find and add DS or NSEC to delegation msg */
static void
find_add_ds(struct module_env* env, struct region* region,
find_add_ds(struct module_env* env, struct regional* region,
struct dns_msg* msg, struct delegpt* dp, uint32_t now)
{
/* Lookup the DS or NSEC at the delegation point. */
@@ -274,21 +282,21 @@ find_add_ds(struct module_env* env, struct region* region,
/** create referral message with NS and query */
static struct dns_msg*
create_msg(uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
struct region* region, struct ub_packed_rrset_key* nskey,
struct regional* region, struct ub_packed_rrset_key* nskey,
struct packed_rrset_data* nsdata, uint32_t now)
{
struct dns_msg* msg = (struct dns_msg*)region_alloc(region,
struct dns_msg* msg = (struct dns_msg*)regional_alloc(region,
sizeof(struct dns_msg));
if(!msg)
return NULL;
msg->qinfo.qname = region_alloc_init(region, qname, qnamelen);
msg->qinfo.qname = regional_alloc_init(region, qname, qnamelen);
if(!msg->qinfo.qname)
return NULL;
msg->qinfo.qname_len = qnamelen;
msg->qinfo.qtype = qtype;
msg->qinfo.qclass = qclass;
/* non-packed reply_info, because it needs to grow the array */
msg->rep = (struct reply_info*)region_alloc(region,
msg->rep = (struct reply_info*)regional_alloc(region,
sizeof(struct reply_info)-sizeof(struct rrset_ref));
if(!msg->rep)
return NULL;
@@ -301,7 +309,8 @@ create_msg(uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
* A rrset for every NS RR
* AAAA rrset for every NS RR
*/
msg->rep->rrsets = (struct ub_packed_rrset_key**)region_alloc(region,
msg->rep->rrsets = (struct ub_packed_rrset_key**)
regional_alloc(region,
(2 + nsdata->count*2)*sizeof(struct ub_packed_rrset_key*));
if(!msg->rep->rrsets)
return NULL;
@@ -316,16 +325,15 @@ create_msg(uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
struct delegpt*
dns_cache_find_delegation(struct module_env* env, uint8_t* qname,
size_t qnamelen, uint16_t qtype, uint16_t qclass,
struct region* region, struct dns_msg** msg)
struct regional* region, struct dns_msg** msg, uint32_t now)
{
/* try to find closest NS rrset */
struct ub_packed_rrset_key* nskey;
struct packed_rrset_data* nsdata;
struct delegpt* dp;
uint32_t now = (uint32_t)time(NULL);
nskey = find_closest_of_type(env, qname, qnamelen, qclass, now,
LDNS_RR_TYPE_NS);
LDNS_RR_TYPE_NS, 0);
if(!nskey) /* hope the caller has hints to prime or something */
return NULL;
nsdata = (struct packed_rrset_data*)nskey->entry.data;
@@ -355,29 +363,28 @@ dns_cache_find_delegation(struct module_env* env, uint8_t* qname,
/* find and add A entries */
if(!find_add_addrs(env, qclass, region, dp, now, msg))
log_err("find_delegation: addrs out of memory");
log_info("dns_cache_find_delegation returns delegpt");
delegpt_log(dp);
return dp;
}
/** allocate dns_msg from query_info and reply_info */
static struct dns_msg*
gen_dns_msg(struct region* region, struct query_info* q, size_t num)
gen_dns_msg(struct regional* region, struct query_info* q, size_t num)
{
struct dns_msg* msg = (struct dns_msg*)region_alloc(region,
struct dns_msg* msg = (struct dns_msg*)regional_alloc(region,
sizeof(struct dns_msg));
if(!msg)
return NULL;
memcpy(&msg->qinfo, q, sizeof(struct query_info));
msg->qinfo.qname = region_alloc_init(region, q->qname, q->qname_len);
msg->qinfo.qname = regional_alloc_init(region, q->qname, q->qname_len);
if(!msg->qinfo.qname)
return NULL;
/* allocate replyinfo struct and rrset key array separately */
msg->rep = (struct reply_info*)region_alloc(region,
msg->rep = (struct reply_info*)regional_alloc(region,
sizeof(struct reply_info) - sizeof(struct rrset_ref));
if(!msg->rep)
return NULL;
msg->rep->rrsets = (struct ub_packed_rrset_key**)region_alloc(region,
msg->rep->rrsets = (struct ub_packed_rrset_key**)
regional_alloc(region,
num * sizeof(struct ub_packed_rrset_key*));
if(!msg->rep->rrsets)
return NULL;
@@ -387,7 +394,7 @@ gen_dns_msg(struct region* region, struct query_info* q, size_t num)
/** generate dns_msg from cached message */
static struct dns_msg*
tomsg(struct module_env* env, struct msgreply_entry* e, struct reply_info* r,
struct region* region, uint32_t now, struct region* scratch)
struct regional* region, uint32_t now, struct regional* scratch)
{
struct dns_msg* msg;
size_t i;
@@ -399,6 +406,7 @@ tomsg(struct module_env* env, struct msgreply_entry* e, struct reply_info* r,
msg->rep->flags = r->flags;
msg->rep->qdcount = r->qdcount;
msg->rep->ttl = r->ttl;
msg->rep->security = r->security;
msg->rep->an_numrrsets = r->an_numrrsets;
msg->rep->ns_numrrsets = r->ns_numrrsets;
msg->rep->ar_numrrsets = r->ar_numrrsets;
@@ -417,9 +425,9 @@ tomsg(struct module_env* env, struct msgreply_entry* e, struct reply_info* r,
return msg;
}
/** synthesize CNAME response from cached CNAME item */
/** synthesize RRset-only response from cached RRset item */
static struct dns_msg*
cname_msg(struct ub_packed_rrset_key* rrset, struct region* region,
rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
uint32_t now, struct query_info* q)
{
struct dns_msg* msg;
@@ -427,12 +435,13 @@ cname_msg(struct ub_packed_rrset_key* rrset, struct region* region,
rrset->entry.data;
if(now > d->ttl)
return NULL;
msg = gen_dns_msg(region, q, 1); /* only the CNAME RRset */
msg = gen_dns_msg(region, q, 1); /* only the CNAME (or other) RRset */
if(!msg)
return NULL;
msg->rep->flags = BIT_QR; /* reply, no AA, no error */
msg->rep->qdcount = 1;
msg->rep->ttl = d->ttl - now;
msg->rep->security = sec_status_unchecked;
msg->rep->an_numrrsets = 1;
msg->rep->ns_numrrsets = 0;
msg->rep->ar_numrrsets = 0;
@@ -445,7 +454,7 @@ cname_msg(struct ub_packed_rrset_key* rrset, struct region* region,
/** synthesize DNAME+CNAME response from cached DNAME item */
static struct dns_msg*
synth_dname_msg(struct ub_packed_rrset_key* rrset, struct region* region,
synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
uint32_t now, struct query_info* q)
{
struct dns_msg* msg;
@@ -462,6 +471,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct region* region,
msg->rep->flags = BIT_QR; /* reply, no AA, no error */
msg->rep->qdcount = 1;
msg->rep->ttl = d->ttl - now;
msg->rep->security = sec_status_unchecked;
msg->rep->an_numrrsets = 1;
msg->rep->ns_numrrsets = 0;
msg->rep->ar_numrrsets = 0;
@@ -478,7 +488,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct region* region,
msg->rep->flags |= LDNS_RCODE_YXDOMAIN;
return msg;
}
newname = (uint8_t*)region_alloc(region, newlen);
newname = (uint8_t*)regional_alloc(region, newlen);
if(!newname)
return NULL;
/* new name is concatenation of qname front (without DNAME owner)
@@ -486,7 +496,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct region* region,
memcpy(newname, q->qname, q->qname_len-rrset->rk.dname_len);
memmove(newname+(q->qname_len-rrset->rk.dname_len), dtarg, dtarglen);
/* create rest of CNAME rrset */
ck = (struct ub_packed_rrset_key*)region_alloc(region,
ck = (struct ub_packed_rrset_key*)regional_alloc(region,
sizeof(struct ub_packed_rrset_key));
if(!ck)
return NULL;
@@ -496,12 +506,12 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct region* region,
ck->rk.type = htons(LDNS_RR_TYPE_CNAME);
ck->rk.rrset_class = rrset->rk.rrset_class;
ck->rk.flags = 0;
ck->rk.dname = region_alloc_init(region, q->qname, q->qname_len);
ck->rk.dname = regional_alloc_init(region, q->qname, q->qname_len);
if(!ck->rk.dname)
return NULL;
ck->rk.dname_len = q->qname_len;
ck->entry.hash = rrset_key_hash(&ck->rk);
newd = (struct packed_rrset_data*)region_alloc(region,
newd = (struct packed_rrset_data*)regional_alloc(region,
sizeof(struct packed_rrset_data) + sizeof(size_t) +
sizeof(uint8_t*) + sizeof(uint32_t) + sizeof(uint16_t)
+ newlen);
@@ -528,12 +538,12 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct region* region,
struct dns_msg*
dns_cache_lookup(struct module_env* env,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
struct region* region, struct region* scratch)
struct regional* region, struct regional* scratch)
{
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 */
@@ -560,7 +570,7 @@ dns_cache_lookup(struct module_env* env,
* are more important, the CNAME is resynthesized and thus
* consistent with the DNAME */
if( (rrset=find_closest_of_type(env, qname, qnamelen, qclass, now,
LDNS_RR_TYPE_DNAME))) {
LDNS_RR_TYPE_DNAME, 1))) {
/* synthesize a DNAME+CNAME message based on this */
struct dns_msg* msg = synth_dname_msg(rrset, region, now, &k);
if(msg) {
@@ -573,7 +583,7 @@ dns_cache_lookup(struct module_env* env,
/* see if we have CNAME for this domain */
if( (rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen,
LDNS_RR_TYPE_CNAME, qclass, 0, now, 0))) {
struct dns_msg* msg = cname_msg(rrset, region, now, &k);
struct dns_msg* msg = rrset_msg(rrset, region, now, &k);
if(msg) {
lock_rw_unlock(&rrset->entry.lock);
return msg;
@@ -581,7 +591,78 @@ dns_cache_lookup(struct module_env* env,
lock_rw_unlock(&rrset->entry.lock);
}
/* construct DS, DNSKEY messages from rrset cache. TODO */
/* construct DS, DNSKEY messages from rrset cache. */
if((qtype == LDNS_RR_TYPE_DS || qtype == LDNS_RR_TYPE_DNSKEY) &&
(rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen,
qtype, qclass, 0, now, 0))) {
/* if the rrset is from the additional section, and the
* signatures have fallen off, then do not synthesize a msg
* instead, allow a full query for signed results to happen.
* Forego all rrset data from additional section, because
* some signatures may not be present and cause validation
* failure.
*/
struct packed_rrset_data *d = (struct packed_rrset_data*)
rrset->entry.data;
if(d->trust != rrset_trust_add_noAA &&
d->trust != rrset_trust_add_AA) {
struct dns_msg* msg = rrset_msg(rrset, region, now, &k);
if(msg) {
lock_rw_unlock(&rrset->entry.lock);
return msg;
}
}
lock_rw_unlock(&rrset->entry.lock);
}
return NULL;
}
int
dns_cache_store(struct module_env* env, struct query_info* msgqinf,
struct reply_info* msgrep, int is_referral)
{
struct reply_info* rep = NULL;
/* alloc, malloc properly (not in region, like msg is) */
rep = reply_info_copy(msgrep, env->alloc, NULL);
if(!rep)
return 0;
if(is_referral) {
/* store rrsets */
struct rrset_ref ref;
size_t i;
for(i=0; i<rep->rrset_count; i++) {
packed_rrset_ttl_add((struct packed_rrset_data*)
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, *env->now);
}
free(rep);
return 1;
} else {
/* store msg, and rrsets */
struct query_info qinf;
hashvalue_t h;
qinf = *msgqinf;
qinf.qname = memdup(msgqinf->qname, msgqinf->qname_len);
if(!qinf.qname) {
reply_info_parsedelete(rep, env->alloc);
return 0;
}
/* fixup flags to be sensible for a reply based on the cache */
/* this module means that RA is available. It is an answer QR.
* Not AA from cache. Not CD in cache (depends on client bit). */
rep->flags |= (BIT_RA | BIT_QR);
rep->flags &= ~(BIT_AA | BIT_CD);
h = query_info_hash(&qinf);
dns_cache_store_msg(env, &qinf, h, rep);
/* qname is used inside query_info_entrysetup, and set to
* NULL. If it has not been used, free it. free(0) is safe. */
free(qinf.qname);
}
return 1;
}
+23 -6
View File
@@ -46,7 +46,7 @@
struct module_env;
struct query_info;
struct reply_info;
struct region;
struct regional;
struct delegpt;
/**
@@ -59,6 +59,24 @@ struct dns_msg {
struct reply_info *rep;
};
/**
* Allocate a dns_msg with malloc/alloc structure and store in dns cache.
*
* @param env: environment, with alloc structure and dns cache.
* @param qinf: query info, the query for which answer is stored.
* this is allocated in a region, and will be copied to malloc area
* before insertion.
* @param rep: reply in dns_msg from dns_alloc_msg for example.
* this is allocated in a region, and will be copied to malloc area
* before insertion.
* @param is_referral: If true, then the given message to be stored is a
* referral. The cache implementation may use this as a hint.
* It will store only the RRsets, not the message.
* @return 0 on alloc error (out of memory).
*/
int dns_cache_store(struct module_env* env, struct query_info* qinf,
struct reply_info* rep, int is_referral);
/**
* Store message in the cache. Stores in message cache and rrset cache.
* Both qinfo and rep should be malloced and are put in the cache.
@@ -84,11 +102,12 @@ void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
* @param region: where to allocate result delegation.
* @param msg: if not NULL, delegation message is returned here, synthesized
* from the cache.
* @param timenow: the time now, for checking if TTL on cache entries is OK.
* @return new delegation or NULL on error or if not found in cache.
*/
struct delegpt* dns_cache_find_delegation(struct module_env* env,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
struct region* region, struct dns_msg** msg);
struct regional* region, struct dns_msg** msg, uint32_t timenow);
/**
* Find cached message
@@ -105,7 +124,7 @@ struct delegpt* dns_cache_find_delegation(struct module_env* env,
*/
struct dns_msg* dns_cache_lookup(struct module_env* env,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
struct region* region, struct region* scratch);
struct regional* region, struct regional* scratch);
/**
* find and add A and AAAA records for missing nameservers in delegpt
@@ -116,8 +135,6 @@ struct dns_msg* dns_cache_lookup(struct module_env* env,
* @return false on alloc failure.
*/
int cache_fill_missing(struct module_env* env, uint16_t qclass,
struct region* region, struct delegpt* dp);
/** Find covering DNAME */
struct regional* region, struct delegpt* dp);
#endif /* SERVICES_CACHE_DNS_H */
+128 -44
View File
@@ -47,16 +47,15 @@
#include "util/net_help.h"
#include "util/config_file.h"
/** calculate size for the hashtable, does not count size of lameness,
* so the hashtable is a fixed number of items */
static size_t
infra_host_sizefunc(void* ATTR_UNUSED(k), void* ATTR_UNUSED(d))
size_t
infra_host_sizefunc(void* k, void* ATTR_UNUSED(d))
{
return sizeof(struct infra_host_key) + sizeof(struct infra_host_data);
struct infra_host_key* key = (struct infra_host_key*)k;
return sizeof(*key) + sizeof(struct infra_host_data)
+ lock_get_mem(&key->entry.lock);
}
/** compare two addresses, returns -1, 0, or +1 */
static int
int
infra_host_compfunc(void* key1, void* key2)
{
struct infra_host_key* k1 = (struct infra_host_key*)key1;
@@ -64,20 +63,17 @@ infra_host_compfunc(void* key1, void* key2)
return sockaddr_cmp(&k1->addr, k1->addrlen, &k2->addr, k2->addrlen);
}
/** delete key, and destroy the lock */
static void
infra_host_delkeyfunc(void* k, void* ATTR_UNUSED(arg), int il)
void
infra_host_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
{
struct infra_host_key* key = (struct infra_host_key*)k;
if(!key)
return;
if(il) { lock_rw_unlock(&key->entry.lock); }
lock_rw_destroy(&key->entry.lock);
free(key);
}
/** delete data and destroy the lameness hashtable */
static void
void
infra_host_deldatafunc(void* d, void* ATTR_UNUSED(arg))
{
struct infra_host_data* data = (struct infra_host_data*)d;
@@ -103,7 +99,7 @@ infra_create(struct config_file* cfg)
}
infra->host_ttl = cfg->host_ttl;
infra->lame_ttl = cfg->lame_ttl;
infra->max_lame = cfg->infra_cache_numlame;
infra->max_lame_size = cfg->infra_cache_lame_size;
return infra;
}
@@ -124,7 +120,7 @@ infra_adjust(struct infra_cache* infra, struct config_file* cfg)
return infra_create(cfg);
infra->host_ttl = cfg->host_ttl;
infra->lame_ttl = cfg->lame_ttl;
infra->max_lame = cfg->infra_cache_numlame;
infra->max_lame_size = cfg->infra_cache_lame_size;
maxmem = cfg->infra_cache_numhosts *
(sizeof(struct infra_host_key)+sizeof(struct infra_host_data));
if(maxmem != slabhash_get_size(infra->hosts) ||
@@ -162,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,
@@ -190,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(
@@ -218,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);
@@ -264,7 +260,8 @@ 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;
@@ -284,20 +281,22 @@ infra_lookup_lame(struct infra_host_data* host,
lock_rw_unlock(&e->lock);
return 0;
}
*dlame = d->isdnsseclame;
*alame = d->lame_type_A;
*olame = d->lame_other;
lock_rw_unlock(&e->lock);
return 1;
return *dlame || *alame || *olame;
}
/** calculate size, which is fixed, zonename does not count so that
* a fixed number of items is stored */
static size_t
infra_lame_sizefunc(void* ATTR_UNUSED(k), void* ATTR_UNUSED(d))
size_t
infra_lame_sizefunc(void* k, void* ATTR_UNUSED(d))
{
return sizeof(struct infra_lame_key)+sizeof(struct infra_lame_data);
struct infra_lame_key* key = (struct infra_lame_key*)k;
return sizeof(*key) + sizeof(struct infra_lame_data)
+ key->namelen + lock_get_mem(&key->entry.lock);
}
/** compare zone names, returns -1, 0, +1 */
static int
int
infra_lame_compfunc(void* key1, void* key2)
{
struct infra_lame_key* k1 = (struct infra_lame_key*)key1;
@@ -310,21 +309,18 @@ infra_lame_compfunc(void* key1, void* key2)
return query_dname_compare(k1->zonename, k2->zonename);
}
/** free key, lock and zonename */
static void
infra_lame_delkeyfunc(void* k, void* ATTR_UNUSED(arg), int il)
void
infra_lame_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
{
struct infra_lame_key* key = (struct infra_lame_key*)k;
if(!key)
return;
if(il) { lock_rw_unlock(&key->entry.lock); }
lock_rw_destroy(&key->entry.lock);
free(key->zonename);
free(key);
}
/** free the lameness data */
static void
void
infra_lame_deldatafunc(void* d, void* ATTR_UNUSED(arg))
{
if(!d)
@@ -335,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)
uint8_t* name, size_t namelen, uint32_t timenow, int dnsseclame,
uint16_t qtype)
{
struct infra_host_data* data;
struct lruhash_entry* e;
@@ -366,6 +363,9 @@ infra_set_lame(struct infra_cache* infra,
k->entry.key = (void*)k;
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) {
@@ -384,8 +384,7 @@ infra_set_lame(struct infra_cache* infra,
if(!data->lameness) {
/* create hash table if not there already */
data->lameness = lruhash_create(INFRA_LAME_STARTSIZE,
infra->max_lame*(sizeof(struct infra_lame_key)+
sizeof(struct infra_lame_data)), infra_lame_sizefunc,
infra->max_lame_size, infra_lame_sizefunc,
infra_lame_compfunc, infra_lame_delkeyfunc,
infra_lame_deldatafunc, NULL);
if(!data->lameness) {
@@ -398,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);
@@ -408,15 +418,33 @@ infra_set_lame(struct infra_cache* infra,
return 1;
}
void
infra_update_tcp_works(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen)
{
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
addrlen, 1);
struct infra_host_data* data;
if(!e)
return; /* doesn't exist */
data = (struct infra_host_data*)e->data;
if(data->rtt.rto >= RTT_MAX_TIMEOUT)
/* do not disqualify this server altogether, it is better
* than nothing */
data->rtt.rto = RTT_MAX_TIMEOUT-1;
lock_rw_unlock(&e->lock);
}
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);
struct infra_host_data* data;
int needtoinsert = 0;
int rto = 1;
if(!e) {
if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
return 0;
@@ -428,17 +456,19 @@ infra_rtt_update(struct infra_cache* infra,
if(roundtrip == -1)
rtt_lost(&data->rtt);
else rtt_update(&data->rtt, roundtrip);
if(data->rtt.rto > 0)
rto = data->rtt.rto;
if(needtoinsert)
slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
else { lock_rw_unlock(&e->lock); }
return 1;
return rto;
}
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);
@@ -463,22 +493,39 @@ 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* 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 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(infra_lookup_lame(host, name, namelen, timenow)) {
lock_rw_unlock(&e->lock);
*lame = 1;
return 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;
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;
}
/* no lameness for this type of query */
}
*lame = 0;
*dnsseclame = 0;
if(timenow > host->ttl) {
lock_rw_unlock(&e->lock);
return 0;
@@ -486,3 +533,40 @@ infra_get_lame_rtt(struct infra_cache* infra,
lock_rw_unlock(&e->lock);
return 1;
}
/** helper memory count for a host lame cache */
static size_t
count_host_lame(struct lruhash_entry* e)
{
struct infra_host_data* host_data = (struct infra_host_data*)e->data;
if(!host_data->lameness)
return 0;
return lruhash_get_mem(host_data->lameness);
}
size_t
infra_get_mem(struct infra_cache* infra)
{
size_t i, bin;
size_t s = sizeof(*infra) +
slabhash_get_mem(infra->hosts);
struct lruhash_entry* e;
for(i=0; i<infra->hosts->size; i++) {
lock_quick_lock(&infra->hosts->array[i]->lock);
for(bin=0; bin<infra->hosts->array[i]->size; bin++) {
lock_quick_lock(&infra->hosts->array[i]->
array[bin].lock);
/* count data size in bin items. */
for(e = infra->hosts->array[i]->array[bin].
overflow_list; e; e = e->overflow_next) {
lock_rw_rdlock(&e->lock);
s += count_host_lame(e);
lock_rw_unlock(&e->lock);
}
lock_quick_unlock(&infra->hosts->array[i]->
array[bin].lock);
}
lock_quick_unlock(&infra->hosts->array[i]->lock);
}
return s;
}
+74 -13
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,7 +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;
};
/**
@@ -103,8 +110,8 @@ struct infra_cache {
int host_ttl;
/** TTL for Lameness information, in seconds */
int lame_ttl;
/** infra lame cache max memory per host, for this many entries */
size_t max_lame;
/** infra lame cache max memory per host, in bytes */
size_t max_lame_size;
};
/** infra host cache default hash lookup size */
@@ -148,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.
@@ -163,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.
@@ -172,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, true if lame.
* @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.
@@ -185,11 +196,15 @@ int infra_lookup_lame(struct infra_host_data* host,
* @param name: domain name of zone apex.
* @param namelen: length of domain name.
* @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);
uint8_t* name, size_t namelen, uint32_t timenow, int dnsseclame,
uint16_t qtype);
/**
* Update rtt information for the host.
@@ -199,11 +214,20 @@ int infra_set_lame(struct infra_cache* infra,
* @param roundtrip: estimate of roundtrip time in milliseconds or -1 for
* timeout.
* @param timenow: what time it is now.
* @return: 0 on error.
* @return: 0 on error. new rto otherwise.
*/
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.
* @param infra: infrastructure cache.
* @param addr: host address.
* @param addrlen: length of addr.
*/
void infra_update_tcp_works(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen);
/**
* Update edns information for the host.
@@ -216,7 +240,7 @@ int 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);
/**
* Get Lameness information and average RTT if host is in the cache.
@@ -225,7 +249,10 @@ 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.
* @param rtt: if function returns true, this returns avg rtt of the server.
* The rtt value is unclamped and reflects recent timeouts.
* @param timenow: what time it is now.
@@ -233,6 +260,40 @@ 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* 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.
* @param infra: infrastructure cache.
* @return memory in use in bytes.
*/
size_t infra_get_mem(struct infra_cache* infra);
/** calculate size for the hashtable, does not count size of lameness,
* so the hashtable is a fixed number of items */
size_t infra_host_sizefunc(void* k, void* d);
/** compare two addresses, returns -1, 0, or +1 */
int infra_host_compfunc(void* key1, void* key2);
/** delete key, and destroy the lock */
void infra_host_delkeyfunc(void* k, void* arg);
/** delete data and destroy the lameness hashtable */
void infra_host_deldatafunc(void* d, void* arg);
/** calculate size, which is fixed, zonename does not count so that
* a fixed number of items is stored */
size_t infra_lame_sizefunc(void* k, void* d);
/** compare zone names, returns -1, 0, +1 */
int infra_lame_compfunc(void* key1, void* key2);
/** free key, lock and zonename */
void infra_lame_delkeyfunc(void* k, void* arg);
/** free the lameness data */
void infra_lame_deldatafunc(void* d, void* arg);
#endif /* SERVICES_CACHE_INFRA_H */
+118 -19
View File
@@ -44,7 +44,15 @@
#include "util/config_file.h"
#include "util/data/packed_rrset.h"
#include "util/data/msgreply.h"
#include "util/region-allocator.h"
#include "util/regional.h"
#include "util/alloc.h"
void
rrset_markdel(void* key)
{
struct ub_packed_rrset_key* r = (struct ub_packed_rrset_key*)key;
r->id = 0;
}
struct rrset_cache* rrset_cache_create(struct config_file* cfg,
struct alloc_cache* alloc)
@@ -56,6 +64,7 @@ struct rrset_cache* rrset_cache_create(struct config_file* cfg,
struct rrset_cache *r = (struct rrset_cache*)slabhash_create(slabs,
startarray, maxmem, ub_rrset_sizefunc, ub_rrset_compare,
ub_rrset_key_delete, rrset_data_delete, alloc);
slabhash_setmarkdel(&r->table, &rrset_markdel);
return r;
}
@@ -64,6 +73,7 @@ void rrset_cache_delete(struct rrset_cache* r)
if(!r)
return;
slabhash_delete(&r->table);
/* slabhash delete also does free(r), since table is first in struct*/
}
struct rrset_cache* rrset_cache_adjust(struct rrset_cache *r,
@@ -110,33 +120,48 @@ rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key,
/** see if rrset needs to be updated in the cache */
static int
need_to_update_rrset(void* nd, void* cd, uint32_t timenow)
need_to_update_rrset(void* nd, void* cd, uint32_t timenow, int equal)
{
struct packed_rrset_data* newd = (struct packed_rrset_data*)nd;
struct packed_rrset_data* cached = (struct packed_rrset_data*)cd;
/* o store if rrset has been validated */
if( newd->security > cached->security) {
return 1;
}
/* o if current RRset is more trustworthy - insert it */
if( newd->trust > cached->trust )
if( newd->trust > cached->trust ) {
/* if the cached rrset is bogus, and this one equal,
* do not update the TTL - let it expire. */
if(equal && cached->ttl >= timenow &&
cached->security == sec_status_bogus)
return 0;
return 1;
}
/* o item in cache has expired */
if( cached->ttl < timenow )
return 1;
/* o same trust, but different in data - insert it */
if( newd->trust == cached->trust &&
!rrsetdata_equal(newd, cached))
if( newd->trust == cached->trust && !equal )
return 1;
/* o see if TTL is better than TTL in cache. */
/* if so, see if rrset+rdata is the same */
/* if so, update TTL in cache, even if trust is worse. */
if( newd->ttl > cached->ttl &&
rrsetdata_equal(newd, cached)) {
/* since all else is the same, use the best trust value */
if(newd->trust < cached->trust)
newd->trust = cached->trust;
return 1;
}
return 0;
}
/** Update RRSet special key ID */
static void
rrset_update_id(struct rrset_ref* ref, struct alloc_cache* alloc)
{
/* this may clear the cache and invalidate lock below */
uint64_t newid = alloc_get_id(alloc);
/* obtain writelock */
lock_rw_wrlock(&ref->key->entry.lock);
/* check if it was deleted in the meantime, if so, skip update */
if(ref->key->id == ref->id) {
ref->key->id = newid;
ref->id = newid;
}
lock_rw_unlock(&ref->key->entry.lock);
}
int
rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
struct alloc_cache* alloc, uint32_t timenow)
@@ -144,6 +169,9 @@ rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
struct lruhash_entry* e;
struct ub_packed_rrset_key* k = ref->key;
hashvalue_t h = k->entry.hash;
uint16_t rrset_type = ntohs(k->rk.type);
int equal = 0;
log_assert(ref->id != 0 && k->id != 0);
/* looks up item with a readlock - no editing! */
if((e=slabhash_lookup(&r->table, h, k, 0)) != 0) {
/* return id and key as they will be used in the cache
@@ -155,7 +183,10 @@ rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
*/
ref->key = (struct ub_packed_rrset_key*)e->key;
ref->id = ref->key->id;
if(!need_to_update_rrset(k->entry.data, e->data, timenow)) {
equal = rrsetdata_equal((struct packed_rrset_data*)k->entry.
data, (struct packed_rrset_data*)e->data);
if(!need_to_update_rrset(k->entry.data, e->data, timenow,
equal)) {
/* cache is superior, return that value */
lock_rw_unlock(&e->lock);
ub_packed_rrset_parsedelete(k, alloc);
@@ -170,9 +201,19 @@ rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
/* use insert to update entry to manage lruhash
* cache size values nicely. */
}
log_assert(ref->key->id != 0);
slabhash_insert(&r->table, h, &k->entry, k->entry.data, alloc);
if(e)
if(e) {
/* For NSEC, NSEC3, DNAME, when rdata is updated, update
* the ID number so that proofs in message cache are
* invalidated */
if((rrset_type == LDNS_RR_TYPE_NSEC
|| rrset_type == LDNS_RR_TYPE_NSEC3
|| rrset_type == LDNS_RR_TYPE_DNAME) && !equal) {
rrset_update_id(ref, alloc);
}
return 1;
}
return 0;
}
@@ -239,12 +280,12 @@ rrset_array_unlock(struct rrset_ref* ref, size_t count)
}
void
rrset_array_unlock_touch(struct rrset_cache* r, struct region* scratch,
rrset_array_unlock_touch(struct rrset_cache* r, struct regional* scratch,
struct rrset_ref* ref, size_t count)
{
hashvalue_t* h;
size_t i;
if(!(h = (hashvalue_t*)region_alloc(scratch,
if(!(h = (hashvalue_t*)regional_alloc(scratch,
sizeof(hashvalue_t)*count)))
log_warn("rrset LRU: memory allocation failed");
else /* store hash values */
@@ -265,3 +306,61 @@ rrset_array_unlock_touch(struct rrset_cache* r, struct region* scratch,
}
}
}
void
rrset_update_sec_status(struct rrset_cache* r,
struct ub_packed_rrset_key* rrset, uint32_t now)
{
struct packed_rrset_data* updata =
(struct packed_rrset_data*)rrset->entry.data;
struct lruhash_entry* e;
struct packed_rrset_data* cachedata;
/* hash it again to make sure it has a hash */
rrset->entry.hash = rrset_key_hash(&rrset->rk);
e = slabhash_lookup(&r->table, rrset->entry.hash, rrset, 1);
if(!e)
return; /* not in the cache anymore */
cachedata = (struct packed_rrset_data*)e->data;
if(!rrsetdata_equal(updata, cachedata)) {
lock_rw_unlock(&e->lock);
return; /* rrset has changed in the meantime */
}
/* update the cached rrset */
if(updata->security > cachedata->security) {
cachedata->trust = updata->trust;
cachedata->security = updata->security;
cachedata->ttl = updata->ttl + now;
}
lock_rw_unlock(&e->lock);
}
void
rrset_check_sec_status(struct rrset_cache* r,
struct ub_packed_rrset_key* rrset, uint32_t now)
{
struct packed_rrset_data* updata =
(struct packed_rrset_data*)rrset->entry.data;
struct lruhash_entry* e;
struct packed_rrset_data* cachedata;
/* hash it again to make sure it has a hash */
rrset->entry.hash = rrset_key_hash(&rrset->rk);
e = slabhash_lookup(&r->table, rrset->entry.hash, rrset, 0);
if(!e)
return; /* not in the cache anymore */
cachedata = (struct packed_rrset_data*)e->data;
if(now > cachedata->ttl || !rrsetdata_equal(updata, cachedata)) {
lock_rw_unlock(&e->lock);
return; /* expired, or rrset has changed in the meantime */
}
if(cachedata->security > updata->security) {
updata->security = cachedata->security;
if(cachedata->security == sec_status_bogus)
updata->ttl = cachedata->ttl - now;
updata->trust = cachedata->trust;
}
lock_rw_unlock(&e->lock);
}
+30 -2
View File
@@ -47,7 +47,7 @@
struct config_file;
struct alloc_cache;
struct rrset_ref;
struct region;
struct regional;
/**
* The rrset cache
@@ -181,7 +181,35 @@ void rrset_array_unlock(struct rrset_ref* ref, size_t count);
* duplicate references are allowed and handled.
* @param count: size of array.
*/
void rrset_array_unlock_touch(struct rrset_cache* r, struct region* scratch,
void rrset_array_unlock_touch(struct rrset_cache* r, struct regional* scratch,
struct rrset_ref* ref, size_t count);
/**
* Update security status of an rrset. Looks up the rrset.
* If found, checks if rdata is equal.
* If so, it will update the security, trust and rrset-ttl values.
* The values are only updated if security is increased (towards secure).
* @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, uint32_t now);
/**
* Looks up security status of an rrset. Looks up the rrset.
* If found, checks if rdata is equal, and entry did not expire.
* If so, it will update the security, trust and rrset-ttl values.
* @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, uint32_t now);
/** mark rrset to be deleted, set id=0 */
void rrset_markdel(void* key);
#endif /* SERVICES_CACHE_RRSET_H */
+265 -54
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() */
@@ -74,6 +76,7 @@ verbose_print_addr(struct addrinfo *addr)
(socklen_t)sizeof(buf)) == 0) {
strncpy(buf, "(null)", sizeof(buf));
}
buf[sizeof(buf)-1] = 0;
verbose(VERB_ALGO, "creating %s%s socket %s %d",
addr->ai_socktype==SOCK_DGRAM?"udp":
addr->ai_socktype==SOCK_STREAM?"tcp":"otherproto",
@@ -85,24 +88,54 @@ verbose_print_addr(struct addrinfo *addr)
}
int
create_udp_sock(struct addrinfo *addr)
create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t addrlen, int v6only, int* inuse, int* noproto)
{
int s;
# if defined(IPV6_V6ONLY)
# if defined(IPV6_USE_MIN_MTU)
int on=1;
# 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 (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
&on, (socklen_t)sizeof(on)) < 0) {
log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
strerror(errno));
return -1;
if(v6only) {
int val=(v6only==2)?0:1;
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
(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;
}
}
# endif
# if defined(IPV6_USE_MIN_MTU)
@@ -115,72 +148,130 @@ create_udp_sock(struct addrinfo *addr)
* 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;
}
/**
* 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)
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) {
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;
@@ -191,20 +282,39 @@ create_tcp_accept_sock(struct addrinfo *addr)
*/
static int
make_sock(int stype, const char* ifname, const char* port,
struct addrinfo *hints)
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);
else s = create_tcp_accept_sock(res);
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;
}
@@ -213,11 +323,11 @@ make_sock(int stype, const char* ifname, const char* port,
* Add port to open ports list.
* @param list: list head. changed.
* @param s: fd.
* @param is_udp: if fd is UDP.
* @param ftype: if fd is UDP.
* @return false on failure. list in unchanged then.
*/
static int
port_insert(struct listen_port** list, int s, int is_udp)
port_insert(struct listen_port** list, int s, enum listen_type ftype)
{
struct listen_port* item = (struct listen_port*)malloc(
sizeof(struct listen_port));
@@ -225,14 +335,71 @@ port_insert(struct listen_port** list, int s, int is_udp)
return 0;
item->next = *list;
item->fd = s;
item->is_udp = is_udp;
item->ftype = ftype;
*list = item;
return 1;
}
/** set fd to receive source address packet info */
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,
(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,
(void*)&on, (socklen_t)sizeof(on)) < 0) {
log_err("setsockopt(..., IPV6_PKTINFO, ...) failed: %s",
strerror(errno));
return 0;
}
# else
log_err("no IPV6_RECVPKTINFO and no IPV6_PKTINFO option, please "
"disable interface-automatic in config");
return 0;
# endif /* defined IPV6_RECVPKTINFO */
} else if(family == AF_INET) {
# ifdef IP_RECVDSTADDR
if(setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR,
(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,
(void*)&on, (socklen_t)sizeof(on)) < 0) {
log_err("setsockopt(..., IP_PKTINFO, ...) failed: %s",
strerror(errno));
return 0;
}
# else
log_err("no IP_RECVDSTADDR or IP_PKTINFO option, please disable "
"interface-automatic in config");
return 0;
# endif /* IP_PKTINFO */
}
return 1;
}
/**
* Helper for ports_open. Creates one interface (or NULL for default).
* @param ifname: The interface ip address.
* @param do_auto: use automatic interface detection.
* If enabled, then ifname must be the wildcard name.
* @param do_udp: if udp should be used.
* @param do_tcp: if udp should be used.
* @param hints: for getaddrinfo. family and flags have to be set by caller.
@@ -241,25 +408,53 @@ port_insert(struct listen_port** list, int s, int is_udp)
* @return: returns false on error.
*/
static int
ports_create_if(const char* ifname, int do_udp, int do_tcp,
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_udp) {
if((s = make_sock(SOCK_DGRAM, ifname, port, hints)) == -1)
if(do_auto) {
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, 1)) {
}
/* getting source addr packet info is highly non-portable */
if(!set_recvpktinfo(s, hints->ai_family))
return 0;
if(!port_insert(list, s, listen_type_udpancil)) {
close(s);
return 0;
}
} else if(do_udp) {
/* regular udp socket */
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) {
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, 0)) {
if(!port_insert(list, s, listen_type_tcp)) {
close(s);
return 0;
}
@@ -288,7 +483,8 @@ listen_cp_insert(struct comm_point* c, struct listen_dnsport* front)
struct listen_dnsport*
listen_create(struct comm_base* base, struct listen_port* ports,
size_t bufsize, comm_point_callback_t* cb, void *cb_arg)
size_t bufsize, int tcp_accept_count,
comm_point_callback_t* cb, void *cb_arg)
{
struct listen_dnsport* front = (struct listen_dnsport*)
malloc(sizeof(struct listen_dnsport));
@@ -304,11 +500,15 @@ listen_create(struct comm_base* base, struct listen_port* ports,
/* create comm points as needed */
while(ports) {
struct comm_point* cp = NULL;
if(ports->is_udp)
if(ports->ftype == listen_type_udp)
cp = comm_point_create_udp(base, ports->fd,
front->udp_buff, cb, cb_arg);
else cp = comm_point_create_tcp(base, ports->fd,
TCP_ACCEPT_COUNT, bufsize, cb, cb_arg);
else if(ports->ftype == listen_type_tcp)
cp = comm_point_create_tcp(base, ports->fd,
tcp_accept_count, bufsize, cb, cb_arg);
else if(ports->ftype == listen_type_udpancil)
cp = comm_point_create_udp_ancil(base, ports->fd,
front->udp_buff, cb, cb_arg);
if(!cp) {
log_err("can't create commpoint");
listen_delete(front);
@@ -381,10 +581,15 @@ listening_ports_open(struct config_file* cfg)
struct listen_port* list = NULL;
struct addrinfo hints;
int i, do_ip4, do_ip6;
int do_tcp, do_auto;
char portbuf[32];
snprintf(portbuf, sizeof(portbuf), "%d", cfg->port);
do_ip4 = cfg->do_ip4;
do_ip6 = cfg->do_ip6;
do_tcp = cfg->do_tcp;
do_auto = cfg->if_automatic && cfg->do_udp;
if(cfg->incoming_num_tcp == 0)
do_tcp = 0;
/* getaddrinfo */
memset(&hints, 0, sizeof(hints));
@@ -399,11 +604,16 @@ listening_ports_open(struct config_file* cfg)
if(!do_ip4 && !do_ip6) {
return NULL;
}
if(do_auto && (!do_ip4 || !do_ip6)) {
log_warn("interface_automatic option does not work when IP4 or IP6 is not enabled. Disabling option.");
do_auto = 0;
}
/* create ip4 and ip6 ports so that return addresses are nice. */
if(cfg->num_ifs == 0) {
if(do_auto || cfg->num_ifs == 0) {
if(do_ip6) {
hints.ai_family = AF_INET6;
if(!ports_create_if(NULL, cfg->do_udp, cfg->do_tcp,
if(!ports_create_if(do_auto?"::0":"::1",
do_auto, cfg->do_udp, do_tcp,
&hints, portbuf, &list)) {
listening_ports_free(list);
return NULL;
@@ -411,7 +621,8 @@ listening_ports_open(struct config_file* cfg)
}
if(do_ip4) {
hints.ai_family = AF_INET;
if(!ports_create_if(NULL, cfg->do_udp, cfg->do_tcp,
if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1",
do_auto, cfg->do_udp, do_tcp,
&hints, portbuf, &list)) {
listening_ports_free(list);
return NULL;
@@ -422,8 +633,8 @@ listening_ports_open(struct config_file* cfg)
if(!do_ip6)
continue;
hints.ai_family = AF_INET6;
if(!ports_create_if(cfg->ifs[i], cfg->do_udp,
cfg->do_tcp, &hints, portbuf, &list)) {
if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
do_tcp, &hints, portbuf, &list)) {
listening_ports_free(list);
return NULL;
}
@@ -431,8 +642,8 @@ listening_ports_open(struct config_file* cfg)
if(!do_ip4)
continue;
hints.ai_family = AF_INET;
if(!ports_create_if(cfg->ifs[i], cfg->do_udp,
cfg->do_tcp, &hints, portbuf, &list)) {
if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
do_tcp, &hints, portbuf, &list)) {
listening_ports_free(list);
return NULL;
}
+27 -8
View File
@@ -45,12 +45,8 @@
#include "config.h"
#include "util/netevent.h"
struct listen_list;
struct addrinfo;
struct config_file;
/** number of simultaneous open TCP connections for queries */
#define TCP_ACCEPT_COUNT 10
/**
* Listening for queries structure.
* Contains list of query-listen sockets.
@@ -77,6 +73,18 @@ struct listen_list {
struct comm_point* com;
};
/**
* type of ports
*/
enum listen_type {
/** udp type */
listen_type_udp,
/** tcp type */
listen_type_tcp,
/** udp ipv6 (v4mapped) for use with ancillary data */
listen_type_udpancil
};
/**
* Single linked list to store shared ports that have been
* opened for use by all threads.
@@ -87,7 +95,7 @@ struct listen_port {
/** file descriptor, open and ready for use */
int fd;
/** type of file descriptor, udp or tcp */
int is_udp;
enum listen_type ftype;
};
/**
@@ -111,13 +119,15 @@ void listening_ports_free(struct listen_port* list);
* for default all ifs.
* @param ports: the list of shared ports.
* @param bufsize: size of datagram buffer.
* @param tcp_accept_count: max number of simultaneous TCP connections
* from clients.
* @param cb: callback function when a request arrives. It is passed
* the packet and user argument. Return true to send a reply.
* @param cb_arg: user data argument for callback function.
* @return: the malloced listening structure, ready for use. NULL on error.
*/
struct listen_dnsport* listen_create(struct comm_base* base,
struct listen_port* ports, size_t bufsize,
struct listen_port* ports, size_t bufsize, int tcp_accept_count,
comm_point_callback_t* cb, void* cb_arg);
/**
@@ -154,9 +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 create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t addrlen, int v6only, int* inuse, int* noproto);
#endif /* LISTEN_DNSPORT_H */
+1041
View File
File diff suppressed because it is too large Load Diff
+215
View File
@@ -0,0 +1,215 @@
/*
* services/localzone.h - local zones authority service.
*
* Copyright (c) 2007, 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 file contains functions to enable local zone authority service.
*/
#ifndef SERVICES_LOCALZONE_H
#define SERVICES_LOCALZONE_H
#include "util/rbtree.h"
struct ub_packed_rrset_key;
struct regional;
struct config_file;
struct edns_data;
struct query_info;
/**
* Local zone type
* This type determines processing for queries that did not match
* local-data directly.
*/
enum localzone_type {
/** drop query */
local_zone_deny = 0,
/** answer with error */
local_zone_refuse,
/** answer nxdomain or nodata */
local_zone_static,
/** resolve normally */
local_zone_transparent,
/** answer with data at zone apex */
local_zone_redirect,
/** remove default AS112 blocking contents for zone
* nodefault is used in config not during service. */
local_zone_nodefault
};
/**
* Authoritative local zones storage, shared.
* This tree is fixed at startup, so, readonly, no locks or mutexes necessary.
*/
struct local_zones {
/** rbtree of struct local_zone */
rbtree_t ztree;
};
/**
* Local zone. A locally served authoritative zone.
*/
struct local_zone {
/** rbtree node, key is name and class */
rbnode_t node;
/** parent zone, if any. */
struct local_zone* parent;
/** zone name, in uncompressed wireformat */
uint8_t* name;
/** length of zone name */
size_t namelen;
/** number of labels in zone name */
int namelabs;
/** the class of this zone.
* uses 'dclass' to not conflict with c++ keyword class. */
uint16_t dclass;
/** how to process zone */
enum localzone_type type;
/** in this region the zone's data is allocated.
* the struct local_zone itself is malloced. */
struct regional* region;
/** local data for this zone
* rbtree of struct local_data */
rbtree_t data;
/** if data contains zone apex SOA data, this is a ptr to it. */
struct ub_packed_rrset_key* soa;
};
/**
* Local data. One domain name, and the RRs to go with it.
*/
struct local_data {
/** rbtree node, key is name only */
rbnode_t node;
/** domain name */
uint8_t* name;
/** length of name */
size_t namelen;
/** number of labels in name */
int namelabs;
/** the data rrsets, with different types, linked list.
* If this list is NULL, the node is an empty non-terminal. */
struct local_rrset* rrsets;
};
/**
* A local data RRset
*/
struct local_rrset {
/** next in list */
struct local_rrset* next;
/** RRset data item */
struct ub_packed_rrset_key* rrset;
};
/**
* Create local zones storage
* @return new struct or NULL on error.
*/
struct local_zones* local_zones_create();
/**
* Delete local zones storage
* @param zones: to delete.
*/
void local_zones_delete(struct local_zones* zones);
/**
* Apply config settings; setup the local authoritative data.
* @param zones: is set up.
* @param cfg: config data.
* @return false on error.
*/
int local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg);
/**
* Compare two local_zone entries in rbtree. Sort hierarchical but not
* canonical
* @param z1: zone 1
* @param z2: zone 2
* @return: -1, 0, +1 comparison value.
*/
int local_zone_cmp(const void* z1, const void* z2);
/**
* Compare two local_data entries in rbtree. Sort canonical.
* @param d1: data 1
* @param d2: data 2
* @return: -1, 0, +1 comparison value.
*/
int local_data_cmp(const void* d1, const void* d2);
/**
* Delete one zone
* @param z: to delete.
*/
void local_zone_delete(struct local_zone* z);
/**
* Lookup zone that contains the given name, class.
* @param zones: the zones tree
* @param name: dname to lookup
* @param len: length of name.
* @param labs: labelcount of name.
* @param dclass: class to lookup.
* @return closest local_zone or NULL if no covering zone is found.
*/
struct local_zone* local_zones_lookup(struct local_zones* zones,
uint8_t* name, size_t len, int labs, uint16_t dclass);
/**
* Debug helper. Print all zones
* @param zones: the zones tree
*/
void local_zones_print(struct local_zones* zones);
/**
* Answer authoritatively for local zones.
* @param zones: the stored zones (shared, read only).
* @param qinfo: query info (parsed).
* @param edns: edns info (parsed).
* @param buf: buffer with query ID and flags, also for reply.
* @param temp: temporary storage region.
* @return true if answer is in buffer. false if query is not answered
* by authority data. If the reply should be dropped altogether, the return
* value is true, but the buffer is cleared (empty).
*/
int local_zones_answer(struct local_zones* zones, struct query_info* qinfo,
struct edns_data* edns, ldns_buffer* buf, struct regional* temp);
#endif /* SERVICES_LOCALZONE_H */
+329 -92
View File
@@ -45,23 +45,25 @@
#include "config.h"
#include "services/mesh.h"
#include "services/outbound_list.h"
#include "services/cache/dns.h"
#include "util/log.h"
#include "util/net_help.h"
#include "util/module.h"
#include "util/region-allocator.h"
#include "util/regional.h"
#include "util/data/msgencode.h"
#include "util/timehist.h"
#include "util/fptr_wlist.h"
#include "util/alloc.h"
/** compare two mesh_states */
static int
int
mesh_state_compare(const void* ap, const void* bp)
{
struct mesh_state* a = (struct mesh_state*)ap;
struct mesh_state* b = (struct mesh_state*)bp;
if(a->is_priming && !b->is_priming)
if(a->s.is_priming && !b->s.is_priming)
return -1;
if(!a->is_priming && b->is_priming)
if(!a->s.is_priming && b->s.is_priming)
return 1;
if((a->s.query_flags&BIT_RD) && !(b->s.query_flags&BIT_RD))
@@ -69,11 +71,15 @@ mesh_state_compare(const void* ap, const void* bp)
if(!(a->s.query_flags&BIT_RD) && (b->s.query_flags&BIT_RD))
return 1;
if((a->s.query_flags&BIT_CD) && !(b->s.query_flags&BIT_CD))
return -1;
if(!(a->s.query_flags&BIT_CD) && (b->s.query_flags&BIT_CD))
return 1;
return query_info_compare(&a->s.qinfo, &b->s.qinfo);
}
/** compare two mesh references */
static int
int
mesh_state_ref_compare(const void* ap, const void* bp)
{
struct mesh_state_ref* a = (struct mesh_state_ref*)ap;
@@ -82,8 +88,7 @@ mesh_state_ref_compare(const void* ap, const void* bp)
}
struct mesh_area*
mesh_create(int num_modules, struct module_func_block** modfunc,
struct module_env* env)
mesh_create(struct module_stack* stack, struct module_env* env)
{
struct mesh_area* mesh = calloc(1, sizeof(struct mesh_area));
if(!mesh) {
@@ -96,8 +101,7 @@ mesh_create(int num_modules, struct module_func_block** modfunc,
log_err("mesh area alloc: out of memory");
return NULL;
}
mesh->num_modules = num_modules;
mesh->modfunc = modfunc;
mesh->mods = *stack;
mesh->env = env;
rbtree_init(&mesh->run, &mesh_state_compare);
rbtree_init(&mesh->all, &mesh_state_compare);
@@ -151,12 +155,12 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
mesh->num_detached_states++;
added = 1;
}
if(!s->reply_list && s->super_set.count == 0)
if(!s->reply_list && !s->cb_list && s->super_set.count == 0)
was_detached = 1;
if(!s->reply_list)
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);
@@ -178,6 +182,52 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
mesh_run(mesh, s, module_event_new, NULL);
}
int
mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, struct edns_data* edns, ldns_buffer* buf,
uint16_t qid, mesh_cb_func_t cb, void* cb_arg)
{
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags, 0);
int was_detached = 0;
int was_noreply = 0;
int added = 0;
/* see if it already exists, if not, create one */
if(!s) {
struct rbnode_t* n;
s = mesh_state_create(mesh->env,qinfo, qflags, 0);
if(!s) {
return 0;
}
n = rbtree_insert(&mesh->all, &s->node);
log_assert(n != NULL);
/* set detached (it is now) */
mesh->num_detached_states++;
added = 1;
}
if(!s->reply_list && !s->cb_list && s->super_set.count == 0)
was_detached = 1;
if(!s->reply_list && !s->cb_list)
was_noreply = 1;
/* add reply to s */
if(!mesh_state_add_cb(s, edns, buf, cb, cb_arg, qid, qflags)) {
if(added)
mesh_state_delete(&s->s);
return 0;
}
/* update statistics */
if(was_detached) {
log_assert(mesh->num_detached_states > 0);
mesh->num_detached_states--;
}
if(was_noreply) {
mesh->num_reply_states ++;
}
mesh->num_reply_addrs++;
if(added)
mesh_run(mesh, s, module_event_new, NULL);
return 1;
}
void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e,
int is_ok, struct comm_reply* reply)
{
@@ -190,15 +240,15 @@ struct mesh_state*
mesh_state_create(struct module_env* env, struct query_info* qinfo,
uint16_t qflags, int prime)
{
region_type* region = region_create(malloc, free);
struct regional* region = alloc_reg_obtain(env->alloc);
struct mesh_state* mstate;
int i;
if(!region)
return NULL;
mstate = (struct mesh_state*)region_alloc(region,
mstate = (struct mesh_state*)regional_alloc(region,
sizeof(struct mesh_state));
if(!mstate) {
region_destroy(region);
alloc_reg_release(env->alloc, region);
return NULL;
}
memset(mstate, 0, sizeof(*mstate));
@@ -206,30 +256,32 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
mstate->run_node = *RBTREE_NULL;
mstate->node.key = mstate;
mstate->run_node.key = mstate;
mstate->debug_flags = 0;
mstate->is_priming = prime;
mstate->reply_list = NULL;
rbtree_init(&mstate->super_set, &mesh_state_ref_compare);
rbtree_init(&mstate->sub_set, &mesh_state_ref_compare);
mstate->num_activated = 0;
/* init module qstate */
mstate->s.qinfo.qtype = qinfo->qtype;
mstate->s.qinfo.qclass = qinfo->qclass;
mstate->s.qinfo.qname_len = qinfo->qname_len;
mstate->s.qinfo.qname = region_alloc_init(region, qinfo->qname,
mstate->s.qinfo.qname = regional_alloc_init(region, qinfo->qname,
qinfo->qname_len);
if(!mstate->s.qinfo.qname) {
region_destroy(region);
alloc_reg_release(env->alloc, region);
return NULL;
}
/* remove all weird bits from qflags */
mstate->s.query_flags = (qflags & BIT_RD);
mstate->s.query_flags = (qflags & (BIT_RD|BIT_CD));
mstate->s.is_priming = prime;
mstate->s.reply = NULL;
mstate->s.region = region;
mstate->s.curmod = 0;
mstate->s.return_msg = 0;
mstate->s.return_rcode = LDNS_RCODE_NOERROR;
mstate->s.env = env;
mstate->s.mesh_info = mstate;
/* init modules */
for(i=0; i<env->mesh->num_modules; i++) {
for(i=0; i<env->mesh->mods.num; i++) {
mstate->s.minfo[i] = NULL;
mstate->s.ext_state[i] = module_state_initial;
}
@@ -245,12 +297,13 @@ mesh_state_cleanup(struct mesh_state* mstate)
return;
/* de-init modules */
mesh = mstate->s.env->mesh;
for(i=0; i<mesh->num_modules; i++) {
(*mesh->modfunc[i]->clear)(&mstate->s, i);
for(i=0; i<mesh->mods.num; i++) {
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;
}
region_destroy(mstate->s.region);
alloc_reg_release(mstate->s.env->alloc, mstate->s.region);
}
void
@@ -264,11 +317,12 @@ mesh_state_delete(struct module_qstate* qstate)
mstate = qstate->mesh_info;
mesh = mstate->s.env->mesh;
mesh_detach_subs(&mstate->s);
if(!mstate->reply_list && mstate->super_set.count == 0) {
if(!mstate->reply_list && !mstate->cb_list
&& mstate->super_set.count == 0) {
log_assert(mesh->num_detached_states > 0);
mesh->num_detached_states--;
}
if(mstate->reply_list) {
if(mstate->reply_list || mstate->cb_list) {
log_assert(mesh->num_reply_states > 0);
mesh->num_reply_states--;
}
@@ -292,7 +346,8 @@ void mesh_detach_subs(struct module_qstate* qstate)
RBTREE_FOR(ref, struct mesh_state_ref*, &qstate->mesh_info->sub_set) {
n = rbtree_delete(&ref->s->super_set, &lookup);
log_assert(n != NULL); /* must have been present */
if(!ref->s->reply_list && ref->s->super_set.count == 0) {
if(!ref->s->reply_list && !ref->s->cb_list
&& ref->s->super_set.count == 0) {
mesh->num_detached_states++;
log_assert(mesh->num_detached_states +
mesh->num_reply_states <= mesh->all.count);
@@ -327,7 +382,7 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
*newq = NULL;
if(!mesh_state_attachment(qstate->mesh_info, sub))
return 0;
if(!sub->reply_list && sub->super_set.count == 1) {
if(!sub->reply_list && !sub->cb_list && sub->super_set.count == 1) {
/* it used to be detached, before this one got added */
log_assert(mesh->num_detached_states > 0);
mesh->num_detached_states--;
@@ -341,9 +396,9 @@ int mesh_state_attachment(struct mesh_state* super, struct mesh_state* sub)
struct rbnode_t* n;
struct mesh_state_ref* subref; /* points to sub, inserted in super */
struct mesh_state_ref* superref; /* points to super, inserted in sub */
if( !(subref = region_alloc(super->s.region,
if( !(subref = regional_alloc(super->s.region,
sizeof(struct mesh_state_ref))) ||
!(superref = region_alloc(sub->s.region,
!(superref = regional_alloc(sub->s.region,
sizeof(struct mesh_state_ref))) ) {
log_err("mesh_state_attachment: out of memory");
return 0;
@@ -406,20 +461,90 @@ timeval_divide(struct timeval* avg, struct timeval* sum, size_t d)
#endif
}
/**
* callback results to mesh cb entry
* @param m: mesh state to send it for.
* @param rcode: if not 0, error code.
* @param rep: reply to send (or NULL if rcode is set).
* @param r: callback entry
*/
static void
mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
struct mesh_cb* r)
{
int secure;
/* bogus messages are not made into servfail, sec_status passed
* to the callback function */
if(rep && rep->security == sec_status_secure)
secure = 1;
else secure = 0;
if(!rep && rcode == LDNS_RCODE_NOERROR)
rcode = LDNS_RCODE_SERVFAIL;
/* send the reply */
if(rcode) {
(*r->cb)(r->cb_arg, rcode, r->buf, sec_status_unchecked);
} else {
size_t udp_size = r->edns.udp_size;
ldns_buffer_clear(r->buf);
r->edns.edns_version = EDNS_ADVERTISED_VERSION;
r->edns.udp_size = EDNS_ADVERTISED_SIZE;
r->edns.ext_rcode = 0;
r->edns.bits &= EDNS_DO;
if(!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
r->qflags, r->buf, 0, 1,
m->s.env->scratch, udp_size, &r->edns,
(int)(r->edns.bits & EDNS_DO), secure))
{
(*r->cb)(r->cb_arg, LDNS_RCODE_SERVFAIL, r->buf,
sec_status_unchecked);
}
else (*r->cb)(r->cb_arg, LDNS_RCODE_NOERROR, r->buf,
rep->security);
}
m->s.env->mesh->num_reply_addrs--;
}
/**
* Send reply to mesh reply entry
* @param m: mesh state to send it for.
* @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 &&
rep->security <= sec_status_bogus) {
rcode = LDNS_RCODE_SERVFAIL;
}
if(rep && rep->security == sec_status_secure)
secure = 1;
else secure = 0;
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);
@@ -429,10 +554,11 @@ 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,
(int)(r->edns.bits & EDNS_DO)))
(int)(r->edns.bits & EDNS_DO), secure))
{
error_encode(r->query_reply.c->buffer,
LDNS_RCODE_SERVFAIL, &m->s.qinfo, r->qid,
@@ -442,46 +568,43 @@ 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 module_qstate* qstate, int rcode,
struct reply_info* rep)
void mesh_query_done(struct mesh_state* mstate)
{
struct mesh_state* m = qstate->mesh_info;
struct mesh_reply* r;
log_assert(!(m->debug_flags&1)); /* not twice! */
m->debug_flags |= 1;
for(r = m->reply_list; r; r = r->next) {
mesh_send_reply(m, rcode, rep, 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, prev);
prev = r;
}
for(c = mstate->cb_list; c; c = c->next) {
mesh_do_callback(mstate, mstate->s.return_rcode, rep, c);
}
}
void mesh_walk_supers(struct module_qstate* qstate, int id,
void (*cb)(struct module_qstate*, int, struct module_qstate*))
void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate)
{
struct mesh_state* m = qstate->mesh_info;
struct mesh_area* mesh = m->s.env->mesh;
struct mesh_state_ref* ref;
log_assert(!(m->debug_flags&2)); /* not twice! */
m->debug_flags |= 2;
RBTREE_FOR(ref, struct mesh_state_ref*, &qstate->mesh_info->super_set)
RBTREE_FOR(ref, struct mesh_state_ref*, &mstate->super_set)
{
/* make super runnable */
(void)rbtree_insert(&mesh->run, &ref->s->run_node);
/* callback */
(*cb)(qstate, id, &ref->s->s);
/* callback the function to inform super of result */
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);
}
}
@@ -492,7 +615,7 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
struct mesh_state* result;
key.node.key = &key;
key.is_priming = prime;
key.s.is_priming = prime;
key.s.qinfo = *qinfo;
key.s.query_flags = qflags;
@@ -500,10 +623,30 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
return result;
}
int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
struct comm_reply* rep, uint16_t qid, uint16_t qflags)
int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,
ldns_buffer* buf, mesh_cb_func_t cb, void* cb_arg,
uint16_t qid, uint16_t qflags)
{
struct mesh_reply* r = region_alloc(s->s.region,
struct mesh_cb* r = regional_alloc(s->s.region,
sizeof(struct mesh_cb));
if(!r)
return 0;
r->buf = buf;
r->cb = cb;
r->cb_arg = cb_arg;
r->edns = *edns;
r->qid = qid;
r->qflags = qflags;
r->next = s->cb_list;
s->cb_list = r;
return 1;
}
int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
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));
if(!r)
return 0;
@@ -511,16 +654,76 @@ 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;
}
/**
* Continue processing the mesh state at another module.
* Handles module to modules tranfer of control.
* Handles module finished.
* @param mesh: the mesh area.
* @param mstate: currently active mesh state.
* Deleted if finished, calls _done and _supers to
* send replies to clients and inform other mesh states.
* This in turn may create additional runnable mesh states.
* @param s: state at which the current module exited.
* @param ev: the event sent to the module.
* returned is the event to send to the next module.
* @return true if continue processing at the new module.
* false if not continued processing is needed.
*/
static int
mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
enum module_ext_state s, enum module_ev* ev)
{
mstate->num_activated++;
if(mstate->num_activated > MESH_MAX_ACTIVATION) {
/* module is looping. Stop it. */
log_err("internal error: looping module stopped");
log_query_info(VERB_QUERY, "pass error for qstate",
&mstate->s.qinfo);
s = module_error;
}
if(s == module_wait_module) {
/* start next module */
mstate->s.curmod++;
if(mesh->mods.num == mstate->s.curmod) {
log_err("Cannot pass to next module; at last module");
log_query_info(VERB_QUERY, "pass error for qstate",
&mstate->s.qinfo);
mstate->s.curmod--;
return mesh_continue(mesh, mstate, module_error, ev);
}
*ev = module_event_pass;
return 1;
}
if(s == module_error && mstate->s.return_rcode == LDNS_RCODE_NOERROR) {
/* error is bad, handle pass back up below */
mstate->s.return_rcode = LDNS_RCODE_SERVFAIL;
}
if(s == module_error || s == module_finished) {
if(mstate->s.curmod == 0) {
mesh_query_done(mstate);
mesh_walk_supers(mesh, mstate);
mesh_state_delete(&mstate->s);
return 0;
}
/* pass along the locus of control */
mstate->s.curmod --;
*ev = module_event_moddone;
return 1;
}
return 0;
}
void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
enum module_ev ev, struct outbound_entry* e)
{
@@ -528,54 +731,87 @@ void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
verbose(VERB_ALGO, "mesh_run: start");
while(mstate) {
/* run the module */
(*mesh->modfunc[mstate->s.curmod]->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);
/* examine results */
mstate->s.reply = NULL;
region_free_all(mstate->s.env->scratch);
regional_free_all(mstate->s.env->scratch);
s = mstate->s.ext_state[mstate->s.curmod];
verbose(VERB_ALGO, "mesh_run: %s module exit state is %s",
mesh->modfunc[mstate->s.curmod]->name, strextstate(s));
if(s == module_error || s == module_finished) {
/* must have called _done and _supers */
log_assert(mstate->debug_flags == 3);
mesh_state_delete(&mstate->s);
}
mesh->mods.mod[mstate->s.curmod]->name, strextstate(s));
e = NULL;
if(mesh_continue(mesh, mstate, s, &ev))
continue;
/* run more modules */
ev = module_event_pass;
e = NULL;
if(mesh->run.count > 0) {
/* pop random element off the runnable tree */
mstate = (struct mesh_state*)mesh->run.root->key;
(void)rbtree_delete(&mesh->run, mstate);
} else mstate = NULL;
}
if(verbosity >= VERB_ALGO)
if(verbosity >= VERB_ALGO) {
mesh_stats(mesh, "mesh_run: end");
mesh_log_list(mesh);
}
}
void
mesh_log_list(struct mesh_area* mesh)
{
char buf[30];
struct mesh_state* m;
int num = 0;
RBTREE_FOR(m, struct mesh_state*, &mesh->all) {
snprintf(buf, sizeof(buf), "%d%s%s%s%s%s mod%d %s%s",
num++, (m->s.is_priming)?"p":"", /* prime */
(m->s.query_flags&BIT_RD)?"RD":"",
(m->s.query_flags&BIT_CD)?"CD":"",
(m->super_set.count==0)?"d":"", /* detached */
(m->sub_set.count!=0)?"c":"", /* children */
m->s.curmod, (m->reply_list)?"rep":"", /*hasreply*/
(m->cb_list)?"cb":"" /* callbacks */
);
log_query_info(VERB_ALGO, buf, &m->s.qinfo);
}
}
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");
}
}
void
mesh_stats_clear(struct mesh_area* mesh)
{
if(!mesh)
return;
mesh->replies_sent = 0;
mesh->replies_sum_wait.tv_sec = 0;
mesh->replies_sum_wait.tv_usec = 0;
timehist_clear(mesh->histogram);
}
size_t
mesh_get_mem(struct mesh_area* mesh)
{
@@ -584,7 +820,7 @@ mesh_get_mem(struct mesh_area* mesh)
sizeof(struct th_buck)*mesh->histogram->num;
RBTREE_FOR(m, struct mesh_state*, &mesh->all) {
/* all, including m itself allocated in qstate region */
s += region_get_mem(m->s.region);
s += regional_get_mem(m->s.region);
}
return s;
}
@@ -602,11 +838,12 @@ find_in_subsub(struct mesh_state* m, struct mesh_state* tofind)
}
int
mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo)
mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo,
uint16_t flags, int prime)
{
struct mesh_area* mesh = qstate->env->mesh;
struct mesh_state* cyc_m = qstate->mesh_info;
struct mesh_state* dep_m = mesh_area_find(mesh, qinfo, BIT_RD, 0);
struct mesh_state* dep_m = mesh_area_find(mesh, qinfo, flags, prime);
if(!dep_m)
return 0;
if(dep_m == cyc_m || find_in_subsub(dep_m, cyc_m))
+123 -34
View File
@@ -50,21 +50,27 @@
#include "util/netevent.h"
#include "util/data/msgparse.h"
#include "util/module.h"
#include "services/modstack.h"
struct mesh_state;
struct mesh_reply;
struct mesh_cb;
struct query_info;
struct reply_info;
struct outbound_entry;
struct timehist;
/**
* Maximum number of mesh state activations. Any more is likely an
* infinite loop in the module. It is then terminated.
*/
#define MESH_MAX_ACTIVATION 1000
/**
* Mesh of query states
*/
struct mesh_area {
/** the number of modules */
int num_modules;
/** the module callbacks, array of num_modules length (ref only) */
struct module_func_block** modfunc;
/** active module stack */
struct module_stack mods;
/** environment for new states */
struct module_env* env;
@@ -95,7 +101,7 @@ struct mesh_area {
/**
* A mesh query state
* Unique per qname, qtype, qclass (from the qstate).
* And RD flag; in case a client turns it off.
* And RD / CD flag; in case a client turns it off.
* And priming queries are different from ordinary queries (because of hints).
*
* The entire structure is allocated in a region, this region is the qstate
@@ -106,21 +112,21 @@ struct mesh_state {
rbnode_t node;
/** node in mesh_area runnable tree, key is this struct */
rbnode_t run_node;
/** if this is a (stub or root) priming query (with hints) */
int is_priming;
/** the query state. Note that the qinfo and query_flags
* may not change. */
struct module_qstate s;
/** the list of replies to clients for the results */
struct mesh_reply* reply_list;
/** debug flags */
int debug_flags;
/** the list of callbacks for the results */
struct mesh_cb* cb_list;
/** set of superstates (that want this state's result)
* contains struct mesh_state_ref* */
rbtree_t super_set;
/** set of substates (that this state needs to continue)
* contains struct mesh_state_ref* */
rbtree_t sub_set;
/** number of activations for the mesh state */
size_t num_activated;
};
/**
@@ -150,20 +156,49 @@ 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;
};
/**
* Mesh result callback func.
* called as func(cb_arg, rcode, buffer_with_reply, security);
* */
typedef void (*mesh_cb_func_t)(void*, int, ldns_buffer*, enum sec_status);
/**
* Callback to result routine
*/
struct mesh_cb {
/** next in list */
struct mesh_cb* next;
/** edns data from query */
struct edns_data edns;
/** id of query, in network byteorder. */
uint16_t qid;
/** flags of query, for reply flags */
uint16_t qflags;
/** buffer for reply */
ldns_buffer* buf;
/** callback routine for results. if rcode != 0 buf has message.
* called as cb(cb_arg, rcode, buf);
*/
mesh_cb_func_t cb;
/** user arg for callback */
void* cb_arg;
};
/* ------------------- Functions for worker -------------------- */
/**
* Allocate mesh, to empty.
* @param num_modules: number of modules that are present.
* @param modfunc: array passed (alloced and deleted by caller), that has
* num_modules function callbacks for the modules.
* @param stack: module stack to activate, copied (as readonly reference).
* @param env: environment for new queries.
* @return mesh: the new mesh or NULL on error.
*/
struct mesh_area* mesh_create(int num_modules,
struct module_func_block** modfunc, struct module_env* env);
struct mesh_area* mesh_create(struct module_stack* stack,
struct module_env* env);
/**
* Delete mesh, and all query states and replies in it.
@@ -187,6 +222,25 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, struct edns_data* edns, struct comm_reply* rep,
uint16_t qid);
/**
* New query with callback. Create new query state if needed, and
* add mesh_cb to it.
* Will run the mesh area queries to process if a new query state is created.
*
* @param mesh: the mesh.
* @param qinfo: query from client.
* @param qflags: flags from client query.
* @param edns: edns data from client query.
* @param buf: buffer for reply contents.
* @param qid: query id to reply with.
* @param cb: callback function.
* @param cb_arg: callback user arg.
* @return 0 on error.
*/
int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, struct edns_data* edns, ldns_buffer* buf,
uint16_t qid, mesh_cb_func_t cb, void* cb_arg);
/**
* Handle new event from the wire. A serviced query has returned.
* The query state will be made runnable, and the mesh_area will process
@@ -226,7 +280,7 @@ void mesh_detach_subs(struct module_qstate* qstate);
* @param qstate: the state to find mesh state, and that wants to receive
* the results from the new subquery.
* @param qinfo: what to query for (copied).
* @param qflags: what flags to use (RD flag or not).
* @param qflags: what flags to use (RD / CD flag or not).
* @param prime: if it is a (stub) priming query.
* @param newq: If the new subquery needs initialisation, it is returned,
* otherwise NULL is returned.
@@ -244,28 +298,25 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
* Must be called before a module can module_finished or return module_error.
* The module must handle the super query states itself as well.
*
* @param qstate: used for original query info. And to find mesh info.
* @param rcode: if not 0 (NOERROR) an error is sent back (and rep ignored).
* @param rep: reply to encode and send back to clients.
* @param mstate: mesh state that is done. return_rcode and return_msg
* are used for replies.
* return_rcode: if not 0 (NOERROR) an error is sent back (and
* return_msg is ignored).
* return_msg: reply to encode and send back to clients.
*/
void mesh_query_done(struct module_qstate* qstate, int rcode,
struct reply_info* rep);
void mesh_query_done(struct mesh_state* mstate);
/**
* Get a callback for the super query states that are interested in the
* Call inform_super for the super query states that are interested in the
* results from this query state. These can then be changed for error
* or results.
* Must be called befor a module can module_finished or return module_error.
* After finishing or module error, the super query states become runnable
* with event module_event_pass.
* Called when a module is module_finished or returns module_error.
* The super query states become runnable with event module_event_pass.
*
* @param qstate: the state that has results, used to find mesh state.
* @param id: module id.
* @param cb: callback function. Called as
* cb(qstate, id, super_qstate) for every super query state.
* @param mesh: mesh area to add newly runnable modules to.
* @param mstate: the state that has results, used to find mesh state.
*/
void mesh_walk_supers(struct module_qstate* qstate, int id,
void (*cb)(struct module_qstate*, int, struct module_qstate*));
void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate);
/**
* Delete mesh state, cleanup and also rbtrees and so on.
@@ -281,7 +332,7 @@ void mesh_state_delete(struct module_qstate* qstate);
* Does not put the mesh state into rbtrees and so on.
* @param env: module environment to set.
* @param qinfo: query info that the mesh is for.
* @param qflags: flags for query (RD flag).
* @param qflags: flags for query (RD / CD flag).
* @param prime: if true, it is a priming query, set is_priming on mesh state.
* @return: new mesh state or NULL on allocation error.
*/
@@ -301,7 +352,7 @@ void mesh_state_cleanup(struct mesh_state* mstate);
*
* @param mesh: the mesh area to look in.
* @param qinfo: what query
* @param qflags: if RD bit is set or not.
* @param qflags: if RD / CD bit is set or not.
* @param prime: if it is a priming query.
* @return: mesh state or NULL if not found.
*/
@@ -326,10 +377,27 @@ 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.
* Does not update stat items in mesh area.
* @param s: the mesh state.
* @param edns: edns data for reply (bufsize).
* @param buf: buffer for reply
* @param cb: callback to call with results.
* @param cb_arg: callback user arg.
* @param qid: ID of reply.
* @param qflags: original query flags.
* @return: 0 on alloc error.
*/
int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,
ldns_buffer* buf, mesh_cb_func_t cb, void* cb_arg, uint16_t qid,
uint16_t qflags);
/**
* Run the mesh. Run all runnable mesh states. Which can create new
@@ -350,6 +418,18 @@ void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
*/
void mesh_stats(struct mesh_area* mesh, const char* str);
/**
* Clear the stats that the mesh keeps (number of queries serviced)
* @param mesh: the mesh
*/
void mesh_stats_clear(struct mesh_area* mesh);
/**
* Print all the states in the mesh to the log.
* @param mesh: the mesh to print all states of.
*/
void mesh_log_list(struct mesh_area* mesh);
/**
* Calculate memory size in use by mesh and all queries inside it.
* @param mesh: the mesh to examine.
@@ -362,10 +442,19 @@ size_t mesh_get_mem(struct mesh_area* mesh);
* trees.
* @param qstate: given mesh querystate.
* @param qinfo: query info for dependency.
* @param flags: query flags of dependency.
* @param prime: if dependency is a priming query or not.
* @return true if the name,type,class exists and the given qstate mesh exists
* as a dependency of that name. Thus if qstate becomes dependent on
* name,type,class then a cycle is created.
*/
int mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo);
int mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo,
uint16_t flags, int prime);
/** compare two mesh_states */
int mesh_state_compare(const void* ap, const void* bp);
/** compare two mesh references */
int mesh_state_ref_compare(const void* ap, const void* bp);
#endif /* SERVICES_MESH_H */
+167
View File
@@ -0,0 +1,167 @@
/*
* services/modstack.c - stack of modules
*
* Copyright (c) 2007, 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 file contains functions to help maintain a stack of modules.
*/
#include "config.h"
#include "services/modstack.h"
#include "util/module.h"
#include "util/fptr_wlist.h"
#include "iterator/iterator.h"
#include "validator/validator.h"
/** count number of modules (words) in the string */
static int
count_modules(const char* s)
{
int num = 0;
if(!s)
return 0;
while(*s) {
/* skip whitespace */
while(*s && isspace((int)*s))
s++;
if(*s && !isspace((int)*s)) {
/* skip identifier */
num++;
while(*s && !isspace((int)*s))
s++;
}
}
return num;
}
void
modstack_init(struct module_stack* stack)
{
stack->num = 0;
stack->mod = NULL;
}
int
modstack_config(struct module_stack* stack, const char* module_conf)
{
int i;
verbose(VERB_QUERY, "module config: \"%s\"", module_conf);
stack->num = count_modules(module_conf);
if(stack->num == 0) {
log_err("error: no modules specified");
return 0;
}
if(stack->num > MAX_MODULE) {
log_err("error: too many modules (%d max %d)",
stack->num, MAX_MODULE);
return 0;
}
stack->mod = (struct module_func_block**)calloc((size_t)
stack->num, sizeof(struct module_func_block*));
if(!stack->mod) {
log_err("out of memory");
return 0;
}
for(i=0; i<stack->num; i++) {
stack->mod[i] = module_factory(&module_conf);
if(!stack->mod[i]) {
log_err("Unknown value for next module: '%s'",
module_conf);
return 0;
}
}
return 1;
}
struct
module_func_block* module_factory(const char** str)
{
/* these are the modules available */
int num = 2;
const char* names[] = {"iterator", "validator", NULL};
struct module_func_block* (*fb[])(void) =
{&iter_get_funcblock, &val_get_funcblock, NULL};
int i;
const char* s = *str;
while(*s && isspace((int)*s))
s++;
for(i=0; i<num; i++) {
if(strncmp(names[i], s, strlen(names[i])) == 0) {
s += strlen(names[i]);
*str = s;
return (*fb[i])();
}
}
return NULL;
}
int
modstack_setup(struct module_stack* stack, const char* module_conf,
struct module_env* env)
{
int i;
if(stack->num != 0)
modstack_desetup(stack, env);
/* fixed setup of the modules */
if(!modstack_config(stack, module_conf)) {
return 0;
}
env->need_to_validate = 0; /* set by module init below */
for(i=0; i<stack->num; i++) {
verbose(VERB_OPS, "init module %d: %s",
i, stack->mod[i]->name);
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);
return 0;
}
}
return 1;
}
void
modstack_desetup(struct module_stack* stack, struct module_env* env)
{
int i;
for(i=0; i<stack->num; i++) {
fptr_ok(fptr_whitelist_mod_deinit(stack->mod[i]->deinit));
(*stack->mod[i]->deinit)(env, i);
}
stack->num = 0;
free(stack->mod);
stack->mod = NULL;
}
+99
View File
@@ -0,0 +1,99 @@
/*
* services/modstack.h - stack of modules
*
* Copyright (c) 2007, 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 file contains functions to help maintain a stack of modules.
*/
#ifndef SERVICES_MODSTACK_H
#define SERVICES_MODSTACK_H
struct module_func_block;
struct module_env;
/**
* Stack of modules.
*/
struct module_stack {
/** the number of modules */
int num;
/** the module callbacks, array of num_modules length (ref only) */
struct module_func_block** mod;
};
/**
* Init a stack of modules
* @param stack: initialised as empty.
*/
void modstack_init(struct module_stack* stack);
/**
* Read config file module settings and set up the modfunc block
* @param stack: the stack of modules (empty before call).
* @param module_conf: string what modules to insert.
* @return false on error
*/
int modstack_config(struct module_stack* stack, const char* module_conf);
/**
* Get funcblock for module name
* @param str: string with module name. Advanced to next value on success.
* The string is assumed whitespace separated list of module names.
* @return funcblock or NULL on error.
*/
struct module_func_block* module_factory(const char** str);
/**
* Setup modules. Assigns ids and calls module_init.
* @param stack: if not empty beforehand, it will be desetup()ed.
* It is then modstack_configged().
* @param module_conf: string what modules to insert.
* @param env: module environment which is inited by the modules.
* environment should have a superalloc, cfg,
* env.need_to_validate is set by the modules.
* @return on false a module init failed.
*/
int modstack_setup(struct module_stack* stack, const char* module_conf,
struct module_env* env);
/**
* Desetup the modules, deinit, delete.
* @param stack: made empty.
* @param env: module env for module deinit() calls.
*/
void modstack_desetup(struct module_stack* stack, struct module_env* env);
#endif /* SERVICES_MODSTACK_H */
+2 -2
View File
@@ -57,7 +57,7 @@ outbound_list_clear(struct outbound_list* list)
while(p) {
np = p->next;
outnet_serviced_query_stop(p->qsent, p);
free(p);
/* in region, no free needed */
p = np;
}
outbound_list_init(list);
@@ -84,5 +84,5 @@ outbound_list_remove(struct outbound_list* list, struct outbound_entry* e)
if(e->prev)
e->prev->next = e->next;
else list->first = e->next;
free(e);
/* in region, no free needed */
}
+700 -322
View File
File diff suppressed because it is too large Load Diff
+137 -41
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,31 +63,38 @@ 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. */
ldns_buffer* udp_buff;
/** 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;
/** buffer for storage. (buffer for incoming connections, since
* either an event to outside or incoming happens, but not both
* This buffer is used during callbacks, so that the datagram
* that just arrived does not collide with new datagrams sent out. */
ldns_buffer* udp_second;
/** linked list of available commpoints, unused file descriptors,
* for use as outgoing UDP ports. cp.fd=-1 in them. */
struct port_comm* unused_fds;
/**
* 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;
/** array of outgoing IP4 interfaces */
struct port_if* ip4_ifs;
/** number of outgoing IP4 interfaces */
int num_ip4;
/**
* The opened ip6 ports.
*/
struct comm_point** udp6_ports;
/** number of udp6 ports */
size_t num_udp6;
/** 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;
@@ -112,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 */
@@ -134,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;
};
/**
@@ -210,7 +275,7 @@ struct serviced_query {
uint8_t* qbuf;
/** length of qbuf. */
size_t qbuflen;
/** If an EDNS section is included, the DO bit will be turned on. */
/** If an EDNS section is included, the DO/CD bit will be turned on. */
int dnssec;
/** where to send it */
struct sockaddr_storage addr;
@@ -228,7 +293,9 @@ struct serviced_query {
serviced_query_TCP_EDNS,
/** TCP without EDNS sent */
serviced_query_TCP
} status;
}
/** variable with current status */
status;
/** true if serviced_query is scheduled for deletion already */
int to_be_deleted;
/** number of UDP retries */
@@ -253,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.
@@ -271,16 +340,6 @@ struct outside_network* outside_network_create(struct comm_base* base,
*/
void outside_network_delete(struct outside_network* outnet);
/**
* Set secondary UDP buffer. Make sure it is not used during outside network
* callbacks. Such as the incoming network UDP buffer. Caller responsible
* for deletion.
* @param outnet: outside network.
* @param buf: buffer to use as secondary buffer.
*/
void outside_network_set_secondary_buffer(struct outside_network* outnet,
ldns_buffer* buf);
/**
* Send UDP query, create pending answer.
* Changes the ID for the query to be random and unique for that destination.
@@ -291,13 +350,12 @@ void outside_network_set_secondary_buffer(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
@@ -311,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.
@@ -337,6 +394,8 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
* @param qclass: query class. (host format)
* @param flags: flags u16 (host format), includes opcode, CD bit.
* @param dnssec: if set, DO bit is set in EDNS queries.
* If the value includes BIT_CD, CD bit is set when in EDNS queries.
* If the value includes BIT_DO, DO bit is set when in EDNS queries.
* @param callback: callback function.
* @param callback_arg: user argument to callback function.
* @param addr: to which server to send the query.
@@ -371,4 +430,41 @@ void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg);
*/
size_t outnet_get_mem(struct outside_network* outnet);
/**
* Get memory size in use by serviced query while it is servicing callbacks.
* This takes into account the pre-deleted status of it; it will be deleted
* when the callbacks are done.
* @param sq: serviced query.
* @return size in bytes.
*/
size_t serviced_get_mem(struct serviced_query* sq);
/** callback for incoming udp answers from the network */
int outnet_udp_cb(struct comm_point* c, void* arg, int error,
struct comm_reply *reply_info);
/** callback for pending tcp connections */
int outnet_tcp_cb(struct comm_point* c, void* arg, int error,
struct comm_reply *reply_info);
/** callback for udp timeout */
void pending_udp_timer_cb(void *arg);
/** callback for outgoing TCP timer event */
void outnet_tcptimer(void* arg);
/** callback for serviced query UDP answers */
int serviced_udp_callback(struct comm_point* c, void* arg, int error,
struct comm_reply* rep);
/** TCP reply or error callback for serviced queries */
int serviced_tcp_callback(struct comm_point* c, void* arg, int error,
struct comm_reply* rep);
/** compare function of pending rbtree */
int pending_cmp(const void* key1, const void* key2);
/** compare function of serviced query rbtree */
int serviced_cmp(const void* key1, const void* key2);
#endif /* OUTSIDE_NETWORK_H */
+435
View File
@@ -0,0 +1,435 @@
/*
* checkconf/unbound-checkconf.c - config file checker for unbound.conf file.
*
* Copyright (c) 2007, 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
*
* The config checker checks for syntax and other errors in the unbound.conf
* file, and can be used to check for errors before the server is started
* or sigHUPped.
* Exit status 1 means an error.
*/
#include "config.h"
#include "util/log.h"
#include "util/config_file.h"
#include "util/module.h"
#include "util/net_help.h"
#include "util/regional.h"
#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
usage()
{
printf("Usage: unbound-checkconf [file]\n");
printf(" Checks unbound configuration file for errors.\n");
printf("file if omitted %s is used.\n", CONFIGFILE);
printf("-h show this usage help.\n");
printf("Version %s\n", PACKAGE_VERSION);
printf("BSD licensed, see LICENSE in source package for details.\n");
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
exit(1);
}
/** check if module works with config */
static void
check_mod(struct config_file* cfg, struct module_func_block* fb)
{
struct module_env env;
memset(&env, 0, sizeof(env));
env.cfg = cfg;
env.scratch = regional_create();
env.scratch_buffer = ldns_buffer_new(BUFSIZ);
if(!env.scratch || !env.scratch_buffer)
fatal_exit("out of memory");
if(!(*fb->init)(&env, 0)) {
fatal_exit("bad config for %s module", fb->name);
}
(*fb->deinit)(&env, 0);
ldns_buffer_free(env.scratch_buffer);
regional_destroy(env.scratch);
}
/** check localzones */
static void
localzonechecks(struct config_file* cfg)
{
struct local_zones* zs;
if(!(zs = local_zones_create()))
fatal_exit("out of memory");
if(!local_zones_apply_cfg(zs, cfg))
fatal_exit("failed local-zone, local-data configuration");
local_zones_delete(zs);
}
/** emit warnings for IP in hosts */
static void
warn_hosts(const char* typ, struct config_stub* list)
{
struct sockaddr_storage a;
socklen_t alen;
struct config_stub* s;
struct config_strlist* h;
for(s=list; s; s=s->next) {
for(h=s->hosts; h; h=h->next) {
if(extstrtoaddr(h->str, &a, &alen)) {
fprintf(stderr, "unbound-checkconf: warning:"
" %s %s: \"%s\" is an IP%s address, "
"and when looked up as a host name "
"during use may not resolve.\n",
s->name, typ, h->str,
addr_is_ip6(&a, alen)?"6":"4");
}
}
}
}
/** check interface strings */
static void
interfacechecks(struct config_file* cfg)
{
struct sockaddr_storage a;
socklen_t alen;
int i, j;
for(i=0; i<cfg->num_ifs; i++) {
if(!ipstrtoaddr(cfg->ifs[i], UNBOUND_DNS_PORT, &a, &alen)) {
fatal_exit("cannot parse interface specified as '%s'",
cfg->ifs[i]);
}
for(j=0; j<cfg->num_ifs; j++) {
if(i!=j && strcmp(cfg->ifs[i], cfg->ifs[j])==0)
fatal_exit("interface: %s present twice, "
"cannot bind same ports twice.",
cfg->ifs[i]);
}
}
for(i=0; i<cfg->num_out_ifs; i++) {
if(!ipstrtoaddr(cfg->out_ifs[i], UNBOUND_DNS_PORT,
&a, &alen)) {
fatal_exit("cannot parse outgoing-interface "
"specified as '%s'", cfg->out_ifs[i]);
}
for(j=0; j<cfg->num_out_ifs; j++) {
if(i!=j && strcmp(cfg->out_ifs[i], cfg->out_ifs[j])==0)
fatal_exit("outgoing-interface: %s present "
"twice, cannot bind same ports twice.",
cfg->out_ifs[i]);
}
}
}
/** check acl ips */
static void
aclchecks(struct config_file* cfg)
{
int d;
struct sockaddr_storage a;
socklen_t alen;
struct config_str2list* acl;
for(acl=cfg->acls; acl; acl = acl->next) {
if(!netblockstrtoaddr(acl->str, UNBOUND_DNS_PORT, &a, &alen,
&d)) {
fatal_exit("cannot parse access control address %s %s",
acl->str, acl->str2);
}
}
}
/** 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, struct config_file* cfg)
{
struct config_strlist* p;
char* old;
for(p=list; p; p=p->next) {
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, char* fname)
{
warn_hosts("stub-host", cfg->stubs);
warn_hosts("forward-host", cfg->forwards);
interfacechecks(cfg);
aclchecks(cfg);
if(cfg->verbosity < 0)
fatal_exit("verbosity value < 0");
if(cfg->num_threads < 0 || cfg->num_threads > 10000)
fatal_exit("num_threads value weird");
if(!cfg->do_ip4 && !cfg->do_ip6)
fatal_exit("ip4 and ip6 are both disabled, pointless");
if(!cfg->do_udp && !cfg->do_tcp)
fatal_exit("udp and tcp are both disabled, pointless");
if(cfg->chrootdir && cfg->chrootdir[0] &&
cfg->chrootdir[strlen(cfg->chrootdir)-1] == '/')
fatal_exit("chootdir %s has trailing slash '/' please remove.",
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);
check_chroot_filelist("trust-anchor-file",
cfg->trust_anchor_file_list, cfg->chrootdir, cfg);
check_chroot_filelist("trusted-keys-file",
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) {
fatal_exit("module conf '%s' is not known to work",
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);
}
/** check config file */
static void
checkconf(char* cfgfile)
{
struct config_file* cfg = config_create();
if(!cfg)
fatal_exit("out of memory");
if(!config_read(cfg, cfgfile)) {
/* config_read prints messages to stderr */
config_delete(cfg);
exit(1);
}
morechecks(cfg, cfgfile);
check_mod(cfg, iter_get_funcblock());
check_mod(cfg, val_get_funcblock());
config_delete(cfg);
printf("unbound-checkconf: no errors in %s\n", cfgfile);
}
/** 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 routine for checkconf */
int main(int argc, char* argv[])
{
int c;
char* f;
log_ident_set("unbound-checkconf");
log_init(NULL, 0, NULL);
checklock_start();
/* parse the options */
while( (c=getopt(argc, argv, "h")) != -1) {
switch(c) {
case '?':
case 'h':
default:
usage();
}
}
argc -= optind;
argv += optind;
if(argc != 0 && argc != 1)
usage();
if(argc == 1)
f = argv[0];
else f = CONFIGFILE;
checkconf(f);
checklock_stop();
return 0;
}
+461
View File
@@ -0,0 +1,461 @@
/*
* checkconf/unbound-host.c - replacement for host that supports validation.
*
* Copyright (c) 2007, 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 file performs functionality like 'host', and also supports validation.
* It uses the libunbound library.
*/
#include "config.h"
#include "libunbound/unbound.h"
#include <ldns/ldns.h>
/** verbosity for unbound-host app */
static int verb = 0;
/** Give unbound-host usage, and exit (1). */
static void
usage()
{
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");
printf(" Use the -v option to see DNSSEC security information.\n");
printf(" -t type what type to look for.\n");
printf(" -c class what class to look for, if not class IN.\n");
printf(" -y 'keystring' specify trust anchor, DS or DNSKEY, like\n");
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");
printf("Version %s\n", PACKAGE_VERSION);
printf("BSD licensed, see LICENSE in source package for details.\n");
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
exit(1);
}
/** determine if str is ip4 and put into reverse lookup format */
static int
isip4(const char* nm, char** res)
{
struct in_addr addr;
/* ddd.ddd.ddd.ddd.in-addr.arpa. is less than 32 */
char buf[32];
if(inet_pton(AF_INET, nm, &addr) <= 0) {
return 0;
}
snprintf(buf, sizeof(buf), "%u.%u.%u.%u.in-addr.arpa",
(unsigned)((uint8_t*)&addr)[3], (unsigned)((uint8_t*)&addr)[2],
(unsigned)((uint8_t*)&addr)[1], (unsigned)((uint8_t*)&addr)[0]);
*res = strdup(buf);
return 1;
}
/** determine if str is ip6 and put into reverse lookup format */
static int
isip6(const char* nm, char** res)
{
struct in6_addr addr;
/* [nibble.]{32}.ip6.arpa. is less than 128 */
char* hex = "0123456789abcdef";
char buf[128];
char *p;
int i;
if(inet_pton(AF_INET6, nm, &addr) <= 0) {
return 0;
}
p = buf;
for(i=15; i>=0; i--) {
uint8_t b = ((uint8_t*)&addr)[i];
*p++ = hex[ (b&0x0f) ];
*p++ = '.';
*p++ = hex[ (b&0xf0) >> 4 ];
*p++ = '.';
}
snprintf(buf+16*4, sizeof(buf)-16*4, "ip6.arpa");
*res = strdup(buf);
if(!*res) {
fprintf(stderr, "error: out of memory\n");
exit(1);
}
return 1;
}
/** massage input name */
static char*
massage_qname(const char* nm, int* reverse)
{
/* recognise IP4 and IP6, create reverse addresses if needed */
char* res;
if(isip4(nm, &res)) {
*reverse = 1;
} else if(isip6(nm, &res)) {
*reverse = 1;
} else {
res = strdup(nm);
}
if(!res) {
fprintf(stderr, "error: out of memory\n");
exit(1);
}
return res;
}
/** massage input type */
static int
massage_type(const char* t, int reverse, int* multi)
{
if(t) {
int r = ldns_get_rr_type_by_name(t);
if(r == 0 && strcasecmp(t, "TYPE0") != 0 &&
strcmp(t, "") != 0) {
fprintf(stderr, "error unknown type %s\n", t);
exit(1);
}
return r;
}
if(!t && reverse)
return LDNS_RR_TYPE_PTR;
*multi = 1;
return LDNS_RR_TYPE_A;
}
/** massage input class */
static int
massage_class(const char* c)
{
if(c) {
int r = ldns_get_rr_class_by_name(c);
if(r == 0 && strcasecmp(c, "CLASS0") != 0 &&
strcmp(c, "") != 0) {
fprintf(stderr, "error unknown class %s\n", c);
exit(1);
}
return r;
}
return LDNS_RR_CLASS_IN;
}
/** nice security status string */
static const char*
secure_str(struct ub_result* result)
{
if(result->secure) return "(secure)";
if(result->bogus) return "(BOGUS (security failure))";
return "(insecure)";
}
/** nice string for type */
static void
pretty_type(char* s, size_t len, int t)
{
const ldns_rr_descriptor *d = ldns_rr_descript((uint16_t)t);
if(d) {
snprintf(s, len, "%s", d->_name);
} else {
snprintf(s, len, "TYPE%d", t);
}
}
/** nice string for class */
static void
pretty_class(char* s, size_t len, int c)
{
ldns_lookup_table *cl = ldns_lookup_by_id(ldns_rr_classes, c);
if(cl) {
snprintf(s, len, "%s", cl->name);
} else {
snprintf(s, len, "CLASS%d", c);
}
}
/** nice string for rcode */
static void
pretty_rcode(char* s, size_t len, int r)
{
ldns_lookup_table *rcode = ldns_lookup_by_id(ldns_rcodes, r);
if(rcode) {
snprintf(s, len, "%s", rcode->name);
} else {
snprintf(s, len, "RCODE%d", r);
}
}
/** convert and print rdata */
static void
print_rd(int t, char* data, size_t len)
{
size_t i, pos = 0;
uint8_t* rd = (uint8_t*)malloc(len+2);
ldns_rr* rr = ldns_rr_new();
ldns_status status;
if(!rd || !rr) {
fprintf(stderr, "out of memory");
exit(1);
}
ldns_rr_set_type(rr, t);
ldns_write_uint16(rd, len);
memmove(rd+2, data, len);
ldns_rr_set_owner(rr, NULL);
status = ldns_wire2rdf(rr, rd, len+2, &pos);
if(status != LDNS_STATUS_OK) {
free(rd);
printf("error_printing_data");
}
for(i=0; i<ldns_rr_rd_count(rr); i++) {
printf(" ");
ldns_rdf_print(stdout, ldns_rr_rdf(rr, i));
}
ldns_rr_free(rr);
free(rd);
}
/** pretty line of RR data for results */
static void
pretty_rdata(char* q, char* cstr, char* tstr, int t, const char* sec,
char* data, size_t len)
{
printf("%s", q);
if(strcmp(cstr, "IN") != 0)
printf(" in class %s", cstr);
if(t == LDNS_RR_TYPE_A)
printf(" has address");
else if(t == LDNS_RR_TYPE_AAAA)
printf(" has IPv6 address");
else if(t == LDNS_RR_TYPE_MX)
printf(" mail is handled by");
else if(t == LDNS_RR_TYPE_PTR)
printf(" domain name pointer");
else printf(" has %s record", tstr);
print_rd(t, data, len);
if(verb > 0)
printf(" %s", sec);
printf("\n");
}
/** pretty line of output for results */
static void
pretty_output(char* q, int t, int c, struct ub_result* result, int docname)
{
int i;
const char *secstatus = secure_str(result);
char tstr[16];
char cstr[16];
char rcodestr[16];
pretty_type(tstr, 16, t);
pretty_class(cstr, 16, c);
pretty_rcode(rcodestr, 16, result->rcode);
if(!result->havedata && result->rcode) {
printf("Host %s not found: %d(%s).",
q, result->rcode, rcodestr);
if(verb > 0)
printf(" %s", secstatus);
printf("\n");
return;
}
if(docname && result->canonname &&
result->canonname != result->qname) {
printf("%s is an alias for %s", result->qname,
result->canonname);
if(verb > 0)
printf(" %s", secstatus);
printf("\n");
}
/* remove trailing . from long canonnames for nicer output */
if(result->canonname && strlen(result->canonname) > 1 &&
result->canonname[strlen(result->canonname)-1] == '.')
result->canonname[strlen(result->canonname)-1] = 0;
if(!result->havedata) {
if(verb > 0) {
printf("%s", result->canonname?result->canonname:q);
if(strcmp(cstr, "IN") != 0)
printf(" in class %s", cstr);
if(t == LDNS_RR_TYPE_A)
printf(" has no address");
else if(t == LDNS_RR_TYPE_AAAA)
printf(" has no IPv6 address");
else if(t == LDNS_RR_TYPE_PTR)
printf(" has no domain name ptr");
else if(t == LDNS_RR_TYPE_MX)
printf(" has no mail handler record");
else printf(" has no %s record", tstr);
printf(" %s\n", secstatus);
}
/* else: emptiness to indicate no data */
return;
}
i=0;
while(result->data[i])
{
pretty_rdata(
result->canonname?result->canonname:q,
cstr, tstr, t, secstatus, result->data[i],
(size_t)result->len[i]);
i++;
}
}
/** perform a lookup and printout return if domain existed */
static int
dnslook(struct ub_ctx* ctx, char* q, int t, int c, int docname)
{
int ret;
struct ub_result* result;
ret = ub_resolve(ctx, q, t, c, &result);
if(ret != 0) {
fprintf(stderr, "resolve error: %s\n", ub_strerror(ret));
exit(1);
}
pretty_output(q, t, c, result, docname);
ret = result->nxdomain;
ub_resolve_free(result);
return ret;
}
/** perform host lookup */
static void
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 */
int reverse = 0; /* we are doing a reverse lookup */
char* realq = massage_qname(nm, &reverse);
int t = massage_type(qt, reverse, &multi);
int c = massage_class(qc);
/* perform the query */
if(multi) {
if(!dnslook(ctx, realq, LDNS_RR_TYPE_A, c, 1)) {
/* domain exists, lookup more */
(void)dnslook(ctx, realq, LDNS_RR_TYPE_AAAA, c, 0);
(void)dnslook(ctx, realq, LDNS_RR_TYPE_MX, c, 0);
}
} else {
(void)dnslook(ctx, realq, t, c, 1);
}
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. */
extern char* optarg;
/** Main routine for checkconf */
int main(int argc, char* argv[])
{
int c;
char* qclass = NULL;
char* qtype = NULL;
struct ub_ctx* ctx = NULL;
int debuglevel = 0;
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: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 */
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;
break;
case 'v':
verb++;
break;
case 'y':
check_ub_res(ub_ctx_add_ta(ctx, optarg));
break;
case 'f':
check_ub_res(ub_ctx_add_ta_file(ctx, optarg));
break;
case 'F':
check_ub_res(ub_ctx_trustedkeys(ctx, optarg));
break;
case '?':
case 'h':
default:
usage();
}
}
argc -= optind;
argv += optind;
if(argc != 1)
usage();
lookup(ctx, argv[0], qtype, qclass);
return 0;
}
+187
View File
@@ -0,0 +1,187 @@
/*
* checkconf/worker_cb.c - fake callback routines to make fptr_wlist work
*
* Copyright (c) 2007, 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 file contains fake callback functions, so that the symbols exist
* and the fptr_wlist continues to work even if the daemon/worker is not
* linked into the resulting program.
*/
#include "config.h"
#include "util/log.h"
struct comm_reply;
struct comm_point;
struct module_qstate;
int worker_handle_control_cmd(struct comm_point* ATTR_UNUSED(c),
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
struct comm_reply* ATTR_UNUSED(reply_info))
{
log_assert(0);
return 0;
}
int worker_handle_request(struct comm_point* ATTR_UNUSED(c),
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
struct comm_reply* ATTR_UNUSED(repinfo))
{
log_assert(0);
return 0;
}
int worker_handle_reply(struct comm_point* ATTR_UNUSED(c),
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
struct comm_reply* ATTR_UNUSED(reply_info))
{
log_assert(0);
return 0;
}
int worker_handle_service_reply(struct comm_point* ATTR_UNUSED(c),
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
struct comm_reply* ATTR_UNUSED(reply_info))
{
log_assert(0);
return 0;
}
void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg))
{
log_assert(0);
}
int worker_send_packet(ldns_buffer* ATTR_UNUSED(pkt),
struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(timeout),
struct module_qstate* ATTR_UNUSED(q), int ATTR_UNUSED(use_tcp))
{
log_assert(0);
return 0;
}
struct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname),
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), struct module_qstate* ATTR_UNUSED(q))
{
log_assert(0);
return 0;
}
void
worker_alloc_cleanup(void* ATTR_UNUSED(arg))
{
log_assert(0);
}
int
acl_list_cmp(const void* ATTR_UNUSED(k1), const void* ATTR_UNUSED(k2))
{
log_assert(0);
return 0;
}
int libworker_send_packet(ldns_buffer* ATTR_UNUSED(pkt),
struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(timeout),
struct module_qstate* ATTR_UNUSED(q), int ATTR_UNUSED(use_tcp))
{
log_assert(0);
return 0;
}
struct outbound_entry* libworker_send_query(uint8_t* ATTR_UNUSED(qname),
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), struct module_qstate* ATTR_UNUSED(q))
{
log_assert(0);
return 0;
}
int libworker_handle_reply(struct comm_point* ATTR_UNUSED(c),
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
struct comm_reply* ATTR_UNUSED(reply_info))
{
log_assert(0);
return 0;
}
int libworker_handle_service_reply(struct comm_point* ATTR_UNUSED(c),
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
struct comm_reply* ATTR_UNUSED(reply_info))
{
log_assert(0);
return 0;
}
int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
{
log_assert(0);
return 0;
}
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);
}
+485
View File
@@ -0,0 +1,485 @@
/*
* testcode/asynclook.c - debug program perform async libunbound 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 shows the results from several background lookups,
* while printing time in the foreground.
*/
#include "config.h"
#include "libunbound/unbound.h"
#include "util/locks.h"
#include "util/log.h"
/**
* result list for the lookups
*/
struct lookinfo {
/** name to look up */
char* name;
/** tracking number that can be used to cancel the query */
int async_id;
/** error code from libunbound */
int err;
/** result from lookup */
struct ub_result* result;
};
/** global variable to see how many queries we have left */
static int num_wait = 0;
/** usage information for asynclook */
void usage(char* argv[])
{
printf("usage: %s [options] name ...\n", argv[0]);
printf("names are looked up at the same time, asynchronously.\n");
printf(" -b : use blocking requests\n");
printf(" -c : cancel the requests\n");
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");
exit(1);
}
/** print result from lookup nicely */
static void
print_result(struct lookinfo* info)
{
char buf[100];
if(info->err) /* error (from libunbound) */
printf("%s: error %s\n", info->name,
ub_strerror(info->err));
else if(!info->result)
printf("%s: cancelled\n", info->name);
else if(info->result->havedata)
printf("%s: %s\n", info->name,
inet_ntop(AF_INET, info->result->data[0],
buf, (socklen_t)sizeof(buf)));
else {
/* there is no data, why that? */
if(info->result->rcode == 0 /*noerror*/ ||
info->result->nxdomain)
printf("%s: no data %s\n", info->name,
info->result->nxdomain?"(no such host)":
"(no IP4 address)");
else /* some error (from the server) */
printf("%s: DNS error %d\n", info->name,
info->result->rcode);
}
}
/** this is a function of type ub_callback_t */
static void
lookup_is_done(void* mydata, int err, struct ub_result* result)
{
/* cast mydata back to the correct type */
struct lookinfo* info = (struct lookinfo*)mydata;
fprintf(stderr, "name %s resolved\n", info->name);
info->err = err;
info->result = result;
/* one less to wait for */
num_wait--;
}
/** check error, if bad, exit with error message */
static void
checkerr(const char* desc, int err)
{
if(err != 0) {
printf("%s error: %s\n", desc, ub_strerror(err));
exit(1);
}
}
#ifdef THREADS_DISABLED
/** only one process can communicate with async worker */
#define NUMTHR 1
#else /* have threads */
/** number of threads to make in extended test */
#define NUMTHR 10
#endif
/** struct for extended thread info */
struct ext_thr_info {
/** thread num for debug */
int thread_num;
/** thread id */
ub_thread_t tid;
/** context */
struct ub_ctx* ctx;
/** size of array to query */
int argc;
/** array of names to query */
char** argv;
/** number of queries to do */
int numq;
};
/** if true, we are testing against 'localhost' and extra checking is done */
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_result* result)
{
checkerr(desc, err);
if(result == NULL) {
printf("%s: error result is NULL.\n", desc);
exit(1);
}
if(q_is_localhost) {
if(strcmp(result->qname, "localhost") != 0) {
printf("%s: error result has wrong qname.\n", desc);
exit(1);
}
if(result->qtype != LDNS_RR_TYPE_A) {
printf("%s: error result has wrong qtype.\n", desc);
exit(1);
}
if(result->qclass != LDNS_RR_CLASS_IN) {
printf("%s: error result has wrong qclass.\n", desc);
exit(1);
}
if(result->data == NULL) {
printf("%s: error result->data is NULL.\n", desc);
exit(1);
}
if(result->len == NULL) {
printf("%s: error result->len is NULL.\n", desc);
exit(1);
}
if(result->rcode != 0) {
printf("%s: error result->rcode is set.\n", desc);
exit(1);
}
if(result->havedata == 0) {
printf("%s: error result->havedata is unset.\n", desc);
exit(1);
}
if(result->nxdomain != 0) {
printf("%s: error result->nxdomain is set.\n", desc);
exit(1);
}
if(result->secure || result->bogus) {
printf("%s: error result->secure or bogus is set.\n",
desc);
exit(1);
}
if(result->data[0] == NULL) {
printf("%s: error result->data[0] is NULL.\n", desc);
exit(1);
}
if(result->len[0] != 4) {
printf("%s: error result->len[0] is wrong.\n", desc);
exit(1);
}
if(result->len[1] != 0 || result->data[1] != NULL) {
printf("%s: error result->data[1] or len[1] is "
"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_callback_t */
static void
ext_callback(void* mydata, int err, struct ub_result* result)
{
int* my_id = (int*)mydata;
int doprint = 0;
if(my_id) {
/* I have an id, make sure we are not cancelled */
if(*my_id == 0) {
printf("error: query returned, but was cancelled\n");
abort();
exit(1);
}
if(doprint)
printf("cb %d: ", *my_id);
}
ext_check_result("ext_callback", err, result);
log_assert(result);
if(doprint) {
struct lookinfo pi;
pi.name = result?result->qname:"noname";
pi.result = result;
pi.err = 0;
print_result(&pi);
}
ub_resolve_free(result);
}
/** extended thread worker */
static void*
ext_thread(void* arg)
{
struct ext_thr_info* inf = (struct ext_thr_info*)arg;
int i, r;
struct ub_result* result;
int* async_ids = NULL;
log_thread_set(&inf->thread_num);
if(inf->thread_num > NUMTHR*2/3) {
async_ids = (int*)calloc((size_t)inf->numq, sizeof(int));
if(!async_ids) {
printf("out of memory\n");
exit(1);
}
}
for(i=0; i<inf->numq; i++) {
if(async_ids) {
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_resolve_async", r);
if(i > 100) {
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_resolve_async(inf->ctx,
inf->argv[i%inf->argc], LDNS_RR_TYPE_A,
LDNS_RR_CLASS_IN, NULL, ext_callback, NULL);
checkerr("ub_resolve_async", r);
} else {
/* blocking */
r = ub_resolve(inf->ctx, inf->argv[i%inf->argc],
LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, &result);
ext_check_result("ub_resolve", r, result);
ub_resolve_free(result);
}
}
if(inf->thread_num > NUMTHR/2) {
r = ub_wait(inf->ctx);
checkerr("ub_ctx_wait", r);
}
free(async_ids);
return NULL;
}
/** perform extended threaded test */
static int
ext_test(struct ub_ctx* ctx, int argc, char** argv)
{
struct ext_thr_info inf[NUMTHR];
int i;
if(argc == 1 && strcmp(argv[0], "localhost") == 0)
q_is_localhost = 1;
printf("extended test start (%d threads)\n", NUMTHR);
for(i=0; i<NUMTHR; i++) {
/* 0 = this, 1 = library bg worker */
inf[i].thread_num = i+2;
inf[i].ctx = ctx;
inf[i].argc = argc;
inf[i].argv = argv;
inf[i].numq = 1000;
ub_thread_create(&inf[i].tid, ext_thread, &inf[i]);
}
/* the work happens here */
for(i=0; i<NUMTHR; i++) {
ub_thread_join(inf[i].tid);
}
printf("extended test end\n");
ub_ctx_delete(ctx);
checklock_stop();
return 0;
}
/** 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 asynclook */
int main(int argc, char** argv)
{
int c;
struct ub_ctx* ctx;
struct lookinfo* lookups;
int i, r, cancel=0, blocking=0, ext=0;
/* lock debug start (if any) */
checklock_start();
/* create context */
ctx = ub_ctx_create();
if(!ctx) {
printf("could not create context, %s\n", strerror(errno));
return 1;
}
/* command line options */
if(argc == 1) {
usage(argv);
}
while( (c=getopt(argc, argv, "bcdf:hH:r:tx")) != -1) {
switch(c) {
case 'd':
r = ub_ctx_debuglevel(ctx, 3);
checkerr("ub_ctx_debuglevel", r);
break;
case 't':
r = ub_ctx_async(ctx, 1);
checkerr("ub_ctx_async", r);
break;
case 'c':
cancel = 1;
break;
case 'b':
blocking = 1;
break;
case 'r':
r = ub_ctx_resolvconf(ctx, optarg);
if(r != 0) {
printf("ub_ctx_resolvconf "
"error: %s : %s\n",
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_ctx_set_fwd(ctx, optarg);
checkerr("ub_ctx_set_fwd", r);
break;
case 'x':
ext = 1;
break;
case 'h':
case '?':
default:
usage(argv);
}
}
argc -= optind;
argv += optind;
if(ext)
return ext_test(ctx, argc, argv);
/* allocate array for results. */
lookups = (struct lookinfo*)calloc((size_t)argc,
sizeof(struct lookinfo));
if(!lookups) {
printf("out of memory\n");
return 1;
}
/* perform asyncronous calls */
num_wait = argc;
for(i=0; i<argc; i++) {
lookups[i].name = argv[i];
if(blocking) {
fprintf(stderr, "lookup %s\n", argv[i]);
r = ub_resolve(ctx, argv[i], LDNS_RR_TYPE_A,
LDNS_RR_CLASS_IN, &lookups[i].result);
checkerr("ub_resolve", r);
} else {
fprintf(stderr, "start async lookup %s\n", argv[i]);
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_resolve_async", r);
}
}
if(blocking)
num_wait = 0;
else if(cancel) {
for(i=0; i<argc; i++) {
fprintf(stderr, "cancel %s\n", argv[i]);
r = ub_cancel(ctx, lookups[i].async_id);
checkerr("ub_cancel", r);
}
num_wait = 0;
}
/* wait while the hostnames are looked up. Do something useful here */
if(num_wait > 0)
for(i=0; i<1000; i++) {
usleep(100000);
fprintf(stderr, "%g seconds passed\n", 0.1*(double)i);
r = ub_process(ctx);
checkerr("ub_process", r);
if(num_wait == 0)
break;
}
if(i>=999) {
printf("timed out\n");
return 0;
}
printf("lookup complete\n");
/* print lookup results */
for(i=0; i<argc; i++) {
print_result(&lookups[i]);
ub_resolve_free(lookups[i].result);
}
ub_ctx_delete(ctx);
free(lookups);
checklock_stop();
return 0;
}
+22 -3
View File
@@ -63,7 +63,7 @@ static ub_thread_key_t thr_debug_key;
/** the list of threads, so all threads can be examined. NULL if unused. */
static struct thr_check* thread_infos[THRDEBUG_MAX_THREADS];
/** do we check locking order */
int check_locking_order = 0;
int check_locking_order = 1;
/** the pid of this runset, reasonably unique. */
static pid_t check_lock_pid;
@@ -205,6 +205,23 @@ prot_store(struct checked_lock* lock)
}
}
/** get memory held by lock */
size_t
lock_get_mem(void* pp)
{
size_t s;
struct checked_lock* lock = *(struct checked_lock**)pp;
struct protected_area* p;
s = sizeof(struct checked_lock);
acquire_locklock(lock, __func__, __FILE__, __LINE__);
for(p = lock->prot; p; p = p->next) {
s += sizeof(struct protected_area);
s += p->size;
}
LOCKRET(pthread_mutex_unlock(&lock->lock));
return s;
}
/** write lock trace info to file, while you hold those locks */
static void
ordercheck_locklock(struct thr_check* thr, struct checked_lock* lock)
@@ -340,7 +357,7 @@ checklock_destroy(enum check_lock_type type, struct checked_lock** lock,
e->create_func, e->create_file, e->create_line,
(unsigned int)e->contention_count,
(unsigned int)e->history_count,
100*e->contention_count/e->history_count);
(int)(100*e->contention_count/e->history_count));
}
/* delete it */
@@ -641,7 +658,9 @@ static void* checklock_main(void* arg)
/* Hack to get same numbers as in log file */
thr->num = *(int*)(thr->arg);
log_assert(thr->num < THRDEBUG_MAX_THREADS);
log_assert(thread_infos[thr->num] == NULL);
/* as an aside, due to this, won't work for libunbound bg thread */
if(thread_infos[thr->num] != NULL)
log_warn("thread warning, thr->num %d not NULL", thr->num);
thread_infos[thr->num] = thr;
LOCKRET(pthread_setspecific(thr_debug_key, thr));
if(check_locking_order)
+7 -1
View File
@@ -196,6 +196,13 @@ void lock_protect(void* lock, void* area, size_t size);
*/
void lock_unprotect(void* lock, void* area);
/**
* Get memory associated with a checked lock
* @param lock: the checked lock, any type. (struct checked_lock**).
* @return: in bytes, including protected areas.
*/
size_t lock_get_mem(void* lock);
/**
* Initialise checklock. Sets up internal debug structures.
*/
@@ -333,5 +340,4 @@ typedef pthread_key_t ub_thread_key_t;
#define ub_thread_key_get(key) pthread_getspecific(key)
#endif /* USE_THREAD_DEBUG */
#endif /* TESTCODE_CHECK_LOCKS_H */
+1155
View File
File diff suppressed because it is too large Load Diff
+61 -1
View File
@@ -2,8 +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 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
@@ -16,10 +39,47 @@ 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;
fi
fi
if echo $NEED_XXD | grep $test >/dev/null; then
if test ! -x "`which xxd`"; then
SKIP=1;
fi
fi
if echo $NEED_NC | grep $test >/dev/null; then
if test ! -x "`which nc`"; then
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
tpkg -a ../.. exe $test
sh ../testcode/mini_tpkg.sh -a ../.. exe $test
else
echo "skip $test"
fi
done
sh ../testcode/mini_tpkg.sh report
cat .perfstats.txt
+177 -33
View File
@@ -56,6 +56,7 @@
#include "testcode/replay.h"
#include "testcode/ldns-testpkts.h"
#include "util/log.h"
#include <signal.h>
/** Global variable: the scenario. Saved here for when event_init is done. */
static struct replay_scenario* saved_scenario = NULL;
@@ -178,7 +179,8 @@ pending_find_match(struct replay_runtime* runtime, struct entry** entry,
"with entry line %d", timenow,
p->start_step, p->end_step, (*entry)->lineno);
if(p->addrlen != 0)
log_addr("matched ip", &p->addr, p->addrlen);
log_addr(0, "matched ip", &p->addr, p->addrlen);
log_pkt("matched pkt: ", (*entry)->reply_list->reply);
return 1;
}
p = p->next_range;
@@ -353,9 +355,12 @@ fake_front_query(struct replay_runtime* runtime, struct replay_moment *todo)
repinfo.c->fd = -1;
repinfo.c->ev = (struct internal_event*)runtime;
repinfo.c->buffer = ldns_buffer_new(runtime->bufsize);
repinfo.c->type = comm_udp;
if(todo->match->match_transport == transport_tcp)
repinfo.c->type = comm_tcp;
else repinfo.c->type = comm_udp;
fill_buffer_with_reply(repinfo.c->buffer, todo->match, NULL);
log_info("testbound: incoming QUERY");
log_pkt("query pkt", todo->match->reply_list->reply);
/* call the callback for incoming queries */
if((*runtime->callback_query)(repinfo.c, runtime->cb_arg,
NETEVENT_NOERROR, &repinfo)) {
@@ -376,6 +381,9 @@ fake_pending_callback(struct replay_runtime* runtime,
struct fake_pending* p = runtime->pending_list;
struct comm_reply repinfo;
struct comm_point c;
void* cb_arg = p->cb_arg;
comm_point_callback_t* cb = p->callback;
memset(&c, 0, sizeof(c));
if(!p) fatal_exit("No pending queries.");
log_assert(todo->qname == NULL); /* or find that one */
@@ -389,12 +397,13 @@ fake_pending_callback(struct replay_runtime* runtime,
repinfo.c = &c;
repinfo.addrlen = p->addrlen;
memcpy(&repinfo.addr, &p->addr, p->addrlen);
if((*p->callback)(&c, p->cb_arg, error, &repinfo)) {
if(!p->serviced)
pending_list_delete(runtime, p);
if((*cb)(&c, cb_arg, error, &repinfo)) {
fatal_exit("unexpected: pending callback returned 1");
}
/* delete the pending item. */
ldns_buffer_free(c.buffer);
pending_list_delete(runtime, p);
}
/**
@@ -514,13 +523,15 @@ run_scenario(struct replay_runtime* runtime)
fatal_exit("testbound: there are unmatched answers.");
}
log_info("testbound: exiting fake runloop.");
runtime->exit_cleanly = 1;
}
/*********** Dummy routines ***********/
struct listen_dnsport*
listen_create(struct comm_base* base, struct listen_port* ATTR_UNUSED(ports),
size_t bufsize, comm_point_callback_t* cb, void* cb_arg)
size_t bufsize, int ATTR_UNUSED(tcp_accept_count),
comm_point_callback_t* cb, void* cb_arg)
{
struct replay_runtime* runtime = (struct replay_runtime*)base;
struct listen_dnsport* l= calloc(1, sizeof(struct listen_dnsport));
@@ -581,18 +592,32 @@ 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)
{
struct replay_runtime* runtime = (struct replay_runtime*)b;
run_scenario(runtime);
if(runtime->sig_cb)
(*runtime->sig_cb)(SIGTERM, runtime->sig_cb_arg);
else exit(0); /* OK exit when LIBEVENT_SIGNAL_PROBLEM exists */
}
void
comm_base_exit(struct comm_base* ATTR_UNUSED(b))
comm_base_exit(struct comm_base* b)
{
/* some sort of failure */
fatal_exit("testbound: comm_base_exit was called.");
struct replay_runtime* runtime = (struct replay_runtime*)b;
if(!runtime->exit_cleanly) {
/* some sort of failure */
fatal_exit("testbound: comm_base_exit was called.");
}
}
struct comm_signal*
@@ -645,15 +670,6 @@ comm_point_send_reply(struct comm_reply* repinfo)
log_pkt("reply pkt: ", ans->pkt);
}
void
comm_point_send_reply_iov(struct comm_reply* repinfo, struct iovec* iov,
size_t iovlen)
{
/* skip tcp len at [0]. */
write_iov_buffer(repinfo->c->buffer, iov+1, iovlen-1);
comm_point_send_reply(repinfo);
}
void
comm_point_drop_reply(struct comm_reply* repinfo)
{
@@ -668,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));
@@ -692,18 +710,10 @@ outside_network_delete(struct outside_network* outnet)
free(outnet);
}
void
outside_network_set_secondary_buffer(struct outside_network*
ATTR_UNUSED(outnet), ldns_buffer* ATTR_UNUSED(buf))
{
/* nothing to do */
}
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,
@@ -755,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,
@@ -818,6 +827,11 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
ldns_status status;
(void)arg_compare;
log_assert(pend);
log_nametypeclass(VERB_OPS, "pending serviced query",
qname, qtype, qclass);
verbose(VERB_OPS, "pending serviced query flags%s%s%s%s",
(flags&BIT_RD)?" RD":"", (flags&BIT_CD)?" CD":"",
(flags&~(BIT_RD|BIT_CD))?" MORE":"", (dnssec)?" DO":"");
/* create packet with EDNS */
pend->buffer = ldns_buffer_new(512);
@@ -848,7 +862,7 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
pend->addrlen = addrlen;
pend->callback = callback;
pend->cb_arg = callback_arg;
pend->timeout = UDP_QUERY_TIMEOUT;
pend->timeout = UDP_AUTH_QUERY_TIMEOUT;
pend->transport = transport_udp; /* pretend UDP */
pend->pkt = NULL;
pend->runtime = runtime;
@@ -859,7 +873,7 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
ldns_get_errorstr_by_id(status));
fatal_exit("internal error");
}
log_pkt("pending serviced query: ", pend->pkt);
/*log_pkt("pending serviced query: ", pend->pkt);*/
/* see if it matches the current moment */
if(runtime->now && runtime->now->evt_type == repevt_back_query &&
@@ -952,4 +966,134 @@ size_t comm_point_get_mem(struct comm_point* ATTR_UNUSED(c))
return 0;
}
size_t serviced_get_mem(struct serviced_query* ATTR_UNUSED(c))
{
return 0;
}
/* fake for fptr wlist */
int outnet_udp_cb(struct comm_point* ATTR_UNUSED(c),
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
struct comm_reply *ATTR_UNUSED(reply_info))
{
log_assert(0);
return 0;
}
int outnet_tcp_cb(struct comm_point* ATTR_UNUSED(c),
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
struct comm_reply *ATTR_UNUSED(reply_info))
{
log_assert(0);
return 0;
}
void pending_udp_timer_cb(void *ATTR_UNUSED(arg))
{
log_assert(0);
}
void outnet_tcptimer(void* ATTR_UNUSED(arg))
{
log_assert(0);
}
void comm_point_udp_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(event),
void* ATTR_UNUSED(arg))
{
log_assert(0);
}
void comm_point_udp_ancil_callback(int ATTR_UNUSED(fd),
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
{
log_assert(0);
}
void comm_point_tcp_accept_callback(int ATTR_UNUSED(fd),
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
{
log_assert(0);
}
void comm_point_tcp_handle_callback(int ATTR_UNUSED(fd),
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
{
log_assert(0);
}
void comm_timer_callback(int ATTR_UNUSED(fd),
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
{
log_assert(0);
}
void comm_signal_callback(int ATTR_UNUSED(fd),
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
{
log_assert(0);
}
void comm_point_local_handle_callback(int ATTR_UNUSED(fd),
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
{
log_assert(0);
}
void comm_point_raw_handle_callback(int ATTR_UNUSED(fd),
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
{
log_assert(0);
}
int serviced_udp_callback(struct comm_point* ATTR_UNUSED(c),
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
struct comm_reply* ATTR_UNUSED(reply_info))
{
log_assert(0);
return 0;
}
int serviced_tcp_callback(struct comm_point* ATTR_UNUSED(c),
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
struct comm_reply* ATTR_UNUSED(reply_info))
{
log_assert(0);
return 0;
}
int pending_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
{
log_assert(0);
return 0;
}
int serviced_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
{
log_assert(0);
return 0;
}
/* no statistics timers in testbound */
struct comm_timer* comm_timer_create(struct comm_base* ATTR_UNUSED(base),
void (*cb)(void*), void* ATTR_UNUSED(cb_arg))
{
(void)cb;
return malloc(1);
}
void comm_timer_disable(struct comm_timer* ATTR_UNUSED(timer))
{
}
void comm_timer_set(struct comm_timer* ATTR_UNUSED(timer),
struct timeval* ATTR_UNUSED(tv))
{
}
void comm_timer_delete(struct comm_timer* timer)
{
free(timer);
}
/*********** End of Dummy routines ***********/
+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;
}

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