From fc040645eb491d80f33befae3b0e3ca67e9a1053 Mon Sep 17 00:00:00 2001 From: Abhishek Shah Date: Thu, 12 May 2016 14:58:55 -0700 Subject: [PATCH] vendor-ed skydns --- Godeps/.license_file_state | 53 +- Godeps/Godeps.json | 25 + Godeps/LICENSES | 704 ++++++++++++++ .../coreos/go-systemd/activation/files.go | 52 + .../coreos/go-systemd/activation/listeners.go | 62 ++ .../go-systemd/activation/packetconns.go | 37 + .../skynetservices/skydns/cache/cache.go | 167 ++++ .../skynetservices/skydns/cache/hit.go | 31 + .../skynetservices/skydns/metrics/metrics.go | 186 ++++ .../skynetservices/skydns/server/backend.go | 46 + .../skynetservices/skydns/server/config.go | 157 ++++ .../skynetservices/skydns/server/dnssec.go | 177 ++++ .../skynetservices/skydns/server/doc.go | 8 + .../skynetservices/skydns/server/exchange.go | 34 + .../skydns/server/forwarding.go | 125 +++ .../skynetservices/skydns/server/log.go | 17 + .../skynetservices/skydns/server/msg.go | 54 ++ .../skynetservices/skydns/server/nsec3.go | 155 +++ .../skynetservices/skydns/server/server.go | 888 ++++++++++++++++++ .../skynetservices/skydns/server/stub.go | 124 +++ .../skydns/singleflight/singleflight.go | 64 ++ 21 files changed, 3129 insertions(+), 37 deletions(-) create mode 100644 vendor/github.com/coreos/go-systemd/activation/files.go create mode 100644 vendor/github.com/coreos/go-systemd/activation/listeners.go create mode 100644 vendor/github.com/coreos/go-systemd/activation/packetconns.go create mode 100644 vendor/github.com/skynetservices/skydns/cache/cache.go create mode 100644 vendor/github.com/skynetservices/skydns/cache/hit.go create mode 100644 vendor/github.com/skynetservices/skydns/metrics/metrics.go create mode 100644 vendor/github.com/skynetservices/skydns/server/backend.go create mode 100644 vendor/github.com/skynetservices/skydns/server/config.go create mode 100644 vendor/github.com/skynetservices/skydns/server/dnssec.go create mode 100644 vendor/github.com/skynetservices/skydns/server/doc.go create mode 100644 vendor/github.com/skynetservices/skydns/server/exchange.go create mode 100644 vendor/github.com/skynetservices/skydns/server/forwarding.go create mode 100644 vendor/github.com/skynetservices/skydns/server/log.go create mode 100644 vendor/github.com/skynetservices/skydns/server/msg.go create mode 100644 vendor/github.com/skynetservices/skydns/server/nsec3.go create mode 100644 vendor/github.com/skynetservices/skydns/server/server.go create mode 100644 vendor/github.com/skynetservices/skydns/server/stub.go create mode 100644 vendor/github.com/skynetservices/skydns/singleflight/singleflight.go diff --git a/Godeps/.license_file_state b/Godeps/.license_file_state index 11500124d6c..ebc33d5e3f7 100644 --- a/Godeps/.license_file_state +++ b/Godeps/.license_file_state @@ -71,6 +71,10 @@ raw.githubusercontent.com/dgrijalva/jwt-go/master/NOTICE raw.githubusercontent.com/dgrijalva/jwt-go/master/NOTICE.txt raw.githubusercontent.com/dgrijalva/jwt-go/master/README raw.githubusercontent.com/dgrijalva/jwt-go/master/README.md +raw.githubusercontent.com/docker/distribution/master/NOTICE +raw.githubusercontent.com/docker/distribution/master/NOTICE.txt +raw.githubusercontent.com/docker/distribution/master/README +raw.githubusercontent.com/docker/distribution/master/README.md raw.githubusercontent.com/docker/engine-api/master/NOTICE raw.githubusercontent.com/docker/engine-api/master/NOTICE.txt raw.githubusercontent.com/docker/engine-api/master/README @@ -129,6 +133,10 @@ raw.githubusercontent.com/golang/groupcache/master/NOTICE raw.githubusercontent.com/golang/groupcache/master/NOTICE.txt raw.githubusercontent.com/golang/groupcache/master/README raw.githubusercontent.com/golang/groupcache/master/README.md +raw.githubusercontent.com/golang/mock/master/NOTICE +raw.githubusercontent.com/golang/mock/master/NOTICE.txt +raw.githubusercontent.com/golang/mock/master/README +raw.githubusercontent.com/golang/mock/master/README.md raw.githubusercontent.com/golang/protobuf/master/NOTICE raw.githubusercontent.com/golang/protobuf/master/NOTICE.txt raw.githubusercontent.com/golang/protobuf/master/README @@ -247,7 +255,6 @@ raw.githubusercontent.com/pmezard/go-difflib/master/NOTICE raw.githubusercontent.com/pmezard/go-difflib/master/NOTICE.txt raw.githubusercontent.com/pmezard/go-difflib/master/README raw.githubusercontent.com/pmezard/go-difflib/master/README.md -raw.githubusercontent.com/prometheus/common/master/LICENSE raw.githubusercontent.com/prometheus/common/master/LICENSE.code raw.githubusercontent.com/prometheus/common/master/LICENSE.txt raw.githubusercontent.com/prometheus/common/master/LICENSE.md @@ -315,6 +322,10 @@ raw.githubusercontent.com/vishvananda/netlink/master/NOTICE raw.githubusercontent.com/vishvananda/netlink/master/NOTICE.txt raw.githubusercontent.com/vishvananda/netlink/master/README raw.githubusercontent.com/vishvananda/netlink/master/README.md +raw.githubusercontent.com/vmware/govmomi/master/NOTICE +raw.githubusercontent.com/vmware/govmomi/master/NOTICE.txt +raw.githubusercontent.com/vmware/govmomi/master/README +raw.githubusercontent.com/vmware/govmomi/master/README.md raw.githubusercontent.com/xiang90/probing/master/NOTICE raw.githubusercontent.com/xiang90/probing/master/NOTICE.txt raw.githubusercontent.com/xiang90/probing/master/README @@ -367,6 +378,10 @@ gopkg.in/gcfg.v1/master/NOTICE gopkg.in/gcfg.v1/master/NOTICE.txt gopkg.in/gcfg.v1/master/README gopkg.in/gcfg.v1/master/README.md +gopkg.in/inf.v0/master/NOTICE +gopkg.in/inf.v0/master/NOTICE.txt +gopkg.in/inf.v0/master/README +gopkg.in/inf.v0/master/README.md gopkg.in/natefinch/master/NOTICE gopkg.in/natefinch/master/NOTICE.txt gopkg.in/natefinch/master/README @@ -379,39 +394,3 @@ k8s.io/heapster/master/NOTICE k8s.io/heapster/master/NOTICE.txt k8s.io/heapster/master/README k8s.io/heapster/master/README.md -speter.net/go/master/NOTICE -speter.net/go/master/NOTICE.txt -speter.net/go/master/README -speter.net/go/master/README.md -gopkg.in/gcfg.v1/master/NOTICE -gopkg.in/gcfg.v1/master/NOTICE.txt -gopkg.in/gcfg.v1/master/README -gopkg.in/gcfg.v1/master/README.md -raw.githubusercontent.com/docker/engine-api/master/NOTICE -raw.githubusercontent.com/docker/engine-api/master/NOTICE.txt -raw.githubusercontent.com/docker/engine-api/master/README -raw.githubusercontent.com/docker/engine-api/master/README.md -raw.githubusercontent.com/docker/go-connections/master/NOTICE -raw.githubusercontent.com/docker/go-connections/master/NOTICE.txt -raw.githubusercontent.com/docker/go-connections/master/README -raw.githubusercontent.com/docker/go-connections/master/README.md -raw.githubusercontent.com/Microsoft/go-winio/master/NOTICE -raw.githubusercontent.com/Microsoft/go-winio/master/NOTICE.txt -raw.githubusercontent.com/Microsoft/go-winio/master/README -raw.githubusercontent.com/Microsoft/go-winio/master/README.md -raw.githubusercontent.com/docker/distribution/master/NOTICE -raw.githubusercontent.com/docker/distribution/master/NOTICE.txt -raw.githubusercontent.com/docker/distribution/master/README -raw.githubusercontent.com/docker/distribution/master/README.md -raw.githubusercontent.com/golang/mock/master/NOTICE -raw.githubusercontent.com/golang/mock/master/NOTICE.txt -raw.githubusercontent.com/golang/mock/master/README -raw.githubusercontent.com/golang/mock/master/README.md -raw.githubusercontent.com/vmware/govmomi/master/NOTICE -raw.githubusercontent.com/vmware/govmomi/master/NOTICE.txt -raw.githubusercontent.com/vmware/govmomi/master/README -raw.githubusercontent.com/vmware/govmomi/master/README.md -gopkg.in/inf.v0/master/NOTICE -gopkg.in/inf.v0/master/NOTICE.txt -gopkg.in/inf.v0/master/README -gopkg.in/inf.v0/master/README.md diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 92511653a1d..5efefcfbc2f 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -507,6 +507,11 @@ "ImportPath": "github.com/coreos/go-semver/semver", "Rev": "d043ae190b3202550d026daf009359bb5d761672" }, + { + "ImportPath": "github.com/coreos/go-systemd/activation", + "Comment": "v4", + "Rev": "b4a58d95188dd092ae20072bac14cece0e67c388" + }, { "ImportPath": "github.com/coreos/go-systemd/daemon", "Comment": "v4", @@ -1777,11 +1782,31 @@ "ImportPath": "github.com/shurcooL/sanitized_anchor_name", "Rev": "9a8b7d4e8f347bfa230879db9d7d4e4d9e19f962" }, + { + "ImportPath": "github.com/skynetservices/skydns/cache", + "Comment": "2.5.3a-32-gf7b6fb7", + "Rev": "f7b6fb74bcfab300b4e7e0e27b1fe6c0ed555f78" + }, + { + "ImportPath": "github.com/skynetservices/skydns/metrics", + "Comment": "2.5.3a-32-gf7b6fb7", + "Rev": "f7b6fb74bcfab300b4e7e0e27b1fe6c0ed555f78" + }, { "ImportPath": "github.com/skynetservices/skydns/msg", "Comment": "2.5.3a-32-gf7b6fb7", "Rev": "f7b6fb74bcfab300b4e7e0e27b1fe6c0ed555f78" }, + { + "ImportPath": "github.com/skynetservices/skydns/server", + "Comment": "2.5.3a-32-gf7b6fb7", + "Rev": "f7b6fb74bcfab300b4e7e0e27b1fe6c0ed555f78" + }, + { + "ImportPath": "github.com/skynetservices/skydns/singleflight", + "Comment": "2.5.3a-32-gf7b6fb7", + "Rev": "f7b6fb74bcfab300b4e7e0e27b1fe6c0ed555f78" + }, { "ImportPath": "github.com/spf13/cobra", "Rev": "4c05eb1145f16d0e6bb4a3e1b6d769f4713cb41f" diff --git a/Godeps/LICENSES b/Godeps/LICENSES index 4a9be26cb77..9f8369c1f88 100644 --- a/Godeps/LICENSES +++ b/Godeps/LICENSES @@ -19925,6 +19925,202 @@ This product includes software developed at CoreOS, Inc. limitations under the License. +================================================================================ += vendor/github.com/coreos/go-systemd/activation licensed under: = + +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + ================================================================================ = vendor/github.com/coreos/go-systemd/daemon licensed under: = @@ -53806,6 +54002,208 @@ SoundCloud Ltd. (http://soundcloud.com/). ================================================================================ = vendor/github.com/prometheus/common/expfmt licensed under: = + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + Copyright 2015 The Prometheus Authors This product includes software developed at @@ -53814,6 +54212,208 @@ SoundCloud Ltd. (http://soundcloud.com/). ================================================================================ = vendor/github.com/prometheus/common/model licensed under: = + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + Copyright 2015 The Prometheus Authors This product includes software developed at @@ -59266,6 +59866,58 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +================================================================================ += vendor/github.com/skynetservices/skydns/cache licensed under: = + +The MIT License (MIT) + +Copyright (c) 2013 The SkyDNS Authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +================================================================================ += vendor/github.com/skynetservices/skydns/metrics licensed under: = + +The MIT License (MIT) + +Copyright (c) 2013 The SkyDNS Authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + ================================================================================ = vendor/github.com/skynetservices/skydns/msg licensed under: = @@ -59292,6 +59944,58 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +================================================================================ += vendor/github.com/skynetservices/skydns/server licensed under: = + +The MIT License (MIT) + +Copyright (c) 2013 The SkyDNS Authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +================================================================================ += vendor/github.com/skynetservices/skydns/singleflight licensed under: = + +The MIT License (MIT) + +Copyright (c) 2013 The SkyDNS Authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + ================================================================================ = vendor/github.com/spf13/cobra licensed under: = diff --git a/vendor/github.com/coreos/go-systemd/activation/files.go b/vendor/github.com/coreos/go-systemd/activation/files.go new file mode 100644 index 00000000000..c8e85fcd588 --- /dev/null +++ b/vendor/github.com/coreos/go-systemd/activation/files.go @@ -0,0 +1,52 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package activation implements primitives for systemd socket activation. +package activation + +import ( + "os" + "strconv" + "syscall" +) + +// based on: https://gist.github.com/alberts/4640792 +const ( + listenFdsStart = 3 +) + +func Files(unsetEnv bool) []*os.File { + if unsetEnv { + defer os.Unsetenv("LISTEN_PID") + defer os.Unsetenv("LISTEN_FDS") + } + + pid, err := strconv.Atoi(os.Getenv("LISTEN_PID")) + if err != nil || pid != os.Getpid() { + return nil + } + + nfds, err := strconv.Atoi(os.Getenv("LISTEN_FDS")) + if err != nil || nfds == 0 { + return nil + } + + files := make([]*os.File, 0, nfds) + for fd := listenFdsStart; fd < listenFdsStart+nfds; fd++ { + syscall.CloseOnExec(fd) + files = append(files, os.NewFile(uintptr(fd), "LISTEN_FD_"+strconv.Itoa(fd))) + } + + return files +} diff --git a/vendor/github.com/coreos/go-systemd/activation/listeners.go b/vendor/github.com/coreos/go-systemd/activation/listeners.go new file mode 100644 index 00000000000..df27c29e9ea --- /dev/null +++ b/vendor/github.com/coreos/go-systemd/activation/listeners.go @@ -0,0 +1,62 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package activation + +import ( + "crypto/tls" + "net" +) + +// Listeners returns a slice containing a net.Listener for each matching socket type +// passed to this process. +// +// The order of the file descriptors is preserved in the returned slice. +// Nil values are used to fill any gaps. For example if systemd were to return file descriptors +// corresponding with "udp, tcp, tcp", then the slice would contain {nil, net.Listener, net.Listener} +func Listeners(unsetEnv bool) ([]net.Listener, error) { + files := Files(unsetEnv) + listeners := make([]net.Listener, len(files)) + + for i, f := range files { + if pc, err := net.FileListener(f); err == nil { + listeners[i] = pc + } + } + return listeners, nil +} + +// TLSListeners returns a slice containing a net.listener for each matching TCP socket type +// passed to this process. +// It uses default Listeners func and forces TCP sockets handlers to use TLS based on tlsConfig. +func TLSListeners(unsetEnv bool, tlsConfig *tls.Config) ([]net.Listener, error) { + listeners, err := Listeners(unsetEnv) + + if listeners == nil || err != nil { + return nil, err + } + + if tlsConfig != nil && err == nil { + tlsConfig.NextProtos = []string{"http/1.1"} + + for i, l := range listeners { + // Activate TLS only for TCP sockets + if l.Addr().Network() == "tcp" { + listeners[i] = tls.NewListener(l, tlsConfig) + } + } + } + + return listeners, err +} diff --git a/vendor/github.com/coreos/go-systemd/activation/packetconns.go b/vendor/github.com/coreos/go-systemd/activation/packetconns.go new file mode 100644 index 00000000000..48b2ca029df --- /dev/null +++ b/vendor/github.com/coreos/go-systemd/activation/packetconns.go @@ -0,0 +1,37 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package activation + +import ( + "net" +) + +// PacketConns returns a slice containing a net.PacketConn for each matching socket type +// passed to this process. +// +// The order of the file descriptors is preserved in the returned slice. +// Nil values are used to fill any gaps. For example if systemd were to return file descriptors +// corresponding with "udp, tcp, udp", then the slice would contain {net.PacketConn, nil, net.PacketConn} +func PacketConns(unsetEnv bool) ([]net.PacketConn, error) { + files := Files(unsetEnv) + conns := make([]net.PacketConn, len(files)) + + for i, f := range files { + if pc, err := net.FilePacketConn(f); err == nil { + conns[i] = pc + } + } + return conns, nil +} diff --git a/vendor/github.com/skynetservices/skydns/cache/cache.go b/vendor/github.com/skynetservices/skydns/cache/cache.go new file mode 100644 index 00000000000..60e42cd5017 --- /dev/null +++ b/vendor/github.com/skynetservices/skydns/cache/cache.go @@ -0,0 +1,167 @@ +// Copyright (c) 2014 The SkyDNS Authors. All rights reserved. +// Use of this source code is governed by The MIT License (MIT) that can be +// found in the LICENSE file. + +package cache + +// Cache that holds RRs and for DNSSEC an RRSIG. + +// TODO(miek): there is a lot of copying going on to copy myself out of data +// races. This should be optimized. + +import ( + "crypto/sha1" + "sync" + "time" + + "github.com/miekg/dns" +) + +// Elem hold an answer and additional section that returned from the cache. +// The signature is put in answer, extra is empty there. This wastes some memory. +type elem struct { + expiration time.Time // time added + TTL, after this the elem is invalid + msg *dns.Msg +} + +// Cache is a cache that holds on the a number of RRs or DNS messages. The cache +// eviction is randomized. +type Cache struct { + sync.RWMutex + + capacity int + m map[string]*elem + ttl time.Duration +} + +// New returns a new cache with the capacity and the ttl specified. +func New(capacity, ttl int) *Cache { + c := new(Cache) + c.m = make(map[string]*elem) + c.capacity = capacity + c.ttl = time.Duration(ttl) * time.Second + return c +} + +func (c *Cache) Capacity() int { return c.capacity } + +func (c *Cache) Remove(s string) { + c.Lock() + delete(c.m, s) + c.Unlock() +} + +// EvictRandom removes a random member a the cache. +// Must be called under a write lock. +func (c *Cache) EvictRandom() { + clen := len(c.m) + if clen < c.capacity { + return + } + i := c.capacity - clen + for k, _ := range c.m { + delete(c.m, k) + i-- + if i == 0 { + break + } + } +} + +// InsertMessage inserts a message in the Cache. We will cache it for ttl seconds, which +// should be a small (60...300) integer. +func (c *Cache) InsertMessage(s string, msg *dns.Msg) { + if c.capacity <= 0 { + return + } + + c.Lock() + if _, ok := c.m[s]; !ok { + c.m[s] = &elem{time.Now().UTC().Add(c.ttl), msg.Copy()} + + } + c.EvictRandom() + c.Unlock() +} + +// InsertSignature inserts a signature, the expiration time is used as the cache ttl. +func (c *Cache) InsertSignature(s string, sig *dns.RRSIG) { + if c.capacity <= 0 { + return + } + c.Lock() + + if _, ok := c.m[s]; !ok { + m := ((int64(sig.Expiration) - time.Now().Unix()) / (1 << 31)) - 1 + if m < 0 { + m = 0 + } + t := time.Unix(int64(sig.Expiration)-(m*(1<<31)), 0).UTC() + c.m[s] = &elem{t, &dns.Msg{Answer: []dns.RR{dns.Copy(sig)}}} + } + c.EvictRandom() + c.Unlock() +} + +// Search returns a dns.Msg, the expiration time and a boolean indicating if we found something +// in the cache. +func (c *Cache) Search(s string) (*dns.Msg, time.Time, bool) { + if c.capacity <= 0 { + return nil, time.Time{}, false + } + c.RLock() + if e, ok := c.m[s]; ok { + e1 := e.msg.Copy() + c.RUnlock() + return e1, e.expiration, true + } + c.RUnlock() + return nil, time.Time{}, false +} + +// Key creates a hash key from a question section. It creates a different key +// for requests with DNSSEC. +func Key(q dns.Question, dnssec, tcp bool) string { + h := sha1.New() + i := append([]byte(q.Name), packUint16(q.Qtype)...) + if dnssec { + i = append(i, byte(255)) + } + if tcp { + i = append(i, byte(254)) + } + return string(h.Sum(i)) +} + +// Key uses the name, type and rdata, which is serialized and then hashed as the key for the lookup. +func KeyRRset(rrs []dns.RR) string { + h := sha1.New() + i := []byte(rrs[0].Header().Name) + i = append(i, packUint16(rrs[0].Header().Rrtype)...) + for _, r := range rrs { + switch t := r.(type) { // we only do a few type, serialize these manually + case *dns.SOA: + // We only fiddle with the serial so store that. + i = append(i, packUint32(t.Serial)...) + case *dns.SRV: + i = append(i, packUint16(t.Priority)...) + i = append(i, packUint16(t.Weight)...) + i = append(i, packUint16(t.Weight)...) + i = append(i, []byte(t.Target)...) + case *dns.A: + i = append(i, []byte(t.A)...) + case *dns.AAAA: + i = append(i, []byte(t.AAAA)...) + case *dns.NSEC3: + i = append(i, []byte(t.NextDomain)...) + // Bitmap does not differentiate in SkyDNS. + case *dns.DNSKEY: + case *dns.NS: + case *dns.TXT: + } + } + return string(h.Sum(i)) +} + +func packUint16(i uint16) []byte { return []byte{byte(i >> 8), byte(i)} } +func packUint32(i uint32) []byte { return []byte{byte(i >> 24), byte(i >> 16), byte(i >> 8), byte(i)} } diff --git a/vendor/github.com/skynetservices/skydns/cache/hit.go b/vendor/github.com/skynetservices/skydns/cache/hit.go new file mode 100644 index 00000000000..2b0a5614cbd --- /dev/null +++ b/vendor/github.com/skynetservices/skydns/cache/hit.go @@ -0,0 +1,31 @@ +// Copyright (c) 2014 The SkyDNS Authors. All rights reserved. +// Use of this source code is governed by The MIT License (MIT) that can be +// found in the LICENSE file. + +package cache + +import ( + "time" + + "github.com/miekg/dns" +) + +// Hit returns a dns message from the cache. If the message's TTL is expired nil +// is returned and the message is removed from the cache. +func (c *Cache) Hit(question dns.Question, dnssec, tcp bool, msgid uint16) *dns.Msg { + key := Key(question, dnssec, tcp) + m1, exp, hit := c.Search(key) + if hit { + // Cache hit! \o/ + if time.Since(exp) < 0 { + m1.Id = msgid + m1.Compress = true + // Even if something ended up with the TC bit *in* the cache, set it to off + m1.Truncated = false + return m1 + } + // Expired! /o\ + c.Remove(key) + } + return nil +} diff --git a/vendor/github.com/skynetservices/skydns/metrics/metrics.go b/vendor/github.com/skynetservices/skydns/metrics/metrics.go new file mode 100644 index 00000000000..7534b756bc5 --- /dev/null +++ b/vendor/github.com/skynetservices/skydns/metrics/metrics.go @@ -0,0 +1,186 @@ +// Copyright (c) 2014 The SkyDNS Authors. All rights reserved. +// Use of this source code is governed by The MIT License (MIT) that can be +// found in the LICENSE file. + +package metrics + +import ( + "fmt" + "net/http" + "os" + "strconv" + "time" + + "github.com/miekg/dns" + "github.com/prometheus/client_golang/prometheus" +) + +var ( + Port = os.Getenv("PROMETHEUS_PORT") + Path = envOrDefault("PROMETHEUS_PATH", "/metrics") + Namespace = envOrDefault("PROMETHEUS_NAMESPACE", "skydns") + Subsystem = envOrDefault("PROMETHEUS_SUBSYSTEM", "skydns") + + requestCount *prometheus.CounterVec + requestDuration *prometheus.HistogramVec + responseSize *prometheus.HistogramVec + errorCount *prometheus.CounterVec + cacheMiss *prometheus.CounterVec +) + +type ( + System string + Cause string + CacheType string +) + +var ( + Auth System = "auth" + Cache System = "cache" + Rec System = "recursive" + Reverse System = "reverse" + Stub System = "stub" + + Nxdomain Cause = "nxdomain" + Nodata Cause = "nodata" + Truncated Cause = "truncated" + Refused Cause = "refused" + Overflow Cause = "overflow" + Fail Cause = "servfail" + + Response CacheType = "response" + Signature CacheType = "signature" +) + +func defineMetrics() { + requestCount = prometheus.NewCounterVec(prometheus.CounterOpts{ + Namespace: Namespace, + Subsystem: Subsystem, + Name: "dns_request_count_total", + Help: "Counter of DNS requests made.", + }, []string{"system"}) + + requestDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{ + Namespace: Namespace, + Subsystem: Subsystem, + Name: "dns_request_duration_seconds", + Help: "Histogram of the time (in seconds) each request took to resolve.", + Buckets: append([]float64{0.001, 0.003}, prometheus.DefBuckets...), + }, []string{"system"}) + + responseSize = prometheus.NewHistogramVec(prometheus.HistogramOpts{ + Namespace: Namespace, + Subsystem: Subsystem, + Name: "dns_response_size_bytes", + Help: "Size of the returns response in bytes.", + Buckets: []float64{0, 512, 1024, 1500, 2048, 4096, + 8192, 12288, 16384, 20480, 24576, 28672, 32768, 36864, + 40960, 45056, 49152, 53248, 57344, 61440, 65536, + }, + }, []string{"system"}) + + errorCount = prometheus.NewCounterVec(prometheus.CounterOpts{ + Namespace: Namespace, + Subsystem: Subsystem, + Name: "dns_error_count_total", + Help: "Counter of DNS requests resulting in an error.", + }, []string{"system", "cause"}) + + cacheMiss = prometheus.NewCounterVec(prometheus.CounterOpts{ + Namespace: Namespace, + Subsystem: Subsystem, + Name: "dns_cachemiss_count_total", + Help: "Counter of DNS requests that result in a cache miss.", + }, []string{"cache"}) +} + +// Metrics registers the DNS metrics to Prometheus, and starts the internal metrics +// server if the environment variable PROMETHEUS_PORT is set. +func Metrics() error { + // We do this in a function instead of using var + init(), because we want to + // able to set Namespace and/or Subsystem. + if Port == "" { + return nil + } + + _, err := strconv.Atoi(Port) + if err != nil { + fmt.Errorf("bad port for prometheus: %s", Port) + } + + defineMetrics() + + prometheus.MustRegister(requestCount) + prometheus.MustRegister(requestDuration) + prometheus.MustRegister(responseSize) + prometheus.MustRegister(errorCount) + prometheus.MustRegister(cacheMiss) + + http.Handle(Path, prometheus.Handler()) + go func() { + fmt.Errorf("%s", http.ListenAndServe(":"+Port, nil)) + }() + return nil +} + +func ReportDuration(resp *dns.Msg, start time.Time, sys System) { + if requestDuration == nil || responseSize == nil { + return + } + + rlen := float64(0) + if resp != nil { + rlen = float64(resp.Len()) + } + requestDuration.WithLabelValues(string(sys)).Observe(float64(time.Since(start)) / float64(time.Second)) + responseSize.WithLabelValues(string(sys)).Observe(rlen) +} + +func ReportRequestCount(req *dns.Msg, sys System) { + if requestCount == nil { + return + } + + requestCount.WithLabelValues(string(sys)).Inc() +} + +func ReportErrorCount(resp *dns.Msg, sys System) { + if resp == nil || errorCount == nil { + return + } + + if resp.Truncated { + errorCount.WithLabelValues(string(sys), string(Truncated)).Inc() + return + } + if resp.Len() > dns.MaxMsgSize { + errorCount.WithLabelValues(string(sys), string(Overflow)).Inc() + return + } + + switch resp.Rcode { + case dns.RcodeServerFailure: + errorCount.WithLabelValues(string(sys), string(Fail)).Inc() + case dns.RcodeRefused: + errorCount.WithLabelValues(string(sys), string(Refused)).Inc() + case dns.RcodeNameError: + errorCount.WithLabelValues(string(sys), string(Nxdomain)).Inc() + // nodata ?? + } + +} + +func ReportCacheMiss(ca CacheType) { + if cacheMiss == nil { + return + } + cacheMiss.WithLabelValues(string(ca)).Inc() +} + +func envOrDefault(env, def string) string { + e := os.Getenv(env) + if e != "" { + return e + } + return def +} diff --git a/vendor/github.com/skynetservices/skydns/server/backend.go b/vendor/github.com/skynetservices/skydns/server/backend.go new file mode 100644 index 00000000000..bb3a8cdd794 --- /dev/null +++ b/vendor/github.com/skynetservices/skydns/server/backend.go @@ -0,0 +1,46 @@ +// Copyright (c) 2014 The SkyDNS Authors. All rights reserved. +// Use of this source code is governed by The MIT License (MIT) that can be +// found in the LICENSE file. + +package server + +import "github.com/skynetservices/skydns/msg" + +type Backend interface { + Records(name string, exact bool) ([]msg.Service, error) + ReverseRecord(name string) (*msg.Service, error) +} + +// FirstBackend exposes the Backend interface over multiple Backends, returning +// the first Backend that answers the provided record request. If no Backend answers +// a record request, the last error seen will be returned. +type FirstBackend []Backend + +// FirstBackend implements Backend +var _ Backend = FirstBackend{} + +func (g FirstBackend) Records(name string, exact bool) (records []msg.Service, err error) { + var lastError error + for _, backend := range g { + if records, err = backend.Records(name, exact); err == nil && len(records) > 0 { + return records, nil + } + if err != nil { + lastError = err + } + } + return nil, lastError +} + +func (g FirstBackend) ReverseRecord(name string) (record *msg.Service, err error) { + var lastError error + for _, backend := range g { + if record, err = backend.ReverseRecord(name); err == nil && record != nil { + return record, nil + } + if err != nil { + lastError = err + } + } + return nil, lastError +} diff --git a/vendor/github.com/skynetservices/skydns/server/config.go b/vendor/github.com/skynetservices/skydns/server/config.go new file mode 100644 index 00000000000..3e4c6cfb078 --- /dev/null +++ b/vendor/github.com/skynetservices/skydns/server/config.go @@ -0,0 +1,157 @@ +// Copyright (c) 2014 The SkyDNS Authors. All rights reserved. +// Use of this source code is governed by The MIT License (MIT) that can be +// found in the LICENSE file. + +package server + +import ( + "crypto" + "fmt" + "net" + "os" + "strings" + "time" + + "github.com/miekg/dns" +) + +const ( + SCacheCapacity = 10000 + RCacheCapacity = 100000 + RCacheTtl = 60 +) + +// Config provides options to the SkyDNS resolver. +type Config struct { + // The ip:port SkyDNS should be listening on for incoming DNS requests. + DnsAddr string `json:"dns_addr,omitempty"` + // bind to port(s) activated by systemd. If set to true, this overrides DnsAddr. + Systemd bool `json:"systemd,omitempty"` + // The domain SkyDNS is authoritative for, defaults to skydns.local. + Domain string `json:"domain,omitempty"` + // Domain pointing to a key where service info is stored when being queried + // for local.dns.skydns.local. + Local string `json:"local,omitempty"` + // The hostmaster responsible for this domain, defaults to hostmaster.. + Hostmaster string `json:"hostmaster,omitempty"` + DNSSEC string `json:"dnssec,omitempty"` + // Round robin A/AAAA replies. Default is true. + RoundRobin bool `json:"round_robin,omitempty"` + // Round robin selection of nameservers from among those listed, rather than have all forwarded requests try the first listed server first every time. + NSRotate bool `json:"ns_rotate,omitempty"` + // List of ip:port, seperated by commas of recursive nameservers to forward queries to. + Nameservers []string `json:"nameservers,omitempty"` + // Never provide a recursive service. + NoRec bool `json:"no_rec,omitempty"` + ReadTimeout time.Duration `json:"read_timeout,omitempty"` + // Default priority on SRV records when none is given. Defaults to 10. + Priority uint16 `json:"priority"` + // Default TTL, in seconds, when none is given in etcd. Defaults to 3600. + Ttl uint32 `json:"ttl,omitempty"` + // Minimum TTL, in seconds, for NXDOMAIN responses. Defaults to 300. + MinTtl uint32 `json:"min_ttl,omitempty"` + // SCache, capacity of the signature cache in signatures stored. + SCache int `json:"scache,omitempty"` + // RCache, capacity of response cache in resource records stored. + RCache int `json:"rcache,omitempty"` + // RCacheTtl, how long to cache in seconds. + RCacheTtl int `json:"rcache_ttl,omitempty"` + // How many labels a name should have before we allow forwarding. Default to 2. + Ndots int `json:"ndot,omitempty"` + + // DNSSEC key material + PubKey *dns.DNSKEY `json:"-"` + KeyTag uint16 `json:"-"` + PrivKey crypto.Signer `json:"-"` + + Verbose bool `json:"-"` + + Version bool + + // some predefined string "constants" + localDomain string // "local.dns." + config.Domain + dnsDomain string // "ns.dns". + config.Domain + + // Stub zones support. Pointer to a map that we refresh when we see + // an update. Map contains domainname -> nameserver:port + stub *map[string][]string +} + +func SetDefaults(config *Config) error { + if config.ReadTimeout == 0 { + config.ReadTimeout = 2 * time.Second + } + if config.DnsAddr == "" { + config.DnsAddr = "127.0.0.1:53" + } + if config.Domain == "" { + config.Domain = "skydns.local." + } + if config.Hostmaster == "" { + config.Hostmaster = appendDomain("hostmaster", config.Domain) + } + // People probably don't know that SOA's email addresses cannot + // contain @-signs, replace them with dots + config.Hostmaster = dns.Fqdn(strings.Replace(config.Hostmaster, "@", ".", -1)) + if config.MinTtl == 0 { + config.MinTtl = 60 + } + if config.Ttl == 0 { + config.Ttl = 3600 + } + if config.Priority == 0 { + config.Priority = 10 + } + if config.RCache < 0 { + config.RCache = 0 + } + if config.SCache < 0 { + config.SCache = 0 + } + if config.RCacheTtl == 0 { + config.RCacheTtl = RCacheTtl + } + if config.Ndots <= 0 { + config.Ndots = 2 + } + + if len(config.Nameservers) == 0 { + c, err := dns.ClientConfigFromFile("/etc/resolv.conf") + if !os.IsNotExist(err) { + if err != nil { + return err + } + for _, s := range c.Servers { + config.Nameservers = append(config.Nameservers, net.JoinHostPort(s, c.Port)) + } + } + } + config.Domain = dns.Fqdn(strings.ToLower(config.Domain)) + if config.DNSSEC != "" { + // For some reason the + are replaces by spaces in etcd. Re-replace them + keyfile := strings.Replace(config.DNSSEC, " ", "+", -1) + k, p, err := ParseKeyFile(keyfile) + if err != nil { + return err + } + if k.Header().Name != dns.Fqdn(config.Domain) { + return fmt.Errorf("ownername of DNSKEY must match SkyDNS domain") + } + k.Header().Ttl = config.Ttl + config.PubKey = k + config.KeyTag = k.KeyTag() + config.PrivKey = p + } + config.localDomain = appendDomain("local.dns", config.Domain) + config.dnsDomain = appendDomain("ns.dns", config.Domain) + stubmap := make(map[string][]string) + config.stub = &stubmap + return nil +} + +func appendDomain(s1, s2 string) string { + if len(s2) > 0 && s2[0] == '.' { + return s1 + s2 + } + return s1 + "." + s2 +} diff --git a/vendor/github.com/skynetservices/skydns/server/dnssec.go b/vendor/github.com/skynetservices/skydns/server/dnssec.go new file mode 100644 index 00000000000..587d054acfb --- /dev/null +++ b/vendor/github.com/skynetservices/skydns/server/dnssec.go @@ -0,0 +1,177 @@ +// Copyright (c) 2013 Erik St. Martin, Brian Ketelsen. All rights reserved. +// Use of this source code is governed by The MIT License (MIT) that can be +// found in the LICENSE file. + +package server + +import ( + "crypto" + "crypto/ecdsa" + "crypto/rsa" + "os" + "time" + + "github.com/skynetservices/skydns/cache" + "github.com/skynetservices/skydns/metrics" + "github.com/skynetservices/skydns/singleflight" + + "github.com/miekg/dns" +) +var ( + inflight = &singleflight.Group{} +) + + +// ParseKeyFile read a DNSSEC keyfile as generated by dnssec-keygen or other +// utilities. It add ".key" for the public key and ".private" for the private key. +func ParseKeyFile(file string) (*dns.DNSKEY, crypto.Signer, error) { + f, e := os.Open(file + ".key") + if e != nil { + return nil, nil, e + } + k, e := dns.ReadRR(f, file+".key") + if e != nil { + return nil, nil, e + } + f, e = os.Open(file + ".private") + if e != nil { + return nil, nil, e + } + p, e := k.(*dns.DNSKEY).ReadPrivateKey(f, file+".private") + if e != nil { + return nil, nil, e + } + + if v, ok := p.(*rsa.PrivateKey); ok { + return k.(*dns.DNSKEY), v, nil + } + if v, ok := p.(*ecdsa.PrivateKey); ok { + return k.(*dns.DNSKEY), v, nil + } + return k.(*dns.DNSKEY), nil, nil +} + +// Sign signs a message m, it takes care of negative or nodata responses as +// well by synthesising NSEC3 records. It will also cache the signatures, using +// a hash of the signed data as a key. +// We also fake the origin TTL in the signature, because we don't want to +// throw away signatures when services decide to have longer TTL. So we just +// set the origTTL to 60. +// TODO(miek): revisit origTTL +func (s *server) Sign(m *dns.Msg, bufsize uint16) { + now := time.Now().UTC() + incep := uint32(now.Add(-3 * time.Hour).Unix()) // 2+1 hours, be sure to catch daylight saving time and such + expir := uint32(now.Add(7 * 24 * time.Hour).Unix()) // sign for a week + + for _, r := range rrSets(m.Answer) { + if r[0].Header().Rrtype == dns.TypeRRSIG { + continue + } + if !dns.IsSubDomain(s.config.Domain, r[0].Header().Name) { + continue + } + if sig, err := s.signSet(r, now, incep, expir); err == nil { + m.Answer = append(m.Answer, sig) + } + } + for _, r := range rrSets(m.Ns) { + if r[0].Header().Rrtype == dns.TypeRRSIG { + continue + } + if !dns.IsSubDomain(s.config.Domain, r[0].Header().Name) { + continue + } + if sig, err := s.signSet(r, now, incep, expir); err == nil { + m.Ns = append(m.Ns, sig) + } + } + for _, r := range rrSets(m.Extra) { + if r[0].Header().Rrtype == dns.TypeRRSIG || r[0].Header().Rrtype == dns.TypeOPT { + continue + } + if !dns.IsSubDomain(s.config.Domain, r[0].Header().Name) { + continue + } + if sig, err := s.signSet(r, now, incep, expir); err == nil { + m.Extra = append(m.Extra, sig) + } + } + + o := new(dns.OPT) + o.Hdr.Name = "." + o.Hdr.Rrtype = dns.TypeOPT + o.SetDo() + o.SetUDPSize(4096) // TODO(miek): echo client + m.Extra = append(m.Extra, o) + return +} + +func (s *server) signSet(r []dns.RR, now time.Time, incep, expir uint32) (*dns.RRSIG, error) { + key := cache.KeyRRset(r) + if m, exp, hit := s.scache.Search(key); hit { // There can only be one sig in this cache. + // Is it still valid 24 hours from now? + if now.Add(+24*time.Hour).Sub(exp) < -24*time.Hour { + return m.Answer[0].(*dns.RRSIG), nil + } + s.scache.Remove(key) + } + if s.config.Verbose { + logf("scache miss for %s type %d", r[0].Header().Name, r[0].Header().Rrtype) + } + + metrics.ReportCacheMiss("signature") + + sig, err := inflight.Do(key, func() (interface{}, error) { + sig1 := s.NewRRSIG(incep, expir) + sig1.Header().Ttl = r[0].Header().Ttl + if r[0].Header().Rrtype == dns.TypeTXT { + sig1.OrigTtl = 0 + } + e := sig1.Sign(s.config.PrivKey, r) + if e != nil { + logf("failed to sign: %s", e.Error()) + } + return sig1, e + }) + if err != nil { + return nil, err + } + s.scache.InsertSignature(key, sig.(*dns.RRSIG)) + return dns.Copy(sig.(*dns.RRSIG)).(*dns.RRSIG), nil +} + +func (s *server) NewRRSIG(incep, expir uint32) *dns.RRSIG { + sig := new(dns.RRSIG) + sig.Hdr.Rrtype = dns.TypeRRSIG + sig.Hdr.Ttl = s.config.Ttl + sig.OrigTtl = s.config.Ttl + sig.Algorithm = s.config.PubKey.Algorithm + sig.KeyTag = s.config.KeyTag + sig.Inception = incep + sig.Expiration = expir + sig.SignerName = s.config.PubKey.Hdr.Name + return sig +} + +type rrset struct { + qname string + qtype uint16 +} + +func rrSets(rrs []dns.RR) map[rrset][]dns.RR { + m := make(map[rrset][]dns.RR) + for _, r := range rrs { + if s, ok := m[rrset{r.Header().Name, r.Header().Rrtype}]; ok { + s = append(s, r) + m[rrset{r.Header().Name, r.Header().Rrtype}] = s + } else { + s := make([]dns.RR, 1, 3) + s[0] = r + m[rrset{r.Header().Name, r.Header().Rrtype}] = s + } + } + if len(m) > 0 { + return m + } + return nil +} diff --git a/vendor/github.com/skynetservices/skydns/server/doc.go b/vendor/github.com/skynetservices/skydns/server/doc.go new file mode 100644 index 00000000000..d2009a65141 --- /dev/null +++ b/vendor/github.com/skynetservices/skydns/server/doc.go @@ -0,0 +1,8 @@ +// Copyright (c) 2014 The SkyDNS Authors. All rights reserved. +// Use of this source code is governed by The MIT License (MIT) that can be +// found in the LICENSE file. + +// Package server provides a DNS server implementation that handles DNS +// queries. To answer a query, the server asks the provided Backend for +// DNS records, which are then converted to the proper answers. +package server diff --git a/vendor/github.com/skynetservices/skydns/server/exchange.go b/vendor/github.com/skynetservices/skydns/server/exchange.go new file mode 100644 index 00000000000..2fb5be9ace0 --- /dev/null +++ b/vendor/github.com/skynetservices/skydns/server/exchange.go @@ -0,0 +1,34 @@ +// Copyright (c) 2014 The SkyDNS Authors. All rights reserved. +// Use of this source code is governed by The MIT License (MIT) that can be +// found in the LICENSE file. + +package server + +import "github.com/miekg/dns" + +// exchangeMsg returns a new dns message based on name, type, bufsize and dnssec. +func newExchangeMsg(name string, typ, bufsize uint16, dnssec bool) *dns.Msg { + m := new(dns.Msg) + m.SetQuestion(name, typ) + m.SetEdns0(bufsize, dnssec) + return m +} + +// exchangeWithRetry sends message m to server, but retries on ServerFailure. +func exchangeWithRetry(c *dns.Client, m *dns.Msg, server string) (*dns.Msg, error) { + r, _, err := c.Exchange(m, server) + if err == nil && r.Rcode == dns.RcodeServerFailure { + // redo the query + r, _, err = c.Exchange(m, server) + } + return r, err +} + +func (s *server) randomNameserverID(id uint16) int { + nsid := 0 + if s.config.NSRotate { + // Use request Id for "random" nameserver selection. + nsid = int(id) % len(s.config.Nameservers) + } + return nsid +} diff --git a/vendor/github.com/skynetservices/skydns/server/forwarding.go b/vendor/github.com/skynetservices/skydns/server/forwarding.go new file mode 100644 index 00000000000..a3c8cb32db8 --- /dev/null +++ b/vendor/github.com/skynetservices/skydns/server/forwarding.go @@ -0,0 +1,125 @@ +// Copyright (c) 2014 The SkyDNS Authors. All rights reserved. +// Use of this source code is governed by The MIT License (MIT) that can be +// found in the LICENSE file. + +package server + +import ( + "fmt" + + "github.com/miekg/dns" +) + +// ServeDNSForward forwards a request to a nameservers and returns the response. +func (s *server) ServeDNSForward(w dns.ResponseWriter, req *dns.Msg) *dns.Msg { + if s.config.NoRec { + m := s.ServerFailure(req) + w.WriteMsg(m) + return m + } + + if len(s.config.Nameservers) == 0 || dns.CountLabel(req.Question[0].Name) < s.config.Ndots { + if s.config.Verbose { + if len(s.config.Nameservers) == 0 { + logf("can not forward, no nameservers defined") + } else { + logf("can not forward, name too short (less than %d labels): `%s'", s.config.Ndots, req.Question[0].Name) + } + } + m := s.ServerFailure(req) + m.RecursionAvailable = true // this is still true + w.WriteMsg(m) + return m + } + + var ( + r *dns.Msg + err error + ) + + nsid := s.randomNameserverID(req.Id) + try := 0 +Redo: + if isTCP(w) { + r, err = exchangeWithRetry(s.dnsTCPclient, req, s.config.Nameservers[nsid]) + } else { + r, err = exchangeWithRetry(s.dnsUDPclient, req, s.config.Nameservers[nsid]) + } + if err == nil { + r.Compress = true + r.Id = req.Id + w.WriteMsg(r) + return r + } + // Seen an error, this can only mean, "server not reached", try again + // but only if we have not exausted our nameservers. + if try < len(s.config.Nameservers) { + try++ + nsid = (nsid + 1) % len(s.config.Nameservers) + goto Redo + } + + logf("failure to forward request %q", err) + m := s.ServerFailure(req) + return m +} + +// ServeDNSReverse is the handler for DNS requests for the reverse zone. If nothing is found +// locally the request is forwarded to the forwarder for resolution. +func (s *server) ServeDNSReverse(w dns.ResponseWriter, req *dns.Msg) *dns.Msg { + m := new(dns.Msg) + m.SetReply(req) + m.Compress = true + m.Authoritative = false // Set to false, because I don't know what to do wrt DNSSEC. + m.RecursionAvailable = true + var err error + if m.Answer, err = s.PTRRecords(req.Question[0]); err == nil { + // TODO(miek): Reverse DNSSEC. We should sign this, but requires a key....and more + // Probably not worth the hassle? + if err := w.WriteMsg(m); err != nil { + logf("failure to return reply %q", err) + } + return m + } + // Always forward if not found locally. + return s.ServeDNSForward(w, req) +} + +// Lookup looks up name,type using the recursive nameserver defines +// in the server's config. If none defined it returns an error. +func (s *server) Lookup(n string, t, bufsize uint16, dnssec bool) (*dns.Msg, error) { + if len(s.config.Nameservers) == 0 { + return nil, fmt.Errorf("no nameservers configured can not lookup name") + } + if dns.CountLabel(n) < s.config.Ndots { + return nil, fmt.Errorf("name has fewer than %d labels", s.config.Ndots) + } + m := newExchangeMsg(n, t, bufsize, dnssec) + + nsid := s.randomNameserverID(m.Id) + try := 0 +Redo: + r, err := exchangeWithRetry(s.dnsUDPclient, m, s.config.Nameservers[nsid]) + if err == nil { + if r.Rcode != dns.RcodeSuccess { + return nil, fmt.Errorf("rcode is not equal to success") + } + // Reset TTLs to rcache TTL to make some of the other code + // and the tests not care about TTLs + for _, rr := range r.Answer { + rr.Header().Ttl = uint32(s.config.RCacheTtl) + } + for _, rr := range r.Extra { + rr.Header().Ttl = uint32(s.config.RCacheTtl) + } + return r, nil + } + // Seen an error, this can only mean, "server not reached", try again + // but only if we have not exausted our nameservers. + if try < len(s.config.Nameservers) { + try++ + nsid = (nsid + 1) % len(s.config.Nameservers) + goto Redo + } + return nil, fmt.Errorf("failure to lookup name") +} diff --git a/vendor/github.com/skynetservices/skydns/server/log.go b/vendor/github.com/skynetservices/skydns/server/log.go new file mode 100644 index 00000000000..13288f83822 --- /dev/null +++ b/vendor/github.com/skynetservices/skydns/server/log.go @@ -0,0 +1,17 @@ +// Copyright (c) 2014 The SkyDNS Authors. All rights reserved. +// Use of this source code is governed by The MIT License (MIT) that can be +// found in the LICENSE file. + +package server + +import "log" + +// printf calls log.Printf with the parameters given. +func logf(format string, a ...interface{}) { + log.Printf("skydns: "+format, a...) +} + +// fatalf calls log.Fatalf with the parameters given. +func fatalf(format string, a ...interface{}) { + log.Fatalf("skydns: "+format, a...) +} diff --git a/vendor/github.com/skynetservices/skydns/server/msg.go b/vendor/github.com/skynetservices/skydns/server/msg.go new file mode 100644 index 00000000000..6250ec8ad84 --- /dev/null +++ b/vendor/github.com/skynetservices/skydns/server/msg.go @@ -0,0 +1,54 @@ +// Copyright (c) 2014 The SkyDNS Authors. All rights reserved. +// Use of this source code is governed by The MIT License (MIT) that can be +// found in the LICENSE file. + +package server + +import "github.com/miekg/dns" + +// Fit will make m fit the size. If a message is larger than size then entire +// additional section is dropped. If it is still to large and the transport +// is udp we return a truncated message. +// If the transport is tcp we are going to drop RR from the answer section +// until it fits. When this is case the returned bool is true. +func Fit(m *dns.Msg, size int, tcp bool) (*dns.Msg, bool) { + if m.Len() > size { + // Check for OPT Records at the end and keep those. TODO(miek) + m.Extra = nil + } + if m.Len() < size { + return m, false + } + + // With TCP setting TC does not mean anything. + if !tcp { + m.Truncated = true + // fall through here, so we at least return a message that can + // fit the udp buffer. + } + + // Additional section is gone, binary search until we have length that fits. + min, max := 0, len(m.Answer) + original := make([]dns.RR, len(m.Answer)) + copy(original, m.Answer) + for { + if min == max { + break + } + + mid := (min + max) / 2 + m.Answer = original[:mid] + + if m.Len() < size { + min++ + continue + } + max = mid + + } + if max > 1 { + max-- + } + m.Answer = m.Answer[:max] + return m, true +} diff --git a/vendor/github.com/skynetservices/skydns/server/nsec3.go b/vendor/github.com/skynetservices/skydns/server/nsec3.go new file mode 100644 index 00000000000..bf911534c35 --- /dev/null +++ b/vendor/github.com/skynetservices/skydns/server/nsec3.go @@ -0,0 +1,155 @@ +// Copyright (c) 2013 Erik St. Martin, Brian Ketelsen. All rights reserved. +// Use of this source code is governed by The MIT License (MIT) that can be +// found in the LICENSE file. + +package server + +import ( + "encoding/base32" + "strings" + + "github.com/miekg/dns" +) + +// Do DNSSEC NXDOMAIN with NSEC3 whitelies: rfc 7129, appendix B. +// The closest encloser will be qname - the left most label and the +// next closer will be the full qname which we then will deny. +// Idem for source of synthesis. + +func (s *server) Denial(m *dns.Msg) { + if m.Rcode == dns.RcodeNameError { + // ce is qname minus the left label + idx := dns.Split(m.Question[0].Name) + ce := m.Question[0].Name[idx[1]:] + + nsec3ce, nsec3wildcard := newNSEC3CEandWildcard(s.config.Domain, ce, s.config.MinTtl) + // Add ce and wildcard + m.Ns = append(m.Ns, nsec3ce) + m.Ns = append(m.Ns, nsec3wildcard) + // Deny Qname nsec3 + m.Ns = append(m.Ns, s.newNSEC3NameError(m.Question[0].Name)) + } + if m.Rcode == dns.RcodeSuccess && len(m.Ns) == 1 { + // NODATA + if _, ok := m.Ns[0].(*dns.SOA); ok { + m.Ns = append(m.Ns, s.newNSEC3NoData(m.Question[0].Name)) + } + } +} + +func packBase32(s string) []byte { + b32len := base32.HexEncoding.DecodedLen(len(s)) + buf := make([]byte, b32len) + n, _ := base32.HexEncoding.Decode(buf, []byte(s)) + buf = buf[:n] + return buf +} + +func unpackBase32(b []byte) string { + b32 := make([]byte, base32.HexEncoding.EncodedLen(len(b))) + base32.HexEncoding.Encode(b32, b) + return string(b32) +} + +// newNSEC3NameError returns the NSEC3 record needed to denial qname. +func (s *server) newNSEC3NameError(qname string) *dns.NSEC3 { + n := new(dns.NSEC3) + n.Hdr.Class = dns.ClassINET + n.Hdr.Rrtype = dns.TypeNSEC3 + n.Hdr.Ttl = s.config.MinTtl + n.Hash = dns.SHA1 + n.Flags = 0 + n.Salt = "" + n.TypeBitMap = []uint16{} + + covername := dns.HashName(qname, dns.SHA1, 0, "") + + buf := packBase32(covername) + byteArith(buf, false) // one before + n.Hdr.Name = appendDomain(strings.ToLower(unpackBase32(buf)), s.config.Domain) + byteArith(buf, true) // one next + byteArith(buf, true) // and another one + n.NextDomain = unpackBase32(buf) + return n +} + +// newNSEC3NoData returns the NSEC3 record needed to denial the types +func (s *server) newNSEC3NoData(qname string) *dns.NSEC3 { + n := new(dns.NSEC3) + n.Hdr.Class = dns.ClassINET + n.Hdr.Rrtype = dns.TypeNSEC3 + n.Hdr.Ttl = s.config.MinTtl + n.Hash = dns.SHA1 + n.Flags = 0 + n.Salt = "" + n.TypeBitMap = []uint16{dns.TypeA, dns.TypeAAAA, dns.TypeSRV, dns.TypeRRSIG} + + n.Hdr.Name = dns.HashName(qname, dns.SHA1, 0, "") + buf := packBase32(n.Hdr.Name) + byteArith(buf, true) // one next + n.NextDomain = unpackBase32(buf) + + n.Hdr.Name += appendDomain("", s.config.Domain) + return n +} + +// newNSEC3CEandWildcard returns the NSEC3 for the closest encloser +// and the NSEC3 that denies that wildcard at that level. +func newNSEC3CEandWildcard(apex, ce string, ttl uint32) (*dns.NSEC3, *dns.NSEC3) { + n1 := new(dns.NSEC3) + n1.Hdr.Class = dns.ClassINET + n1.Hdr.Rrtype = dns.TypeNSEC3 + n1.Hdr.Ttl = ttl + n1.Hash = dns.SHA1 + n1.Flags = 0 + n1.Iterations = 0 + n1.Salt = "" + // for the apex we need another bitmap + n1.TypeBitMap = []uint16{dns.TypeA, dns.TypeAAAA, dns.TypeSRV, dns.TypeRRSIG} + prev := dns.HashName(ce, dns.SHA1, n1.Iterations, n1.Salt) + n1.Hdr.Name = strings.ToLower(prev) + "." + apex + buf := packBase32(prev) + byteArith(buf, true) // one next + n1.NextDomain = unpackBase32(buf) + + n2 := new(dns.NSEC3) + n2.Hdr.Class = dns.ClassINET + n2.Hdr.Rrtype = dns.TypeNSEC3 + n2.Hdr.Ttl = ttl + n2.Hash = dns.SHA1 + n2.Flags = 0 + n2.Iterations = 0 + n2.Salt = "" + + prev = dns.HashName("*."+ce, dns.SHA1, n2.Iterations, n2.Salt) + buf = packBase32(prev) + byteArith(buf, false) // one before + n2.Hdr.Name = appendDomain(strings.ToLower(unpackBase32(buf)), apex) + byteArith(buf, true) // one next + byteArith(buf, true) // and another one + n2.NextDomain = unpackBase32(buf) + + return n1, n2 +} + +// byteArith adds either 1 or -1 to b, there is no check for under- or overflow. +func byteArith(b []byte, x bool) { + if x { + for i := len(b) - 1; i >= 0; i-- { + if b[i] == 255 { + b[i] = 0 + continue + } + b[i]++ + return + } + } + for i := len(b) - 1; i >= 0; i-- { + if b[i] == 0 { + b[i] = 255 + continue + } + b[i]-- + return + } +} diff --git a/vendor/github.com/skynetservices/skydns/server/server.go b/vendor/github.com/skynetservices/skydns/server/server.go new file mode 100644 index 00000000000..883afef9972 --- /dev/null +++ b/vendor/github.com/skynetservices/skydns/server/server.go @@ -0,0 +1,888 @@ +// Copyright (c) 2014 The SkyDNS Authors. All rights reserved. +// Use of this source code is governed by The MIT License (MIT) that can be +// found in the LICENSE file. + +package server + +import ( + "fmt" + "math" + "net" + "strconv" + "strings" + "sync" + "time" + + "github.com/skynetservices/skydns/cache" + "github.com/skynetservices/skydns/metrics" + "github.com/skynetservices/skydns/msg" + + etcd "github.com/coreos/etcd/client" + "github.com/coreos/go-systemd/activation" + "github.com/miekg/dns" +) + +const Version = "2.5.3a" + +type server struct { + backend Backend + config *Config + + group *sync.WaitGroup + dnsUDPclient *dns.Client // used for forwarding queries + dnsTCPclient *dns.Client // used for forwarding queries + scache *cache.Cache + rcache *cache.Cache +} + +// New returns a new SkyDNS server. +func New(backend Backend, config *Config) *server { + return &server{ + backend: backend, + config: config, + + group: new(sync.WaitGroup), + scache: cache.New(config.SCache, 0), + rcache: cache.New(config.RCache, config.RCacheTtl), + dnsUDPclient: &dns.Client{Net: "udp", ReadTimeout: config.ReadTimeout, WriteTimeout: config.ReadTimeout, SingleInflight: true}, + dnsTCPclient: &dns.Client{Net: "tcp", ReadTimeout: config.ReadTimeout, WriteTimeout: config.ReadTimeout, SingleInflight: true}, + } +} + +// Run is a blocking operation that starts the server listening on the DNS ports. +func (s *server) Run() error { + mux := dns.NewServeMux() + mux.Handle(".", s) + + dnsReadyMsg := func(addr, net string) { + if s.config.DNSSEC == "" { + logf("ready for queries on %s for %s://%s [rcache %d]", s.config.Domain, net, addr, s.config.RCache) + } else { + logf("ready for queries on %s for %s://%s [rcache %d], signing with %s [scache %d]", s.config.Domain, net, addr, s.config.RCache, s.config.DNSSEC, s.config.SCache) + } + } + + if s.config.Systemd { + packetConns, err := activation.PacketConns(false) + if err != nil { + return err + } + listeners, err := activation.Listeners(true) + if err != nil { + return err + } + if len(packetConns) == 0 && len(listeners) == 0 { + return fmt.Errorf("no UDP or TCP sockets supplied by systemd") + } + for _, p := range packetConns { + if u, ok := p.(*net.UDPConn); ok { + s.group.Add(1) + go func() { + defer s.group.Done() + if err := dns.ActivateAndServe(nil, u, mux); err != nil { + fatalf("%s", err) + } + }() + dnsReadyMsg(u.LocalAddr().String(), "udp") + } + } + for _, l := range listeners { + if t, ok := l.(*net.TCPListener); ok { + s.group.Add(1) + go func() { + defer s.group.Done() + if err := dns.ActivateAndServe(t, nil, mux); err != nil { + fatalf("%s", err) + } + }() + dnsReadyMsg(t.Addr().String(), "tcp") + } + } + } else { + s.group.Add(1) + go func() { + defer s.group.Done() + if err := dns.ListenAndServe(s.config.DnsAddr, "tcp", mux); err != nil { + fatalf("%s", err) + } + }() + dnsReadyMsg(s.config.DnsAddr, "tcp") + s.group.Add(1) + go func() { + defer s.group.Done() + if err := dns.ListenAndServe(s.config.DnsAddr, "udp", mux); err != nil { + fatalf("%s", err) + } + }() + dnsReadyMsg(s.config.DnsAddr, "udp") + } + + s.group.Wait() + return nil +} + +// Stop stops a server. +func (s *server) Stop() { + // TODO(miek) + //s.group.Add(-2) +} + +// ServeDNS is the handler for DNS requests, responsible for parsing DNS request, possibly forwarding +// it to a real dns server and returning a response. +func (s *server) ServeDNS(w dns.ResponseWriter, req *dns.Msg) { + m := new(dns.Msg) + m.SetReply(req) + m.Authoritative = true + m.RecursionAvailable = true + m.Compress = true + + bufsize := uint16(512) + dnssec := false + tcp := false + start := time.Now() + + q := req.Question[0] + name := strings.ToLower(q.Name) + + if q.Qtype == dns.TypeANY { + m.Authoritative = false + m.Rcode = dns.RcodeRefused + m.RecursionAvailable = false + m.RecursionDesired = false + m.Compress = false + w.WriteMsg(m) + + metrics.ReportRequestCount(m, metrics.Auth) + metrics.ReportDuration(m, start, metrics.Auth) + metrics.ReportErrorCount(m, metrics.Auth) + + return + } + + if o := req.IsEdns0(); o != nil { + bufsize = o.UDPSize() + dnssec = o.Do() + } + if bufsize < 512 { + bufsize = 512 + } + // with TCP we can send 64K + if tcp = isTCP(w); tcp { + bufsize = dns.MaxMsgSize - 1 + } + + if s.config.Verbose { + logf("received DNS Request for %q from %q with type %d", q.Name, w.RemoteAddr(), q.Qtype) + } + + // Check cache first. + m1 := s.rcache.Hit(q, dnssec, tcp, m.Id) + if m1 != nil { + metrics.ReportRequestCount(req, metrics.Cache) + + if send := s.overflowOrTruncated(w, m1, int(bufsize), metrics.Cache); send { + return + } + + // Still round-robin even with hits from the cache. + // Only shuffle A and AAAA records with each other. + if q.Qtype == dns.TypeA || q.Qtype == dns.TypeAAAA { + s.RoundRobin(m1.Answer) + } + + if err := w.WriteMsg(m1); err != nil { + logf("failure to return reply %q", err) + } + + metrics.ReportDuration(m1, start, metrics.Cache) + metrics.ReportErrorCount(m1, metrics.Cache) + return + } + + for zone, ns := range *s.config.stub { + if strings.HasSuffix(name, zone) { + metrics.ReportRequestCount(req, metrics.Stub) + + resp := s.ServeDNSStubForward(w, req, ns) + if resp != nil { + s.rcache.InsertMessage(cache.Key(q, dnssec, tcp), resp) + } + + metrics.ReportDuration(resp, start, metrics.Stub) + metrics.ReportErrorCount(resp, metrics.Stub) + return + } + } + + // If the qname is local.ds.skydns.local. and s.config.Local != "", substitute that name. + if s.config.Local != "" && name == s.config.localDomain { + name = s.config.Local + } + + if q.Qtype == dns.TypePTR && strings.HasSuffix(name, ".in-addr.arpa.") || strings.HasSuffix(name, ".ip6.arpa.") { + metrics.ReportRequestCount(req, metrics.Reverse) + + resp := s.ServeDNSReverse(w, req) + if resp != nil { + s.rcache.InsertMessage(cache.Key(q, dnssec, tcp), resp) + } + + metrics.ReportDuration(resp, start, metrics.Reverse) + metrics.ReportErrorCount(resp, metrics.Reverse) + return + } + + if q.Qclass != dns.ClassCHAOS && !strings.HasSuffix(name, s.config.Domain) { + metrics.ReportRequestCount(req, metrics.Rec) + + resp := s.ServeDNSForward(w, req) + if resp != nil { + s.rcache.InsertMessage(cache.Key(q, dnssec, tcp), resp) + } + + metrics.ReportDuration(resp, start, metrics.Rec) + metrics.ReportErrorCount(resp, metrics.Rec) + return + } + + metrics.ReportCacheMiss(metrics.Response) + + defer func() { + metrics.ReportDuration(m, start, metrics.Auth) + metrics.ReportErrorCount(m, metrics.Auth) + + if m.Rcode == dns.RcodeServerFailure { + if err := w.WriteMsg(m); err != nil { + logf("failure to return reply %q", err) + } + return + } + // Set TTL to the minimum of the RRset and dedup the message, i.e. remove identical RRs. + m = s.dedup(m) + + minttl := s.config.Ttl + if len(m.Answer) > 1 { + for _, r := range m.Answer { + if r.Header().Ttl < minttl { + minttl = r.Header().Ttl + } + } + for _, r := range m.Answer { + r.Header().Ttl = minttl + } + } + + if dnssec { + if s.config.PubKey != nil { + m.AuthenticatedData = true + s.Denial(m) + s.Sign(m, bufsize) + } + } + + if send := s.overflowOrTruncated(w, m, int(bufsize), metrics.Auth); send { + return + } + + s.rcache.InsertMessage(cache.Key(q, dnssec, tcp), m) + + if err := w.WriteMsg(m); err != nil { + logf("failure to return reply %q", err) + } + }() + + if name == s.config.Domain { + if q.Qtype == dns.TypeSOA { + m.Answer = []dns.RR{s.NewSOA()} + return + } + if q.Qtype == dns.TypeDNSKEY { + if s.config.PubKey != nil { + m.Answer = []dns.RR{s.config.PubKey} + return + } + } + } + if q.Qclass == dns.ClassCHAOS { + if q.Qtype == dns.TypeTXT { + switch name { + case "authors.bind.": + fallthrough + case s.config.Domain: + hdr := dns.RR_Header{Name: q.Name, Rrtype: dns.TypeTXT, Class: dns.ClassCHAOS, Ttl: 0} + authors := []string{"Erik St. Martin", "Brian Ketelsen", "Miek Gieben", "Michael Crosby"} + for _, a := range authors { + m.Answer = append(m.Answer, &dns.TXT{Hdr: hdr, Txt: []string{a}}) + } + for j := 0; j < len(authors)*(int(dns.Id())%4+1); j++ { + q := int(dns.Id()) % len(authors) + p := int(dns.Id()) % len(authors) + if q == p { + p = (p + 1) % len(authors) + } + m.Answer[q], m.Answer[p] = m.Answer[p], m.Answer[q] + } + return + case "version.bind.": + fallthrough + case "version.server.": + hdr := dns.RR_Header{Name: q.Name, Rrtype: dns.TypeTXT, Class: dns.ClassCHAOS, Ttl: 0} + m.Answer = []dns.RR{&dns.TXT{Hdr: hdr, Txt: []string{Version}}} + return + case "hostname.bind.": + fallthrough + case "id.server.": + // TODO(miek): machine name to return + hdr := dns.RR_Header{Name: q.Name, Rrtype: dns.TypeTXT, Class: dns.ClassCHAOS, Ttl: 0} + m.Answer = []dns.RR{&dns.TXT{Hdr: hdr, Txt: []string{"localhost"}}} + return + } + } + // still here, fail + m.SetReply(req) + m.SetRcode(req, dns.RcodeServerFailure) + return + } + + switch q.Qtype { + case dns.TypeNS: + if name != s.config.Domain { + break + } + // Lookup s.config.DnsDomain + records, extra, err := s.NSRecords(q, s.config.dnsDomain) + if isEtcdNameError(err, s) { + m = s.NameError(req) + return + } + m.Answer = append(m.Answer, records...) + m.Extra = append(m.Extra, extra...) + case dns.TypeA, dns.TypeAAAA: + records, err := s.AddressRecords(q, name, nil, bufsize, dnssec, false) + if isEtcdNameError(err, s) { + m = s.NameError(req) + return + } + m.Answer = append(m.Answer, records...) + case dns.TypeTXT: + records, err := s.TXTRecords(q, name) + if isEtcdNameError(err, s) { + m = s.NameError(req) + return + } + m.Answer = append(m.Answer, records...) + case dns.TypeCNAME: + records, err := s.CNAMERecords(q, name) + if isEtcdNameError(err, s) { + m = s.NameError(req) + return + } + m.Answer = append(m.Answer, records...) + case dns.TypeMX: + records, extra, err := s.MXRecords(q, name, bufsize, dnssec) + if isEtcdNameError(err, s) { + m = s.NameError(req) + return + } + m.Answer = append(m.Answer, records...) + m.Extra = append(m.Extra, extra...) + default: + fallthrough // also catch other types, so that they return NODATA + case dns.TypeSRV: + records, extra, err := s.SRVRecords(q, name, bufsize, dnssec) + if err != nil { + if isEtcdNameError(err, s) { + m = s.NameError(req) + return + } + logf("got error from backend: %s", err) + if q.Qtype == dns.TypeSRV { // Otherwise NODATA + m = s.ServerFailure(req) + return + } + } + // if we are here again, check the types, because an answer may only + // be given for SRV. All other types should return NODATA, the + // NXDOMAIN part is handled in the above code. TODO(miek): yes this + // can be done in a more elegant manor. + if q.Qtype == dns.TypeSRV { + m.Answer = append(m.Answer, records...) + m.Extra = append(m.Extra, extra...) + } + } + + if len(m.Answer) == 0 { // NODATA response + m.Ns = []dns.RR{s.NewSOA()} + m.Ns[0].Header().Ttl = s.config.MinTtl + } +} + +func (s *server) AddressRecords(q dns.Question, name string, previousRecords []dns.RR, bufsize uint16, dnssec, both bool) (records []dns.RR, err error) { + services, err := s.backend.Records(name, false) + if err != nil { + return nil, err + } + + services = msg.Group(services) + + for _, serv := range services { + ip := net.ParseIP(serv.Host) + switch { + case ip == nil: + // Try to resolve as CNAME if it's not an IP, but only if we don't create loops. + if q.Name == dns.Fqdn(serv.Host) { + // x CNAME x is a direct loop, don't add those + continue + } + + newRecord := serv.NewCNAME(q.Name, dns.Fqdn(serv.Host)) + if len(previousRecords) > 7 { + logf("CNAME lookup limit of 8 exceeded for %s", newRecord) + // don't add it, and just continue + continue + } + if s.isDuplicateCNAME(newRecord, previousRecords) { + logf("CNAME loop detected for record %s", newRecord) + continue + } + + nextRecords, err := s.AddressRecords(dns.Question{Name: dns.Fqdn(serv.Host), Qtype: q.Qtype, Qclass: q.Qclass}, + strings.ToLower(dns.Fqdn(serv.Host)), append(previousRecords, newRecord), bufsize, dnssec, both) + if err == nil { + // Only have we found something we should add the CNAME and the IP addresses. + if len(nextRecords) > 0 { + records = append(records, newRecord) + records = append(records, nextRecords...) + } + continue + } + // This means we can not complete the CNAME, try to look else where. + target := newRecord.Target + if dns.IsSubDomain(s.config.Domain, target) { + // We should already have found it + continue + } + m1, e1 := s.Lookup(target, q.Qtype, bufsize, dnssec) + if e1 != nil { + logf("incomplete CNAME chain: %s", e1) + continue + } + // Len(m1.Answer) > 0 here is well? + records = append(records, newRecord) + records = append(records, m1.Answer...) + continue + case ip.To4() != nil && (q.Qtype == dns.TypeA || both): + records = append(records, serv.NewA(q.Name, ip.To4())) + case ip.To4() == nil && (q.Qtype == dns.TypeAAAA || both): + records = append(records, serv.NewAAAA(q.Name, ip.To16())) + } + } + s.RoundRobin(records) + return records, nil +} + +// NSRecords returns NS records from etcd. +func (s *server) NSRecords(q dns.Question, name string) (records []dns.RR, extra []dns.RR, err error) { + services, err := s.backend.Records(name, false) + if err != nil { + return nil, nil, err + } + + services = msg.Group(services) + + for _, serv := range services { + ip := net.ParseIP(serv.Host) + switch { + case ip == nil: + return nil, nil, fmt.Errorf("NS record must be an IP address") + case ip.To4() != nil: + serv.Host = msg.Domain(serv.Key) + records = append(records, serv.NewNS(q.Name, serv.Host)) + extra = append(extra, serv.NewA(serv.Host, ip.To4())) + case ip.To4() == nil: + serv.Host = msg.Domain(serv.Key) + records = append(records, serv.NewNS(q.Name, serv.Host)) + extra = append(extra, serv.NewAAAA(serv.Host, ip.To16())) + } + } + return records, extra, nil +} + +// SRVRecords returns SRV records from etcd. +// If the Target is not a name but an IP address, a name is created. +func (s *server) SRVRecords(q dns.Question, name string, bufsize uint16, dnssec bool) (records []dns.RR, extra []dns.RR, err error) { + services, err := s.backend.Records(name, false) + if err != nil { + return nil, nil, err + } + + services = msg.Group(services) + + // Looping twice to get the right weight vs priority + w := make(map[int]int) + for _, serv := range services { + weight := 100 + if serv.Weight != 0 { + weight = serv.Weight + } + if _, ok := w[serv.Priority]; !ok { + w[serv.Priority] = weight + continue + } + w[serv.Priority] += weight + } + lookup := make(map[string]bool) + for _, serv := range services { + w1 := 100.0 / float64(w[serv.Priority]) + if serv.Weight == 0 { + w1 *= 100 + } else { + w1 *= float64(serv.Weight) + } + weight := uint16(math.Floor(w1)) + ip := net.ParseIP(serv.Host) + switch { + case ip == nil: + srv := serv.NewSRV(q.Name, weight) + records = append(records, srv) + + if _, ok := lookup[srv.Target]; ok { + break + } + + lookup[srv.Target] = true + + if !dns.IsSubDomain(s.config.Domain, srv.Target) { + m1, e1 := s.Lookup(srv.Target, dns.TypeA, bufsize, dnssec) + if e1 == nil { + extra = append(extra, m1.Answer...) + } + m1, e1 = s.Lookup(srv.Target, dns.TypeAAAA, bufsize, dnssec) + if e1 == nil { + // If we have seen CNAME's we *assume* that they are already added. + for _, a := range m1.Answer { + if _, ok := a.(*dns.CNAME); !ok { + extra = append(extra, a) + } + } + } + break + } + // Internal name, we should have some info on them, either v4 or v6 + // Clients expect a complete answer, because we are a recursor in their + // view. + addr, e1 := s.AddressRecords(dns.Question{srv.Target, dns.ClassINET, dns.TypeA}, + srv.Target, nil, bufsize, dnssec, true) + if e1 == nil { + extra = append(extra, addr...) + } + case ip.To4() != nil: + serv.Host = msg.Domain(serv.Key) + srv := serv.NewSRV(q.Name, weight) + + records = append(records, srv) + extra = append(extra, serv.NewA(srv.Target, ip.To4())) + case ip.To4() == nil: + serv.Host = msg.Domain(serv.Key) + srv := serv.NewSRV(q.Name, weight) + + records = append(records, srv) + extra = append(extra, serv.NewAAAA(srv.Target, ip.To16())) + } + } + return records, extra, nil +} + +// MXRecords returns MX records from etcd. +// If the Target is not a name but an IP address, a name is created. +func (s *server) MXRecords(q dns.Question, name string, bufsize uint16, dnssec bool) (records []dns.RR, extra []dns.RR, err error) { + services, err := s.backend.Records(name, false) + if err != nil { + return nil, nil, err + } + + lookup := make(map[string]bool) + for _, serv := range services { + if !serv.Mail { + continue + } + ip := net.ParseIP(serv.Host) + switch { + case ip == nil: + mx := serv.NewMX(q.Name) + records = append(records, mx) + if _, ok := lookup[mx.Mx]; ok { + break + } + + lookup[mx.Mx] = true + + if !dns.IsSubDomain(s.config.Domain, mx.Mx) { + m1, e1 := s.Lookup(mx.Mx, dns.TypeA, bufsize, dnssec) + if e1 == nil { + extra = append(extra, m1.Answer...) + } + m1, e1 = s.Lookup(mx.Mx, dns.TypeAAAA, bufsize, dnssec) + if e1 == nil { + // If we have seen CNAME's we *assume* that they are already added. + for _, a := range m1.Answer { + if _, ok := a.(*dns.CNAME); !ok { + extra = append(extra, a) + } + } + } + break + } + // Internal name + addr, e1 := s.AddressRecords(dns.Question{mx.Mx, dns.ClassINET, dns.TypeA}, + mx.Mx, nil, bufsize, dnssec, true) + if e1 == nil { + extra = append(extra, addr...) + } + case ip.To4() != nil: + serv.Host = msg.Domain(serv.Key) + records = append(records, serv.NewMX(q.Name)) + extra = append(extra, serv.NewA(serv.Host, ip.To4())) + case ip.To4() == nil: + serv.Host = msg.Domain(serv.Key) + records = append(records, serv.NewMX(q.Name)) + extra = append(extra, serv.NewAAAA(serv.Host, ip.To16())) + } + } + return records, extra, nil +} + +func (s *server) CNAMERecords(q dns.Question, name string) (records []dns.RR, err error) { + services, err := s.backend.Records(name, true) + if err != nil { + return nil, err + } + + services = msg.Group(services) + + if len(services) > 0 { + serv := services[0] + if ip := net.ParseIP(serv.Host); ip == nil { + records = append(records, serv.NewCNAME(q.Name, dns.Fqdn(serv.Host))) + } + } + return records, nil +} + +func (s *server) TXTRecords(q dns.Question, name string) (records []dns.RR, err error) { + services, err := s.backend.Records(name, false) + if err != nil { + return nil, err + } + + services = msg.Group(services) + + for _, serv := range services { + if serv.Text == "" { + continue + } + records = append(records, serv.NewTXT(q.Name)) + } + return records, nil +} + +func (s *server) PTRRecords(q dns.Question) (records []dns.RR, err error) { + name := strings.ToLower(q.Name) + serv, err := s.backend.ReverseRecord(name) + if err != nil { + return nil, err + } + + records = append(records, serv.NewPTR(q.Name, serv.Ttl)) + return records, nil +} + +// SOA returns a SOA record for this SkyDNS instance. +func (s *server) NewSOA() dns.RR { + return &dns.SOA{Hdr: dns.RR_Header{Name: s.config.Domain, Rrtype: dns.TypeSOA, Class: dns.ClassINET, Ttl: s.config.Ttl}, + Ns: appendDomain("ns.dns", s.config.Domain), + Mbox: s.config.Hostmaster, + Serial: uint32(time.Now().Truncate(time.Hour).Unix()), + Refresh: 28800, + Retry: 7200, + Expire: 604800, + Minttl: s.config.MinTtl, + } +} + +func (s *server) isDuplicateCNAME(r *dns.CNAME, records []dns.RR) bool { + for _, rec := range records { + if v, ok := rec.(*dns.CNAME); ok { + if v.Target == r.Target { + return true + } + } + } + return false +} + +func (s *server) NameError(req *dns.Msg) *dns.Msg { + m := new(dns.Msg) + m.SetRcode(req, dns.RcodeNameError) + m.Ns = []dns.RR{s.NewSOA()} + m.Ns[0].Header().Ttl = s.config.MinTtl + return m +} + +func (s *server) ServerFailure(req *dns.Msg) *dns.Msg { + m := new(dns.Msg) + m.SetRcode(req, dns.RcodeServerFailure) + return m +} + +func (s *server) RoundRobin(rrs []dns.RR) { + if !s.config.RoundRobin { + return + } + // If we have more than 1 CNAME don't touch the packet, because some stub resolver (=glibc) + // can't deal with the returned packet if the CNAMEs need to be accesses in the reverse order. + cname := 0 + for _, r := range rrs { + if r.Header().Rrtype == dns.TypeCNAME { + cname++ + if cname > 1 { + return + } + } + } + + switch l := len(rrs); l { + case 2: + if dns.Id()%2 == 0 { + rrs[0], rrs[1] = rrs[1], rrs[0] + } + default: + for j := 0; j < l*(int(dns.Id())%4+1); j++ { + q := int(dns.Id()) % l + p := int(dns.Id()) % l + if q == p { + p = (p + 1) % l + } + rrs[q], rrs[p] = rrs[p], rrs[q] + } + } + +} + +// dedup will de-duplicate a message on a per section basis. +// Multiple identical (same name, class, type and rdata) RRs will be coalesced into one. +func (s *server) dedup(m *dns.Msg) *dns.Msg { + // Answer section + ma := make(map[string]dns.RR) + for _, a := range m.Answer { + // Or use Pack()... Think this function also could be placed in go dns. + s1 := a.Header().Name + s1 += strconv.Itoa(int(a.Header().Class)) + s1 += strconv.Itoa(int(a.Header().Rrtype)) + // there can only be one CNAME for an ownername + if a.Header().Rrtype == dns.TypeCNAME { + if _, ok := ma[s1]; ok { + // already exist, randomly overwrite if roundrobin is true + // Note: even with roundrobin *off* this depends on the + // order we get the names. + if s.config.RoundRobin && dns.Id()%2 == 0 { + ma[s1] = a + continue + } + } + ma[s1] = a + continue + } + for i := 1; i <= dns.NumField(a); i++ { + s1 += dns.Field(a, i) + } + ma[s1] = a + } + // Only is our map is smaller than the #RR in the answer section we should reset the RRs + // in the section it self + if len(ma) < len(m.Answer) { + i := 0 + for _, v := range ma { + m.Answer[i] = v + i++ + } + m.Answer = m.Answer[:len(ma)] + } + + // Additional section + me := make(map[string]dns.RR) + for _, e := range m.Extra { + s1 := e.Header().Name + s1 += strconv.Itoa(int(e.Header().Class)) + s1 += strconv.Itoa(int(e.Header().Rrtype)) + // there can only be one CNAME for an ownername + if e.Header().Rrtype == dns.TypeCNAME { + if _, ok := me[s1]; ok { + // already exist, randomly overwrite if roundrobin is true + if s.config.RoundRobin && dns.Id()%2 == 0 { + me[s1] = e + continue + } + } + me[s1] = e + continue + } + for i := 1; i <= dns.NumField(e); i++ { + s1 += dns.Field(e, i) + } + me[s1] = e + } + + if len(me) < len(m.Extra) { + i := 0 + for _, v := range me { + m.Extra[i] = v + i++ + } + m.Extra = m.Extra[:len(me)] + } + + return m +} + +// overflowOrTruncated writes back an error to the client if the message does not fit. +// It updates prometheus metrics. If something has been written to the client, true +// will be returned. +func (s *server) overflowOrTruncated(w dns.ResponseWriter, m *dns.Msg, bufsize int, sy metrics.System) bool { + switch isTCP(w) { + case true: + if _, overflow := Fit(m, dns.MaxMsgSize, true); overflow { + metrics.ReportErrorCount(m, sy) + msgFail := s.ServerFailure(m) + w.WriteMsg(msgFail) + return true + } + case false: + // Overflow with udp always results in TC. + Fit(m, bufsize, false) + metrics.ReportErrorCount(m, sy) + if m.Truncated { + w.WriteMsg(m) + return true + } + } + return false +} + +// isTCP returns true if the client is connecting over TCP. +func isTCP(w dns.ResponseWriter) bool { + _, ok := w.RemoteAddr().(*net.TCPAddr) + return ok +} + +// etcNameError return a NameError to the client if the error +// returned from etcd has ErrorCode == 100. +func isEtcdNameError(err error, s *server) bool { + if e, ok := err.(etcd.Error); ok && e.Code == etcd.ErrorCodeKeyNotFound { + return true + } + if err != nil { + logf("error from backend: %s", err) + } + return false +} diff --git a/vendor/github.com/skynetservices/skydns/server/stub.go b/vendor/github.com/skynetservices/skydns/server/stub.go new file mode 100644 index 00000000000..6e8b38c0cac --- /dev/null +++ b/vendor/github.com/skynetservices/skydns/server/stub.go @@ -0,0 +1,124 @@ +// Copyright (c) 2014 The SkyDNS Authors. All rights reserved. +// Use of this source code is governed by The MIT License (MIT) that can be +// found in the LICENSE file. + +package server + +import ( + "net" + "strconv" + "strings" + + "github.com/miekg/dns" + "github.com/skynetservices/skydns/msg" +) + +const ednsStubCode = dns.EDNS0LOCALSTART + 10 + +// ednsStub is the EDNS0 record we add to stub queries. Queries which have this record are +// not forwarded again. +var ednsStub = func() *dns.OPT { + o := new(dns.OPT) + o.Hdr.Name = "." + o.Hdr.Rrtype = dns.TypeOPT + e := new(dns.EDNS0_LOCAL) + e.Code = ednsStubCode + e.Data = []byte{1} + o.Option = append(o.Option, e) + return o +}() + +// Look in .../dns/stub//xx for msg.Services. Loop through them +// extract and add them as forwarders (ip:port-combos) for +// the stub zones. Only numeric (i.e. IP address) hosts are used. +func (s *server) UpdateStubZones() { + stubmap := make(map[string][]string) + + services, err := s.backend.Records("stub.dns."+s.config.Domain, false) + if err != nil { + logf("stub zone update failed: %s", err) + return + } + for _, serv := range services { + if serv.Port == 0 { + serv.Port = 53 + } + ip := net.ParseIP(serv.Host) + if ip == nil { + logf("stub zone non-address %s seen for: %s", serv.Key, serv.Host) + continue + } + + domain := msg.Domain(serv.Key) + // Chop of left most label, because that is used as the nameserver place holder + // and drop the right most labels that belong to localDomain. + labels := dns.SplitDomainName(domain) + domain = dns.Fqdn(strings.Join(labels[1:len(labels)-dns.CountLabel(s.config.localDomain)], ".")) + + // If the remaining name equals s.config.LocalDomain we ignore it. + if domain == s.config.localDomain { + logf("not adding stub zone for my own domain") + continue + } + stubmap[domain] = append(stubmap[domain], net.JoinHostPort(serv.Host, strconv.Itoa(serv.Port))) + } + + s.config.stub = &stubmap +} + +// ServeDNSStubForward forwards a request to a nameservers and returns the response. +func (s *server) ServeDNSStubForward(w dns.ResponseWriter, req *dns.Msg, ns []string) *dns.Msg { + // Check EDNS0 Stub option, if set drop the packet. + option := req.IsEdns0() + if option != nil { + for _, o := range option.Option { + if o.Option() == ednsStubCode && len(o.(*dns.EDNS0_LOCAL).Data) == 1 && + o.(*dns.EDNS0_LOCAL).Data[0] == 1 { + // Maybe log source IP here? + logf("not fowarding stub request to another stub") + return nil + } + } + } + + // Add a custom EDNS0 option to the packet, so we can detect loops + // when 2 stubs are forwarding to each other. + if option != nil { + option.Option = append(option.Option, &dns.EDNS0_LOCAL{ednsStubCode, []byte{1}}) + } else { + req.Extra = append(req.Extra, ednsStub) + } + + var ( + r *dns.Msg + err error + ) + + // Use request Id for "random" nameserver selection. + nsid := int(req.Id) % len(ns) + try := 0 +Redo: + if isTCP(w) { + r, err = exchangeWithRetry(s.dnsTCPclient, req, ns[nsid]) + } else { + r, err = exchangeWithRetry(s.dnsUDPclient, req, ns[nsid]) + } + if err == nil { + r.Compress = true + r.Id = req.Id + w.WriteMsg(r) + return r + } + // Seen an error, this can only mean, "server not reached", try again + // but only if we have not exausted our nameservers. + if try < len(ns) { + try++ + nsid = (nsid + 1) % len(ns) + goto Redo + } + + logf("failure to forward stub request %q", err) + m := s.ServerFailure(req) + w.WriteMsg(m) + return m +} diff --git a/vendor/github.com/skynetservices/skydns/singleflight/singleflight.go b/vendor/github.com/skynetservices/skydns/singleflight/singleflight.go new file mode 100644 index 00000000000..ff2c2ee4f3d --- /dev/null +++ b/vendor/github.com/skynetservices/skydns/singleflight/singleflight.go @@ -0,0 +1,64 @@ +/* +Copyright 2012 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package singleflight provides a duplicate function call suppression +// mechanism. +package singleflight + +import "sync" + +// call is an in-flight or completed Do call +type call struct { + wg sync.WaitGroup + val interface{} + err error +} + +// Group represents a class of work and forms a namespace in which +// units of work can be executed with duplicate suppression. +type Group struct { + mu sync.Mutex // protects m + m map[string]*call // lazily initialized +} + +// Do executes and returns the results of the given function, making +// sure that only one execution is in-flight for a given key at a +// time. If a duplicate comes in, the duplicate caller waits for the +// original to complete and receives the same results. +func (g *Group) Do(key string, fn func() (interface{}, error)) (interface{}, error) { + g.mu.Lock() + if g.m == nil { + g.m = make(map[string]*call) + } + if c, ok := g.m[key]; ok { + g.mu.Unlock() + c.wg.Wait() + return c.val, c.err + } + c := new(call) + c.wg.Add(1) + g.m[key] = c + g.mu.Unlock() + + c.val, c.err = fn() + c.wg.Done() + + g.mu.Lock() + delete(g.m, key) + g.mu.Unlock() + + return c.val, c.err +}