Update miekg/dns and golang/protobuf. (#4150)
Precursor to #4116. Since some of our dependencies impose a minimum version on these two packages higher than what we have in Godeps, we'll have to bump them anyhow. Bumping them independently of the modules update should keep things a little simpler. In order to get protobuf tests to pass, I had to update protoc-gen-go in boulder-tools. Now we download a prebuilt binary instead of using the Ubuntu package, which is stuck on 3.0.0. This also meant I needed to re-generate our pb.go files, since the new version generates somewhat different output. This happens to change the tag for pbutil, but it's not a substantive change - they just added a tagged version where there was none. $ go test github.com/miekg/dns/... ok github.com/miekg/dns 4.675s ok github.com/miekg/dns/dnsutil 0.003s ok github.com/golang/protobuf/descriptor (cached) ok github.com/golang/protobuf/jsonpb (cached) ? github.com/golang/protobuf/jsonpb/jsonpb_test_proto [no test files] ok github.com/golang/protobuf/proto (cached) ? github.com/golang/protobuf/proto/proto3_proto [no test files] ? github.com/golang/protobuf/proto/test_proto [no test files] ok github.com/golang/protobuf/protoc-gen-go (cached) ? github.com/golang/protobuf/protoc-gen-go/descriptor [no test files] ok github.com/golang/protobuf/protoc-gen-go/generator (cached) ok github.com/golang/protobuf/protoc-gen-go/generator/internal/remap (cached) ? github.com/golang/protobuf/protoc-gen-go/grpc [no test files] ? github.com/golang/protobuf/protoc-gen-go/plugin [no test files] ok github.com/golang/protobuf/ptypes (cached) ? github.com/golang/protobuf/ptypes/any [no test files] ? github.com/golang/protobuf/ptypes/duration [no test files] ? github.com/golang/protobuf/ptypes/empty [no test files] ? github.com/golang/protobuf/ptypes/struct [no test files] ? github.com/golang/protobuf/ptypes/timestamp [no test files] ? github.com/golang/protobuf/ptypes/wrappers [no test files]
This commit is contained in:
parent
de15c267d0
commit
d2d5f0a328
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"ImportPath": "github.com/letsencrypt/boulder",
|
||||
"GoVersion": "go1.11",
|
||||
"GoVersion": "go1.12",
|
||||
"GodepVersion": "v80",
|
||||
"Packages": [
|
||||
"./..."
|
||||
|
|
@ -122,28 +122,28 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/protobuf/proto",
|
||||
"Comment": "v1.1.0",
|
||||
"Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265"
|
||||
"Comment": "v1.3.1",
|
||||
"Rev": "b5d812f8a3706043e23a9cd5babf2e5423744d30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/protobuf/ptypes",
|
||||
"Comment": "v1.1.0",
|
||||
"Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265"
|
||||
"Comment": "v1.3.1",
|
||||
"Rev": "b5d812f8a3706043e23a9cd5babf2e5423744d30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/protobuf/ptypes/any",
|
||||
"Comment": "v1.1.0",
|
||||
"Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265"
|
||||
"Comment": "v1.3.1",
|
||||
"Rev": "b5d812f8a3706043e23a9cd5babf2e5423744d30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/protobuf/ptypes/duration",
|
||||
"Comment": "v1.1.0",
|
||||
"Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265"
|
||||
"Comment": "v1.3.1",
|
||||
"Rev": "b5d812f8a3706043e23a9cd5babf2e5423744d30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/protobuf/ptypes/timestamp",
|
||||
"Comment": "v1.1.0",
|
||||
"Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265"
|
||||
"Comment": "v1.3.1",
|
||||
"Rev": "b5d812f8a3706043e23a9cd5babf2e5423744d30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/snappy",
|
||||
|
|
@ -225,12 +225,13 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "github.com/matttproud/golang_protobuf_extensions/pbutil",
|
||||
"Comment": "v1.0.0-2-gc12348c",
|
||||
"Comment": "v1.0.1",
|
||||
"Rev": "c12348ce28de40eed0136aa2b644d0ee0650e56c"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/miekg/dns",
|
||||
"Rev": "031fad65fea12748347cbb2a30f190b6257fc844"
|
||||
"Comment": "v1.1.8",
|
||||
"Rev": "73601d4aed9d844322611759d7f3619110b7c88e"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/miekg/pkcs11",
|
||||
|
|
|
|||
|
|
@ -1,30 +1,21 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: akamai/proto/akamai.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package proto is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
akamai/proto/akamai.proto
|
||||
|
||||
It has these top-level messages:
|
||||
PurgeRequest
|
||||
*/
|
||||
package proto
|
||||
|
||||
import proto1 "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import core "github.com/letsencrypt/boulder/core/proto"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
proto1 "github.com/letsencrypt/boulder/core/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto1.Marshal
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
|
|
@ -32,17 +23,39 @@ var _ = math.Inf
|
|||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto1.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type PurgeRequest struct {
|
||||
Urls []string `protobuf:"bytes,1,rep,name=urls" json:"urls,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Urls []string `protobuf:"bytes,1,rep,name=urls" json:"urls,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *PurgeRequest) Reset() { *m = PurgeRequest{} }
|
||||
func (m *PurgeRequest) String() string { return proto1.CompactTextString(m) }
|
||||
func (*PurgeRequest) ProtoMessage() {}
|
||||
func (*PurgeRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
func (m *PurgeRequest) Reset() { *m = PurgeRequest{} }
|
||||
func (m *PurgeRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*PurgeRequest) ProtoMessage() {}
|
||||
func (*PurgeRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_97376b3b31deb04b, []int{0}
|
||||
}
|
||||
|
||||
func (m *PurgeRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PurgeRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *PurgeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_PurgeRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *PurgeRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PurgeRequest.Merge(m, src)
|
||||
}
|
||||
func (m *PurgeRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_PurgeRequest.Size(m)
|
||||
}
|
||||
func (m *PurgeRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_PurgeRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_PurgeRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *PurgeRequest) GetUrls() []string {
|
||||
if m != nil {
|
||||
|
|
@ -52,7 +65,22 @@ func (m *PurgeRequest) GetUrls() []string {
|
|||
}
|
||||
|
||||
func init() {
|
||||
proto1.RegisterType((*PurgeRequest)(nil), "akamai.PurgeRequest")
|
||||
proto.RegisterType((*PurgeRequest)(nil), "akamai.PurgeRequest")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("akamai/proto/akamai.proto", fileDescriptor_97376b3b31deb04b) }
|
||||
|
||||
var fileDescriptor_97376b3b31deb04b = []byte{
|
||||
// 133 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcc, 0x4e, 0xcc,
|
||||
0x4d, 0xcc, 0xd4, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0xd7, 0x87, 0x70, 0xf4, 0xc0, 0x1c, 0x21, 0x36,
|
||||
0x08, 0x4f, 0x4a, 0x34, 0x39, 0xbf, 0x28, 0x15, 0xaa, 0x00, 0xc4, 0x84, 0x48, 0x2b, 0x29, 0x71,
|
||||
0xf1, 0x04, 0x94, 0x16, 0xa5, 0xa7, 0x06, 0xa5, 0x16, 0x96, 0xa6, 0x16, 0x97, 0x08, 0x09, 0x71,
|
||||
0xb1, 0x94, 0x16, 0xe5, 0x14, 0x4b, 0x30, 0x2a, 0x30, 0x6b, 0x70, 0x06, 0x81, 0xd9, 0x46, 0x36,
|
||||
0x5c, 0x3c, 0x8e, 0x60, 0x43, 0xc0, 0x2a, 0x8b, 0x84, 0x74, 0xb8, 0x58, 0xc1, 0x2c, 0x21, 0x11,
|
||||
0x3d, 0xa8, 0x55, 0xc8, 0x46, 0x48, 0x71, 0xeb, 0x81, 0xcd, 0x77, 0xcd, 0x2d, 0x28, 0xa9, 0x54,
|
||||
0x62, 0x70, 0x62, 0x8f, 0x62, 0x05, 0x5b, 0x05, 0x08, 0x00, 0x00, 0xff, 0xff, 0xe8, 0x1f, 0x67,
|
||||
0x30, 0xa5, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
@ -63,10 +91,11 @@ var _ grpc.ClientConn
|
|||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// Client API for AkamaiPurger service
|
||||
|
||||
// AkamaiPurgerClient is the client API for AkamaiPurger service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type AkamaiPurgerClient interface {
|
||||
Purge(ctx context.Context, in *PurgeRequest, opts ...grpc.CallOption) (*core.Empty, error)
|
||||
Purge(ctx context.Context, in *PurgeRequest, opts ...grpc.CallOption) (*proto1.Empty, error)
|
||||
}
|
||||
|
||||
type akamaiPurgerClient struct {
|
||||
|
|
@ -77,19 +106,26 @@ func NewAkamaiPurgerClient(cc *grpc.ClientConn) AkamaiPurgerClient {
|
|||
return &akamaiPurgerClient{cc}
|
||||
}
|
||||
|
||||
func (c *akamaiPurgerClient) Purge(ctx context.Context, in *PurgeRequest, opts ...grpc.CallOption) (*core.Empty, error) {
|
||||
out := new(core.Empty)
|
||||
err := grpc.Invoke(ctx, "/akamai.AkamaiPurger/Purge", in, out, c.cc, opts...)
|
||||
func (c *akamaiPurgerClient) Purge(ctx context.Context, in *PurgeRequest, opts ...grpc.CallOption) (*proto1.Empty, error) {
|
||||
out := new(proto1.Empty)
|
||||
err := c.cc.Invoke(ctx, "/akamai.AkamaiPurger/Purge", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for AkamaiPurger service
|
||||
|
||||
// AkamaiPurgerServer is the server API for AkamaiPurger service.
|
||||
type AkamaiPurgerServer interface {
|
||||
Purge(context.Context, *PurgeRequest) (*core.Empty, error)
|
||||
Purge(context.Context, *PurgeRequest) (*proto1.Empty, error)
|
||||
}
|
||||
|
||||
// UnimplementedAkamaiPurgerServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedAkamaiPurgerServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedAkamaiPurgerServer) Purge(ctx context.Context, req *PurgeRequest) (*proto1.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Purge not implemented")
|
||||
}
|
||||
|
||||
func RegisterAkamaiPurgerServer(s *grpc.Server, srv AkamaiPurgerServer) {
|
||||
|
|
@ -126,18 +162,3 @@ var _AkamaiPurger_serviceDesc = grpc.ServiceDesc{
|
|||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "akamai/proto/akamai.proto",
|
||||
}
|
||||
|
||||
func init() { proto1.RegisterFile("akamai/proto/akamai.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 133 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcc, 0x4e, 0xcc,
|
||||
0x4d, 0xcc, 0xd4, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0xd7, 0x87, 0x70, 0xf4, 0xc0, 0x1c, 0x21, 0x36,
|
||||
0x08, 0x4f, 0x4a, 0x34, 0x39, 0xbf, 0x28, 0x15, 0xaa, 0x00, 0xc4, 0x84, 0x48, 0x2b, 0x29, 0x71,
|
||||
0xf1, 0x04, 0x94, 0x16, 0xa5, 0xa7, 0x06, 0xa5, 0x16, 0x96, 0xa6, 0x16, 0x97, 0x08, 0x09, 0x71,
|
||||
0xb1, 0x94, 0x16, 0xe5, 0x14, 0x4b, 0x30, 0x2a, 0x30, 0x6b, 0x70, 0x06, 0x81, 0xd9, 0x46, 0x36,
|
||||
0x5c, 0x3c, 0x8e, 0x60, 0x43, 0xc0, 0x2a, 0x8b, 0x84, 0x74, 0xb8, 0x58, 0xc1, 0x2c, 0x21, 0x11,
|
||||
0x3d, 0xa8, 0x55, 0xc8, 0x46, 0x48, 0x71, 0xeb, 0x81, 0xcd, 0x77, 0xcd, 0x2d, 0x28, 0xa9, 0x54,
|
||||
0x62, 0x70, 0x62, 0x8f, 0x62, 0x05, 0x5b, 0x05, 0x08, 0x00, 0x00, 0xff, 0xff, 0xe8, 0x1f, 0x67,
|
||||
0x30, 0xa5, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,34 +1,21 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: ca/proto/ca.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package proto is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
ca/proto/ca.proto
|
||||
|
||||
It has these top-level messages:
|
||||
IssueCertificateRequest
|
||||
IssuePrecertificateResponse
|
||||
IssueCertificateForPrecertificateRequest
|
||||
GenerateOCSPRequest
|
||||
OCSPResponse
|
||||
*/
|
||||
package proto
|
||||
|
||||
import proto1 "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import core "github.com/letsencrypt/boulder/core/proto"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
proto1 "github.com/letsencrypt/boulder/core/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto1.Marshal
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
|
|
@ -36,19 +23,41 @@ var _ = math.Inf
|
|||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto1.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type IssueCertificateRequest struct {
|
||||
Csr []byte `protobuf:"bytes,1,opt,name=csr" json:"csr,omitempty"`
|
||||
RegistrationID *int64 `protobuf:"varint,2,opt,name=registrationID" json:"registrationID,omitempty"`
|
||||
OrderID *int64 `protobuf:"varint,3,opt,name=orderID" json:"orderID,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Csr []byte `protobuf:"bytes,1,opt,name=csr" json:"csr,omitempty"`
|
||||
RegistrationID *int64 `protobuf:"varint,2,opt,name=registrationID" json:"registrationID,omitempty"`
|
||||
OrderID *int64 `protobuf:"varint,3,opt,name=orderID" json:"orderID,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *IssueCertificateRequest) Reset() { *m = IssueCertificateRequest{} }
|
||||
func (m *IssueCertificateRequest) String() string { return proto1.CompactTextString(m) }
|
||||
func (*IssueCertificateRequest) ProtoMessage() {}
|
||||
func (*IssueCertificateRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
func (m *IssueCertificateRequest) Reset() { *m = IssueCertificateRequest{} }
|
||||
func (m *IssueCertificateRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*IssueCertificateRequest) ProtoMessage() {}
|
||||
func (*IssueCertificateRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_8f9fdc2529716820, []int{0}
|
||||
}
|
||||
|
||||
func (m *IssueCertificateRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_IssueCertificateRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *IssueCertificateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_IssueCertificateRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *IssueCertificateRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_IssueCertificateRequest.Merge(m, src)
|
||||
}
|
||||
func (m *IssueCertificateRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_IssueCertificateRequest.Size(m)
|
||||
}
|
||||
func (m *IssueCertificateRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_IssueCertificateRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_IssueCertificateRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *IssueCertificateRequest) GetCsr() []byte {
|
||||
if m != nil {
|
||||
|
|
@ -72,14 +81,36 @@ func (m *IssueCertificateRequest) GetOrderID() int64 {
|
|||
}
|
||||
|
||||
type IssuePrecertificateResponse struct {
|
||||
DER []byte `protobuf:"bytes,1,opt,name=DER,json=dER" json:"DER,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
DER []byte `protobuf:"bytes,1,opt,name=DER" json:"DER,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *IssuePrecertificateResponse) Reset() { *m = IssuePrecertificateResponse{} }
|
||||
func (m *IssuePrecertificateResponse) String() string { return proto1.CompactTextString(m) }
|
||||
func (*IssuePrecertificateResponse) ProtoMessage() {}
|
||||
func (*IssuePrecertificateResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
func (m *IssuePrecertificateResponse) Reset() { *m = IssuePrecertificateResponse{} }
|
||||
func (m *IssuePrecertificateResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*IssuePrecertificateResponse) ProtoMessage() {}
|
||||
func (*IssuePrecertificateResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_8f9fdc2529716820, []int{1}
|
||||
}
|
||||
|
||||
func (m *IssuePrecertificateResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_IssuePrecertificateResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *IssuePrecertificateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_IssuePrecertificateResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *IssuePrecertificateResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_IssuePrecertificateResponse.Merge(m, src)
|
||||
}
|
||||
func (m *IssuePrecertificateResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_IssuePrecertificateResponse.Size(m)
|
||||
}
|
||||
func (m *IssuePrecertificateResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_IssuePrecertificateResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_IssuePrecertificateResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *IssuePrecertificateResponse) GetDER() []byte {
|
||||
if m != nil {
|
||||
|
|
@ -89,22 +120,42 @@ func (m *IssuePrecertificateResponse) GetDER() []byte {
|
|||
}
|
||||
|
||||
type IssueCertificateForPrecertificateRequest struct {
|
||||
DER []byte `protobuf:"bytes,1,opt,name=DER,json=dER" json:"DER,omitempty"`
|
||||
SCTs [][]byte `protobuf:"bytes,2,rep,name=SCTs,json=sCTs" json:"SCTs,omitempty"`
|
||||
RegistrationID *int64 `protobuf:"varint,3,opt,name=registrationID" json:"registrationID,omitempty"`
|
||||
OrderID *int64 `protobuf:"varint,4,opt,name=orderID" json:"orderID,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
DER []byte `protobuf:"bytes,1,opt,name=DER" json:"DER,omitempty"`
|
||||
SCTs [][]byte `protobuf:"bytes,2,rep,name=SCTs" json:"SCTs,omitempty"`
|
||||
RegistrationID *int64 `protobuf:"varint,3,opt,name=registrationID" json:"registrationID,omitempty"`
|
||||
OrderID *int64 `protobuf:"varint,4,opt,name=orderID" json:"orderID,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *IssueCertificateForPrecertificateRequest) Reset() {
|
||||
*m = IssueCertificateForPrecertificateRequest{}
|
||||
}
|
||||
func (m *IssueCertificateForPrecertificateRequest) String() string { return proto1.CompactTextString(m) }
|
||||
func (m *IssueCertificateForPrecertificateRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*IssueCertificateForPrecertificateRequest) ProtoMessage() {}
|
||||
func (*IssueCertificateForPrecertificateRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor0, []int{2}
|
||||
return fileDescriptor_8f9fdc2529716820, []int{2}
|
||||
}
|
||||
|
||||
func (m *IssueCertificateForPrecertificateRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_IssueCertificateForPrecertificateRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *IssueCertificateForPrecertificateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_IssueCertificateForPrecertificateRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *IssueCertificateForPrecertificateRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_IssueCertificateForPrecertificateRequest.Merge(m, src)
|
||||
}
|
||||
func (m *IssueCertificateForPrecertificateRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_IssueCertificateForPrecertificateRequest.Size(m)
|
||||
}
|
||||
func (m *IssueCertificateForPrecertificateRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_IssueCertificateForPrecertificateRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_IssueCertificateForPrecertificateRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *IssueCertificateForPrecertificateRequest) GetDER() []byte {
|
||||
if m != nil {
|
||||
return m.DER
|
||||
|
|
@ -134,17 +185,39 @@ func (m *IssueCertificateForPrecertificateRequest) GetOrderID() int64 {
|
|||
}
|
||||
|
||||
type GenerateOCSPRequest struct {
|
||||
CertDER []byte `protobuf:"bytes,1,opt,name=certDER" json:"certDER,omitempty"`
|
||||
Status *string `protobuf:"bytes,2,opt,name=status" json:"status,omitempty"`
|
||||
Reason *int32 `protobuf:"varint,3,opt,name=reason" json:"reason,omitempty"`
|
||||
RevokedAt *int64 `protobuf:"varint,4,opt,name=revokedAt" json:"revokedAt,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
CertDER []byte `protobuf:"bytes,1,opt,name=certDER" json:"certDER,omitempty"`
|
||||
Status *string `protobuf:"bytes,2,opt,name=status" json:"status,omitempty"`
|
||||
Reason *int32 `protobuf:"varint,3,opt,name=reason" json:"reason,omitempty"`
|
||||
RevokedAt *int64 `protobuf:"varint,4,opt,name=revokedAt" json:"revokedAt,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *GenerateOCSPRequest) Reset() { *m = GenerateOCSPRequest{} }
|
||||
func (m *GenerateOCSPRequest) String() string { return proto1.CompactTextString(m) }
|
||||
func (*GenerateOCSPRequest) ProtoMessage() {}
|
||||
func (*GenerateOCSPRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
func (m *GenerateOCSPRequest) Reset() { *m = GenerateOCSPRequest{} }
|
||||
func (m *GenerateOCSPRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*GenerateOCSPRequest) ProtoMessage() {}
|
||||
func (*GenerateOCSPRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_8f9fdc2529716820, []int{3}
|
||||
}
|
||||
|
||||
func (m *GenerateOCSPRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GenerateOCSPRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *GenerateOCSPRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_GenerateOCSPRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *GenerateOCSPRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GenerateOCSPRequest.Merge(m, src)
|
||||
}
|
||||
func (m *GenerateOCSPRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_GenerateOCSPRequest.Size(m)
|
||||
}
|
||||
func (m *GenerateOCSPRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GenerateOCSPRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GenerateOCSPRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *GenerateOCSPRequest) GetCertDER() []byte {
|
||||
if m != nil {
|
||||
|
|
@ -175,14 +248,36 @@ func (m *GenerateOCSPRequest) GetRevokedAt() int64 {
|
|||
}
|
||||
|
||||
type OCSPResponse struct {
|
||||
Response []byte `protobuf:"bytes,1,opt,name=response" json:"response,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Response []byte `protobuf:"bytes,1,opt,name=response" json:"response,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *OCSPResponse) Reset() { *m = OCSPResponse{} }
|
||||
func (m *OCSPResponse) String() string { return proto1.CompactTextString(m) }
|
||||
func (*OCSPResponse) ProtoMessage() {}
|
||||
func (*OCSPResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
|
||||
func (m *OCSPResponse) Reset() { *m = OCSPResponse{} }
|
||||
func (m *OCSPResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*OCSPResponse) ProtoMessage() {}
|
||||
func (*OCSPResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_8f9fdc2529716820, []int{4}
|
||||
}
|
||||
|
||||
func (m *OCSPResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_OCSPResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *OCSPResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_OCSPResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *OCSPResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_OCSPResponse.Merge(m, src)
|
||||
}
|
||||
func (m *OCSPResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_OCSPResponse.Size(m)
|
||||
}
|
||||
func (m *OCSPResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_OCSPResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_OCSPResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *OCSPResponse) GetResponse() []byte {
|
||||
if m != nil {
|
||||
|
|
@ -192,11 +287,43 @@ func (m *OCSPResponse) GetResponse() []byte {
|
|||
}
|
||||
|
||||
func init() {
|
||||
proto1.RegisterType((*IssueCertificateRequest)(nil), "ca.IssueCertificateRequest")
|
||||
proto1.RegisterType((*IssuePrecertificateResponse)(nil), "ca.IssuePrecertificateResponse")
|
||||
proto1.RegisterType((*IssueCertificateForPrecertificateRequest)(nil), "ca.IssueCertificateForPrecertificateRequest")
|
||||
proto1.RegisterType((*GenerateOCSPRequest)(nil), "ca.GenerateOCSPRequest")
|
||||
proto1.RegisterType((*OCSPResponse)(nil), "ca.OCSPResponse")
|
||||
proto.RegisterType((*IssueCertificateRequest)(nil), "ca.IssueCertificateRequest")
|
||||
proto.RegisterType((*IssuePrecertificateResponse)(nil), "ca.IssuePrecertificateResponse")
|
||||
proto.RegisterType((*IssueCertificateForPrecertificateRequest)(nil), "ca.IssueCertificateForPrecertificateRequest")
|
||||
proto.RegisterType((*GenerateOCSPRequest)(nil), "ca.GenerateOCSPRequest")
|
||||
proto.RegisterType((*OCSPResponse)(nil), "ca.OCSPResponse")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("ca/proto/ca.proto", fileDescriptor_8f9fdc2529716820) }
|
||||
|
||||
var fileDescriptor_8f9fdc2529716820 = []byte{
|
||||
// 401 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0x41, 0xab, 0xd3, 0x40,
|
||||
0x10, 0x6e, 0x92, 0xf7, 0xac, 0x6f, 0x88, 0xd2, 0xb7, 0x4f, 0x7d, 0x21, 0x15, 0xac, 0x39, 0x48,
|
||||
0x10, 0x49, 0xa1, 0x57, 0x4f, 0xb5, 0xa9, 0x52, 0x10, 0x2c, 0x5b, 0xbd, 0x78, 0x5b, 0xb6, 0x53,
|
||||
0x0d, 0x62, 0xb6, 0xce, 0x6e, 0x04, 0x0f, 0xfe, 0x09, 0x7f, 0x9d, 0x3f, 0x47, 0xb2, 0x4d, 0xda,
|
||||
0x34, 0xa4, 0xf6, 0xf0, 0x6e, 0x33, 0xf3, 0x65, 0xe7, 0xfb, 0xe6, 0x9b, 0x09, 0x5c, 0x4b, 0x31,
|
||||
0xde, 0x92, 0x32, 0x6a, 0x2c, 0x45, 0x62, 0x03, 0xe6, 0x4a, 0x11, 0x3e, 0x96, 0x8a, 0xb0, 0x06,
|
||||
0x14, 0xe1, 0x0e, 0x8a, 0xbe, 0xc3, 0xed, 0x42, 0xeb, 0x02, 0x67, 0x48, 0x26, 0xdb, 0x64, 0x52,
|
||||
0x18, 0xe4, 0xf8, 0xa3, 0x40, 0x6d, 0xd8, 0x00, 0x3c, 0xa9, 0x29, 0x70, 0x46, 0x4e, 0xec, 0xf3,
|
||||
0x32, 0x64, 0x2f, 0xe0, 0x21, 0xe1, 0x97, 0x4c, 0x1b, 0x12, 0x26, 0x53, 0xf9, 0x22, 0x0d, 0xdc,
|
||||
0x91, 0x13, 0x7b, 0xbc, 0x55, 0x65, 0x01, 0xf4, 0x15, 0xad, 0x91, 0x16, 0x69, 0xe0, 0xd9, 0x0f,
|
||||
0xea, 0x34, 0x1a, 0xc3, 0xd0, 0xd2, 0x2d, 0x09, 0x65, 0x93, 0x51, 0x6f, 0x55, 0xae, 0xb1, 0xa4,
|
||||
0x4c, 0xe7, 0xbc, 0xa6, 0x4c, 0xe7, 0x3c, 0xfa, 0xe3, 0x40, 0xdc, 0x16, 0xf8, 0x56, 0x51, 0xfb,
|
||||
0xfd, 0x5e, 0xf1, 0xf1, 0x73, 0xc6, 0xe0, 0x62, 0x35, 0xfb, 0xa8, 0x03, 0x77, 0xe4, 0xc5, 0x3e,
|
||||
0xb7, 0x71, 0xc7, 0x14, 0xde, 0xb9, 0x29, 0x2e, 0x8e, 0xa7, 0xf8, 0x0d, 0x37, 0xef, 0x30, 0x47,
|
||||
0x12, 0x06, 0x3f, 0xcc, 0x56, 0xcb, 0x9a, 0x3e, 0x80, 0x7e, 0x29, 0xea, 0x20, 0xa1, 0x4e, 0xd9,
|
||||
0x13, 0xb8, 0xa7, 0x8d, 0x30, 0x85, 0xb6, 0x86, 0x5d, 0xf1, 0x2a, 0x2b, 0xeb, 0x84, 0x42, 0xab,
|
||||
0xdc, 0x4a, 0xb8, 0xe4, 0x55, 0xc6, 0x9e, 0xc2, 0x15, 0xe1, 0x4f, 0xf5, 0x0d, 0xd7, 0x53, 0x53,
|
||||
0x91, 0x1f, 0x0a, 0xd1, 0x4b, 0xf0, 0x77, 0xb4, 0x95, 0x6b, 0x21, 0xdc, 0xa7, 0x2a, 0xae, 0x88,
|
||||
0xf7, 0xf9, 0xe4, 0xaf, 0x0b, 0x8f, 0x1a, 0xd6, 0x4d, 0x0b, 0xf3, 0x55, 0x51, 0x66, 0x7e, 0xb1,
|
||||
0x14, 0x06, 0x6d, 0x5f, 0xd9, 0x30, 0x91, 0x22, 0x39, 0x71, 0x0e, 0xe1, 0x75, 0x62, 0xcf, 0xa6,
|
||||
0x81, 0x44, 0x3d, 0xf6, 0x09, 0x6e, 0x3a, 0xf6, 0xf9, 0xff, 0x46, 0xcf, 0xf6, 0x60, 0xf7, 0x15,
|
||||
0x44, 0x3d, 0xb6, 0x81, 0xe7, 0x67, 0x97, 0xce, 0x5e, 0x75, 0x91, 0x9c, 0xba, 0x8d, 0x6e, 0xf9,
|
||||
0xaf, 0xc1, 0x6f, 0x2e, 0x92, 0xdd, 0x96, 0x2d, 0x3b, 0x56, 0x1b, 0x0e, 0x4a, 0xa0, 0x69, 0x7a,
|
||||
0xd4, 0x9b, 0xbc, 0x87, 0x07, 0x65, 0xa5, 0xfa, 0x5c, 0xd1, 0x9d, 0xba, 0xbd, 0xe9, 0x7f, 0xbe,
|
||||
0xb4, 0x7f, 0xe4, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x16, 0x23, 0x09, 0x70, 0xc0, 0x03, 0x00,
|
||||
0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
@ -207,12 +334,13 @@ var _ grpc.ClientConn
|
|||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// Client API for CertificateAuthority service
|
||||
|
||||
// CertificateAuthorityClient is the client API for CertificateAuthority service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type CertificateAuthorityClient interface {
|
||||
IssueCertificate(ctx context.Context, in *IssueCertificateRequest, opts ...grpc.CallOption) (*core.Certificate, error)
|
||||
IssueCertificate(ctx context.Context, in *IssueCertificateRequest, opts ...grpc.CallOption) (*proto1.Certificate, error)
|
||||
IssuePrecertificate(ctx context.Context, in *IssueCertificateRequest, opts ...grpc.CallOption) (*IssuePrecertificateResponse, error)
|
||||
IssueCertificateForPrecertificate(ctx context.Context, in *IssueCertificateForPrecertificateRequest, opts ...grpc.CallOption) (*core.Certificate, error)
|
||||
IssueCertificateForPrecertificate(ctx context.Context, in *IssueCertificateForPrecertificateRequest, opts ...grpc.CallOption) (*proto1.Certificate, error)
|
||||
GenerateOCSP(ctx context.Context, in *GenerateOCSPRequest, opts ...grpc.CallOption) (*OCSPResponse, error)
|
||||
}
|
||||
|
||||
|
|
@ -224,9 +352,9 @@ func NewCertificateAuthorityClient(cc *grpc.ClientConn) CertificateAuthorityClie
|
|||
return &certificateAuthorityClient{cc}
|
||||
}
|
||||
|
||||
func (c *certificateAuthorityClient) IssueCertificate(ctx context.Context, in *IssueCertificateRequest, opts ...grpc.CallOption) (*core.Certificate, error) {
|
||||
out := new(core.Certificate)
|
||||
err := grpc.Invoke(ctx, "/ca.CertificateAuthority/IssueCertificate", in, out, c.cc, opts...)
|
||||
func (c *certificateAuthorityClient) IssueCertificate(ctx context.Context, in *IssueCertificateRequest, opts ...grpc.CallOption) (*proto1.Certificate, error) {
|
||||
out := new(proto1.Certificate)
|
||||
err := c.cc.Invoke(ctx, "/ca.CertificateAuthority/IssueCertificate", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -235,16 +363,16 @@ func (c *certificateAuthorityClient) IssueCertificate(ctx context.Context, in *I
|
|||
|
||||
func (c *certificateAuthorityClient) IssuePrecertificate(ctx context.Context, in *IssueCertificateRequest, opts ...grpc.CallOption) (*IssuePrecertificateResponse, error) {
|
||||
out := new(IssuePrecertificateResponse)
|
||||
err := grpc.Invoke(ctx, "/ca.CertificateAuthority/IssuePrecertificate", in, out, c.cc, opts...)
|
||||
err := c.cc.Invoke(ctx, "/ca.CertificateAuthority/IssuePrecertificate", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *certificateAuthorityClient) IssueCertificateForPrecertificate(ctx context.Context, in *IssueCertificateForPrecertificateRequest, opts ...grpc.CallOption) (*core.Certificate, error) {
|
||||
out := new(core.Certificate)
|
||||
err := grpc.Invoke(ctx, "/ca.CertificateAuthority/IssueCertificateForPrecertificate", in, out, c.cc, opts...)
|
||||
func (c *certificateAuthorityClient) IssueCertificateForPrecertificate(ctx context.Context, in *IssueCertificateForPrecertificateRequest, opts ...grpc.CallOption) (*proto1.Certificate, error) {
|
||||
out := new(proto1.Certificate)
|
||||
err := c.cc.Invoke(ctx, "/ca.CertificateAuthority/IssueCertificateForPrecertificate", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -253,22 +381,38 @@ func (c *certificateAuthorityClient) IssueCertificateForPrecertificate(ctx conte
|
|||
|
||||
func (c *certificateAuthorityClient) GenerateOCSP(ctx context.Context, in *GenerateOCSPRequest, opts ...grpc.CallOption) (*OCSPResponse, error) {
|
||||
out := new(OCSPResponse)
|
||||
err := grpc.Invoke(ctx, "/ca.CertificateAuthority/GenerateOCSP", in, out, c.cc, opts...)
|
||||
err := c.cc.Invoke(ctx, "/ca.CertificateAuthority/GenerateOCSP", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for CertificateAuthority service
|
||||
|
||||
// CertificateAuthorityServer is the server API for CertificateAuthority service.
|
||||
type CertificateAuthorityServer interface {
|
||||
IssueCertificate(context.Context, *IssueCertificateRequest) (*core.Certificate, error)
|
||||
IssueCertificate(context.Context, *IssueCertificateRequest) (*proto1.Certificate, error)
|
||||
IssuePrecertificate(context.Context, *IssueCertificateRequest) (*IssuePrecertificateResponse, error)
|
||||
IssueCertificateForPrecertificate(context.Context, *IssueCertificateForPrecertificateRequest) (*core.Certificate, error)
|
||||
IssueCertificateForPrecertificate(context.Context, *IssueCertificateForPrecertificateRequest) (*proto1.Certificate, error)
|
||||
GenerateOCSP(context.Context, *GenerateOCSPRequest) (*OCSPResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedCertificateAuthorityServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedCertificateAuthorityServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedCertificateAuthorityServer) IssueCertificate(ctx context.Context, req *IssueCertificateRequest) (*proto1.Certificate, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method IssueCertificate not implemented")
|
||||
}
|
||||
func (*UnimplementedCertificateAuthorityServer) IssuePrecertificate(ctx context.Context, req *IssueCertificateRequest) (*IssuePrecertificateResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method IssuePrecertificate not implemented")
|
||||
}
|
||||
func (*UnimplementedCertificateAuthorityServer) IssueCertificateForPrecertificate(ctx context.Context, req *IssueCertificateForPrecertificateRequest) (*proto1.Certificate, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method IssueCertificateForPrecertificate not implemented")
|
||||
}
|
||||
func (*UnimplementedCertificateAuthorityServer) GenerateOCSP(ctx context.Context, req *GenerateOCSPRequest) (*OCSPResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GenerateOCSP not implemented")
|
||||
}
|
||||
|
||||
func RegisterCertificateAuthorityServer(s *grpc.Server, srv CertificateAuthorityServer) {
|
||||
s.RegisterService(&_CertificateAuthority_serviceDesc, srv)
|
||||
}
|
||||
|
|
@ -370,8 +514,9 @@ var _CertificateAuthority_serviceDesc = grpc.ServiceDesc{
|
|||
Metadata: "ca/proto/ca.proto",
|
||||
}
|
||||
|
||||
// Client API for OCSPGenerator service
|
||||
|
||||
// OCSPGeneratorClient is the client API for OCSPGenerator service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type OCSPGeneratorClient interface {
|
||||
GenerateOCSP(ctx context.Context, in *GenerateOCSPRequest, opts ...grpc.CallOption) (*OCSPResponse, error)
|
||||
}
|
||||
|
|
@ -386,19 +531,26 @@ func NewOCSPGeneratorClient(cc *grpc.ClientConn) OCSPGeneratorClient {
|
|||
|
||||
func (c *oCSPGeneratorClient) GenerateOCSP(ctx context.Context, in *GenerateOCSPRequest, opts ...grpc.CallOption) (*OCSPResponse, error) {
|
||||
out := new(OCSPResponse)
|
||||
err := grpc.Invoke(ctx, "/ca.OCSPGenerator/GenerateOCSP", in, out, c.cc, opts...)
|
||||
err := c.cc.Invoke(ctx, "/ca.OCSPGenerator/GenerateOCSP", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for OCSPGenerator service
|
||||
|
||||
// OCSPGeneratorServer is the server API for OCSPGenerator service.
|
||||
type OCSPGeneratorServer interface {
|
||||
GenerateOCSP(context.Context, *GenerateOCSPRequest) (*OCSPResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedOCSPGeneratorServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedOCSPGeneratorServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedOCSPGeneratorServer) GenerateOCSP(ctx context.Context, req *GenerateOCSPRequest) (*OCSPResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GenerateOCSP not implemented")
|
||||
}
|
||||
|
||||
func RegisterOCSPGeneratorServer(s *grpc.Server, srv OCSPGeneratorServer) {
|
||||
s.RegisterService(&_OCSPGenerator_serviceDesc, srv)
|
||||
}
|
||||
|
|
@ -433,35 +585,3 @@ var _OCSPGenerator_serviceDesc = grpc.ServiceDesc{
|
|||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "ca/proto/ca.proto",
|
||||
}
|
||||
|
||||
func init() { proto1.RegisterFile("ca/proto/ca.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 403 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0x41, 0xab, 0xd3, 0x40,
|
||||
0x10, 0x6e, 0x92, 0x3e, 0xeb, 0x1b, 0xa2, 0xf4, 0xed, 0x53, 0x5f, 0x48, 0x05, 0x6b, 0x0e, 0x12,
|
||||
0x44, 0x52, 0xe8, 0xd5, 0x53, 0x4d, 0xaa, 0x14, 0x04, 0xcb, 0xb6, 0x5e, 0xbc, 0x2d, 0xdb, 0xa9,
|
||||
0x06, 0x31, 0x5b, 0x67, 0x37, 0x82, 0x07, 0xff, 0x84, 0xbf, 0xce, 0x9f, 0x23, 0x49, 0x93, 0x36,
|
||||
0x0d, 0xa9, 0x3d, 0x78, 0x9b, 0x99, 0x2f, 0x3b, 0xdf, 0x37, 0xdf, 0x4c, 0xe0, 0x46, 0x8a, 0xc9,
|
||||
0x8e, 0x94, 0x51, 0x13, 0x29, 0xa2, 0x32, 0x60, 0xb6, 0x14, 0xfe, 0x63, 0xa9, 0x08, 0x6b, 0x40,
|
||||
0x11, 0xee, 0xa1, 0xe0, 0x1b, 0xdc, 0x2d, 0xb4, 0xce, 0x31, 0x46, 0x32, 0xe9, 0x36, 0x95, 0xc2,
|
||||
0x20, 0xc7, 0xef, 0x39, 0x6a, 0xc3, 0x86, 0xe0, 0x48, 0x4d, 0x9e, 0x35, 0xb6, 0x42, 0x97, 0x17,
|
||||
0x21, 0x7b, 0x01, 0x0f, 0x09, 0x3f, 0xa7, 0xda, 0x90, 0x30, 0xa9, 0xca, 0x16, 0x89, 0x67, 0x8f,
|
||||
0xad, 0xd0, 0xe1, 0xad, 0x2a, 0xf3, 0x60, 0xa0, 0x68, 0x83, 0xb4, 0x48, 0x3c, 0xa7, 0xfc, 0xa0,
|
||||
0x4e, 0x83, 0x09, 0x8c, 0x4a, 0xba, 0x25, 0xa1, 0x6c, 0x32, 0xea, 0x9d, 0xca, 0x34, 0x16, 0x94,
|
||||
0xc9, 0x9c, 0xd7, 0x94, 0x9b, 0x39, 0x0f, 0x7e, 0x5b, 0x10, 0xb6, 0x05, 0xbe, 0x55, 0xd4, 0x7e,
|
||||
0x7f, 0x50, 0x7c, 0xfa, 0x9c, 0x31, 0xe8, 0xaf, 0xe2, 0xb5, 0xf6, 0xec, 0xb1, 0x13, 0xba, 0xbc,
|
||||
0xaf, 0xe3, 0xb5, 0xee, 0x98, 0xc2, 0xb9, 0x34, 0x45, 0xff, 0x74, 0x8a, 0x5f, 0x70, 0xfb, 0x0e,
|
||||
0x33, 0x24, 0x61, 0xf0, 0x43, 0xbc, 0x5a, 0xd6, 0xf4, 0x1e, 0x0c, 0x0a, 0x51, 0x47, 0x09, 0x75,
|
||||
0xca, 0x9e, 0xc0, 0x3d, 0x6d, 0x84, 0xc9, 0x75, 0x69, 0xd8, 0x35, 0xaf, 0xb2, 0xa2, 0x4e, 0x28,
|
||||
0xb4, 0xca, 0x4a, 0x09, 0x57, 0xbc, 0xca, 0xd8, 0x53, 0xb8, 0x26, 0xfc, 0xa1, 0xbe, 0xe2, 0x66,
|
||||
0x66, 0x2a, 0xf2, 0x63, 0x21, 0x78, 0x09, 0xee, 0x9e, 0xb6, 0x72, 0xcd, 0x87, 0xfb, 0x54, 0xc5,
|
||||
0x15, 0xf1, 0x21, 0x9f, 0xfe, 0xb1, 0xe1, 0x51, 0xc3, 0xba, 0x59, 0x6e, 0xbe, 0x28, 0x4a, 0xcd,
|
||||
0x4f, 0x96, 0xc0, 0xb0, 0xed, 0x2b, 0x1b, 0x45, 0x52, 0x44, 0x67, 0xce, 0xc1, 0xbf, 0x89, 0xca,
|
||||
0xb3, 0x69, 0x20, 0x41, 0x8f, 0x7d, 0x84, 0xdb, 0x8e, 0x7d, 0xfe, 0xbb, 0xd1, 0xb3, 0x03, 0xd8,
|
||||
0x7d, 0x05, 0x41, 0x8f, 0x6d, 0xe1, 0xf9, 0xc5, 0xa5, 0xb3, 0x57, 0x5d, 0x24, 0xe7, 0x6e, 0xa3,
|
||||
0x5b, 0xfe, 0x6b, 0x70, 0x9b, 0x8b, 0x64, 0x77, 0x45, 0xcb, 0x8e, 0xd5, 0xfa, 0xc3, 0x02, 0x68,
|
||||
0x9a, 0x1e, 0xf4, 0xa6, 0xef, 0xe1, 0x41, 0x51, 0xa9, 0x3e, 0x57, 0xf4, 0x5f, 0xdd, 0xde, 0x0c,
|
||||
0x3e, 0x5d, 0x95, 0x7f, 0xe4, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5d, 0x91, 0xda, 0xc7, 0xc0,
|
||||
0x03, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,16 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: core/proto/core.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package proto is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
core/proto/core.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Challenge
|
||||
ValidationRecord
|
||||
ProblemDetails
|
||||
Certificate
|
||||
Registration
|
||||
Authorization
|
||||
Order
|
||||
Empty
|
||||
*/
|
||||
package proto
|
||||
|
||||
import proto1 "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto1.Marshal
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
|
|
@ -33,24 +18,46 @@ var _ = math.Inf
|
|||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto1.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type Challenge struct {
|
||||
Id *int64 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
|
||||
Type *string `protobuf:"bytes,2,opt,name=type" json:"type,omitempty"`
|
||||
Status *string `protobuf:"bytes,6,opt,name=status" json:"status,omitempty"`
|
||||
Uri *string `protobuf:"bytes,9,opt,name=uri" json:"uri,omitempty"`
|
||||
Token *string `protobuf:"bytes,3,opt,name=token" json:"token,omitempty"`
|
||||
KeyAuthorization *string `protobuf:"bytes,5,opt,name=keyAuthorization" json:"keyAuthorization,omitempty"`
|
||||
Validationrecords []*ValidationRecord `protobuf:"bytes,10,rep,name=validationrecords" json:"validationrecords,omitempty"`
|
||||
Error *ProblemDetails `protobuf:"bytes,7,opt,name=error" json:"error,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Id *int64 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
|
||||
Type *string `protobuf:"bytes,2,opt,name=type" json:"type,omitempty"`
|
||||
Status *string `protobuf:"bytes,6,opt,name=status" json:"status,omitempty"`
|
||||
Uri *string `protobuf:"bytes,9,opt,name=uri" json:"uri,omitempty"`
|
||||
Token *string `protobuf:"bytes,3,opt,name=token" json:"token,omitempty"`
|
||||
KeyAuthorization *string `protobuf:"bytes,5,opt,name=keyAuthorization" json:"keyAuthorization,omitempty"`
|
||||
Validationrecords []*ValidationRecord `protobuf:"bytes,10,rep,name=validationrecords" json:"validationrecords,omitempty"`
|
||||
Error *ProblemDetails `protobuf:"bytes,7,opt,name=error" json:"error,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Challenge) Reset() { *m = Challenge{} }
|
||||
func (m *Challenge) String() string { return proto1.CompactTextString(m) }
|
||||
func (*Challenge) ProtoMessage() {}
|
||||
func (*Challenge) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
func (m *Challenge) Reset() { *m = Challenge{} }
|
||||
func (m *Challenge) String() string { return proto.CompactTextString(m) }
|
||||
func (*Challenge) ProtoMessage() {}
|
||||
func (*Challenge) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_80ea9561f1d738ba, []int{0}
|
||||
}
|
||||
|
||||
func (m *Challenge) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Challenge.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Challenge) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Challenge.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Challenge) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Challenge.Merge(m, src)
|
||||
}
|
||||
func (m *Challenge) XXX_Size() int {
|
||||
return xxx_messageInfo_Challenge.Size(m)
|
||||
}
|
||||
func (m *Challenge) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Challenge.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Challenge proto.InternalMessageInfo
|
||||
|
||||
func (m *Challenge) GetId() int64 {
|
||||
if m != nil && m.Id != nil {
|
||||
|
|
@ -118,14 +125,36 @@ type ValidationRecord struct {
|
|||
// A list of addresses tried before the address used (see
|
||||
// core/objects.go and the comment on the ValidationRecord structure
|
||||
// definition for more information.
|
||||
AddressesTried [][]byte `protobuf:"bytes,7,rep,name=addressesTried" json:"addressesTried,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
AddressesTried [][]byte `protobuf:"bytes,7,rep,name=addressesTried" json:"addressesTried,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ValidationRecord) Reset() { *m = ValidationRecord{} }
|
||||
func (m *ValidationRecord) String() string { return proto1.CompactTextString(m) }
|
||||
func (*ValidationRecord) ProtoMessage() {}
|
||||
func (*ValidationRecord) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
func (m *ValidationRecord) Reset() { *m = ValidationRecord{} }
|
||||
func (m *ValidationRecord) String() string { return proto.CompactTextString(m) }
|
||||
func (*ValidationRecord) ProtoMessage() {}
|
||||
func (*ValidationRecord) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_80ea9561f1d738ba, []int{1}
|
||||
}
|
||||
|
||||
func (m *ValidationRecord) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ValidationRecord.Unmarshal(m, b)
|
||||
}
|
||||
func (m *ValidationRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ValidationRecord.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *ValidationRecord) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ValidationRecord.Merge(m, src)
|
||||
}
|
||||
func (m *ValidationRecord) XXX_Size() int {
|
||||
return xxx_messageInfo_ValidationRecord.Size(m)
|
||||
}
|
||||
func (m *ValidationRecord) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ValidationRecord.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ValidationRecord proto.InternalMessageInfo
|
||||
|
||||
func (m *ValidationRecord) GetHostname() string {
|
||||
if m != nil && m.Hostname != nil {
|
||||
|
|
@ -177,16 +206,38 @@ func (m *ValidationRecord) GetAddressesTried() [][]byte {
|
|||
}
|
||||
|
||||
type ProblemDetails struct {
|
||||
ProblemType *string `protobuf:"bytes,1,opt,name=problemType" json:"problemType,omitempty"`
|
||||
Detail *string `protobuf:"bytes,2,opt,name=detail" json:"detail,omitempty"`
|
||||
HttpStatus *int32 `protobuf:"varint,3,opt,name=httpStatus" json:"httpStatus,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
ProblemType *string `protobuf:"bytes,1,opt,name=problemType" json:"problemType,omitempty"`
|
||||
Detail *string `protobuf:"bytes,2,opt,name=detail" json:"detail,omitempty"`
|
||||
HttpStatus *int32 `protobuf:"varint,3,opt,name=httpStatus" json:"httpStatus,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ProblemDetails) Reset() { *m = ProblemDetails{} }
|
||||
func (m *ProblemDetails) String() string { return proto1.CompactTextString(m) }
|
||||
func (*ProblemDetails) ProtoMessage() {}
|
||||
func (*ProblemDetails) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
func (m *ProblemDetails) Reset() { *m = ProblemDetails{} }
|
||||
func (m *ProblemDetails) String() string { return proto.CompactTextString(m) }
|
||||
func (*ProblemDetails) ProtoMessage() {}
|
||||
func (*ProblemDetails) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_80ea9561f1d738ba, []int{2}
|
||||
}
|
||||
|
||||
func (m *ProblemDetails) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ProblemDetails.Unmarshal(m, b)
|
||||
}
|
||||
func (m *ProblemDetails) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ProblemDetails.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *ProblemDetails) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ProblemDetails.Merge(m, src)
|
||||
}
|
||||
func (m *ProblemDetails) XXX_Size() int {
|
||||
return xxx_messageInfo_ProblemDetails.Size(m)
|
||||
}
|
||||
func (m *ProblemDetails) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ProblemDetails.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ProblemDetails proto.InternalMessageInfo
|
||||
|
||||
func (m *ProblemDetails) GetProblemType() string {
|
||||
if m != nil && m.ProblemType != nil {
|
||||
|
|
@ -210,19 +261,41 @@ func (m *ProblemDetails) GetHttpStatus() int32 {
|
|||
}
|
||||
|
||||
type Certificate struct {
|
||||
RegistrationID *int64 `protobuf:"varint,1,opt,name=registrationID" json:"registrationID,omitempty"`
|
||||
Serial *string `protobuf:"bytes,2,opt,name=serial" json:"serial,omitempty"`
|
||||
Digest *string `protobuf:"bytes,3,opt,name=digest" json:"digest,omitempty"`
|
||||
Der []byte `protobuf:"bytes,4,opt,name=der" json:"der,omitempty"`
|
||||
Issued *int64 `protobuf:"varint,5,opt,name=issued" json:"issued,omitempty"`
|
||||
Expires *int64 `protobuf:"varint,6,opt,name=expires" json:"expires,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
RegistrationID *int64 `protobuf:"varint,1,opt,name=registrationID" json:"registrationID,omitempty"`
|
||||
Serial *string `protobuf:"bytes,2,opt,name=serial" json:"serial,omitempty"`
|
||||
Digest *string `protobuf:"bytes,3,opt,name=digest" json:"digest,omitempty"`
|
||||
Der []byte `protobuf:"bytes,4,opt,name=der" json:"der,omitempty"`
|
||||
Issued *int64 `protobuf:"varint,5,opt,name=issued" json:"issued,omitempty"`
|
||||
Expires *int64 `protobuf:"varint,6,opt,name=expires" json:"expires,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Certificate) Reset() { *m = Certificate{} }
|
||||
func (m *Certificate) String() string { return proto1.CompactTextString(m) }
|
||||
func (*Certificate) ProtoMessage() {}
|
||||
func (*Certificate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
func (m *Certificate) Reset() { *m = Certificate{} }
|
||||
func (m *Certificate) String() string { return proto.CompactTextString(m) }
|
||||
func (*Certificate) ProtoMessage() {}
|
||||
func (*Certificate) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_80ea9561f1d738ba, []int{3}
|
||||
}
|
||||
|
||||
func (m *Certificate) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Certificate.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Certificate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Certificate.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Certificate) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Certificate.Merge(m, src)
|
||||
}
|
||||
func (m *Certificate) XXX_Size() int {
|
||||
return xxx_messageInfo_Certificate.Size(m)
|
||||
}
|
||||
func (m *Certificate) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Certificate.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Certificate proto.InternalMessageInfo
|
||||
|
||||
func (m *Certificate) GetRegistrationID() int64 {
|
||||
if m != nil && m.RegistrationID != nil {
|
||||
|
|
@ -267,21 +340,43 @@ func (m *Certificate) GetExpires() int64 {
|
|||
}
|
||||
|
||||
type Registration struct {
|
||||
Id *int64 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
|
||||
Key []byte `protobuf:"bytes,2,opt,name=key" json:"key,omitempty"`
|
||||
Contact []string `protobuf:"bytes,3,rep,name=contact" json:"contact,omitempty"`
|
||||
ContactsPresent *bool `protobuf:"varint,4,opt,name=contactsPresent" json:"contactsPresent,omitempty"`
|
||||
Agreement *string `protobuf:"bytes,5,opt,name=agreement" json:"agreement,omitempty"`
|
||||
InitialIP []byte `protobuf:"bytes,6,opt,name=initialIP" json:"initialIP,omitempty"`
|
||||
CreatedAt *int64 `protobuf:"varint,7,opt,name=createdAt" json:"createdAt,omitempty"`
|
||||
Status *string `protobuf:"bytes,8,opt,name=status" json:"status,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Id *int64 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
|
||||
Key []byte `protobuf:"bytes,2,opt,name=key" json:"key,omitempty"`
|
||||
Contact []string `protobuf:"bytes,3,rep,name=contact" json:"contact,omitempty"`
|
||||
ContactsPresent *bool `protobuf:"varint,4,opt,name=contactsPresent" json:"contactsPresent,omitempty"`
|
||||
Agreement *string `protobuf:"bytes,5,opt,name=agreement" json:"agreement,omitempty"`
|
||||
InitialIP []byte `protobuf:"bytes,6,opt,name=initialIP" json:"initialIP,omitempty"`
|
||||
CreatedAt *int64 `protobuf:"varint,7,opt,name=createdAt" json:"createdAt,omitempty"`
|
||||
Status *string `protobuf:"bytes,8,opt,name=status" json:"status,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Registration) Reset() { *m = Registration{} }
|
||||
func (m *Registration) String() string { return proto1.CompactTextString(m) }
|
||||
func (*Registration) ProtoMessage() {}
|
||||
func (*Registration) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
|
||||
func (m *Registration) Reset() { *m = Registration{} }
|
||||
func (m *Registration) String() string { return proto.CompactTextString(m) }
|
||||
func (*Registration) ProtoMessage() {}
|
||||
func (*Registration) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_80ea9561f1d738ba, []int{4}
|
||||
}
|
||||
|
||||
func (m *Registration) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Registration.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Registration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Registration.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Registration) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Registration.Merge(m, src)
|
||||
}
|
||||
func (m *Registration) XXX_Size() int {
|
||||
return xxx_messageInfo_Registration.Size(m)
|
||||
}
|
||||
func (m *Registration) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Registration.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Registration proto.InternalMessageInfo
|
||||
|
||||
func (m *Registration) GetId() int64 {
|
||||
if m != nil && m.Id != nil {
|
||||
|
|
@ -340,21 +435,43 @@ func (m *Registration) GetStatus() string {
|
|||
}
|
||||
|
||||
type Authorization struct {
|
||||
Id *string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
|
||||
Identifier *string `protobuf:"bytes,2,opt,name=identifier" json:"identifier,omitempty"`
|
||||
RegistrationID *int64 `protobuf:"varint,3,opt,name=registrationID" json:"registrationID,omitempty"`
|
||||
Status *string `protobuf:"bytes,4,opt,name=status" json:"status,omitempty"`
|
||||
Expires *int64 `protobuf:"varint,5,opt,name=expires" json:"expires,omitempty"`
|
||||
Challenges []*Challenge `protobuf:"bytes,6,rep,name=challenges" json:"challenges,omitempty"`
|
||||
Combinations []byte `protobuf:"bytes,7,opt,name=combinations" json:"combinations,omitempty"`
|
||||
V2 *bool `protobuf:"varint,8,opt,name=v2" json:"v2,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Id *string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
|
||||
Identifier *string `protobuf:"bytes,2,opt,name=identifier" json:"identifier,omitempty"`
|
||||
RegistrationID *int64 `protobuf:"varint,3,opt,name=registrationID" json:"registrationID,omitempty"`
|
||||
Status *string `protobuf:"bytes,4,opt,name=status" json:"status,omitempty"`
|
||||
Expires *int64 `protobuf:"varint,5,opt,name=expires" json:"expires,omitempty"`
|
||||
Challenges []*Challenge `protobuf:"bytes,6,rep,name=challenges" json:"challenges,omitempty"`
|
||||
Combinations []byte `protobuf:"bytes,7,opt,name=combinations" json:"combinations,omitempty"`
|
||||
V2 *bool `protobuf:"varint,8,opt,name=v2" json:"v2,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Authorization) Reset() { *m = Authorization{} }
|
||||
func (m *Authorization) String() string { return proto1.CompactTextString(m) }
|
||||
func (*Authorization) ProtoMessage() {}
|
||||
func (*Authorization) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
|
||||
func (m *Authorization) Reset() { *m = Authorization{} }
|
||||
func (m *Authorization) String() string { return proto.CompactTextString(m) }
|
||||
func (*Authorization) ProtoMessage() {}
|
||||
func (*Authorization) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_80ea9561f1d738ba, []int{5}
|
||||
}
|
||||
|
||||
func (m *Authorization) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Authorization.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Authorization) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Authorization.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Authorization) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Authorization.Merge(m, src)
|
||||
}
|
||||
func (m *Authorization) XXX_Size() int {
|
||||
return xxx_messageInfo_Authorization.Size(m)
|
||||
}
|
||||
func (m *Authorization) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Authorization.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Authorization proto.InternalMessageInfo
|
||||
|
||||
func (m *Authorization) GetId() string {
|
||||
if m != nil && m.Id != nil {
|
||||
|
|
@ -413,23 +530,45 @@ func (m *Authorization) GetV2() bool {
|
|||
}
|
||||
|
||||
type Order struct {
|
||||
Id *int64 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
|
||||
RegistrationID *int64 `protobuf:"varint,2,opt,name=registrationID" json:"registrationID,omitempty"`
|
||||
Expires *int64 `protobuf:"varint,3,opt,name=expires" json:"expires,omitempty"`
|
||||
Error *ProblemDetails `protobuf:"bytes,4,opt,name=error" json:"error,omitempty"`
|
||||
CertificateSerial *string `protobuf:"bytes,5,opt,name=certificateSerial" json:"certificateSerial,omitempty"`
|
||||
Authorizations []string `protobuf:"bytes,6,rep,name=authorizations" json:"authorizations,omitempty"`
|
||||
Status *string `protobuf:"bytes,7,opt,name=status" json:"status,omitempty"`
|
||||
Names []string `protobuf:"bytes,8,rep,name=names" json:"names,omitempty"`
|
||||
BeganProcessing *bool `protobuf:"varint,9,opt,name=beganProcessing" json:"beganProcessing,omitempty"`
|
||||
Created *int64 `protobuf:"varint,10,opt,name=created" json:"created,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Id *int64 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
|
||||
RegistrationID *int64 `protobuf:"varint,2,opt,name=registrationID" json:"registrationID,omitempty"`
|
||||
Expires *int64 `protobuf:"varint,3,opt,name=expires" json:"expires,omitempty"`
|
||||
Error *ProblemDetails `protobuf:"bytes,4,opt,name=error" json:"error,omitempty"`
|
||||
CertificateSerial *string `protobuf:"bytes,5,opt,name=certificateSerial" json:"certificateSerial,omitempty"`
|
||||
Authorizations []string `protobuf:"bytes,6,rep,name=authorizations" json:"authorizations,omitempty"`
|
||||
Status *string `protobuf:"bytes,7,opt,name=status" json:"status,omitempty"`
|
||||
Names []string `protobuf:"bytes,8,rep,name=names" json:"names,omitempty"`
|
||||
BeganProcessing *bool `protobuf:"varint,9,opt,name=beganProcessing" json:"beganProcessing,omitempty"`
|
||||
Created *int64 `protobuf:"varint,10,opt,name=created" json:"created,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Order) Reset() { *m = Order{} }
|
||||
func (m *Order) String() string { return proto1.CompactTextString(m) }
|
||||
func (*Order) ProtoMessage() {}
|
||||
func (*Order) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
|
||||
func (m *Order) Reset() { *m = Order{} }
|
||||
func (m *Order) String() string { return proto.CompactTextString(m) }
|
||||
func (*Order) ProtoMessage() {}
|
||||
func (*Order) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_80ea9561f1d738ba, []int{6}
|
||||
}
|
||||
|
||||
func (m *Order) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Order.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Order) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Order.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Order) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Order.Merge(m, src)
|
||||
}
|
||||
func (m *Order) XXX_Size() int {
|
||||
return xxx_messageInfo_Order.Size(m)
|
||||
}
|
||||
func (m *Order) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Order.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Order proto.InternalMessageInfo
|
||||
|
||||
func (m *Order) GetId() int64 {
|
||||
if m != nil && m.Id != nil {
|
||||
|
|
@ -502,28 +641,50 @@ func (m *Order) GetCreated() int64 {
|
|||
}
|
||||
|
||||
type Empty struct {
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Empty) Reset() { *m = Empty{} }
|
||||
func (m *Empty) String() string { return proto1.CompactTextString(m) }
|
||||
func (*Empty) ProtoMessage() {}
|
||||
func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
|
||||
func (m *Empty) Reset() { *m = Empty{} }
|
||||
func (m *Empty) String() string { return proto.CompactTextString(m) }
|
||||
func (*Empty) ProtoMessage() {}
|
||||
func (*Empty) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_80ea9561f1d738ba, []int{7}
|
||||
}
|
||||
|
||||
func (m *Empty) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Empty.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Empty) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Empty.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Empty) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Empty.Merge(m, src)
|
||||
}
|
||||
func (m *Empty) XXX_Size() int {
|
||||
return xxx_messageInfo_Empty.Size(m)
|
||||
}
|
||||
func (m *Empty) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Empty.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Empty proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto1.RegisterType((*Challenge)(nil), "core.Challenge")
|
||||
proto1.RegisterType((*ValidationRecord)(nil), "core.ValidationRecord")
|
||||
proto1.RegisterType((*ProblemDetails)(nil), "core.ProblemDetails")
|
||||
proto1.RegisterType((*Certificate)(nil), "core.Certificate")
|
||||
proto1.RegisterType((*Registration)(nil), "core.Registration")
|
||||
proto1.RegisterType((*Authorization)(nil), "core.Authorization")
|
||||
proto1.RegisterType((*Order)(nil), "core.Order")
|
||||
proto1.RegisterType((*Empty)(nil), "core.Empty")
|
||||
proto.RegisterType((*Challenge)(nil), "core.Challenge")
|
||||
proto.RegisterType((*ValidationRecord)(nil), "core.ValidationRecord")
|
||||
proto.RegisterType((*ProblemDetails)(nil), "core.ProblemDetails")
|
||||
proto.RegisterType((*Certificate)(nil), "core.Certificate")
|
||||
proto.RegisterType((*Registration)(nil), "core.Registration")
|
||||
proto.RegisterType((*Authorization)(nil), "core.Authorization")
|
||||
proto.RegisterType((*Order)(nil), "core.Order")
|
||||
proto.RegisterType((*Empty)(nil), "core.Empty")
|
||||
}
|
||||
|
||||
func init() { proto1.RegisterFile("core/proto/core.proto", fileDescriptor0) }
|
||||
func init() { proto.RegisterFile("core/proto/core.proto", fileDescriptor_80ea9561f1d738ba) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
var fileDescriptor_80ea9561f1d738ba = []byte{
|
||||
// 736 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x55, 0x41, 0x6e, 0xdb, 0x3a,
|
||||
0x10, 0x85, 0x2c, 0x2b, 0xb6, 0xc6, 0xfe, 0x89, 0x43, 0xe4, 0x07, 0xc2, 0xc7, 0x47, 0x20, 0x68,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ version: '3'
|
|||
services:
|
||||
boulder:
|
||||
# To minimize fetching this should be the same version used below
|
||||
image: letsencrypt/boulder-tools-go${TRAVIS_GO_VERSION:-1.12}:2019-03-06
|
||||
image: letsencrypt/boulder-tools-go${TRAVIS_GO_VERSION:-1.12}:2019-04-08
|
||||
environment:
|
||||
FAKE_DNS: 10.77.77.77
|
||||
PKCS11_PROXY_SOCKET: tcp://boulder-hsm:5657
|
||||
|
|
@ -51,7 +51,7 @@ services:
|
|||
working_dir: /go/src/github.com/letsencrypt/boulder
|
||||
bhsm:
|
||||
# To minimize fetching this should be the same version used above
|
||||
image: letsencrypt/boulder-tools-go${TRAVIS_GO_VERSION:-1.12}:2019-03-06
|
||||
image: letsencrypt/boulder-tools-go${TRAVIS_GO_VERSION:-1.12}:2019-04-08
|
||||
environment:
|
||||
PKCS11_DAEMON_SOCKET: tcp://0.0.0.0:5657
|
||||
command: /usr/local/bin/pkcs11-daemon /usr/lib/softhsm/libsofthsm2.so
|
||||
|
|
@ -73,7 +73,7 @@ services:
|
|||
logging:
|
||||
driver: none
|
||||
netaccess:
|
||||
image: letsencrypt/boulder-tools-go${TRAVIS_GO_VERSION:-1.12}:2019-03-06
|
||||
image: letsencrypt/boulder-tools-go${TRAVIS_GO_VERSION:-1.12}:2019-04-08
|
||||
networks:
|
||||
- bluenet
|
||||
volumes:
|
||||
|
|
|
|||
|
|
@ -4,6 +4,28 @@ package features
|
|||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[unused-0]
|
||||
_ = x[PerformValidationRPC-1]
|
||||
_ = x[ACME13KeyRollover-2]
|
||||
_ = x[SimplifiedVAHTTP-3]
|
||||
_ = x[TLSSNIRevalidation-4]
|
||||
_ = x[AllowRenewalFirstRL-5]
|
||||
_ = x[CAAValidationMethods-6]
|
||||
_ = x[CAAAccountURI-7]
|
||||
_ = x[ProbeCTLogs-8]
|
||||
_ = x[HeadNonceStatusOK-9]
|
||||
_ = x[NewAuthorizationSchema-10]
|
||||
_ = x[RevokeAtRA-11]
|
||||
_ = x[SetIssuedNamesRenewalBit-12]
|
||||
_ = x[EarlyOrderRateLimit-13]
|
||||
_ = x[EnforceMultiVA-14]
|
||||
_ = x[MultiVAFullResults-15]
|
||||
}
|
||||
|
||||
const _FeatureFlag_name = "unusedPerformValidationRPCACME13KeyRolloverSimplifiedVAHTTPTLSSNIRevalidationAllowRenewalFirstRLCAAValidationMethodsCAAAccountURIProbeCTLogsHeadNonceStatusOKNewAuthorizationSchemaRevokeAtRASetIssuedNamesRenewalBitEarlyOrderRateLimitEnforceMultiVAMultiVAFullResults"
|
||||
|
||||
var _FeatureFlag_index = [...]uint16{0, 6, 26, 43, 59, 77, 96, 116, 129, 140, 157, 179, 189, 213, 232, 246, 264}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,16 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: grpc/test_proto/interceptors_test.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package test_proto is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
grpc/test_proto/interceptors_test.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Time
|
||||
*/
|
||||
package test_proto
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
@ -31,17 +22,39 @@ var _ = math.Inf
|
|||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type Time struct {
|
||||
Time *int64 `protobuf:"varint,1,opt,name=time" json:"time,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Time *int64 `protobuf:"varint,1,opt,name=time" json:"time,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Time) Reset() { *m = Time{} }
|
||||
func (m *Time) String() string { return proto.CompactTextString(m) }
|
||||
func (*Time) ProtoMessage() {}
|
||||
func (*Time) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
func (m *Time) Reset() { *m = Time{} }
|
||||
func (m *Time) String() string { return proto.CompactTextString(m) }
|
||||
func (*Time) ProtoMessage() {}
|
||||
func (*Time) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_8e88cbda9fef6d38, []int{0}
|
||||
}
|
||||
|
||||
func (m *Time) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Time.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Time) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Time.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Time) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Time.Merge(m, src)
|
||||
}
|
||||
func (m *Time) XXX_Size() int {
|
||||
return xxx_messageInfo_Time.Size(m)
|
||||
}
|
||||
func (m *Time) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Time.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Time proto.InternalMessageInfo
|
||||
|
||||
func (m *Time) GetTime() int64 {
|
||||
if m != nil && m.Time != nil {
|
||||
|
|
@ -54,6 +67,22 @@ func init() {
|
|||
proto.RegisterType((*Time)(nil), "Time")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("grpc/test_proto/interceptors_test.proto", fileDescriptor_8e88cbda9fef6d38)
|
||||
}
|
||||
|
||||
var fileDescriptor_8e88cbda9fef6d38 = []byte{
|
||||
// 117 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4f, 0x2f, 0x2a, 0x48,
|
||||
0xd6, 0x2f, 0x49, 0x2d, 0x2e, 0x89, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0xd7, 0xcf, 0xcc, 0x2b, 0x49,
|
||||
0x2d, 0x4a, 0x4e, 0x2d, 0x28, 0xc9, 0x2f, 0x2a, 0x8e, 0x07, 0x89, 0xeb, 0x81, 0xc5, 0x95, 0xa4,
|
||||
0xb8, 0x58, 0x42, 0x32, 0x73, 0x53, 0x85, 0x84, 0xb8, 0x58, 0x4a, 0x32, 0x73, 0x53, 0x25, 0x18,
|
||||
0x15, 0x18, 0x35, 0x98, 0x83, 0xc0, 0x6c, 0x23, 0x25, 0x2e, 0x76, 0xe7, 0x8c, 0xcc, 0x9c, 0x9c,
|
||||
0xd4, 0x22, 0x21, 0x71, 0x2e, 0x56, 0x30, 0x53, 0x88, 0x55, 0x0f, 0xa4, 0x5c, 0x0a, 0x42, 0x29,
|
||||
0x31, 0x38, 0xf1, 0x44, 0x71, 0x21, 0x6c, 0x01, 0x04, 0x00, 0x00, 0xff, 0xff, 0x56, 0xd9, 0xf5,
|
||||
0x39, 0x77, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
|
@ -62,8 +91,9 @@ var _ grpc.ClientConn
|
|||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// Client API for Chiller service
|
||||
|
||||
// ChillerClient is the client API for Chiller service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type ChillerClient interface {
|
||||
// Sleep for the given amount of time, and return the amount of time slept.
|
||||
Chill(ctx context.Context, in *Time, opts ...grpc.CallOption) (*Time, error)
|
||||
|
|
@ -79,20 +109,27 @@ func NewChillerClient(cc *grpc.ClientConn) ChillerClient {
|
|||
|
||||
func (c *chillerClient) Chill(ctx context.Context, in *Time, opts ...grpc.CallOption) (*Time, error) {
|
||||
out := new(Time)
|
||||
err := grpc.Invoke(ctx, "/Chiller/Chill", in, out, c.cc, opts...)
|
||||
err := c.cc.Invoke(ctx, "/Chiller/Chill", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Chiller service
|
||||
|
||||
// ChillerServer is the server API for Chiller service.
|
||||
type ChillerServer interface {
|
||||
// Sleep for the given amount of time, and return the amount of time slept.
|
||||
Chill(context.Context, *Time) (*Time, error)
|
||||
}
|
||||
|
||||
// UnimplementedChillerServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedChillerServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedChillerServer) Chill(ctx context.Context, req *Time) (*Time, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Chill not implemented")
|
||||
}
|
||||
|
||||
func RegisterChillerServer(s *grpc.Server, srv ChillerServer) {
|
||||
s.RegisterService(&_Chiller_serviceDesc, srv)
|
||||
}
|
||||
|
|
@ -127,17 +164,3 @@ var _Chiller_serviceDesc = grpc.ServiceDesc{
|
|||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "grpc/test_proto/interceptors_test.proto",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("grpc/test_proto/interceptors_test.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 117 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4f, 0x2f, 0x2a, 0x48,
|
||||
0xd6, 0x2f, 0x49, 0x2d, 0x2e, 0x89, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0xd7, 0xcf, 0xcc, 0x2b, 0x49,
|
||||
0x2d, 0x4a, 0x4e, 0x2d, 0x28, 0xc9, 0x2f, 0x2a, 0x8e, 0x07, 0x89, 0xeb, 0x81, 0xc5, 0x95, 0xa4,
|
||||
0xb8, 0x58, 0x42, 0x32, 0x73, 0x53, 0x85, 0x84, 0xb8, 0x58, 0x4a, 0x32, 0x73, 0x53, 0x25, 0x18,
|
||||
0x15, 0x18, 0x35, 0x98, 0x83, 0xc0, 0x6c, 0x23, 0x25, 0x2e, 0x76, 0xe7, 0x8c, 0xcc, 0x9c, 0x9c,
|
||||
0xd4, 0x22, 0x21, 0x71, 0x2e, 0x56, 0x30, 0x53, 0x88, 0x55, 0x0f, 0xa4, 0x5c, 0x0a, 0x42, 0x29,
|
||||
0x31, 0x38, 0xf1, 0x44, 0x71, 0x21, 0x6c, 0x01, 0x04, 0x00, 0x00, 0xff, 0xff, 0x56, 0xd9, 0xf5,
|
||||
0x39, 0x77, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,16 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: publisher.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package publisher is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
publisher.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Request
|
||||
Result
|
||||
*/
|
||||
package publisher
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
@ -32,21 +22,43 @@ var _ = math.Inf
|
|||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type Request struct {
|
||||
Der []byte `protobuf:"bytes,1,opt,name=der" json:"der,omitempty"`
|
||||
LogURL *string `protobuf:"bytes,2,opt,name=LogURL,json=logURL" json:"LogURL,omitempty"`
|
||||
LogPublicKey *string `protobuf:"bytes,3,opt,name=LogPublicKey,json=logPublicKey" json:"LogPublicKey,omitempty"`
|
||||
Precert *bool `protobuf:"varint,4,opt,name=precert" json:"precert,omitempty"`
|
||||
StoreSCT *bool `protobuf:"varint,5,opt,name=storeSCT" json:"storeSCT,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Der []byte `protobuf:"bytes,1,opt,name=der" json:"der,omitempty"`
|
||||
LogURL *string `protobuf:"bytes,2,opt,name=LogURL" json:"LogURL,omitempty"`
|
||||
LogPublicKey *string `protobuf:"bytes,3,opt,name=LogPublicKey" json:"LogPublicKey,omitempty"`
|
||||
Precert *bool `protobuf:"varint,4,opt,name=precert" json:"precert,omitempty"`
|
||||
StoreSCT *bool `protobuf:"varint,5,opt,name=storeSCT" json:"storeSCT,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Request) Reset() { *m = Request{} }
|
||||
func (m *Request) String() string { return proto.CompactTextString(m) }
|
||||
func (*Request) ProtoMessage() {}
|
||||
func (*Request) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
func (m *Request) Reset() { *m = Request{} }
|
||||
func (m *Request) String() string { return proto.CompactTextString(m) }
|
||||
func (*Request) ProtoMessage() {}
|
||||
func (*Request) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_41489454d08668ce, []int{0}
|
||||
}
|
||||
|
||||
func (m *Request) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Request.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Request.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Request) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Request.Merge(m, src)
|
||||
}
|
||||
func (m *Request) XXX_Size() int {
|
||||
return xxx_messageInfo_Request.Size(m)
|
||||
}
|
||||
func (m *Request) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Request.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Request proto.InternalMessageInfo
|
||||
|
||||
func (m *Request) GetDer() []byte {
|
||||
if m != nil {
|
||||
|
|
@ -84,14 +96,36 @@ func (m *Request) GetStoreSCT() bool {
|
|||
}
|
||||
|
||||
type Result struct {
|
||||
Sct []byte `protobuf:"bytes,1,opt,name=sct" json:"sct,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Sct []byte `protobuf:"bytes,1,opt,name=sct" json:"sct,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Result) Reset() { *m = Result{} }
|
||||
func (m *Result) String() string { return proto.CompactTextString(m) }
|
||||
func (*Result) ProtoMessage() {}
|
||||
func (*Result) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
func (m *Result) Reset() { *m = Result{} }
|
||||
func (m *Result) String() string { return proto.CompactTextString(m) }
|
||||
func (*Result) ProtoMessage() {}
|
||||
func (*Result) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_41489454d08668ce, []int{1}
|
||||
}
|
||||
|
||||
func (m *Result) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Result.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Result) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Result.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Result) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Result.Merge(m, src)
|
||||
}
|
||||
func (m *Result) XXX_Size() int {
|
||||
return xxx_messageInfo_Result.Size(m)
|
||||
}
|
||||
func (m *Result) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Result.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Result proto.InternalMessageInfo
|
||||
|
||||
func (m *Result) GetSct() []byte {
|
||||
if m != nil {
|
||||
|
|
@ -105,6 +139,25 @@ func init() {
|
|||
proto.RegisterType((*Result)(nil), "Result")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("publisher.proto", fileDescriptor_41489454d08668ce) }
|
||||
|
||||
var fileDescriptor_41489454d08668ce = []byte{
|
||||
// 207 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x8f, 0x31, 0x4f, 0x86, 0x30,
|
||||
0x10, 0x86, 0xad, 0x9f, 0x7e, 0xc0, 0x85, 0x44, 0xd3, 0xc1, 0x34, 0x9d, 0x48, 0x27, 0x26, 0x12,
|
||||
0xfd, 0x01, 0x2e, 0x8c, 0x32, 0x90, 0x82, 0x71, 0xa7, 0x5e, 0xa0, 0x09, 0x5a, 0x6c, 0xaf, 0x83,
|
||||
0x3f, 0xc2, 0xff, 0x6c, 0x40, 0x30, 0xf9, 0xb6, 0x7b, 0xde, 0x37, 0x77, 0x79, 0x0e, 0xee, 0x96,
|
||||
0x38, 0xcc, 0x36, 0x4c, 0xe8, 0xab, 0xc5, 0x3b, 0x72, 0xea, 0x87, 0x41, 0xa2, 0xf1, 0x2b, 0x62,
|
||||
0x20, 0x7e, 0x0f, 0xa7, 0x77, 0xf4, 0x82, 0x15, 0xac, 0xcc, 0xf5, 0x3a, 0xf2, 0x07, 0x38, 0x37,
|
||||
0x6e, 0x7c, 0xd5, 0x8d, 0xb8, 0x2e, 0x58, 0x99, 0xe9, 0x9d, 0xb8, 0x82, 0xbc, 0x71, 0x63, 0xbb,
|
||||
0xde, 0x32, 0x2f, 0xf8, 0x2d, 0x4e, 0x5b, 0x7b, 0x91, 0x71, 0x01, 0xc9, 0xe2, 0xd1, 0xa0, 0x27,
|
||||
0x71, 0x53, 0xb0, 0x32, 0xd5, 0x07, 0x72, 0x09, 0x69, 0x20, 0xe7, 0xb1, 0xab, 0x7b, 0x71, 0xbb,
|
||||
0x55, 0xff, 0xac, 0x24, 0x9c, 0x35, 0x86, 0x38, 0x6f, 0x36, 0xc1, 0xd0, 0x61, 0x13, 0x0c, 0x3d,
|
||||
0x3d, 0x43, 0xd6, 0x1e, 0xfa, 0xfc, 0x11, 0x64, 0x17, 0x87, 0x0f, 0x4b, 0xbd, 0xeb, 0xec, 0xe7,
|
||||
0x38, 0x63, 0xdd, 0xbf, 0x59, 0x9a, 0xf6, 0xe5, 0xb4, 0xda, 0x9f, 0x92, 0x49, 0xf5, 0x17, 0xa9,
|
||||
0xab, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x32, 0x17, 0x12, 0x9f, 0xfd, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
|
@ -113,8 +166,9 @@ var _ grpc.ClientConn
|
|||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// Client API for Publisher service
|
||||
|
||||
// PublisherClient is the client API for Publisher service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type PublisherClient interface {
|
||||
SubmitToSingleCTWithResult(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Result, error)
|
||||
}
|
||||
|
|
@ -129,19 +183,26 @@ func NewPublisherClient(cc *grpc.ClientConn) PublisherClient {
|
|||
|
||||
func (c *publisherClient) SubmitToSingleCTWithResult(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Result, error) {
|
||||
out := new(Result)
|
||||
err := grpc.Invoke(ctx, "/Publisher/SubmitToSingleCTWithResult", in, out, c.cc, opts...)
|
||||
err := c.cc.Invoke(ctx, "/Publisher/SubmitToSingleCTWithResult", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for Publisher service
|
||||
|
||||
// PublisherServer is the server API for Publisher service.
|
||||
type PublisherServer interface {
|
||||
SubmitToSingleCTWithResult(context.Context, *Request) (*Result, error)
|
||||
}
|
||||
|
||||
// UnimplementedPublisherServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedPublisherServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedPublisherServer) SubmitToSingleCTWithResult(ctx context.Context, req *Request) (*Result, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SubmitToSingleCTWithResult not implemented")
|
||||
}
|
||||
|
||||
func RegisterPublisherServer(s *grpc.Server, srv PublisherServer) {
|
||||
s.RegisterService(&_Publisher_serviceDesc, srv)
|
||||
}
|
||||
|
|
@ -176,23 +237,3 @@ var _Publisher_serviceDesc = grpc.ServiceDesc{
|
|||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "publisher.proto",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("publisher.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 210 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x8f, 0xc1, 0x4a, 0xc4, 0x30,
|
||||
0x10, 0x86, 0x8d, 0xab, 0x6d, 0x77, 0x28, 0x28, 0x39, 0x48, 0xc8, 0xa9, 0xe4, 0xd4, 0x53, 0x41,
|
||||
0x1f, 0xc0, 0xcb, 0x1e, 0xed, 0x61, 0x49, 0x2b, 0xde, 0x37, 0x0e, 0xdd, 0x40, 0x34, 0x35, 0x99,
|
||||
0x1c, 0x7c, 0x08, 0xdf, 0x59, 0x1a, 0x5b, 0xd9, 0xdb, 0x7c, 0xff, 0xcf, 0x0c, 0xdf, 0xc0, 0xdd,
|
||||
0x9c, 0x4e, 0xce, 0xc6, 0x33, 0x86, 0x6e, 0x0e, 0x9e, 0xbc, 0xfa, 0x61, 0x50, 0x6a, 0xfc, 0x4a,
|
||||
0x18, 0x89, 0xdf, 0xc3, 0xee, 0x1d, 0x83, 0x60, 0x0d, 0x6b, 0x6b, 0xbd, 0x8c, 0xfc, 0x01, 0x8a,
|
||||
0xde, 0x4f, 0xaf, 0xba, 0x17, 0xd7, 0x0d, 0x6b, 0xf7, 0xba, 0x70, 0x99, 0xb8, 0x82, 0xba, 0xf7,
|
||||
0xd3, 0x71, 0xb9, 0x65, 0x5e, 0xf0, 0x5b, 0xec, 0x72, 0x5b, 0xbb, 0x8b, 0x8c, 0x0b, 0x28, 0xe7,
|
||||
0x80, 0x06, 0x03, 0x89, 0x9b, 0x86, 0xb5, 0x95, 0xde, 0x90, 0x4b, 0xa8, 0x22, 0xf9, 0x80, 0xc3,
|
||||
0x61, 0x14, 0xb7, 0xb9, 0xfa, 0x67, 0x25, 0xa1, 0xd0, 0x18, 0x93, 0xcb, 0x36, 0xd1, 0xd0, 0x66,
|
||||
0x13, 0x0d, 0x3d, 0x3d, 0xc3, 0xfe, 0xb8, 0xe9, 0xf3, 0x47, 0x90, 0x43, 0x3a, 0x7d, 0x58, 0x1a,
|
||||
0xfd, 0x60, 0x3f, 0x27, 0x87, 0x87, 0xf1, 0xcd, 0xd2, 0x79, 0x5d, 0xae, 0xba, 0xf5, 0x29, 0x59,
|
||||
0x76, 0x7f, 0x91, 0xba, 0xfa, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x55, 0x8b, 0xd8, 0x2b, 0xfd, 0x00,
|
||||
0x00, 0x00,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,38 +1,21 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: ra/proto/ra.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package proto is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
ra/proto/ra.proto
|
||||
|
||||
It has these top-level messages:
|
||||
NewAuthorizationRequest
|
||||
NewCertificateRequest
|
||||
UpdateRegistrationRequest
|
||||
UpdateAuthorizationRequest
|
||||
PerformValidationRequest
|
||||
RevokeCertificateWithRegRequest
|
||||
AdministrativelyRevokeCertificateRequest
|
||||
NewOrderRequest
|
||||
FinalizeOrderRequest
|
||||
*/
|
||||
package proto
|
||||
|
||||
import proto1 "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import core "github.com/letsencrypt/boulder/core/proto"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
proto1 "github.com/letsencrypt/boulder/core/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto1.Marshal
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
|
|
@ -40,20 +23,42 @@ var _ = math.Inf
|
|||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto1.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type NewAuthorizationRequest struct {
|
||||
Authz *core.Authorization `protobuf:"bytes,1,opt,name=authz" json:"authz,omitempty"`
|
||||
RegID *int64 `protobuf:"varint,2,opt,name=regID" json:"regID,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Authz *proto1.Authorization `protobuf:"bytes,1,opt,name=authz" json:"authz,omitempty"`
|
||||
RegID *int64 `protobuf:"varint,2,opt,name=regID" json:"regID,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *NewAuthorizationRequest) Reset() { *m = NewAuthorizationRequest{} }
|
||||
func (m *NewAuthorizationRequest) String() string { return proto1.CompactTextString(m) }
|
||||
func (*NewAuthorizationRequest) ProtoMessage() {}
|
||||
func (*NewAuthorizationRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
func (m *NewAuthorizationRequest) Reset() { *m = NewAuthorizationRequest{} }
|
||||
func (m *NewAuthorizationRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*NewAuthorizationRequest) ProtoMessage() {}
|
||||
func (*NewAuthorizationRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_f3baba040132fbcd, []int{0}
|
||||
}
|
||||
|
||||
func (m *NewAuthorizationRequest) GetAuthz() *core.Authorization {
|
||||
func (m *NewAuthorizationRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NewAuthorizationRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *NewAuthorizationRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_NewAuthorizationRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *NewAuthorizationRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_NewAuthorizationRequest.Merge(m, src)
|
||||
}
|
||||
func (m *NewAuthorizationRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_NewAuthorizationRequest.Size(m)
|
||||
}
|
||||
func (m *NewAuthorizationRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_NewAuthorizationRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_NewAuthorizationRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *NewAuthorizationRequest) GetAuthz() *proto1.Authorization {
|
||||
if m != nil {
|
||||
return m.Authz
|
||||
}
|
||||
|
|
@ -68,15 +73,37 @@ func (m *NewAuthorizationRequest) GetRegID() int64 {
|
|||
}
|
||||
|
||||
type NewCertificateRequest struct {
|
||||
Csr []byte `protobuf:"bytes,1,opt,name=csr" json:"csr,omitempty"`
|
||||
RegID *int64 `protobuf:"varint,2,opt,name=regID" json:"regID,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Csr []byte `protobuf:"bytes,1,opt,name=csr" json:"csr,omitempty"`
|
||||
RegID *int64 `protobuf:"varint,2,opt,name=regID" json:"regID,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *NewCertificateRequest) Reset() { *m = NewCertificateRequest{} }
|
||||
func (m *NewCertificateRequest) String() string { return proto1.CompactTextString(m) }
|
||||
func (*NewCertificateRequest) ProtoMessage() {}
|
||||
func (*NewCertificateRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
func (m *NewCertificateRequest) Reset() { *m = NewCertificateRequest{} }
|
||||
func (m *NewCertificateRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*NewCertificateRequest) ProtoMessage() {}
|
||||
func (*NewCertificateRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_f3baba040132fbcd, []int{1}
|
||||
}
|
||||
|
||||
func (m *NewCertificateRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NewCertificateRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *NewCertificateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_NewCertificateRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *NewCertificateRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_NewCertificateRequest.Merge(m, src)
|
||||
}
|
||||
func (m *NewCertificateRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_NewCertificateRequest.Size(m)
|
||||
}
|
||||
func (m *NewCertificateRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_NewCertificateRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_NewCertificateRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *NewCertificateRequest) GetCsr() []byte {
|
||||
if m != nil {
|
||||
|
|
@ -93,24 +120,46 @@ func (m *NewCertificateRequest) GetRegID() int64 {
|
|||
}
|
||||
|
||||
type UpdateRegistrationRequest struct {
|
||||
Base *core.Registration `protobuf:"bytes,1,opt,name=base" json:"base,omitempty"`
|
||||
Update *core.Registration `protobuf:"bytes,2,opt,name=update" json:"update,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Base *proto1.Registration `protobuf:"bytes,1,opt,name=base" json:"base,omitempty"`
|
||||
Update *proto1.Registration `protobuf:"bytes,2,opt,name=update" json:"update,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *UpdateRegistrationRequest) Reset() { *m = UpdateRegistrationRequest{} }
|
||||
func (m *UpdateRegistrationRequest) String() string { return proto1.CompactTextString(m) }
|
||||
func (*UpdateRegistrationRequest) ProtoMessage() {}
|
||||
func (*UpdateRegistrationRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
func (m *UpdateRegistrationRequest) Reset() { *m = UpdateRegistrationRequest{} }
|
||||
func (m *UpdateRegistrationRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*UpdateRegistrationRequest) ProtoMessage() {}
|
||||
func (*UpdateRegistrationRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_f3baba040132fbcd, []int{2}
|
||||
}
|
||||
|
||||
func (m *UpdateRegistrationRequest) GetBase() *core.Registration {
|
||||
func (m *UpdateRegistrationRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_UpdateRegistrationRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *UpdateRegistrationRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_UpdateRegistrationRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *UpdateRegistrationRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_UpdateRegistrationRequest.Merge(m, src)
|
||||
}
|
||||
func (m *UpdateRegistrationRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_UpdateRegistrationRequest.Size(m)
|
||||
}
|
||||
func (m *UpdateRegistrationRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_UpdateRegistrationRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_UpdateRegistrationRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *UpdateRegistrationRequest) GetBase() *proto1.Registration {
|
||||
if m != nil {
|
||||
return m.Base
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *UpdateRegistrationRequest) GetUpdate() *core.Registration {
|
||||
func (m *UpdateRegistrationRequest) GetUpdate() *proto1.Registration {
|
||||
if m != nil {
|
||||
return m.Update
|
||||
}
|
||||
|
|
@ -118,18 +167,40 @@ func (m *UpdateRegistrationRequest) GetUpdate() *core.Registration {
|
|||
}
|
||||
|
||||
type UpdateAuthorizationRequest struct {
|
||||
Authz *core.Authorization `protobuf:"bytes,1,opt,name=authz" json:"authz,omitempty"`
|
||||
ChallengeIndex *int64 `protobuf:"varint,2,opt,name=challengeIndex" json:"challengeIndex,omitempty"`
|
||||
Response *core.Challenge `protobuf:"bytes,3,opt,name=response" json:"response,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Authz *proto1.Authorization `protobuf:"bytes,1,opt,name=authz" json:"authz,omitempty"`
|
||||
ChallengeIndex *int64 `protobuf:"varint,2,opt,name=challengeIndex" json:"challengeIndex,omitempty"`
|
||||
Response *proto1.Challenge `protobuf:"bytes,3,opt,name=response" json:"response,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *UpdateAuthorizationRequest) Reset() { *m = UpdateAuthorizationRequest{} }
|
||||
func (m *UpdateAuthorizationRequest) String() string { return proto1.CompactTextString(m) }
|
||||
func (*UpdateAuthorizationRequest) ProtoMessage() {}
|
||||
func (*UpdateAuthorizationRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
func (m *UpdateAuthorizationRequest) Reset() { *m = UpdateAuthorizationRequest{} }
|
||||
func (m *UpdateAuthorizationRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*UpdateAuthorizationRequest) ProtoMessage() {}
|
||||
func (*UpdateAuthorizationRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_f3baba040132fbcd, []int{3}
|
||||
}
|
||||
|
||||
func (m *UpdateAuthorizationRequest) GetAuthz() *core.Authorization {
|
||||
func (m *UpdateAuthorizationRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_UpdateAuthorizationRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *UpdateAuthorizationRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_UpdateAuthorizationRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *UpdateAuthorizationRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_UpdateAuthorizationRequest.Merge(m, src)
|
||||
}
|
||||
func (m *UpdateAuthorizationRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_UpdateAuthorizationRequest.Size(m)
|
||||
}
|
||||
func (m *UpdateAuthorizationRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_UpdateAuthorizationRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_UpdateAuthorizationRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *UpdateAuthorizationRequest) GetAuthz() *proto1.Authorization {
|
||||
if m != nil {
|
||||
return m.Authz
|
||||
}
|
||||
|
|
@ -143,7 +214,7 @@ func (m *UpdateAuthorizationRequest) GetChallengeIndex() int64 {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (m *UpdateAuthorizationRequest) GetResponse() *core.Challenge {
|
||||
func (m *UpdateAuthorizationRequest) GetResponse() *proto1.Challenge {
|
||||
if m != nil {
|
||||
return m.Response
|
||||
}
|
||||
|
|
@ -151,17 +222,39 @@ func (m *UpdateAuthorizationRequest) GetResponse() *core.Challenge {
|
|||
}
|
||||
|
||||
type PerformValidationRequest struct {
|
||||
Authz *core.Authorization `protobuf:"bytes,1,opt,name=authz" json:"authz,omitempty"`
|
||||
ChallengeIndex *int64 `protobuf:"varint,2,opt,name=challengeIndex" json:"challengeIndex,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Authz *proto1.Authorization `protobuf:"bytes,1,opt,name=authz" json:"authz,omitempty"`
|
||||
ChallengeIndex *int64 `protobuf:"varint,2,opt,name=challengeIndex" json:"challengeIndex,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *PerformValidationRequest) Reset() { *m = PerformValidationRequest{} }
|
||||
func (m *PerformValidationRequest) String() string { return proto1.CompactTextString(m) }
|
||||
func (*PerformValidationRequest) ProtoMessage() {}
|
||||
func (*PerformValidationRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
|
||||
func (m *PerformValidationRequest) Reset() { *m = PerformValidationRequest{} }
|
||||
func (m *PerformValidationRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*PerformValidationRequest) ProtoMessage() {}
|
||||
func (*PerformValidationRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_f3baba040132fbcd, []int{4}
|
||||
}
|
||||
|
||||
func (m *PerformValidationRequest) GetAuthz() *core.Authorization {
|
||||
func (m *PerformValidationRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PerformValidationRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *PerformValidationRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_PerformValidationRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *PerformValidationRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PerformValidationRequest.Merge(m, src)
|
||||
}
|
||||
func (m *PerformValidationRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_PerformValidationRequest.Size(m)
|
||||
}
|
||||
func (m *PerformValidationRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_PerformValidationRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_PerformValidationRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *PerformValidationRequest) GetAuthz() *proto1.Authorization {
|
||||
if m != nil {
|
||||
return m.Authz
|
||||
}
|
||||
|
|
@ -176,16 +269,38 @@ func (m *PerformValidationRequest) GetChallengeIndex() int64 {
|
|||
}
|
||||
|
||||
type RevokeCertificateWithRegRequest struct {
|
||||
Cert []byte `protobuf:"bytes,1,opt,name=cert" json:"cert,omitempty"`
|
||||
Code *int64 `protobuf:"varint,2,opt,name=code" json:"code,omitempty"`
|
||||
RegID *int64 `protobuf:"varint,3,opt,name=regID" json:"regID,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Cert []byte `protobuf:"bytes,1,opt,name=cert" json:"cert,omitempty"`
|
||||
Code *int64 `protobuf:"varint,2,opt,name=code" json:"code,omitempty"`
|
||||
RegID *int64 `protobuf:"varint,3,opt,name=regID" json:"regID,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *RevokeCertificateWithRegRequest) Reset() { *m = RevokeCertificateWithRegRequest{} }
|
||||
func (m *RevokeCertificateWithRegRequest) String() string { return proto1.CompactTextString(m) }
|
||||
func (*RevokeCertificateWithRegRequest) ProtoMessage() {}
|
||||
func (*RevokeCertificateWithRegRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
|
||||
func (m *RevokeCertificateWithRegRequest) Reset() { *m = RevokeCertificateWithRegRequest{} }
|
||||
func (m *RevokeCertificateWithRegRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*RevokeCertificateWithRegRequest) ProtoMessage() {}
|
||||
func (*RevokeCertificateWithRegRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_f3baba040132fbcd, []int{5}
|
||||
}
|
||||
|
||||
func (m *RevokeCertificateWithRegRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_RevokeCertificateWithRegRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *RevokeCertificateWithRegRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_RevokeCertificateWithRegRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *RevokeCertificateWithRegRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_RevokeCertificateWithRegRequest.Merge(m, src)
|
||||
}
|
||||
func (m *RevokeCertificateWithRegRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_RevokeCertificateWithRegRequest.Size(m)
|
||||
}
|
||||
func (m *RevokeCertificateWithRegRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_RevokeCertificateWithRegRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_RevokeCertificateWithRegRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *RevokeCertificateWithRegRequest) GetCert() []byte {
|
||||
if m != nil {
|
||||
|
|
@ -209,21 +324,41 @@ func (m *RevokeCertificateWithRegRequest) GetRegID() int64 {
|
|||
}
|
||||
|
||||
type AdministrativelyRevokeCertificateRequest struct {
|
||||
Cert []byte `protobuf:"bytes,1,opt,name=cert" json:"cert,omitempty"`
|
||||
Code *int64 `protobuf:"varint,2,opt,name=code" json:"code,omitempty"`
|
||||
AdminName *string `protobuf:"bytes,3,opt,name=adminName" json:"adminName,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Cert []byte `protobuf:"bytes,1,opt,name=cert" json:"cert,omitempty"`
|
||||
Code *int64 `protobuf:"varint,2,opt,name=code" json:"code,omitempty"`
|
||||
AdminName *string `protobuf:"bytes,3,opt,name=adminName" json:"adminName,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *AdministrativelyRevokeCertificateRequest) Reset() {
|
||||
*m = AdministrativelyRevokeCertificateRequest{}
|
||||
}
|
||||
func (m *AdministrativelyRevokeCertificateRequest) String() string { return proto1.CompactTextString(m) }
|
||||
func (m *AdministrativelyRevokeCertificateRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*AdministrativelyRevokeCertificateRequest) ProtoMessage() {}
|
||||
func (*AdministrativelyRevokeCertificateRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor0, []int{6}
|
||||
return fileDescriptor_f3baba040132fbcd, []int{6}
|
||||
}
|
||||
|
||||
func (m *AdministrativelyRevokeCertificateRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_AdministrativelyRevokeCertificateRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *AdministrativelyRevokeCertificateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_AdministrativelyRevokeCertificateRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *AdministrativelyRevokeCertificateRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_AdministrativelyRevokeCertificateRequest.Merge(m, src)
|
||||
}
|
||||
func (m *AdministrativelyRevokeCertificateRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_AdministrativelyRevokeCertificateRequest.Size(m)
|
||||
}
|
||||
func (m *AdministrativelyRevokeCertificateRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_AdministrativelyRevokeCertificateRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_AdministrativelyRevokeCertificateRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *AdministrativelyRevokeCertificateRequest) GetCert() []byte {
|
||||
if m != nil {
|
||||
return m.Cert
|
||||
|
|
@ -246,15 +381,37 @@ func (m *AdministrativelyRevokeCertificateRequest) GetAdminName() string {
|
|||
}
|
||||
|
||||
type NewOrderRequest struct {
|
||||
RegistrationID *int64 `protobuf:"varint,1,opt,name=registrationID" json:"registrationID,omitempty"`
|
||||
Names []string `protobuf:"bytes,2,rep,name=names" json:"names,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
RegistrationID *int64 `protobuf:"varint,1,opt,name=registrationID" json:"registrationID,omitempty"`
|
||||
Names []string `protobuf:"bytes,2,rep,name=names" json:"names,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *NewOrderRequest) Reset() { *m = NewOrderRequest{} }
|
||||
func (m *NewOrderRequest) String() string { return proto1.CompactTextString(m) }
|
||||
func (*NewOrderRequest) ProtoMessage() {}
|
||||
func (*NewOrderRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
|
||||
func (m *NewOrderRequest) Reset() { *m = NewOrderRequest{} }
|
||||
func (m *NewOrderRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*NewOrderRequest) ProtoMessage() {}
|
||||
func (*NewOrderRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_f3baba040132fbcd, []int{7}
|
||||
}
|
||||
|
||||
func (m *NewOrderRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NewOrderRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *NewOrderRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_NewOrderRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *NewOrderRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_NewOrderRequest.Merge(m, src)
|
||||
}
|
||||
func (m *NewOrderRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_NewOrderRequest.Size(m)
|
||||
}
|
||||
func (m *NewOrderRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_NewOrderRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_NewOrderRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *NewOrderRequest) GetRegistrationID() int64 {
|
||||
if m != nil && m.RegistrationID != nil {
|
||||
|
|
@ -271,17 +428,39 @@ func (m *NewOrderRequest) GetNames() []string {
|
|||
}
|
||||
|
||||
type FinalizeOrderRequest struct {
|
||||
Order *core.Order `protobuf:"bytes,1,opt,name=order" json:"order,omitempty"`
|
||||
Csr []byte `protobuf:"bytes,2,opt,name=csr" json:"csr,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Order *proto1.Order `protobuf:"bytes,1,opt,name=order" json:"order,omitempty"`
|
||||
Csr []byte `protobuf:"bytes,2,opt,name=csr" json:"csr,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *FinalizeOrderRequest) Reset() { *m = FinalizeOrderRequest{} }
|
||||
func (m *FinalizeOrderRequest) String() string { return proto1.CompactTextString(m) }
|
||||
func (*FinalizeOrderRequest) ProtoMessage() {}
|
||||
func (*FinalizeOrderRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
|
||||
func (m *FinalizeOrderRequest) Reset() { *m = FinalizeOrderRequest{} }
|
||||
func (m *FinalizeOrderRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*FinalizeOrderRequest) ProtoMessage() {}
|
||||
func (*FinalizeOrderRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_f3baba040132fbcd, []int{8}
|
||||
}
|
||||
|
||||
func (m *FinalizeOrderRequest) GetOrder() *core.Order {
|
||||
func (m *FinalizeOrderRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_FinalizeOrderRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *FinalizeOrderRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_FinalizeOrderRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *FinalizeOrderRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_FinalizeOrderRequest.Merge(m, src)
|
||||
}
|
||||
func (m *FinalizeOrderRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_FinalizeOrderRequest.Size(m)
|
||||
}
|
||||
func (m *FinalizeOrderRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_FinalizeOrderRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_FinalizeOrderRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *FinalizeOrderRequest) GetOrder() *proto1.Order {
|
||||
if m != nil {
|
||||
return m.Order
|
||||
}
|
||||
|
|
@ -296,15 +475,59 @@ func (m *FinalizeOrderRequest) GetCsr() []byte {
|
|||
}
|
||||
|
||||
func init() {
|
||||
proto1.RegisterType((*NewAuthorizationRequest)(nil), "ra.NewAuthorizationRequest")
|
||||
proto1.RegisterType((*NewCertificateRequest)(nil), "ra.NewCertificateRequest")
|
||||
proto1.RegisterType((*UpdateRegistrationRequest)(nil), "ra.UpdateRegistrationRequest")
|
||||
proto1.RegisterType((*UpdateAuthorizationRequest)(nil), "ra.UpdateAuthorizationRequest")
|
||||
proto1.RegisterType((*PerformValidationRequest)(nil), "ra.PerformValidationRequest")
|
||||
proto1.RegisterType((*RevokeCertificateWithRegRequest)(nil), "ra.RevokeCertificateWithRegRequest")
|
||||
proto1.RegisterType((*AdministrativelyRevokeCertificateRequest)(nil), "ra.AdministrativelyRevokeCertificateRequest")
|
||||
proto1.RegisterType((*NewOrderRequest)(nil), "ra.NewOrderRequest")
|
||||
proto1.RegisterType((*FinalizeOrderRequest)(nil), "ra.FinalizeOrderRequest")
|
||||
proto.RegisterType((*NewAuthorizationRequest)(nil), "ra.NewAuthorizationRequest")
|
||||
proto.RegisterType((*NewCertificateRequest)(nil), "ra.NewCertificateRequest")
|
||||
proto.RegisterType((*UpdateRegistrationRequest)(nil), "ra.UpdateRegistrationRequest")
|
||||
proto.RegisterType((*UpdateAuthorizationRequest)(nil), "ra.UpdateAuthorizationRequest")
|
||||
proto.RegisterType((*PerformValidationRequest)(nil), "ra.PerformValidationRequest")
|
||||
proto.RegisterType((*RevokeCertificateWithRegRequest)(nil), "ra.RevokeCertificateWithRegRequest")
|
||||
proto.RegisterType((*AdministrativelyRevokeCertificateRequest)(nil), "ra.AdministrativelyRevokeCertificateRequest")
|
||||
proto.RegisterType((*NewOrderRequest)(nil), "ra.NewOrderRequest")
|
||||
proto.RegisterType((*FinalizeOrderRequest)(nil), "ra.FinalizeOrderRequest")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("ra/proto/ra.proto", fileDescriptor_f3baba040132fbcd) }
|
||||
|
||||
var fileDescriptor_f3baba040132fbcd = []byte{
|
||||
// 605 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xdb, 0x6e, 0xd3, 0x4c,
|
||||
0x10, 0x4e, 0xe2, 0xa6, 0x7f, 0x3b, 0xfd, 0xe9, 0x61, 0xda, 0x52, 0xd7, 0x14, 0xd1, 0x2e, 0x52,
|
||||
0x15, 0x0e, 0x4a, 0xa5, 0x5e, 0x21, 0x55, 0x08, 0x4a, 0x4b, 0x45, 0x84, 0x94, 0x22, 0x4b, 0x80,
|
||||
0xd4, 0x1b, 0x58, 0xec, 0x69, 0x62, 0x11, 0xdb, 0x61, 0xbd, 0x49, 0x48, 0x5e, 0x81, 0x57, 0xe0,
|
||||
0x61, 0x91, 0xd7, 0x9b, 0xc6, 0x76, 0x6c, 0x15, 0x84, 0xb8, 0x9b, 0x9d, 0xc3, 0x37, 0x33, 0xfe,
|
||||
0xe6, 0x93, 0x61, 0x43, 0xf0, 0xa3, 0xbe, 0x08, 0x65, 0x78, 0x24, 0x78, 0x53, 0x19, 0x58, 0x13,
|
||||
0xdc, 0xda, 0x76, 0x42, 0x41, 0x3a, 0x10, 0x9b, 0x49, 0x88, 0x5d, 0xc1, 0x4e, 0x9b, 0x46, 0xa7,
|
||||
0x03, 0xd9, 0x0d, 0x85, 0x37, 0xe1, 0xd2, 0x0b, 0x03, 0x9b, 0xbe, 0x0d, 0x28, 0x92, 0xf8, 0x08,
|
||||
0xea, 0x7c, 0x20, 0xbb, 0x13, 0xb3, 0xba, 0x5f, 0x6d, 0xac, 0x1c, 0x6f, 0x36, 0x55, 0x59, 0x36,
|
||||
0x35, 0xc9, 0xc0, 0x2d, 0xa8, 0x0b, 0xea, 0xb4, 0xce, 0xcd, 0xda, 0x7e, 0xb5, 0x61, 0xd8, 0xc9,
|
||||
0x83, 0xbd, 0x80, 0xed, 0x36, 0x8d, 0xce, 0x48, 0x48, 0xef, 0xda, 0x73, 0xb8, 0xa4, 0x29, 0xf2,
|
||||
0x3a, 0x18, 0x4e, 0x24, 0x14, 0xee, 0xff, 0x76, 0x6c, 0x96, 0x00, 0x84, 0xb0, 0xfb, 0xbe, 0xef,
|
||||
0xaa, 0xc2, 0x8e, 0x17, 0x49, 0x91, 0x19, 0xef, 0x10, 0x16, 0xbe, 0xf0, 0x88, 0xf4, 0x74, 0x98,
|
||||
0x4c, 0x97, 0x49, 0x54, 0x71, 0x7c, 0x0c, 0x8b, 0x03, 0x05, 0xa2, 0xb0, 0x8b, 0x33, 0x75, 0x06,
|
||||
0xfb, 0x59, 0x05, 0x2b, 0xe9, 0xf8, 0xb7, 0x5f, 0xe4, 0x10, 0x56, 0x9d, 0x2e, 0xef, 0xf5, 0x28,
|
||||
0xe8, 0x50, 0x2b, 0x70, 0xe9, 0xbb, 0xde, 0x2c, 0xe7, 0xc5, 0x27, 0xb0, 0x24, 0x28, 0xea, 0x87,
|
||||
0x41, 0x44, 0xa6, 0xa1, 0x50, 0xd7, 0x12, 0xd4, 0xb3, 0x69, 0x9e, 0x7d, 0x93, 0xc0, 0x7c, 0x30,
|
||||
0xdf, 0x91, 0xb8, 0x0e, 0x85, 0xff, 0x81, 0xf7, 0x3c, 0xf7, 0x1f, 0xcf, 0xc6, 0x3e, 0xc1, 0x03,
|
||||
0x9b, 0x86, 0xe1, 0x57, 0x4a, 0x51, 0xf8, 0xd1, 0x93, 0x5d, 0x9b, 0x3a, 0xd3, 0xae, 0x08, 0x0b,
|
||||
0x0e, 0x09, 0xa9, 0xa9, 0x54, 0xb6, 0xf2, 0x85, 0x2e, 0x69, 0x50, 0x65, 0xcf, 0xf8, 0x35, 0xd2,
|
||||
0xfc, 0xf6, 0xa1, 0x71, 0xea, 0xfa, 0x5e, 0xa0, 0x89, 0x18, 0x52, 0x6f, 0x3c, 0xd7, 0xf0, 0x4f,
|
||||
0x3b, 0xed, 0xc1, 0x32, 0x8f, 0x31, 0xdb, 0xdc, 0x4f, 0xbe, 0xe8, 0xb2, 0x3d, 0x73, 0xb0, 0x4b,
|
||||
0x58, 0x6b, 0xd3, 0xe8, 0x52, 0xb8, 0x24, 0x66, 0x77, 0xb4, 0x2a, 0x52, 0xb7, 0xd0, 0x3a, 0x57,
|
||||
0x2d, 0x0c, 0x3b, 0xe7, 0x8d, 0x57, 0x08, 0xb8, 0x4f, 0x91, 0x59, 0xdb, 0x37, 0x1a, 0xcb, 0x76,
|
||||
0xf2, 0x60, 0x6f, 0x61, 0xeb, 0xc2, 0x0b, 0x78, 0xcf, 0x9b, 0x50, 0x06, 0xf5, 0x00, 0xea, 0x61,
|
||||
0xfc, 0xd6, 0x74, 0xac, 0x24, 0x74, 0x24, 0x29, 0x49, 0x64, 0xaa, 0x82, 0xda, 0x8d, 0x0a, 0x8e,
|
||||
0x7f, 0x2c, 0xc2, 0x76, 0xfa, 0x2e, 0x35, 0x7b, 0x72, 0x8c, 0x27, 0x6a, 0xee, 0x74, 0x0c, 0x0b,
|
||||
0xee, 0xd8, 0x2a, 0xf0, 0xb1, 0x0a, 0x5e, 0xc0, 0x7a, 0x5e, 0xe3, 0x78, 0xaf, 0x29, 0x78, 0xb3,
|
||||
0x44, 0xf9, 0x56, 0xd1, 0xf1, 0xb0, 0x0a, 0xbe, 0x84, 0xd5, 0xac, 0x9e, 0x71, 0x57, 0xa3, 0xcc,
|
||||
0xf3, 0x65, 0x6d, 0xe8, 0x33, 0x9e, 0x45, 0x58, 0x05, 0x5b, 0x80, 0xf3, 0x82, 0xc6, 0xfb, 0x31,
|
||||
0x4a, 0xa9, 0xd0, 0x4b, 0x96, 0x7a, 0x03, 0x1b, 0x73, 0x5a, 0xc0, 0xbd, 0x18, 0xa9, 0x4c, 0x22,
|
||||
0x65, 0x6b, 0xb5, 0xc1, 0x2c, 0x3b, 0x73, 0x7c, 0x18, 0x03, 0xde, 0x22, 0x02, 0x4b, 0x93, 0xfb,
|
||||
0xda, 0xef, 0xcb, 0x31, 0xab, 0xe0, 0x09, 0xdc, 0x3d, 0x27, 0xee, 0x48, 0x6f, 0x98, 0x5f, 0xb4,
|
||||
0x88, 0xb2, 0x5c, 0xf1, 0x73, 0xd8, 0x99, 0x15, 0x67, 0x29, 0x2b, 0x1a, 0x3f, 0x5f, 0xfe, 0x19,
|
||||
0x0e, 0x6e, 0x55, 0x14, 0x3e, 0x8d, 0x97, 0xfa, 0x5d, 0xe1, 0xe5, 0x3b, 0x34, 0x61, 0x69, 0xaa,
|
||||
0x20, 0xdc, 0xd4, 0xf4, 0xa7, 0x2f, 0xdf, 0x4a, 0x9f, 0x3a, 0xab, 0xe0, 0x33, 0xb8, 0x93, 0x11,
|
||||
0x08, 0x9a, 0x71, 0x51, 0x91, 0x66, 0x72, 0x95, 0xaf, 0xfe, 0xbb, 0xaa, 0xab, 0x7f, 0xd4, 0xaf,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0x3a, 0x20, 0x77, 0x28, 0xd2, 0x06, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
@ -315,20 +538,21 @@ var _ grpc.ClientConn
|
|||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// Client API for RegistrationAuthority service
|
||||
|
||||
// RegistrationAuthorityClient is the client API for RegistrationAuthority service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type RegistrationAuthorityClient interface {
|
||||
NewRegistration(ctx context.Context, in *core.Registration, opts ...grpc.CallOption) (*core.Registration, error)
|
||||
NewAuthorization(ctx context.Context, in *NewAuthorizationRequest, opts ...grpc.CallOption) (*core.Authorization, error)
|
||||
NewCertificate(ctx context.Context, in *NewCertificateRequest, opts ...grpc.CallOption) (*core.Certificate, error)
|
||||
UpdateRegistration(ctx context.Context, in *UpdateRegistrationRequest, opts ...grpc.CallOption) (*core.Registration, error)
|
||||
PerformValidation(ctx context.Context, in *PerformValidationRequest, opts ...grpc.CallOption) (*core.Authorization, error)
|
||||
RevokeCertificateWithReg(ctx context.Context, in *RevokeCertificateWithRegRequest, opts ...grpc.CallOption) (*core.Empty, error)
|
||||
DeactivateRegistration(ctx context.Context, in *core.Registration, opts ...grpc.CallOption) (*core.Empty, error)
|
||||
DeactivateAuthorization(ctx context.Context, in *core.Authorization, opts ...grpc.CallOption) (*core.Empty, error)
|
||||
AdministrativelyRevokeCertificate(ctx context.Context, in *AdministrativelyRevokeCertificateRequest, opts ...grpc.CallOption) (*core.Empty, error)
|
||||
NewOrder(ctx context.Context, in *NewOrderRequest, opts ...grpc.CallOption) (*core.Order, error)
|
||||
FinalizeOrder(ctx context.Context, in *FinalizeOrderRequest, opts ...grpc.CallOption) (*core.Order, error)
|
||||
NewRegistration(ctx context.Context, in *proto1.Registration, opts ...grpc.CallOption) (*proto1.Registration, error)
|
||||
NewAuthorization(ctx context.Context, in *NewAuthorizationRequest, opts ...grpc.CallOption) (*proto1.Authorization, error)
|
||||
NewCertificate(ctx context.Context, in *NewCertificateRequest, opts ...grpc.CallOption) (*proto1.Certificate, error)
|
||||
UpdateRegistration(ctx context.Context, in *UpdateRegistrationRequest, opts ...grpc.CallOption) (*proto1.Registration, error)
|
||||
PerformValidation(ctx context.Context, in *PerformValidationRequest, opts ...grpc.CallOption) (*proto1.Authorization, error)
|
||||
RevokeCertificateWithReg(ctx context.Context, in *RevokeCertificateWithRegRequest, opts ...grpc.CallOption) (*proto1.Empty, error)
|
||||
DeactivateRegistration(ctx context.Context, in *proto1.Registration, opts ...grpc.CallOption) (*proto1.Empty, error)
|
||||
DeactivateAuthorization(ctx context.Context, in *proto1.Authorization, opts ...grpc.CallOption) (*proto1.Empty, error)
|
||||
AdministrativelyRevokeCertificate(ctx context.Context, in *AdministrativelyRevokeCertificateRequest, opts ...grpc.CallOption) (*proto1.Empty, error)
|
||||
NewOrder(ctx context.Context, in *NewOrderRequest, opts ...grpc.CallOption) (*proto1.Order, error)
|
||||
FinalizeOrder(ctx context.Context, in *FinalizeOrderRequest, opts ...grpc.CallOption) (*proto1.Order, error)
|
||||
}
|
||||
|
||||
type registrationAuthorityClient struct {
|
||||
|
|
@ -339,119 +563,156 @@ func NewRegistrationAuthorityClient(cc *grpc.ClientConn) RegistrationAuthorityCl
|
|||
return ®istrationAuthorityClient{cc}
|
||||
}
|
||||
|
||||
func (c *registrationAuthorityClient) NewRegistration(ctx context.Context, in *core.Registration, opts ...grpc.CallOption) (*core.Registration, error) {
|
||||
out := new(core.Registration)
|
||||
err := grpc.Invoke(ctx, "/ra.RegistrationAuthority/NewRegistration", in, out, c.cc, opts...)
|
||||
func (c *registrationAuthorityClient) NewRegistration(ctx context.Context, in *proto1.Registration, opts ...grpc.CallOption) (*proto1.Registration, error) {
|
||||
out := new(proto1.Registration)
|
||||
err := c.cc.Invoke(ctx, "/ra.RegistrationAuthority/NewRegistration", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *registrationAuthorityClient) NewAuthorization(ctx context.Context, in *NewAuthorizationRequest, opts ...grpc.CallOption) (*core.Authorization, error) {
|
||||
out := new(core.Authorization)
|
||||
err := grpc.Invoke(ctx, "/ra.RegistrationAuthority/NewAuthorization", in, out, c.cc, opts...)
|
||||
func (c *registrationAuthorityClient) NewAuthorization(ctx context.Context, in *NewAuthorizationRequest, opts ...grpc.CallOption) (*proto1.Authorization, error) {
|
||||
out := new(proto1.Authorization)
|
||||
err := c.cc.Invoke(ctx, "/ra.RegistrationAuthority/NewAuthorization", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *registrationAuthorityClient) NewCertificate(ctx context.Context, in *NewCertificateRequest, opts ...grpc.CallOption) (*core.Certificate, error) {
|
||||
out := new(core.Certificate)
|
||||
err := grpc.Invoke(ctx, "/ra.RegistrationAuthority/NewCertificate", in, out, c.cc, opts...)
|
||||
func (c *registrationAuthorityClient) NewCertificate(ctx context.Context, in *NewCertificateRequest, opts ...grpc.CallOption) (*proto1.Certificate, error) {
|
||||
out := new(proto1.Certificate)
|
||||
err := c.cc.Invoke(ctx, "/ra.RegistrationAuthority/NewCertificate", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *registrationAuthorityClient) UpdateRegistration(ctx context.Context, in *UpdateRegistrationRequest, opts ...grpc.CallOption) (*core.Registration, error) {
|
||||
out := new(core.Registration)
|
||||
err := grpc.Invoke(ctx, "/ra.RegistrationAuthority/UpdateRegistration", in, out, c.cc, opts...)
|
||||
func (c *registrationAuthorityClient) UpdateRegistration(ctx context.Context, in *UpdateRegistrationRequest, opts ...grpc.CallOption) (*proto1.Registration, error) {
|
||||
out := new(proto1.Registration)
|
||||
err := c.cc.Invoke(ctx, "/ra.RegistrationAuthority/UpdateRegistration", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *registrationAuthorityClient) PerformValidation(ctx context.Context, in *PerformValidationRequest, opts ...grpc.CallOption) (*core.Authorization, error) {
|
||||
out := new(core.Authorization)
|
||||
err := grpc.Invoke(ctx, "/ra.RegistrationAuthority/PerformValidation", in, out, c.cc, opts...)
|
||||
func (c *registrationAuthorityClient) PerformValidation(ctx context.Context, in *PerformValidationRequest, opts ...grpc.CallOption) (*proto1.Authorization, error) {
|
||||
out := new(proto1.Authorization)
|
||||
err := c.cc.Invoke(ctx, "/ra.RegistrationAuthority/PerformValidation", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *registrationAuthorityClient) RevokeCertificateWithReg(ctx context.Context, in *RevokeCertificateWithRegRequest, opts ...grpc.CallOption) (*core.Empty, error) {
|
||||
out := new(core.Empty)
|
||||
err := grpc.Invoke(ctx, "/ra.RegistrationAuthority/RevokeCertificateWithReg", in, out, c.cc, opts...)
|
||||
func (c *registrationAuthorityClient) RevokeCertificateWithReg(ctx context.Context, in *RevokeCertificateWithRegRequest, opts ...grpc.CallOption) (*proto1.Empty, error) {
|
||||
out := new(proto1.Empty)
|
||||
err := c.cc.Invoke(ctx, "/ra.RegistrationAuthority/RevokeCertificateWithReg", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *registrationAuthorityClient) DeactivateRegistration(ctx context.Context, in *core.Registration, opts ...grpc.CallOption) (*core.Empty, error) {
|
||||
out := new(core.Empty)
|
||||
err := grpc.Invoke(ctx, "/ra.RegistrationAuthority/DeactivateRegistration", in, out, c.cc, opts...)
|
||||
func (c *registrationAuthorityClient) DeactivateRegistration(ctx context.Context, in *proto1.Registration, opts ...grpc.CallOption) (*proto1.Empty, error) {
|
||||
out := new(proto1.Empty)
|
||||
err := c.cc.Invoke(ctx, "/ra.RegistrationAuthority/DeactivateRegistration", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *registrationAuthorityClient) DeactivateAuthorization(ctx context.Context, in *core.Authorization, opts ...grpc.CallOption) (*core.Empty, error) {
|
||||
out := new(core.Empty)
|
||||
err := grpc.Invoke(ctx, "/ra.RegistrationAuthority/DeactivateAuthorization", in, out, c.cc, opts...)
|
||||
func (c *registrationAuthorityClient) DeactivateAuthorization(ctx context.Context, in *proto1.Authorization, opts ...grpc.CallOption) (*proto1.Empty, error) {
|
||||
out := new(proto1.Empty)
|
||||
err := c.cc.Invoke(ctx, "/ra.RegistrationAuthority/DeactivateAuthorization", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *registrationAuthorityClient) AdministrativelyRevokeCertificate(ctx context.Context, in *AdministrativelyRevokeCertificateRequest, opts ...grpc.CallOption) (*core.Empty, error) {
|
||||
out := new(core.Empty)
|
||||
err := grpc.Invoke(ctx, "/ra.RegistrationAuthority/AdministrativelyRevokeCertificate", in, out, c.cc, opts...)
|
||||
func (c *registrationAuthorityClient) AdministrativelyRevokeCertificate(ctx context.Context, in *AdministrativelyRevokeCertificateRequest, opts ...grpc.CallOption) (*proto1.Empty, error) {
|
||||
out := new(proto1.Empty)
|
||||
err := c.cc.Invoke(ctx, "/ra.RegistrationAuthority/AdministrativelyRevokeCertificate", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *registrationAuthorityClient) NewOrder(ctx context.Context, in *NewOrderRequest, opts ...grpc.CallOption) (*core.Order, error) {
|
||||
out := new(core.Order)
|
||||
err := grpc.Invoke(ctx, "/ra.RegistrationAuthority/NewOrder", in, out, c.cc, opts...)
|
||||
func (c *registrationAuthorityClient) NewOrder(ctx context.Context, in *NewOrderRequest, opts ...grpc.CallOption) (*proto1.Order, error) {
|
||||
out := new(proto1.Order)
|
||||
err := c.cc.Invoke(ctx, "/ra.RegistrationAuthority/NewOrder", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *registrationAuthorityClient) FinalizeOrder(ctx context.Context, in *FinalizeOrderRequest, opts ...grpc.CallOption) (*core.Order, error) {
|
||||
out := new(core.Order)
|
||||
err := grpc.Invoke(ctx, "/ra.RegistrationAuthority/FinalizeOrder", in, out, c.cc, opts...)
|
||||
func (c *registrationAuthorityClient) FinalizeOrder(ctx context.Context, in *FinalizeOrderRequest, opts ...grpc.CallOption) (*proto1.Order, error) {
|
||||
out := new(proto1.Order)
|
||||
err := c.cc.Invoke(ctx, "/ra.RegistrationAuthority/FinalizeOrder", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for RegistrationAuthority service
|
||||
|
||||
// RegistrationAuthorityServer is the server API for RegistrationAuthority service.
|
||||
type RegistrationAuthorityServer interface {
|
||||
NewRegistration(context.Context, *core.Registration) (*core.Registration, error)
|
||||
NewAuthorization(context.Context, *NewAuthorizationRequest) (*core.Authorization, error)
|
||||
NewCertificate(context.Context, *NewCertificateRequest) (*core.Certificate, error)
|
||||
UpdateRegistration(context.Context, *UpdateRegistrationRequest) (*core.Registration, error)
|
||||
PerformValidation(context.Context, *PerformValidationRequest) (*core.Authorization, error)
|
||||
RevokeCertificateWithReg(context.Context, *RevokeCertificateWithRegRequest) (*core.Empty, error)
|
||||
DeactivateRegistration(context.Context, *core.Registration) (*core.Empty, error)
|
||||
DeactivateAuthorization(context.Context, *core.Authorization) (*core.Empty, error)
|
||||
AdministrativelyRevokeCertificate(context.Context, *AdministrativelyRevokeCertificateRequest) (*core.Empty, error)
|
||||
NewOrder(context.Context, *NewOrderRequest) (*core.Order, error)
|
||||
FinalizeOrder(context.Context, *FinalizeOrderRequest) (*core.Order, error)
|
||||
NewRegistration(context.Context, *proto1.Registration) (*proto1.Registration, error)
|
||||
NewAuthorization(context.Context, *NewAuthorizationRequest) (*proto1.Authorization, error)
|
||||
NewCertificate(context.Context, *NewCertificateRequest) (*proto1.Certificate, error)
|
||||
UpdateRegistration(context.Context, *UpdateRegistrationRequest) (*proto1.Registration, error)
|
||||
PerformValidation(context.Context, *PerformValidationRequest) (*proto1.Authorization, error)
|
||||
RevokeCertificateWithReg(context.Context, *RevokeCertificateWithRegRequest) (*proto1.Empty, error)
|
||||
DeactivateRegistration(context.Context, *proto1.Registration) (*proto1.Empty, error)
|
||||
DeactivateAuthorization(context.Context, *proto1.Authorization) (*proto1.Empty, error)
|
||||
AdministrativelyRevokeCertificate(context.Context, *AdministrativelyRevokeCertificateRequest) (*proto1.Empty, error)
|
||||
NewOrder(context.Context, *NewOrderRequest) (*proto1.Order, error)
|
||||
FinalizeOrder(context.Context, *FinalizeOrderRequest) (*proto1.Order, error)
|
||||
}
|
||||
|
||||
// UnimplementedRegistrationAuthorityServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedRegistrationAuthorityServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedRegistrationAuthorityServer) NewRegistration(ctx context.Context, req *proto1.Registration) (*proto1.Registration, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method NewRegistration not implemented")
|
||||
}
|
||||
func (*UnimplementedRegistrationAuthorityServer) NewAuthorization(ctx context.Context, req *NewAuthorizationRequest) (*proto1.Authorization, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method NewAuthorization not implemented")
|
||||
}
|
||||
func (*UnimplementedRegistrationAuthorityServer) NewCertificate(ctx context.Context, req *NewCertificateRequest) (*proto1.Certificate, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method NewCertificate not implemented")
|
||||
}
|
||||
func (*UnimplementedRegistrationAuthorityServer) UpdateRegistration(ctx context.Context, req *UpdateRegistrationRequest) (*proto1.Registration, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateRegistration not implemented")
|
||||
}
|
||||
func (*UnimplementedRegistrationAuthorityServer) PerformValidation(ctx context.Context, req *PerformValidationRequest) (*proto1.Authorization, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method PerformValidation not implemented")
|
||||
}
|
||||
func (*UnimplementedRegistrationAuthorityServer) RevokeCertificateWithReg(ctx context.Context, req *RevokeCertificateWithRegRequest) (*proto1.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RevokeCertificateWithReg not implemented")
|
||||
}
|
||||
func (*UnimplementedRegistrationAuthorityServer) DeactivateRegistration(ctx context.Context, req *proto1.Registration) (*proto1.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DeactivateRegistration not implemented")
|
||||
}
|
||||
func (*UnimplementedRegistrationAuthorityServer) DeactivateAuthorization(ctx context.Context, req *proto1.Authorization) (*proto1.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DeactivateAuthorization not implemented")
|
||||
}
|
||||
func (*UnimplementedRegistrationAuthorityServer) AdministrativelyRevokeCertificate(ctx context.Context, req *AdministrativelyRevokeCertificateRequest) (*proto1.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AdministrativelyRevokeCertificate not implemented")
|
||||
}
|
||||
func (*UnimplementedRegistrationAuthorityServer) NewOrder(ctx context.Context, req *NewOrderRequest) (*proto1.Order, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method NewOrder not implemented")
|
||||
}
|
||||
func (*UnimplementedRegistrationAuthorityServer) FinalizeOrder(ctx context.Context, req *FinalizeOrderRequest) (*proto1.Order, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method FinalizeOrder not implemented")
|
||||
}
|
||||
|
||||
func RegisterRegistrationAuthorityServer(s *grpc.Server, srv RegistrationAuthorityServer) {
|
||||
|
|
@ -459,7 +720,7 @@ func RegisterRegistrationAuthorityServer(s *grpc.Server, srv RegistrationAuthori
|
|||
}
|
||||
|
||||
func _RegistrationAuthority_NewRegistration_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(core.Registration)
|
||||
in := new(proto1.Registration)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -471,7 +732,7 @@ func _RegistrationAuthority_NewRegistration_Handler(srv interface{}, ctx context
|
|||
FullMethod: "/ra.RegistrationAuthority/NewRegistration",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(RegistrationAuthorityServer).NewRegistration(ctx, req.(*core.Registration))
|
||||
return srv.(RegistrationAuthorityServer).NewRegistration(ctx, req.(*proto1.Registration))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
|
@ -567,7 +828,7 @@ func _RegistrationAuthority_RevokeCertificateWithReg_Handler(srv interface{}, ct
|
|||
}
|
||||
|
||||
func _RegistrationAuthority_DeactivateRegistration_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(core.Registration)
|
||||
in := new(proto1.Registration)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -579,13 +840,13 @@ func _RegistrationAuthority_DeactivateRegistration_Handler(srv interface{}, ctx
|
|||
FullMethod: "/ra.RegistrationAuthority/DeactivateRegistration",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(RegistrationAuthorityServer).DeactivateRegistration(ctx, req.(*core.Registration))
|
||||
return srv.(RegistrationAuthorityServer).DeactivateRegistration(ctx, req.(*proto1.Registration))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _RegistrationAuthority_DeactivateAuthorization_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(core.Authorization)
|
||||
in := new(proto1.Authorization)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -597,7 +858,7 @@ func _RegistrationAuthority_DeactivateAuthorization_Handler(srv interface{}, ctx
|
|||
FullMethod: "/ra.RegistrationAuthority/DeactivateAuthorization",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(RegistrationAuthorityServer).DeactivateAuthorization(ctx, req.(*core.Authorization))
|
||||
return srv.(RegistrationAuthorityServer).DeactivateAuthorization(ctx, req.(*proto1.Authorization))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
|
@ -708,47 +969,3 @@ var _RegistrationAuthority_serviceDesc = grpc.ServiceDesc{
|
|||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "ra/proto/ra.proto",
|
||||
}
|
||||
|
||||
func init() { proto1.RegisterFile("ra/proto/ra.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 605 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0xdb, 0x6e, 0xd3, 0x4c,
|
||||
0x10, 0x4e, 0xe2, 0xa6, 0x7f, 0x3b, 0xfd, 0xe9, 0x61, 0xda, 0x52, 0xd7, 0x14, 0xd1, 0x2e, 0x52,
|
||||
0x15, 0x0e, 0x4a, 0xa5, 0x5e, 0x21, 0x55, 0x08, 0x4a, 0x4b, 0x45, 0x84, 0x94, 0x22, 0x4b, 0x80,
|
||||
0xd4, 0x1b, 0x58, 0xec, 0x69, 0x62, 0x11, 0xdb, 0x61, 0xbd, 0x49, 0x48, 0x5e, 0x81, 0x57, 0xe0,
|
||||
0x61, 0x91, 0xd7, 0x9b, 0xc6, 0x76, 0x6c, 0x15, 0x84, 0xb8, 0x9b, 0x9d, 0xc3, 0x37, 0x33, 0xfe,
|
||||
0xe6, 0x93, 0x61, 0x43, 0xf0, 0xa3, 0xbe, 0x08, 0x65, 0x78, 0x24, 0x78, 0x53, 0x19, 0x58, 0x13,
|
||||
0xdc, 0xda, 0x76, 0x42, 0x41, 0x3a, 0x10, 0x9b, 0x49, 0x88, 0x5d, 0xc1, 0x4e, 0x9b, 0x46, 0xa7,
|
||||
0x03, 0xd9, 0x0d, 0x85, 0x37, 0xe1, 0xd2, 0x0b, 0x03, 0x9b, 0xbe, 0x0d, 0x28, 0x92, 0xf8, 0x08,
|
||||
0xea, 0x7c, 0x20, 0xbb, 0x13, 0xb3, 0xba, 0x5f, 0x6d, 0xac, 0x1c, 0x6f, 0x36, 0x55, 0x59, 0x36,
|
||||
0x35, 0xc9, 0xc0, 0x2d, 0xa8, 0x0b, 0xea, 0xb4, 0xce, 0xcd, 0xda, 0x7e, 0xb5, 0x61, 0xd8, 0xc9,
|
||||
0x83, 0xbd, 0x80, 0xed, 0x36, 0x8d, 0xce, 0x48, 0x48, 0xef, 0xda, 0x73, 0xb8, 0xa4, 0x29, 0xf2,
|
||||
0x3a, 0x18, 0x4e, 0x24, 0x14, 0xee, 0xff, 0x76, 0x6c, 0x96, 0x00, 0x84, 0xb0, 0xfb, 0xbe, 0xef,
|
||||
0xaa, 0xc2, 0x8e, 0x17, 0x49, 0x91, 0x19, 0xef, 0x10, 0x16, 0xbe, 0xf0, 0x88, 0xf4, 0x74, 0x98,
|
||||
0x4c, 0x97, 0x49, 0x54, 0x71, 0x7c, 0x0c, 0x8b, 0x03, 0x05, 0xa2, 0xb0, 0x8b, 0x33, 0x75, 0x06,
|
||||
0xfb, 0x59, 0x05, 0x2b, 0xe9, 0xf8, 0xb7, 0x5f, 0xe4, 0x10, 0x56, 0x9d, 0x2e, 0xef, 0xf5, 0x28,
|
||||
0xe8, 0x50, 0x2b, 0x70, 0xe9, 0xbb, 0xde, 0x2c, 0xe7, 0xc5, 0x27, 0xb0, 0x24, 0x28, 0xea, 0x87,
|
||||
0x41, 0x44, 0xa6, 0xa1, 0x50, 0xd7, 0x12, 0xd4, 0xb3, 0x69, 0x9e, 0x7d, 0x93, 0xc0, 0x7c, 0x30,
|
||||
0xdf, 0x91, 0xb8, 0x0e, 0x85, 0xff, 0x81, 0xf7, 0x3c, 0xf7, 0x1f, 0xcf, 0xc6, 0x3e, 0xc1, 0x03,
|
||||
0x9b, 0x86, 0xe1, 0x57, 0x4a, 0x51, 0xf8, 0xd1, 0x93, 0x5d, 0x9b, 0x3a, 0xd3, 0xae, 0x08, 0x0b,
|
||||
0x0e, 0x09, 0xa9, 0xa9, 0x54, 0xb6, 0xf2, 0x85, 0x2e, 0x69, 0x50, 0x65, 0xcf, 0xf8, 0x35, 0xd2,
|
||||
0xfc, 0xf6, 0xa1, 0x71, 0xea, 0xfa, 0x5e, 0xa0, 0x89, 0x18, 0x52, 0x6f, 0x3c, 0xd7, 0xf0, 0x4f,
|
||||
0x3b, 0xed, 0xc1, 0x32, 0x8f, 0x31, 0xdb, 0xdc, 0x4f, 0xbe, 0xe8, 0xb2, 0x3d, 0x73, 0xb0, 0x4b,
|
||||
0x58, 0x6b, 0xd3, 0xe8, 0x52, 0xb8, 0x24, 0x66, 0x77, 0xb4, 0x2a, 0x52, 0xb7, 0xd0, 0x3a, 0x57,
|
||||
0x2d, 0x0c, 0x3b, 0xe7, 0x8d, 0x57, 0x08, 0xb8, 0x4f, 0x91, 0x59, 0xdb, 0x37, 0x1a, 0xcb, 0x76,
|
||||
0xf2, 0x60, 0x6f, 0x61, 0xeb, 0xc2, 0x0b, 0x78, 0xcf, 0x9b, 0x50, 0x06, 0xf5, 0x00, 0xea, 0x61,
|
||||
0xfc, 0xd6, 0x74, 0xac, 0x24, 0x74, 0x24, 0x29, 0x49, 0x64, 0xaa, 0x82, 0xda, 0x8d, 0x0a, 0x8e,
|
||||
0x7f, 0x2c, 0xc2, 0x76, 0xfa, 0x2e, 0x35, 0x7b, 0x72, 0x8c, 0x27, 0x6a, 0xee, 0x74, 0x0c, 0x0b,
|
||||
0xee, 0xd8, 0x2a, 0xf0, 0xb1, 0x0a, 0x5e, 0xc0, 0x7a, 0x5e, 0xe3, 0x78, 0xaf, 0x29, 0x78, 0xb3,
|
||||
0x44, 0xf9, 0x56, 0xd1, 0xf1, 0xb0, 0x0a, 0xbe, 0x84, 0xd5, 0xac, 0x9e, 0x71, 0x57, 0xa3, 0xcc,
|
||||
0xf3, 0x65, 0x6d, 0xe8, 0x33, 0x9e, 0x45, 0x58, 0x05, 0x5b, 0x80, 0xf3, 0x82, 0xc6, 0xfb, 0x31,
|
||||
0x4a, 0xa9, 0xd0, 0x4b, 0x96, 0x7a, 0x03, 0x1b, 0x73, 0x5a, 0xc0, 0xbd, 0x18, 0xa9, 0x4c, 0x22,
|
||||
0x65, 0x6b, 0xb5, 0xc1, 0x2c, 0x3b, 0x73, 0x7c, 0x18, 0x03, 0xde, 0x22, 0x02, 0x4b, 0x93, 0xfb,
|
||||
0xda, 0xef, 0xcb, 0x31, 0xab, 0xe0, 0x09, 0xdc, 0x3d, 0x27, 0xee, 0x48, 0x6f, 0x98, 0x5f, 0xb4,
|
||||
0x88, 0xb2, 0x5c, 0xf1, 0x73, 0xd8, 0x99, 0x15, 0x67, 0x29, 0x2b, 0x1a, 0x3f, 0x5f, 0xfe, 0x19,
|
||||
0x0e, 0x6e, 0x55, 0x14, 0x3e, 0x8d, 0x97, 0xfa, 0x5d, 0xe1, 0xe5, 0x3b, 0x34, 0x61, 0x69, 0xaa,
|
||||
0x20, 0xdc, 0xd4, 0xf4, 0xa7, 0x2f, 0xdf, 0x4a, 0x9f, 0x3a, 0xab, 0xe0, 0x33, 0xb8, 0x93, 0x11,
|
||||
0x08, 0x9a, 0x71, 0x51, 0x91, 0x66, 0x72, 0x95, 0xaf, 0xfe, 0xbb, 0xaa, 0xab, 0x7f, 0xd4, 0xaf,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0x3a, 0x20, 0x77, 0x28, 0xd2, 0x06, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
|||
1987
sa/proto/sa.pb.go
1987
sa/proto/sa.pb.go
File diff suppressed because it is too large
Load Diff
4
test.sh
4
test.sh
|
|
@ -239,8 +239,8 @@ if [[ "$RUN" =~ "generate" ]] ; then
|
|||
# stringer: checking package: grpc/bcodes.go:6:2: could not import
|
||||
# github.com/letsencrypt/boulder/probs (can't find import:
|
||||
# github.com/letsencrypt/boulder/probs)
|
||||
go install ./probs
|
||||
go install google.golang.org/grpc/codes
|
||||
run go install ./probs
|
||||
run go install ./vendor/google.golang.org/grpc/codes
|
||||
run_and_expect_silence go generate ./...
|
||||
# Because the `mock` package we use to generate mocks does not properly
|
||||
# support vendored dependencies[0] we are forced to sed out any references to
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ ENV GO_VERSION_TO_INSTALL %%GO_VERSION%%
|
|||
|
||||
# Copied from https://github.com/docker-library/golang/blob/master/Dockerfile-debian.template
|
||||
ENV GOPATH /go
|
||||
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
|
||||
ENV PATH $GOPATH/bin:/usr/local/go/bin:/usr/local/protoc/bin:$PATH
|
||||
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
|
||||
WORKDIR $GOPATH
|
||||
|
||||
|
|
|
|||
|
|
@ -16,13 +16,16 @@ apt-get install -y --no-install-recommends \
|
|||
ruby \
|
||||
ruby-dev \
|
||||
rsyslog \
|
||||
protobuf-compiler \
|
||||
softhsm \
|
||||
build-essential \
|
||||
cmake \
|
||||
libssl-dev \
|
||||
libseccomp-dev \
|
||||
opensc
|
||||
opensc \
|
||||
unzip
|
||||
|
||||
curl -L https://github.com/google/protobuf/releases/download/v3.6.1/protoc-3.6.1-linux-x86_64.zip -o /tmp/protoc.zip
|
||||
unzip /tmp/protoc.zip -d /usr/local/protoc
|
||||
|
||||
# Override default GOBIN and GOPATH
|
||||
export GOBIN=/usr/local/bin GOPATH=/tmp/gopath
|
||||
|
|
@ -43,16 +46,6 @@ go get \
|
|||
golang.org/x/tools/cmd/stringer \
|
||||
github.com/gordonklaus/ineffassign
|
||||
|
||||
# grpc uses a version attestation variable of the form grpc.SupportPackageIsVersionN
|
||||
# where N is the generated code version shared between protoc-gen-go and grpc-go
|
||||
# and is used to keep their mappings in sync. Check out the specific version
|
||||
# we used to generate the checked-in protobuf mappings so that we get the
|
||||
# same mappings + version number even if protoc-gen-go bumps the generated code
|
||||
# version
|
||||
cd $GOPATH/src/github.com/golang/protobuf/protoc-gen-go
|
||||
git checkout c9c7427a2a70d2eb3bafa0ab2dc163e45f143317
|
||||
go install ./
|
||||
|
||||
git clone https://github.com/certbot/certbot /certbot
|
||||
cd /certbot
|
||||
./letsencrypt-auto --os-packages-only
|
||||
|
|
|
|||
|
|
@ -1,34 +1,21 @@
|
|||
// Code generated by protoc-gen-go.
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: va/proto/va.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package proto is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
va/proto/va.proto
|
||||
|
||||
It has these top-level messages:
|
||||
IsCAAValidRequest
|
||||
IsCAAValidResponse
|
||||
PerformValidationRequest
|
||||
AuthzMeta
|
||||
ValidationResult
|
||||
*/
|
||||
package proto
|
||||
|
||||
import proto1 "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import core "github.com/letsencrypt/boulder/core/proto"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
proto1 "github.com/letsencrypt/boulder/core/proto"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto1.Marshal
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
|
|
@ -36,20 +23,42 @@ var _ = math.Inf
|
|||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto1.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type IsCAAValidRequest struct {
|
||||
// NOTE: Domain may be a name with a wildcard prefix (e.g. `*.example.com`)
|
||||
Domain *string `protobuf:"bytes,1,opt,name=domain" json:"domain,omitempty"`
|
||||
ValidationMethod *string `protobuf:"bytes,2,opt,name=validationMethod" json:"validationMethod,omitempty"`
|
||||
AccountURIID *int64 `protobuf:"varint,3,opt,name=accountURIID" json:"accountURIID,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Domain *string `protobuf:"bytes,1,opt,name=domain" json:"domain,omitempty"`
|
||||
ValidationMethod *string `protobuf:"bytes,2,opt,name=validationMethod" json:"validationMethod,omitempty"`
|
||||
AccountURIID *int64 `protobuf:"varint,3,opt,name=accountURIID" json:"accountURIID,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *IsCAAValidRequest) Reset() { *m = IsCAAValidRequest{} }
|
||||
func (m *IsCAAValidRequest) String() string { return proto1.CompactTextString(m) }
|
||||
func (*IsCAAValidRequest) ProtoMessage() {}
|
||||
func (*IsCAAValidRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
func (m *IsCAAValidRequest) Reset() { *m = IsCAAValidRequest{} }
|
||||
func (m *IsCAAValidRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*IsCAAValidRequest) ProtoMessage() {}
|
||||
func (*IsCAAValidRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_b39cc52ec1cb3a92, []int{0}
|
||||
}
|
||||
|
||||
func (m *IsCAAValidRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_IsCAAValidRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *IsCAAValidRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_IsCAAValidRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *IsCAAValidRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_IsCAAValidRequest.Merge(m, src)
|
||||
}
|
||||
func (m *IsCAAValidRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_IsCAAValidRequest.Size(m)
|
||||
}
|
||||
func (m *IsCAAValidRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_IsCAAValidRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_IsCAAValidRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *IsCAAValidRequest) GetDomain() string {
|
||||
if m != nil && m.Domain != nil {
|
||||
|
|
@ -74,16 +83,38 @@ func (m *IsCAAValidRequest) GetAccountURIID() int64 {
|
|||
|
||||
// If CAA is valid for the requested domain, the problem will be empty
|
||||
type IsCAAValidResponse struct {
|
||||
Problem *core.ProblemDetails `protobuf:"bytes,1,opt,name=problem" json:"problem,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Problem *proto1.ProblemDetails `protobuf:"bytes,1,opt,name=problem" json:"problem,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *IsCAAValidResponse) Reset() { *m = IsCAAValidResponse{} }
|
||||
func (m *IsCAAValidResponse) String() string { return proto1.CompactTextString(m) }
|
||||
func (*IsCAAValidResponse) ProtoMessage() {}
|
||||
func (*IsCAAValidResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
func (m *IsCAAValidResponse) Reset() { *m = IsCAAValidResponse{} }
|
||||
func (m *IsCAAValidResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*IsCAAValidResponse) ProtoMessage() {}
|
||||
func (*IsCAAValidResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_b39cc52ec1cb3a92, []int{1}
|
||||
}
|
||||
|
||||
func (m *IsCAAValidResponse) GetProblem() *core.ProblemDetails {
|
||||
func (m *IsCAAValidResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_IsCAAValidResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *IsCAAValidResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_IsCAAValidResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *IsCAAValidResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_IsCAAValidResponse.Merge(m, src)
|
||||
}
|
||||
func (m *IsCAAValidResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_IsCAAValidResponse.Size(m)
|
||||
}
|
||||
func (m *IsCAAValidResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_IsCAAValidResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_IsCAAValidResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *IsCAAValidResponse) GetProblem() *proto1.ProblemDetails {
|
||||
if m != nil {
|
||||
return m.Problem
|
||||
}
|
||||
|
|
@ -91,16 +122,38 @@ func (m *IsCAAValidResponse) GetProblem() *core.ProblemDetails {
|
|||
}
|
||||
|
||||
type PerformValidationRequest struct {
|
||||
Domain *string `protobuf:"bytes,1,opt,name=domain" json:"domain,omitempty"`
|
||||
Challenge *core.Challenge `protobuf:"bytes,2,opt,name=challenge" json:"challenge,omitempty"`
|
||||
Authz *AuthzMeta `protobuf:"bytes,3,opt,name=authz" json:"authz,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Domain *string `protobuf:"bytes,1,opt,name=domain" json:"domain,omitempty"`
|
||||
Challenge *proto1.Challenge `protobuf:"bytes,2,opt,name=challenge" json:"challenge,omitempty"`
|
||||
Authz *AuthzMeta `protobuf:"bytes,3,opt,name=authz" json:"authz,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *PerformValidationRequest) Reset() { *m = PerformValidationRequest{} }
|
||||
func (m *PerformValidationRequest) String() string { return proto1.CompactTextString(m) }
|
||||
func (*PerformValidationRequest) ProtoMessage() {}
|
||||
func (*PerformValidationRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
func (m *PerformValidationRequest) Reset() { *m = PerformValidationRequest{} }
|
||||
func (m *PerformValidationRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*PerformValidationRequest) ProtoMessage() {}
|
||||
func (*PerformValidationRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_b39cc52ec1cb3a92, []int{2}
|
||||
}
|
||||
|
||||
func (m *PerformValidationRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PerformValidationRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *PerformValidationRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_PerformValidationRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *PerformValidationRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PerformValidationRequest.Merge(m, src)
|
||||
}
|
||||
func (m *PerformValidationRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_PerformValidationRequest.Size(m)
|
||||
}
|
||||
func (m *PerformValidationRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_PerformValidationRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_PerformValidationRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *PerformValidationRequest) GetDomain() string {
|
||||
if m != nil && m.Domain != nil {
|
||||
|
|
@ -109,7 +162,7 @@ func (m *PerformValidationRequest) GetDomain() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func (m *PerformValidationRequest) GetChallenge() *core.Challenge {
|
||||
func (m *PerformValidationRequest) GetChallenge() *proto1.Challenge {
|
||||
if m != nil {
|
||||
return m.Challenge
|
||||
}
|
||||
|
|
@ -124,15 +177,37 @@ func (m *PerformValidationRequest) GetAuthz() *AuthzMeta {
|
|||
}
|
||||
|
||||
type AuthzMeta struct {
|
||||
Id *string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
|
||||
RegID *int64 `protobuf:"varint,2,opt,name=regID" json:"regID,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Id *string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
|
||||
RegID *int64 `protobuf:"varint,2,opt,name=regID" json:"regID,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *AuthzMeta) Reset() { *m = AuthzMeta{} }
|
||||
func (m *AuthzMeta) String() string { return proto1.CompactTextString(m) }
|
||||
func (*AuthzMeta) ProtoMessage() {}
|
||||
func (*AuthzMeta) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
func (m *AuthzMeta) Reset() { *m = AuthzMeta{} }
|
||||
func (m *AuthzMeta) String() string { return proto.CompactTextString(m) }
|
||||
func (*AuthzMeta) ProtoMessage() {}
|
||||
func (*AuthzMeta) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_b39cc52ec1cb3a92, []int{3}
|
||||
}
|
||||
|
||||
func (m *AuthzMeta) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_AuthzMeta.Unmarshal(m, b)
|
||||
}
|
||||
func (m *AuthzMeta) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_AuthzMeta.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *AuthzMeta) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_AuthzMeta.Merge(m, src)
|
||||
}
|
||||
func (m *AuthzMeta) XXX_Size() int {
|
||||
return xxx_messageInfo_AuthzMeta.Size(m)
|
||||
}
|
||||
func (m *AuthzMeta) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_AuthzMeta.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_AuthzMeta proto.InternalMessageInfo
|
||||
|
||||
func (m *AuthzMeta) GetId() string {
|
||||
if m != nil && m.Id != nil {
|
||||
|
|
@ -149,24 +224,46 @@ func (m *AuthzMeta) GetRegID() int64 {
|
|||
}
|
||||
|
||||
type ValidationResult struct {
|
||||
Records []*core.ValidationRecord `protobuf:"bytes,1,rep,name=records" json:"records,omitempty"`
|
||||
Problems *core.ProblemDetails `protobuf:"bytes,2,opt,name=problems" json:"problems,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
Records []*proto1.ValidationRecord `protobuf:"bytes,1,rep,name=records" json:"records,omitempty"`
|
||||
Problems *proto1.ProblemDetails `protobuf:"bytes,2,opt,name=problems" json:"problems,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ValidationResult) Reset() { *m = ValidationResult{} }
|
||||
func (m *ValidationResult) String() string { return proto1.CompactTextString(m) }
|
||||
func (*ValidationResult) ProtoMessage() {}
|
||||
func (*ValidationResult) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
|
||||
func (m *ValidationResult) Reset() { *m = ValidationResult{} }
|
||||
func (m *ValidationResult) String() string { return proto.CompactTextString(m) }
|
||||
func (*ValidationResult) ProtoMessage() {}
|
||||
func (*ValidationResult) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_b39cc52ec1cb3a92, []int{4}
|
||||
}
|
||||
|
||||
func (m *ValidationResult) GetRecords() []*core.ValidationRecord {
|
||||
func (m *ValidationResult) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ValidationResult.Unmarshal(m, b)
|
||||
}
|
||||
func (m *ValidationResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ValidationResult.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *ValidationResult) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ValidationResult.Merge(m, src)
|
||||
}
|
||||
func (m *ValidationResult) XXX_Size() int {
|
||||
return xxx_messageInfo_ValidationResult.Size(m)
|
||||
}
|
||||
func (m *ValidationResult) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ValidationResult.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ValidationResult proto.InternalMessageInfo
|
||||
|
||||
func (m *ValidationResult) GetRecords() []*proto1.ValidationRecord {
|
||||
if m != nil {
|
||||
return m.Records
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ValidationResult) GetProblems() *core.ProblemDetails {
|
||||
func (m *ValidationResult) GetProblems() *proto1.ProblemDetails {
|
||||
if m != nil {
|
||||
return m.Problems
|
||||
}
|
||||
|
|
@ -174,11 +271,41 @@ func (m *ValidationResult) GetProblems() *core.ProblemDetails {
|
|||
}
|
||||
|
||||
func init() {
|
||||
proto1.RegisterType((*IsCAAValidRequest)(nil), "va.IsCAAValidRequest")
|
||||
proto1.RegisterType((*IsCAAValidResponse)(nil), "va.IsCAAValidResponse")
|
||||
proto1.RegisterType((*PerformValidationRequest)(nil), "va.PerformValidationRequest")
|
||||
proto1.RegisterType((*AuthzMeta)(nil), "va.AuthzMeta")
|
||||
proto1.RegisterType((*ValidationResult)(nil), "va.ValidationResult")
|
||||
proto.RegisterType((*IsCAAValidRequest)(nil), "va.IsCAAValidRequest")
|
||||
proto.RegisterType((*IsCAAValidResponse)(nil), "va.IsCAAValidResponse")
|
||||
proto.RegisterType((*PerformValidationRequest)(nil), "va.PerformValidationRequest")
|
||||
proto.RegisterType((*AuthzMeta)(nil), "va.AuthzMeta")
|
||||
proto.RegisterType((*ValidationResult)(nil), "va.ValidationResult")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("va/proto/va.proto", fileDescriptor_b39cc52ec1cb3a92) }
|
||||
|
||||
var fileDescriptor_b39cc52ec1cb3a92 = []byte{
|
||||
// 378 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x52, 0x3b, 0x6f, 0xea, 0x30,
|
||||
0x18, 0x25, 0x89, 0xb8, 0x5c, 0xbe, 0xdc, 0x07, 0x58, 0x80, 0x22, 0xd4, 0x01, 0xb9, 0x0b, 0xaa,
|
||||
0xd4, 0x40, 0xb3, 0x77, 0x48, 0xc9, 0x92, 0x01, 0x15, 0x59, 0x2a, 0x43, 0x37, 0x37, 0x71, 0x21,
|
||||
0x52, 0x88, 0xa9, 0xed, 0x64, 0x68, 0xf7, 0xfe, 0xee, 0x2a, 0x4e, 0x78, 0x14, 0x5a, 0x75, 0xb3,
|
||||
0xcf, 0x39, 0xd2, 0x79, 0xd8, 0xd0, 0x2d, 0xe8, 0x64, 0x2b, 0xb8, 0xe2, 0x93, 0x82, 0xba, 0xfa,
|
||||
0x80, 0xcc, 0x82, 0x0e, 0xfb, 0x11, 0x17, 0xac, 0x26, 0xca, 0x63, 0x45, 0xe1, 0x37, 0xe8, 0x86,
|
||||
0x72, 0xe6, 0xfb, 0x4b, 0x9a, 0x26, 0x31, 0x61, 0x2f, 0x39, 0x93, 0x0a, 0x0d, 0xe0, 0x57, 0xcc,
|
||||
0x37, 0x34, 0xc9, 0x1c, 0x63, 0x64, 0x8c, 0xdb, 0xa4, 0xbe, 0xa1, 0x2b, 0xe8, 0x14, 0xa5, 0x8e,
|
||||
0xaa, 0x84, 0x67, 0x73, 0xa6, 0xd6, 0x3c, 0x76, 0x4c, 0xad, 0x38, 0xc3, 0x11, 0x86, 0x3f, 0x34,
|
||||
0x8a, 0x78, 0x9e, 0xa9, 0x07, 0x12, 0x86, 0x81, 0x63, 0x8d, 0x8c, 0xb1, 0x45, 0x3e, 0x61, 0x38,
|
||||
0x00, 0x74, 0x6c, 0x2e, 0xb7, 0x3c, 0x93, 0x0c, 0xb9, 0xd0, 0xda, 0x0a, 0xfe, 0x94, 0xb2, 0x8d,
|
||||
0xb6, 0xb7, 0xbd, 0x9e, 0xab, 0x03, 0x2f, 0x2a, 0x30, 0x60, 0x8a, 0x26, 0xa9, 0x24, 0x3b, 0x11,
|
||||
0x7e, 0x37, 0xc0, 0x59, 0x30, 0xf1, 0xcc, 0xc5, 0x66, 0xb9, 0x4f, 0xf1, 0x53, 0x95, 0x6b, 0x68,
|
||||
0x47, 0x6b, 0x9a, 0xa6, 0x2c, 0x5b, 0x31, 0xdd, 0xc1, 0xf6, 0xfe, 0x57, 0x36, 0xb3, 0x1d, 0x4c,
|
||||
0x0e, 0x0a, 0x74, 0x09, 0x4d, 0x9a, 0xab, 0xf5, 0xab, 0xae, 0x61, 0x7b, 0x7f, 0xdd, 0x82, 0xba,
|
||||
0x7e, 0x09, 0xcc, 0x99, 0xa2, 0xa4, 0xe2, 0xf0, 0x0d, 0xb4, 0xf7, 0x18, 0xfa, 0x07, 0x66, 0x12,
|
||||
0xd7, 0xa6, 0x66, 0x12, 0xa3, 0x1e, 0x34, 0x05, 0x5b, 0x85, 0x81, 0x36, 0xb3, 0x48, 0x75, 0xc1,
|
||||
0x05, 0x74, 0x8e, 0x33, 0xcb, 0x3c, 0x55, 0x68, 0x0a, 0x2d, 0xc1, 0x22, 0x2e, 0x62, 0xe9, 0x18,
|
||||
0x23, 0x6b, 0x6c, 0x7b, 0x83, 0x2a, 0xd8, 0xb1, 0xb0, 0xa4, 0xc9, 0x4e, 0x86, 0xa6, 0xf0, 0xbb,
|
||||
0x1e, 0x43, 0xd6, 0x5d, 0xbe, 0x9e, 0x6c, 0xaf, 0xf2, 0xee, 0xc1, 0x5c, 0xfa, 0x28, 0x84, 0xee,
|
||||
0xd9, 0x70, 0xe8, 0xa2, 0xec, 0xf6, 0xdd, 0x9e, 0xc3, 0x5e, 0xc9, 0x9e, 0x46, 0xc6, 0x0d, 0x2f,
|
||||
0x00, 0x6b, 0xe6, 0xfb, 0xe8, 0x16, 0xe0, 0xf0, 0xa2, 0xa8, 0x5f, 0x8a, 0xcf, 0xbe, 0xd7, 0x70,
|
||||
0x70, 0x0a, 0x57, 0x0f, 0x8f, 0x1b, 0x77, 0xad, 0xc7, 0xa6, 0xfe, 0x96, 0x1f, 0x01, 0x00, 0x00,
|
||||
0xff, 0xff, 0x63, 0xcf, 0xa9, 0x6d, 0xc5, 0x02, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
|
|
@ -189,8 +316,9 @@ var _ grpc.ClientConn
|
|||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// Client API for VA service
|
||||
|
||||
// VAClient is the client API for VA service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type VAClient interface {
|
||||
PerformValidation(ctx context.Context, in *PerformValidationRequest, opts ...grpc.CallOption) (*ValidationResult, error)
|
||||
}
|
||||
|
|
@ -205,19 +333,26 @@ func NewVAClient(cc *grpc.ClientConn) VAClient {
|
|||
|
||||
func (c *vAClient) PerformValidation(ctx context.Context, in *PerformValidationRequest, opts ...grpc.CallOption) (*ValidationResult, error) {
|
||||
out := new(ValidationResult)
|
||||
err := grpc.Invoke(ctx, "/va.VA/PerformValidation", in, out, c.cc, opts...)
|
||||
err := c.cc.Invoke(ctx, "/va.VA/PerformValidation", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for VA service
|
||||
|
||||
// VAServer is the server API for VA service.
|
||||
type VAServer interface {
|
||||
PerformValidation(context.Context, *PerformValidationRequest) (*ValidationResult, error)
|
||||
}
|
||||
|
||||
// UnimplementedVAServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedVAServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedVAServer) PerformValidation(ctx context.Context, req *PerformValidationRequest) (*ValidationResult, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method PerformValidation not implemented")
|
||||
}
|
||||
|
||||
func RegisterVAServer(s *grpc.Server, srv VAServer) {
|
||||
s.RegisterService(&_VA_serviceDesc, srv)
|
||||
}
|
||||
|
|
@ -253,8 +388,9 @@ var _VA_serviceDesc = grpc.ServiceDesc{
|
|||
Metadata: "va/proto/va.proto",
|
||||
}
|
||||
|
||||
// Client API for CAA service
|
||||
|
||||
// CAAClient is the client API for CAA service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type CAAClient interface {
|
||||
IsCAAValid(ctx context.Context, in *IsCAAValidRequest, opts ...grpc.CallOption) (*IsCAAValidResponse, error)
|
||||
}
|
||||
|
|
@ -269,19 +405,26 @@ func NewCAAClient(cc *grpc.ClientConn) CAAClient {
|
|||
|
||||
func (c *cAAClient) IsCAAValid(ctx context.Context, in *IsCAAValidRequest, opts ...grpc.CallOption) (*IsCAAValidResponse, error) {
|
||||
out := new(IsCAAValidResponse)
|
||||
err := grpc.Invoke(ctx, "/va.CAA/IsCAAValid", in, out, c.cc, opts...)
|
||||
err := c.cc.Invoke(ctx, "/va.CAA/IsCAAValid", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Server API for CAA service
|
||||
|
||||
// CAAServer is the server API for CAA service.
|
||||
type CAAServer interface {
|
||||
IsCAAValid(context.Context, *IsCAAValidRequest) (*IsCAAValidResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedCAAServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedCAAServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedCAAServer) IsCAAValid(ctx context.Context, req *IsCAAValidRequest) (*IsCAAValidResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method IsCAAValid not implemented")
|
||||
}
|
||||
|
||||
func RegisterCAAServer(s *grpc.Server, srv CAAServer) {
|
||||
s.RegisterService(&_CAA_serviceDesc, srv)
|
||||
}
|
||||
|
|
@ -316,33 +459,3 @@ var _CAA_serviceDesc = grpc.ServiceDesc{
|
|||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "va/proto/va.proto",
|
||||
}
|
||||
|
||||
func init() { proto1.RegisterFile("va/proto/va.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 378 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x52, 0x3b, 0x6f, 0xea, 0x30,
|
||||
0x18, 0x25, 0x89, 0xb8, 0x5c, 0xbe, 0xdc, 0x07, 0x58, 0x80, 0x22, 0xd4, 0x01, 0xb9, 0x0b, 0xaa,
|
||||
0xd4, 0x40, 0xb3, 0x77, 0x48, 0xc9, 0x92, 0x01, 0x15, 0x59, 0x2a, 0x43, 0x37, 0x37, 0x71, 0x21,
|
||||
0x52, 0x88, 0xa9, 0xed, 0x64, 0x68, 0xf7, 0xfe, 0xee, 0x2a, 0x4e, 0x78, 0x14, 0x5a, 0x75, 0xb3,
|
||||
0xcf, 0x39, 0xd2, 0x79, 0xd8, 0xd0, 0x2d, 0xe8, 0x64, 0x2b, 0xb8, 0xe2, 0x93, 0x82, 0xba, 0xfa,
|
||||
0x80, 0xcc, 0x82, 0x0e, 0xfb, 0x11, 0x17, 0xac, 0x26, 0xca, 0x63, 0x45, 0xe1, 0x37, 0xe8, 0x86,
|
||||
0x72, 0xe6, 0xfb, 0x4b, 0x9a, 0x26, 0x31, 0x61, 0x2f, 0x39, 0x93, 0x0a, 0x0d, 0xe0, 0x57, 0xcc,
|
||||
0x37, 0x34, 0xc9, 0x1c, 0x63, 0x64, 0x8c, 0xdb, 0xa4, 0xbe, 0xa1, 0x2b, 0xe8, 0x14, 0xa5, 0x8e,
|
||||
0xaa, 0x84, 0x67, 0x73, 0xa6, 0xd6, 0x3c, 0x76, 0x4c, 0xad, 0x38, 0xc3, 0x11, 0x86, 0x3f, 0x34,
|
||||
0x8a, 0x78, 0x9e, 0xa9, 0x07, 0x12, 0x86, 0x81, 0x63, 0x8d, 0x8c, 0xb1, 0x45, 0x3e, 0x61, 0x38,
|
||||
0x00, 0x74, 0x6c, 0x2e, 0xb7, 0x3c, 0x93, 0x0c, 0xb9, 0xd0, 0xda, 0x0a, 0xfe, 0x94, 0xb2, 0x8d,
|
||||
0xb6, 0xb7, 0xbd, 0x9e, 0xab, 0x03, 0x2f, 0x2a, 0x30, 0x60, 0x8a, 0x26, 0xa9, 0x24, 0x3b, 0x11,
|
||||
0x7e, 0x37, 0xc0, 0x59, 0x30, 0xf1, 0xcc, 0xc5, 0x66, 0xb9, 0x4f, 0xf1, 0x53, 0x95, 0x6b, 0x68,
|
||||
0x47, 0x6b, 0x9a, 0xa6, 0x2c, 0x5b, 0x31, 0xdd, 0xc1, 0xf6, 0xfe, 0x57, 0x36, 0xb3, 0x1d, 0x4c,
|
||||
0x0e, 0x0a, 0x74, 0x09, 0x4d, 0x9a, 0xab, 0xf5, 0xab, 0xae, 0x61, 0x7b, 0x7f, 0xdd, 0x82, 0xba,
|
||||
0x7e, 0x09, 0xcc, 0x99, 0xa2, 0xa4, 0xe2, 0xf0, 0x0d, 0xb4, 0xf7, 0x18, 0xfa, 0x07, 0x66, 0x12,
|
||||
0xd7, 0xa6, 0x66, 0x12, 0xa3, 0x1e, 0x34, 0x05, 0x5b, 0x85, 0x81, 0x36, 0xb3, 0x48, 0x75, 0xc1,
|
||||
0x05, 0x74, 0x8e, 0x33, 0xcb, 0x3c, 0x55, 0x68, 0x0a, 0x2d, 0xc1, 0x22, 0x2e, 0x62, 0xe9, 0x18,
|
||||
0x23, 0x6b, 0x6c, 0x7b, 0x83, 0x2a, 0xd8, 0xb1, 0xb0, 0xa4, 0xc9, 0x4e, 0x86, 0xa6, 0xf0, 0xbb,
|
||||
0x1e, 0x43, 0xd6, 0x5d, 0xbe, 0x9e, 0x6c, 0xaf, 0xf2, 0xee, 0xc1, 0x5c, 0xfa, 0x28, 0x84, 0xee,
|
||||
0xd9, 0x70, 0xe8, 0xa2, 0xec, 0xf6, 0xdd, 0x9e, 0xc3, 0x5e, 0xc9, 0x9e, 0x46, 0xc6, 0x0d, 0x2f,
|
||||
0x00, 0x6b, 0xe6, 0xfb, 0xe8, 0x16, 0xe0, 0xf0, 0xa2, 0xa8, 0x5f, 0x8a, 0xcf, 0xbe, 0xd7, 0x70,
|
||||
0x70, 0x0a, 0x57, 0x0f, 0x8f, 0x1b, 0x77, 0xad, 0xc7, 0xa6, 0xfe, 0x96, 0x1f, 0x01, 0x00, 0x00,
|
||||
0xff, 0xff, 0x63, 0xcf, 0xa9, 0x6d, 0xc5, 0x02, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,4 @@
|
|||
Go support for Protocol Buffers - Google's data interchange format
|
||||
|
||||
Copyright 2010 The Go Authors. All rights reserved.
|
||||
https://github.com/golang/protobuf
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
|
|
|
|||
|
|
@ -186,7 +186,6 @@ func (p *Buffer) DecodeVarint() (x uint64, err error) {
|
|||
if b&0x80 == 0 {
|
||||
goto done
|
||||
}
|
||||
// x -= 0x80 << 63 // Always zero.
|
||||
|
||||
return 0, errOverflow
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
// Go support for Protocol Buffers - Google's data interchange format
|
||||
//
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// https://github.com/golang/protobuf
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package proto
|
||||
|
||||
import "errors"
|
||||
|
||||
// Deprecated: do not use.
|
||||
type Stats struct{ Emalloc, Dmalloc, Encode, Decode, Chit, Cmiss, Size uint64 }
|
||||
|
||||
// Deprecated: do not use.
|
||||
func GetStats() Stats { return Stats{} }
|
||||
|
||||
// Deprecated: do not use.
|
||||
func MarshalMessageSet(interface{}) ([]byte, error) {
|
||||
return nil, errors.New("proto: not implemented")
|
||||
}
|
||||
|
||||
// Deprecated: do not use.
|
||||
func UnmarshalMessageSet([]byte, interface{}) error {
|
||||
return errors.New("proto: not implemented")
|
||||
}
|
||||
|
||||
// Deprecated: do not use.
|
||||
func MarshalMessageSetJSON(interface{}) ([]byte, error) {
|
||||
return nil, errors.New("proto: not implemented")
|
||||
}
|
||||
|
||||
// Deprecated: do not use.
|
||||
func UnmarshalMessageSetJSON([]byte, interface{}) error {
|
||||
return errors.New("proto: not implemented")
|
||||
}
|
||||
|
||||
// Deprecated: do not use.
|
||||
func RegisterMessageSetType(Message, int32, string) {}
|
||||
|
|
@ -37,27 +37,9 @@ package proto
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// RequiredNotSetError is the error returned if Marshal is called with
|
||||
// a protocol buffer struct whose required fields have not
|
||||
// all been initialized. It is also the error returned if Unmarshal is
|
||||
// called with an encoded protocol buffer that does not include all the
|
||||
// required fields.
|
||||
//
|
||||
// When printed, RequiredNotSetError reports the first unset required field in a
|
||||
// message. If the field cannot be precisely determined, it is reported as
|
||||
// "{Unknown}".
|
||||
type RequiredNotSetError struct {
|
||||
field string
|
||||
}
|
||||
|
||||
func (e *RequiredNotSetError) Error() string {
|
||||
return fmt.Sprintf("proto: required field %q not set", e.field)
|
||||
}
|
||||
|
||||
var (
|
||||
// errRepeatedHasNil is the error returned if Marshal is called with
|
||||
// a struct with a repeated field containing a nil element.
|
||||
|
|
|
|||
|
|
@ -246,7 +246,8 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
m1, m2 := e1.value, e2.value
|
||||
m1 := extensionAsLegacyType(e1.value)
|
||||
m2 := extensionAsLegacyType(e2.value)
|
||||
|
||||
if m1 == nil && m2 == nil {
|
||||
// Both have only encoded form.
|
||||
|
|
|
|||
|
|
@ -185,9 +185,25 @@ type Extension struct {
|
|||
// extension will have only enc set. When such an extension is
|
||||
// accessed using GetExtension (or GetExtensions) desc and value
|
||||
// will be set.
|
||||
desc *ExtensionDesc
|
||||
desc *ExtensionDesc
|
||||
|
||||
// value is a concrete value for the extension field. Let the type of
|
||||
// desc.ExtensionType be the "API type" and the type of Extension.value
|
||||
// be the "storage type". The API type and storage type are the same except:
|
||||
// * For scalars (except []byte), the API type uses *T,
|
||||
// while the storage type uses T.
|
||||
// * For repeated fields, the API type uses []T, while the storage type
|
||||
// uses *[]T.
|
||||
//
|
||||
// The reason for the divergence is so that the storage type more naturally
|
||||
// matches what is expected of when retrieving the values through the
|
||||
// protobuf reflection APIs.
|
||||
//
|
||||
// The value may only be populated if desc is also populated.
|
||||
value interface{}
|
||||
enc []byte
|
||||
|
||||
// enc is the raw bytes for the extension field.
|
||||
enc []byte
|
||||
}
|
||||
|
||||
// SetRawExtension is for testing only.
|
||||
|
|
@ -334,7 +350,7 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
|
|||
// descriptors with the same field number.
|
||||
return nil, errors.New("proto: descriptor conflict")
|
||||
}
|
||||
return e.value, nil
|
||||
return extensionAsLegacyType(e.value), nil
|
||||
}
|
||||
|
||||
if extension.ExtensionType == nil {
|
||||
|
|
@ -349,11 +365,11 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
|
|||
|
||||
// Remember the decoded version and drop the encoded version.
|
||||
// That way it is safe to mutate what we return.
|
||||
e.value = v
|
||||
e.value = extensionAsStorageType(v)
|
||||
e.desc = extension
|
||||
e.enc = nil
|
||||
emap[extension.Field] = e
|
||||
return e.value, nil
|
||||
return extensionAsLegacyType(e.value), nil
|
||||
}
|
||||
|
||||
// defaultExtensionValue returns the default value for extension.
|
||||
|
|
@ -488,7 +504,7 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error
|
|||
}
|
||||
typ := reflect.TypeOf(extension.ExtensionType)
|
||||
if typ != reflect.TypeOf(value) {
|
||||
return errors.New("proto: bad extension value type")
|
||||
return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", value, extension.ExtensionType)
|
||||
}
|
||||
// nil extension values need to be caught early, because the
|
||||
// encoder can't distinguish an ErrNil due to a nil extension
|
||||
|
|
@ -500,7 +516,7 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error
|
|||
}
|
||||
|
||||
extmap := epb.extensionsWrite()
|
||||
extmap[extension.Field] = Extension{desc: extension, value: value}
|
||||
extmap[extension.Field] = Extension{desc: extension, value: extensionAsStorageType(value)}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -541,3 +557,51 @@ func RegisterExtension(desc *ExtensionDesc) {
|
|||
func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
|
||||
return extensionMaps[reflect.TypeOf(pb).Elem()]
|
||||
}
|
||||
|
||||
// extensionAsLegacyType converts an value in the storage type as the API type.
|
||||
// See Extension.value.
|
||||
func extensionAsLegacyType(v interface{}) interface{} {
|
||||
switch rv := reflect.ValueOf(v); rv.Kind() {
|
||||
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
|
||||
// Represent primitive types as a pointer to the value.
|
||||
rv2 := reflect.New(rv.Type())
|
||||
rv2.Elem().Set(rv)
|
||||
v = rv2.Interface()
|
||||
case reflect.Ptr:
|
||||
// Represent slice types as the value itself.
|
||||
switch rv.Type().Elem().Kind() {
|
||||
case reflect.Slice:
|
||||
if rv.IsNil() {
|
||||
v = reflect.Zero(rv.Type().Elem()).Interface()
|
||||
} else {
|
||||
v = rv.Elem().Interface()
|
||||
}
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// extensionAsStorageType converts an value in the API type as the storage type.
|
||||
// See Extension.value.
|
||||
func extensionAsStorageType(v interface{}) interface{} {
|
||||
switch rv := reflect.ValueOf(v); rv.Kind() {
|
||||
case reflect.Ptr:
|
||||
// Represent slice types as the value itself.
|
||||
switch rv.Type().Elem().Kind() {
|
||||
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
|
||||
if rv.IsNil() {
|
||||
v = reflect.Zero(rv.Type().Elem()).Interface()
|
||||
} else {
|
||||
v = rv.Elem().Interface()
|
||||
}
|
||||
}
|
||||
case reflect.Slice:
|
||||
// Represent slice types as a pointer to the value.
|
||||
if rv.Type().Elem().Kind() != reflect.Uint8 {
|
||||
rv2 := reflect.New(rv.Type())
|
||||
rv2.Elem().Set(rv)
|
||||
v = rv2.Interface()
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
|
|
|||
|
|
@ -265,7 +265,6 @@ package proto
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
|
|
@ -274,7 +273,66 @@ import (
|
|||
"sync"
|
||||
)
|
||||
|
||||
var errInvalidUTF8 = errors.New("proto: invalid UTF-8 string")
|
||||
// RequiredNotSetError is an error type returned by either Marshal or Unmarshal.
|
||||
// Marshal reports this when a required field is not initialized.
|
||||
// Unmarshal reports this when a required field is missing from the wire data.
|
||||
type RequiredNotSetError struct{ field string }
|
||||
|
||||
func (e *RequiredNotSetError) Error() string {
|
||||
if e.field == "" {
|
||||
return fmt.Sprintf("proto: required field not set")
|
||||
}
|
||||
return fmt.Sprintf("proto: required field %q not set", e.field)
|
||||
}
|
||||
func (e *RequiredNotSetError) RequiredNotSet() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type invalidUTF8Error struct{ field string }
|
||||
|
||||
func (e *invalidUTF8Error) Error() string {
|
||||
if e.field == "" {
|
||||
return "proto: invalid UTF-8 detected"
|
||||
}
|
||||
return fmt.Sprintf("proto: field %q contains invalid UTF-8", e.field)
|
||||
}
|
||||
func (e *invalidUTF8Error) InvalidUTF8() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// errInvalidUTF8 is a sentinel error to identify fields with invalid UTF-8.
|
||||
// This error should not be exposed to the external API as such errors should
|
||||
// be recreated with the field information.
|
||||
var errInvalidUTF8 = &invalidUTF8Error{}
|
||||
|
||||
// isNonFatal reports whether the error is either a RequiredNotSet error
|
||||
// or a InvalidUTF8 error.
|
||||
func isNonFatal(err error) bool {
|
||||
if re, ok := err.(interface{ RequiredNotSet() bool }); ok && re.RequiredNotSet() {
|
||||
return true
|
||||
}
|
||||
if re, ok := err.(interface{ InvalidUTF8() bool }); ok && re.InvalidUTF8() {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type nonFatal struct{ E error }
|
||||
|
||||
// Merge merges err into nf and reports whether it was successful.
|
||||
// Otherwise it returns false for any fatal non-nil errors.
|
||||
func (nf *nonFatal) Merge(err error) (ok bool) {
|
||||
if err == nil {
|
||||
return true // not an error
|
||||
}
|
||||
if !isNonFatal(err) {
|
||||
return false // fatal error
|
||||
}
|
||||
if nf.E == nil {
|
||||
nf.E = err // store first instance of non-fatal error
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Message is implemented by generated protocol buffer messages.
|
||||
type Message interface {
|
||||
|
|
@ -283,26 +341,6 @@ type Message interface {
|
|||
ProtoMessage()
|
||||
}
|
||||
|
||||
// Stats records allocation details about the protocol buffer encoders
|
||||
// and decoders. Useful for tuning the library itself.
|
||||
type Stats struct {
|
||||
Emalloc uint64 // mallocs in encode
|
||||
Dmalloc uint64 // mallocs in decode
|
||||
Encode uint64 // number of encodes
|
||||
Decode uint64 // number of decodes
|
||||
Chit uint64 // number of cache hits
|
||||
Cmiss uint64 // number of cache misses
|
||||
Size uint64 // number of sizes
|
||||
}
|
||||
|
||||
// Set to true to enable stats collection.
|
||||
const collectStats = false
|
||||
|
||||
var stats Stats
|
||||
|
||||
// GetStats returns a copy of the global Stats structure.
|
||||
func GetStats() Stats { return stats }
|
||||
|
||||
// A Buffer is a buffer manager for marshaling and unmarshaling
|
||||
// protocol buffers. It may be reused between invocations to
|
||||
// reduce memory usage. It is not necessary to use a Buffer;
|
||||
|
|
@ -902,13 +940,19 @@ func isProto3Zero(v reflect.Value) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
|
||||
// to assert that that code is compatible with this version of the proto package.
|
||||
const ProtoPackageIsVersion2 = true
|
||||
const (
|
||||
// ProtoPackageIsVersion3 is referenced from generated protocol buffer files
|
||||
// to assert that that code is compatible with this version of the proto package.
|
||||
ProtoPackageIsVersion3 = true
|
||||
|
||||
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
|
||||
// to assert that that code is compatible with this version of the proto package.
|
||||
const ProtoPackageIsVersion1 = true
|
||||
// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
|
||||
// to assert that that code is compatible with this version of the proto package.
|
||||
ProtoPackageIsVersion2 = true
|
||||
|
||||
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
|
||||
// to assert that that code is compatible with this version of the proto package.
|
||||
ProtoPackageIsVersion1 = true
|
||||
)
|
||||
|
||||
// InternalMessageInfo is a type used internally by generated .pb.go files.
|
||||
// This type is not intended to be used by non-generated code.
|
||||
|
|
|
|||
|
|
@ -36,13 +36,7 @@ package proto
|
|||
*/
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
|
||||
|
|
@ -145,46 +139,9 @@ func skipVarint(buf []byte) []byte {
|
|||
return buf[i+1:]
|
||||
}
|
||||
|
||||
// MarshalMessageSet encodes the extension map represented by m in the message set wire format.
|
||||
// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
|
||||
func MarshalMessageSet(exts interface{}) ([]byte, error) {
|
||||
return marshalMessageSet(exts, false)
|
||||
}
|
||||
|
||||
// marshaMessageSet implements above function, with the opt to turn on / off deterministic during Marshal.
|
||||
func marshalMessageSet(exts interface{}, deterministic bool) ([]byte, error) {
|
||||
switch exts := exts.(type) {
|
||||
case *XXX_InternalExtensions:
|
||||
var u marshalInfo
|
||||
siz := u.sizeMessageSet(exts)
|
||||
b := make([]byte, 0, siz)
|
||||
return u.appendMessageSet(b, exts, deterministic)
|
||||
|
||||
case map[int32]Extension:
|
||||
// This is an old-style extension map.
|
||||
// Wrap it in a new-style XXX_InternalExtensions.
|
||||
ie := XXX_InternalExtensions{
|
||||
p: &struct {
|
||||
mu sync.Mutex
|
||||
extensionMap map[int32]Extension
|
||||
}{
|
||||
extensionMap: exts,
|
||||
},
|
||||
}
|
||||
|
||||
var u marshalInfo
|
||||
siz := u.sizeMessageSet(&ie)
|
||||
b := make([]byte, 0, siz)
|
||||
return u.appendMessageSet(b, &ie, deterministic)
|
||||
|
||||
default:
|
||||
return nil, errors.New("proto: not an extension map")
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
|
||||
// unmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
|
||||
// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
|
||||
func UnmarshalMessageSet(buf []byte, exts interface{}) error {
|
||||
func unmarshalMessageSet(buf []byte, exts interface{}) error {
|
||||
var m map[int32]Extension
|
||||
switch exts := exts.(type) {
|
||||
case *XXX_InternalExtensions:
|
||||
|
|
@ -222,93 +179,3 @@ func UnmarshalMessageSet(buf []byte, exts interface{}) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalMessageSetJSON encodes the extension map represented by m in JSON format.
|
||||
// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
|
||||
func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
|
||||
var m map[int32]Extension
|
||||
switch exts := exts.(type) {
|
||||
case *XXX_InternalExtensions:
|
||||
var mu sync.Locker
|
||||
m, mu = exts.extensionsRead()
|
||||
if m != nil {
|
||||
// Keep the extensions map locked until we're done marshaling to prevent
|
||||
// races between marshaling and unmarshaling the lazily-{en,de}coded
|
||||
// values.
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
}
|
||||
case map[int32]Extension:
|
||||
m = exts
|
||||
default:
|
||||
return nil, errors.New("proto: not an extension map")
|
||||
}
|
||||
var b bytes.Buffer
|
||||
b.WriteByte('{')
|
||||
|
||||
// Process the map in key order for deterministic output.
|
||||
ids := make([]int32, 0, len(m))
|
||||
for id := range m {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
sort.Sort(int32Slice(ids)) // int32Slice defined in text.go
|
||||
|
||||
for i, id := range ids {
|
||||
ext := m[id]
|
||||
msd, ok := messageSetMap[id]
|
||||
if !ok {
|
||||
// Unknown type; we can't render it, so skip it.
|
||||
continue
|
||||
}
|
||||
|
||||
if i > 0 && b.Len() > 1 {
|
||||
b.WriteByte(',')
|
||||
}
|
||||
|
||||
fmt.Fprintf(&b, `"[%s]":`, msd.name)
|
||||
|
||||
x := ext.value
|
||||
if x == nil {
|
||||
x = reflect.New(msd.t.Elem()).Interface()
|
||||
if err := Unmarshal(ext.enc, x.(Message)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
d, err := json.Marshal(x)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.Write(d)
|
||||
}
|
||||
b.WriteByte('}')
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format.
|
||||
// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
|
||||
func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error {
|
||||
// Common-case fast path.
|
||||
if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// This is fairly tricky, and it's not clear that it is needed.
|
||||
return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented")
|
||||
}
|
||||
|
||||
// A global registry of types that can be used in a MessageSet.
|
||||
|
||||
var messageSetMap = make(map[int32]messageSetDesc)
|
||||
|
||||
type messageSetDesc struct {
|
||||
t reflect.Type // pointer to struct
|
||||
name string
|
||||
}
|
||||
|
||||
// RegisterMessageSetType is called from the generated code.
|
||||
func RegisterMessageSetType(m Message, fieldNum int32, name string) {
|
||||
messageSetMap[fieldNum] = messageSetDesc{
|
||||
t: reflect.TypeOf(m),
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,10 +79,13 @@ func toPointer(i *Message) pointer {
|
|||
|
||||
// toAddrPointer converts an interface to a pointer that points to
|
||||
// the interface data.
|
||||
func toAddrPointer(i *interface{}, isptr bool) pointer {
|
||||
func toAddrPointer(i *interface{}, isptr, deref bool) pointer {
|
||||
v := reflect.ValueOf(*i)
|
||||
u := reflect.New(v.Type())
|
||||
u.Elem().Set(v)
|
||||
if deref {
|
||||
u = u.Elem()
|
||||
}
|
||||
return pointer{v: u}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,16 +85,21 @@ func toPointer(i *Message) pointer {
|
|||
|
||||
// toAddrPointer converts an interface to a pointer that points to
|
||||
// the interface data.
|
||||
func toAddrPointer(i *interface{}, isptr bool) pointer {
|
||||
func toAddrPointer(i *interface{}, isptr, deref bool) (p pointer) {
|
||||
// Super-tricky - read or get the address of data word of interface value.
|
||||
if isptr {
|
||||
// The interface is of pointer type, thus it is a direct interface.
|
||||
// The data word is the pointer data itself. We take its address.
|
||||
return pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
|
||||
p = pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
|
||||
} else {
|
||||
// The interface is not of pointer type. The data word is the pointer
|
||||
// to the data.
|
||||
p = pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
|
||||
}
|
||||
// The interface is not of pointer type. The data word is the pointer
|
||||
// to the data.
|
||||
return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
|
||||
if deref {
|
||||
p.p = *(*unsafe.Pointer)(p.p)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// valToPointer converts v to a pointer. v must be of pointer type.
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ type Properties struct {
|
|||
Repeated bool
|
||||
Packed bool // relevant for repeated primitives only
|
||||
Enum string // set for enum types only
|
||||
proto3 bool // whether this is known to be a proto3 field; set for []byte only
|
||||
proto3 bool // whether this is known to be a proto3 field
|
||||
oneof bool // whether this is a oneof field
|
||||
|
||||
Default string // default value
|
||||
|
|
@ -148,9 +148,9 @@ type Properties struct {
|
|||
stype reflect.Type // set for struct types only
|
||||
sprop *StructProperties // set for struct types only
|
||||
|
||||
mtype reflect.Type // set for map types only
|
||||
mkeyprop *Properties // set for map types only
|
||||
mvalprop *Properties // set for map types only
|
||||
mtype reflect.Type // set for map types only
|
||||
MapKeyProp *Properties // set for map types only
|
||||
MapValProp *Properties // set for map types only
|
||||
}
|
||||
|
||||
// String formats the properties in the protobuf struct field tag style.
|
||||
|
|
@ -275,16 +275,16 @@ func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, loc
|
|||
|
||||
case reflect.Map:
|
||||
p.mtype = t1
|
||||
p.mkeyprop = &Properties{}
|
||||
p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
|
||||
p.mvalprop = &Properties{}
|
||||
p.MapKeyProp = &Properties{}
|
||||
p.MapKeyProp.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
|
||||
p.MapValProp = &Properties{}
|
||||
vtype := p.mtype.Elem()
|
||||
if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {
|
||||
// The value type is not a message (*T) or bytes ([]byte),
|
||||
// so we need encoders for the pointer to this type.
|
||||
vtype = reflect.PtrTo(vtype)
|
||||
}
|
||||
p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
|
||||
p.MapValProp.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
|
||||
}
|
||||
|
||||
if p.stype != nil {
|
||||
|
|
@ -334,9 +334,6 @@ func GetProperties(t reflect.Type) *StructProperties {
|
|||
sprop, ok := propertiesMap[t]
|
||||
propertiesMu.RUnlock()
|
||||
if ok {
|
||||
if collectStats {
|
||||
stats.Chit++
|
||||
}
|
||||
return sprop
|
||||
}
|
||||
|
||||
|
|
@ -346,17 +343,20 @@ func GetProperties(t reflect.Type) *StructProperties {
|
|||
return sprop
|
||||
}
|
||||
|
||||
type (
|
||||
oneofFuncsIface interface {
|
||||
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
|
||||
}
|
||||
oneofWrappersIface interface {
|
||||
XXX_OneofWrappers() []interface{}
|
||||
}
|
||||
)
|
||||
|
||||
// getPropertiesLocked requires that propertiesMu is held.
|
||||
func getPropertiesLocked(t reflect.Type) *StructProperties {
|
||||
if prop, ok := propertiesMap[t]; ok {
|
||||
if collectStats {
|
||||
stats.Chit++
|
||||
}
|
||||
return prop
|
||||
}
|
||||
if collectStats {
|
||||
stats.Cmiss++
|
||||
}
|
||||
|
||||
prop := new(StructProperties)
|
||||
// in case of recursive protos, fill this in now.
|
||||
|
|
@ -391,13 +391,14 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
|
|||
// Re-order prop.order.
|
||||
sort.Sort(prop)
|
||||
|
||||
type oneofMessage interface {
|
||||
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
|
||||
var oots []interface{}
|
||||
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
|
||||
case oneofFuncsIface:
|
||||
_, _, _, oots = m.XXX_OneofFuncs()
|
||||
case oneofWrappersIface:
|
||||
oots = m.XXX_OneofWrappers()
|
||||
}
|
||||
if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
|
||||
var oots []interface{}
|
||||
_, _, _, oots = om.XXX_OneofFuncs()
|
||||
|
||||
if len(oots) > 0 {
|
||||
// Interpret oneof metadata.
|
||||
prop.OneofTypes = make(map[string]*OneofProperties)
|
||||
for _, oot := range oots {
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ type marshalElemInfo struct {
|
|||
sizer sizer
|
||||
marshaler marshaler
|
||||
isptr bool // elem is pointer typed, thus interface of this type is a direct interface (extension only)
|
||||
deref bool // dereference the pointer before operating on it; implies isptr
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
@ -231,7 +232,7 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
|
|||
return b, err
|
||||
}
|
||||
|
||||
var err, errreq error
|
||||
var err, errLater error
|
||||
// The old marshaler encodes extensions at beginning.
|
||||
if u.extensions.IsValid() {
|
||||
e := ptr.offset(u.extensions).toExtensions()
|
||||
|
|
@ -252,11 +253,13 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
|
|||
}
|
||||
}
|
||||
for _, f := range u.fields {
|
||||
if f.required && errreq == nil {
|
||||
if f.required {
|
||||
if ptr.offset(f.field).getPointer().isNil() {
|
||||
// Required field is not set.
|
||||
// We record the error but keep going, to give a complete marshaling.
|
||||
errreq = &RequiredNotSetError{f.name}
|
||||
if errLater == nil {
|
||||
errLater = &RequiredNotSetError{f.name}
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
|
@ -269,14 +272,21 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
|
|||
if err1, ok := err.(*RequiredNotSetError); ok {
|
||||
// Required field in submessage is not set.
|
||||
// We record the error but keep going, to give a complete marshaling.
|
||||
if errreq == nil {
|
||||
errreq = &RequiredNotSetError{f.name + "." + err1.field}
|
||||
if errLater == nil {
|
||||
errLater = &RequiredNotSetError{f.name + "." + err1.field}
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err == errRepeatedHasNil {
|
||||
err = errors.New("proto: repeated field " + f.name + " has nil element")
|
||||
}
|
||||
if err == errInvalidUTF8 {
|
||||
if errLater == nil {
|
||||
fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name
|
||||
errLater = &invalidUTF8Error{fullName}
|
||||
}
|
||||
continue
|
||||
}
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
|
|
@ -284,7 +294,7 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
|
|||
s := *ptr.offset(u.unrecognized).toBytes()
|
||||
b = append(b, s...)
|
||||
}
|
||||
return b, errreq
|
||||
return b, errLater
|
||||
}
|
||||
|
||||
// computeMarshalInfo initializes the marshal info.
|
||||
|
|
@ -311,8 +321,11 @@ func (u *marshalInfo) computeMarshalInfo() {
|
|||
|
||||
// get oneof implementers
|
||||
var oneofImplementers []interface{}
|
||||
if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
|
||||
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
|
||||
case oneofFuncsIface:
|
||||
_, _, _, oneofImplementers = m.XXX_OneofFuncs()
|
||||
case oneofWrappersIface:
|
||||
oneofImplementers = m.XXX_OneofWrappers()
|
||||
}
|
||||
|
||||
n := t.NumField()
|
||||
|
|
@ -398,13 +411,22 @@ func (u *marshalInfo) getExtElemInfo(desc *ExtensionDesc) *marshalElemInfo {
|
|||
panic("tag is not an integer")
|
||||
}
|
||||
wt := wiretype(tags[0])
|
||||
if t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct {
|
||||
t = t.Elem()
|
||||
}
|
||||
sizer, marshaler := typeMarshaler(t, tags, false, false)
|
||||
var deref bool
|
||||
if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 {
|
||||
t = reflect.PtrTo(t)
|
||||
deref = true
|
||||
}
|
||||
e = &marshalElemInfo{
|
||||
wiretag: uint64(tag)<<3 | wt,
|
||||
tagsize: SizeVarint(uint64(tag) << 3),
|
||||
sizer: sizer,
|
||||
marshaler: marshaler,
|
||||
isptr: t.Kind() == reflect.Ptr,
|
||||
deref: deref,
|
||||
}
|
||||
|
||||
// update cache
|
||||
|
|
@ -439,7 +461,7 @@ func (fi *marshalFieldInfo) computeMarshalFieldInfo(f *reflect.StructField) {
|
|||
|
||||
func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) {
|
||||
fi.field = toField(f)
|
||||
fi.wiretag = 1<<31 - 1 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire.
|
||||
fi.wiretag = math.MaxInt32 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire.
|
||||
fi.isPointer = true
|
||||
fi.sizer, fi.marshaler = makeOneOfMarshaler(fi, f)
|
||||
fi.oneofElems = make(map[reflect.Type]*marshalElemInfo)
|
||||
|
|
@ -467,10 +489,6 @@ func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofI
|
|||
}
|
||||
}
|
||||
|
||||
type oneofMessage interface {
|
||||
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
|
||||
}
|
||||
|
||||
// wiretype returns the wire encoding of the type.
|
||||
func wiretype(encoding string) uint64 {
|
||||
switch encoding {
|
||||
|
|
@ -530,6 +548,7 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
|
|||
|
||||
packed := false
|
||||
proto3 := false
|
||||
validateUTF8 := true
|
||||
for i := 2; i < len(tags); i++ {
|
||||
if tags[i] == "packed" {
|
||||
packed = true
|
||||
|
|
@ -538,6 +557,7 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
|
|||
proto3 = true
|
||||
}
|
||||
}
|
||||
validateUTF8 = validateUTF8 && proto3
|
||||
|
||||
switch t.Kind() {
|
||||
case reflect.Bool:
|
||||
|
|
@ -735,6 +755,18 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
|
|||
}
|
||||
return sizeFloat64Value, appendFloat64Value
|
||||
case reflect.String:
|
||||
if validateUTF8 {
|
||||
if pointer {
|
||||
return sizeStringPtr, appendUTF8StringPtr
|
||||
}
|
||||
if slice {
|
||||
return sizeStringSlice, appendUTF8StringSlice
|
||||
}
|
||||
if nozero {
|
||||
return sizeStringValueNoZero, appendUTF8StringValueNoZero
|
||||
}
|
||||
return sizeStringValue, appendUTF8StringValue
|
||||
}
|
||||
if pointer {
|
||||
return sizeStringPtr, appendStringPtr
|
||||
}
|
||||
|
|
@ -1984,9 +2016,6 @@ func appendBoolPackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byt
|
|||
}
|
||||
func appendStringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
||||
v := *ptr.toString()
|
||||
if !utf8.ValidString(v) {
|
||||
return nil, errInvalidUTF8
|
||||
}
|
||||
b = appendVarint(b, wiretag)
|
||||
b = appendVarint(b, uint64(len(v)))
|
||||
b = append(b, v...)
|
||||
|
|
@ -1997,9 +2026,6 @@ func appendStringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]b
|
|||
if v == "" {
|
||||
return b, nil
|
||||
}
|
||||
if !utf8.ValidString(v) {
|
||||
return nil, errInvalidUTF8
|
||||
}
|
||||
b = appendVarint(b, wiretag)
|
||||
b = appendVarint(b, uint64(len(v)))
|
||||
b = append(b, v...)
|
||||
|
|
@ -2011,24 +2037,83 @@ func appendStringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, err
|
|||
return b, nil
|
||||
}
|
||||
v := *p
|
||||
if !utf8.ValidString(v) {
|
||||
return nil, errInvalidUTF8
|
||||
}
|
||||
b = appendVarint(b, wiretag)
|
||||
b = appendVarint(b, uint64(len(v)))
|
||||
b = append(b, v...)
|
||||
return b, nil
|
||||
}
|
||||
func appendStringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
||||
s := *ptr.toStringSlice()
|
||||
for _, v := range s {
|
||||
b = appendVarint(b, wiretag)
|
||||
b = appendVarint(b, uint64(len(v)))
|
||||
b = append(b, v...)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
func appendUTF8StringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
||||
var invalidUTF8 bool
|
||||
v := *ptr.toString()
|
||||
if !utf8.ValidString(v) {
|
||||
invalidUTF8 = true
|
||||
}
|
||||
b = appendVarint(b, wiretag)
|
||||
b = appendVarint(b, uint64(len(v)))
|
||||
b = append(b, v...)
|
||||
if invalidUTF8 {
|
||||
return b, errInvalidUTF8
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
func appendUTF8StringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
||||
var invalidUTF8 bool
|
||||
v := *ptr.toString()
|
||||
if v == "" {
|
||||
return b, nil
|
||||
}
|
||||
if !utf8.ValidString(v) {
|
||||
invalidUTF8 = true
|
||||
}
|
||||
b = appendVarint(b, wiretag)
|
||||
b = appendVarint(b, uint64(len(v)))
|
||||
b = append(b, v...)
|
||||
if invalidUTF8 {
|
||||
return b, errInvalidUTF8
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
func appendUTF8StringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
||||
var invalidUTF8 bool
|
||||
p := *ptr.toStringPtr()
|
||||
if p == nil {
|
||||
return b, nil
|
||||
}
|
||||
v := *p
|
||||
if !utf8.ValidString(v) {
|
||||
invalidUTF8 = true
|
||||
}
|
||||
b = appendVarint(b, wiretag)
|
||||
b = appendVarint(b, uint64(len(v)))
|
||||
b = append(b, v...)
|
||||
if invalidUTF8 {
|
||||
return b, errInvalidUTF8
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
func appendUTF8StringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
||||
var invalidUTF8 bool
|
||||
s := *ptr.toStringSlice()
|
||||
for _, v := range s {
|
||||
if !utf8.ValidString(v) {
|
||||
return nil, errInvalidUTF8
|
||||
invalidUTF8 = true
|
||||
}
|
||||
b = appendVarint(b, wiretag)
|
||||
b = appendVarint(b, uint64(len(v)))
|
||||
b = append(b, v...)
|
||||
}
|
||||
if invalidUTF8 {
|
||||
return b, errInvalidUTF8
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
func appendBytes(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
|
||||
|
|
@ -2107,7 +2192,8 @@ func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
|
|||
},
|
||||
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
|
||||
s := ptr.getPointerSlice()
|
||||
var err, errreq error
|
||||
var err error
|
||||
var nerr nonFatal
|
||||
for _, v := range s {
|
||||
if v.isNil() {
|
||||
return b, errRepeatedHasNil
|
||||
|
|
@ -2115,22 +2201,14 @@ func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
|
|||
b = appendVarint(b, wiretag) // start group
|
||||
b, err = u.marshal(b, v, deterministic)
|
||||
b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group
|
||||
if err != nil {
|
||||
if _, ok := err.(*RequiredNotSetError); ok {
|
||||
// Required field in submessage is not set.
|
||||
// We record the error but keep going, to give a complete marshaling.
|
||||
if errreq == nil {
|
||||
errreq = err
|
||||
}
|
||||
continue
|
||||
}
|
||||
if !nerr.Merge(err) {
|
||||
if err == ErrNil {
|
||||
err = errRepeatedHasNil
|
||||
}
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
return b, errreq
|
||||
return b, nerr.E
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2174,7 +2252,8 @@ func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
|
|||
},
|
||||
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
|
||||
s := ptr.getPointerSlice()
|
||||
var err, errreq error
|
||||
var err error
|
||||
var nerr nonFatal
|
||||
for _, v := range s {
|
||||
if v.isNil() {
|
||||
return b, errRepeatedHasNil
|
||||
|
|
@ -2184,22 +2263,14 @@ func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
|
|||
b = appendVarint(b, uint64(siz))
|
||||
b, err = u.marshal(b, v, deterministic)
|
||||
|
||||
if err != nil {
|
||||
if _, ok := err.(*RequiredNotSetError); ok {
|
||||
// Required field in submessage is not set.
|
||||
// We record the error but keep going, to give a complete marshaling.
|
||||
if errreq == nil {
|
||||
errreq = err
|
||||
}
|
||||
continue
|
||||
}
|
||||
if !nerr.Merge(err) {
|
||||
if err == ErrNil {
|
||||
err = errRepeatedHasNil
|
||||
}
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
return b, errreq
|
||||
return b, nerr.E
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2223,14 +2294,33 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
|
|||
// value.
|
||||
// Key cannot be pointer-typed.
|
||||
valIsPtr := valType.Kind() == reflect.Ptr
|
||||
|
||||
// If value is a message with nested maps, calling
|
||||
// valSizer in marshal may be quadratic. We should use
|
||||
// cached version in marshal (but not in size).
|
||||
// If value is not message type, we don't have size cache,
|
||||
// but it cannot be nested either. Just use valSizer.
|
||||
valCachedSizer := valSizer
|
||||
if valIsPtr && valType.Elem().Kind() == reflect.Struct {
|
||||
u := getMarshalInfo(valType.Elem())
|
||||
valCachedSizer = func(ptr pointer, tagsize int) int {
|
||||
// Same as message sizer, but use cache.
|
||||
p := ptr.getPointer()
|
||||
if p.isNil() {
|
||||
return 0
|
||||
}
|
||||
siz := u.cachedsize(p)
|
||||
return siz + SizeVarint(uint64(siz)) + tagsize
|
||||
}
|
||||
}
|
||||
return func(ptr pointer, tagsize int) int {
|
||||
m := ptr.asPointerTo(t).Elem() // the map
|
||||
n := 0
|
||||
for _, k := range m.MapKeys() {
|
||||
ki := k.Interface()
|
||||
vi := m.MapIndex(k).Interface()
|
||||
kaddr := toAddrPointer(&ki, false) // pointer to key
|
||||
vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value
|
||||
kaddr := toAddrPointer(&ki, false, false) // pointer to key
|
||||
vaddr := toAddrPointer(&vi, valIsPtr, false) // pointer to value
|
||||
siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
|
||||
n += siz + SizeVarint(uint64(siz)) + tagsize
|
||||
}
|
||||
|
|
@ -2243,24 +2333,26 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
|
|||
if len(keys) > 1 && deterministic {
|
||||
sort.Sort(mapKeys(keys))
|
||||
}
|
||||
|
||||
var nerr nonFatal
|
||||
for _, k := range keys {
|
||||
ki := k.Interface()
|
||||
vi := m.MapIndex(k).Interface()
|
||||
kaddr := toAddrPointer(&ki, false) // pointer to key
|
||||
vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value
|
||||
kaddr := toAddrPointer(&ki, false, false) // pointer to key
|
||||
vaddr := toAddrPointer(&vi, valIsPtr, false) // pointer to value
|
||||
b = appendVarint(b, tag)
|
||||
siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
|
||||
siz := keySizer(kaddr, 1) + valCachedSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
|
||||
b = appendVarint(b, uint64(siz))
|
||||
b, err = keyMarshaler(b, kaddr, keyWireTag, deterministic)
|
||||
if err != nil {
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
}
|
||||
b, err = valMarshaler(b, vaddr, valWireTag, deterministic)
|
||||
if err != nil && err != ErrNil { // allow nil value in map
|
||||
if err != ErrNil && !nerr.Merge(err) { // allow nil value in map
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
return b, nil
|
||||
return b, nerr.E
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2316,7 +2408,7 @@ func (u *marshalInfo) sizeExtensions(ext *XXX_InternalExtensions) int {
|
|||
// the last time this function was called.
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
n += ei.sizer(p, ei.tagsize)
|
||||
}
|
||||
mu.Unlock()
|
||||
|
|
@ -2333,6 +2425,7 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
|
|||
defer mu.Unlock()
|
||||
|
||||
var err error
|
||||
var nerr nonFatal
|
||||
|
||||
// Fast-path for common cases: zero or one extensions.
|
||||
// Don't bother sorting the keys.
|
||||
|
|
@ -2350,13 +2443,13 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
|
|||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
|
||||
if err != nil {
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
return b, nil
|
||||
return b, nerr.E
|
||||
}
|
||||
|
||||
// Sort the keys to provide a deterministic encoding.
|
||||
|
|
@ -2381,13 +2474,13 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
|
|||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
|
||||
if err != nil {
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
return b, nil
|
||||
return b, nerr.E
|
||||
}
|
||||
|
||||
// message set format is:
|
||||
|
|
@ -2426,7 +2519,7 @@ func (u *marshalInfo) sizeMessageSet(ext *XXX_InternalExtensions) int {
|
|||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
n += ei.sizer(p, 1) // message, tag = 3 (size=1)
|
||||
}
|
||||
mu.Unlock()
|
||||
|
|
@ -2444,6 +2537,7 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
|
|||
defer mu.Unlock()
|
||||
|
||||
var err error
|
||||
var nerr nonFatal
|
||||
|
||||
// Fast-path for common cases: zero or one extensions.
|
||||
// Don't bother sorting the keys.
|
||||
|
|
@ -2468,14 +2562,14 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
|
|||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
|
||||
if err != nil {
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
}
|
||||
b = append(b, 1<<3|WireEndGroup)
|
||||
}
|
||||
return b, nil
|
||||
return b, nerr.E
|
||||
}
|
||||
|
||||
// Sort the keys to provide a deterministic encoding.
|
||||
|
|
@ -2506,14 +2600,14 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
|
|||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
|
||||
b = append(b, 1<<3|WireEndGroup)
|
||||
if err != nil {
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
return b, nil
|
||||
return b, nerr.E
|
||||
}
|
||||
|
||||
// sizeV1Extensions computes the size of encoded data for a V1-API extension field.
|
||||
|
|
@ -2536,7 +2630,7 @@ func (u *marshalInfo) sizeV1Extensions(m map[int32]Extension) int {
|
|||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
n += ei.sizer(p, ei.tagsize)
|
||||
}
|
||||
return n
|
||||
|
|
@ -2556,6 +2650,7 @@ func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, determ
|
|||
sort.Ints(keys)
|
||||
|
||||
var err error
|
||||
var nerr nonFatal
|
||||
for _, k := range keys {
|
||||
e := m[int32(k)]
|
||||
if e.value == nil || e.desc == nil {
|
||||
|
|
@ -2570,13 +2665,13 @@ func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, determ
|
|||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
|
||||
if err != nil {
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
}
|
||||
}
|
||||
return b, nil
|
||||
return b, nerr.E
|
||||
}
|
||||
|
||||
// newMarshaler is the interface representing objects that can marshal themselves.
|
||||
|
|
|
|||
|
|
@ -97,6 +97,8 @@ type unmarshalFieldInfo struct {
|
|||
|
||||
// if a required field, contains a single set bit at this field's index in the required field list.
|
||||
reqMask uint64
|
||||
|
||||
name string // name of the field, for error reporting
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
@ -134,10 +136,10 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
|
|||
u.computeUnmarshalInfo()
|
||||
}
|
||||
if u.isMessageSet {
|
||||
return UnmarshalMessageSet(b, m.offset(u.extensions).toExtensions())
|
||||
return unmarshalMessageSet(b, m.offset(u.extensions).toExtensions())
|
||||
}
|
||||
var reqMask uint64 // bitmask of required fields we've seen.
|
||||
var rnse *RequiredNotSetError // an instance of a RequiredNotSetError returned by a submessage.
|
||||
var reqMask uint64 // bitmask of required fields we've seen.
|
||||
var errLater error
|
||||
for len(b) > 0 {
|
||||
// Read tag and wire type.
|
||||
// Special case 1 and 2 byte varints.
|
||||
|
|
@ -176,11 +178,20 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
|
|||
if r, ok := err.(*RequiredNotSetError); ok {
|
||||
// Remember this error, but keep parsing. We need to produce
|
||||
// a full parse even if a required field is missing.
|
||||
rnse = r
|
||||
if errLater == nil {
|
||||
errLater = r
|
||||
}
|
||||
reqMask |= f.reqMask
|
||||
continue
|
||||
}
|
||||
if err != errInternalBadWireType {
|
||||
if err == errInvalidUTF8 {
|
||||
if errLater == nil {
|
||||
fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name
|
||||
errLater = &invalidUTF8Error{fullName}
|
||||
}
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
// Fragments with bad wire type are treated as unknown fields.
|
||||
|
|
@ -239,20 +250,16 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
|
|||
emap[int32(tag)] = e
|
||||
}
|
||||
}
|
||||
if rnse != nil {
|
||||
// A required field of a submessage/group is missing. Return that error.
|
||||
return rnse
|
||||
}
|
||||
if reqMask != u.reqMask {
|
||||
if reqMask != u.reqMask && errLater == nil {
|
||||
// A required field of this message is missing.
|
||||
for _, n := range u.reqFields {
|
||||
if reqMask&1 == 0 {
|
||||
return &RequiredNotSetError{n}
|
||||
errLater = &RequiredNotSetError{n}
|
||||
}
|
||||
reqMask >>= 1
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return errLater
|
||||
}
|
||||
|
||||
// computeUnmarshalInfo fills in u with information for use
|
||||
|
|
@ -351,43 +358,52 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
|
|||
}
|
||||
|
||||
// Store the info in the correct slot in the message.
|
||||
u.setTag(tag, toField(&f), unmarshal, reqMask)
|
||||
u.setTag(tag, toField(&f), unmarshal, reqMask, name)
|
||||
}
|
||||
|
||||
// Find any types associated with oneof fields.
|
||||
// TODO: XXX_OneofFuncs returns more info than we need. Get rid of some of it?
|
||||
fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("XXX_OneofFuncs")
|
||||
if fn.IsValid() {
|
||||
res := fn.Call(nil)[3] // last return value from XXX_OneofFuncs: []interface{}
|
||||
for i := res.Len() - 1; i >= 0; i-- {
|
||||
v := res.Index(i) // interface{}
|
||||
tptr := reflect.ValueOf(v.Interface()).Type() // *Msg_X
|
||||
typ := tptr.Elem() // Msg_X
|
||||
var oneofImplementers []interface{}
|
||||
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
|
||||
case oneofFuncsIface:
|
||||
_, _, _, oneofImplementers = m.XXX_OneofFuncs()
|
||||
case oneofWrappersIface:
|
||||
oneofImplementers = m.XXX_OneofWrappers()
|
||||
}
|
||||
for _, v := range oneofImplementers {
|
||||
tptr := reflect.TypeOf(v) // *Msg_X
|
||||
typ := tptr.Elem() // Msg_X
|
||||
|
||||
f := typ.Field(0) // oneof implementers have one field
|
||||
baseUnmarshal := fieldUnmarshaler(&f)
|
||||
tagstr := strings.Split(f.Tag.Get("protobuf"), ",")[1]
|
||||
tag, err := strconv.Atoi(tagstr)
|
||||
if err != nil {
|
||||
panic("protobuf tag field not an integer: " + tagstr)
|
||||
}
|
||||
|
||||
// Find the oneof field that this struct implements.
|
||||
// Might take O(n^2) to process all of the oneofs, but who cares.
|
||||
for _, of := range oneofFields {
|
||||
if tptr.Implements(of.ityp) {
|
||||
// We have found the corresponding interface for this struct.
|
||||
// That lets us know where this struct should be stored
|
||||
// when we encounter it during unmarshaling.
|
||||
unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal)
|
||||
u.setTag(tag, of.field, unmarshal, 0)
|
||||
}
|
||||
f := typ.Field(0) // oneof implementers have one field
|
||||
baseUnmarshal := fieldUnmarshaler(&f)
|
||||
tags := strings.Split(f.Tag.Get("protobuf"), ",")
|
||||
fieldNum, err := strconv.Atoi(tags[1])
|
||||
if err != nil {
|
||||
panic("protobuf tag field not an integer: " + tags[1])
|
||||
}
|
||||
var name string
|
||||
for _, tag := range tags {
|
||||
if strings.HasPrefix(tag, "name=") {
|
||||
name = strings.TrimPrefix(tag, "name=")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Find the oneof field that this struct implements.
|
||||
// Might take O(n^2) to process all of the oneofs, but who cares.
|
||||
for _, of := range oneofFields {
|
||||
if tptr.Implements(of.ityp) {
|
||||
// We have found the corresponding interface for this struct.
|
||||
// That lets us know where this struct should be stored
|
||||
// when we encounter it during unmarshaling.
|
||||
unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal)
|
||||
u.setTag(fieldNum, of.field, unmarshal, 0, name)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Get extension ranges, if any.
|
||||
fn = reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray")
|
||||
fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray")
|
||||
if fn.IsValid() {
|
||||
if !u.extensions.IsValid() && !u.oldExtensions.IsValid() {
|
||||
panic("a message with extensions, but no extensions field in " + t.Name())
|
||||
|
|
@ -401,7 +417,7 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
|
|||
// [0 0] is [tag=0/wiretype=varint varint-encoded-0].
|
||||
u.setTag(0, zeroField, func(b []byte, f pointer, w int) ([]byte, error) {
|
||||
return nil, fmt.Errorf("proto: %s: illegal tag 0 (wire type %d)", t, w)
|
||||
}, 0)
|
||||
}, 0, "")
|
||||
|
||||
// Set mask for required field check.
|
||||
u.reqMask = uint64(1)<<uint(len(u.reqFields)) - 1
|
||||
|
|
@ -413,8 +429,9 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
|
|||
// tag = tag # for field
|
||||
// field/unmarshal = unmarshal info for that field.
|
||||
// reqMask = if required, bitmask for field position in required field list. 0 otherwise.
|
||||
func (u *unmarshalInfo) setTag(tag int, field field, unmarshal unmarshaler, reqMask uint64) {
|
||||
i := unmarshalFieldInfo{field: field, unmarshal: unmarshal, reqMask: reqMask}
|
||||
// name = short name of the field.
|
||||
func (u *unmarshalInfo) setTag(tag int, field field, unmarshal unmarshaler, reqMask uint64, name string) {
|
||||
i := unmarshalFieldInfo{field: field, unmarshal: unmarshal, reqMask: reqMask, name: name}
|
||||
n := u.typ.NumField()
|
||||
if tag >= 0 && (tag < 16 || tag < 2*n) { // TODO: what are the right numbers here?
|
||||
for len(u.dense) <= tag {
|
||||
|
|
@ -442,11 +459,17 @@ func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
|
|||
tagArray := strings.Split(tags, ",")
|
||||
encoding := tagArray[0]
|
||||
name := "unknown"
|
||||
proto3 := false
|
||||
validateUTF8 := true
|
||||
for _, tag := range tagArray[3:] {
|
||||
if strings.HasPrefix(tag, "name=") {
|
||||
name = tag[5:]
|
||||
}
|
||||
if tag == "proto3" {
|
||||
proto3 = true
|
||||
}
|
||||
}
|
||||
validateUTF8 = validateUTF8 && proto3
|
||||
|
||||
// Figure out packaging (pointer, slice, or both)
|
||||
slice := false
|
||||
|
|
@ -594,6 +617,15 @@ func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
|
|||
}
|
||||
return unmarshalBytesValue
|
||||
case reflect.String:
|
||||
if validateUTF8 {
|
||||
if pointer {
|
||||
return unmarshalUTF8StringPtr
|
||||
}
|
||||
if slice {
|
||||
return unmarshalUTF8StringSlice
|
||||
}
|
||||
return unmarshalUTF8StringValue
|
||||
}
|
||||
if pointer {
|
||||
return unmarshalStringPtr
|
||||
}
|
||||
|
|
@ -1448,9 +1480,6 @@ func unmarshalStringValue(b []byte, f pointer, w int) ([]byte, error) {
|
|||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
v := string(b[:x])
|
||||
if !utf8.ValidString(v) {
|
||||
return nil, errInvalidUTF8
|
||||
}
|
||||
*f.toString() = v
|
||||
return b[x:], nil
|
||||
}
|
||||
|
|
@ -1468,9 +1497,6 @@ func unmarshalStringPtr(b []byte, f pointer, w int) ([]byte, error) {
|
|||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
v := string(b[:x])
|
||||
if !utf8.ValidString(v) {
|
||||
return nil, errInvalidUTF8
|
||||
}
|
||||
*f.toStringPtr() = &v
|
||||
return b[x:], nil
|
||||
}
|
||||
|
|
@ -1488,14 +1514,72 @@ func unmarshalStringSlice(b []byte, f pointer, w int) ([]byte, error) {
|
|||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
v := string(b[:x])
|
||||
if !utf8.ValidString(v) {
|
||||
return nil, errInvalidUTF8
|
||||
}
|
||||
s := f.toStringSlice()
|
||||
*s = append(*s, v)
|
||||
return b[x:], nil
|
||||
}
|
||||
|
||||
func unmarshalUTF8StringValue(b []byte, f pointer, w int) ([]byte, error) {
|
||||
if w != WireBytes {
|
||||
return b, errInternalBadWireType
|
||||
}
|
||||
x, n := decodeVarint(b)
|
||||
if n == 0 {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
b = b[n:]
|
||||
if x > uint64(len(b)) {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
v := string(b[:x])
|
||||
*f.toString() = v
|
||||
if !utf8.ValidString(v) {
|
||||
return b[x:], errInvalidUTF8
|
||||
}
|
||||
return b[x:], nil
|
||||
}
|
||||
|
||||
func unmarshalUTF8StringPtr(b []byte, f pointer, w int) ([]byte, error) {
|
||||
if w != WireBytes {
|
||||
return b, errInternalBadWireType
|
||||
}
|
||||
x, n := decodeVarint(b)
|
||||
if n == 0 {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
b = b[n:]
|
||||
if x > uint64(len(b)) {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
v := string(b[:x])
|
||||
*f.toStringPtr() = &v
|
||||
if !utf8.ValidString(v) {
|
||||
return b[x:], errInvalidUTF8
|
||||
}
|
||||
return b[x:], nil
|
||||
}
|
||||
|
||||
func unmarshalUTF8StringSlice(b []byte, f pointer, w int) ([]byte, error) {
|
||||
if w != WireBytes {
|
||||
return b, errInternalBadWireType
|
||||
}
|
||||
x, n := decodeVarint(b)
|
||||
if n == 0 {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
b = b[n:]
|
||||
if x > uint64(len(b)) {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
v := string(b[:x])
|
||||
s := f.toStringSlice()
|
||||
*s = append(*s, v)
|
||||
if !utf8.ValidString(v) {
|
||||
return b[x:], errInvalidUTF8
|
||||
}
|
||||
return b[x:], nil
|
||||
}
|
||||
|
||||
var emptyBuf [0]byte
|
||||
|
||||
func unmarshalBytesValue(b []byte, f pointer, w int) ([]byte, error) {
|
||||
|
|
@ -1674,6 +1758,7 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
|
|||
// Maps will be somewhat slow. Oh well.
|
||||
|
||||
// Read key and value from data.
|
||||
var nerr nonFatal
|
||||
k := reflect.New(kt)
|
||||
v := reflect.New(vt)
|
||||
for len(b) > 0 {
|
||||
|
|
@ -1694,7 +1779,7 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
|
|||
err = errInternalBadWireType // skip unknown tag
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
if nerr.Merge(err) {
|
||||
continue
|
||||
}
|
||||
if err != errInternalBadWireType {
|
||||
|
|
@ -1717,7 +1802,7 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
|
|||
// Insert into map.
|
||||
m.SetMapIndex(k.Elem(), v.Elem())
|
||||
|
||||
return r, nil
|
||||
return r, nerr.E
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1743,15 +1828,16 @@ func makeUnmarshalOneof(typ, ityp reflect.Type, unmarshal unmarshaler) unmarshal
|
|||
// Unmarshal data into holder.
|
||||
// We unmarshal into the first field of the holder object.
|
||||
var err error
|
||||
var nerr nonFatal
|
||||
b, err = unmarshal(b, valToPointer(v).offset(field0), w)
|
||||
if err != nil {
|
||||
if !nerr.Merge(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Write pointer to holder into target field.
|
||||
f.asPointerTo(ityp).Elem().Set(v)
|
||||
|
||||
return b, nil
|
||||
return b, nerr.E
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1864,7 +1950,7 @@ func encodeVarint(b []byte, x uint64) []byte {
|
|||
// If there is an error, it returns 0,0.
|
||||
func decodeVarint(b []byte) (uint64, int) {
|
||||
var x, y uint64
|
||||
if len(b) <= 0 {
|
||||
if len(b) == 0 {
|
||||
goto bad
|
||||
}
|
||||
x = uint64(b[0])
|
||||
|
|
|
|||
|
|
@ -353,7 +353,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
if err := tm.writeAny(w, key, props.mkeyprop); err != nil {
|
||||
if err := tm.writeAny(w, key, props.MapKeyProp); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := w.WriteByte('\n'); err != nil {
|
||||
|
|
@ -370,7 +370,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
if err := tm.writeAny(w, val, props.mvalprop); err != nil {
|
||||
if err := tm.writeAny(w, val, props.MapValProp); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := w.WriteByte('\n'); err != nil {
|
||||
|
|
|
|||
|
|
@ -630,17 +630,17 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
|
|||
if err := p.consumeToken(":"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.readAny(key, props.mkeyprop); err != nil {
|
||||
if err := p.readAny(key, props.MapKeyProp); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.consumeOptionalSeparator(); err != nil {
|
||||
return err
|
||||
}
|
||||
case "value":
|
||||
if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
|
||||
if err := p.checkForColon(props.MapValProp, dst.Type().Elem()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.readAny(val, props.mvalprop); err != nil {
|
||||
if err := p.readAny(val, props.MapValProp); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.consumeOptionalSeparator(); err != nil {
|
||||
|
|
|
|||
|
|
@ -130,10 +130,12 @@ func UnmarshalAny(any *any.Any, pb proto.Message) error {
|
|||
|
||||
// Is returns true if any value contains a given message type.
|
||||
func Is(any *any.Any, pb proto.Message) bool {
|
||||
aname, err := AnyMessageName(any)
|
||||
if err != nil {
|
||||
// The following is equivalent to AnyMessageName(any) == proto.MessageName(pb),
|
||||
// but it avoids scanning TypeUrl for the slash.
|
||||
if any == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return aname == proto.MessageName(pb)
|
||||
name := proto.MessageName(pb)
|
||||
prefix := len(any.TypeUrl) - len(name)
|
||||
return prefix >= 1 && any.TypeUrl[prefix-1] == '/' && any.TypeUrl[prefix:] == name
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@
|
|||
|
||||
package any
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
@ -16,7 +18,7 @@ var _ = math.Inf
|
|||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// `Any` contains an arbitrary serialized protocol buffer message along with a
|
||||
// URL that describes the type of the serialized message.
|
||||
|
|
@ -99,17 +101,18 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
|||
// }
|
||||
//
|
||||
type Any struct {
|
||||
// A URL/resource name whose content describes the type of the
|
||||
// serialized protocol buffer message.
|
||||
// A URL/resource name that uniquely identifies the type of the serialized
|
||||
// protocol buffer message. The last segment of the URL's path must represent
|
||||
// the fully qualified name of the type (as in
|
||||
// `path/google.protobuf.Duration`). The name should be in a canonical form
|
||||
// (e.g., leading "." is not accepted).
|
||||
//
|
||||
// For URLs which use the scheme `http`, `https`, or no scheme, the
|
||||
// following restrictions and interpretations apply:
|
||||
// In practice, teams usually precompile into the binary all types that they
|
||||
// expect it to use in the context of Any. However, for URLs which use the
|
||||
// scheme `http`, `https`, or no scheme, one can optionally set up a type
|
||||
// server that maps type URLs to message definitions as follows:
|
||||
//
|
||||
// * If no scheme is provided, `https` is assumed.
|
||||
// * The last segment of the URL's path must represent the fully
|
||||
// qualified name of the type (as in `path/google.protobuf.Duration`).
|
||||
// The name should be in a canonical form (e.g., leading "." is
|
||||
// not accepted).
|
||||
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
||||
// value in binary format, or produce an error.
|
||||
// * Applications are allowed to cache lookup results based on the
|
||||
|
|
@ -118,10 +121,14 @@ type Any struct {
|
|||
// on changes to types. (Use versioned type names to manage
|
||||
// breaking changes.)
|
||||
//
|
||||
// Note: this functionality is not currently available in the official
|
||||
// protobuf release, and it is not used for type URLs beginning with
|
||||
// type.googleapis.com.
|
||||
//
|
||||
// Schemes other than `http`, `https` (or the empty scheme) might be
|
||||
// used with implementation specific semantics.
|
||||
//
|
||||
TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl" json:"type_url,omitempty"`
|
||||
TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"`
|
||||
// Must be a valid serialized protocol buffer of the above specified type.
|
||||
Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
|
|
@ -133,17 +140,19 @@ func (m *Any) Reset() { *m = Any{} }
|
|||
func (m *Any) String() string { return proto.CompactTextString(m) }
|
||||
func (*Any) ProtoMessage() {}
|
||||
func (*Any) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_any_744b9ca530f228db, []int{0}
|
||||
return fileDescriptor_b53526c13ae22eb4, []int{0}
|
||||
}
|
||||
|
||||
func (*Any) XXX_WellKnownType() string { return "Any" }
|
||||
|
||||
func (m *Any) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Any.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Any) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Any.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Any) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Any.Merge(dst, src)
|
||||
func (m *Any) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Any.Merge(m, src)
|
||||
}
|
||||
func (m *Any) XXX_Size() int {
|
||||
return xxx_messageInfo_Any.Size(m)
|
||||
|
|
@ -172,9 +181,9 @@ func init() {
|
|||
proto.RegisterType((*Any)(nil), "google.protobuf.Any")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor_any_744b9ca530f228db) }
|
||||
func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor_b53526c13ae22eb4) }
|
||||
|
||||
var fileDescriptor_any_744b9ca530f228db = []byte{
|
||||
var fileDescriptor_b53526c13ae22eb4 = []byte{
|
||||
// 185 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcf, 0xcf, 0x4f,
|
||||
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcc, 0xab, 0xd4,
|
||||
|
|
|
|||
|
|
@ -120,17 +120,18 @@ option objc_class_prefix = "GPB";
|
|||
// }
|
||||
//
|
||||
message Any {
|
||||
// A URL/resource name whose content describes the type of the
|
||||
// serialized protocol buffer message.
|
||||
// A URL/resource name that uniquely identifies the type of the serialized
|
||||
// protocol buffer message. The last segment of the URL's path must represent
|
||||
// the fully qualified name of the type (as in
|
||||
// `path/google.protobuf.Duration`). The name should be in a canonical form
|
||||
// (e.g., leading "." is not accepted).
|
||||
//
|
||||
// For URLs which use the scheme `http`, `https`, or no scheme, the
|
||||
// following restrictions and interpretations apply:
|
||||
// In practice, teams usually precompile into the binary all types that they
|
||||
// expect it to use in the context of Any. However, for URLs which use the
|
||||
// scheme `http`, `https`, or no scheme, one can optionally set up a type
|
||||
// server that maps type URLs to message definitions as follows:
|
||||
//
|
||||
// * If no scheme is provided, `https` is assumed.
|
||||
// * The last segment of the URL's path must represent the fully
|
||||
// qualified name of the type (as in `path/google.protobuf.Duration`).
|
||||
// The name should be in a canonical form (e.g., leading "." is
|
||||
// not accepted).
|
||||
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
||||
// value in binary format, or produce an error.
|
||||
// * Applications are allowed to cache lookup results based on the
|
||||
|
|
@ -139,6 +140,10 @@ message Any {
|
|||
// on changes to types. (Use versioned type names to manage
|
||||
// breaking changes.)
|
||||
//
|
||||
// Note: this functionality is not currently available in the official
|
||||
// protobuf release, and it is not used for type URLs beginning with
|
||||
// type.googleapis.com.
|
||||
//
|
||||
// Schemes other than `http`, `https` (or the empty scheme) might be
|
||||
// used with implementation specific semantics.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ func Duration(p *durpb.Duration) (time.Duration, error) {
|
|||
return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p)
|
||||
}
|
||||
if p.Nanos != 0 {
|
||||
d += time.Duration(p.Nanos)
|
||||
d += time.Duration(p.Nanos) * time.Nanosecond
|
||||
if (d < 0) != (p.Nanos < 0) {
|
||||
return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@
|
|||
|
||||
package duration
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
@ -16,7 +18,7 @@ var _ = math.Inf
|
|||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// A Duration represents a signed, fixed-length span of time represented
|
||||
// as a count of seconds and fractions of seconds at nanosecond
|
||||
|
|
@ -82,14 +84,14 @@ type Duration struct {
|
|||
// Signed seconds of the span of time. Must be from -315,576,000,000
|
||||
// to +315,576,000,000 inclusive. Note: these bounds are computed from:
|
||||
// 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
|
||||
Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"`
|
||||
Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
|
||||
// Signed fractions of a second at nanosecond resolution of the span
|
||||
// of time. Durations less than one second are represented with a 0
|
||||
// `seconds` field and a positive or negative `nanos` field. For durations
|
||||
// of one second or more, a non-zero value for the `nanos` field must be
|
||||
// of the same sign as the `seconds` field. Must be from -999,999,999
|
||||
// to +999,999,999 inclusive.
|
||||
Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"`
|
||||
Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
|
|
@ -99,17 +101,19 @@ func (m *Duration) Reset() { *m = Duration{} }
|
|||
func (m *Duration) String() string { return proto.CompactTextString(m) }
|
||||
func (*Duration) ProtoMessage() {}
|
||||
func (*Duration) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_duration_e7d612259e3f0613, []int{0}
|
||||
return fileDescriptor_23597b2ebd7ac6c5, []int{0}
|
||||
}
|
||||
|
||||
func (*Duration) XXX_WellKnownType() string { return "Duration" }
|
||||
|
||||
func (m *Duration) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Duration.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Duration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Duration.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Duration) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Duration.Merge(dst, src)
|
||||
func (m *Duration) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Duration.Merge(m, src)
|
||||
}
|
||||
func (m *Duration) XXX_Size() int {
|
||||
return xxx_messageInfo_Duration.Size(m)
|
||||
|
|
@ -138,11 +142,9 @@ func init() {
|
|||
proto.RegisterType((*Duration)(nil), "google.protobuf.Duration")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor_duration_e7d612259e3f0613)
|
||||
}
|
||||
func init() { proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor_23597b2ebd7ac6c5) }
|
||||
|
||||
var fileDescriptor_duration_e7d612259e3f0613 = []byte{
|
||||
var fileDescriptor_23597b2ebd7ac6c5 = []byte{
|
||||
// 190 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f,
|
||||
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0x29, 0x2d, 0x4a,
|
||||
|
|
|
|||
|
|
@ -111,11 +111,9 @@ func TimestampNow() *tspb.Timestamp {
|
|||
// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
|
||||
// It returns an error if the resulting Timestamp is invalid.
|
||||
func TimestampProto(t time.Time) (*tspb.Timestamp, error) {
|
||||
seconds := t.Unix()
|
||||
nanos := int32(t.Sub(time.Unix(seconds, 0)))
|
||||
ts := &tspb.Timestamp{
|
||||
Seconds: seconds,
|
||||
Nanos: nanos,
|
||||
Seconds: t.Unix(),
|
||||
Nanos: int32(t.Nanosecond()),
|
||||
}
|
||||
if err := validateTimestamp(ts); err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@
|
|||
|
||||
package timestamp
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
@ -16,7 +18,7 @@ var _ = math.Inf
|
|||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// A Timestamp represents a point in time independent of any time zone
|
||||
// or calendar, represented as seconds and fractions of seconds at
|
||||
|
|
@ -81,7 +83,9 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
|||
// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
|
||||
// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
|
||||
// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
|
||||
// is required, though only UTC (as indicated by "Z") is presently supported.
|
||||
// is required. A proto3 JSON serializer should always use UTC (as indicated by
|
||||
// "Z") when printing the Timestamp type and a proto3 JSON parser should be
|
||||
// able to accept both UTC and other timezones (as indicated by an offset).
|
||||
//
|
||||
// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
|
||||
// 01:30 UTC on January 15, 2017.
|
||||
|
|
@ -92,20 +96,20 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
|||
// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
|
||||
// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
|
||||
// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
||||
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--)
|
||||
// to obtain a formatter capable of generating timestamps in this format.
|
||||
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
|
||||
// ) to obtain a formatter capable of generating timestamps in this format.
|
||||
//
|
||||
//
|
||||
type Timestamp struct {
|
||||
// Represents seconds of UTC time since Unix epoch
|
||||
// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
|
||||
// 9999-12-31T23:59:59Z inclusive.
|
||||
Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"`
|
||||
Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
|
||||
// Non-negative fractions of a second at nanosecond resolution. Negative
|
||||
// second values with fractions must still have non-negative nanos values
|
||||
// that count forward in time. Must be from 0 to 999,999,999
|
||||
// inclusive.
|
||||
Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"`
|
||||
Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
|
|
@ -115,17 +119,19 @@ func (m *Timestamp) Reset() { *m = Timestamp{} }
|
|||
func (m *Timestamp) String() string { return proto.CompactTextString(m) }
|
||||
func (*Timestamp) ProtoMessage() {}
|
||||
func (*Timestamp) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_timestamp_b826e8e5fba671a8, []int{0}
|
||||
return fileDescriptor_292007bbfe81227e, []int{0}
|
||||
}
|
||||
|
||||
func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" }
|
||||
|
||||
func (m *Timestamp) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Timestamp.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Timestamp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Timestamp.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Timestamp) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Timestamp.Merge(dst, src)
|
||||
func (m *Timestamp) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Timestamp.Merge(m, src)
|
||||
}
|
||||
func (m *Timestamp) XXX_Size() int {
|
||||
return xxx_messageInfo_Timestamp.Size(m)
|
||||
|
|
@ -154,11 +160,9 @@ func init() {
|
|||
proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor_timestamp_b826e8e5fba671a8)
|
||||
}
|
||||
func init() { proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor_292007bbfe81227e) }
|
||||
|
||||
var fileDescriptor_timestamp_b826e8e5fba671a8 = []byte{
|
||||
var fileDescriptor_292007bbfe81227e = []byte{
|
||||
// 191 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xcf, 0xcf, 0x4f,
|
||||
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xc9, 0xcc, 0x4d,
|
||||
|
|
|
|||
|
|
@ -103,7 +103,9 @@ option objc_class_prefix = "GPB";
|
|||
// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
|
||||
// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
|
||||
// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
|
||||
// is required, though only UTC (as indicated by "Z") is presently supported.
|
||||
// is required. A proto3 JSON serializer should always use UTC (as indicated by
|
||||
// "Z") when printing the Timestamp type and a proto3 JSON parser should be
|
||||
// able to accept both UTC and other timezones (as indicated by an offset).
|
||||
//
|
||||
// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
|
||||
// 01:30 UTC on January 15, 2017.
|
||||
|
|
@ -114,8 +116,8 @@ option objc_class_prefix = "GPB";
|
|||
// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
|
||||
// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
|
||||
// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
||||
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--)
|
||||
// to obtain a formatter capable of generating timestamps in this format.
|
||||
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
|
||||
// ) to obtain a formatter capable of generating timestamps in this format.
|
||||
//
|
||||
//
|
||||
message Timestamp {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: 40%
|
||||
threshold: null
|
||||
patch: false
|
||||
changes: false
|
||||
|
|
@ -1,7 +1,19 @@
|
|||
language: go
|
||||
sudo: false
|
||||
|
||||
go:
|
||||
- 1.5
|
||||
- 1.6
|
||||
- 1.10.x
|
||||
- 1.11.x
|
||||
- 1.12.x
|
||||
- tip
|
||||
|
||||
before_install:
|
||||
# don't use the miekg/dns when testing forks
|
||||
- mkdir -p $GOPATH/src/github.com/miekg
|
||||
- ln -s $TRAVIS_BUILD_DIR $GOPATH/src/github.com/miekg/ || true
|
||||
|
||||
script:
|
||||
- go test -race -v -bench=.
|
||||
- go test -race -v -bench=. -coverprofile=coverage.txt -covermode=atomic ./...
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
|
|
|||
|
|
@ -7,3 +7,4 @@ Marek Majkowski
|
|||
Peter van Dijk
|
||||
Omri Bahumi
|
||||
Alex Sergeyev
|
||||
James Hartig
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:6914c49eed986dfb8dffb33516fa129c49929d4d873f41e073c83c11c372b870"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = [
|
||||
"ed25519",
|
||||
"ed25519/internal/edwards25519",
|
||||
]
|
||||
pruneopts = ""
|
||||
revision = "e3636079e1a4c1f337f212cc5cd2aca108f6c900"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:08e41d63f8dac84d83797368b56cf0b339e42d0224e5e56668963c28aec95685"
|
||||
name = "golang.org/x/net"
|
||||
packages = [
|
||||
"bpf",
|
||||
"context",
|
||||
"internal/iana",
|
||||
"internal/socket",
|
||||
"ipv4",
|
||||
"ipv6",
|
||||
]
|
||||
pruneopts = ""
|
||||
revision = "4dfa2610cdf3b287375bbba5b8f2a14d3b01d8de"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:b2ea75de0ccb2db2ac79356407f8a4cd8f798fe15d41b381c00abf3ae8e55ed1"
|
||||
name = "golang.org/x/sync"
|
||||
packages = ["errgroup"]
|
||||
pruneopts = ""
|
||||
revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:149a432fabebb8221a80f77731b1cd63597197ded4f14af606ebe3a0959004ec"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix"]
|
||||
pruneopts = ""
|
||||
revision = "e4b3c5e9061176387e7cea65e4dc5853801f3fb7"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
input-imports = [
|
||||
"golang.org/x/crypto/ed25519",
|
||||
"golang.org/x/net/ipv4",
|
||||
"golang.org/x/net/ipv6",
|
||||
"golang.org/x/sync/errgroup",
|
||||
"golang.org/x/sys/unix",
|
||||
]
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sync"
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# Makefile for fuzzing
|
||||
#
|
||||
# Use go-fuzz and needs the tools installed.
|
||||
# See https://blog.cloudflare.com/dns-parser-meet-go-fuzzer/
|
||||
#
|
||||
# Installing go-fuzz:
|
||||
# $ make -f Makefile.fuzz get
|
||||
# Installs:
|
||||
# * github.com/dvyukov/go-fuzz/go-fuzz
|
||||
# * get github.com/dvyukov/go-fuzz/go-fuzz-build
|
||||
|
||||
all: build
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
go-fuzz-build -tags fuzz github.com/miekg/dns
|
||||
|
||||
.PHONY: build-newrr
|
||||
build-newrr:
|
||||
go-fuzz-build -func FuzzNewRR -tags fuzz github.com/miekg/dns
|
||||
|
||||
.PHONY: fuzz
|
||||
fuzz:
|
||||
go-fuzz -bin=dns-fuzz.zip -workdir=fuzz
|
||||
|
||||
.PHONY: get
|
||||
get:
|
||||
go get github.com/dvyukov/go-fuzz/go-fuzz
|
||||
go get github.com/dvyukov/go-fuzz/go-fuzz-build
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm *-fuzz.zip
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
# Makefile for releasing.
|
||||
#
|
||||
# The release is controlled from version.go. The version found there is
|
||||
# used to tag the git repo, we're not building any artifects so there is nothing
|
||||
# to upload to github.
|
||||
#
|
||||
# * Up the version in version.go
|
||||
# * Run: make -f Makefile.release release
|
||||
# * will *commit* your change with 'Release $VERSION'
|
||||
# * push to github
|
||||
#
|
||||
|
||||
define GO
|
||||
//+build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(dns.Version.String())
|
||||
}
|
||||
endef
|
||||
|
||||
$(file > version_release.go,$(GO))
|
||||
VERSION:=$(shell go run version_release.go)
|
||||
TAG="v$(VERSION)"
|
||||
|
||||
all:
|
||||
@echo Use the \'release\' target to start a release $(VERSION)
|
||||
rm -f version_release.go
|
||||
|
||||
.PHONY: release
|
||||
release: commit push
|
||||
@echo Released $(VERSION)
|
||||
rm -f version_release.go
|
||||
|
||||
.PHONY: commit
|
||||
commit:
|
||||
@echo Committing release $(VERSION)
|
||||
git commit -am"Release $(VERSION)"
|
||||
git tag $(TAG)
|
||||
|
||||
.PHONY: push
|
||||
push:
|
||||
@echo Pushing release $(VERSION) to master
|
||||
git push --tags
|
||||
git push
|
||||
|
|
@ -1,29 +1,31 @@
|
|||
[](https://travis-ci.org/miekg/dns)
|
||||
[](https://codecov.io/github/miekg/dns?branch=master)
|
||||
[](https://goreportcard.com/report/miekg/dns)
|
||||
[](https://godoc.org/github.com/miekg/dns)
|
||||
|
||||
# Alternative (more granular) approach to a DNS library
|
||||
|
||||
> Less is more.
|
||||
|
||||
Complete and usable DNS library. All widely used Resource Records are
|
||||
supported, including the DNSSEC types. It follows a lean and mean philosophy.
|
||||
If there is stuff you should know as a DNS programmer there isn't a convenience
|
||||
function for it. Server side and client side programming is supported, i.e. you
|
||||
Complete and usable DNS library. All Resource Records are supported, including the DNSSEC types.
|
||||
It follows a lean and mean philosophy. If there is stuff you should know as a DNS programmer there
|
||||
isn't a convenience function for it. Server side and client side programming is supported, i.e. you
|
||||
can build servers and resolvers with it.
|
||||
|
||||
We try to keep the "master" branch as sane as possible and at the bleeding edge
|
||||
of standards, avoiding breaking changes wherever reasonable. We support the last
|
||||
two versions of Go, currently: 1.4 and 1.5.
|
||||
We try to keep the "master" branch as sane as possible and at the bleeding edge of standards,
|
||||
avoiding breaking changes wherever reasonable. We support the last two versions of Go.
|
||||
|
||||
# Goals
|
||||
|
||||
* KISS;
|
||||
* Fast;
|
||||
* Small API, if its easy to code in Go, don't make a function for it.
|
||||
* Small API. If it's easy to code in Go, don't make a function for it.
|
||||
|
||||
# Users
|
||||
|
||||
A not-so-up-to-date-list-that-may-be-actually-current:
|
||||
|
||||
* https://github.com/coredns/coredns
|
||||
* https://cloudflare.com
|
||||
* https://github.com/abh/geodns
|
||||
* http://www.statdns.com/
|
||||
|
|
@ -40,50 +42,67 @@ A not-so-up-to-date-list-that-may-be-actually-current:
|
|||
* https://github.com/tianon/rawdns
|
||||
* https://mesosphere.github.io/mesos-dns/
|
||||
* https://pulse.turbobytes.com/
|
||||
* https://play.google.com/store/apps/details?id=com.turbobytes.dig
|
||||
* https://github.com/fcambus/statzone
|
||||
* https://github.com/benschw/dns-clb-go
|
||||
* https://github.com/corny/dnscheck for http://public-dns.info/
|
||||
* https://github.com/corny/dnscheck for <http://public-dns.info/>
|
||||
* https://namesmith.io
|
||||
* https://github.com/miekg/unbound
|
||||
* https://github.com/miekg/exdns
|
||||
* https://dnslookup.org
|
||||
* https://github.com/looterz/grimd
|
||||
* https://github.com/phamhongviet/serf-dns
|
||||
* https://github.com/mehrdadrad/mylg
|
||||
* https://github.com/bamarni/dockness
|
||||
* https://github.com/fffaraz/microdns
|
||||
* http://kelda.io
|
||||
* https://github.com/ipdcode/hades <https://jd.com>
|
||||
* https://github.com/StackExchange/dnscontrol/
|
||||
* https://www.dnsperf.com/
|
||||
* https://dnssectest.net/
|
||||
* https://dns.apebits.com
|
||||
* https://github.com/oif/apex
|
||||
* https://github.com/jedisct1/dnscrypt-proxy
|
||||
* https://github.com/jedisct1/rpdns
|
||||
* https://github.com/xor-gate/sshfp
|
||||
* https://github.com/rs/dnstrace
|
||||
* https://blitiri.com.ar/p/dnss ([github mirror](https://github.com/albertito/dnss))
|
||||
* https://github.com/semihalev/sdns
|
||||
* https://render.com
|
||||
* https://github.com/peterzen/goresolver
|
||||
|
||||
Send pull request if you want to be listed here.
|
||||
|
||||
# Features
|
||||
|
||||
* UDP/TCP queries, IPv4 and IPv6;
|
||||
* RFC 1035 zone file parsing ($INCLUDE, $ORIGIN, $TTL and $GENERATE (for all record types) are supported;
|
||||
* Fast:
|
||||
* Reply speed around ~ 80K qps (faster hardware results in more qps);
|
||||
* Parsing RRs ~ 100K RR/s, that's 5M records in about 50 seconds;
|
||||
* Server side programming (mimicking the net/http package);
|
||||
* Client side programming;
|
||||
* DNSSEC: signing, validating and key generation for DSA, RSA and ECDSA;
|
||||
* EDNS0, NSID;
|
||||
* AXFR/IXFR;
|
||||
* TSIG, SIG(0);
|
||||
* DNS over TLS: optional encrypted connection between client and server;
|
||||
* DNS name compression;
|
||||
* Depends only on the standard library.
|
||||
* UDP/TCP queries, IPv4 and IPv6
|
||||
* RFC 1035 zone file parsing ($INCLUDE, $ORIGIN, $TTL and $GENERATE (for all record types) are supported
|
||||
* Fast
|
||||
* Server side programming (mimicking the net/http package)
|
||||
* Client side programming
|
||||
* DNSSEC: signing, validating and key generation for DSA, RSA, ECDSA and Ed25519
|
||||
* EDNS0, NSID, Cookies
|
||||
* AXFR/IXFR
|
||||
* TSIG, SIG(0)
|
||||
* DNS over TLS (DoT): encrypted connection between client and server over TCP
|
||||
* DNS name compression
|
||||
|
||||
Have fun!
|
||||
|
||||
Miek Gieben - 2010-2012 - <miek@miek.nl>
|
||||
DNS Authors 2012-
|
||||
|
||||
# Building
|
||||
|
||||
Building is done with the `go` tool. If you have setup your GOPATH
|
||||
correctly, the following should work:
|
||||
Building is done with the `go` tool. If you have setup your GOPATH correctly, the following should
|
||||
work:
|
||||
|
||||
go get github.com/miekg/dns
|
||||
go build github.com/miekg/dns
|
||||
|
||||
## Examples
|
||||
|
||||
A short "how to use the API" is at the beginning of doc.go (this also will show
|
||||
when you call `godoc github.com/miekg/dns`).
|
||||
A short "how to use the API" is at the beginning of doc.go (this also will show when you call `godoc
|
||||
github.com/miekg/dns`).
|
||||
|
||||
Example programs can be found in the `github.com/miekg/exdns` repository.
|
||||
|
||||
|
|
@ -111,7 +130,6 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
|
|||
* 340{1,2,3} - NAPTR record
|
||||
* 3445 - Limiting the scope of (DNS)KEY
|
||||
* 3597 - Unknown RRs
|
||||
* 4025 - IPSECKEY
|
||||
* 403{3,4,5} - DNSSEC + validation functions
|
||||
* 4255 - SSHFP record
|
||||
* 4343 - Case insensitivity
|
||||
|
|
@ -137,21 +155,18 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
|
|||
* 6975 - Algorithm Understanding in DNSSEC
|
||||
* 7043 - EUI48/EUI64 records
|
||||
* 7314 - DNS (EDNS) EXPIRE Option
|
||||
* 7477 - CSYNC RR
|
||||
* 7828 - edns-tcp-keepalive EDNS0 Option
|
||||
* 7553 - URI record
|
||||
* xxxx - EDNS0 DNS Update Lease (draft)
|
||||
* yyyy - DNS over TLS: Initiation and Performance Considerations (draft)
|
||||
* 7858 - DNS over TLS: Initiation and Performance Considerations
|
||||
* 7871 - EDNS0 Client Subnet
|
||||
* 7873 - Domain Name System (DNS) Cookies
|
||||
* 8080 - EdDSA for DNSSEC
|
||||
* 8499 - DNS Terminology
|
||||
|
||||
## Loosely based upon
|
||||
## Loosely Based Upon
|
||||
|
||||
* `ldns`
|
||||
* `NSD`
|
||||
* `Net::DNS`
|
||||
* `GRONG`
|
||||
|
||||
## TODO
|
||||
|
||||
* privatekey.Precompute() when signing?
|
||||
* Last remaining RRs: APL, ATMA, A6, NSAP and NXT.
|
||||
* Missing in parsing: ISDN, UNSPEC, NSAP and ATMA.
|
||||
* NSEC(3) cover/match/closest enclose.
|
||||
* Replies with TC bit are not parsed to the end.
|
||||
* ldns - <https://nlnetlabs.nl/projects/ldns/about/>
|
||||
* NSD - <https://nlnetlabs.nl/projects/nsd/about/>
|
||||
* Net::DNS - <http://www.net-dns.org/>
|
||||
* GRONG - <https://github.com/bortzmeyer/grong>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
package dns
|
||||
|
||||
// MsgAcceptFunc is used early in the server code to accept or reject a message with RcodeFormatError.
|
||||
// It returns a MsgAcceptAction to indicate what should happen with the message.
|
||||
type MsgAcceptFunc func(dh Header) MsgAcceptAction
|
||||
|
||||
// DefaultMsgAcceptFunc checks the request and will reject if:
|
||||
//
|
||||
// * isn't a request (don't respond in that case).
|
||||
// * opcode isn't OpcodeQuery or OpcodeNotify
|
||||
// * Zero bit isn't zero
|
||||
// * has more than 1 question in the question section
|
||||
// * has more than 1 RR in the Answer section
|
||||
// * has more than 0 RRs in the Authority section
|
||||
// * has more than 2 RRs in the Additional section
|
||||
var DefaultMsgAcceptFunc MsgAcceptFunc = defaultMsgAcceptFunc
|
||||
|
||||
// MsgAcceptAction represents the action to be taken.
|
||||
type MsgAcceptAction int
|
||||
|
||||
const (
|
||||
MsgAccept MsgAcceptAction = iota // Accept the message
|
||||
MsgReject // Reject the message with a RcodeFormatError
|
||||
MsgIgnore // Ignore the error and send nothing back.
|
||||
)
|
||||
|
||||
func defaultMsgAcceptFunc(dh Header) MsgAcceptAction {
|
||||
if isResponse := dh.Bits&_QR != 0; isResponse {
|
||||
return MsgIgnore
|
||||
}
|
||||
|
||||
// Don't allow dynamic updates, because then the sections can contain a whole bunch of RRs.
|
||||
opcode := int(dh.Bits>>11) & 0xF
|
||||
if opcode != OpcodeQuery && opcode != OpcodeNotify {
|
||||
return MsgReject
|
||||
}
|
||||
|
||||
if isZero := dh.Bits&_Z != 0; isZero {
|
||||
return MsgReject
|
||||
}
|
||||
if dh.Qdcount != 1 {
|
||||
return MsgReject
|
||||
}
|
||||
// NOTIFY requests can have a SOA in the ANSWER section. See RFC 1996 Section 3.7 and 3.11.
|
||||
if dh.Ancount > 1 {
|
||||
return MsgReject
|
||||
}
|
||||
// IXFR request could have one SOA RR in the NS section. See RFC 1995, section 3.
|
||||
if dh.Nscount > 1 {
|
||||
return MsgReject
|
||||
}
|
||||
if dh.Arcount > 2 {
|
||||
return MsgReject
|
||||
}
|
||||
return MsgAccept
|
||||
}
|
||||
|
|
@ -3,132 +3,60 @@ package dns
|
|||
// A client implementation.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const dnsTimeout time.Duration = 2 * time.Second
|
||||
const tcpIdleTimeout time.Duration = 8 * time.Second
|
||||
const (
|
||||
dnsTimeout time.Duration = 2 * time.Second
|
||||
tcpIdleTimeout time.Duration = 8 * time.Second
|
||||
)
|
||||
|
||||
// A Conn represents a connection to a DNS server.
|
||||
type Conn struct {
|
||||
net.Conn // a net.Conn holding the connection
|
||||
UDPSize uint16 // minimum receive buffer for UDP messages
|
||||
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
|
||||
rtt time.Duration
|
||||
t time.Time
|
||||
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
|
||||
tsigRequestMAC string
|
||||
}
|
||||
|
||||
// A Client defines parameters for a DNS client.
|
||||
type Client struct {
|
||||
Net string // if "tcp" or "tcp-tls" (DNS over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
|
||||
UDPSize uint16 // minimum receive buffer for UDP messages
|
||||
TLSConfig *tls.Config // TLS connection configuration
|
||||
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds
|
||||
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds
|
||||
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds
|
||||
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
|
||||
Net string // if "tcp" or "tcp-tls" (DNS over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
|
||||
UDPSize uint16 // minimum receive buffer for UDP messages
|
||||
TLSConfig *tls.Config // TLS connection configuration
|
||||
Dialer *net.Dialer // a net.Dialer used to set local address, timeouts and more
|
||||
// Timeout is a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout,
|
||||
// WriteTimeout when non-zero. Can be overridden with net.Dialer.Timeout (see Client.ExchangeWithDialer and
|
||||
// Client.Dialer) or context.Context.Deadline (see the deprecated ExchangeContext)
|
||||
Timeout time.Duration
|
||||
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero
|
||||
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
|
||||
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
|
||||
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
|
||||
SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
|
||||
group singleflight
|
||||
}
|
||||
|
||||
// Exchange performs a synchronous UDP query. It sends the message m to the address
|
||||
// contained in a and waits for an reply. Exchange does not retry a failed query, nor
|
||||
// contained in a and waits for a reply. Exchange does not retry a failed query, nor
|
||||
// will it fall back to TCP in case of truncation.
|
||||
// See client.Exchange for more information on setting larger buffer sizes.
|
||||
func Exchange(m *Msg, a string) (r *Msg, err error) {
|
||||
var co *Conn
|
||||
co, err = DialTimeout("udp", a, dnsTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer co.Close()
|
||||
|
||||
opt := m.IsEdns0()
|
||||
// If EDNS0 is used use that for size.
|
||||
if opt != nil && opt.UDPSize() >= MinMsgSize {
|
||||
co.UDPSize = opt.UDPSize()
|
||||
}
|
||||
|
||||
co.SetWriteDeadline(time.Now().Add(dnsTimeout))
|
||||
if err = co.WriteMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
co.SetReadDeadline(time.Now().Add(dnsTimeout))
|
||||
r, err = co.ReadMsg()
|
||||
if err == nil && r.Id != m.Id {
|
||||
err = ErrId
|
||||
}
|
||||
client := Client{Net: "udp"}
|
||||
r, _, err = client.Exchange(m, a)
|
||||
return r, err
|
||||
}
|
||||
|
||||
// ExchangeConn performs a synchronous query. It sends the message m via the connection
|
||||
// c and waits for a reply. The connection c is not closed by ExchangeConn.
|
||||
// This function is going away, but can easily be mimicked:
|
||||
//
|
||||
// co := &dns.Conn{Conn: c} // c is your net.Conn
|
||||
// co.WriteMsg(m)
|
||||
// in, _ := co.ReadMsg()
|
||||
// co.Close()
|
||||
//
|
||||
func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
|
||||
println("dns: this function is deprecated")
|
||||
co := new(Conn)
|
||||
co.Conn = c
|
||||
if err = co.WriteMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r, err = co.ReadMsg()
|
||||
if err == nil && r.Id != m.Id {
|
||||
err = ErrId
|
||||
}
|
||||
return r, err
|
||||
}
|
||||
|
||||
// Exchange performs an synchronous query. It sends the message m to the address
|
||||
// contained in a and waits for an reply. Basic use pattern with a *dns.Client:
|
||||
//
|
||||
// c := new(dns.Client)
|
||||
// in, rtt, err := c.Exchange(message, "127.0.0.1:53")
|
||||
//
|
||||
// Exchange does not retry a failed query, nor will it fall back to TCP in
|
||||
// case of truncation.
|
||||
// It is up to the caller to create a message that allows for larger responses to be
|
||||
// returned. Specifically this means adding an EDNS0 OPT RR that will advertise a larger
|
||||
// buffer, see SetEdns0. Messsages without an OPT RR will fallback to the historic limit
|
||||
// of 512 bytes.
|
||||
func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
||||
if !c.SingleInflight {
|
||||
return c.exchange(m, a)
|
||||
}
|
||||
// This adds a bunch of garbage, TODO(miek).
|
||||
t := "nop"
|
||||
if t1, ok := TypeToString[m.Question[0].Qtype]; ok {
|
||||
t = t1
|
||||
}
|
||||
cl := "nop"
|
||||
if cl1, ok := ClassToString[m.Question[0].Qclass]; ok {
|
||||
cl = cl1
|
||||
}
|
||||
r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) {
|
||||
return c.exchange(m, a)
|
||||
})
|
||||
if err != nil {
|
||||
return r, rtt, err
|
||||
}
|
||||
if shared {
|
||||
return r.Copy(), rtt, nil
|
||||
}
|
||||
return r, rtt, nil
|
||||
}
|
||||
|
||||
func (c *Client) dialTimeout() time.Duration {
|
||||
if c.Timeout != 0 {
|
||||
return c.Timeout
|
||||
}
|
||||
if c.DialTimeout != 0 {
|
||||
return c.DialTimeout
|
||||
}
|
||||
|
|
@ -149,32 +77,78 @@ func (c *Client) writeTimeout() time.Duration {
|
|||
return dnsTimeout
|
||||
}
|
||||
|
||||
// Dial connects to the address on the named network.
|
||||
func (c *Client) Dial(address string) (conn *Conn, err error) {
|
||||
// create a new dialer with the appropriate timeout
|
||||
var d net.Dialer
|
||||
if c.Dialer == nil {
|
||||
d = net.Dialer{Timeout: c.getTimeoutForRequest(c.dialTimeout())}
|
||||
} else {
|
||||
d = *c.Dialer
|
||||
}
|
||||
|
||||
network := c.Net
|
||||
if network == "" {
|
||||
network = "udp"
|
||||
}
|
||||
|
||||
useTLS := strings.HasPrefix(network, "tcp") && strings.HasSuffix(network, "-tls")
|
||||
|
||||
conn = new(Conn)
|
||||
if useTLS {
|
||||
network = strings.TrimSuffix(network, "-tls")
|
||||
|
||||
conn.Conn, err = tls.DialWithDialer(&d, network, address, c.TLSConfig)
|
||||
} else {
|
||||
conn.Conn, err = d.Dial(network, address)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// Exchange performs a synchronous query. It sends the message m to the address
|
||||
// contained in a and waits for a reply. Basic use pattern with a *dns.Client:
|
||||
//
|
||||
// c := new(dns.Client)
|
||||
// in, rtt, err := c.Exchange(message, "127.0.0.1:53")
|
||||
//
|
||||
// Exchange does not retry a failed query, nor will it fall back to TCP in
|
||||
// case of truncation.
|
||||
// It is up to the caller to create a message that allows for larger responses to be
|
||||
// returned. Specifically this means adding an EDNS0 OPT RR that will advertise a larger
|
||||
// buffer, see SetEdns0. Messages without an OPT RR will fallback to the historic limit
|
||||
// of 512 bytes
|
||||
// To specify a local address or a timeout, the caller has to set the `Client.Dialer`
|
||||
// attribute appropriately
|
||||
func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, err error) {
|
||||
if !c.SingleInflight {
|
||||
return c.exchange(m, address)
|
||||
}
|
||||
|
||||
t := "nop"
|
||||
if t1, ok := TypeToString[m.Question[0].Qtype]; ok {
|
||||
t = t1
|
||||
}
|
||||
cl := "nop"
|
||||
if cl1, ok := ClassToString[m.Question[0].Qclass]; ok {
|
||||
cl = cl1
|
||||
}
|
||||
r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) {
|
||||
return c.exchange(m, address)
|
||||
})
|
||||
if r != nil && shared {
|
||||
r = r.Copy()
|
||||
}
|
||||
return r, rtt, err
|
||||
}
|
||||
|
||||
func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
||||
var co *Conn
|
||||
network := "udp"
|
||||
tls := false
|
||||
|
||||
switch c.Net {
|
||||
case "tcp-tls":
|
||||
network = "tcp"
|
||||
tls = true
|
||||
case "tcp4-tls":
|
||||
network = "tcp4"
|
||||
tls = true
|
||||
case "tcp6-tls":
|
||||
network = "tcp6"
|
||||
tls = true
|
||||
default:
|
||||
if c.Net != "" {
|
||||
network = c.Net
|
||||
}
|
||||
}
|
||||
|
||||
if tls {
|
||||
co, err = DialTimeoutWithTLS(network, a, c.TLSConfig, c.dialTimeout())
|
||||
} else {
|
||||
co, err = DialTimeout(network, a, c.dialTimeout())
|
||||
}
|
||||
co, err = c.Dial(a)
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
|
|
@ -192,22 +166,27 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
|
|||
}
|
||||
|
||||
co.TsigSecret = c.TsigSecret
|
||||
co.SetWriteDeadline(time.Now().Add(c.writeTimeout()))
|
||||
t := time.Now()
|
||||
// write with the appropriate write timeout
|
||||
co.SetWriteDeadline(t.Add(c.getTimeoutForRequest(c.writeTimeout())))
|
||||
if err = co.WriteMsg(m); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
co.SetReadDeadline(time.Now().Add(c.readTimeout()))
|
||||
co.SetReadDeadline(time.Now().Add(c.getTimeoutForRequest(c.readTimeout())))
|
||||
r, err = co.ReadMsg()
|
||||
if err == nil && r.Id != m.Id {
|
||||
err = ErrId
|
||||
}
|
||||
return r, co.rtt, err
|
||||
rtt = time.Since(t)
|
||||
return r, rtt, err
|
||||
}
|
||||
|
||||
// ReadMsg reads a message from the connection co.
|
||||
// If the received message contains a TSIG record the transaction
|
||||
// signature is verified.
|
||||
// If the received message contains a TSIG record the transaction signature
|
||||
// is verified. This method always tries to return the message, however if an
|
||||
// error is returned there are no guarantees that the returned message is a
|
||||
// valid representation of the packet read.
|
||||
func (co *Conn) ReadMsg() (*Msg, error) {
|
||||
p, err := co.ReadMsgHeader(nil)
|
||||
if err != nil {
|
||||
|
|
@ -216,13 +195,10 @@ func (co *Conn) ReadMsg() (*Msg, error) {
|
|||
|
||||
m := new(Msg)
|
||||
if err := m.Unpack(p); err != nil {
|
||||
// If ErrTruncated was returned, we still want to allow the user to use
|
||||
// If an error was returned, we still want to allow the user to use
|
||||
// the message, but naively they can just check err if they don't want
|
||||
// to use a truncated message
|
||||
if err == ErrTruncated {
|
||||
return m, err
|
||||
}
|
||||
return nil, err
|
||||
// to use an erroneous message
|
||||
return m, err
|
||||
}
|
||||
if t := m.IsTsig(); t != nil {
|
||||
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
|
||||
|
|
@ -243,19 +219,15 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
|
|||
n int
|
||||
err error
|
||||
)
|
||||
|
||||
switch t := co.Conn.(type) {
|
||||
switch co.Conn.(type) {
|
||||
case *net.TCPConn, *tls.Conn:
|
||||
r := t.(io.Reader)
|
||||
|
||||
// First two bytes specify the length of the entire message.
|
||||
l, err := tcpMsgLen(r)
|
||||
if err != nil {
|
||||
var length uint16
|
||||
if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p = make([]byte, l)
|
||||
n, err = tcpRead(r, p)
|
||||
co.rtt = time.Since(co.t)
|
||||
|
||||
p = make([]byte, length)
|
||||
n, err = io.ReadFull(co.Conn, p)
|
||||
default:
|
||||
if co.UDPSize > MinMsgSize {
|
||||
p = make([]byte, co.UDPSize)
|
||||
|
|
@ -263,7 +235,6 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
|
|||
p = make([]byte, MinMsgSize)
|
||||
}
|
||||
n, err = co.Read(p)
|
||||
co.rtt = time.Since(co.t)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -274,73 +245,36 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
|
|||
|
||||
p = p[:n]
|
||||
if hdr != nil {
|
||||
if _, err = UnpackStruct(hdr, p, 0); err != nil {
|
||||
dh, _, err := unpackMsgHdr(p, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
*hdr = dh
|
||||
}
|
||||
return p, err
|
||||
}
|
||||
|
||||
// tcpMsgLen is a helper func to read first two bytes of stream as uint16 packet length.
|
||||
func tcpMsgLen(t io.Reader) (int, error) {
|
||||
p := []byte{0, 0}
|
||||
n, err := t.Read(p)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if n != 2 {
|
||||
return 0, ErrShortRead
|
||||
}
|
||||
l, _ := unpackUint16(p, 0)
|
||||
if l == 0 {
|
||||
return 0, ErrShortRead
|
||||
}
|
||||
return int(l), nil
|
||||
}
|
||||
|
||||
// tcpRead calls TCPConn.Read enough times to fill allocated buffer.
|
||||
func tcpRead(t io.Reader, p []byte) (int, error) {
|
||||
n, err := t.Read(p)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
for n < len(p) {
|
||||
j, err := t.Read(p[n:])
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
n += j
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Read implements the net.Conn read method.
|
||||
func (co *Conn) Read(p []byte) (n int, err error) {
|
||||
if co.Conn == nil {
|
||||
return 0, ErrConnEmpty
|
||||
}
|
||||
if len(p) < 2 {
|
||||
return 0, io.ErrShortBuffer
|
||||
}
|
||||
switch t := co.Conn.(type) {
|
||||
case *net.TCPConn, *tls.Conn:
|
||||
r := t.(io.Reader)
|
||||
|
||||
l, err := tcpMsgLen(r)
|
||||
if err != nil {
|
||||
switch co.Conn.(type) {
|
||||
case *net.TCPConn, *tls.Conn:
|
||||
var length uint16
|
||||
if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if l > len(p) {
|
||||
return int(l), io.ErrShortBuffer
|
||||
if int(length) > len(p) {
|
||||
return 0, io.ErrShortBuffer
|
||||
}
|
||||
return tcpRead(r, p[:l])
|
||||
|
||||
return io.ReadFull(co.Conn, p[:length])
|
||||
}
|
||||
|
||||
// UDP connection
|
||||
n, err = co.Conn.Read(p)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
return n, err
|
||||
return co.Conn.Read(p)
|
||||
}
|
||||
|
||||
// WriteMsg sends a message through the connection co.
|
||||
|
|
@ -362,34 +296,44 @@ func (co *Conn) WriteMsg(m *Msg) (err error) {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
co.t = time.Now()
|
||||
if _, err = co.Write(out); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
_, err = co.Write(out)
|
||||
return err
|
||||
}
|
||||
|
||||
// Write implements the net.Conn Write method.
|
||||
func (co *Conn) Write(p []byte) (n int, err error) {
|
||||
switch t := co.Conn.(type) {
|
||||
switch co.Conn.(type) {
|
||||
case *net.TCPConn, *tls.Conn:
|
||||
w := t.(io.Writer)
|
||||
|
||||
lp := len(p)
|
||||
if lp < 2 {
|
||||
return 0, io.ErrShortBuffer
|
||||
}
|
||||
if lp > MaxMsgSize {
|
||||
if len(p) > MaxMsgSize {
|
||||
return 0, &Error{err: "message too large"}
|
||||
}
|
||||
l := make([]byte, 2, lp+2)
|
||||
l[0], l[1] = packUint16(uint16(lp))
|
||||
p = append(l, p...)
|
||||
n, err := io.Copy(w, bytes.NewReader(p))
|
||||
|
||||
l := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(l, uint16(len(p)))
|
||||
|
||||
n, err := (&net.Buffers{l, p}).WriteTo(co.Conn)
|
||||
return int(n), err
|
||||
}
|
||||
n, err = co.Conn.(*net.UDPConn).Write(p)
|
||||
return n, err
|
||||
|
||||
return co.Conn.Write(p)
|
||||
}
|
||||
|
||||
// Return the appropriate timeout for a specific request
|
||||
func (c *Client) getTimeoutForRequest(timeout time.Duration) time.Duration {
|
||||
var requestTimeout time.Duration
|
||||
if c.Timeout != 0 {
|
||||
requestTimeout = c.Timeout
|
||||
} else {
|
||||
requestTimeout = timeout
|
||||
}
|
||||
// net.Dialer.Timeout has priority if smaller than the timeouts computed so
|
||||
// far
|
||||
if c.Dialer != nil && c.Dialer.Timeout != 0 {
|
||||
if c.Dialer.Timeout < requestTimeout {
|
||||
requestTimeout = c.Dialer.Timeout
|
||||
}
|
||||
}
|
||||
return requestTimeout
|
||||
}
|
||||
|
||||
// Dial connects to the address on the named network.
|
||||
|
|
@ -402,35 +346,76 @@ func Dial(network, address string) (conn *Conn, err error) {
|
|||
return conn, nil
|
||||
}
|
||||
|
||||
// DialTimeout acts like Dial but takes a timeout.
|
||||
func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
|
||||
conn = new(Conn)
|
||||
conn.Conn, err = net.DialTimeout(network, address, timeout)
|
||||
if err != nil {
|
||||
// ExchangeContext performs a synchronous UDP query, like Exchange. It
|
||||
// additionally obeys deadlines from the passed Context.
|
||||
func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error) {
|
||||
client := Client{Net: "udp"}
|
||||
r, _, err = client.ExchangeContext(ctx, m, a)
|
||||
// ignorint rtt to leave the original ExchangeContext API unchanged, but
|
||||
// this function will go away
|
||||
return r, err
|
||||
}
|
||||
|
||||
// ExchangeConn performs a synchronous query. It sends the message m via the connection
|
||||
// c and waits for a reply. The connection c is not closed by ExchangeConn.
|
||||
// Deprecated: This function is going away, but can easily be mimicked:
|
||||
//
|
||||
// co := &dns.Conn{Conn: c} // c is your net.Conn
|
||||
// co.WriteMsg(m)
|
||||
// in, _ := co.ReadMsg()
|
||||
// co.Close()
|
||||
//
|
||||
func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
|
||||
println("dns: ExchangeConn: this function is deprecated")
|
||||
co := new(Conn)
|
||||
co.Conn = c
|
||||
if err = co.WriteMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return conn, nil
|
||||
r, err = co.ReadMsg()
|
||||
if err == nil && r.Id != m.Id {
|
||||
err = ErrId
|
||||
}
|
||||
return r, err
|
||||
}
|
||||
|
||||
// DialTimeout acts like Dial but takes a timeout.
|
||||
func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
|
||||
client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}}
|
||||
return client.Dial(address)
|
||||
}
|
||||
|
||||
// DialWithTLS connects to the address on the named network with TLS.
|
||||
func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, err error) {
|
||||
conn = new(Conn)
|
||||
conn.Conn, err = tls.Dial(network, address, tlsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if !strings.HasSuffix(network, "-tls") {
|
||||
network += "-tls"
|
||||
}
|
||||
return conn, nil
|
||||
client := Client{Net: network, TLSConfig: tlsConfig}
|
||||
return client.Dial(address)
|
||||
}
|
||||
|
||||
// DialTimeoutWithTLS acts like DialWithTLS but takes a timeout.
|
||||
func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout time.Duration) (conn *Conn, err error) {
|
||||
var dialer net.Dialer
|
||||
dialer.Timeout = timeout
|
||||
|
||||
conn = new(Conn)
|
||||
conn.Conn, err = tls.DialWithDialer(&dialer, network, address, tlsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if !strings.HasSuffix(network, "-tls") {
|
||||
network += "-tls"
|
||||
}
|
||||
return conn, nil
|
||||
client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}, TLSConfig: tlsConfig}
|
||||
return client.Dial(address)
|
||||
}
|
||||
|
||||
// ExchangeContext acts like Exchange, but honors the deadline on the provided
|
||||
// context, if present. If there is both a context deadline and a configured
|
||||
// timeout on the client, the earliest of the two takes effect.
|
||||
func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
||||
var timeout time.Duration
|
||||
if deadline, ok := ctx.Deadline(); !ok {
|
||||
timeout = 0
|
||||
} else {
|
||||
timeout = time.Until(deadline)
|
||||
}
|
||||
// not passing the context to the underlying calls, as the API does not support
|
||||
// context. For timeouts you should set up Client.Dialer and call Client.Exchange.
|
||||
// TODO(tmthrgd,miekg): this is a race condition.
|
||||
c.Dialer = &net.Dialer{Timeout: timeout}
|
||||
return c.Exchange(m, a)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package dns
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -25,8 +26,13 @@ func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
|
|||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
return ClientConfigFromReader(file)
|
||||
}
|
||||
|
||||
// ClientConfigFromReader works like ClientConfigFromFile but takes an io.Reader as argument
|
||||
func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error) {
|
||||
c := new(ClientConfig)
|
||||
scanner := bufio.NewScanner(file)
|
||||
scanner := bufio.NewScanner(resolvconf)
|
||||
c.Servers = make([]string, 0)
|
||||
c.Search = make([]string, 0)
|
||||
c.Port = "53"
|
||||
|
|
@ -62,19 +68,17 @@ func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
|
|||
}
|
||||
|
||||
case "search": // set search path to given servers
|
||||
c.Search = make([]string, len(f)-1)
|
||||
for i := 0; i < len(c.Search); i++ {
|
||||
c.Search[i] = f[i+1]
|
||||
}
|
||||
c.Search = append([]string(nil), f[1:]...)
|
||||
|
||||
case "options": // magic options
|
||||
for i := 1; i < len(f); i++ {
|
||||
s := f[i]
|
||||
for _, s := range f[1:] {
|
||||
switch {
|
||||
case len(s) >= 6 && s[:6] == "ndots:":
|
||||
n, _ := strconv.Atoi(s[6:])
|
||||
if n < 1 {
|
||||
n = 1
|
||||
if n < 0 {
|
||||
n = 0
|
||||
} else if n > 15 {
|
||||
n = 15
|
||||
}
|
||||
c.Ndots = n
|
||||
case len(s) >= 8 && s[:8] == "timeout:":
|
||||
|
|
@ -83,7 +87,7 @@ func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
|
|||
n = 1
|
||||
}
|
||||
c.Timeout = n
|
||||
case len(s) >= 8 && s[:9] == "attempts:":
|
||||
case len(s) >= 9 && s[:9] == "attempts:":
|
||||
n, _ := strconv.Atoi(s[9:])
|
||||
if n < 1 {
|
||||
n = 1
|
||||
|
|
@ -97,3 +101,35 @@ func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) {
|
|||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// NameList returns all of the names that should be queried based on the
|
||||
// config. It is based off of go's net/dns name building, but it does not
|
||||
// check the length of the resulting names.
|
||||
func (c *ClientConfig) NameList(name string) []string {
|
||||
// if this domain is already fully qualified, no append needed.
|
||||
if IsFqdn(name) {
|
||||
return []string{name}
|
||||
}
|
||||
|
||||
// Check to see if the name has more labels than Ndots. Do this before making
|
||||
// the domain fully qualified.
|
||||
hasNdots := CountLabel(name) > c.Ndots
|
||||
// Make the domain fully qualified.
|
||||
name = Fqdn(name)
|
||||
|
||||
// Make a list of names based off search.
|
||||
names := []string{}
|
||||
|
||||
// If name has enough dots, try that first.
|
||||
if hasNdots {
|
||||
names = append(names, name)
|
||||
}
|
||||
for _, s := range c.Search {
|
||||
names = append(names, Fqdn(name+s))
|
||||
}
|
||||
// If we didn't have enough dots, try after suffixes.
|
||||
if !hasNdots {
|
||||
names = append(names, name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// CertificateToDANE converts a certificate to a hex string as used in the TLSA or SMIMEA records.
|
||||
func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) (string, error) {
|
||||
switch matchingType {
|
||||
case 0:
|
||||
switch selector {
|
||||
case 0:
|
||||
return hex.EncodeToString(cert.Raw), nil
|
||||
case 1:
|
||||
return hex.EncodeToString(cert.RawSubjectPublicKeyInfo), nil
|
||||
}
|
||||
case 1:
|
||||
h := sha256.New()
|
||||
switch selector {
|
||||
case 0:
|
||||
h.Write(cert.Raw)
|
||||
return hex.EncodeToString(h.Sum(nil)), nil
|
||||
case 1:
|
||||
h.Write(cert.RawSubjectPublicKeyInfo)
|
||||
return hex.EncodeToString(h.Sum(nil)), nil
|
||||
}
|
||||
case 2:
|
||||
h := sha512.New()
|
||||
switch selector {
|
||||
case 0:
|
||||
h.Write(cert.Raw)
|
||||
return hex.EncodeToString(h.Sum(nil)), nil
|
||||
case 1:
|
||||
h.Write(cert.RawSubjectPublicKeyInfo)
|
||||
return hex.EncodeToString(h.Sum(nil)), nil
|
||||
}
|
||||
}
|
||||
return "", errors.New("dns: bad MatchingType or Selector")
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"errors"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const hexDigit = "0123456789abcdef"
|
||||
|
|
@ -13,9 +14,12 @@ const hexDigit = "0123456789abcdef"
|
|||
// SetReply creates a reply message from a request message.
|
||||
func (dns *Msg) SetReply(request *Msg) *Msg {
|
||||
dns.Id = request.Id
|
||||
dns.RecursionDesired = request.RecursionDesired // Copy rd bit
|
||||
dns.Response = true
|
||||
dns.Opcode = OpcodeQuery
|
||||
dns.Opcode = request.Opcode
|
||||
if dns.Opcode == OpcodeQuery {
|
||||
dns.RecursionDesired = request.RecursionDesired // Copy rd bit
|
||||
dns.CheckingDisabled = request.CheckingDisabled // Copy cd bit
|
||||
}
|
||||
dns.Rcode = RcodeSuccess
|
||||
if len(request.Question) > 0 {
|
||||
dns.Question = make([]Question, 1)
|
||||
|
|
@ -102,11 +106,11 @@ func (dns *Msg) SetAxfr(z string) *Msg {
|
|||
// SetTsig appends a TSIG RR to the message.
|
||||
// This is only a skeleton TSIG RR that is added as the last RR in the
|
||||
// additional section. The Tsig is calculated when the message is being send.
|
||||
func (dns *Msg) SetTsig(z, algo string, fudge, timesigned int64) *Msg {
|
||||
func (dns *Msg) SetTsig(z, algo string, fudge uint16, timesigned int64) *Msg {
|
||||
t := new(TSIG)
|
||||
t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0}
|
||||
t.Algorithm = algo
|
||||
t.Fudge = 300
|
||||
t.Fudge = fudge
|
||||
t.TimeSigned = uint64(timesigned)
|
||||
t.OrigId = dns.Id
|
||||
dns.Extra = append(dns.Extra, t)
|
||||
|
|
@ -142,10 +146,9 @@ func (dns *Msg) IsTsig() *TSIG {
|
|||
// record in the additional section will do. It returns the OPT record
|
||||
// found or nil.
|
||||
func (dns *Msg) IsEdns0() *OPT {
|
||||
// EDNS0 is at the end of the additional section, start there.
|
||||
// We might want to change this to *only* look at the last two
|
||||
// records. So we see TSIG and/or OPT - this a slightly bigger
|
||||
// change though.
|
||||
// RFC 6891, Section 6.1.1 allows the OPT record to appear
|
||||
// anywhere in the additional record section, but it's usually at
|
||||
// the end so start there.
|
||||
for i := len(dns.Extra) - 1; i >= 0; i-- {
|
||||
if dns.Extra[i].Header().Rrtype == TypeOPT {
|
||||
return dns.Extra[i].(*OPT)
|
||||
|
|
@ -154,17 +157,93 @@ func (dns *Msg) IsEdns0() *OPT {
|
|||
return nil
|
||||
}
|
||||
|
||||
// popEdns0 is like IsEdns0, but it removes the record from the message.
|
||||
func (dns *Msg) popEdns0() *OPT {
|
||||
// RFC 6891, Section 6.1.1 allows the OPT record to appear
|
||||
// anywhere in the additional record section, but it's usually at
|
||||
// the end so start there.
|
||||
for i := len(dns.Extra) - 1; i >= 0; i-- {
|
||||
if dns.Extra[i].Header().Rrtype == TypeOPT {
|
||||
opt := dns.Extra[i].(*OPT)
|
||||
dns.Extra = append(dns.Extra[:i], dns.Extra[i+1:]...)
|
||||
return opt
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsDomainName checks if s is a valid domain name, it returns the number of
|
||||
// labels and true, when a domain name is valid. Note that non fully qualified
|
||||
// domain name is considered valid, in this case the last label is counted in
|
||||
// the number of labels. When false is returned the number of labels is not
|
||||
// defined. Also note that this function is extremely liberal; almost any
|
||||
// string is a valid domain name as the DNS is 8 bit protocol. It checks if each
|
||||
// label fits in 63 characters, but there is no length check for the entire
|
||||
// string s. I.e. a domain name longer than 255 characters is considered valid.
|
||||
// label fits in 63 characters and that the entire name will fit into the 255
|
||||
// octet wire format limit.
|
||||
func IsDomainName(s string) (labels int, ok bool) {
|
||||
_, labels, err := packDomainName(s, nil, 0, nil, false)
|
||||
return labels, err == nil
|
||||
// XXX: The logic in this function was copied from packDomainName and
|
||||
// should be kept in sync with that function.
|
||||
|
||||
const lenmsg = 256
|
||||
|
||||
if len(s) == 0 { // Ok, for instance when dealing with update RR without any rdata.
|
||||
return 0, false
|
||||
}
|
||||
|
||||
s = Fqdn(s)
|
||||
|
||||
// Each dot ends a segment of the name. Except for escaped dots (\.), which
|
||||
// are normal dots.
|
||||
|
||||
var (
|
||||
off int
|
||||
begin int
|
||||
wasDot bool
|
||||
)
|
||||
for i := 0; i < len(s); i++ {
|
||||
switch s[i] {
|
||||
case '\\':
|
||||
if off+1 > lenmsg {
|
||||
return labels, false
|
||||
}
|
||||
|
||||
// check for \DDD
|
||||
if i+3 < len(s) && isDigit(s[i+1]) && isDigit(s[i+2]) && isDigit(s[i+3]) {
|
||||
i += 3
|
||||
begin += 3
|
||||
} else {
|
||||
i++
|
||||
begin++
|
||||
}
|
||||
|
||||
wasDot = false
|
||||
case '.':
|
||||
if wasDot {
|
||||
// two dots back to back is not legal
|
||||
return labels, false
|
||||
}
|
||||
wasDot = true
|
||||
|
||||
labelLen := i - begin
|
||||
if labelLen >= 1<<6 { // top two bits of length must be clear
|
||||
return labels, false
|
||||
}
|
||||
|
||||
// off can already (we're in a loop) be bigger than lenmsg
|
||||
// this happens when a name isn't fully qualified
|
||||
off += 1 + labelLen
|
||||
if off > lenmsg {
|
||||
return labels, false
|
||||
}
|
||||
|
||||
labels++
|
||||
begin = i + 1
|
||||
default:
|
||||
wasDot = false
|
||||
}
|
||||
}
|
||||
|
||||
return labels, true
|
||||
}
|
||||
|
||||
// IsSubDomain checks if child is indeed a child of the parent. If child and parent
|
||||
|
|
@ -178,7 +257,7 @@ func IsSubDomain(parent, child string) bool {
|
|||
// The checking is performed on the binary payload.
|
||||
func IsMsg(buf []byte) error {
|
||||
// Header
|
||||
if len(buf) < 12 {
|
||||
if len(buf) < headerSize {
|
||||
return errors.New("dns: bad message header")
|
||||
}
|
||||
// Header: Opcode
|
||||
|
|
@ -188,11 +267,18 @@ func IsMsg(buf []byte) error {
|
|||
|
||||
// IsFqdn checks if a domain name is fully qualified.
|
||||
func IsFqdn(s string) bool {
|
||||
l := len(s)
|
||||
if l == 0 {
|
||||
s2 := strings.TrimSuffix(s, ".")
|
||||
if s == s2 {
|
||||
return false
|
||||
}
|
||||
return s[l-1] == '.'
|
||||
|
||||
i := strings.LastIndexFunc(s2, func(r rune) bool {
|
||||
return r != '\\'
|
||||
})
|
||||
|
||||
// Test whether we have an even number of escape sequences before
|
||||
// the dot or none.
|
||||
return (len(s2)-i)%2 != 0
|
||||
}
|
||||
|
||||
// IsRRset checks if a set of RRs is a valid RRset as defined by RFC 2181.
|
||||
|
|
@ -241,12 +327,19 @@ func ReverseAddr(addr string) (arpa string, err error) {
|
|||
if ip == nil {
|
||||
return "", &Error{err: "unrecognized address: " + addr}
|
||||
}
|
||||
if ip.To4() != nil {
|
||||
return strconv.Itoa(int(ip[15])) + "." + strconv.Itoa(int(ip[14])) + "." + strconv.Itoa(int(ip[13])) + "." +
|
||||
strconv.Itoa(int(ip[12])) + ".in-addr.arpa.", nil
|
||||
if v4 := ip.To4(); v4 != nil {
|
||||
buf := make([]byte, 0, net.IPv4len*4+len("in-addr.arpa."))
|
||||
// Add it, in reverse, to the buffer
|
||||
for i := len(v4) - 1; i >= 0; i-- {
|
||||
buf = strconv.AppendInt(buf, int64(v4[i]), 10)
|
||||
buf = append(buf, '.')
|
||||
}
|
||||
// Append "in-addr.arpa." and return (buf already has the final .)
|
||||
buf = append(buf, "in-addr.arpa."...)
|
||||
return string(buf), nil
|
||||
}
|
||||
// Must be IPv6
|
||||
buf := make([]byte, 0, len(ip)*4+len("ip6.arpa."))
|
||||
buf := make([]byte, 0, net.IPv6len*4+len("ip6.arpa."))
|
||||
// Add it, in reverse, to the buffer
|
||||
for i := len(ip) - 1; i >= 0; i-- {
|
||||
v := ip[i]
|
||||
|
|
@ -270,8 +363,11 @@ func (t Type) String() string {
|
|||
|
||||
// String returns the string representation for the class c.
|
||||
func (c Class) String() string {
|
||||
if c1, ok := ClassToString[uint16(c)]; ok {
|
||||
return c1
|
||||
if s, ok := ClassToString[uint16(c)]; ok {
|
||||
// Only emit mnemonics when they are unambiguous, specically ANY is in both.
|
||||
if _, ok := StringToType[s]; !ok {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return "CLASS" + strconv.Itoa(int(c))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,17 +3,18 @@ package dns
|
|||
import "strconv"
|
||||
|
||||
const (
|
||||
year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits.
|
||||
year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits.
|
||||
defaultTtl = 3600 // Default internal TTL.
|
||||
|
||||
// DefaultMsgSize is the standard default for messages larger than 512 bytes.
|
||||
DefaultMsgSize = 4096
|
||||
// MinMsgSize is the minimal size of a DNS packet.
|
||||
MinMsgSize = 512
|
||||
// MaxMsgSize is the largest possible DNS packet.
|
||||
MaxMsgSize = 65535
|
||||
defaultTtl = 3600 // Default internal TTL.
|
||||
)
|
||||
|
||||
// Error represents a DNS error
|
||||
// Error represents a DNS error.
|
||||
type Error struct{ err string }
|
||||
|
||||
func (e *Error) Error() string {
|
||||
|
|
@ -30,10 +31,33 @@ type RR interface {
|
|||
Header() *RR_Header
|
||||
// String returns the text representation of the resource record.
|
||||
String() string
|
||||
|
||||
// copy returns a copy of the RR
|
||||
copy() RR
|
||||
// len returns the length (in octets) of the uncompressed RR in wire format.
|
||||
len() int
|
||||
|
||||
// len returns the length (in octets) of the compressed or uncompressed RR in wire format.
|
||||
//
|
||||
// If compression is nil, the uncompressed size will be returned, otherwise the compressed
|
||||
// size will be returned and domain names will be added to the map for future compression.
|
||||
len(off int, compression map[string]struct{}) int
|
||||
|
||||
// pack packs the records RDATA into wire format. The header will
|
||||
// already have been packed into msg.
|
||||
pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error)
|
||||
|
||||
// unpack unpacks an RR from wire format.
|
||||
//
|
||||
// This will only be called on a new and empty RR type with only the header populated. It
|
||||
// will only be called if the record's RDATA is non-empty.
|
||||
unpack(msg []byte, off int) (off1 int, err error)
|
||||
|
||||
// parse parses an RR from zone file format.
|
||||
//
|
||||
// This will only be called on a new and empty RR type with only the header populated.
|
||||
parse(c *zlexer, origin, file string) *ParseError
|
||||
|
||||
// isDuplicate returns whether the two RRs are duplicates.
|
||||
isDuplicate(r2 RR) bool
|
||||
}
|
||||
|
||||
// RR_Header is the header all DNS resource records share.
|
||||
|
|
@ -42,25 +66,15 @@ type RR_Header struct {
|
|||
Rrtype uint16
|
||||
Class uint16
|
||||
Ttl uint32
|
||||
Rdlength uint16 // length of data after header
|
||||
Rdlength uint16 // Length of data after header.
|
||||
}
|
||||
|
||||
// Header returns itself. This is here to make RR_Header implement the RR interface.
|
||||
// Header returns itself. This is here to make RR_Header implements the RR interface.
|
||||
func (h *RR_Header) Header() *RR_Header { return h }
|
||||
|
||||
// Just to imlement the RR interface.
|
||||
// Just to implement the RR interface.
|
||||
func (h *RR_Header) copy() RR { return nil }
|
||||
|
||||
func (h *RR_Header) copyHeader() *RR_Header {
|
||||
r := new(RR_Header)
|
||||
r.Name = h.Name
|
||||
r.Rrtype = h.Rrtype
|
||||
r.Class = h.Class
|
||||
r.Ttl = h.Ttl
|
||||
r.Rdlength = h.Rdlength
|
||||
return r
|
||||
}
|
||||
|
||||
func (h *RR_Header) String() string {
|
||||
var s string
|
||||
|
||||
|
|
@ -76,25 +90,45 @@ func (h *RR_Header) String() string {
|
|||
return s
|
||||
}
|
||||
|
||||
func (h *RR_Header) len() int {
|
||||
l := len(h.Name) + 1
|
||||
func (h *RR_Header) len(off int, compression map[string]struct{}) int {
|
||||
l := domainNameLen(h.Name, off, compression, true)
|
||||
l += 10 // rrtype(2) + class(2) + ttl(4) + rdlength(2)
|
||||
return l
|
||||
}
|
||||
|
||||
// ToRFC3597 converts a known RR to the unknown RR representation
|
||||
// from RFC 3597.
|
||||
func (h *RR_Header) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
|
||||
// RR_Header has no RDATA to pack.
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func (h *RR_Header) unpack(msg []byte, off int) (int, error) {
|
||||
panic("dns: internal error: unpack should never be called on RR_Header")
|
||||
}
|
||||
|
||||
func (h *RR_Header) parse(c *zlexer, origin, file string) *ParseError {
|
||||
panic("dns: internal error: parse should never be called on RR_Header")
|
||||
}
|
||||
|
||||
// ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597.
|
||||
func (rr *RFC3597) ToRFC3597(r RR) error {
|
||||
buf := make([]byte, r.len()*2)
|
||||
off, err := PackStruct(r, buf, 0)
|
||||
buf := make([]byte, Len(r)*2)
|
||||
headerEnd, off, err := packRR(r, buf, 0, compressionMap{}, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf = buf[:off]
|
||||
rawSetRdlength(buf, 0, off)
|
||||
_, err = UnpackStruct(rr, buf, 0)
|
||||
|
||||
*rr = RFC3597{Hdr: *r.Header()}
|
||||
rr.Hdr.Rdlength = uint16(off - headerEnd)
|
||||
|
||||
if noRdata(rr.Hdr) {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = rr.unpack(buf, headerEnd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,11 +13,14 @@ import (
|
|||
_ "crypto/sha256"
|
||||
_ "crypto/sha512"
|
||||
"encoding/asn1"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
// DNSSEC encryption algorithm codes.
|
||||
|
|
@ -37,12 +40,14 @@ const (
|
|||
ECCGOST
|
||||
ECDSAP256SHA256
|
||||
ECDSAP384SHA384
|
||||
ED25519
|
||||
ED448
|
||||
INDIRECT uint8 = 252
|
||||
PRIVATEDNS uint8 = 253 // Private (experimental keys)
|
||||
PRIVATEOID uint8 = 254
|
||||
)
|
||||
|
||||
// Map for algorithm names.
|
||||
// AlgorithmToString is a map of algorithm IDs to algorithm names.
|
||||
var AlgorithmToString = map[uint8]string{
|
||||
RSAMD5: "RSAMD5",
|
||||
DH: "DH",
|
||||
|
|
@ -55,23 +60,24 @@ var AlgorithmToString = map[uint8]string{
|
|||
ECCGOST: "ECC-GOST",
|
||||
ECDSAP256SHA256: "ECDSAP256SHA256",
|
||||
ECDSAP384SHA384: "ECDSAP384SHA384",
|
||||
ED25519: "ED25519",
|
||||
ED448: "ED448",
|
||||
INDIRECT: "INDIRECT",
|
||||
PRIVATEDNS: "PRIVATEDNS",
|
||||
PRIVATEOID: "PRIVATEOID",
|
||||
}
|
||||
|
||||
// Map of algorithm strings.
|
||||
var StringToAlgorithm = reverseInt8(AlgorithmToString)
|
||||
|
||||
// Map of algorithm crypto hashes.
|
||||
// AlgorithmToHash is a map of algorithm crypto hash IDs to crypto.Hash's.
|
||||
var AlgorithmToHash = map[uint8]crypto.Hash{
|
||||
RSAMD5: crypto.MD5, // Deprecated in RFC 6725
|
||||
DSA: crypto.SHA1,
|
||||
RSASHA1: crypto.SHA1,
|
||||
RSASHA1NSEC3SHA1: crypto.SHA1,
|
||||
RSASHA256: crypto.SHA256,
|
||||
ECDSAP256SHA256: crypto.SHA256,
|
||||
ECDSAP384SHA384: crypto.SHA384,
|
||||
RSASHA512: crypto.SHA512,
|
||||
ED25519: crypto.Hash(0),
|
||||
}
|
||||
|
||||
// DNSSEC hashing algorithm codes.
|
||||
|
|
@ -84,7 +90,7 @@ const (
|
|||
SHA512 // Experimental
|
||||
)
|
||||
|
||||
// Map for hash names.
|
||||
// HashToString is a map of hash IDs to names.
|
||||
var HashToString = map[uint8]string{
|
||||
SHA1: "SHA1",
|
||||
SHA256: "SHA256",
|
||||
|
|
@ -93,9 +99,6 @@ var HashToString = map[uint8]string{
|
|||
SHA512: "SHA512",
|
||||
}
|
||||
|
||||
// Map of hash strings.
|
||||
var StringToHash = reverseInt8(HashToString)
|
||||
|
||||
// DNSKEY flag values.
|
||||
const (
|
||||
SEP = 1
|
||||
|
|
@ -103,9 +106,7 @@ const (
|
|||
ZONE = 1 << 8
|
||||
)
|
||||
|
||||
// The RRSIG needs to be converted to wireformat with some of
|
||||
// the rdata (the signature) missing. Use this struct to ease
|
||||
// the conversion (and re-use the pack/unpack functions).
|
||||
// The RRSIG needs to be converted to wireformat with some of the rdata (the signature) missing.
|
||||
type rrsigWireFmt struct {
|
||||
TypeCovered uint16
|
||||
Algorithm uint8
|
||||
|
|
@ -144,7 +145,7 @@ func (k *DNSKEY) KeyTag() uint16 {
|
|||
// at the base64 values. But I'm lazy.
|
||||
modulus, _ := fromBase64([]byte(k.PublicKey))
|
||||
if len(modulus) > 1 {
|
||||
x, _ := unpackUint16(modulus, len(modulus)-2)
|
||||
x := binary.BigEndian.Uint16(modulus[len(modulus)-2:])
|
||||
keytag = int(x)
|
||||
}
|
||||
default:
|
||||
|
|
@ -154,7 +155,7 @@ func (k *DNSKEY) KeyTag() uint16 {
|
|||
keywire.Algorithm = k.Algorithm
|
||||
keywire.PublicKey = k.PublicKey
|
||||
wire := make([]byte, DefaultMsgSize)
|
||||
n, err := PackStruct(keywire, wire, 0)
|
||||
n, err := packKeyWire(keywire, wire)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
|
@ -166,7 +167,7 @@ func (k *DNSKEY) KeyTag() uint16 {
|
|||
keytag += int(v) << 8
|
||||
}
|
||||
}
|
||||
keytag += (keytag >> 16) & 0xFFFF
|
||||
keytag += keytag >> 16 & 0xFFFF
|
||||
keytag &= 0xFFFF
|
||||
}
|
||||
return uint16(keytag)
|
||||
|
|
@ -192,7 +193,7 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
|
|||
keywire.Algorithm = k.Algorithm
|
||||
keywire.PublicKey = k.PublicKey
|
||||
wire := make([]byte, DefaultMsgSize)
|
||||
n, err := PackStruct(keywire, wire, 0)
|
||||
n, err := packKeyWire(keywire, wire)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -209,9 +210,6 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
|
|||
// "|" denotes concatenation
|
||||
// DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key.
|
||||
|
||||
// digest buffer
|
||||
digest := append(owner, wire...) // another copy
|
||||
|
||||
var hash crypto.Hash
|
||||
switch h {
|
||||
case SHA1:
|
||||
|
|
@ -227,7 +225,8 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
|
|||
}
|
||||
|
||||
s := hash.New()
|
||||
s.Write(digest)
|
||||
s.Write(owner)
|
||||
s.Write(wire)
|
||||
ds.Digest = hex.EncodeToString(s.Sum(nil))
|
||||
return ds
|
||||
}
|
||||
|
|
@ -235,7 +234,7 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
|
|||
// ToCDNSKEY converts a DNSKEY record to a CDNSKEY record.
|
||||
func (k *DNSKEY) ToCDNSKEY() *CDNSKEY {
|
||||
c := &CDNSKEY{DNSKEY: *k}
|
||||
c.Hdr = *k.Hdr.copyHeader()
|
||||
c.Hdr = k.Hdr
|
||||
c.Hdr.Rrtype = TypeCDNSKEY
|
||||
return c
|
||||
}
|
||||
|
|
@ -243,7 +242,7 @@ func (k *DNSKEY) ToCDNSKEY() *CDNSKEY {
|
|||
// ToCDS converts a DS record to a CDS record.
|
||||
func (d *DS) ToCDS() *CDS {
|
||||
c := &CDS{DS: *d}
|
||||
c.Hdr = *d.Hdr.copyHeader()
|
||||
c.Hdr = d.Hdr
|
||||
c.Hdr.Rrtype = TypeCDS
|
||||
return c
|
||||
}
|
||||
|
|
@ -263,16 +262,17 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
|
|||
return ErrKey
|
||||
}
|
||||
|
||||
h0 := rrset[0].Header()
|
||||
rr.Hdr.Rrtype = TypeRRSIG
|
||||
rr.Hdr.Name = rrset[0].Header().Name
|
||||
rr.Hdr.Class = rrset[0].Header().Class
|
||||
rr.Hdr.Name = h0.Name
|
||||
rr.Hdr.Class = h0.Class
|
||||
if rr.OrigTtl == 0 { // If set don't override
|
||||
rr.OrigTtl = rrset[0].Header().Ttl
|
||||
rr.OrigTtl = h0.Ttl
|
||||
}
|
||||
rr.TypeCovered = rrset[0].Header().Rrtype
|
||||
rr.Labels = uint8(CountLabel(rrset[0].Header().Name))
|
||||
rr.TypeCovered = h0.Rrtype
|
||||
rr.Labels = uint8(CountLabel(h0.Name))
|
||||
|
||||
if strings.HasPrefix(rrset[0].Header().Name, "*") {
|
||||
if strings.HasPrefix(h0.Name, "*") {
|
||||
rr.Labels-- // wildcard, remove from label count
|
||||
}
|
||||
|
||||
|
|
@ -289,7 +289,7 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
|
|||
|
||||
// Create the desired binary blob
|
||||
signdata := make([]byte, DefaultMsgSize)
|
||||
n, err := PackStruct(sigwire, signdata, 0)
|
||||
n, err := packSigWire(sigwire, signdata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -298,23 +298,39 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
signdata = append(signdata, wire...)
|
||||
|
||||
hash, ok := AlgorithmToHash[rr.Algorithm]
|
||||
if !ok {
|
||||
return ErrAlg
|
||||
}
|
||||
|
||||
h := hash.New()
|
||||
h.Write(signdata)
|
||||
switch rr.Algorithm {
|
||||
case ED25519:
|
||||
// ed25519 signs the raw message and performs hashing internally.
|
||||
// All other supported signature schemes operate over the pre-hashed
|
||||
// message, and thus ed25519 must be handled separately here.
|
||||
//
|
||||
// The raw message is passed directly into sign and crypto.Hash(0) is
|
||||
// used to signal to the crypto.Signer that the data has not been hashed.
|
||||
signature, err := sign(k, append(signdata, wire...), crypto.Hash(0), rr.Algorithm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
|
||||
if err != nil {
|
||||
return err
|
||||
rr.Signature = toBase64(signature)
|
||||
default:
|
||||
h := hash.New()
|
||||
h.Write(signdata)
|
||||
h.Write(wire)
|
||||
|
||||
signature, err := sign(k, h.Sum(nil), hash, rr.Algorithm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rr.Signature = toBase64(signature)
|
||||
}
|
||||
|
||||
rr.Signature = toBase64(signature)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -355,6 +371,9 @@ func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte,
|
|||
// signature = append(signature, intToBytes(r1, 20)...)
|
||||
// signature = append(signature, intToBytes(s1, 20)...)
|
||||
// rr.Signature = signature
|
||||
|
||||
case ED25519:
|
||||
return signature, nil
|
||||
}
|
||||
|
||||
return nil, ErrAlg
|
||||
|
|
@ -377,7 +396,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
|||
if rr.Algorithm != k.Algorithm {
|
||||
return ErrKey
|
||||
}
|
||||
if strings.ToLower(rr.SignerName) != strings.ToLower(k.Hdr.Name) {
|
||||
if !strings.EqualFold(rr.SignerName, k.Hdr.Name) {
|
||||
return ErrKey
|
||||
}
|
||||
if k.Protocol != 3 {
|
||||
|
|
@ -387,10 +406,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
|||
// IsRRset checked that we have at least one RR and that the RRs in
|
||||
// the set have consistent type, class, and name. Also check that type and
|
||||
// class matches the RRSIG record.
|
||||
if rrset[0].Header().Class != rr.Hdr.Class {
|
||||
return ErrRRset
|
||||
}
|
||||
if rrset[0].Header().Rrtype != rr.TypeCovered {
|
||||
if h0 := rrset[0].Header(); h0.Class != rr.Hdr.Class || h0.Rrtype != rr.TypeCovered {
|
||||
return ErrRRset
|
||||
}
|
||||
|
||||
|
|
@ -407,7 +423,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
|||
sigwire.SignerName = strings.ToLower(rr.SignerName)
|
||||
// Create the desired binary blob
|
||||
signeddata := make([]byte, DefaultMsgSize)
|
||||
n, err := PackStruct(sigwire, signeddata, 0)
|
||||
n, err := packSigWire(sigwire, signeddata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -416,7 +432,6 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
signeddata = append(signeddata, wire...)
|
||||
|
||||
sigbuf := rr.sigBuf() // Get the binary signature data
|
||||
if rr.Algorithm == PRIVATEDNS { // PRIVATEOID
|
||||
|
|
@ -439,6 +454,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
|||
|
||||
h := hash.New()
|
||||
h.Write(signeddata)
|
||||
h.Write(wire)
|
||||
return rsa.VerifyPKCS1v15(pubkey, hash, h.Sum(nil), sigbuf)
|
||||
|
||||
case ECDSAP256SHA256, ECDSAP384SHA384:
|
||||
|
|
@ -453,11 +469,23 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
|
|||
|
||||
h := hash.New()
|
||||
h.Write(signeddata)
|
||||
h.Write(wire)
|
||||
if ecdsa.Verify(pubkey, h.Sum(nil), r, s) {
|
||||
return nil
|
||||
}
|
||||
return ErrSig
|
||||
|
||||
case ED25519:
|
||||
pubkey := k.publicKeyED25519()
|
||||
if pubkey == nil {
|
||||
return ErrKey
|
||||
}
|
||||
|
||||
if ed25519.Verify(pubkey, append(signeddata, wire...), sigbuf) {
|
||||
return nil
|
||||
}
|
||||
return ErrSig
|
||||
|
||||
default:
|
||||
return ErrAlg
|
||||
}
|
||||
|
|
@ -476,8 +504,8 @@ func (rr *RRSIG) ValidityPeriod(t time.Time) bool {
|
|||
}
|
||||
modi := (int64(rr.Inception) - utc) / year68
|
||||
mode := (int64(rr.Expiration) - utc) / year68
|
||||
ti := int64(rr.Inception) + (modi * year68)
|
||||
te := int64(rr.Expiration) + (mode * year68)
|
||||
ti := int64(rr.Inception) + modi*year68
|
||||
te := int64(rr.Expiration) + mode*year68
|
||||
return ti <= utc && utc <= te
|
||||
}
|
||||
|
||||
|
|
@ -497,6 +525,11 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
|
|||
return nil
|
||||
}
|
||||
|
||||
if len(keybuf) < 1+1+64 {
|
||||
// Exponent must be at least 1 byte and modulus at least 64
|
||||
return nil
|
||||
}
|
||||
|
||||
// RFC 2537/3110, section 2. RSA Public KEY Resource Records
|
||||
// Length is in the 0th byte, unless its zero, then it
|
||||
// it in bytes 1 and 2 and its a 16 bit number
|
||||
|
|
@ -506,25 +539,35 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
|
|||
explen = uint16(keybuf[1])<<8 | uint16(keybuf[2])
|
||||
keyoff = 3
|
||||
}
|
||||
pubkey := new(rsa.PublicKey)
|
||||
|
||||
pubkey.N = big.NewInt(0)
|
||||
shift := uint64((explen - 1) * 8)
|
||||
expo := uint64(0)
|
||||
for i := int(explen - 1); i > 0; i-- {
|
||||
expo += uint64(keybuf[keyoff+i]) << shift
|
||||
shift -= 8
|
||||
}
|
||||
// Remainder
|
||||
expo += uint64(keybuf[keyoff])
|
||||
if expo > 2<<31 {
|
||||
// Larger expo than supported.
|
||||
// println("dns: F5 primes (or larger) are not supported")
|
||||
if explen > 4 || explen == 0 || keybuf[keyoff] == 0 {
|
||||
// Exponent larger than supported by the crypto package,
|
||||
// empty, or contains prohibited leading zero.
|
||||
return nil
|
||||
}
|
||||
pubkey.E = int(expo)
|
||||
|
||||
pubkey.N.SetBytes(keybuf[keyoff+int(explen):])
|
||||
modoff := keyoff + int(explen)
|
||||
modlen := len(keybuf) - modoff
|
||||
if modlen < 64 || modlen > 512 || keybuf[modoff] == 0 {
|
||||
// Modulus is too small, large, or contains prohibited leading zero.
|
||||
return nil
|
||||
}
|
||||
|
||||
pubkey := new(rsa.PublicKey)
|
||||
|
||||
var expo uint64
|
||||
// The exponent of length explen is between keyoff and modoff.
|
||||
for _, v := range keybuf[keyoff:modoff] {
|
||||
expo <<= 8
|
||||
expo |= uint64(v)
|
||||
}
|
||||
if expo > 1<<31-1 {
|
||||
// Larger exponent than supported by the crypto package.
|
||||
return nil
|
||||
}
|
||||
|
||||
pubkey.E = int(expo)
|
||||
pubkey.N = new(big.Int).SetBytes(keybuf[modoff:])
|
||||
return pubkey
|
||||
}
|
||||
|
||||
|
|
@ -549,10 +592,8 @@ func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
pubkey.X = big.NewInt(0)
|
||||
pubkey.X.SetBytes(keybuf[:len(keybuf)/2])
|
||||
pubkey.Y = big.NewInt(0)
|
||||
pubkey.Y.SetBytes(keybuf[len(keybuf)/2:])
|
||||
pubkey.X = new(big.Int).SetBytes(keybuf[:len(keybuf)/2])
|
||||
pubkey.Y = new(big.Int).SetBytes(keybuf[len(keybuf)/2:])
|
||||
return pubkey
|
||||
}
|
||||
|
||||
|
|
@ -573,13 +614,24 @@ func (k *DNSKEY) publicKeyDSA() *dsa.PublicKey {
|
|||
p, keybuf := keybuf[:size], keybuf[size:]
|
||||
g, y := keybuf[:size], keybuf[size:]
|
||||
pubkey := new(dsa.PublicKey)
|
||||
pubkey.Parameters.Q = big.NewInt(0).SetBytes(q)
|
||||
pubkey.Parameters.P = big.NewInt(0).SetBytes(p)
|
||||
pubkey.Parameters.G = big.NewInt(0).SetBytes(g)
|
||||
pubkey.Y = big.NewInt(0).SetBytes(y)
|
||||
pubkey.Parameters.Q = new(big.Int).SetBytes(q)
|
||||
pubkey.Parameters.P = new(big.Int).SetBytes(p)
|
||||
pubkey.Parameters.G = new(big.Int).SetBytes(g)
|
||||
pubkey.Y = new(big.Int).SetBytes(y)
|
||||
return pubkey
|
||||
}
|
||||
|
||||
func (k *DNSKEY) publicKeyED25519() ed25519.PublicKey {
|
||||
keybuf, err := fromBase64([]byte(k.PublicKey))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if len(keybuf) != ed25519.PublicKeySize {
|
||||
return nil
|
||||
}
|
||||
return keybuf
|
||||
}
|
||||
|
||||
type wireSlice [][]byte
|
||||
|
||||
func (p wireSlice) Len() int { return len(p) }
|
||||
|
|
@ -595,15 +647,16 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
|
|||
wires := make(wireSlice, len(rrset))
|
||||
for i, r := range rrset {
|
||||
r1 := r.copy()
|
||||
r1.Header().Ttl = s.OrigTtl
|
||||
labels := SplitDomainName(r1.Header().Name)
|
||||
h := r1.Header()
|
||||
h.Ttl = s.OrigTtl
|
||||
labels := SplitDomainName(h.Name)
|
||||
// 6.2. Canonical RR Form. (4) - wildcards
|
||||
if len(labels) > int(s.Labels) {
|
||||
// Wildcard
|
||||
r1.Header().Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "."
|
||||
h.Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "."
|
||||
}
|
||||
// RFC 4034: 6.2. Canonical RR Form. (2) - domain name to lowercase
|
||||
r1.Header().Name = strings.ToLower(r1.Header().Name)
|
||||
h.Name = strings.ToLower(h.Name)
|
||||
// 6.2. Canonical RR Form. (3) - domain rdata to lowercase.
|
||||
// NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
|
||||
// HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
|
||||
|
|
@ -617,6 +670,10 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
|
|||
switch x := r1.(type) {
|
||||
case *NS:
|
||||
x.Ns = strings.ToLower(x.Ns)
|
||||
case *MD:
|
||||
x.Md = strings.ToLower(x.Md)
|
||||
case *MF:
|
||||
x.Mf = strings.ToLower(x.Mf)
|
||||
case *CNAME:
|
||||
x.Target = strings.ToLower(x.Target)
|
||||
case *SOA:
|
||||
|
|
@ -635,6 +692,18 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
|
|||
x.Email = strings.ToLower(x.Email)
|
||||
case *MX:
|
||||
x.Mx = strings.ToLower(x.Mx)
|
||||
case *RP:
|
||||
x.Mbox = strings.ToLower(x.Mbox)
|
||||
x.Txt = strings.ToLower(x.Txt)
|
||||
case *AFSDB:
|
||||
x.Hostname = strings.ToLower(x.Hostname)
|
||||
case *RT:
|
||||
x.Host = strings.ToLower(x.Host)
|
||||
case *SIG:
|
||||
x.SignerName = strings.ToLower(x.SignerName)
|
||||
case *PX:
|
||||
x.Map822 = strings.ToLower(x.Map822)
|
||||
x.Mapx400 = strings.ToLower(x.Mapx400)
|
||||
case *NAPTR:
|
||||
x.Replacement = strings.ToLower(x.Replacement)
|
||||
case *KX:
|
||||
|
|
@ -645,7 +714,7 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
|
|||
x.Target = strings.ToLower(x.Target)
|
||||
}
|
||||
// 6.2. Canonical RR Form. (5) - origTTL
|
||||
wire := make([]byte, r1.len()+1) // +1 to be safe(r)
|
||||
wire := make([]byte, Len(r1)+1) // +1 to be safe(r)
|
||||
off, err1 := PackRR(r1, wire, 0, nil, false)
|
||||
if err1 != nil {
|
||||
return nil, err1
|
||||
|
|
@ -662,3 +731,61 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
|
|||
}
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func packSigWire(sw *rrsigWireFmt, msg []byte) (int, error) {
|
||||
// copied from zmsg.go RRSIG packing
|
||||
off, err := packUint16(sw.TypeCovered, msg, 0)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = packUint8(sw.Algorithm, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = packUint8(sw.Labels, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = packUint32(sw.OrigTtl, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = packUint32(sw.Expiration, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = packUint32(sw.Inception, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = packUint16(sw.KeyTag, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = PackDomainName(sw.SignerName, msg, off, nil, false)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func packKeyWire(dw *dnskeyWireFmt, msg []byte) (int, error) {
|
||||
// copied from zmsg.go DNSKEY packing
|
||||
off, err := packUint16(dw.Flags, msg, 0)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = packUint8(dw.Protocol, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = packUint8(dw.Algorithm, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = packStringBase64(dw.PublicKey, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
return off, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import (
|
|||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"math/big"
|
||||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
// Generate generates a DNSKEY of the given bit size.
|
||||
|
|
@ -38,6 +40,10 @@ func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
|
|||
if bits != 384 {
|
||||
return nil, ErrKeySize
|
||||
}
|
||||
case ED25519:
|
||||
if bits != 256 {
|
||||
return nil, ErrKeySize
|
||||
}
|
||||
}
|
||||
|
||||
switch k.Algorithm {
|
||||
|
|
@ -75,6 +81,13 @@ func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) {
|
|||
}
|
||||
k.setPublicKeyECDSA(priv.PublicKey.X, priv.PublicKey.Y)
|
||||
return priv, nil
|
||||
case ED25519:
|
||||
pub, priv, err := ed25519.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
k.setPublicKeyED25519(pub)
|
||||
return priv, nil
|
||||
default:
|
||||
return nil, ErrAlg
|
||||
}
|
||||
|
|
@ -117,21 +130,30 @@ func (k *DNSKEY) setPublicKeyDSA(_Q, _P, _G, _Y *big.Int) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// Set the public key for Ed25519
|
||||
func (k *DNSKEY) setPublicKeyED25519(_K ed25519.PublicKey) bool {
|
||||
if _K == nil {
|
||||
return false
|
||||
}
|
||||
k.PublicKey = toBase64(_K)
|
||||
return true
|
||||
}
|
||||
|
||||
// Set the public key (the values E and N) for RSA
|
||||
// RFC 3110: Section 2. RSA Public KEY Resource Records
|
||||
func exponentToBuf(_E int) []byte {
|
||||
var buf []byte
|
||||
i := big.NewInt(int64(_E))
|
||||
if len(i.Bytes()) < 256 {
|
||||
buf = make([]byte, 1)
|
||||
buf[0] = uint8(len(i.Bytes()))
|
||||
i := big.NewInt(int64(_E)).Bytes()
|
||||
if len(i) < 256 {
|
||||
buf = make([]byte, 1, 1+len(i))
|
||||
buf[0] = uint8(len(i))
|
||||
} else {
|
||||
buf = make([]byte, 3)
|
||||
buf = make([]byte, 3, 3+len(i))
|
||||
buf[0] = 0
|
||||
buf[1] = uint8(len(i.Bytes()) >> 8)
|
||||
buf[2] = uint8(len(i.Bytes()))
|
||||
buf[1] = uint8(len(i) >> 8)
|
||||
buf[2] = uint8(len(i))
|
||||
}
|
||||
buf = append(buf, i.Bytes()...)
|
||||
buf = append(buf, i...)
|
||||
return buf
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto"
|
||||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
|
|
@ -9,12 +10,14 @@ import (
|
|||
"math/big"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
// NewPrivateKey returns a PrivateKey by parsing the string s.
|
||||
// s should be in the same form of the BIND private key files.
|
||||
func (k *DNSKEY) NewPrivateKey(s string) (crypto.PrivateKey, error) {
|
||||
if s[len(s)-1] != '\n' { // We need a closing newline
|
||||
if s == "" || s[len(s)-1] != '\n' { // We need a closing newline
|
||||
return k.ReadPrivateKey(strings.NewReader(s+"\n"), "")
|
||||
}
|
||||
return k.ReadPrivateKey(strings.NewReader(s), "")
|
||||
|
|
@ -25,9 +28,9 @@ func (k *DNSKEY) NewPrivateKey(s string) (crypto.PrivateKey, error) {
|
|||
// The public key must be known, because some cryptographic algorithms embed
|
||||
// the public inside the privatekey.
|
||||
func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, error) {
|
||||
m, e := parseKey(q, file)
|
||||
m, err := parseKey(q, file)
|
||||
if m == nil {
|
||||
return nil, e
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := m["private-key-format"]; !ok {
|
||||
return nil, ErrPrivKey
|
||||
|
|
@ -36,22 +39,22 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
|
|||
return nil, ErrPrivKey
|
||||
}
|
||||
// TODO(mg): check if the pubkey matches the private key
|
||||
algo, err := strconv.Atoi(strings.SplitN(m["algorithm"], " ", 2)[0])
|
||||
algo, err := strconv.ParseUint(strings.SplitN(m["algorithm"], " ", 2)[0], 10, 8)
|
||||
if err != nil {
|
||||
return nil, ErrPrivKey
|
||||
}
|
||||
switch uint8(algo) {
|
||||
case DSA:
|
||||
priv, e := readPrivateKeyDSA(m)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
priv, err := readPrivateKeyDSA(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pub := k.publicKeyDSA()
|
||||
if pub == nil {
|
||||
return nil, ErrKey
|
||||
}
|
||||
priv.PublicKey = *pub
|
||||
return priv, e
|
||||
return priv, nil
|
||||
case RSAMD5:
|
||||
fallthrough
|
||||
case RSASHA1:
|
||||
|
|
@ -61,31 +64,33 @@ func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, er
|
|||
case RSASHA256:
|
||||
fallthrough
|
||||
case RSASHA512:
|
||||
priv, e := readPrivateKeyRSA(m)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
priv, err := readPrivateKeyRSA(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pub := k.publicKeyRSA()
|
||||
if pub == nil {
|
||||
return nil, ErrKey
|
||||
}
|
||||
priv.PublicKey = *pub
|
||||
return priv, e
|
||||
return priv, nil
|
||||
case ECCGOST:
|
||||
return nil, ErrPrivKey
|
||||
case ECDSAP256SHA256:
|
||||
fallthrough
|
||||
case ECDSAP384SHA384:
|
||||
priv, e := readPrivateKeyECDSA(m)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
priv, err := readPrivateKeyECDSA(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pub := k.publicKeyECDSA()
|
||||
if pub == nil {
|
||||
return nil, ErrKey
|
||||
}
|
||||
priv.PublicKey = *pub
|
||||
return priv, e
|
||||
return priv, nil
|
||||
case ED25519:
|
||||
return readPrivateKeyED25519(m)
|
||||
default:
|
||||
return nil, ErrPrivKey
|
||||
}
|
||||
|
|
@ -104,21 +109,16 @@ func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
|
|||
}
|
||||
switch k {
|
||||
case "modulus":
|
||||
p.PublicKey.N = big.NewInt(0)
|
||||
p.PublicKey.N.SetBytes(v1)
|
||||
p.PublicKey.N = new(big.Int).SetBytes(v1)
|
||||
case "publicexponent":
|
||||
i := big.NewInt(0)
|
||||
i.SetBytes(v1)
|
||||
i := new(big.Int).SetBytes(v1)
|
||||
p.PublicKey.E = int(i.Int64()) // int64 should be large enough
|
||||
case "privateexponent":
|
||||
p.D = big.NewInt(0)
|
||||
p.D.SetBytes(v1)
|
||||
p.D = new(big.Int).SetBytes(v1)
|
||||
case "prime1":
|
||||
p.Primes[0] = big.NewInt(0)
|
||||
p.Primes[0].SetBytes(v1)
|
||||
p.Primes[0] = new(big.Int).SetBytes(v1)
|
||||
case "prime2":
|
||||
p.Primes[1] = big.NewInt(0)
|
||||
p.Primes[1].SetBytes(v1)
|
||||
p.Primes[1] = new(big.Int).SetBytes(v1)
|
||||
}
|
||||
case "exponent1", "exponent2", "coefficient":
|
||||
// not used in Go (yet)
|
||||
|
|
@ -131,7 +131,7 @@ func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
|
|||
|
||||
func readPrivateKeyDSA(m map[string]string) (*dsa.PrivateKey, error) {
|
||||
p := new(dsa.PrivateKey)
|
||||
p.X = big.NewInt(0)
|
||||
p.X = new(big.Int)
|
||||
for k, v := range m {
|
||||
switch k {
|
||||
case "private_value(x)":
|
||||
|
|
@ -149,7 +149,7 @@ func readPrivateKeyDSA(m map[string]string) (*dsa.PrivateKey, error) {
|
|||
|
||||
func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) {
|
||||
p := new(ecdsa.PrivateKey)
|
||||
p.D = big.NewInt(0)
|
||||
p.D = new(big.Int)
|
||||
// TODO: validate that the required flags are present
|
||||
for k, v := range m {
|
||||
switch k {
|
||||
|
|
@ -166,16 +166,36 @@ func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) {
|
|||
return p, nil
|
||||
}
|
||||
|
||||
func readPrivateKeyED25519(m map[string]string) (ed25519.PrivateKey, error) {
|
||||
var p ed25519.PrivateKey
|
||||
// TODO: validate that the required flags are present
|
||||
for k, v := range m {
|
||||
switch k {
|
||||
case "privatekey":
|
||||
p1, err := fromBase64([]byte(v))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(p1) != ed25519.SeedSize {
|
||||
return nil, ErrPrivKey
|
||||
}
|
||||
p = ed25519.NewKeyFromSeed(p1)
|
||||
case "created", "publish", "activate":
|
||||
/* not used in Go (yet) */
|
||||
}
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// parseKey reads a private key from r. It returns a map[string]string,
|
||||
// with the key-value pairs, or an error when the file is not correct.
|
||||
func parseKey(r io.Reader, file string) (map[string]string, error) {
|
||||
s := scanInit(r)
|
||||
m := make(map[string]string)
|
||||
c := make(chan lex)
|
||||
k := ""
|
||||
// Start the lexer
|
||||
go klexer(s, c)
|
||||
for l := range c {
|
||||
var k string
|
||||
|
||||
c := newKLexer(r)
|
||||
|
||||
for l, ok := c.Next(); ok; l, ok = c.Next() {
|
||||
// It should alternate
|
||||
switch l.value {
|
||||
case zKey:
|
||||
|
|
@ -184,41 +204,111 @@ func parseKey(r io.Reader, file string) (map[string]string, error) {
|
|||
if k == "" {
|
||||
return nil, &ParseError{file, "no private key seen", l}
|
||||
}
|
||||
//println("Setting", strings.ToLower(k), "to", l.token, "b")
|
||||
|
||||
m[strings.ToLower(k)] = l.token
|
||||
k = ""
|
||||
}
|
||||
}
|
||||
|
||||
// Surface any read errors from r.
|
||||
if err := c.Err(); err != nil {
|
||||
return nil, &ParseError{file: file, err: err.Error()}
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// klexer scans the sourcefile and returns tokens on the channel c.
|
||||
func klexer(s *scan, c chan lex) {
|
||||
var l lex
|
||||
str := "" // Hold the current read text
|
||||
commt := false
|
||||
key := true
|
||||
x, err := s.tokenText()
|
||||
defer close(c)
|
||||
for err == nil {
|
||||
l.column = s.position.Column
|
||||
l.line = s.position.Line
|
||||
type klexer struct {
|
||||
br io.ByteReader
|
||||
|
||||
readErr error
|
||||
|
||||
line int
|
||||
column int
|
||||
|
||||
key bool
|
||||
|
||||
eol bool // end-of-line
|
||||
}
|
||||
|
||||
func newKLexer(r io.Reader) *klexer {
|
||||
br, ok := r.(io.ByteReader)
|
||||
if !ok {
|
||||
br = bufio.NewReaderSize(r, 1024)
|
||||
}
|
||||
|
||||
return &klexer{
|
||||
br: br,
|
||||
|
||||
line: 1,
|
||||
|
||||
key: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (kl *klexer) Err() error {
|
||||
if kl.readErr == io.EOF {
|
||||
return nil
|
||||
}
|
||||
|
||||
return kl.readErr
|
||||
}
|
||||
|
||||
// readByte returns the next byte from the input
|
||||
func (kl *klexer) readByte() (byte, bool) {
|
||||
if kl.readErr != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
c, err := kl.br.ReadByte()
|
||||
if err != nil {
|
||||
kl.readErr = err
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// delay the newline handling until the next token is delivered,
|
||||
// fixes off-by-one errors when reporting a parse error.
|
||||
if kl.eol {
|
||||
kl.line++
|
||||
kl.column = 0
|
||||
kl.eol = false
|
||||
}
|
||||
|
||||
if c == '\n' {
|
||||
kl.eol = true
|
||||
} else {
|
||||
kl.column++
|
||||
}
|
||||
|
||||
return c, true
|
||||
}
|
||||
|
||||
func (kl *klexer) Next() (lex, bool) {
|
||||
var (
|
||||
l lex
|
||||
|
||||
str strings.Builder
|
||||
|
||||
commt bool
|
||||
)
|
||||
|
||||
for x, ok := kl.readByte(); ok; x, ok = kl.readByte() {
|
||||
l.line, l.column = kl.line, kl.column
|
||||
|
||||
switch x {
|
||||
case ':':
|
||||
if commt {
|
||||
if commt || !kl.key {
|
||||
break
|
||||
}
|
||||
l.token = str
|
||||
if key {
|
||||
l.value = zKey
|
||||
c <- l
|
||||
// Next token is a space, eat it
|
||||
s.tokenText()
|
||||
key = false
|
||||
str = ""
|
||||
} else {
|
||||
l.value = zValue
|
||||
}
|
||||
|
||||
kl.key = false
|
||||
|
||||
// Next token is a space, eat it
|
||||
kl.readByte()
|
||||
|
||||
l.value = zKey
|
||||
l.token = str.String()
|
||||
return l, true
|
||||
case ';':
|
||||
commt = true
|
||||
case '\n':
|
||||
|
|
@ -226,24 +316,37 @@ func klexer(s *scan, c chan lex) {
|
|||
// Reset a comment
|
||||
commt = false
|
||||
}
|
||||
|
||||
if kl.key && str.Len() == 0 {
|
||||
// ignore empty lines
|
||||
break
|
||||
}
|
||||
|
||||
kl.key = true
|
||||
|
||||
l.value = zValue
|
||||
l.token = str
|
||||
c <- l
|
||||
str = ""
|
||||
commt = false
|
||||
key = true
|
||||
l.token = str.String()
|
||||
return l, true
|
||||
default:
|
||||
if commt {
|
||||
break
|
||||
}
|
||||
str += string(x)
|
||||
|
||||
str.WriteByte(x)
|
||||
}
|
||||
x, err = s.tokenText()
|
||||
}
|
||||
if len(str) > 0 {
|
||||
|
||||
if kl.readErr != nil && kl.readErr != io.EOF {
|
||||
// Don't return any tokens after a read error occurs.
|
||||
return lex{value: zEOF}, false
|
||||
}
|
||||
|
||||
if str.Len() > 0 {
|
||||
// Send remainder
|
||||
l.token = str
|
||||
l.value = zValue
|
||||
c <- l
|
||||
l.token = str.String()
|
||||
return l, true
|
||||
}
|
||||
|
||||
return lex{value: zEOF}, false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,14 @@ import (
|
|||
"crypto/rsa"
|
||||
"math/big"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
const format = "Private-key-format: v1.3\n"
|
||||
|
||||
var bigIntOne = big.NewInt(1)
|
||||
|
||||
// PrivateKeyString converts a PrivateKey to a string. This string has the same
|
||||
// format as the private-key-file of BIND9 (Private-key-format: v1.3).
|
||||
// It needs some info from the key (the algorithm), so its a method of the DNSKEY
|
||||
|
|
@ -29,12 +33,11 @@ func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
|
|||
prime2 := toBase64(p.Primes[1].Bytes())
|
||||
// Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm
|
||||
// and from: http://code.google.com/p/go/issues/detail?id=987
|
||||
one := big.NewInt(1)
|
||||
p1 := big.NewInt(0).Sub(p.Primes[0], one)
|
||||
q1 := big.NewInt(0).Sub(p.Primes[1], one)
|
||||
exp1 := big.NewInt(0).Mod(p.D, p1)
|
||||
exp2 := big.NewInt(0).Mod(p.D, q1)
|
||||
coeff := big.NewInt(0).ModInverse(p.Primes[1], p.Primes[0])
|
||||
p1 := new(big.Int).Sub(p.Primes[0], bigIntOne)
|
||||
q1 := new(big.Int).Sub(p.Primes[1], bigIntOne)
|
||||
exp1 := new(big.Int).Mod(p.D, p1)
|
||||
exp2 := new(big.Int).Mod(p.D, q1)
|
||||
coeff := new(big.Int).ModInverse(p.Primes[1], p.Primes[0])
|
||||
|
||||
exponent1 := toBase64(exp1.Bytes())
|
||||
exponent2 := toBase64(exp2.Bytes())
|
||||
|
|
@ -79,6 +82,12 @@ func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
|
|||
"Private_value(x): " + priv + "\n" +
|
||||
"Public_value(y): " + pub + "\n"
|
||||
|
||||
case ed25519.PrivateKey:
|
||||
private := toBase64(p.Seed())
|
||||
return format +
|
||||
"Algorithm: " + algorithm + "\n" +
|
||||
"PrivateKey: " + private + "\n"
|
||||
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
/*
|
||||
Package dns implements a full featured interface to the Domain Name System.
|
||||
Server- and client-side programming is supported.
|
||||
The package allows complete control over what is send out to the DNS. The package
|
||||
API follows the less-is-more principle, by presenting a small, clean interface.
|
||||
Both server- and client-side programming is supported. The package allows
|
||||
complete control over what is sent out to the DNS. The API follows the
|
||||
less-is-more principle, by presenting a small, clean interface.
|
||||
|
||||
The package dns supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
|
||||
It supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
|
||||
TSIG, EDNS0, dynamic updates, notifies and DNSSEC validation/signing.
|
||||
Note that domain names MUST be fully qualified, before sending them, unqualified
|
||||
|
||||
Note that domain names MUST be fully qualified before sending them, unqualified
|
||||
names in a message will result in a packing failure.
|
||||
|
||||
Resource records are native types. They are not stored in wire format.
|
||||
Basic usage pattern for creating a new resource record:
|
||||
Resource records are native types. They are not stored in wire format. Basic
|
||||
usage pattern for creating a new resource record:
|
||||
|
||||
r := new(dns.MX)
|
||||
r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX,
|
||||
Class: dns.ClassINET, Ttl: 3600}
|
||||
r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: 3600}
|
||||
r.Preference = 10
|
||||
r.Mx = "mx.miek.nl."
|
||||
|
||||
|
|
@ -22,16 +22,16 @@ Or directly from a string:
|
|||
|
||||
mx, err := dns.NewRR("miek.nl. 3600 IN MX 10 mx.miek.nl.")
|
||||
|
||||
Or when the default TTL (3600) and class (IN) suit you:
|
||||
Or when the default origin (.) and TTL (3600) and class (IN) suit you:
|
||||
|
||||
mx, err := dns.NewRR("miek.nl. MX 10 mx.miek.nl.")
|
||||
mx, err := dns.NewRR("miek.nl MX 10 mx.miek.nl")
|
||||
|
||||
Or even:
|
||||
|
||||
mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")
|
||||
|
||||
In the DNS messages are exchanged, these messages contain resource
|
||||
records (sets). Use pattern for creating a message:
|
||||
In the DNS messages are exchanged, these messages contain resource records
|
||||
(sets). Use pattern for creating a message:
|
||||
|
||||
m := new(dns.Msg)
|
||||
m.SetQuestion("miek.nl.", dns.TypeMX)
|
||||
|
|
@ -40,8 +40,8 @@ Or when not certain if the domain name is fully qualified:
|
|||
|
||||
m.SetQuestion(dns.Fqdn("miek.nl"), dns.TypeMX)
|
||||
|
||||
The message m is now a message with the question section set to ask
|
||||
the MX records for the miek.nl. zone.
|
||||
The message m is now a message with the question section set to ask the MX
|
||||
records for the miek.nl. zone.
|
||||
|
||||
The following is slightly more verbose, but more flexible:
|
||||
|
||||
|
|
@ -51,9 +51,8 @@ The following is slightly more verbose, but more flexible:
|
|||
m1.Question = make([]dns.Question, 1)
|
||||
m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}
|
||||
|
||||
After creating a message it can be send.
|
||||
Basic use pattern for synchronous querying the DNS at a
|
||||
server configured on 127.0.0.1 and port 53:
|
||||
After creating a message it can be sent. Basic use pattern for synchronous
|
||||
querying the DNS at a server configured on 127.0.0.1 and port 53:
|
||||
|
||||
c := new(dns.Client)
|
||||
in, rtt, err := c.Exchange(m1, "127.0.0.1:53")
|
||||
|
|
@ -63,7 +62,23 @@ class) is as easy as setting:
|
|||
|
||||
c.SingleInflight = true
|
||||
|
||||
If these "advanced" features are not needed, a simple UDP query can be send,
|
||||
More advanced options are available using a net.Dialer and the corresponding API.
|
||||
For example it is possible to set a timeout, or to specify a source IP address
|
||||
and port to use for the connection:
|
||||
|
||||
c := new(dns.Client)
|
||||
laddr := net.UDPAddr{
|
||||
IP: net.ParseIP("[::1]"),
|
||||
Port: 12345,
|
||||
Zone: "",
|
||||
}
|
||||
c.Dialer := &net.Dialer{
|
||||
Timeout: 200 * time.Millisecond,
|
||||
LocalAddr: &laddr,
|
||||
}
|
||||
in, rtt, err := c.Exchange(m1, "8.8.8.8:53")
|
||||
|
||||
If these "advanced" features are not needed, a simple UDP query can be sent,
|
||||
with:
|
||||
|
||||
in, err := dns.Exchange(m1, "127.0.0.1:53")
|
||||
|
|
@ -83,25 +98,24 @@ the Answer section:
|
|||
|
||||
Domain Name and TXT Character String Representations
|
||||
|
||||
Both domain names and TXT character strings are converted to presentation
|
||||
form both when unpacked and when converted to strings.
|
||||
Both domain names and TXT character strings are converted to presentation form
|
||||
both when unpacked and when converted to strings.
|
||||
|
||||
For TXT character strings, tabs, carriage returns and line feeds will be
|
||||
converted to \t, \r and \n respectively. Back slashes and quotations marks
|
||||
will be escaped. Bytes below 32 and above 127 will be converted to \DDD
|
||||
form.
|
||||
converted to \t, \r and \n respectively. Back slashes and quotations marks will
|
||||
be escaped. Bytes below 32 and above 127 will be converted to \DDD form.
|
||||
|
||||
For domain names, in addition to the above rules brackets, periods,
|
||||
spaces, semicolons and the at symbol are escaped.
|
||||
For domain names, in addition to the above rules brackets, periods, spaces,
|
||||
semicolons and the at symbol are escaped.
|
||||
|
||||
DNSSEC
|
||||
|
||||
DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It
|
||||
uses public key cryptography to sign resource records. The
|
||||
public keys are stored in DNSKEY records and the signatures in RRSIG records.
|
||||
DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It uses
|
||||
public key cryptography to sign resource records. The public keys are stored in
|
||||
DNSKEY records and the signatures in RRSIG records.
|
||||
|
||||
Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK) bit
|
||||
to a request.
|
||||
Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK)
|
||||
bit to a request.
|
||||
|
||||
m := new(dns.Msg)
|
||||
m.SetEdns0(4096, true)
|
||||
|
|
@ -110,9 +124,9 @@ Signature generation, signature verification and key generation are all supporte
|
|||
|
||||
DYNAMIC UPDATES
|
||||
|
||||
Dynamic updates reuses the DNS message format, but renames three of
|
||||
the sections. Question is Zone, Answer is Prerequisite, Authority is
|
||||
Update, only the Additional is not renamed. See RFC 2136 for the gory details.
|
||||
Dynamic updates reuses the DNS message format, but renames three of the
|
||||
sections. Question is Zone, Answer is Prerequisite, Authority is Update, only
|
||||
the Additional is not renamed. See RFC 2136 for the gory details.
|
||||
|
||||
You can set a rather complex set of rules for the existence of absence of
|
||||
certain resource records or names in a zone to specify if resource records
|
||||
|
|
@ -129,10 +143,9 @@ DNS function shows which functions exist to specify the prerequisites.
|
|||
NONE rrset empty RRset does not exist dns.RRsetNotUsed
|
||||
zone rrset rr RRset exists (value dep) dns.Used
|
||||
|
||||
The prerequisite section can also be left empty.
|
||||
If you have decided on the prerequisites you can tell what RRs should
|
||||
be added or deleted. The next table shows the options you have and
|
||||
what functions to call.
|
||||
The prerequisite section can also be left empty. If you have decided on the
|
||||
prerequisites you can tell what RRs should be added or deleted. The next table
|
||||
shows the options you have and what functions to call.
|
||||
|
||||
3.4.2.6 - Table Of Metavalues Used In Update Section
|
||||
|
||||
|
|
@ -152,6 +165,11 @@ Basic use pattern when querying with a TSIG name "axfr." (note that these key na
|
|||
must be fully qualified - as they are domain names) and the base64 secret
|
||||
"so6ZGir4GPAqINNh9U5c3A==":
|
||||
|
||||
If an incoming message contains a TSIG record it MUST be the last record in
|
||||
the additional section (RFC2845 3.2). This means that you should make the
|
||||
call to SetTsig last, right before executing the query. If you make any
|
||||
changes to the RRset after calling SetTsig() the signature will be incorrect.
|
||||
|
||||
c := new(dns.Client)
|
||||
c.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="}
|
||||
m := new(dns.Msg)
|
||||
|
|
@ -160,10 +178,10 @@ must be fully qualified - as they are domain names) and the base64 secret
|
|||
...
|
||||
// When sending the TSIG RR is calculated and filled in before sending
|
||||
|
||||
When requesting an zone transfer (almost all TSIG usage is when requesting zone transfers), with
|
||||
TSIG, this is the basic use pattern. In this example we request an AXFR for
|
||||
miek.nl. with TSIG key named "axfr." and secret "so6ZGir4GPAqINNh9U5c3A=="
|
||||
and using the server 176.58.119.54:
|
||||
When requesting an zone transfer (almost all TSIG usage is when requesting zone
|
||||
transfers), with TSIG, this is the basic use pattern. In this example we
|
||||
request an AXFR for miek.nl. with TSIG key named "axfr." and secret
|
||||
"so6ZGir4GPAqINNh9U5c3A==" and using the server 176.58.119.54:
|
||||
|
||||
t := new(dns.Transfer)
|
||||
m := new(dns.Msg)
|
||||
|
|
@ -173,8 +191,8 @@ and using the server 176.58.119.54:
|
|||
c, err := t.In(m, "176.58.119.54:53")
|
||||
for r := range c { ... }
|
||||
|
||||
You can now read the records from the transfer as they come in. Each envelope is checked with TSIG.
|
||||
If something is not correct an error is returned.
|
||||
You can now read the records from the transfer as they come in. Each envelope
|
||||
is checked with TSIG. If something is not correct an error is returned.
|
||||
|
||||
Basic use pattern validating and replying to a message that has TSIG set.
|
||||
|
||||
|
|
@ -199,29 +217,30 @@ Basic use pattern validating and replying to a message that has TSIG set.
|
|||
|
||||
PRIVATE RRS
|
||||
|
||||
RFC 6895 sets aside a range of type codes for private use. This range
|
||||
is 65,280 - 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these
|
||||
RFC 6895 sets aside a range of type codes for private use. This range is 65,280
|
||||
- 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these
|
||||
can be used, before requesting an official type code from IANA.
|
||||
|
||||
see http://miek.nl/posts/2014/Sep/21/Private%20RRs%20and%20IDN%20in%20Go%20DNS/ for more
|
||||
See https://miek.nl/2014/September/21/idn-and-private-rr-in-go-dns/ for more
|
||||
information.
|
||||
|
||||
EDNS0
|
||||
|
||||
EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated
|
||||
by RFC 6891. It defines an new RR type, the OPT RR, which is then completely
|
||||
EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated by
|
||||
RFC 6891. It defines an new RR type, the OPT RR, which is then completely
|
||||
abused.
|
||||
|
||||
Basic use pattern for creating an (empty) OPT RR:
|
||||
|
||||
o := new(dns.OPT)
|
||||
o.Hdr.Name = "." // MUST be the root zone, per definition.
|
||||
o.Hdr.Rrtype = dns.TypeOPT
|
||||
|
||||
The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891)
|
||||
interfaces. Currently only a few have been standardized: EDNS0_NSID
|
||||
(RFC 5001) and EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note
|
||||
that these options may be combined in an OPT RR.
|
||||
Basic use pattern for a server to check if (and which) options are set:
|
||||
The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891) interfaces.
|
||||
Currently only a few have been standardized: EDNS0_NSID (RFC 5001) and
|
||||
EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note that these options
|
||||
may be combined in an OPT RR. Basic use pattern for a server to check if (and
|
||||
which) options are set:
|
||||
|
||||
// o is a dns.OPT
|
||||
for _, s := range o.Option {
|
||||
|
|
@ -241,10 +260,9 @@ From RFC 2931:
|
|||
... protection for glue records, DNS requests, protection for message headers
|
||||
on requests and responses, and protection of the overall integrity of a response.
|
||||
|
||||
It works like TSIG, except that SIG(0) uses public key cryptography, instead of the shared
|
||||
secret approach in TSIG.
|
||||
Supported algorithms: DSA, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256 and
|
||||
RSASHA512.
|
||||
It works like TSIG, except that SIG(0) uses public key cryptography, instead of
|
||||
the shared secret approach in TSIG. Supported algorithms: DSA, ECDSAP256SHA256,
|
||||
ECDSAP384SHA384, RSASHA1, RSASHA256 and RSASHA512.
|
||||
|
||||
Signing subsequent messages in multi-message sessions is not implemented.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
package dns
|
||||
|
||||
//go:generate go run duplicate_generate.go
|
||||
|
||||
// IsDuplicate checks of r1 and r2 are duplicates of each other, excluding the TTL.
|
||||
// So this means the header data is equal *and* the RDATA is the same. Return true
|
||||
// is so, otherwise false.
|
||||
// It's is a protocol violation to have identical RRs in a message.
|
||||
func IsDuplicate(r1, r2 RR) bool {
|
||||
// Check whether the record header is identical.
|
||||
if !r1.Header().isDuplicate(r2.Header()) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check whether the RDATA is identical.
|
||||
return r1.isDuplicate(r2)
|
||||
}
|
||||
|
||||
func (r1 *RR_Header) isDuplicate(_r2 RR) bool {
|
||||
r2, ok := _r2.(*RR_Header)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if r1.Class != r2.Class {
|
||||
return false
|
||||
}
|
||||
if r1.Rrtype != r2.Rrtype {
|
||||
return false
|
||||
}
|
||||
if !isDuplicateName(r1.Name, r2.Name) {
|
||||
return false
|
||||
}
|
||||
// ignore TTL
|
||||
return true
|
||||
}
|
||||
|
||||
// isDuplicateName checks if the domain names s1 and s2 are equal.
|
||||
func isDuplicateName(s1, s2 string) bool { return equal(s1, s2) }
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
//+build ignore
|
||||
|
||||
// types_generate.go is meant to run with go generate. It will use
|
||||
// go/{importer,types} to track down all the RR struct types. Then for each type
|
||||
// it will generate conversion tables (TypeToRR and TypeToString) and banal
|
||||
// methods (len, Header, copy) based on the struct tags. The generated source is
|
||||
// written to ztypes.go, and is meant to be checked into git.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"go/importer"
|
||||
"go/types"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var packageHdr = `
|
||||
// Code generated by "go run duplicate_generate.go"; DO NOT EDIT.
|
||||
|
||||
package dns
|
||||
|
||||
`
|
||||
|
||||
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
|
||||
st, ok := t.Underlying().(*types.Struct)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
|
||||
return st, false
|
||||
}
|
||||
if st.Field(0).Anonymous() {
|
||||
st, _ := getTypeStruct(st.Field(0).Type(), scope)
|
||||
return st, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Import and type-check the package
|
||||
pkg, err := importer.Default().Import("github.com/miekg/dns")
|
||||
fatalIfErr(err)
|
||||
scope := pkg.Scope()
|
||||
|
||||
// Collect actual types (*X)
|
||||
var namedTypes []string
|
||||
for _, name := range scope.Names() {
|
||||
o := scope.Lookup(name)
|
||||
if o == nil || !o.Exported() {
|
||||
continue
|
||||
}
|
||||
|
||||
if st, _ := getTypeStruct(o.Type(), scope); st == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if name == "PrivateRR" || name == "OPT" {
|
||||
continue
|
||||
}
|
||||
|
||||
namedTypes = append(namedTypes, o.Name())
|
||||
}
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
b.WriteString(packageHdr)
|
||||
|
||||
// Generate the duplicate check for each type.
|
||||
fmt.Fprint(b, "// isDuplicate() functions\n\n")
|
||||
for _, name := range namedTypes {
|
||||
|
||||
o := scope.Lookup(name)
|
||||
st, isEmbedded := getTypeStruct(o.Type(), scope)
|
||||
if isEmbedded {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(b, "func (r1 *%s) isDuplicate(_r2 RR) bool {\n", name)
|
||||
fmt.Fprintf(b, "r2, ok := _r2.(*%s)\n", name)
|
||||
fmt.Fprint(b, "if !ok { return false }\n")
|
||||
fmt.Fprint(b, "_ = r2\n")
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
field := st.Field(i).Name()
|
||||
o2 := func(s string) { fmt.Fprintf(b, s+"\n", field, field) }
|
||||
o3 := func(s string) { fmt.Fprintf(b, s+"\n", field, field, field) }
|
||||
|
||||
// For some reason, a and aaaa don't pop up as *types.Slice here (mostly like because the are
|
||||
// *indirectly* defined as a slice in the net package).
|
||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||
o2("if len(r1.%s) != len(r2.%s) {\nreturn false\n}")
|
||||
|
||||
if st.Tag(i) == `dns:"cdomain-name"` || st.Tag(i) == `dns:"domain-name"` {
|
||||
o3(`for i := 0; i < len(r1.%s); i++ {
|
||||
if !isDuplicateName(r1.%s[i], r2.%s[i]) {
|
||||
return false
|
||||
}
|
||||
}`)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
o3(`for i := 0; i < len(r1.%s); i++ {
|
||||
if r1.%s[i] != r2.%s[i] {
|
||||
return false
|
||||
}
|
||||
}`)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
switch st.Tag(i) {
|
||||
case `dns:"-"`:
|
||||
// ignored
|
||||
case `dns:"a"`, `dns:"aaaa"`:
|
||||
o2("if !r1.%s.Equal(r2.%s) {\nreturn false\n}")
|
||||
case `dns:"cdomain-name"`, `dns:"domain-name"`:
|
||||
o2("if !isDuplicateName(r1.%s, r2.%s) {\nreturn false\n}")
|
||||
default:
|
||||
o2("if r1.%s != r2.%s {\nreturn false\n}")
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(b, "return true\n}\n\n")
|
||||
}
|
||||
|
||||
// gofmt
|
||||
res, err := format.Source(b.Bytes())
|
||||
if err != nil {
|
||||
b.WriteTo(os.Stderr)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// write result
|
||||
f, err := os.Create("zduplicate.go")
|
||||
fatalIfErr(err)
|
||||
defer f.Close()
|
||||
f.Write(res)
|
||||
}
|
||||
|
||||
func fatalIfErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +1,30 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// EDNS0 Option codes.
|
||||
const (
|
||||
EDNS0LLQ = 0x1 // long lived queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
|
||||
EDNS0UL = 0x2 // update lease draft: http://files.dns-sd.org/draft-sekar-dns-ul.txt
|
||||
EDNS0NSID = 0x3 // nsid (RFC5001)
|
||||
EDNS0DAU = 0x5 // DNSSEC Algorithm Understood
|
||||
EDNS0DHU = 0x6 // DS Hash Understood
|
||||
EDNS0N3U = 0x7 // NSEC3 Hash Understood
|
||||
EDNS0SUBNET = 0x8 // client-subnet (RFC6891)
|
||||
EDNS0EXPIRE = 0x9 // EDNS0 expire
|
||||
EDNS0SUBNETDRAFT = 0x50fa // Don't use! Use EDNS0SUBNET
|
||||
EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (RFC6891)
|
||||
EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (RFC6891)
|
||||
_DO = 1 << 15 // dnssec ok
|
||||
EDNS0LLQ = 0x1 // long lived queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
|
||||
EDNS0UL = 0x2 // update lease draft: http://files.dns-sd.org/draft-sekar-dns-ul.txt
|
||||
EDNS0NSID = 0x3 // nsid (See RFC 5001)
|
||||
EDNS0DAU = 0x5 // DNSSEC Algorithm Understood
|
||||
EDNS0DHU = 0x6 // DS Hash Understood
|
||||
EDNS0N3U = 0x7 // NSEC3 Hash Understood
|
||||
EDNS0SUBNET = 0x8 // client-subnet (See RFC 7871)
|
||||
EDNS0EXPIRE = 0x9 // EDNS0 expire
|
||||
EDNS0COOKIE = 0xa // EDNS0 Cookie
|
||||
EDNS0TCPKEEPALIVE = 0xb // EDNS0 tcp keep alive (See RFC 7828)
|
||||
EDNS0PADDING = 0xc // EDNS0 padding (See RFC 7830)
|
||||
EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (See RFC 6891)
|
||||
EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (See RFC 6891)
|
||||
_DO = 1 << 15 // DNSSEC OK
|
||||
)
|
||||
|
||||
// OPT is the EDNS0 RR appended to messages to convey extra (meta) information.
|
||||
|
|
@ -53,9 +57,8 @@ func (rr *OPT) String() string {
|
|||
}
|
||||
case *EDNS0_SUBNET:
|
||||
s += "\n; SUBNET: " + o.String()
|
||||
if o.(*EDNS0_SUBNET).DraftOption {
|
||||
s += " (draft)"
|
||||
}
|
||||
case *EDNS0_COOKIE:
|
||||
s += "\n; COOKIE: " + o.String()
|
||||
case *EDNS0_UL:
|
||||
s += "\n; UPDATE LEASE: " + o.String()
|
||||
case *EDNS0_LLQ:
|
||||
|
|
@ -68,44 +71,51 @@ func (rr *OPT) String() string {
|
|||
s += "\n; NSEC3 HASH UNDERSTOOD: " + o.String()
|
||||
case *EDNS0_LOCAL:
|
||||
s += "\n; LOCAL OPT: " + o.String()
|
||||
case *EDNS0_PADDING:
|
||||
s += "\n; PADDING: " + o.String()
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (rr *OPT) len() int {
|
||||
l := rr.Hdr.len()
|
||||
for i := 0; i < len(rr.Option); i++ {
|
||||
func (rr *OPT) len(off int, compression map[string]struct{}) int {
|
||||
l := rr.Hdr.len(off, compression)
|
||||
for _, o := range rr.Option {
|
||||
l += 4 // Account for 2-byte option code and 2-byte option length.
|
||||
lo, _ := rr.Option[i].pack()
|
||||
lo, _ := o.pack()
|
||||
l += len(lo)
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
func (rr *OPT) parse(c *zlexer, origin, file string) *ParseError {
|
||||
panic("dns: internal error: parse should never be called on OPT")
|
||||
}
|
||||
|
||||
func (r1 *OPT) isDuplicate(r2 RR) bool { return false }
|
||||
|
||||
// return the old value -> delete SetVersion?
|
||||
|
||||
// Version returns the EDNS version used. Only zero is defined.
|
||||
func (rr *OPT) Version() uint8 {
|
||||
return uint8((rr.Hdr.Ttl & 0x00FF0000) >> 16)
|
||||
return uint8(rr.Hdr.Ttl & 0x00FF0000 >> 16)
|
||||
}
|
||||
|
||||
// SetVersion sets the version of EDNS. This is usually zero.
|
||||
func (rr *OPT) SetVersion(v uint8) {
|
||||
rr.Hdr.Ttl = rr.Hdr.Ttl&0xFF00FFFF | (uint32(v) << 16)
|
||||
rr.Hdr.Ttl = rr.Hdr.Ttl&0xFF00FFFF | uint32(v)<<16
|
||||
}
|
||||
|
||||
// ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL).
|
||||
func (rr *OPT) ExtendedRcode() uint8 {
|
||||
return uint8((rr.Hdr.Ttl&0xFF000000)>>24) + 15
|
||||
func (rr *OPT) ExtendedRcode() int {
|
||||
return int(rr.Hdr.Ttl&0xFF000000>>24) << 4
|
||||
}
|
||||
|
||||
// SetExtendedRcode sets the EDNS extended RCODE field.
|
||||
func (rr *OPT) SetExtendedRcode(v uint8) {
|
||||
if v < RcodeBadVers { // Smaller than 16.. Use the 4 bits you have!
|
||||
return
|
||||
}
|
||||
rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | (uint32(v-15) << 24)
|
||||
//
|
||||
// If the RCODE is not an extended RCODE, will reset the extended RCODE field to 0.
|
||||
func (rr *OPT) SetExtendedRcode(v uint16) {
|
||||
rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | uint32(v>>4)<<24
|
||||
}
|
||||
|
||||
// UDPSize returns the UDP buffer size.
|
||||
|
|
@ -124,12 +134,21 @@ func (rr *OPT) Do() bool {
|
|||
}
|
||||
|
||||
// SetDo sets the DO (DNSSEC OK) bit.
|
||||
func (rr *OPT) SetDo() {
|
||||
rr.Hdr.Ttl |= _DO
|
||||
// If we pass an argument, set the DO bit to that value.
|
||||
// It is possible to pass 2 or more arguments. Any arguments after the 1st is silently ignored.
|
||||
func (rr *OPT) SetDo(do ...bool) {
|
||||
if len(do) == 1 {
|
||||
if do[0] {
|
||||
rr.Hdr.Ttl |= _DO
|
||||
} else {
|
||||
rr.Hdr.Ttl &^= _DO
|
||||
}
|
||||
} else {
|
||||
rr.Hdr.Ttl |= _DO
|
||||
}
|
||||
}
|
||||
|
||||
// EDNS0 defines an EDNS0 Option. An OPT RR can have multiple options appended to
|
||||
// it.
|
||||
// EDNS0 defines an EDNS0 Option. An OPT RR can have multiple options appended to it.
|
||||
type EDNS0 interface {
|
||||
// Option returns the option code for the option.
|
||||
Option() uint16
|
||||
|
|
@ -140,9 +159,11 @@ type EDNS0 interface {
|
|||
unpack([]byte) error
|
||||
// String returns the string representation of the option.
|
||||
String() string
|
||||
// copy returns a deep-copy of the option.
|
||||
copy() EDNS0
|
||||
}
|
||||
|
||||
// The nsid EDNS0 option is used to retrieve a nameserver
|
||||
// EDNS0_NSID option is used to retrieve a nameserver
|
||||
// identifier. When sending a request Nsid must be set to the empty string
|
||||
// The identifier is an opaque string encoded as hex.
|
||||
// Basic use pattern for creating an nsid option:
|
||||
|
|
@ -167,12 +188,14 @@ func (e *EDNS0_NSID) pack() ([]byte, error) {
|
|||
return h, nil
|
||||
}
|
||||
|
||||
func (e *EDNS0_NSID) Option() uint16 { return EDNS0NSID }
|
||||
// Option implements the EDNS0 interface.
|
||||
func (e *EDNS0_NSID) Option() uint16 { return EDNS0NSID } // Option returns the option code.
|
||||
func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); return nil }
|
||||
func (e *EDNS0_NSID) String() string { return string(e.Nsid) }
|
||||
func (e *EDNS0_NSID) String() string { return e.Nsid }
|
||||
func (e *EDNS0_NSID) copy() EDNS0 { return &EDNS0_NSID{e.Code, e.Nsid} }
|
||||
|
||||
// EDNS0_SUBNET is the subnet option that is used to give the remote nameserver
|
||||
// an idea of where the client lives. It can then give back a different
|
||||
// an idea of where the client lives. See RFC 7871. It can then give back a different
|
||||
// answer depending on the location or network topology.
|
||||
// Basic use pattern for creating an subnet option:
|
||||
//
|
||||
|
|
@ -182,38 +205,38 @@ func (e *EDNS0_NSID) String() string { return string(e.Nsid) }
|
|||
// e := new(dns.EDNS0_SUBNET)
|
||||
// e.Code = dns.EDNS0SUBNET
|
||||
// e.Family = 1 // 1 for IPv4 source address, 2 for IPv6
|
||||
// e.NetMask = 32 // 32 for IPV4, 128 for IPv6
|
||||
// e.SourceNetmask = 32 // 32 for IPV4, 128 for IPv6
|
||||
// e.SourceScope = 0
|
||||
// e.Address = net.ParseIP("127.0.0.1").To4() // for IPv4
|
||||
// // e.Address = net.ParseIP("2001:7b8:32a::2") // for IPV6
|
||||
// o.Option = append(o.Option, e)
|
||||
//
|
||||
// Note: the spec (draft-ietf-dnsop-edns-client-subnet-00) has some insane logic
|
||||
// for which netmask applies to the address. This code will parse all the
|
||||
// available bits when unpacking (up to optlen). When packing it will apply
|
||||
// SourceNetmask. If you need more advanced logic, patches welcome and good luck.
|
||||
// This code will parse all the available bits when unpacking (up to optlen).
|
||||
// When packing it will apply SourceNetmask. If you need more advanced logic,
|
||||
// patches welcome and good luck.
|
||||
type EDNS0_SUBNET struct {
|
||||
Code uint16 // Always EDNS0SUBNET
|
||||
Family uint16 // 1 for IP, 2 for IP6
|
||||
SourceNetmask uint8
|
||||
SourceScope uint8
|
||||
Address net.IP
|
||||
DraftOption bool // Set to true if using the old (0x50fa) option code
|
||||
}
|
||||
|
||||
func (e *EDNS0_SUBNET) Option() uint16 {
|
||||
if e.DraftOption {
|
||||
return EDNS0SUBNETDRAFT
|
||||
}
|
||||
return EDNS0SUBNET
|
||||
}
|
||||
// Option implements the EDNS0 interface.
|
||||
func (e *EDNS0_SUBNET) Option() uint16 { return EDNS0SUBNET }
|
||||
|
||||
func (e *EDNS0_SUBNET) pack() ([]byte, error) {
|
||||
b := make([]byte, 4)
|
||||
b[0], b[1] = packUint16(e.Family)
|
||||
binary.BigEndian.PutUint16(b[0:], e.Family)
|
||||
b[2] = e.SourceNetmask
|
||||
b[3] = e.SourceScope
|
||||
switch e.Family {
|
||||
case 0:
|
||||
// "dig" sets AddressFamily to 0 if SourceNetmask is also 0
|
||||
// We might don't need to complain either
|
||||
if e.SourceNetmask != 0 {
|
||||
return nil, errors.New("dns: bad address family")
|
||||
}
|
||||
case 1:
|
||||
if e.SourceNetmask > net.IPv4len*8 {
|
||||
return nil, errors.New("dns: bad netmask")
|
||||
|
|
@ -244,30 +267,31 @@ func (e *EDNS0_SUBNET) unpack(b []byte) error {
|
|||
if len(b) < 4 {
|
||||
return ErrBuf
|
||||
}
|
||||
e.Family, _ = unpackUint16(b, 0)
|
||||
e.Family = binary.BigEndian.Uint16(b)
|
||||
e.SourceNetmask = b[2]
|
||||
e.SourceScope = b[3]
|
||||
switch e.Family {
|
||||
case 0:
|
||||
// "dig" sets AddressFamily to 0 if SourceNetmask is also 0
|
||||
// It's okay to accept such a packet
|
||||
if e.SourceNetmask != 0 {
|
||||
return errors.New("dns: bad address family")
|
||||
}
|
||||
e.Address = net.IPv4(0, 0, 0, 0)
|
||||
case 1:
|
||||
if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 {
|
||||
return errors.New("dns: bad netmask")
|
||||
}
|
||||
addr := make([]byte, net.IPv4len)
|
||||
for i := 0; i < net.IPv4len && 4+i < len(b); i++ {
|
||||
addr[i] = b[4+i]
|
||||
}
|
||||
e.Address = net.IPv4(addr[0], addr[1], addr[2], addr[3])
|
||||
addr := make(net.IP, net.IPv4len)
|
||||
copy(addr, b[4:])
|
||||
e.Address = addr.To16()
|
||||
case 2:
|
||||
if e.SourceNetmask > net.IPv6len*8 || e.SourceScope > net.IPv6len*8 {
|
||||
return errors.New("dns: bad netmask")
|
||||
}
|
||||
addr := make([]byte, net.IPv6len)
|
||||
for i := 0; i < net.IPv6len && 4+i < len(b); i++ {
|
||||
addr[i] = b[4+i]
|
||||
}
|
||||
e.Address = net.IP{addr[0], addr[1], addr[2], addr[3], addr[4],
|
||||
addr[5], addr[6], addr[7], addr[8], addr[9], addr[10],
|
||||
addr[11], addr[12], addr[13], addr[14], addr[15]}
|
||||
addr := make(net.IP, net.IPv6len)
|
||||
copy(addr, b[4:])
|
||||
e.Address = addr
|
||||
default:
|
||||
return errors.New("dns: bad address family")
|
||||
}
|
||||
|
|
@ -286,6 +310,53 @@ func (e *EDNS0_SUBNET) String() (s string) {
|
|||
return
|
||||
}
|
||||
|
||||
func (e *EDNS0_SUBNET) copy() EDNS0 {
|
||||
return &EDNS0_SUBNET{
|
||||
e.Code,
|
||||
e.Family,
|
||||
e.SourceNetmask,
|
||||
e.SourceScope,
|
||||
e.Address,
|
||||
}
|
||||
}
|
||||
|
||||
// The EDNS0_COOKIE option is used to add a DNS Cookie to a message.
|
||||
//
|
||||
// o := new(dns.OPT)
|
||||
// o.Hdr.Name = "."
|
||||
// o.Hdr.Rrtype = dns.TypeOPT
|
||||
// e := new(dns.EDNS0_COOKIE)
|
||||
// e.Code = dns.EDNS0COOKIE
|
||||
// e.Cookie = "24a5ac.."
|
||||
// o.Option = append(o.Option, e)
|
||||
//
|
||||
// The Cookie field consists out of a client cookie (RFC 7873 Section 4), that is
|
||||
// always 8 bytes. It may then optionally be followed by the server cookie. The server
|
||||
// cookie is of variable length, 8 to a maximum of 32 bytes. In other words:
|
||||
//
|
||||
// cCookie := o.Cookie[:16]
|
||||
// sCookie := o.Cookie[16:]
|
||||
//
|
||||
// There is no guarantee that the Cookie string has a specific length.
|
||||
type EDNS0_COOKIE struct {
|
||||
Code uint16 // Always EDNS0COOKIE
|
||||
Cookie string // Hex-encoded cookie data
|
||||
}
|
||||
|
||||
func (e *EDNS0_COOKIE) pack() ([]byte, error) {
|
||||
h, err := hex.DecodeString(e.Cookie)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// Option implements the EDNS0 interface.
|
||||
func (e *EDNS0_COOKIE) Option() uint16 { return EDNS0COOKIE }
|
||||
func (e *EDNS0_COOKIE) unpack(b []byte) error { e.Cookie = hex.EncodeToString(b); return nil }
|
||||
func (e *EDNS0_COOKIE) String() string { return e.Cookie }
|
||||
func (e *EDNS0_COOKIE) copy() EDNS0 { return &EDNS0_COOKIE{e.Code, e.Cookie} }
|
||||
|
||||
// The EDNS0_UL (Update Lease) (draft RFC) option is used to tell the server to set
|
||||
// an expiration on an update RR. This is helpful for clients that cannot clean
|
||||
// up after themselves. This is a draft RFC and more information can be found at
|
||||
|
|
@ -303,16 +374,15 @@ type EDNS0_UL struct {
|
|||
Lease uint32
|
||||
}
|
||||
|
||||
// Option implements the EDNS0 interface.
|
||||
func (e *EDNS0_UL) Option() uint16 { return EDNS0UL }
|
||||
func (e *EDNS0_UL) String() string { return strconv.FormatUint(uint64(e.Lease), 10) }
|
||||
func (e *EDNS0_UL) copy() EDNS0 { return &EDNS0_UL{e.Code, e.Lease} }
|
||||
|
||||
// Copied: http://golang.org/src/pkg/net/dnsmsg.go
|
||||
func (e *EDNS0_UL) pack() ([]byte, error) {
|
||||
b := make([]byte, 4)
|
||||
b[0] = byte(e.Lease >> 24)
|
||||
b[1] = byte(e.Lease >> 16)
|
||||
b[2] = byte(e.Lease >> 8)
|
||||
b[3] = byte(e.Lease)
|
||||
binary.BigEndian.PutUint32(b, e.Lease)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
|
|
@ -320,7 +390,7 @@ func (e *EDNS0_UL) unpack(b []byte) error {
|
|||
if len(b) < 4 {
|
||||
return ErrBuf
|
||||
}
|
||||
e.Lease = uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
|
||||
e.Lease = binary.BigEndian.Uint32(b)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -335,25 +405,16 @@ type EDNS0_LLQ struct {
|
|||
LeaseLife uint32
|
||||
}
|
||||
|
||||
// Option implements the EDNS0 interface.
|
||||
func (e *EDNS0_LLQ) Option() uint16 { return EDNS0LLQ }
|
||||
|
||||
func (e *EDNS0_LLQ) pack() ([]byte, error) {
|
||||
b := make([]byte, 18)
|
||||
b[0], b[1] = packUint16(e.Version)
|
||||
b[2], b[3] = packUint16(e.Opcode)
|
||||
b[4], b[5] = packUint16(e.Error)
|
||||
b[6] = byte(e.Id >> 56)
|
||||
b[7] = byte(e.Id >> 48)
|
||||
b[8] = byte(e.Id >> 40)
|
||||
b[9] = byte(e.Id >> 32)
|
||||
b[10] = byte(e.Id >> 24)
|
||||
b[11] = byte(e.Id >> 16)
|
||||
b[12] = byte(e.Id >> 8)
|
||||
b[13] = byte(e.Id)
|
||||
b[14] = byte(e.LeaseLife >> 24)
|
||||
b[15] = byte(e.LeaseLife >> 16)
|
||||
b[16] = byte(e.LeaseLife >> 8)
|
||||
b[17] = byte(e.LeaseLife)
|
||||
binary.BigEndian.PutUint16(b[0:], e.Version)
|
||||
binary.BigEndian.PutUint16(b[2:], e.Opcode)
|
||||
binary.BigEndian.PutUint16(b[4:], e.Error)
|
||||
binary.BigEndian.PutUint64(b[6:], e.Id)
|
||||
binary.BigEndian.PutUint32(b[14:], e.LeaseLife)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
|
|
@ -361,69 +422,79 @@ func (e *EDNS0_LLQ) unpack(b []byte) error {
|
|||
if len(b) < 18 {
|
||||
return ErrBuf
|
||||
}
|
||||
e.Version, _ = unpackUint16(b, 0)
|
||||
e.Opcode, _ = unpackUint16(b, 2)
|
||||
e.Error, _ = unpackUint16(b, 4)
|
||||
e.Id = uint64(b[6])<<56 | uint64(b[6+1])<<48 | uint64(b[6+2])<<40 |
|
||||
uint64(b[6+3])<<32 | uint64(b[6+4])<<24 | uint64(b[6+5])<<16 | uint64(b[6+6])<<8 | uint64(b[6+7])
|
||||
e.LeaseLife = uint32(b[14])<<24 | uint32(b[14+1])<<16 | uint32(b[14+2])<<8 | uint32(b[14+3])
|
||||
e.Version = binary.BigEndian.Uint16(b[0:])
|
||||
e.Opcode = binary.BigEndian.Uint16(b[2:])
|
||||
e.Error = binary.BigEndian.Uint16(b[4:])
|
||||
e.Id = binary.BigEndian.Uint64(b[6:])
|
||||
e.LeaseLife = binary.BigEndian.Uint32(b[14:])
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *EDNS0_LLQ) String() string {
|
||||
s := strconv.FormatUint(uint64(e.Version), 10) + " " + strconv.FormatUint(uint64(e.Opcode), 10) +
|
||||
" " + strconv.FormatUint(uint64(e.Error), 10) + " " + strconv.FormatUint(uint64(e.Id), 10) +
|
||||
" " + strconv.FormatUint(uint64(e.Error), 10) + " " + strconv.FormatUint(e.Id, 10) +
|
||||
" " + strconv.FormatUint(uint64(e.LeaseLife), 10)
|
||||
return s
|
||||
}
|
||||
func (e *EDNS0_LLQ) copy() EDNS0 {
|
||||
return &EDNS0_LLQ{e.Code, e.Version, e.Opcode, e.Error, e.Id, e.LeaseLife}
|
||||
}
|
||||
|
||||
// EDNS0_DUA implements the EDNS0 "DNSSEC Algorithm Understood" option. See RFC 6975.
|
||||
type EDNS0_DAU struct {
|
||||
Code uint16 // Always EDNS0DAU
|
||||
AlgCode []uint8
|
||||
}
|
||||
|
||||
// Option implements the EDNS0 interface.
|
||||
func (e *EDNS0_DAU) Option() uint16 { return EDNS0DAU }
|
||||
func (e *EDNS0_DAU) pack() ([]byte, error) { return e.AlgCode, nil }
|
||||
func (e *EDNS0_DAU) unpack(b []byte) error { e.AlgCode = b; return nil }
|
||||
|
||||
func (e *EDNS0_DAU) String() string {
|
||||
s := ""
|
||||
for i := 0; i < len(e.AlgCode); i++ {
|
||||
if a, ok := AlgorithmToString[e.AlgCode[i]]; ok {
|
||||
for _, alg := range e.AlgCode {
|
||||
if a, ok := AlgorithmToString[alg]; ok {
|
||||
s += " " + a
|
||||
} else {
|
||||
s += " " + strconv.Itoa(int(e.AlgCode[i]))
|
||||
s += " " + strconv.Itoa(int(alg))
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
func (e *EDNS0_DAU) copy() EDNS0 { return &EDNS0_DAU{e.Code, e.AlgCode} }
|
||||
|
||||
// EDNS0_DHU implements the EDNS0 "DS Hash Understood" option. See RFC 6975.
|
||||
type EDNS0_DHU struct {
|
||||
Code uint16 // Always EDNS0DHU
|
||||
AlgCode []uint8
|
||||
}
|
||||
|
||||
// Option implements the EDNS0 interface.
|
||||
func (e *EDNS0_DHU) Option() uint16 { return EDNS0DHU }
|
||||
func (e *EDNS0_DHU) pack() ([]byte, error) { return e.AlgCode, nil }
|
||||
func (e *EDNS0_DHU) unpack(b []byte) error { e.AlgCode = b; return nil }
|
||||
|
||||
func (e *EDNS0_DHU) String() string {
|
||||
s := ""
|
||||
for i := 0; i < len(e.AlgCode); i++ {
|
||||
if a, ok := HashToString[e.AlgCode[i]]; ok {
|
||||
for _, alg := range e.AlgCode {
|
||||
if a, ok := HashToString[alg]; ok {
|
||||
s += " " + a
|
||||
} else {
|
||||
s += " " + strconv.Itoa(int(e.AlgCode[i]))
|
||||
s += " " + strconv.Itoa(int(alg))
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
func (e *EDNS0_DHU) copy() EDNS0 { return &EDNS0_DHU{e.Code, e.AlgCode} }
|
||||
|
||||
// EDNS0_N3U implements the EDNS0 "NSEC3 Hash Understood" option. See RFC 6975.
|
||||
type EDNS0_N3U struct {
|
||||
Code uint16 // Always EDNS0N3U
|
||||
AlgCode []uint8
|
||||
}
|
||||
|
||||
// Option implements the EDNS0 interface.
|
||||
func (e *EDNS0_N3U) Option() uint16 { return EDNS0N3U }
|
||||
func (e *EDNS0_N3U) pack() ([]byte, error) { return e.AlgCode, nil }
|
||||
func (e *EDNS0_N3U) unpack(b []byte) error { e.AlgCode = b; return nil }
|
||||
|
|
@ -431,30 +502,31 @@ func (e *EDNS0_N3U) unpack(b []byte) error { e.AlgCode = b; return nil }
|
|||
func (e *EDNS0_N3U) String() string {
|
||||
// Re-use the hash map
|
||||
s := ""
|
||||
for i := 0; i < len(e.AlgCode); i++ {
|
||||
if a, ok := HashToString[e.AlgCode[i]]; ok {
|
||||
for _, alg := range e.AlgCode {
|
||||
if a, ok := HashToString[alg]; ok {
|
||||
s += " " + a
|
||||
} else {
|
||||
s += " " + strconv.Itoa(int(e.AlgCode[i]))
|
||||
s += " " + strconv.Itoa(int(alg))
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
func (e *EDNS0_N3U) copy() EDNS0 { return &EDNS0_N3U{e.Code, e.AlgCode} }
|
||||
|
||||
// EDNS0_EXPIRE implementes the EDNS0 option as described in RFC 7314.
|
||||
type EDNS0_EXPIRE struct {
|
||||
Code uint16 // Always EDNS0EXPIRE
|
||||
Expire uint32
|
||||
}
|
||||
|
||||
// Option implements the EDNS0 interface.
|
||||
func (e *EDNS0_EXPIRE) Option() uint16 { return EDNS0EXPIRE }
|
||||
func (e *EDNS0_EXPIRE) String() string { return strconv.FormatUint(uint64(e.Expire), 10) }
|
||||
func (e *EDNS0_EXPIRE) copy() EDNS0 { return &EDNS0_EXPIRE{e.Code, e.Expire} }
|
||||
|
||||
func (e *EDNS0_EXPIRE) pack() ([]byte, error) {
|
||||
b := make([]byte, 4)
|
||||
b[0] = byte(e.Expire >> 24)
|
||||
b[1] = byte(e.Expire >> 16)
|
||||
b[2] = byte(e.Expire >> 8)
|
||||
b[3] = byte(e.Expire)
|
||||
binary.BigEndian.PutUint32(b, e.Expire)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
|
|
@ -462,7 +534,7 @@ func (e *EDNS0_EXPIRE) unpack(b []byte) error {
|
|||
if len(b) < 4 {
|
||||
return ErrBuf
|
||||
}
|
||||
e.Expire = uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
|
||||
e.Expire = binary.BigEndian.Uint32(b)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -484,10 +556,16 @@ type EDNS0_LOCAL struct {
|
|||
Data []byte
|
||||
}
|
||||
|
||||
// Option implements the EDNS0 interface.
|
||||
func (e *EDNS0_LOCAL) Option() uint16 { return e.Code }
|
||||
func (e *EDNS0_LOCAL) String() string {
|
||||
return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data)
|
||||
}
|
||||
func (e *EDNS0_LOCAL) copy() EDNS0 {
|
||||
b := make([]byte, len(e.Data))
|
||||
copy(b, e.Data)
|
||||
return &EDNS0_LOCAL{e.Code, b}
|
||||
}
|
||||
|
||||
func (e *EDNS0_LOCAL) pack() ([]byte, error) {
|
||||
b := make([]byte, len(e.Data))
|
||||
|
|
@ -506,3 +584,76 @@ func (e *EDNS0_LOCAL) unpack(b []byte) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// EDNS0_TCP_KEEPALIVE is an EDNS0 option that instructs the server to keep
|
||||
// the TCP connection alive. See RFC 7828.
|
||||
type EDNS0_TCP_KEEPALIVE struct {
|
||||
Code uint16 // Always EDNSTCPKEEPALIVE
|
||||
Length uint16 // the value 0 if the TIMEOUT is omitted, the value 2 if it is present;
|
||||
Timeout uint16 // an idle timeout value for the TCP connection, specified in units of 100 milliseconds, encoded in network byte order.
|
||||
}
|
||||
|
||||
// Option implements the EDNS0 interface.
|
||||
func (e *EDNS0_TCP_KEEPALIVE) Option() uint16 { return EDNS0TCPKEEPALIVE }
|
||||
|
||||
func (e *EDNS0_TCP_KEEPALIVE) pack() ([]byte, error) {
|
||||
if e.Timeout != 0 && e.Length != 2 {
|
||||
return nil, errors.New("dns: timeout specified but length is not 2")
|
||||
}
|
||||
if e.Timeout == 0 && e.Length != 0 {
|
||||
return nil, errors.New("dns: timeout not specified but length is not 0")
|
||||
}
|
||||
b := make([]byte, 4+e.Length)
|
||||
binary.BigEndian.PutUint16(b[0:], e.Code)
|
||||
binary.BigEndian.PutUint16(b[2:], e.Length)
|
||||
if e.Length == 2 {
|
||||
binary.BigEndian.PutUint16(b[4:], e.Timeout)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (e *EDNS0_TCP_KEEPALIVE) unpack(b []byte) error {
|
||||
if len(b) < 4 {
|
||||
return ErrBuf
|
||||
}
|
||||
e.Length = binary.BigEndian.Uint16(b[2:4])
|
||||
if e.Length != 0 && e.Length != 2 {
|
||||
return errors.New("dns: length mismatch, want 0/2 but got " + strconv.FormatUint(uint64(e.Length), 10))
|
||||
}
|
||||
if e.Length == 2 {
|
||||
if len(b) < 6 {
|
||||
return ErrBuf
|
||||
}
|
||||
e.Timeout = binary.BigEndian.Uint16(b[4:6])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *EDNS0_TCP_KEEPALIVE) String() (s string) {
|
||||
s = "use tcp keep-alive"
|
||||
if e.Length == 0 {
|
||||
s += ", timeout omitted"
|
||||
} else {
|
||||
s += fmt.Sprintf(", timeout %dms", e.Timeout*100)
|
||||
}
|
||||
return
|
||||
}
|
||||
func (e *EDNS0_TCP_KEEPALIVE) copy() EDNS0 { return &EDNS0_TCP_KEEPALIVE{e.Code, e.Length, e.Timeout} }
|
||||
|
||||
// EDNS0_PADDING option is used to add padding to a request/response. The default
|
||||
// value of padding SHOULD be 0x0 but other values MAY be used, for instance if
|
||||
// compression is applied before encryption which may break signatures.
|
||||
type EDNS0_PADDING struct {
|
||||
Padding []byte
|
||||
}
|
||||
|
||||
// Option implements the EDNS0 interface.
|
||||
func (e *EDNS0_PADDING) Option() uint16 { return EDNS0PADDING }
|
||||
func (e *EDNS0_PADDING) pack() ([]byte, error) { return e.Padding, nil }
|
||||
func (e *EDNS0_PADDING) unpack(b []byte) error { e.Padding = b; return nil }
|
||||
func (e *EDNS0_PADDING) String() string { return fmt.Sprintf("%0X", e.Padding) }
|
||||
func (e *EDNS0_PADDING) copy() EDNS0 {
|
||||
b := make([]byte, len(e.Padding))
|
||||
copy(b, e.Padding)
|
||||
return &EDNS0_PADDING{b}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ func Field(r RR, i int) string {
|
|||
return ""
|
||||
}
|
||||
d := reflect.ValueOf(r).Elem().Field(i)
|
||||
switch k := d.Kind(); k {
|
||||
switch d.Kind() {
|
||||
case reflect.String:
|
||||
return d.String()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
|
|
@ -31,6 +31,9 @@ func Field(r RR, i int) string {
|
|||
switch reflect.ValueOf(r).Elem().Type().Field(i).Tag {
|
||||
case `dns:"a"`:
|
||||
// TODO(miek): Hmm store this as 16 bytes
|
||||
if d.Len() < net.IPv4len {
|
||||
return ""
|
||||
}
|
||||
if d.Len() < net.IPv6len {
|
||||
return net.IPv4(byte(d.Index(0).Uint()),
|
||||
byte(d.Index(1).Uint()),
|
||||
|
|
@ -42,6 +45,9 @@ func Field(r RR, i int) string {
|
|||
byte(d.Index(14).Uint()),
|
||||
byte(d.Index(15).Uint())).String()
|
||||
case `dns:"aaaa"`:
|
||||
if d.Len() < net.IPv6len {
|
||||
return ""
|
||||
}
|
||||
return net.IP{
|
||||
byte(d.Index(0).Uint()),
|
||||
byte(d.Index(1).Uint()),
|
||||
|
|
@ -69,15 +75,6 @@ func Field(r RR, i int) string {
|
|||
s += " " + Type(d.Index(i).Uint()).String()
|
||||
}
|
||||
return s
|
||||
case `dns:"wks"`:
|
||||
if d.Len() == 0 {
|
||||
return ""
|
||||
}
|
||||
s := strconv.Itoa(int(d.Index(0).Uint()))
|
||||
for i := 0; i < d.Len(); i++ {
|
||||
s += " " + strconv.Itoa(int(d.Index(i).Uint()))
|
||||
}
|
||||
return s
|
||||
default:
|
||||
// if it does not have a tag its a string slice
|
||||
fallthrough
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
// +build fuzz
|
||||
|
||||
package dns
|
||||
|
||||
func Fuzz(data []byte) int {
|
||||
msg := new(Msg)
|
||||
|
||||
if err := msg.Unpack(data); err != nil {
|
||||
return 0
|
||||
}
|
||||
if _, err := msg.Pack(); err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
func FuzzNewRR(data []byte) int {
|
||||
if _, err := NewRR(string(data)); err != nil {
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
|
@ -0,0 +1,242 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Parse the $GENERATE statement as used in BIND9 zones.
|
||||
// See http://www.zytrax.com/books/dns/ch8/generate.html for instance.
|
||||
// We are called after '$GENERATE '. After which we expect:
|
||||
// * the range (12-24/2)
|
||||
// * lhs (ownername)
|
||||
// * [[ttl][class]]
|
||||
// * type
|
||||
// * rhs (rdata)
|
||||
// But we are lazy here, only the range is parsed *all* occurrences
|
||||
// of $ after that are interpreted.
|
||||
func (zp *ZoneParser) generate(l lex) (RR, bool) {
|
||||
token := l.token
|
||||
step := 1
|
||||
if i := strings.IndexByte(token, '/'); i >= 0 {
|
||||
if i+1 == len(token) {
|
||||
return zp.setParseError("bad step in $GENERATE range", l)
|
||||
}
|
||||
|
||||
s, err := strconv.Atoi(token[i+1:])
|
||||
if err != nil || s <= 0 {
|
||||
return zp.setParseError("bad step in $GENERATE range", l)
|
||||
}
|
||||
|
||||
step = s
|
||||
token = token[:i]
|
||||
}
|
||||
|
||||
sx := strings.SplitN(token, "-", 2)
|
||||
if len(sx) != 2 {
|
||||
return zp.setParseError("bad start-stop in $GENERATE range", l)
|
||||
}
|
||||
|
||||
start, err := strconv.Atoi(sx[0])
|
||||
if err != nil {
|
||||
return zp.setParseError("bad start in $GENERATE range", l)
|
||||
}
|
||||
|
||||
end, err := strconv.Atoi(sx[1])
|
||||
if err != nil {
|
||||
return zp.setParseError("bad stop in $GENERATE range", l)
|
||||
}
|
||||
if end < 0 || start < 0 || end < start {
|
||||
return zp.setParseError("bad range in $GENERATE range", l)
|
||||
}
|
||||
|
||||
zp.c.Next() // _BLANK
|
||||
|
||||
// Create a complete new string, which we then parse again.
|
||||
var s string
|
||||
for l, ok := zp.c.Next(); ok; l, ok = zp.c.Next() {
|
||||
if l.err {
|
||||
return zp.setParseError("bad data in $GENERATE directive", l)
|
||||
}
|
||||
if l.value == zNewline {
|
||||
break
|
||||
}
|
||||
|
||||
s += l.token
|
||||
}
|
||||
|
||||
r := &generateReader{
|
||||
s: s,
|
||||
|
||||
cur: start,
|
||||
start: start,
|
||||
end: end,
|
||||
step: step,
|
||||
|
||||
file: zp.file,
|
||||
lex: &l,
|
||||
}
|
||||
zp.sub = NewZoneParser(r, zp.origin, zp.file)
|
||||
zp.sub.includeDepth, zp.sub.includeAllowed = zp.includeDepth, zp.includeAllowed
|
||||
zp.sub.SetDefaultTTL(defaultTtl)
|
||||
return zp.subNext()
|
||||
}
|
||||
|
||||
type generateReader struct {
|
||||
s string
|
||||
si int
|
||||
|
||||
cur int
|
||||
start int
|
||||
end int
|
||||
step int
|
||||
|
||||
mod bytes.Buffer
|
||||
|
||||
escape bool
|
||||
|
||||
eof bool
|
||||
|
||||
file string
|
||||
lex *lex
|
||||
}
|
||||
|
||||
func (r *generateReader) parseError(msg string, end int) *ParseError {
|
||||
r.eof = true // Make errors sticky.
|
||||
|
||||
l := *r.lex
|
||||
l.token = r.s[r.si-1 : end]
|
||||
l.column += r.si // l.column starts one zBLANK before r.s
|
||||
|
||||
return &ParseError{r.file, msg, l}
|
||||
}
|
||||
|
||||
func (r *generateReader) Read(p []byte) (int, error) {
|
||||
// NewZLexer, through NewZoneParser, should use ReadByte and
|
||||
// not end up here.
|
||||
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (r *generateReader) ReadByte() (byte, error) {
|
||||
if r.eof {
|
||||
return 0, io.EOF
|
||||
}
|
||||
if r.mod.Len() > 0 {
|
||||
return r.mod.ReadByte()
|
||||
}
|
||||
|
||||
if r.si >= len(r.s) {
|
||||
r.si = 0
|
||||
r.cur += r.step
|
||||
|
||||
r.eof = r.cur > r.end || r.cur < 0
|
||||
return '\n', nil
|
||||
}
|
||||
|
||||
si := r.si
|
||||
r.si++
|
||||
|
||||
switch r.s[si] {
|
||||
case '\\':
|
||||
if r.escape {
|
||||
r.escape = false
|
||||
return '\\', nil
|
||||
}
|
||||
|
||||
r.escape = true
|
||||
return r.ReadByte()
|
||||
case '$':
|
||||
if r.escape {
|
||||
r.escape = false
|
||||
return '$', nil
|
||||
}
|
||||
|
||||
mod := "%d"
|
||||
|
||||
if si >= len(r.s)-1 {
|
||||
// End of the string
|
||||
fmt.Fprintf(&r.mod, mod, r.cur)
|
||||
return r.mod.ReadByte()
|
||||
}
|
||||
|
||||
if r.s[si+1] == '$' {
|
||||
r.si++
|
||||
return '$', nil
|
||||
}
|
||||
|
||||
var offset int
|
||||
|
||||
// Search for { and }
|
||||
if r.s[si+1] == '{' {
|
||||
// Modifier block
|
||||
sep := strings.Index(r.s[si+2:], "}")
|
||||
if sep < 0 {
|
||||
return 0, r.parseError("bad modifier in $GENERATE", len(r.s))
|
||||
}
|
||||
|
||||
var errMsg string
|
||||
mod, offset, errMsg = modToPrintf(r.s[si+2 : si+2+sep])
|
||||
if errMsg != "" {
|
||||
return 0, r.parseError(errMsg, si+3+sep)
|
||||
}
|
||||
if r.start+offset < 0 || r.end+offset > 1<<31-1 {
|
||||
return 0, r.parseError("bad offset in $GENERATE", si+3+sep)
|
||||
}
|
||||
|
||||
r.si += 2 + sep // Jump to it
|
||||
}
|
||||
|
||||
fmt.Fprintf(&r.mod, mod, r.cur+offset)
|
||||
return r.mod.ReadByte()
|
||||
default:
|
||||
if r.escape { // Pretty useless here
|
||||
r.escape = false
|
||||
return r.ReadByte()
|
||||
}
|
||||
|
||||
return r.s[si], nil
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a $GENERATE modifier 0,0,d to something Printf can deal with.
|
||||
func modToPrintf(s string) (string, int, string) {
|
||||
// Modifier is { offset [ ,width [ ,base ] ] } - provide default
|
||||
// values for optional width and type, if necessary.
|
||||
var offStr, widthStr, base string
|
||||
switch xs := strings.Split(s, ","); len(xs) {
|
||||
case 1:
|
||||
offStr, widthStr, base = xs[0], "0", "d"
|
||||
case 2:
|
||||
offStr, widthStr, base = xs[0], xs[1], "d"
|
||||
case 3:
|
||||
offStr, widthStr, base = xs[0], xs[1], xs[2]
|
||||
default:
|
||||
return "", 0, "bad modifier in $GENERATE"
|
||||
}
|
||||
|
||||
switch base {
|
||||
case "o", "d", "x", "X":
|
||||
default:
|
||||
return "", 0, "bad base in $GENERATE"
|
||||
}
|
||||
|
||||
offset, err := strconv.Atoi(offStr)
|
||||
if err != nil {
|
||||
return "", 0, "bad offset in $GENERATE"
|
||||
}
|
||||
|
||||
width, err := strconv.Atoi(widthStr)
|
||||
if err != nil || width < 0 || width > 255 {
|
||||
return "", 0, "bad width in $GENERATE"
|
||||
}
|
||||
|
||||
if width == 0 {
|
||||
return "%" + base, offset, ""
|
||||
}
|
||||
|
||||
return "%0" + widthStr + base, offset, ""
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ func SplitDomainName(s string) (labels []string) {
|
|||
fqdnEnd := 0 // offset of the final '.' or the length of the name
|
||||
idx := Split(s)
|
||||
begin := 0
|
||||
if s[len(s)-1] == '.' {
|
||||
if IsFqdn(s) {
|
||||
fqdnEnd = len(s) - 1
|
||||
} else {
|
||||
fqdnEnd = len(s)
|
||||
|
|
@ -28,21 +28,18 @@ func SplitDomainName(s string) (labels []string) {
|
|||
case 1:
|
||||
// no-op
|
||||
default:
|
||||
end := 0
|
||||
for i := 1; i < len(idx); i++ {
|
||||
end = idx[i]
|
||||
for _, end := range idx[1:] {
|
||||
labels = append(labels, s[begin:end-1])
|
||||
begin = end
|
||||
}
|
||||
}
|
||||
|
||||
labels = append(labels, s[begin:fqdnEnd])
|
||||
return labels
|
||||
return append(labels, s[begin:fqdnEnd])
|
||||
}
|
||||
|
||||
// CompareDomainName compares the names s1 and s2 and
|
||||
// returns how many labels they have in common starting from the *right*.
|
||||
// The comparison stops at the first inequality. The names are not downcased
|
||||
// The comparison stops at the first inequality. The names are downcased
|
||||
// before the comparison.
|
||||
//
|
||||
// www.miek.nl. and miek.nl. have two labels in common: miek and nl
|
||||
|
|
@ -50,23 +47,21 @@ func SplitDomainName(s string) (labels []string) {
|
|||
//
|
||||
// s1 and s2 must be syntactically valid domain names.
|
||||
func CompareDomainName(s1, s2 string) (n int) {
|
||||
s1 = Fqdn(s1)
|
||||
s2 = Fqdn(s2)
|
||||
// the first check: root label
|
||||
if s1 == "." || s2 == "." {
|
||||
return 0
|
||||
}
|
||||
|
||||
l1 := Split(s1)
|
||||
l2 := Split(s2)
|
||||
|
||||
// the first check: root label
|
||||
if l1 == nil || l2 == nil {
|
||||
return
|
||||
}
|
||||
|
||||
j1 := len(l1) - 1 // end
|
||||
i1 := len(l1) - 2 // start
|
||||
j2 := len(l2) - 1
|
||||
i2 := len(l2) - 2
|
||||
// the second check can be done here: last/only label
|
||||
// before we fall through into the for-loop below
|
||||
if s1[l1[j1]:] == s2[l2[j2]:] {
|
||||
if equal(s1[l1[j1]:], s2[l2[j2]:]) {
|
||||
n++
|
||||
} else {
|
||||
return
|
||||
|
|
@ -75,7 +70,7 @@ func CompareDomainName(s1, s2 string) (n int) {
|
|||
if i1 < 0 || i2 < 0 {
|
||||
break
|
||||
}
|
||||
if s1[l1[i1]:l1[j1]] == s2[l2[i2]:l2[j2]] {
|
||||
if equal(s1[l1[i1]:l1[j1]], s2[l2[i2]:l2[j2]]) {
|
||||
n++
|
||||
} else {
|
||||
break
|
||||
|
|
@ -107,7 +102,7 @@ func CountLabel(s string) (labels int) {
|
|||
|
||||
// Split splits a name s into its label indexes.
|
||||
// www.miek.nl. returns []int{0, 4, 9}, www.miek.nl also returns []int{0, 4, 9}.
|
||||
// The root name (.) returns nil. Also see SplitDomainName.
|
||||
// The root name (.) returns nil. Also see SplitDomainName.
|
||||
// s must be a syntactically valid domain name.
|
||||
func Split(s string) []int {
|
||||
if s == "." {
|
||||
|
|
@ -166,3 +161,28 @@ func PrevLabel(s string, n int) (i int, start bool) {
|
|||
}
|
||||
return lab[len(lab)-n], false
|
||||
}
|
||||
|
||||
// equal compares a and b while ignoring case. It returns true when equal otherwise false.
|
||||
func equal(a, b string) bool {
|
||||
// might be lifted into API function.
|
||||
la := len(a)
|
||||
lb := len(b)
|
||||
if la != lb {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := la - 1; i >= 0; i-- {
|
||||
ai := a[i]
|
||||
bi := b[i]
|
||||
if ai >= 'A' && ai <= 'Z' {
|
||||
ai |= 'a' - 'A'
|
||||
}
|
||||
if bi >= 'A' && bi <= 'Z' {
|
||||
bi |= 'a' - 'A'
|
||||
}
|
||||
if ai != bi {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
// +build go1.11
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd
|
||||
|
||||
package dns
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const supportsReusePort = true
|
||||
|
||||
func reuseportControl(network, address string, c syscall.RawConn) error {
|
||||
var opErr error
|
||||
err := c.Control(func(fd uintptr) {
|
||||
opErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return opErr
|
||||
}
|
||||
|
||||
func listenTCP(network, addr string, reuseport bool) (net.Listener, error) {
|
||||
var lc net.ListenConfig
|
||||
if reuseport {
|
||||
lc.Control = reuseportControl
|
||||
}
|
||||
|
||||
return lc.Listen(context.Background(), network, addr)
|
||||
}
|
||||
|
||||
func listenUDP(network, addr string, reuseport bool) (net.PacketConn, error) {
|
||||
var lc net.ListenConfig
|
||||
if reuseport {
|
||||
lc.Control = reuseportControl
|
||||
}
|
||||
|
||||
return lc.ListenPacket(context.Background(), network, addr)
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// +build !go1.11 !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd
|
||||
|
||||
package dns
|
||||
|
||||
import "net"
|
||||
|
||||
const supportsReusePort = false
|
||||
|
||||
func listenTCP(network, addr string, reuseport bool) (net.Listener, error) {
|
||||
if reuseport {
|
||||
// TODO(tmthrgd): return an error?
|
||||
}
|
||||
|
||||
return net.Listen(network, addr)
|
||||
}
|
||||
|
||||
func listenUDP(network, addr string, reuseport bool) (net.PacketConn, error) {
|
||||
if reuseport {
|
||||
// TODO(tmthrgd): return an error?
|
||||
}
|
||||
|
||||
return net.ListenPacket(network, addr)
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,328 @@
|
|||
//+build ignore
|
||||
|
||||
// msg_generate.go is meant to run with go generate. It will use
|
||||
// go/{importer,types} to track down all the RR struct types. Then for each type
|
||||
// it will generate pack/unpack methods based on the struct tags. The generated source is
|
||||
// written to zmsg.go, and is meant to be checked into git.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"go/importer"
|
||||
"go/types"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var packageHdr = `
|
||||
// Code generated by "go run msg_generate.go"; DO NOT EDIT.
|
||||
|
||||
package dns
|
||||
|
||||
`
|
||||
|
||||
// getTypeStruct will take a type and the package scope, and return the
|
||||
// (innermost) struct if the type is considered a RR type (currently defined as
|
||||
// those structs beginning with a RR_Header, could be redefined as implementing
|
||||
// the RR interface). The bool return value indicates if embedded structs were
|
||||
// resolved.
|
||||
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
|
||||
st, ok := t.Underlying().(*types.Struct)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
|
||||
return st, false
|
||||
}
|
||||
if st.Field(0).Anonymous() {
|
||||
st, _ := getTypeStruct(st.Field(0).Type(), scope)
|
||||
return st, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Import and type-check the package
|
||||
pkg, err := importer.Default().Import("github.com/miekg/dns")
|
||||
fatalIfErr(err)
|
||||
scope := pkg.Scope()
|
||||
|
||||
// Collect actual types (*X)
|
||||
var namedTypes []string
|
||||
for _, name := range scope.Names() {
|
||||
o := scope.Lookup(name)
|
||||
if o == nil || !o.Exported() {
|
||||
continue
|
||||
}
|
||||
if st, _ := getTypeStruct(o.Type(), scope); st == nil {
|
||||
continue
|
||||
}
|
||||
if name == "PrivateRR" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if corresponding TypeX exists
|
||||
if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
|
||||
log.Fatalf("Constant Type%s does not exist.", o.Name())
|
||||
}
|
||||
|
||||
namedTypes = append(namedTypes, o.Name())
|
||||
}
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
b.WriteString(packageHdr)
|
||||
|
||||
fmt.Fprint(b, "// pack*() functions\n\n")
|
||||
for _, name := range namedTypes {
|
||||
o := scope.Lookup(name)
|
||||
st, _ := getTypeStruct(o.Type(), scope)
|
||||
|
||||
fmt.Fprintf(b, "func (rr *%s) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {\n", name)
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
o := func(s string) {
|
||||
fmt.Fprintf(b, s, st.Field(i).Name())
|
||||
fmt.Fprint(b, `if err != nil {
|
||||
return off, err
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||
switch st.Tag(i) {
|
||||
case `dns:"-"`: // ignored
|
||||
case `dns:"txt"`:
|
||||
o("off, err = packStringTxt(rr.%s, msg, off)\n")
|
||||
case `dns:"opt"`:
|
||||
o("off, err = packDataOpt(rr.%s, msg, off)\n")
|
||||
case `dns:"nsec"`:
|
||||
o("off, err = packDataNsec(rr.%s, msg, off)\n")
|
||||
case `dns:"domain-name"`:
|
||||
o("off, err = packDataDomainNames(rr.%s, msg, off, compression, false)\n")
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case st.Tag(i) == `dns:"-"`: // ignored
|
||||
case st.Tag(i) == `dns:"cdomain-name"`:
|
||||
o("off, err = packDomainName(rr.%s, msg, off, compression, compress)\n")
|
||||
case st.Tag(i) == `dns:"domain-name"`:
|
||||
o("off, err = packDomainName(rr.%s, msg, off, compression, false)\n")
|
||||
case st.Tag(i) == `dns:"a"`:
|
||||
o("off, err = packDataA(rr.%s, msg, off)\n")
|
||||
case st.Tag(i) == `dns:"aaaa"`:
|
||||
o("off, err = packDataAAAA(rr.%s, msg, off)\n")
|
||||
case st.Tag(i) == `dns:"uint48"`:
|
||||
o("off, err = packUint48(rr.%s, msg, off)\n")
|
||||
case st.Tag(i) == `dns:"txt"`:
|
||||
o("off, err = packString(rr.%s, msg, off)\n")
|
||||
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-base32`): // size-base32 can be packed just like base32
|
||||
fallthrough
|
||||
case st.Tag(i) == `dns:"base32"`:
|
||||
o("off, err = packStringBase32(rr.%s, msg, off)\n")
|
||||
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-base64`): // size-base64 can be packed just like base64
|
||||
fallthrough
|
||||
case st.Tag(i) == `dns:"base64"`:
|
||||
o("off, err = packStringBase64(rr.%s, msg, off)\n")
|
||||
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex:SaltLength`):
|
||||
// directly write instead of using o() so we get the error check in the correct place
|
||||
field := st.Field(i).Name()
|
||||
fmt.Fprintf(b, `// Only pack salt if value is not "-", i.e. empty
|
||||
if rr.%s != "-" {
|
||||
off, err = packStringHex(rr.%s, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
}
|
||||
`, field, field)
|
||||
continue
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`): // size-hex can be packed just like hex
|
||||
fallthrough
|
||||
case st.Tag(i) == `dns:"hex"`:
|
||||
o("off, err = packStringHex(rr.%s, msg, off)\n")
|
||||
case st.Tag(i) == `dns:"any"`:
|
||||
o("off, err = packStringAny(rr.%s, msg, off)\n")
|
||||
case st.Tag(i) == `dns:"octet"`:
|
||||
o("off, err = packStringOctet(rr.%s, msg, off)\n")
|
||||
case st.Tag(i) == "":
|
||||
switch st.Field(i).Type().(*types.Basic).Kind() {
|
||||
case types.Uint8:
|
||||
o("off, err = packUint8(rr.%s, msg, off)\n")
|
||||
case types.Uint16:
|
||||
o("off, err = packUint16(rr.%s, msg, off)\n")
|
||||
case types.Uint32:
|
||||
o("off, err = packUint32(rr.%s, msg, off)\n")
|
||||
case types.Uint64:
|
||||
o("off, err = packUint64(rr.%s, msg, off)\n")
|
||||
case types.String:
|
||||
o("off, err = packString(rr.%s, msg, off)\n")
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name())
|
||||
}
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(b, "return off, nil }\n")
|
||||
}
|
||||
|
||||
fmt.Fprint(b, "// unpack*() functions\n\n")
|
||||
for _, name := range namedTypes {
|
||||
o := scope.Lookup(name)
|
||||
st, _ := getTypeStruct(o.Type(), scope)
|
||||
|
||||
fmt.Fprintf(b, "func (rr *%s) unpack(msg []byte, off int) (off1 int, err error) {\n", name)
|
||||
fmt.Fprint(b, `rdStart := off
|
||||
_ = rdStart
|
||||
|
||||
`)
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
o := func(s string) {
|
||||
fmt.Fprintf(b, s, st.Field(i).Name())
|
||||
fmt.Fprint(b, `if err != nil {
|
||||
return off, err
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
// size-* are special, because they reference a struct member we should use for the length.
|
||||
if strings.HasPrefix(st.Tag(i), `dns:"size-`) {
|
||||
structMember := structMember(st.Tag(i))
|
||||
structTag := structTag(st.Tag(i))
|
||||
switch structTag {
|
||||
case "hex":
|
||||
fmt.Fprintf(b, "rr.%s, off, err = unpackStringHex(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
|
||||
case "base32":
|
||||
fmt.Fprintf(b, "rr.%s, off, err = unpackStringBase32(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
|
||||
case "base64":
|
||||
fmt.Fprintf(b, "rr.%s, off, err = unpackStringBase64(msg, off, off + int(rr.%s))\n", st.Field(i).Name(), structMember)
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
fmt.Fprint(b, `if err != nil {
|
||||
return off, err
|
||||
}
|
||||
`)
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||
switch st.Tag(i) {
|
||||
case `dns:"-"`: // ignored
|
||||
case `dns:"txt"`:
|
||||
o("rr.%s, off, err = unpackStringTxt(msg, off)\n")
|
||||
case `dns:"opt"`:
|
||||
o("rr.%s, off, err = unpackDataOpt(msg, off)\n")
|
||||
case `dns:"nsec"`:
|
||||
o("rr.%s, off, err = unpackDataNsec(msg, off)\n")
|
||||
case `dns:"domain-name"`:
|
||||
o("rr.%s, off, err = unpackDataDomainNames(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
switch st.Tag(i) {
|
||||
case `dns:"-"`: // ignored
|
||||
case `dns:"cdomain-name"`:
|
||||
fallthrough
|
||||
case `dns:"domain-name"`:
|
||||
o("rr.%s, off, err = UnpackDomainName(msg, off)\n")
|
||||
case `dns:"a"`:
|
||||
o("rr.%s, off, err = unpackDataA(msg, off)\n")
|
||||
case `dns:"aaaa"`:
|
||||
o("rr.%s, off, err = unpackDataAAAA(msg, off)\n")
|
||||
case `dns:"uint48"`:
|
||||
o("rr.%s, off, err = unpackUint48(msg, off)\n")
|
||||
case `dns:"txt"`:
|
||||
o("rr.%s, off, err = unpackString(msg, off)\n")
|
||||
case `dns:"base32"`:
|
||||
o("rr.%s, off, err = unpackStringBase32(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
||||
case `dns:"base64"`:
|
||||
o("rr.%s, off, err = unpackStringBase64(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
||||
case `dns:"hex"`:
|
||||
o("rr.%s, off, err = unpackStringHex(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
||||
case `dns:"any"`:
|
||||
o("rr.%s, off, err = unpackStringAny(msg, off, rdStart + int(rr.Hdr.Rdlength))\n")
|
||||
case `dns:"octet"`:
|
||||
o("rr.%s, off, err = unpackStringOctet(msg, off)\n")
|
||||
case "":
|
||||
switch st.Field(i).Type().(*types.Basic).Kind() {
|
||||
case types.Uint8:
|
||||
o("rr.%s, off, err = unpackUint8(msg, off)\n")
|
||||
case types.Uint16:
|
||||
o("rr.%s, off, err = unpackUint16(msg, off)\n")
|
||||
case types.Uint32:
|
||||
o("rr.%s, off, err = unpackUint32(msg, off)\n")
|
||||
case types.Uint64:
|
||||
o("rr.%s, off, err = unpackUint64(msg, off)\n")
|
||||
case types.String:
|
||||
o("rr.%s, off, err = unpackString(msg, off)\n")
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name())
|
||||
}
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
}
|
||||
// If we've hit len(msg) we return without error.
|
||||
if i < st.NumFields()-1 {
|
||||
fmt.Fprintf(b, `if off == len(msg) {
|
||||
return off, nil
|
||||
}
|
||||
`)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(b, "return off, nil }\n\n")
|
||||
}
|
||||
|
||||
// gofmt
|
||||
res, err := format.Source(b.Bytes())
|
||||
if err != nil {
|
||||
b.WriteTo(os.Stderr)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// write result
|
||||
f, err := os.Create("zmsg.go")
|
||||
fatalIfErr(err)
|
||||
defer f.Close()
|
||||
f.Write(res)
|
||||
}
|
||||
|
||||
// structMember will take a tag like dns:"size-base32:SaltLength" and return the last part of this string.
|
||||
func structMember(s string) string {
|
||||
fields := strings.Split(s, ":")
|
||||
if len(fields) == 0 {
|
||||
return ""
|
||||
}
|
||||
f := fields[len(fields)-1]
|
||||
// f should have a closing "
|
||||
if len(f) > 1 {
|
||||
return f[:len(f)-1]
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// structTag will take a tag like dns:"size-base32:SaltLength" and return base32.
|
||||
func structTag(s string) string {
|
||||
fields := strings.Split(s, ":")
|
||||
if len(fields) < 2 {
|
||||
return ""
|
||||
}
|
||||
return fields[1][len("\"size-"):]
|
||||
}
|
||||
|
||||
func fatalIfErr(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,648 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"encoding/base32"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// helper functions called from the generated zmsg.go
|
||||
|
||||
// These function are named after the tag to help pack/unpack, if there is no tag it is the name
|
||||
// of the type they pack/unpack (string, int, etc). We prefix all with unpackData or packData, so packDataA or
|
||||
// packDataDomainName.
|
||||
|
||||
func unpackDataA(msg []byte, off int) (net.IP, int, error) {
|
||||
if off+net.IPv4len > len(msg) {
|
||||
return nil, len(msg), &Error{err: "overflow unpacking a"}
|
||||
}
|
||||
a := append(make(net.IP, 0, net.IPv4len), msg[off:off+net.IPv4len]...)
|
||||
off += net.IPv4len
|
||||
return a, off, nil
|
||||
}
|
||||
|
||||
func packDataA(a net.IP, msg []byte, off int) (int, error) {
|
||||
switch len(a) {
|
||||
case net.IPv4len, net.IPv6len:
|
||||
// It must be a slice of 4, even if it is 16, we encode only the first 4
|
||||
if off+net.IPv4len > len(msg) {
|
||||
return len(msg), &Error{err: "overflow packing a"}
|
||||
}
|
||||
|
||||
copy(msg[off:], a.To4())
|
||||
off += net.IPv4len
|
||||
case 0:
|
||||
// Allowed, for dynamic updates.
|
||||
default:
|
||||
return len(msg), &Error{err: "overflow packing a"}
|
||||
}
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func unpackDataAAAA(msg []byte, off int) (net.IP, int, error) {
|
||||
if off+net.IPv6len > len(msg) {
|
||||
return nil, len(msg), &Error{err: "overflow unpacking aaaa"}
|
||||
}
|
||||
aaaa := append(make(net.IP, 0, net.IPv6len), msg[off:off+net.IPv6len]...)
|
||||
off += net.IPv6len
|
||||
return aaaa, off, nil
|
||||
}
|
||||
|
||||
func packDataAAAA(aaaa net.IP, msg []byte, off int) (int, error) {
|
||||
switch len(aaaa) {
|
||||
case net.IPv6len:
|
||||
if off+net.IPv6len > len(msg) {
|
||||
return len(msg), &Error{err: "overflow packing aaaa"}
|
||||
}
|
||||
|
||||
copy(msg[off:], aaaa)
|
||||
off += net.IPv6len
|
||||
case 0:
|
||||
// Allowed, dynamic updates.
|
||||
default:
|
||||
return len(msg), &Error{err: "overflow packing aaaa"}
|
||||
}
|
||||
return off, nil
|
||||
}
|
||||
|
||||
// unpackHeader unpacks an RR header, returning the offset to the end of the header and a
|
||||
// re-sliced msg according to the expected length of the RR.
|
||||
func unpackHeader(msg []byte, off int) (rr RR_Header, off1 int, truncmsg []byte, err error) {
|
||||
hdr := RR_Header{}
|
||||
if off == len(msg) {
|
||||
return hdr, off, msg, nil
|
||||
}
|
||||
|
||||
hdr.Name, off, err = UnpackDomainName(msg, off)
|
||||
if err != nil {
|
||||
return hdr, len(msg), msg, err
|
||||
}
|
||||
hdr.Rrtype, off, err = unpackUint16(msg, off)
|
||||
if err != nil {
|
||||
return hdr, len(msg), msg, err
|
||||
}
|
||||
hdr.Class, off, err = unpackUint16(msg, off)
|
||||
if err != nil {
|
||||
return hdr, len(msg), msg, err
|
||||
}
|
||||
hdr.Ttl, off, err = unpackUint32(msg, off)
|
||||
if err != nil {
|
||||
return hdr, len(msg), msg, err
|
||||
}
|
||||
hdr.Rdlength, off, err = unpackUint16(msg, off)
|
||||
if err != nil {
|
||||
return hdr, len(msg), msg, err
|
||||
}
|
||||
msg, err = truncateMsgFromRdlength(msg, off, hdr.Rdlength)
|
||||
return hdr, off, msg, err
|
||||
}
|
||||
|
||||
// packHeader packs an RR header, returning the offset to the end of the header.
|
||||
// See PackDomainName for documentation about the compression.
|
||||
func (hdr RR_Header) packHeader(msg []byte, off int, compression compressionMap, compress bool) (int, error) {
|
||||
if off == len(msg) {
|
||||
return off, nil
|
||||
}
|
||||
|
||||
off, err := packDomainName(hdr.Name, msg, off, compression, compress)
|
||||
if err != nil {
|
||||
return len(msg), err
|
||||
}
|
||||
off, err = packUint16(hdr.Rrtype, msg, off)
|
||||
if err != nil {
|
||||
return len(msg), err
|
||||
}
|
||||
off, err = packUint16(hdr.Class, msg, off)
|
||||
if err != nil {
|
||||
return len(msg), err
|
||||
}
|
||||
off, err = packUint32(hdr.Ttl, msg, off)
|
||||
if err != nil {
|
||||
return len(msg), err
|
||||
}
|
||||
off, err = packUint16(0, msg, off) // The RDLENGTH field will be set later in packRR.
|
||||
if err != nil {
|
||||
return len(msg), err
|
||||
}
|
||||
return off, nil
|
||||
}
|
||||
|
||||
// helper helper functions.
|
||||
|
||||
// truncateMsgFromRdLength truncates msg to match the expected length of the RR.
|
||||
// Returns an error if msg is smaller than the expected size.
|
||||
func truncateMsgFromRdlength(msg []byte, off int, rdlength uint16) (truncmsg []byte, err error) {
|
||||
lenrd := off + int(rdlength)
|
||||
if lenrd > len(msg) {
|
||||
return msg, &Error{err: "overflowing header size"}
|
||||
}
|
||||
return msg[:lenrd], nil
|
||||
}
|
||||
|
||||
var base32HexNoPadEncoding = base32.HexEncoding.WithPadding(base32.NoPadding)
|
||||
|
||||
func fromBase32(s []byte) (buf []byte, err error) {
|
||||
for i, b := range s {
|
||||
if b >= 'a' && b <= 'z' {
|
||||
s[i] = b - 32
|
||||
}
|
||||
}
|
||||
buflen := base32HexNoPadEncoding.DecodedLen(len(s))
|
||||
buf = make([]byte, buflen)
|
||||
n, err := base32HexNoPadEncoding.Decode(buf, s)
|
||||
buf = buf[:n]
|
||||
return
|
||||
}
|
||||
|
||||
func toBase32(b []byte) string {
|
||||
return base32HexNoPadEncoding.EncodeToString(b)
|
||||
}
|
||||
|
||||
func fromBase64(s []byte) (buf []byte, err error) {
|
||||
buflen := base64.StdEncoding.DecodedLen(len(s))
|
||||
buf = make([]byte, buflen)
|
||||
n, err := base64.StdEncoding.Decode(buf, s)
|
||||
buf = buf[:n]
|
||||
return
|
||||
}
|
||||
|
||||
func toBase64(b []byte) string { return base64.StdEncoding.EncodeToString(b) }
|
||||
|
||||
// dynamicUpdate returns true if the Rdlength is zero.
|
||||
func noRdata(h RR_Header) bool { return h.Rdlength == 0 }
|
||||
|
||||
func unpackUint8(msg []byte, off int) (i uint8, off1 int, err error) {
|
||||
if off+1 > len(msg) {
|
||||
return 0, len(msg), &Error{err: "overflow unpacking uint8"}
|
||||
}
|
||||
return msg[off], off + 1, nil
|
||||
}
|
||||
|
||||
func packUint8(i uint8, msg []byte, off int) (off1 int, err error) {
|
||||
if off+1 > len(msg) {
|
||||
return len(msg), &Error{err: "overflow packing uint8"}
|
||||
}
|
||||
msg[off] = i
|
||||
return off + 1, nil
|
||||
}
|
||||
|
||||
func unpackUint16(msg []byte, off int) (i uint16, off1 int, err error) {
|
||||
if off+2 > len(msg) {
|
||||
return 0, len(msg), &Error{err: "overflow unpacking uint16"}
|
||||
}
|
||||
return binary.BigEndian.Uint16(msg[off:]), off + 2, nil
|
||||
}
|
||||
|
||||
func packUint16(i uint16, msg []byte, off int) (off1 int, err error) {
|
||||
if off+2 > len(msg) {
|
||||
return len(msg), &Error{err: "overflow packing uint16"}
|
||||
}
|
||||
binary.BigEndian.PutUint16(msg[off:], i)
|
||||
return off + 2, nil
|
||||
}
|
||||
|
||||
func unpackUint32(msg []byte, off int) (i uint32, off1 int, err error) {
|
||||
if off+4 > len(msg) {
|
||||
return 0, len(msg), &Error{err: "overflow unpacking uint32"}
|
||||
}
|
||||
return binary.BigEndian.Uint32(msg[off:]), off + 4, nil
|
||||
}
|
||||
|
||||
func packUint32(i uint32, msg []byte, off int) (off1 int, err error) {
|
||||
if off+4 > len(msg) {
|
||||
return len(msg), &Error{err: "overflow packing uint32"}
|
||||
}
|
||||
binary.BigEndian.PutUint32(msg[off:], i)
|
||||
return off + 4, nil
|
||||
}
|
||||
|
||||
func unpackUint48(msg []byte, off int) (i uint64, off1 int, err error) {
|
||||
if off+6 > len(msg) {
|
||||
return 0, len(msg), &Error{err: "overflow unpacking uint64 as uint48"}
|
||||
}
|
||||
// Used in TSIG where the last 48 bits are occupied, so for now, assume a uint48 (6 bytes)
|
||||
i = uint64(msg[off])<<40 | uint64(msg[off+1])<<32 | uint64(msg[off+2])<<24 | uint64(msg[off+3])<<16 |
|
||||
uint64(msg[off+4])<<8 | uint64(msg[off+5])
|
||||
off += 6
|
||||
return i, off, nil
|
||||
}
|
||||
|
||||
func packUint48(i uint64, msg []byte, off int) (off1 int, err error) {
|
||||
if off+6 > len(msg) {
|
||||
return len(msg), &Error{err: "overflow packing uint64 as uint48"}
|
||||
}
|
||||
msg[off] = byte(i >> 40)
|
||||
msg[off+1] = byte(i >> 32)
|
||||
msg[off+2] = byte(i >> 24)
|
||||
msg[off+3] = byte(i >> 16)
|
||||
msg[off+4] = byte(i >> 8)
|
||||
msg[off+5] = byte(i)
|
||||
off += 6
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func unpackUint64(msg []byte, off int) (i uint64, off1 int, err error) {
|
||||
if off+8 > len(msg) {
|
||||
return 0, len(msg), &Error{err: "overflow unpacking uint64"}
|
||||
}
|
||||
return binary.BigEndian.Uint64(msg[off:]), off + 8, nil
|
||||
}
|
||||
|
||||
func packUint64(i uint64, msg []byte, off int) (off1 int, err error) {
|
||||
if off+8 > len(msg) {
|
||||
return len(msg), &Error{err: "overflow packing uint64"}
|
||||
}
|
||||
binary.BigEndian.PutUint64(msg[off:], i)
|
||||
off += 8
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func unpackString(msg []byte, off int) (string, int, error) {
|
||||
if off+1 > len(msg) {
|
||||
return "", off, &Error{err: "overflow unpacking txt"}
|
||||
}
|
||||
l := int(msg[off])
|
||||
if off+l+1 > len(msg) {
|
||||
return "", off, &Error{err: "overflow unpacking txt"}
|
||||
}
|
||||
var s strings.Builder
|
||||
s.Grow(l)
|
||||
for _, b := range msg[off+1 : off+1+l] {
|
||||
switch {
|
||||
case b == '"' || b == '\\':
|
||||
s.WriteByte('\\')
|
||||
s.WriteByte(b)
|
||||
case b < ' ' || b > '~': // unprintable
|
||||
s.WriteString(escapeByte(b))
|
||||
default:
|
||||
s.WriteByte(b)
|
||||
}
|
||||
}
|
||||
off += 1 + l
|
||||
return s.String(), off, nil
|
||||
}
|
||||
|
||||
func packString(s string, msg []byte, off int) (int, error) {
|
||||
txtTmp := make([]byte, 256*4+1)
|
||||
off, err := packTxtString(s, msg, off, txtTmp)
|
||||
if err != nil {
|
||||
return len(msg), err
|
||||
}
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func unpackStringBase32(msg []byte, off, end int) (string, int, error) {
|
||||
if end > len(msg) {
|
||||
return "", len(msg), &Error{err: "overflow unpacking base32"}
|
||||
}
|
||||
s := toBase32(msg[off:end])
|
||||
return s, end, nil
|
||||
}
|
||||
|
||||
func packStringBase32(s string, msg []byte, off int) (int, error) {
|
||||
b32, err := fromBase32([]byte(s))
|
||||
if err != nil {
|
||||
return len(msg), err
|
||||
}
|
||||
if off+len(b32) > len(msg) {
|
||||
return len(msg), &Error{err: "overflow packing base32"}
|
||||
}
|
||||
copy(msg[off:off+len(b32)], b32)
|
||||
off += len(b32)
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func unpackStringBase64(msg []byte, off, end int) (string, int, error) {
|
||||
// Rest of the RR is base64 encoded value, so we don't need an explicit length
|
||||
// to be set. Thus far all RR's that have base64 encoded fields have those as their
|
||||
// last one. What we do need is the end of the RR!
|
||||
if end > len(msg) {
|
||||
return "", len(msg), &Error{err: "overflow unpacking base64"}
|
||||
}
|
||||
s := toBase64(msg[off:end])
|
||||
return s, end, nil
|
||||
}
|
||||
|
||||
func packStringBase64(s string, msg []byte, off int) (int, error) {
|
||||
b64, err := fromBase64([]byte(s))
|
||||
if err != nil {
|
||||
return len(msg), err
|
||||
}
|
||||
if off+len(b64) > len(msg) {
|
||||
return len(msg), &Error{err: "overflow packing base64"}
|
||||
}
|
||||
copy(msg[off:off+len(b64)], b64)
|
||||
off += len(b64)
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func unpackStringHex(msg []byte, off, end int) (string, int, error) {
|
||||
// Rest of the RR is hex encoded value, so we don't need an explicit length
|
||||
// to be set. NSEC and TSIG have hex fields with a length field.
|
||||
// What we do need is the end of the RR!
|
||||
if end > len(msg) {
|
||||
return "", len(msg), &Error{err: "overflow unpacking hex"}
|
||||
}
|
||||
|
||||
s := hex.EncodeToString(msg[off:end])
|
||||
return s, end, nil
|
||||
}
|
||||
|
||||
func packStringHex(s string, msg []byte, off int) (int, error) {
|
||||
h, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
return len(msg), err
|
||||
}
|
||||
if off+len(h) > len(msg) {
|
||||
return len(msg), &Error{err: "overflow packing hex"}
|
||||
}
|
||||
copy(msg[off:off+len(h)], h)
|
||||
off += len(h)
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func unpackStringAny(msg []byte, off, end int) (string, int, error) {
|
||||
if end > len(msg) {
|
||||
return "", len(msg), &Error{err: "overflow unpacking anything"}
|
||||
}
|
||||
return string(msg[off:end]), end, nil
|
||||
}
|
||||
|
||||
func packStringAny(s string, msg []byte, off int) (int, error) {
|
||||
if off+len(s) > len(msg) {
|
||||
return len(msg), &Error{err: "overflow packing anything"}
|
||||
}
|
||||
copy(msg[off:off+len(s)], s)
|
||||
off += len(s)
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func unpackStringTxt(msg []byte, off int) ([]string, int, error) {
|
||||
txt, off, err := unpackTxt(msg, off)
|
||||
if err != nil {
|
||||
return nil, len(msg), err
|
||||
}
|
||||
return txt, off, nil
|
||||
}
|
||||
|
||||
func packStringTxt(s []string, msg []byte, off int) (int, error) {
|
||||
txtTmp := make([]byte, 256*4+1) // If the whole string consists out of \DDD we need this many.
|
||||
off, err := packTxt(s, msg, off, txtTmp)
|
||||
if err != nil {
|
||||
return len(msg), err
|
||||
}
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func unpackDataOpt(msg []byte, off int) ([]EDNS0, int, error) {
|
||||
var edns []EDNS0
|
||||
Option:
|
||||
var code uint16
|
||||
if off+4 > len(msg) {
|
||||
return nil, len(msg), &Error{err: "overflow unpacking opt"}
|
||||
}
|
||||
code = binary.BigEndian.Uint16(msg[off:])
|
||||
off += 2
|
||||
optlen := binary.BigEndian.Uint16(msg[off:])
|
||||
off += 2
|
||||
if off+int(optlen) > len(msg) {
|
||||
return nil, len(msg), &Error{err: "overflow unpacking opt"}
|
||||
}
|
||||
switch code {
|
||||
case EDNS0NSID:
|
||||
e := new(EDNS0_NSID)
|
||||
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
|
||||
return nil, len(msg), err
|
||||
}
|
||||
edns = append(edns, e)
|
||||
off += int(optlen)
|
||||
case EDNS0SUBNET:
|
||||
e := new(EDNS0_SUBNET)
|
||||
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
|
||||
return nil, len(msg), err
|
||||
}
|
||||
edns = append(edns, e)
|
||||
off += int(optlen)
|
||||
case EDNS0COOKIE:
|
||||
e := new(EDNS0_COOKIE)
|
||||
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
|
||||
return nil, len(msg), err
|
||||
}
|
||||
edns = append(edns, e)
|
||||
off += int(optlen)
|
||||
case EDNS0UL:
|
||||
e := new(EDNS0_UL)
|
||||
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
|
||||
return nil, len(msg), err
|
||||
}
|
||||
edns = append(edns, e)
|
||||
off += int(optlen)
|
||||
case EDNS0LLQ:
|
||||
e := new(EDNS0_LLQ)
|
||||
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
|
||||
return nil, len(msg), err
|
||||
}
|
||||
edns = append(edns, e)
|
||||
off += int(optlen)
|
||||
case EDNS0DAU:
|
||||
e := new(EDNS0_DAU)
|
||||
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
|
||||
return nil, len(msg), err
|
||||
}
|
||||
edns = append(edns, e)
|
||||
off += int(optlen)
|
||||
case EDNS0DHU:
|
||||
e := new(EDNS0_DHU)
|
||||
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
|
||||
return nil, len(msg), err
|
||||
}
|
||||
edns = append(edns, e)
|
||||
off += int(optlen)
|
||||
case EDNS0N3U:
|
||||
e := new(EDNS0_N3U)
|
||||
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
|
||||
return nil, len(msg), err
|
||||
}
|
||||
edns = append(edns, e)
|
||||
off += int(optlen)
|
||||
case EDNS0PADDING:
|
||||
e := new(EDNS0_PADDING)
|
||||
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
|
||||
return nil, len(msg), err
|
||||
}
|
||||
edns = append(edns, e)
|
||||
off += int(optlen)
|
||||
default:
|
||||
e := new(EDNS0_LOCAL)
|
||||
e.Code = code
|
||||
if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
|
||||
return nil, len(msg), err
|
||||
}
|
||||
edns = append(edns, e)
|
||||
off += int(optlen)
|
||||
}
|
||||
|
||||
if off < len(msg) {
|
||||
goto Option
|
||||
}
|
||||
|
||||
return edns, off, nil
|
||||
}
|
||||
|
||||
func packDataOpt(options []EDNS0, msg []byte, off int) (int, error) {
|
||||
for _, el := range options {
|
||||
b, err := el.pack()
|
||||
if err != nil || off+3 > len(msg) {
|
||||
return len(msg), &Error{err: "overflow packing opt"}
|
||||
}
|
||||
binary.BigEndian.PutUint16(msg[off:], el.Option()) // Option code
|
||||
binary.BigEndian.PutUint16(msg[off+2:], uint16(len(b))) // Length
|
||||
off += 4
|
||||
if off+len(b) > len(msg) {
|
||||
copy(msg[off:], b)
|
||||
off = len(msg)
|
||||
continue
|
||||
}
|
||||
// Actual data
|
||||
copy(msg[off:off+len(b)], b)
|
||||
off += len(b)
|
||||
}
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func unpackStringOctet(msg []byte, off int) (string, int, error) {
|
||||
s := string(msg[off:])
|
||||
return s, len(msg), nil
|
||||
}
|
||||
|
||||
func packStringOctet(s string, msg []byte, off int) (int, error) {
|
||||
txtTmp := make([]byte, 256*4+1)
|
||||
off, err := packOctetString(s, msg, off, txtTmp)
|
||||
if err != nil {
|
||||
return len(msg), err
|
||||
}
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) {
|
||||
var nsec []uint16
|
||||
length, window, lastwindow := 0, 0, -1
|
||||
for off < len(msg) {
|
||||
if off+2 > len(msg) {
|
||||
return nsec, len(msg), &Error{err: "overflow unpacking nsecx"}
|
||||
}
|
||||
window = int(msg[off])
|
||||
length = int(msg[off+1])
|
||||
off += 2
|
||||
if window <= lastwindow {
|
||||
// RFC 4034: Blocks are present in the NSEC RR RDATA in
|
||||
// increasing numerical order.
|
||||
return nsec, len(msg), &Error{err: "out of order NSEC block"}
|
||||
}
|
||||
if length == 0 {
|
||||
// RFC 4034: Blocks with no types present MUST NOT be included.
|
||||
return nsec, len(msg), &Error{err: "empty NSEC block"}
|
||||
}
|
||||
if length > 32 {
|
||||
return nsec, len(msg), &Error{err: "NSEC block too long"}
|
||||
}
|
||||
if off+length > len(msg) {
|
||||
return nsec, len(msg), &Error{err: "overflowing NSEC block"}
|
||||
}
|
||||
|
||||
// Walk the bytes in the window and extract the type bits
|
||||
for j, b := range msg[off : off+length] {
|
||||
// Check the bits one by one, and set the type
|
||||
if b&0x80 == 0x80 {
|
||||
nsec = append(nsec, uint16(window*256+j*8+0))
|
||||
}
|
||||
if b&0x40 == 0x40 {
|
||||
nsec = append(nsec, uint16(window*256+j*8+1))
|
||||
}
|
||||
if b&0x20 == 0x20 {
|
||||
nsec = append(nsec, uint16(window*256+j*8+2))
|
||||
}
|
||||
if b&0x10 == 0x10 {
|
||||
nsec = append(nsec, uint16(window*256+j*8+3))
|
||||
}
|
||||
if b&0x8 == 0x8 {
|
||||
nsec = append(nsec, uint16(window*256+j*8+4))
|
||||
}
|
||||
if b&0x4 == 0x4 {
|
||||
nsec = append(nsec, uint16(window*256+j*8+5))
|
||||
}
|
||||
if b&0x2 == 0x2 {
|
||||
nsec = append(nsec, uint16(window*256+j*8+6))
|
||||
}
|
||||
if b&0x1 == 0x1 {
|
||||
nsec = append(nsec, uint16(window*256+j*8+7))
|
||||
}
|
||||
}
|
||||
off += length
|
||||
lastwindow = window
|
||||
}
|
||||
return nsec, off, nil
|
||||
}
|
||||
|
||||
func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
|
||||
if len(bitmap) == 0 {
|
||||
return off, nil
|
||||
}
|
||||
var lastwindow, lastlength uint16
|
||||
for _, t := range bitmap {
|
||||
window := t / 256
|
||||
length := (t-window*256)/8 + 1
|
||||
if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
|
||||
off += int(lastlength) + 2
|
||||
lastlength = 0
|
||||
}
|
||||
if window < lastwindow || length < lastlength {
|
||||
return len(msg), &Error{err: "nsec bits out of order"}
|
||||
}
|
||||
if off+2+int(length) > len(msg) {
|
||||
return len(msg), &Error{err: "overflow packing nsec"}
|
||||
}
|
||||
// Setting the window #
|
||||
msg[off] = byte(window)
|
||||
// Setting the octets length
|
||||
msg[off+1] = byte(length)
|
||||
// Setting the bit value for the type in the right octet
|
||||
msg[off+1+int(length)] |= byte(1 << (7 - t%8))
|
||||
lastwindow, lastlength = window, length
|
||||
}
|
||||
off += int(lastlength) + 2
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) {
|
||||
var (
|
||||
servers []string
|
||||
s string
|
||||
err error
|
||||
)
|
||||
if end > len(msg) {
|
||||
return nil, len(msg), &Error{err: "overflow unpacking domain names"}
|
||||
}
|
||||
for off < end {
|
||||
s, off, err = UnpackDomainName(msg, off)
|
||||
if err != nil {
|
||||
return servers, len(msg), err
|
||||
}
|
||||
servers = append(servers, s)
|
||||
}
|
||||
return servers, off, nil
|
||||
}
|
||||
|
||||
func packDataDomainNames(names []string, msg []byte, off int, compression compressionMap, compress bool) (int, error) {
|
||||
var err error
|
||||
for _, name := range names {
|
||||
off, err = packDomainName(name, msg, off, compression, compress)
|
||||
if err != nil {
|
||||
return len(msg), err
|
||||
}
|
||||
}
|
||||
return off, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
package dns
|
||||
|
||||
// Truncate ensures the reply message will fit into the requested buffer
|
||||
// size by removing records that exceed the requested size.
|
||||
//
|
||||
// It will first check if the reply fits without compression and then with
|
||||
// compression. If it won't fit with compression, Scrub then walks the
|
||||
// record adding as many records as possible without exceeding the
|
||||
// requested buffer size.
|
||||
//
|
||||
// The TC bit will be set if any answer records were excluded from the
|
||||
// message. This indicates to that the client should retry over TCP.
|
||||
//
|
||||
// The appropriate buffer size can be retrieved from the requests OPT
|
||||
// record, if present, and is transport specific otherwise. dns.MinMsgSize
|
||||
// should be used for UDP requests without an OPT record, and
|
||||
// dns.MaxMsgSize for TCP requests without an OPT record.
|
||||
func (dns *Msg) Truncate(size int) {
|
||||
if dns.IsTsig() != nil {
|
||||
// To simplify this implementation, we don't perform
|
||||
// truncation on responses with a TSIG record.
|
||||
return
|
||||
}
|
||||
|
||||
// RFC 6891 mandates that the payload size in an OPT record
|
||||
// less than 512 bytes must be treated as equal to 512 bytes.
|
||||
//
|
||||
// For ease of use, we impose that restriction here.
|
||||
if size < 512 {
|
||||
size = 512
|
||||
}
|
||||
|
||||
l := msgLenWithCompressionMap(dns, nil) // uncompressed length
|
||||
if l <= size {
|
||||
// Don't waste effort compressing this message.
|
||||
dns.Compress = false
|
||||
return
|
||||
}
|
||||
|
||||
dns.Compress = true
|
||||
|
||||
edns0 := dns.popEdns0()
|
||||
if edns0 != nil {
|
||||
// Account for the OPT record that gets added at the end,
|
||||
// by subtracting that length from our budget.
|
||||
//
|
||||
// The EDNS(0) OPT record must have the root domain and
|
||||
// it's length is thus unaffected by compression.
|
||||
size -= Len(edns0)
|
||||
}
|
||||
|
||||
compression := make(map[string]struct{})
|
||||
|
||||
l = headerSize
|
||||
for _, r := range dns.Question {
|
||||
l += r.len(l, compression)
|
||||
}
|
||||
|
||||
var numAnswer int
|
||||
if l < size {
|
||||
l, numAnswer = truncateLoop(dns.Answer, size, l, compression)
|
||||
}
|
||||
|
||||
var numNS int
|
||||
if l < size {
|
||||
l, numNS = truncateLoop(dns.Ns, size, l, compression)
|
||||
}
|
||||
|
||||
var numExtra int
|
||||
if l < size {
|
||||
l, numExtra = truncateLoop(dns.Extra, size, l, compression)
|
||||
}
|
||||
|
||||
// According to RFC 2181, the TC bit should only be set if not all
|
||||
// of the answer RRs can be included in the response.
|
||||
dns.Truncated = len(dns.Answer) > numAnswer
|
||||
|
||||
dns.Answer = dns.Answer[:numAnswer]
|
||||
dns.Ns = dns.Ns[:numNS]
|
||||
dns.Extra = dns.Extra[:numExtra]
|
||||
|
||||
if edns0 != nil {
|
||||
// Add the OPT record back onto the additional section.
|
||||
dns.Extra = append(dns.Extra, edns0)
|
||||
}
|
||||
}
|
||||
|
||||
func truncateLoop(rrs []RR, size, l int, compression map[string]struct{}) (int, int) {
|
||||
for i, r := range rrs {
|
||||
if r == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
l += r.len(l, compression)
|
||||
if l > size {
|
||||
// Return size, rather than l prior to this record,
|
||||
// to prevent any further records being added.
|
||||
return size, i
|
||||
}
|
||||
if l == size {
|
||||
return l, i + 1
|
||||
}
|
||||
}
|
||||
|
||||
return l, len(rrs)
|
||||
}
|
||||
|
|
@ -2,110 +2,93 @@ package dns
|
|||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"hash"
|
||||
"io"
|
||||
"encoding/hex"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type saltWireFmt struct {
|
||||
Salt string `dns:"size-hex"`
|
||||
}
|
||||
|
||||
// HashName hashes a string (label) according to RFC 5155. It returns the hashed string in
|
||||
// uppercase.
|
||||
// HashName hashes a string (label) according to RFC 5155. It returns the hashed string in uppercase.
|
||||
func HashName(label string, ha uint8, iter uint16, salt string) string {
|
||||
saltwire := new(saltWireFmt)
|
||||
saltwire.Salt = salt
|
||||
wire := make([]byte, DefaultMsgSize)
|
||||
n, err := PackStruct(saltwire, wire, 0)
|
||||
if ha != SHA1 {
|
||||
return ""
|
||||
}
|
||||
|
||||
wireSalt := make([]byte, hex.DecodedLen(len(salt)))
|
||||
n, err := packStringHex(salt, wireSalt, 0)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
wire = wire[:n]
|
||||
wireSalt = wireSalt[:n]
|
||||
|
||||
name := make([]byte, 255)
|
||||
off, err := PackDomainName(strings.ToLower(label), name, 0, nil, false)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
name = name[:off]
|
||||
var s hash.Hash
|
||||
switch ha {
|
||||
case SHA1:
|
||||
s = sha1.New()
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
||||
s := sha1.New()
|
||||
// k = 0
|
||||
name = append(name, wire...)
|
||||
io.WriteString(s, string(name))
|
||||
s.Write(name)
|
||||
s.Write(wireSalt)
|
||||
nsec3 := s.Sum(nil)
|
||||
|
||||
// k > 0
|
||||
for k := uint16(0); k < iter; k++ {
|
||||
s.Reset()
|
||||
nsec3 = append(nsec3, wire...)
|
||||
io.WriteString(s, string(nsec3))
|
||||
nsec3 = s.Sum(nil)
|
||||
s.Write(nsec3)
|
||||
s.Write(wireSalt)
|
||||
nsec3 = s.Sum(nsec3[:0])
|
||||
}
|
||||
|
||||
return toBase32(nsec3)
|
||||
}
|
||||
|
||||
// Denialer is an interface that should be implemented by types that are used to denial
|
||||
// answers in DNSSEC.
|
||||
type Denialer interface {
|
||||
// Cover will check if the (unhashed) name is being covered by this NSEC or NSEC3.
|
||||
Cover(name string) bool
|
||||
// Match will check if the ownername matches the (unhashed) name for this NSEC3 or NSEC3.
|
||||
Match(name string) bool
|
||||
}
|
||||
|
||||
// Cover implements the Denialer interface.
|
||||
func (rr *NSEC) Cover(name string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Match implements the Denialer interface.
|
||||
func (rr *NSEC) Match(name string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Cover implements the Denialer interface.
|
||||
// Cover returns true if a name is covered by the NSEC3 record
|
||||
func (rr *NSEC3) Cover(name string) bool {
|
||||
// FIXME(miek): check if the zones match
|
||||
// FIXME(miek): check if we're not dealing with parent nsec3
|
||||
hname := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
|
||||
labels := Split(rr.Hdr.Name)
|
||||
if len(labels) < 2 {
|
||||
nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
|
||||
owner := strings.ToUpper(rr.Hdr.Name)
|
||||
labelIndices := Split(owner)
|
||||
if len(labelIndices) < 2 {
|
||||
return false
|
||||
}
|
||||
hash := strings.ToUpper(rr.Hdr.Name[labels[0] : labels[1]-1]) // -1 to remove the dot
|
||||
if hash == rr.NextDomain {
|
||||
return false // empty interval
|
||||
}
|
||||
if hash > rr.NextDomain { // last name, points to apex
|
||||
// hname > hash
|
||||
// hname > rr.NextDomain
|
||||
// TODO(miek)
|
||||
}
|
||||
if hname <= hash {
|
||||
ownerHash := owner[:labelIndices[1]-1]
|
||||
ownerZone := owner[labelIndices[1]:]
|
||||
if !IsSubDomain(ownerZone, strings.ToUpper(name)) { // name is outside owner zone
|
||||
return false
|
||||
}
|
||||
if hname >= rr.NextDomain {
|
||||
|
||||
nextHash := rr.NextDomain
|
||||
|
||||
// if empty interval found, try cover wildcard hashes so nameHash shouldn't match with ownerHash
|
||||
if ownerHash == nextHash && nameHash != ownerHash { // empty interval
|
||||
return true
|
||||
}
|
||||
if ownerHash > nextHash { // end of zone
|
||||
if nameHash > ownerHash { // covered since there is nothing after ownerHash
|
||||
return true
|
||||
}
|
||||
return nameHash < nextHash // if nameHash is before beginning of zone it is covered
|
||||
}
|
||||
if nameHash < ownerHash { // nameHash is before ownerHash, not covered
|
||||
return false
|
||||
}
|
||||
return true
|
||||
return nameHash < nextHash // if nameHash is before nextHash is it covered (between ownerHash and nextHash)
|
||||
}
|
||||
|
||||
// Match implements the Denialer interface.
|
||||
// Match returns true if a name matches the NSEC3 record
|
||||
func (rr *NSEC3) Match(name string) bool {
|
||||
// FIXME(miek): Check if we are in the same zone
|
||||
hname := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
|
||||
labels := Split(rr.Hdr.Name)
|
||||
if len(labels) < 2 {
|
||||
nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt)
|
||||
owner := strings.ToUpper(rr.Hdr.Name)
|
||||
labelIndices := Split(owner)
|
||||
if len(labelIndices) < 2 {
|
||||
return false
|
||||
}
|
||||
hash := strings.ToUpper(rr.Hdr.Name[labels[0] : labels[1]-1]) // -1 to remove the .
|
||||
if hash == hname {
|
||||
ownerHash := owner[:labelIndices[1]-1]
|
||||
ownerZone := owner[labelIndices[1]:]
|
||||
if !IsSubDomain(ownerZone, strings.ToUpper(name)) { // name is outside owner zone
|
||||
return false
|
||||
}
|
||||
if ownerHash == nameHash {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -39,11 +39,12 @@ func mkPrivateRR(rrtype uint16) *PrivateRR {
|
|||
}
|
||||
|
||||
anyrr := rrfunc()
|
||||
switch rr := anyrr.(type) {
|
||||
case *PrivateRR:
|
||||
return rr
|
||||
rr, ok := anyrr.(*PrivateRR)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("dns: RR is not a PrivateRR, TypeToRR[%d] generator returned %T", rrtype, anyrr))
|
||||
}
|
||||
panic(fmt.Sprintf("dns: RR is not a PrivateRR, TypeToRR[%d] generator returned %T", rrtype, anyrr))
|
||||
|
||||
return rr
|
||||
}
|
||||
|
||||
// Header return the RR header of r.
|
||||
|
|
@ -52,12 +53,16 @@ func (r *PrivateRR) Header() *RR_Header { return &r.Hdr }
|
|||
func (r *PrivateRR) String() string { return r.Hdr.String() + r.Data.String() }
|
||||
|
||||
// Private len and copy parts to satisfy RR interface.
|
||||
func (r *PrivateRR) len() int { return r.Hdr.len() + r.Data.Len() }
|
||||
func (r *PrivateRR) len(off int, compression map[string]struct{}) int {
|
||||
l := r.Hdr.len(off, compression)
|
||||
l += r.Data.Len()
|
||||
return l
|
||||
}
|
||||
|
||||
func (r *PrivateRR) copy() RR {
|
||||
// make new RR like this:
|
||||
rr := mkPrivateRR(r.Hdr.Rrtype)
|
||||
newh := r.Hdr.copyHeader()
|
||||
rr.Hdr = *newh
|
||||
rr.Hdr = r.Hdr
|
||||
|
||||
err := r.Data.Copy(rr.Data)
|
||||
if err != nil {
|
||||
|
|
@ -66,6 +71,46 @@ func (r *PrivateRR) copy() RR {
|
|||
return rr
|
||||
}
|
||||
|
||||
func (r *PrivateRR) pack(msg []byte, off int, compression compressionMap, compress bool) (int, error) {
|
||||
n, err := r.Data.Pack(msg[off:])
|
||||
if err != nil {
|
||||
return len(msg), err
|
||||
}
|
||||
off += n
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func (r *PrivateRR) unpack(msg []byte, off int) (int, error) {
|
||||
off1, err := r.Data.Unpack(msg[off:])
|
||||
off += off1
|
||||
return off, err
|
||||
}
|
||||
|
||||
func (r *PrivateRR) parse(c *zlexer, origin, file string) *ParseError {
|
||||
var l lex
|
||||
text := make([]string, 0, 2) // could be 0..N elements, median is probably 1
|
||||
Fetch:
|
||||
for {
|
||||
// TODO(miek): we could also be returning _QUOTE, this might or might not
|
||||
// be an issue (basically parsing TXT becomes hard)
|
||||
switch l, _ = c.Next(); l.value {
|
||||
case zNewline, zEOF:
|
||||
break Fetch
|
||||
case zString:
|
||||
text = append(text, l.token)
|
||||
}
|
||||
}
|
||||
|
||||
err := r.Data.Parse(text)
|
||||
if err != nil {
|
||||
return &ParseError{file, err.Error(), l}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r1 *PrivateRR) isDuplicate(r2 RR) bool { return false }
|
||||
|
||||
// PrivateHandle registers a private resource record type. It requires
|
||||
// string and numeric representation of private RR type and generator function as argument.
|
||||
func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) {
|
||||
|
|
@ -74,44 +119,14 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata)
|
|||
TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator()} }
|
||||
TypeToString[rtype] = rtypestr
|
||||
StringToType[rtypestr] = rtype
|
||||
|
||||
setPrivateRR := func(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
|
||||
rr := mkPrivateRR(h.Rrtype)
|
||||
rr.Hdr = h
|
||||
|
||||
var l lex
|
||||
text := make([]string, 0, 2) // could be 0..N elements, median is probably 1
|
||||
FETCH:
|
||||
for {
|
||||
// TODO(miek): we could also be returning _QUOTE, this might or might not
|
||||
// be an issue (basically parsing TXT becomes hard)
|
||||
switch l = <-c; l.value {
|
||||
case zNewline, zEOF:
|
||||
break FETCH
|
||||
case zString:
|
||||
text = append(text, l.token)
|
||||
}
|
||||
}
|
||||
|
||||
err := rr.Data.Parse(text)
|
||||
if err != nil {
|
||||
return nil, &ParseError{f, err.Error(), l}, ""
|
||||
}
|
||||
|
||||
return rr, nil, ""
|
||||
}
|
||||
|
||||
typeToparserFunc[rtype] = parserFunc{setPrivateRR, true}
|
||||
}
|
||||
|
||||
// PrivateHandleRemove removes defenitions required to support private RR type.
|
||||
// PrivateHandleRemove removes definitions required to support private RR type.
|
||||
func PrivateHandleRemove(rtype uint16) {
|
||||
rtypestr, ok := TypeToString[rtype]
|
||||
if ok {
|
||||
delete(TypeToRR, rtype)
|
||||
delete(TypeToString, rtype)
|
||||
delete(typeToparserFunc, rtype)
|
||||
delete(StringToType, rtypestr)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,95 +0,0 @@
|
|||
package dns
|
||||
|
||||
// These raw* functions do not use reflection, they directly set the values
|
||||
// in the buffer. There are faster than their reflection counterparts.
|
||||
|
||||
// RawSetId sets the message id in buf.
|
||||
func rawSetId(msg []byte, i uint16) bool {
|
||||
if len(msg) < 2 {
|
||||
return false
|
||||
}
|
||||
msg[0], msg[1] = packUint16(i)
|
||||
return true
|
||||
}
|
||||
|
||||
// rawSetQuestionLen sets the length of the question section.
|
||||
func rawSetQuestionLen(msg []byte, i uint16) bool {
|
||||
if len(msg) < 6 {
|
||||
return false
|
||||
}
|
||||
msg[4], msg[5] = packUint16(i)
|
||||
return true
|
||||
}
|
||||
|
||||
// rawSetAnswerLen sets the length of the answer section.
|
||||
func rawSetAnswerLen(msg []byte, i uint16) bool {
|
||||
if len(msg) < 8 {
|
||||
return false
|
||||
}
|
||||
msg[6], msg[7] = packUint16(i)
|
||||
return true
|
||||
}
|
||||
|
||||
// rawSetsNsLen sets the length of the authority section.
|
||||
func rawSetNsLen(msg []byte, i uint16) bool {
|
||||
if len(msg) < 10 {
|
||||
return false
|
||||
}
|
||||
msg[8], msg[9] = packUint16(i)
|
||||
return true
|
||||
}
|
||||
|
||||
// rawSetExtraLen sets the length of the additional section.
|
||||
func rawSetExtraLen(msg []byte, i uint16) bool {
|
||||
if len(msg) < 12 {
|
||||
return false
|
||||
}
|
||||
msg[10], msg[11] = packUint16(i)
|
||||
return true
|
||||
}
|
||||
|
||||
// rawSetRdlength sets the rdlength in the header of
|
||||
// the RR. The offset 'off' must be positioned at the
|
||||
// start of the header of the RR, 'end' must be the
|
||||
// end of the RR.
|
||||
func rawSetRdlength(msg []byte, off, end int) bool {
|
||||
l := len(msg)
|
||||
Loop:
|
||||
for {
|
||||
if off+1 > l {
|
||||
return false
|
||||
}
|
||||
c := int(msg[off])
|
||||
off++
|
||||
switch c & 0xC0 {
|
||||
case 0x00:
|
||||
if c == 0x00 {
|
||||
// End of the domainname
|
||||
break Loop
|
||||
}
|
||||
if off+c > l {
|
||||
return false
|
||||
}
|
||||
off += c
|
||||
|
||||
case 0xC0:
|
||||
// pointer, next byte included, ends domainname
|
||||
off++
|
||||
break Loop
|
||||
}
|
||||
}
|
||||
// The domainname has been seen, we at the start of the fixed part in the header.
|
||||
// Type is 2 bytes, class is 2 bytes, ttl 4 and then 2 bytes for the length.
|
||||
off += 2 + 2 + 4
|
||||
if off+2 > l {
|
||||
return false
|
||||
}
|
||||
//off+1 is the end of the header, 'end' is the end of the rr
|
||||
//so 'end' - 'off+2' is the length of the rdata
|
||||
rdatalen := end - (off + 2)
|
||||
if rdatalen > 0xFFFF {
|
||||
return false
|
||||
}
|
||||
msg[off], msg[off+1] = packUint16(uint16(rdatalen))
|
||||
return true
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package dns
|
||||
|
||||
// StringToType is the reverse of TypeToString, needed for string parsing.
|
||||
var StringToType = reverseInt16(TypeToString)
|
||||
|
||||
// StringToClass is the reverse of ClassToString, needed for string parsing.
|
||||
var StringToClass = reverseInt16(ClassToString)
|
||||
|
||||
// StringToOpcode is a map of opcodes to strings.
|
||||
var StringToOpcode = reverseInt(OpcodeToString)
|
||||
|
||||
// StringToRcode is a map of rcodes to strings.
|
||||
var StringToRcode = reverseInt(RcodeToString)
|
||||
|
||||
func init() {
|
||||
// Preserve previous NOTIMP typo, see github.com/miekg/dns/issues/733.
|
||||
StringToRcode["NOTIMPL"] = RcodeNotImplemented
|
||||
}
|
||||
|
||||
// StringToAlgorithm is the reverse of AlgorithmToString.
|
||||
var StringToAlgorithm = reverseInt8(AlgorithmToString)
|
||||
|
||||
// StringToHash is a map of names to hash IDs.
|
||||
var StringToHash = reverseInt8(HashToString)
|
||||
|
||||
// StringToCertType is the reverseof CertTypeToString.
|
||||
var StringToCertType = reverseInt16(CertTypeToString)
|
||||
|
||||
// Reverse a map
|
||||
func reverseInt8(m map[uint8]string) map[string]uint8 {
|
||||
n := make(map[string]uint8, len(m))
|
||||
for u, s := range m {
|
||||
n[s] = u
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func reverseInt16(m map[uint16]string) map[string]uint16 {
|
||||
n := make(map[string]uint16, len(m))
|
||||
for u, s := range m {
|
||||
n[s] = u
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func reverseInt(m map[int]string) map[string]int {
|
||||
n := make(map[string]int, len(m))
|
||||
for u, s := range m {
|
||||
n[s] = u
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
|
@ -3,8 +3,9 @@ package dns
|
|||
// Dedup removes identical RRs from rrs. It preserves the original ordering.
|
||||
// The lowest TTL of any duplicates is used in the remaining one. Dedup modifies
|
||||
// rrs.
|
||||
// m is used to store the RRs temporay. If it is nil a new map will be allocated.
|
||||
// m is used to store the RRs temporary. If it is nil a new map will be allocated.
|
||||
func Dedup(rrs []RR, m map[string]RR) []RR {
|
||||
|
||||
if m == nil {
|
||||
m = make(map[string]RR)
|
||||
}
|
||||
|
|
@ -14,10 +15,11 @@ func Dedup(rrs []RR, m map[string]RR) []RR {
|
|||
for _, r := range rrs {
|
||||
key := normalizedString(r)
|
||||
keys = append(keys, &key)
|
||||
if _, ok := m[key]; ok {
|
||||
if mr, ok := m[key]; ok {
|
||||
// Shortest TTL wins.
|
||||
if m[key].Header().Ttl > r.Header().Ttl {
|
||||
m[key].Header().Ttl = r.Header().Ttl
|
||||
rh, mrh := r.Header(), mr.Header()
|
||||
if mrh.Ttl > rh.Ttl {
|
||||
mrh.Ttl = rh.Ttl
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,43 +0,0 @@
|
|||
package dns
|
||||
|
||||
// Implement a simple scanner, return a byte stream from an io reader.
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"text/scanner"
|
||||
)
|
||||
|
||||
type scan struct {
|
||||
src *bufio.Reader
|
||||
position scanner.Position
|
||||
eof bool // Have we just seen a eof
|
||||
}
|
||||
|
||||
func scanInit(r io.Reader) *scan {
|
||||
s := new(scan)
|
||||
s.src = bufio.NewReader(r)
|
||||
s.position.Line = 1
|
||||
return s
|
||||
}
|
||||
|
||||
// tokenText returns the next byte from the input
|
||||
func (s *scan) tokenText() (byte, error) {
|
||||
c, err := s.src.ReadByte()
|
||||
if err != nil {
|
||||
return c, err
|
||||
}
|
||||
// delay the newline handling until the next token is delivered,
|
||||
// fixes off-by-one errors when reporting a parse error.
|
||||
if s.eof == true {
|
||||
s.position.Line++
|
||||
s.position.Column = 0
|
||||
s.eof = false
|
||||
}
|
||||
if c == '\n' {
|
||||
s.eof = true
|
||||
return c, nil
|
||||
}
|
||||
s.position.Column++
|
||||
return c, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// ServeMux is an DNS request multiplexer. It matches the zone name of
|
||||
// each incoming request against a list of registered patterns add calls
|
||||
// the handler for the pattern that most closely matches the zone name.
|
||||
//
|
||||
// ServeMux is DNSSEC aware, meaning that queries for the DS record are
|
||||
// redirected to the parent zone (if that is also registered), otherwise
|
||||
// the child gets the query.
|
||||
//
|
||||
// ServeMux is also safe for concurrent access from multiple goroutines.
|
||||
//
|
||||
// The zero ServeMux is empty and ready for use.
|
||||
type ServeMux struct {
|
||||
z map[string]Handler
|
||||
m sync.RWMutex
|
||||
}
|
||||
|
||||
// NewServeMux allocates and returns a new ServeMux.
|
||||
func NewServeMux() *ServeMux {
|
||||
return new(ServeMux)
|
||||
}
|
||||
|
||||
// DefaultServeMux is the default ServeMux used by Serve.
|
||||
var DefaultServeMux = NewServeMux()
|
||||
|
||||
func (mux *ServeMux) match(q string, t uint16) Handler {
|
||||
mux.m.RLock()
|
||||
defer mux.m.RUnlock()
|
||||
if mux.z == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var handler Handler
|
||||
|
||||
// TODO(tmthrgd): Once https://go-review.googlesource.com/c/go/+/137575
|
||||
// lands in a go release, replace the following with strings.ToLower.
|
||||
var sb strings.Builder
|
||||
for i := 0; i < len(q); i++ {
|
||||
c := q[i]
|
||||
if !(c >= 'A' && c <= 'Z') {
|
||||
continue
|
||||
}
|
||||
|
||||
sb.Grow(len(q))
|
||||
sb.WriteString(q[:i])
|
||||
|
||||
for ; i < len(q); i++ {
|
||||
c := q[i]
|
||||
if c >= 'A' && c <= 'Z' {
|
||||
c += 'a' - 'A'
|
||||
}
|
||||
|
||||
sb.WriteByte(c)
|
||||
}
|
||||
|
||||
q = sb.String()
|
||||
break
|
||||
}
|
||||
|
||||
for off, end := 0, false; !end; off, end = NextLabel(q, off) {
|
||||
if h, ok := mux.z[q[off:]]; ok {
|
||||
if t != TypeDS {
|
||||
return h
|
||||
}
|
||||
// Continue for DS to see if we have a parent too, if so delegate to the parent
|
||||
handler = h
|
||||
}
|
||||
}
|
||||
|
||||
// Wildcard match, if we have found nothing try the root zone as a last resort.
|
||||
if h, ok := mux.z["."]; ok {
|
||||
return h
|
||||
}
|
||||
|
||||
return handler
|
||||
}
|
||||
|
||||
// Handle adds a handler to the ServeMux for pattern.
|
||||
func (mux *ServeMux) Handle(pattern string, handler Handler) {
|
||||
if pattern == "" {
|
||||
panic("dns: invalid pattern " + pattern)
|
||||
}
|
||||
mux.m.Lock()
|
||||
if mux.z == nil {
|
||||
mux.z = make(map[string]Handler)
|
||||
}
|
||||
mux.z[Fqdn(pattern)] = handler
|
||||
mux.m.Unlock()
|
||||
}
|
||||
|
||||
// HandleFunc adds a handler function to the ServeMux for pattern.
|
||||
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
|
||||
mux.Handle(pattern, HandlerFunc(handler))
|
||||
}
|
||||
|
||||
// HandleRemove deregisters the handler specific for pattern from the ServeMux.
|
||||
func (mux *ServeMux) HandleRemove(pattern string) {
|
||||
if pattern == "" {
|
||||
panic("dns: invalid pattern " + pattern)
|
||||
}
|
||||
mux.m.Lock()
|
||||
delete(mux.z, Fqdn(pattern))
|
||||
mux.m.Unlock()
|
||||
}
|
||||
|
||||
// ServeDNS dispatches the request to the handler whose pattern most
|
||||
// closely matches the request message.
|
||||
//
|
||||
// ServeDNS is DNSSEC aware, meaning that queries for the DS record
|
||||
// are redirected to the parent zone (if that is also registered),
|
||||
// otherwise the child gets the query.
|
||||
//
|
||||
// If no handler is found, or there is no question, a standard SERVFAIL
|
||||
// message is returned
|
||||
func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) {
|
||||
var h Handler
|
||||
if len(req.Question) >= 1 { // allow more than one question
|
||||
h = mux.match(req.Question[0].Name, req.Question[0].Qtype)
|
||||
}
|
||||
|
||||
if h != nil {
|
||||
h.ServeDNS(w, req)
|
||||
} else {
|
||||
HandleFailed(w, req)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle registers the handler with the given pattern
|
||||
// in the DefaultServeMux. The documentation for
|
||||
// ServeMux explains how patterns are matched.
|
||||
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
|
||||
|
||||
// HandleRemove deregisters the handle with the given pattern
|
||||
// in the DefaultServeMux.
|
||||
func HandleRemove(pattern string) { DefaultServeMux.HandleRemove(pattern) }
|
||||
|
||||
// HandleFunc registers the handler function with the given pattern
|
||||
// in the DefaultServeMux.
|
||||
func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
|
||||
DefaultServeMux.HandleFunc(pattern, handler)
|
||||
}
|
||||
|
|
@ -3,22 +3,40 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Maximum number of TCP queries before we close the socket.
|
||||
// Default maximum number of TCP queries before we close the socket.
|
||||
const maxTCPQueries = 128
|
||||
|
||||
// aLongTimeAgo is a non-zero time, far in the past, used for
|
||||
// immediate cancelation of network operations.
|
||||
var aLongTimeAgo = time.Unix(1, 0)
|
||||
|
||||
// Handler is implemented by any value that implements ServeDNS.
|
||||
type Handler interface {
|
||||
ServeDNS(w ResponseWriter, r *Msg)
|
||||
}
|
||||
|
||||
// The HandlerFunc type is an adapter to allow the use of
|
||||
// ordinary functions as DNS handlers. If f is a function
|
||||
// with the appropriate signature, HandlerFunc(f) is a
|
||||
// Handler object that calls f.
|
||||
type HandlerFunc func(ResponseWriter, *Msg)
|
||||
|
||||
// ServeDNS calls f(w, r).
|
||||
func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg) {
|
||||
f(w, r)
|
||||
}
|
||||
|
||||
// A ResponseWriter interface is used by an DNS handler to
|
||||
// construct an DNS response.
|
||||
type ResponseWriter interface {
|
||||
|
|
@ -41,48 +59,25 @@ type ResponseWriter interface {
|
|||
Hijack()
|
||||
}
|
||||
|
||||
// A ConnectionStater interface is used by a DNS Handler to access TLS connection state
|
||||
// when available.
|
||||
type ConnectionStater interface {
|
||||
ConnectionState() *tls.ConnectionState
|
||||
}
|
||||
|
||||
type response struct {
|
||||
closed bool // connection has been closed
|
||||
hijacked bool // connection has been hijacked by handler
|
||||
tsigStatus error
|
||||
tsigTimersOnly bool
|
||||
tsigStatus error
|
||||
tsigRequestMAC string
|
||||
tsigSecret map[string]string // the tsig secrets
|
||||
udp *net.UDPConn // i/o connection if UDP was used
|
||||
tcp net.Conn // i/o connection if TCP was used
|
||||
udpSession *SessionUDP // oob data to get egress interface right
|
||||
remoteAddr net.Addr // address of the client
|
||||
writer Writer // writer to output the raw DNS bits
|
||||
}
|
||||
|
||||
// ServeMux is an DNS request multiplexer. It matches the
|
||||
// zone name of each incoming request against a list of
|
||||
// registered patterns add calls the handler for the pattern
|
||||
// that most closely matches the zone name. ServeMux is DNSSEC aware, meaning
|
||||
// that queries for the DS record are redirected to the parent zone (if that
|
||||
// is also registered), otherwise the child gets the query.
|
||||
// ServeMux is also safe for concurrent access from multiple goroutines.
|
||||
type ServeMux struct {
|
||||
z map[string]Handler
|
||||
m *sync.RWMutex
|
||||
}
|
||||
|
||||
// NewServeMux allocates and returns a new ServeMux.
|
||||
func NewServeMux() *ServeMux { return &ServeMux{z: make(map[string]Handler), m: new(sync.RWMutex)} }
|
||||
|
||||
// DefaultServeMux is the default ServeMux used by Serve.
|
||||
var DefaultServeMux = NewServeMux()
|
||||
|
||||
// The HandlerFunc type is an adapter to allow the use of
|
||||
// ordinary functions as DNS handlers. If f is a function
|
||||
// with the appropriate signature, HandlerFunc(f) is a
|
||||
// Handler object that calls f.
|
||||
type HandlerFunc func(ResponseWriter, *Msg)
|
||||
|
||||
// ServeDNS calls f(w, r).
|
||||
func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg) {
|
||||
f(w, r)
|
||||
}
|
||||
|
||||
// HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets.
|
||||
func HandleFailed(w ResponseWriter, r *Msg) {
|
||||
m := new(Msg)
|
||||
|
|
@ -91,8 +86,6 @@ func HandleFailed(w ResponseWriter, r *Msg) {
|
|||
w.WriteMsg(m)
|
||||
}
|
||||
|
||||
func failedHandler() Handler { return HandlerFunc(HandleFailed) }
|
||||
|
||||
// ListenAndServe Starts a server on address and network specified Invoke handler
|
||||
// for incoming queries.
|
||||
func ListenAndServe(addr string, network string, handler Handler) error {
|
||||
|
|
@ -131,99 +124,6 @@ func ActivateAndServe(l net.Listener, p net.PacketConn, handler Handler) error {
|
|||
return server.ActivateAndServe()
|
||||
}
|
||||
|
||||
func (mux *ServeMux) match(q string, t uint16) Handler {
|
||||
mux.m.RLock()
|
||||
defer mux.m.RUnlock()
|
||||
var handler Handler
|
||||
b := make([]byte, len(q)) // worst case, one label of length q
|
||||
off := 0
|
||||
end := false
|
||||
for {
|
||||
l := len(q[off:])
|
||||
for i := 0; i < l; i++ {
|
||||
b[i] = q[off+i]
|
||||
if b[i] >= 'A' && b[i] <= 'Z' {
|
||||
b[i] |= ('a' - 'A')
|
||||
}
|
||||
}
|
||||
if h, ok := mux.z[string(b[:l])]; ok { // 'causes garbage, might want to change the map key
|
||||
if t != TypeDS {
|
||||
return h
|
||||
}
|
||||
// Continue for DS to see if we have a parent too, if so delegeate to the parent
|
||||
handler = h
|
||||
}
|
||||
off, end = NextLabel(q, off)
|
||||
if end {
|
||||
break
|
||||
}
|
||||
}
|
||||
// Wildcard match, if we have found nothing try the root zone as a last resort.
|
||||
if h, ok := mux.z["."]; ok {
|
||||
return h
|
||||
}
|
||||
return handler
|
||||
}
|
||||
|
||||
// Handle adds a handler to the ServeMux for pattern.
|
||||
func (mux *ServeMux) Handle(pattern string, handler Handler) {
|
||||
if pattern == "" {
|
||||
panic("dns: invalid pattern " + pattern)
|
||||
}
|
||||
mux.m.Lock()
|
||||
mux.z[Fqdn(pattern)] = handler
|
||||
mux.m.Unlock()
|
||||
}
|
||||
|
||||
// HandleFunc adds a handler function to the ServeMux for pattern.
|
||||
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
|
||||
mux.Handle(pattern, HandlerFunc(handler))
|
||||
}
|
||||
|
||||
// HandleRemove deregistrars the handler specific for pattern from the ServeMux.
|
||||
func (mux *ServeMux) HandleRemove(pattern string) {
|
||||
if pattern == "" {
|
||||
panic("dns: invalid pattern " + pattern)
|
||||
}
|
||||
mux.m.Lock()
|
||||
delete(mux.z, Fqdn(pattern))
|
||||
mux.m.Unlock()
|
||||
}
|
||||
|
||||
// ServeDNS dispatches the request to the handler whose
|
||||
// pattern most closely matches the request message. If DefaultServeMux
|
||||
// is used the correct thing for DS queries is done: a possible parent
|
||||
// is sought.
|
||||
// If no handler is found a standard SERVFAIL message is returned
|
||||
// If the request message does not have exactly one question in the
|
||||
// question section a SERVFAIL is returned, unlesss Unsafe is true.
|
||||
func (mux *ServeMux) ServeDNS(w ResponseWriter, request *Msg) {
|
||||
var h Handler
|
||||
if len(request.Question) < 1 { // allow more than one question
|
||||
h = failedHandler()
|
||||
} else {
|
||||
if h = mux.match(request.Question[0].Name, request.Question[0].Qtype); h == nil {
|
||||
h = failedHandler()
|
||||
}
|
||||
}
|
||||
h.ServeDNS(w, request)
|
||||
}
|
||||
|
||||
// Handle registers the handler with the given pattern
|
||||
// in the DefaultServeMux. The documentation for
|
||||
// ServeMux explains how patterns are matched.
|
||||
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
|
||||
|
||||
// HandleRemove deregisters the handle with the given pattern
|
||||
// in the DefaultServeMux.
|
||||
func HandleRemove(pattern string) { DefaultServeMux.HandleRemove(pattern) }
|
||||
|
||||
// HandleFunc registers the handler function with the given pattern
|
||||
// in the DefaultServeMux.
|
||||
func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
|
||||
DefaultServeMux.HandleFunc(pattern, handler)
|
||||
}
|
||||
|
||||
// Writer writes raw DNS messages; each call to Write should send an entire message.
|
||||
type Writer interface {
|
||||
io.Writer
|
||||
|
|
@ -245,11 +145,11 @@ type defaultReader struct {
|
|||
*Server
|
||||
}
|
||||
|
||||
func (dr *defaultReader) ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
|
||||
func (dr defaultReader) ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
|
||||
return dr.readTCP(conn, timeout)
|
||||
}
|
||||
|
||||
func (dr *defaultReader) ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
|
||||
func (dr defaultReader) ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
|
||||
return dr.readUDP(conn, timeout)
|
||||
}
|
||||
|
||||
|
|
@ -284,92 +184,122 @@ type Server struct {
|
|||
WriteTimeout time.Duration
|
||||
// TCP idle timeout for multiple queries, if nil, defaults to 8 * time.Second (RFC 5966).
|
||||
IdleTimeout func() time.Duration
|
||||
// Secret(s) for Tsig map[<zonename>]<base64 secret>.
|
||||
// Secret(s) for Tsig map[<zonename>]<base64 secret>. The zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2).
|
||||
TsigSecret map[string]string
|
||||
// Unsafe instructs the server to disregard any sanity checks and directly hand the message to
|
||||
// the handler. It will specifically not check if the query has the QR bit not set.
|
||||
Unsafe bool
|
||||
// If NotifyStartedFunc is set it is called once the server has started listening.
|
||||
NotifyStartedFunc func()
|
||||
// DecorateReader is optional, allows customization of the process that reads raw DNS messages.
|
||||
DecorateReader DecorateReader
|
||||
// DecorateWriter is optional, allows customization of the process that writes raw DNS messages.
|
||||
DecorateWriter DecorateWriter
|
||||
// Maximum number of TCP queries before we close the socket. Default is maxTCPQueries (unlimited if -1).
|
||||
MaxTCPQueries int
|
||||
// Whether to set the SO_REUSEPORT socket option, allowing multiple listeners to be bound to a single address.
|
||||
// It is only supported on go1.11+ and when using ListenAndServe.
|
||||
ReusePort bool
|
||||
// AcceptMsgFunc will check the incoming message and will reject it early in the process.
|
||||
// By default DefaultMsgAcceptFunc will be used.
|
||||
MsgAcceptFunc MsgAcceptFunc
|
||||
|
||||
// Graceful shutdown handling
|
||||
// Shutdown handling
|
||||
lock sync.RWMutex
|
||||
started bool
|
||||
shutdown chan struct{}
|
||||
conns map[net.Conn]struct{}
|
||||
|
||||
inFlight sync.WaitGroup
|
||||
// A pool for UDP message buffers.
|
||||
udpPool sync.Pool
|
||||
}
|
||||
|
||||
lock sync.RWMutex
|
||||
started bool
|
||||
func (srv *Server) isStarted() bool {
|
||||
srv.lock.RLock()
|
||||
started := srv.started
|
||||
srv.lock.RUnlock()
|
||||
return started
|
||||
}
|
||||
|
||||
func makeUDPBuffer(size int) func() interface{} {
|
||||
return func() interface{} {
|
||||
return make([]byte, size)
|
||||
}
|
||||
}
|
||||
|
||||
func (srv *Server) init() {
|
||||
srv.shutdown = make(chan struct{})
|
||||
srv.conns = make(map[net.Conn]struct{})
|
||||
|
||||
if srv.UDPSize == 0 {
|
||||
srv.UDPSize = MinMsgSize
|
||||
}
|
||||
if srv.MsgAcceptFunc == nil {
|
||||
srv.MsgAcceptFunc = DefaultMsgAcceptFunc
|
||||
}
|
||||
if srv.Handler == nil {
|
||||
srv.Handler = DefaultServeMux
|
||||
}
|
||||
|
||||
srv.udpPool.New = makeUDPBuffer(srv.UDPSize)
|
||||
}
|
||||
|
||||
func unlockOnce(l sync.Locker) func() {
|
||||
var once sync.Once
|
||||
return func() { once.Do(l.Unlock) }
|
||||
}
|
||||
|
||||
// ListenAndServe starts a nameserver on the configured address in *Server.
|
||||
func (srv *Server) ListenAndServe() error {
|
||||
unlock := unlockOnce(&srv.lock)
|
||||
srv.lock.Lock()
|
||||
defer srv.lock.Unlock()
|
||||
defer unlock()
|
||||
|
||||
if srv.started {
|
||||
return &Error{err: "server already started"}
|
||||
}
|
||||
|
||||
addr := srv.Addr
|
||||
if addr == "" {
|
||||
addr = ":domain"
|
||||
}
|
||||
if srv.UDPSize == 0 {
|
||||
srv.UDPSize = MinMsgSize
|
||||
}
|
||||
|
||||
srv.init()
|
||||
|
||||
switch srv.Net {
|
||||
case "tcp", "tcp4", "tcp6":
|
||||
a, e := net.ResolveTCPAddr(srv.Net, addr)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
l, e := net.ListenTCP(srv.Net, a)
|
||||
if e != nil {
|
||||
return e
|
||||
l, err := listenTCP(srv.Net, addr, srv.ReusePort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv.Listener = l
|
||||
srv.started = true
|
||||
srv.lock.Unlock()
|
||||
e = srv.serveTCP(l)
|
||||
srv.lock.Lock() // to satisfy the defer at the top
|
||||
return e
|
||||
unlock()
|
||||
return srv.serveTCP(l)
|
||||
case "tcp-tls", "tcp4-tls", "tcp6-tls":
|
||||
network := "tcp"
|
||||
if srv.Net == "tcp4-tls" {
|
||||
network = "tcp4"
|
||||
} else if srv.Net == "tcp6" {
|
||||
network = "tcp6"
|
||||
if srv.TLSConfig == nil || (len(srv.TLSConfig.Certificates) == 0 && srv.TLSConfig.GetCertificate == nil) {
|
||||
return errors.New("dns: neither Certificates nor GetCertificate set in Config")
|
||||
}
|
||||
|
||||
l, e := tls.Listen(network, addr, srv.TLSConfig)
|
||||
if e != nil {
|
||||
return e
|
||||
network := strings.TrimSuffix(srv.Net, "-tls")
|
||||
l, err := listenTCP(network, addr, srv.ReusePort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l = tls.NewListener(l, srv.TLSConfig)
|
||||
srv.Listener = l
|
||||
srv.started = true
|
||||
srv.lock.Unlock()
|
||||
e = srv.serveTCP(l)
|
||||
srv.lock.Lock() // to satisfy the defer at the top
|
||||
return e
|
||||
unlock()
|
||||
return srv.serveTCP(l)
|
||||
case "udp", "udp4", "udp6":
|
||||
a, e := net.ResolveUDPAddr(srv.Net, addr)
|
||||
if e != nil {
|
||||
return e
|
||||
l, err := listenUDP(srv.Net, addr, srv.ReusePort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l, e := net.ListenUDP(srv.Net, a)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
if e := setUDPSocketOptions(l); e != nil {
|
||||
u := l.(*net.UDPConn)
|
||||
if e := setUDPSocketOptions(u); e != nil {
|
||||
return e
|
||||
}
|
||||
srv.PacketConn = l
|
||||
srv.started = true
|
||||
srv.lock.Unlock()
|
||||
e = srv.serveUDP(l)
|
||||
srv.lock.Lock() // to satisfy the defer at the top
|
||||
return e
|
||||
unlock()
|
||||
return srv.serveUDP(u)
|
||||
}
|
||||
return &Error{err: "bad network"}
|
||||
}
|
||||
|
|
@ -377,83 +307,101 @@ func (srv *Server) ListenAndServe() error {
|
|||
// ActivateAndServe starts a nameserver with the PacketConn or Listener
|
||||
// configured in *Server. Its main use is to start a server from systemd.
|
||||
func (srv *Server) ActivateAndServe() error {
|
||||
unlock := unlockOnce(&srv.lock)
|
||||
srv.lock.Lock()
|
||||
defer srv.lock.Unlock()
|
||||
defer unlock()
|
||||
|
||||
if srv.started {
|
||||
return &Error{err: "server already started"}
|
||||
}
|
||||
|
||||
srv.init()
|
||||
|
||||
pConn := srv.PacketConn
|
||||
l := srv.Listener
|
||||
if pConn != nil {
|
||||
if srv.UDPSize == 0 {
|
||||
srv.UDPSize = MinMsgSize
|
||||
}
|
||||
if t, ok := pConn.(*net.UDPConn); ok {
|
||||
// Check PacketConn interface's type is valid and value
|
||||
// is not nil
|
||||
if t, ok := pConn.(*net.UDPConn); ok && t != nil {
|
||||
if e := setUDPSocketOptions(t); e != nil {
|
||||
return e
|
||||
}
|
||||
srv.started = true
|
||||
srv.lock.Unlock()
|
||||
e := srv.serveUDP(t)
|
||||
srv.lock.Lock() // to satisfy the defer at the top
|
||||
return e
|
||||
unlock()
|
||||
return srv.serveUDP(t)
|
||||
}
|
||||
}
|
||||
if l != nil {
|
||||
srv.started = true
|
||||
srv.lock.Unlock()
|
||||
e := srv.serveTCP(l)
|
||||
srv.lock.Lock() // to satisfy the defer at the top
|
||||
return e
|
||||
unlock()
|
||||
return srv.serveTCP(l)
|
||||
}
|
||||
return &Error{err: "bad listeners"}
|
||||
}
|
||||
|
||||
// Shutdown gracefully shuts down a server. After a call to Shutdown, ListenAndServe and
|
||||
// ActivateAndServe will return. All in progress queries are completed before the server
|
||||
// is taken down. If the Shutdown is taking longer than the reading timeout an error
|
||||
// is returned.
|
||||
// Shutdown shuts down a server. After a call to Shutdown, ListenAndServe and
|
||||
// ActivateAndServe will return.
|
||||
func (srv *Server) Shutdown() error {
|
||||
return srv.ShutdownContext(context.Background())
|
||||
}
|
||||
|
||||
// ShutdownContext shuts down a server. After a call to ShutdownContext,
|
||||
// ListenAndServe and ActivateAndServe will return.
|
||||
//
|
||||
// A context.Context may be passed to limit how long to wait for connections
|
||||
// to terminate.
|
||||
func (srv *Server) ShutdownContext(ctx context.Context) error {
|
||||
srv.lock.Lock()
|
||||
if !srv.started {
|
||||
srv.lock.Unlock()
|
||||
return &Error{err: "server not started"}
|
||||
}
|
||||
|
||||
srv.started = false
|
||||
srv.lock.Unlock()
|
||||
|
||||
if srv.PacketConn != nil {
|
||||
srv.PacketConn.Close()
|
||||
srv.PacketConn.SetReadDeadline(aLongTimeAgo) // Unblock reads
|
||||
}
|
||||
|
||||
if srv.Listener != nil {
|
||||
srv.Listener.Close()
|
||||
}
|
||||
|
||||
fin := make(chan bool)
|
||||
go func() {
|
||||
srv.inFlight.Wait()
|
||||
fin <- true
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-time.After(srv.getReadTimeout()):
|
||||
return &Error{err: "server shutdown is pending"}
|
||||
case <-fin:
|
||||
return nil
|
||||
for rw := range srv.conns {
|
||||
rw.SetReadDeadline(aLongTimeAgo) // Unblock reads
|
||||
}
|
||||
|
||||
srv.lock.Unlock()
|
||||
|
||||
if testShutdownNotify != nil {
|
||||
testShutdownNotify.Broadcast()
|
||||
}
|
||||
|
||||
var ctxErr error
|
||||
select {
|
||||
case <-srv.shutdown:
|
||||
case <-ctx.Done():
|
||||
ctxErr = ctx.Err()
|
||||
}
|
||||
|
||||
if srv.PacketConn != nil {
|
||||
srv.PacketConn.Close()
|
||||
}
|
||||
|
||||
return ctxErr
|
||||
}
|
||||
|
||||
var testShutdownNotify *sync.Cond
|
||||
|
||||
// getReadTimeout is a helper func to use system timeout if server did not intend to change it.
|
||||
func (srv *Server) getReadTimeout() time.Duration {
|
||||
rtimeout := dnsTimeout
|
||||
if srv.ReadTimeout != 0 {
|
||||
rtimeout = srv.ReadTimeout
|
||||
return srv.ReadTimeout
|
||||
}
|
||||
return rtimeout
|
||||
return dnsTimeout
|
||||
}
|
||||
|
||||
// serveTCP starts a TCP listener for the server.
|
||||
// Each request is handled in a separate goroutine.
|
||||
func (srv *Server) serveTCP(l net.Listener) error {
|
||||
defer l.Close()
|
||||
|
||||
|
|
@ -461,42 +409,35 @@ func (srv *Server) serveTCP(l net.Listener) error {
|
|||
srv.NotifyStartedFunc()
|
||||
}
|
||||
|
||||
reader := Reader(&defaultReader{srv})
|
||||
if srv.DecorateReader != nil {
|
||||
reader = srv.DecorateReader(reader)
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
defer func() {
|
||||
wg.Wait()
|
||||
close(srv.shutdown)
|
||||
}()
|
||||
|
||||
handler := srv.Handler
|
||||
if handler == nil {
|
||||
handler = DefaultServeMux
|
||||
}
|
||||
rtimeout := srv.getReadTimeout()
|
||||
// deadline is not used here
|
||||
for {
|
||||
rw, e := l.Accept()
|
||||
if e != nil {
|
||||
if neterr, ok := e.(net.Error); ok && neterr.Temporary() {
|
||||
for srv.isStarted() {
|
||||
rw, err := l.Accept()
|
||||
if err != nil {
|
||||
if !srv.isStarted() {
|
||||
return nil
|
||||
}
|
||||
if neterr, ok := err.(net.Error); ok && neterr.Temporary() {
|
||||
continue
|
||||
}
|
||||
return e
|
||||
return err
|
||||
}
|
||||
m, e := reader.ReadTCP(rw, rtimeout)
|
||||
srv.lock.RLock()
|
||||
if !srv.started {
|
||||
srv.lock.RUnlock()
|
||||
return nil
|
||||
}
|
||||
srv.lock.RUnlock()
|
||||
if e != nil {
|
||||
continue
|
||||
}
|
||||
srv.inFlight.Add(1)
|
||||
go srv.serve(rw.RemoteAddr(), handler, m, nil, nil, rw)
|
||||
srv.lock.Lock()
|
||||
// Track the connection to allow unblocking reads on shutdown.
|
||||
srv.conns[rw] = struct{}{}
|
||||
srv.lock.Unlock()
|
||||
wg.Add(1)
|
||||
go srv.serveTCPConn(&wg, rw)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// serveUDP starts a UDP listener for the server.
|
||||
// Each request is handled in a separate goroutine.
|
||||
func (srv *Server) serveUDP(l *net.UDPConn) error {
|
||||
defer l.Close()
|
||||
|
||||
|
|
@ -504,151 +445,201 @@ func (srv *Server) serveUDP(l *net.UDPConn) error {
|
|||
srv.NotifyStartedFunc()
|
||||
}
|
||||
|
||||
reader := Reader(&defaultReader{srv})
|
||||
reader := Reader(defaultReader{srv})
|
||||
if srv.DecorateReader != nil {
|
||||
reader = srv.DecorateReader(reader)
|
||||
}
|
||||
|
||||
handler := srv.Handler
|
||||
if handler == nil {
|
||||
handler = DefaultServeMux
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
defer func() {
|
||||
wg.Wait()
|
||||
close(srv.shutdown)
|
||||
}()
|
||||
|
||||
rtimeout := srv.getReadTimeout()
|
||||
// deadline is not used here
|
||||
for {
|
||||
m, s, e := reader.ReadUDP(l, rtimeout)
|
||||
srv.lock.RLock()
|
||||
if !srv.started {
|
||||
srv.lock.RUnlock()
|
||||
return nil
|
||||
for srv.isStarted() {
|
||||
m, s, err := reader.ReadUDP(l, rtimeout)
|
||||
if err != nil {
|
||||
if !srv.isStarted() {
|
||||
return nil
|
||||
}
|
||||
if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
srv.lock.RUnlock()
|
||||
if e != nil {
|
||||
if len(m) < headerSize {
|
||||
if cap(m) == srv.UDPSize {
|
||||
srv.udpPool.Put(m[:srv.UDPSize])
|
||||
}
|
||||
continue
|
||||
}
|
||||
srv.inFlight.Add(1)
|
||||
go srv.serve(s.RemoteAddr(), handler, m, l, s, nil)
|
||||
wg.Add(1)
|
||||
go srv.serveUDPPacket(&wg, m, l, s)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Serve a new connection.
|
||||
func (srv *Server) serve(a net.Addr, h Handler, m []byte, u *net.UDPConn, s *SessionUDP, t net.Conn) {
|
||||
defer srv.inFlight.Done()
|
||||
|
||||
w := &response{tsigSecret: srv.TsigSecret, udp: u, tcp: t, remoteAddr: a, udpSession: s}
|
||||
// Serve a new TCP connection.
|
||||
func (srv *Server) serveTCPConn(wg *sync.WaitGroup, rw net.Conn) {
|
||||
w := &response{tsigSecret: srv.TsigSecret, tcp: rw}
|
||||
if srv.DecorateWriter != nil {
|
||||
w.writer = srv.DecorateWriter(w)
|
||||
} else {
|
||||
w.writer = w
|
||||
}
|
||||
|
||||
q := 0 // counter for the amount of TCP queries we get
|
||||
|
||||
reader := Reader(&defaultReader{srv})
|
||||
reader := Reader(defaultReader{srv})
|
||||
if srv.DecorateReader != nil {
|
||||
reader = srv.DecorateReader(reader)
|
||||
}
|
||||
Redo:
|
||||
req := new(Msg)
|
||||
err := req.Unpack(m)
|
||||
if err != nil { // Send a FormatError back
|
||||
x := new(Msg)
|
||||
x.SetRcodeFormatError(req)
|
||||
w.WriteMsg(x)
|
||||
goto Exit
|
||||
|
||||
idleTimeout := tcpIdleTimeout
|
||||
if srv.IdleTimeout != nil {
|
||||
idleTimeout = srv.IdleTimeout()
|
||||
}
|
||||
if !srv.Unsafe && req.Response {
|
||||
goto Exit
|
||||
|
||||
timeout := srv.getReadTimeout()
|
||||
|
||||
limit := srv.MaxTCPQueries
|
||||
if limit == 0 {
|
||||
limit = maxTCPQueries
|
||||
}
|
||||
|
||||
for q := 0; (q < limit || limit == -1) && srv.isStarted(); q++ {
|
||||
m, err := reader.ReadTCP(w.tcp, timeout)
|
||||
if err != nil {
|
||||
// TODO(tmthrgd): handle error
|
||||
break
|
||||
}
|
||||
srv.serveDNS(m, w)
|
||||
if w.closed {
|
||||
break // Close() was called
|
||||
}
|
||||
if w.hijacked {
|
||||
break // client will call Close() themselves
|
||||
}
|
||||
// The first read uses the read timeout, the rest use the
|
||||
// idle timeout.
|
||||
timeout = idleTimeout
|
||||
}
|
||||
|
||||
if !w.hijacked {
|
||||
w.Close()
|
||||
}
|
||||
|
||||
srv.lock.Lock()
|
||||
delete(srv.conns, w.tcp)
|
||||
srv.lock.Unlock()
|
||||
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
// Serve a new UDP request.
|
||||
func (srv *Server) serveUDPPacket(wg *sync.WaitGroup, m []byte, u *net.UDPConn, s *SessionUDP) {
|
||||
w := &response{tsigSecret: srv.TsigSecret, udp: u, udpSession: s}
|
||||
if srv.DecorateWriter != nil {
|
||||
w.writer = srv.DecorateWriter(w)
|
||||
} else {
|
||||
w.writer = w
|
||||
}
|
||||
|
||||
srv.serveDNS(m, w)
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
func (srv *Server) serveDNS(m []byte, w *response) {
|
||||
dh, off, err := unpackMsgHdr(m, 0)
|
||||
if err != nil {
|
||||
// Let client hang, they are sending crap; any reply can be used to amplify.
|
||||
return
|
||||
}
|
||||
|
||||
req := new(Msg)
|
||||
req.setHdr(dh)
|
||||
|
||||
switch srv.MsgAcceptFunc(dh) {
|
||||
case MsgAccept:
|
||||
if req.unpack(dh, m, off) == nil {
|
||||
break
|
||||
}
|
||||
|
||||
fallthrough
|
||||
case MsgReject:
|
||||
req.SetRcodeFormatError(req)
|
||||
// Are we allowed to delete any OPT records here?
|
||||
req.Ns, req.Answer, req.Extra = nil, nil, nil
|
||||
|
||||
w.WriteMsg(req)
|
||||
|
||||
if w.udp != nil && cap(m) == srv.UDPSize {
|
||||
srv.udpPool.Put(m[:srv.UDPSize])
|
||||
}
|
||||
|
||||
return
|
||||
case MsgIgnore:
|
||||
return
|
||||
}
|
||||
|
||||
w.tsigStatus = nil
|
||||
if w.tsigSecret != nil {
|
||||
if t := req.IsTsig(); t != nil {
|
||||
secret := t.Hdr.Name
|
||||
if _, ok := w.tsigSecret[secret]; !ok {
|
||||
w.tsigStatus = ErrKeyAlg
|
||||
if secret, ok := w.tsigSecret[t.Hdr.Name]; ok {
|
||||
w.tsigStatus = TsigVerify(m, secret, "", false)
|
||||
} else {
|
||||
w.tsigStatus = ErrSecret
|
||||
}
|
||||
w.tsigStatus = TsigVerify(m, w.tsigSecret[secret], "", false)
|
||||
w.tsigTimersOnly = false
|
||||
w.tsigRequestMAC = req.Extra[len(req.Extra)-1].(*TSIG).MAC
|
||||
}
|
||||
}
|
||||
h.ServeDNS(w, req) // Writes back to the client
|
||||
|
||||
Exit:
|
||||
if w.tcp == nil {
|
||||
return
|
||||
}
|
||||
// TODO(miek): make this number configurable?
|
||||
if q > maxTCPQueries { // close socket after this many queries
|
||||
w.Close()
|
||||
return
|
||||
if w.udp != nil && cap(m) == srv.UDPSize {
|
||||
srv.udpPool.Put(m[:srv.UDPSize])
|
||||
}
|
||||
|
||||
if w.hijacked {
|
||||
return // client calls Close()
|
||||
}
|
||||
if u != nil { // UDP, "close" and return
|
||||
w.Close()
|
||||
return
|
||||
}
|
||||
idleTimeout := tcpIdleTimeout
|
||||
if srv.IdleTimeout != nil {
|
||||
idleTimeout = srv.IdleTimeout()
|
||||
}
|
||||
m, e := reader.ReadTCP(w.tcp, idleTimeout)
|
||||
if e == nil {
|
||||
q++
|
||||
goto Redo
|
||||
}
|
||||
w.Close()
|
||||
return
|
||||
srv.Handler.ServeDNS(w, req) // Writes back to the client
|
||||
}
|
||||
|
||||
func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
|
||||
conn.SetReadDeadline(time.Now().Add(timeout))
|
||||
l := make([]byte, 2)
|
||||
n, err := conn.Read(l)
|
||||
if err != nil || n != 2 {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, ErrShortRead
|
||||
// If we race with ShutdownContext, the read deadline may
|
||||
// have been set in the distant past to unblock the read
|
||||
// below. We must not override it, otherwise we may block
|
||||
// ShutdownContext.
|
||||
srv.lock.RLock()
|
||||
if srv.started {
|
||||
conn.SetReadDeadline(time.Now().Add(timeout))
|
||||
}
|
||||
length, _ := unpackUint16(l, 0)
|
||||
if length == 0 {
|
||||
return nil, ErrShortRead
|
||||
srv.lock.RUnlock()
|
||||
|
||||
var length uint16
|
||||
if err := binary.Read(conn, binary.BigEndian, &length); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make([]byte, int(length))
|
||||
n, err = conn.Read(m[:int(length)])
|
||||
if err != nil || n == 0 {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, ErrShortRead
|
||||
|
||||
m := make([]byte, length)
|
||||
if _, err := io.ReadFull(conn, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i := n
|
||||
for i < int(length) {
|
||||
j, err := conn.Read(m[i:int(length)])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i += j
|
||||
}
|
||||
n = i
|
||||
m = m[:n]
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
|
||||
conn.SetReadDeadline(time.Now().Add(timeout))
|
||||
m := make([]byte, srv.UDPSize)
|
||||
n, s, e := ReadFromSessionUDP(conn, m)
|
||||
if e != nil || n == 0 {
|
||||
if e != nil {
|
||||
return nil, nil, e
|
||||
}
|
||||
return nil, nil, ErrShortRead
|
||||
srv.lock.RLock()
|
||||
if srv.started {
|
||||
// See the comment in readTCP above.
|
||||
conn.SetReadDeadline(time.Now().Add(timeout))
|
||||
}
|
||||
srv.lock.RUnlock()
|
||||
|
||||
m := srv.udpPool.Get().([]byte)
|
||||
n, s, err := ReadFromSessionUDP(conn, m)
|
||||
if err != nil {
|
||||
srv.udpPool.Put(m)
|
||||
return nil, nil, err
|
||||
}
|
||||
m = m[:n]
|
||||
return m, s, nil
|
||||
|
|
@ -656,6 +647,10 @@ func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *S
|
|||
|
||||
// WriteMsg implements the ResponseWriter.WriteMsg method.
|
||||
func (w *response) WriteMsg(m *Msg) (err error) {
|
||||
if w.closed {
|
||||
return &Error{err: "WriteMsg called after Close"}
|
||||
}
|
||||
|
||||
var data []byte
|
||||
if w.tsigSecret != nil { // if no secrets, dont check for the tsig (which is a longer check)
|
||||
if t := m.IsTsig(); t != nil {
|
||||
|
|
@ -677,38 +672,51 @@ func (w *response) WriteMsg(m *Msg) (err error) {
|
|||
|
||||
// Write implements the ResponseWriter.Write method.
|
||||
func (w *response) Write(m []byte) (int, error) {
|
||||
if w.closed {
|
||||
return 0, &Error{err: "Write called after Close"}
|
||||
}
|
||||
|
||||
switch {
|
||||
case w.udp != nil:
|
||||
n, err := WriteToSessionUDP(w.udp, m, w.udpSession)
|
||||
return n, err
|
||||
return WriteToSessionUDP(w.udp, m, w.udpSession)
|
||||
case w.tcp != nil:
|
||||
lm := len(m)
|
||||
if lm < 2 {
|
||||
return 0, io.ErrShortBuffer
|
||||
}
|
||||
if lm > MaxMsgSize {
|
||||
if len(m) > MaxMsgSize {
|
||||
return 0, &Error{err: "message too large"}
|
||||
}
|
||||
l := make([]byte, 2, 2+lm)
|
||||
l[0], l[1] = packUint16(uint16(lm))
|
||||
m = append(l, m...)
|
||||
|
||||
n, err := io.Copy(w.tcp, bytes.NewReader(m))
|
||||
l := make([]byte, 2)
|
||||
binary.BigEndian.PutUint16(l, uint16(len(m)))
|
||||
|
||||
n, err := (&net.Buffers{l, m}).WriteTo(w.tcp)
|
||||
return int(n), err
|
||||
default:
|
||||
panic("dns: internal error: udp and tcp both nil")
|
||||
}
|
||||
panic("not reached")
|
||||
}
|
||||
|
||||
// LocalAddr implements the ResponseWriter.LocalAddr method.
|
||||
func (w *response) LocalAddr() net.Addr {
|
||||
if w.tcp != nil {
|
||||
switch {
|
||||
case w.udp != nil:
|
||||
return w.udp.LocalAddr()
|
||||
case w.tcp != nil:
|
||||
return w.tcp.LocalAddr()
|
||||
default:
|
||||
panic("dns: internal error: udp and tcp both nil")
|
||||
}
|
||||
return w.udp.LocalAddr()
|
||||
}
|
||||
|
||||
// RemoteAddr implements the ResponseWriter.RemoteAddr method.
|
||||
func (w *response) RemoteAddr() net.Addr { return w.remoteAddr }
|
||||
func (w *response) RemoteAddr() net.Addr {
|
||||
switch {
|
||||
case w.udpSession != nil:
|
||||
return w.udpSession.RemoteAddr()
|
||||
case w.tcp != nil:
|
||||
return w.tcp.RemoteAddr()
|
||||
default:
|
||||
panic("dns: internal error: udpSession and tcp both nil")
|
||||
}
|
||||
}
|
||||
|
||||
// TsigStatus implements the ResponseWriter.TsigStatus method.
|
||||
func (w *response) TsigStatus() error { return w.tsigStatus }
|
||||
|
|
@ -721,11 +729,30 @@ func (w *response) Hijack() { w.hijacked = true }
|
|||
|
||||
// Close implements the ResponseWriter.Close method
|
||||
func (w *response) Close() error {
|
||||
// Can't close the udp conn, as that is actually the listener.
|
||||
if w.tcp != nil {
|
||||
e := w.tcp.Close()
|
||||
w.tcp = nil
|
||||
return e
|
||||
if w.closed {
|
||||
return &Error{err: "connection already closed"}
|
||||
}
|
||||
w.closed = true
|
||||
|
||||
switch {
|
||||
case w.udp != nil:
|
||||
// Can't close the udp conn, as that is actually the listener.
|
||||
return nil
|
||||
case w.tcp != nil:
|
||||
return w.tcp.Close()
|
||||
default:
|
||||
panic("dns: internal error: udp and tcp both nil")
|
||||
}
|
||||
}
|
||||
|
||||
// ConnectionState() implements the ConnectionStater.ConnectionState() interface.
|
||||
func (w *response) ConnectionState() *tls.ConnectionState {
|
||||
type tlsConnectionStater interface {
|
||||
ConnectionState() tls.ConnectionState
|
||||
}
|
||||
if v, ok := w.tcp.(tlsConnectionStater); ok {
|
||||
t := v.ConnectionState()
|
||||
return &t
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"encoding/binary"
|
||||
"math/big"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -20,15 +21,11 @@ func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) {
|
|||
if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 {
|
||||
return nil, ErrKey
|
||||
}
|
||||
rr.Header().Rrtype = TypeSIG
|
||||
rr.Header().Class = ClassANY
|
||||
rr.Header().Ttl = 0
|
||||
rr.Header().Name = "."
|
||||
rr.OrigTtl = 0
|
||||
rr.TypeCovered = 0
|
||||
rr.Labels = 0
|
||||
|
||||
buf := make([]byte, m.Len()+rr.len())
|
||||
rr.Hdr = RR_Header{Name: ".", Rrtype: TypeSIG, Class: ClassANY, Ttl: 0}
|
||||
rr.OrigTtl, rr.TypeCovered, rr.Labels = 0, 0, 0
|
||||
|
||||
buf := make([]byte, m.Len()+Len(rr))
|
||||
mbuf, err := m.PackBuffer(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -59,21 +56,20 @@ func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) {
|
|||
}
|
||||
|
||||
rr.Signature = toBase64(signature)
|
||||
sig := string(signature)
|
||||
|
||||
buf = append(buf, sig...)
|
||||
buf = append(buf, signature...)
|
||||
if len(buf) > int(^uint16(0)) {
|
||||
return nil, ErrBuf
|
||||
}
|
||||
// Adjust sig data length
|
||||
rdoff := len(mbuf) + 1 + 2 + 2 + 4
|
||||
rdlen, _ := unpackUint16(buf, rdoff)
|
||||
rdlen += uint16(len(sig))
|
||||
buf[rdoff], buf[rdoff+1] = packUint16(rdlen)
|
||||
rdlen := binary.BigEndian.Uint16(buf[rdoff:])
|
||||
rdlen += uint16(len(signature))
|
||||
binary.BigEndian.PutUint16(buf[rdoff:], rdlen)
|
||||
// Adjust additional count
|
||||
adc, _ := unpackUint16(buf, 10)
|
||||
adc := binary.BigEndian.Uint16(buf[10:])
|
||||
adc++
|
||||
buf[10], buf[11] = packUint16(adc)
|
||||
binary.BigEndian.PutUint16(buf[10:], adc)
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
|
|
@ -103,10 +99,11 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
|
|||
hasher := hash.New()
|
||||
|
||||
buflen := len(buf)
|
||||
qdc, _ := unpackUint16(buf, 4)
|
||||
anc, _ := unpackUint16(buf, 6)
|
||||
auc, _ := unpackUint16(buf, 8)
|
||||
adc, offset := unpackUint16(buf, 10)
|
||||
qdc := binary.BigEndian.Uint16(buf[4:])
|
||||
anc := binary.BigEndian.Uint16(buf[6:])
|
||||
auc := binary.BigEndian.Uint16(buf[8:])
|
||||
adc := binary.BigEndian.Uint16(buf[10:])
|
||||
offset := headerSize
|
||||
var err error
|
||||
for i := uint16(0); i < qdc && offset < buflen; i++ {
|
||||
_, offset, err = UnpackDomainName(buf, offset)
|
||||
|
|
@ -126,8 +123,8 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
|
|||
if offset+1 >= buflen {
|
||||
continue
|
||||
}
|
||||
var rdlen uint16
|
||||
rdlen, offset = unpackUint16(buf, offset)
|
||||
rdlen := binary.BigEndian.Uint16(buf[offset:])
|
||||
offset += 2
|
||||
offset += int(rdlen)
|
||||
}
|
||||
if offset >= buflen {
|
||||
|
|
@ -149,9 +146,9 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
|
|||
if offset+4+4 >= buflen {
|
||||
return &Error{err: "overflow unpacking signed message"}
|
||||
}
|
||||
expire := uint32(buf[offset])<<24 | uint32(buf[offset+1])<<16 | uint32(buf[offset+2])<<8 | uint32(buf[offset+3])
|
||||
expire := binary.BigEndian.Uint32(buf[offset:])
|
||||
offset += 4
|
||||
incept := uint32(buf[offset])<<24 | uint32(buf[offset+1])<<16 | uint32(buf[offset+2])<<8 | uint32(buf[offset+3])
|
||||
incept := binary.BigEndian.Uint32(buf[offset:])
|
||||
offset += 4
|
||||
now := uint32(time.Now().Unix())
|
||||
if now < incept || now > expire {
|
||||
|
|
@ -166,7 +163,7 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
|
|||
}
|
||||
// If key has come from the DNS name compression might
|
||||
// have mangled the case of the name
|
||||
if strings.ToLower(signername) != strings.ToLower(k.Header().Name) {
|
||||
if !strings.EqualFold(signername, k.Header().Name) {
|
||||
return &Error{err: "signer name doesn't match key name"}
|
||||
}
|
||||
sigend := offset
|
||||
|
|
@ -184,10 +181,8 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
|
|||
case DSA:
|
||||
pk := k.publicKeyDSA()
|
||||
sig = sig[1:]
|
||||
r := big.NewInt(0)
|
||||
r.SetBytes(sig[:len(sig)/2])
|
||||
s := big.NewInt(0)
|
||||
s.SetBytes(sig[len(sig)/2:])
|
||||
r := new(big.Int).SetBytes(sig[:len(sig)/2])
|
||||
s := new(big.Int).SetBytes(sig[len(sig)/2:])
|
||||
if pk != nil {
|
||||
if dsa.Verify(pk, hashed, r, s) {
|
||||
return nil
|
||||
|
|
@ -201,10 +196,8 @@ func (rr *SIG) Verify(k *KEY, buf []byte) error {
|
|||
}
|
||||
case ECDSAP256SHA256, ECDSAP384SHA384:
|
||||
pk := k.publicKeyECDSA()
|
||||
r := big.NewInt(0)
|
||||
r.SetBytes(sig[:len(sig)/2])
|
||||
s := big.NewInt(0)
|
||||
s.SetBytes(sig[len(sig)/2:])
|
||||
r := new(big.Int).SetBytes(sig[:len(sig)/2])
|
||||
s := new(big.Int).SetBytes(sig[len(sig)/2:])
|
||||
if pk != nil {
|
||||
if ecdsa.Verify(pk, hashed, r, s) {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ type call struct {
|
|||
type singleflight struct {
|
||||
sync.Mutex // protects m
|
||||
m map[string]*call // lazily initialized
|
||||
|
||||
dontDeleteForTesting bool // this is only to be used by TestConcurrentExchanges
|
||||
}
|
||||
|
||||
// Do executes and returns the results of the given function, making
|
||||
|
|
@ -49,9 +51,11 @@ func (g *singleflight) Do(key string, fn func() (*Msg, time.Duration, error)) (v
|
|||
c.val, c.rtt, c.err = fn()
|
||||
c.wg.Done()
|
||||
|
||||
g.Lock()
|
||||
delete(g.m, key)
|
||||
g.Unlock()
|
||||
if !g.dontDeleteForTesting {
|
||||
g.Lock()
|
||||
delete(g.m, key)
|
||||
g.Unlock()
|
||||
}
|
||||
|
||||
return c.val, c.rtt, c.err, c.dups > 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
// Sign creates a SMIMEA record from an SSL certificate.
|
||||
func (r *SMIMEA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (err error) {
|
||||
r.Hdr.Rrtype = TypeSMIMEA
|
||||
r.Usage = uint8(usage)
|
||||
r.Selector = uint8(selector)
|
||||
r.MatchingType = uint8(matchingType)
|
||||
|
||||
r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify verifies a SMIMEA record against an SSL certificate. If it is OK
|
||||
// a nil error is returned.
|
||||
func (r *SMIMEA) Verify(cert *x509.Certificate) error {
|
||||
c, err := CertificateToDANE(r.Selector, r.MatchingType, cert)
|
||||
if err != nil {
|
||||
return err // Not also ErrSig?
|
||||
}
|
||||
if r.Certificate == c {
|
||||
return nil
|
||||
}
|
||||
return ErrSig // ErrSig, really?
|
||||
}
|
||||
|
||||
// SMIMEAName returns the ownername of a SMIMEA resource record as per the
|
||||
// format specified in RFC 'draft-ietf-dane-smime-12' Section 2 and 3
|
||||
func SMIMEAName(email, domain string) (string, error) {
|
||||
hasher := sha256.New()
|
||||
hasher.Write([]byte(email))
|
||||
|
||||
// RFC Section 3: "The local-part is hashed using the SHA2-256
|
||||
// algorithm with the hash truncated to 28 octets and
|
||||
// represented in its hexadecimal representation to become the
|
||||
// left-most label in the prepared domain name"
|
||||
return hex.EncodeToString(hasher.Sum(nil)[:28]) + "." + "_smimecert." + domain, nil
|
||||
}
|
||||
|
|
@ -1,50 +1,11 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// CertificateToDANE converts a certificate to a hex string as used in the TLSA record.
|
||||
func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) (string, error) {
|
||||
switch matchingType {
|
||||
case 0:
|
||||
switch selector {
|
||||
case 0:
|
||||
return hex.EncodeToString(cert.Raw), nil
|
||||
case 1:
|
||||
return hex.EncodeToString(cert.RawSubjectPublicKeyInfo), nil
|
||||
}
|
||||
case 1:
|
||||
h := sha256.New()
|
||||
switch selector {
|
||||
case 0:
|
||||
io.WriteString(h, string(cert.Raw))
|
||||
return hex.EncodeToString(h.Sum(nil)), nil
|
||||
case 1:
|
||||
io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
|
||||
return hex.EncodeToString(h.Sum(nil)), nil
|
||||
}
|
||||
case 2:
|
||||
h := sha512.New()
|
||||
switch selector {
|
||||
case 0:
|
||||
io.WriteString(h, string(cert.Raw))
|
||||
return hex.EncodeToString(h.Sum(nil)), nil
|
||||
case 1:
|
||||
io.WriteString(h, string(cert.RawSubjectPublicKeyInfo))
|
||||
return hex.EncodeToString(h.Sum(nil)), nil
|
||||
}
|
||||
}
|
||||
return "", errors.New("dns: bad TLSA MatchingType or TLSA Selector")
|
||||
}
|
||||
|
||||
// Sign creates a TLSA record from an SSL certificate.
|
||||
func (r *TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (err error) {
|
||||
r.Hdr.Rrtype = TypeTLSA
|
||||
|
|
@ -53,10 +14,7 @@ func (r *TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (
|
|||
r.MatchingType = uint8(matchingType)
|
||||
|
||||
r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify verifies a TLSA record against an SSL certificate. If it is OK
|
||||
|
|
@ -78,9 +36,9 @@ func TLSAName(name, service, network string) (string, error) {
|
|||
if !IsFqdn(name) {
|
||||
return "", ErrFqdn
|
||||
}
|
||||
p, e := net.LookupPort(network, service)
|
||||
if e != nil {
|
||||
return "", e
|
||||
p, err := net.LookupPort(network, service)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "_" + strconv.Itoa(p) + "._" + network + "." + name, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ import (
|
|||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"hash"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -30,11 +30,11 @@ type TSIG struct {
|
|||
TimeSigned uint64 `dns:"uint48"`
|
||||
Fudge uint16
|
||||
MACSize uint16
|
||||
MAC string `dns:"size-hex"`
|
||||
MAC string `dns:"size-hex:MACSize"`
|
||||
OrigId uint16
|
||||
Error uint16
|
||||
OtherLen uint16
|
||||
OtherData string `dns:"size-hex"`
|
||||
OtherData string `dns:"size-hex:OtherLen"`
|
||||
}
|
||||
|
||||
// TSIG has no official presentation format, but this will suffice.
|
||||
|
|
@ -54,6 +54,10 @@ func (rr *TSIG) String() string {
|
|||
return s
|
||||
}
|
||||
|
||||
func (rr *TSIG) parse(c *zlexer, origin, file string) *ParseError {
|
||||
panic("dns: internal error: parse should never be called on TSIG")
|
||||
}
|
||||
|
||||
// The following values must be put in wireformat, so that the MAC can be calculated.
|
||||
// RFC 2845, section 3.4.2. TSIG Variables.
|
||||
type tsigWireFmt struct {
|
||||
|
|
@ -68,14 +72,13 @@ type tsigWireFmt struct {
|
|||
// MACSize, MAC and OrigId excluded
|
||||
Error uint16
|
||||
OtherLen uint16
|
||||
OtherData string `dns:"size-hex"`
|
||||
OtherData string `dns:"size-hex:OtherLen"`
|
||||
}
|
||||
|
||||
// If we have the MAC use this type to convert it to wiredata.
|
||||
// Section 3.4.3. Request MAC
|
||||
// If we have the MAC use this type to convert it to wiredata. Section 3.4.3. Request MAC
|
||||
type macWireFmt struct {
|
||||
MACSize uint16
|
||||
MAC string `dns:"size-hex"`
|
||||
MAC string `dns:"size-hex:MACSize"`
|
||||
}
|
||||
|
||||
// 3.3. Time values used in TSIG calculations
|
||||
|
|
@ -114,17 +117,17 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
|
|||
var h hash.Hash
|
||||
switch strings.ToLower(rr.Algorithm) {
|
||||
case HmacMD5:
|
||||
h = hmac.New(md5.New, []byte(rawsecret))
|
||||
h = hmac.New(md5.New, rawsecret)
|
||||
case HmacSHA1:
|
||||
h = hmac.New(sha1.New, []byte(rawsecret))
|
||||
h = hmac.New(sha1.New, rawsecret)
|
||||
case HmacSHA256:
|
||||
h = hmac.New(sha256.New, []byte(rawsecret))
|
||||
h = hmac.New(sha256.New, rawsecret)
|
||||
case HmacSHA512:
|
||||
h = hmac.New(sha512.New, []byte(rawsecret))
|
||||
h = hmac.New(sha512.New, rawsecret)
|
||||
default:
|
||||
return nil, "", ErrKeyAlg
|
||||
}
|
||||
io.WriteString(h, string(buf))
|
||||
h.Write(buf)
|
||||
t.MAC = hex.EncodeToString(h.Sum(nil))
|
||||
t.MACSize = uint16(len(t.MAC) / 2) // Size is half!
|
||||
|
||||
|
|
@ -134,14 +137,15 @@ func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, s
|
|||
t.Algorithm = rr.Algorithm
|
||||
t.OrigId = m.Id
|
||||
|
||||
tbuf := make([]byte, t.len())
|
||||
if off, err := PackRR(t, tbuf, 0, nil, false); err == nil {
|
||||
tbuf = tbuf[:off] // reset to actual size used
|
||||
} else {
|
||||
tbuf := make([]byte, Len(t))
|
||||
off, err := PackRR(t, tbuf, 0, nil, false)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
mbuf = append(mbuf, tbuf...)
|
||||
rawSetExtraLen(mbuf, uint16(len(m.Extra)+1))
|
||||
mbuf = append(mbuf, tbuf[:off]...)
|
||||
// Update the ArCount directly in the buffer.
|
||||
binary.BigEndian.PutUint16(mbuf[10:], uint16(len(m.Extra)+1))
|
||||
|
||||
return mbuf, t.MAC, nil
|
||||
}
|
||||
|
||||
|
|
@ -207,12 +211,15 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
|
|||
rr.Fudge = 300 // Standard (RFC) default.
|
||||
}
|
||||
|
||||
// Replace message ID in header with original ID from TSIG
|
||||
binary.BigEndian.PutUint16(msgbuf[0:2], rr.OrigId)
|
||||
|
||||
if requestMAC != "" {
|
||||
m := new(macWireFmt)
|
||||
m.MACSize = uint16(len(requestMAC) / 2)
|
||||
m.MAC = requestMAC
|
||||
buf = make([]byte, len(requestMAC)) // long enough
|
||||
n, _ := PackStruct(m, buf, 0)
|
||||
n, _ := packMacWire(m, buf)
|
||||
buf = buf[:n]
|
||||
}
|
||||
|
||||
|
|
@ -221,7 +228,7 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
|
|||
tsig := new(timerWireFmt)
|
||||
tsig.TimeSigned = rr.TimeSigned
|
||||
tsig.Fudge = rr.Fudge
|
||||
n, _ := PackStruct(tsig, tsigvar, 0)
|
||||
n, _ := packTimerWire(tsig, tsigvar)
|
||||
tsigvar = tsigvar[:n]
|
||||
} else {
|
||||
tsig := new(tsigWireFmt)
|
||||
|
|
@ -234,7 +241,7 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
|
|||
tsig.Error = rr.Error
|
||||
tsig.OtherLen = rr.OtherLen
|
||||
tsig.OtherData = rr.OtherData
|
||||
n, _ := PackStruct(tsig, tsigvar, 0)
|
||||
n, _ := packTsigWire(tsig, tsigvar)
|
||||
tsigvar = tsigvar[:n]
|
||||
}
|
||||
|
||||
|
|
@ -249,60 +256,54 @@ func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) []b
|
|||
|
||||
// Strip the TSIG from the raw message.
|
||||
func stripTsig(msg []byte) ([]byte, *TSIG, error) {
|
||||
// Copied from msg.go's Unpack()
|
||||
// Header.
|
||||
var dh Header
|
||||
var err error
|
||||
dns := new(Msg)
|
||||
rr := new(TSIG)
|
||||
off := 0
|
||||
tsigoff := 0
|
||||
if off, err = UnpackStruct(&dh, msg, off); err != nil {
|
||||
// Copied from msg.go's Unpack() Header, but modified.
|
||||
var (
|
||||
dh Header
|
||||
err error
|
||||
)
|
||||
off, tsigoff := 0, 0
|
||||
|
||||
if dh, off, err = unpackMsgHdr(msg, off); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if dh.Arcount == 0 {
|
||||
return nil, nil, ErrNoSig
|
||||
}
|
||||
|
||||
// Rcode, see msg.go Unpack()
|
||||
if int(dh.Bits&0xF) == RcodeNotAuth {
|
||||
return nil, nil, ErrAuth
|
||||
}
|
||||
|
||||
// Arrays.
|
||||
dns.Question = make([]Question, dh.Qdcount)
|
||||
dns.Answer = make([]RR, dh.Ancount)
|
||||
dns.Ns = make([]RR, dh.Nscount)
|
||||
dns.Extra = make([]RR, dh.Arcount)
|
||||
for i := 0; i < int(dh.Qdcount); i++ {
|
||||
_, off, err = unpackQuestion(msg, off)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < len(dns.Question); i++ {
|
||||
off, err = UnpackStruct(&dns.Question[i], msg, off)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
_, off, err = unpackRRslice(int(dh.Ancount), msg, off)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
for i := 0; i < len(dns.Answer); i++ {
|
||||
dns.Answer[i], off, err = UnpackRR(msg, off)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
_, off, err = unpackRRslice(int(dh.Nscount), msg, off)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
for i := 0; i < len(dns.Ns); i++ {
|
||||
dns.Ns[i], off, err = UnpackRR(msg, off)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(dns.Extra); i++ {
|
||||
|
||||
rr := new(TSIG)
|
||||
var extra RR
|
||||
for i := 0; i < int(dh.Arcount); i++ {
|
||||
tsigoff = off
|
||||
dns.Extra[i], off, err = UnpackRR(msg, off)
|
||||
extra, off, err = UnpackRR(msg, off)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if dns.Extra[i].Header().Rrtype == TypeTSIG {
|
||||
rr = dns.Extra[i].(*TSIG)
|
||||
if extra.Header().Rrtype == TypeTSIG {
|
||||
rr = extra.(*TSIG)
|
||||
// Adjust Arcount.
|
||||
arcount, _ := unpackUint16(msg, 10)
|
||||
msg[10], msg[11] = packUint16(arcount - 1)
|
||||
arcount := binary.BigEndian.Uint16(msg[10:])
|
||||
binary.BigEndian.PutUint16(msg[10:], arcount-1)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
@ -318,3 +319,71 @@ func tsigTimeToString(t uint64) string {
|
|||
ti := time.Unix(int64(t), 0).UTC()
|
||||
return ti.Format("20060102150405")
|
||||
}
|
||||
|
||||
func packTsigWire(tw *tsigWireFmt, msg []byte) (int, error) {
|
||||
// copied from zmsg.go TSIG packing
|
||||
// RR_Header
|
||||
off, err := PackDomainName(tw.Name, msg, 0, nil, false)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = packUint16(tw.Class, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = packUint32(tw.Ttl, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
|
||||
off, err = PackDomainName(tw.Algorithm, msg, off, nil, false)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = packUint48(tw.TimeSigned, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = packUint16(tw.Fudge, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
|
||||
off, err = packUint16(tw.Error, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = packUint16(tw.OtherLen, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = packStringHex(tw.OtherData, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func packMacWire(mw *macWireFmt, msg []byte) (int, error) {
|
||||
off, err := packUint16(mw.MACSize, msg, 0)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = packStringHex(mw.MAC, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
return off, nil
|
||||
}
|
||||
|
||||
func packTimerWire(tw *timerWireFmt, msg []byte) (int, error) {
|
||||
off, err := packUint48(tw.TimeSigned, msg, 0)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
off, err = packUint16(tw.Fudge, msg, off)
|
||||
if err != nil {
|
||||
return off, err
|
||||
}
|
||||
return off, nil
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -20,16 +20,14 @@ import (
|
|||
)
|
||||
|
||||
var skipLen = map[string]struct{}{
|
||||
"NSEC": {},
|
||||
"NSEC3": {},
|
||||
"OPT": {},
|
||||
"WKS": {},
|
||||
"IPSECKEY": {},
|
||||
"NSEC": {},
|
||||
"NSEC3": {},
|
||||
"OPT": {},
|
||||
"CSYNC": {},
|
||||
}
|
||||
|
||||
var packageHdr = `
|
||||
// *** DO NOT MODIFY ***
|
||||
// AUTOGENERATED BY go generate
|
||||
// Code generated by "go run types_generate.go"; DO NOT EDIT.
|
||||
|
||||
package dns
|
||||
|
||||
|
|
@ -58,7 +56,6 @@ var TypeToString = map[uint16]string{
|
|||
`))
|
||||
|
||||
var headerFunc = template.Must(template.New("headerFunc").Parse(`
|
||||
// Header() functions
|
||||
{{range .}} func (rr *{{.}}) Header() *RR_Header { return &rr.Hdr }
|
||||
{{end}}
|
||||
|
||||
|
|
@ -156,8 +153,8 @@ func main() {
|
|||
if isEmbedded {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(b, "func (rr *%s) len() int {\n", name)
|
||||
fmt.Fprintf(b, "l := rr.Hdr.len()\n")
|
||||
fmt.Fprintf(b, "func (rr *%s) len(off int, compression map[string]struct{}) int {\n", name)
|
||||
fmt.Fprintf(b, "l := rr.Hdr.len(off, compression)\n")
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
o := func(s string) { fmt.Fprintf(b, s, st.Field(i).Name()) }
|
||||
|
||||
|
|
@ -165,7 +162,11 @@ func main() {
|
|||
switch st.Tag(i) {
|
||||
case `dns:"-"`:
|
||||
// ignored
|
||||
case `dns:"cdomain-name"`, `dns:"domain-name"`, `dns:"txt"`:
|
||||
case `dns:"cdomain-name"`:
|
||||
o("for _, x := range rr.%s { l += domainNameLen(x, off+l, compression, true) }\n")
|
||||
case `dns:"domain-name"`:
|
||||
o("for _, x := range rr.%s { l += domainNameLen(x, off+l, compression, false) }\n")
|
||||
case `dns:"txt"`:
|
||||
o("for _, x := range rr.%s { l += len(x) + 1 }\n")
|
||||
default:
|
||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||
|
|
@ -173,29 +174,39 @@ func main() {
|
|||
continue
|
||||
}
|
||||
|
||||
switch st.Tag(i) {
|
||||
case `dns:"-"`:
|
||||
switch {
|
||||
case st.Tag(i) == `dns:"-"`:
|
||||
// ignored
|
||||
case `dns:"cdomain-name"`, `dns:"domain-name"`:
|
||||
o("l += len(rr.%s) + 1\n")
|
||||
case `dns:"octet"`:
|
||||
case st.Tag(i) == `dns:"cdomain-name"`:
|
||||
o("l += domainNameLen(rr.%s, off+l, compression, true)\n")
|
||||
case st.Tag(i) == `dns:"domain-name"`:
|
||||
o("l += domainNameLen(rr.%s, off+l, compression, false)\n")
|
||||
case st.Tag(i) == `dns:"octet"`:
|
||||
o("l += len(rr.%s)\n")
|
||||
case `dns:"base64"`:
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-base64`):
|
||||
fallthrough
|
||||
case st.Tag(i) == `dns:"base64"`:
|
||||
o("l += base64.StdEncoding.DecodedLen(len(rr.%s))\n")
|
||||
case `dns:"size-hex"`, `dns:"hex"`:
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex:`): // this has an extra field where the length is stored
|
||||
o("l += len(rr.%s)/2\n")
|
||||
case strings.HasPrefix(st.Tag(i), `dns:"size-hex`):
|
||||
fallthrough
|
||||
case st.Tag(i) == `dns:"hex"`:
|
||||
o("l += len(rr.%s)/2 + 1\n")
|
||||
case `dns:"a"`:
|
||||
o("l += net.IPv4len // %s\n")
|
||||
case `dns:"aaaa"`:
|
||||
o("l += net.IPv6len // %s\n")
|
||||
case `dns:"txt"`:
|
||||
case st.Tag(i) == `dns:"any"`:
|
||||
o("l += len(rr.%s)\n")
|
||||
case st.Tag(i) == `dns:"a"`:
|
||||
o("if len(rr.%s) != 0 { l += net.IPv4len }\n")
|
||||
case st.Tag(i) == `dns:"aaaa"`:
|
||||
o("if len(rr.%s) != 0 { l += net.IPv6len }\n")
|
||||
case st.Tag(i) == `dns:"txt"`:
|
||||
o("for _, t := range rr.%s { l += len(t) + 1 }\n")
|
||||
case `dns:"uint48"`:
|
||||
case st.Tag(i) == `dns:"uint48"`:
|
||||
o("l += 6 // %s\n")
|
||||
case "":
|
||||
case st.Tag(i) == "":
|
||||
switch st.Field(i).Type().(*types.Basic).Kind() {
|
||||
case types.Uint8:
|
||||
o("l += 1 // %s\n")
|
||||
o("l++ // %s\n")
|
||||
case types.Uint16:
|
||||
o("l += 2 // %s\n")
|
||||
case types.Uint32:
|
||||
|
|
@ -223,7 +234,7 @@ func main() {
|
|||
continue
|
||||
}
|
||||
fmt.Fprintf(b, "func (rr *%s) copy() RR {\n", name)
|
||||
fields := []string{"*rr.Hdr.copyHeader()"}
|
||||
fields := []string{"rr.Hdr"}
|
||||
for i := 1; i < st.NumFields(); i++ {
|
||||
f := st.Field(i).Name()
|
||||
if sl, ok := st.Field(i).Type().(*types.Slice); ok {
|
||||
|
|
@ -233,6 +244,13 @@ func main() {
|
|||
splits := strings.Split(t, ".")
|
||||
t = splits[len(splits)-1]
|
||||
}
|
||||
// For the EDNS0 interface (used in the OPT RR), we need to call the copy method on each element.
|
||||
if t == "EDNS0" {
|
||||
fmt.Fprintf(b, "%s := make([]%s, len(rr.%s));\nfor i,e := range rr.%s {\n %s[i] = e.copy()\n}\n",
|
||||
f, t, f, f, f)
|
||||
fields = append(fields, f)
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(b, "%s := make([]%s, len(rr.%s)); copy(%s, rr.%s)\n",
|
||||
f, t, f, f, f)
|
||||
fields = append(fields, f)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,30 @@
|
|||
// +build !windows,!plan9
|
||||
// +build !windows
|
||||
|
||||
package dns
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
// This is the required size of the OOB buffer to pass to ReadMsgUDP.
|
||||
var udpOOBSize = func() int {
|
||||
// We can't know whether we'll get an IPv4 control message or an
|
||||
// IPv6 control message ahead of time. To get around this, we size
|
||||
// the buffer equal to the largest of the two.
|
||||
|
||||
oob4 := ipv4.NewControlMessage(ipv4.FlagDst | ipv4.FlagInterface)
|
||||
oob6 := ipv6.NewControlMessage(ipv6.FlagDst | ipv6.FlagInterface)
|
||||
|
||||
if len(oob4) > len(oob6) {
|
||||
return len(oob4)
|
||||
}
|
||||
|
||||
return len(oob6)
|
||||
}()
|
||||
|
||||
// SessionUDP holds the remote address and the associated
|
||||
// out-of-band data.
|
||||
type SessionUDP struct {
|
||||
|
|
@ -17,33 +35,10 @@ type SessionUDP struct {
|
|||
// RemoteAddr returns the remote network address.
|
||||
func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
|
||||
|
||||
// setUDPSocketOptions sets the UDP socket options.
|
||||
// This function is implemented on a per platform basis. See udp_*.go for more details
|
||||
func setUDPSocketOptions(conn *net.UDPConn) error {
|
||||
sa, err := getUDPSocketName(conn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch sa.(type) {
|
||||
case *syscall.SockaddrInet6:
|
||||
v6only, err := getUDPSocketOptions6Only(conn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
setUDPSocketOptions6(conn)
|
||||
if !v6only {
|
||||
setUDPSocketOptions4(conn)
|
||||
}
|
||||
case *syscall.SockaddrInet4:
|
||||
setUDPSocketOptions4(conn)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
|
||||
// net.UDPAddr.
|
||||
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
||||
oob := make([]byte, 40)
|
||||
oob := make([]byte, udpOOBSize)
|
||||
n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob)
|
||||
if err != nil {
|
||||
return n, nil, err
|
||||
|
|
@ -51,8 +46,57 @@ func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
|||
return n, &SessionUDP{raddr, oob[:oobn]}, err
|
||||
}
|
||||
|
||||
// WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr.
|
||||
// WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
|
||||
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
|
||||
n, _, err := conn.WriteMsgUDP(b, session.context, session.raddr)
|
||||
oob := correctSource(session.context)
|
||||
n, _, err := conn.WriteMsgUDP(b, oob, session.raddr)
|
||||
return n, err
|
||||
}
|
||||
|
||||
func setUDPSocketOptions(conn *net.UDPConn) error {
|
||||
// Try setting the flags for both families and ignore the errors unless they
|
||||
// both error.
|
||||
err6 := ipv6.NewPacketConn(conn).SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true)
|
||||
err4 := ipv4.NewPacketConn(conn).SetControlMessage(ipv4.FlagDst|ipv4.FlagInterface, true)
|
||||
if err6 != nil && err4 != nil {
|
||||
return err4
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseDstFromOOB takes oob data and returns the destination IP.
|
||||
func parseDstFromOOB(oob []byte) net.IP {
|
||||
// Start with IPv6 and then fallback to IPv4
|
||||
// TODO(fastest963): Figure out a way to prefer one or the other. Looking at
|
||||
// the lvl of the header for a 0 or 41 isn't cross-platform.
|
||||
cm6 := new(ipv6.ControlMessage)
|
||||
if cm6.Parse(oob) == nil && cm6.Dst != nil {
|
||||
return cm6.Dst
|
||||
}
|
||||
cm4 := new(ipv4.ControlMessage)
|
||||
if cm4.Parse(oob) == nil && cm4.Dst != nil {
|
||||
return cm4.Dst
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// correctSource takes oob data and returns new oob data with the Src equal to the Dst
|
||||
func correctSource(oob []byte) []byte {
|
||||
dst := parseDstFromOOB(oob)
|
||||
if dst == nil {
|
||||
return nil
|
||||
}
|
||||
// If the dst is definitely an IPv6, then use ipv6's ControlMessage to
|
||||
// respond otherwise use ipv4's because ipv6's marshal ignores ipv4
|
||||
// addresses.
|
||||
if dst.To4() == nil {
|
||||
cm := new(ipv6.ControlMessage)
|
||||
cm.Src = dst
|
||||
oob = cm.Marshal()
|
||||
} else {
|
||||
cm := new(ipv4.ControlMessage)
|
||||
cm.Src = dst
|
||||
oob = cm.Marshal()
|
||||
}
|
||||
return oob
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,73 +0,0 @@
|
|||
// +build linux
|
||||
|
||||
package dns
|
||||
|
||||
// See:
|
||||
// * http://stackoverflow.com/questions/3062205/setting-the-source-ip-for-a-udp-socket and
|
||||
// * http://blog.powerdns.com/2012/10/08/on-binding-datagram-udp-sockets-to-the-any-addresses/
|
||||
//
|
||||
// Why do we need this: When listening on 0.0.0.0 with UDP so kernel decides what is the outgoing
|
||||
// interface, this might not always be the correct one. This code will make sure the egress
|
||||
// packet's interface matched the ingress' one.
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// setUDPSocketOptions4 prepares the v4 socket for sessions.
|
||||
func setUDPSocketOptions4(conn *net.UDPConn) error {
|
||||
file, err := conn.File()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil {
|
||||
return err
|
||||
}
|
||||
// Calling File() above results in the connection becoming blocking, we must fix that.
|
||||
// See https://github.com/miekg/dns/issues/279
|
||||
err = syscall.SetNonblock(int(file.Fd()), true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// setUDPSocketOptions6 prepares the v6 socket for sessions.
|
||||
func setUDPSocketOptions6(conn *net.UDPConn) error {
|
||||
file, err := conn.File()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1); err != nil {
|
||||
return err
|
||||
}
|
||||
err = syscall.SetNonblock(int(file.Fd()), true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getUDPSocketOption6Only return true if the socket is v6 only and false when it is v4/v6 combined
|
||||
// (dualstack).
|
||||
func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) {
|
||||
file, err := conn.File()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
// dual stack. See http://stackoverflow.com/questions/1618240/how-to-support-both-ipv4-and-ipv6-connections
|
||||
v6only, err := syscall.GetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return v6only == 1, nil
|
||||
}
|
||||
|
||||
func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) {
|
||||
file, err := conn.File()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return syscall.Getsockname(int(file.Fd()))
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
// +build !linux,!plan9
|
||||
|
||||
package dns
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// These do nothing. See udp_linux.go for an example of how to implement this.
|
||||
|
||||
// We tried to adhire to some kind of naming scheme.
|
||||
|
||||
func setUDPSocketOptions4(conn *net.UDPConn) error { return nil }
|
||||
func setUDPSocketOptions6(conn *net.UDPConn) error { return nil }
|
||||
func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) { return false, nil }
|
||||
func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) { return nil, nil }
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
func setUDPSocketOptions(conn *net.UDPConn) error { return nil }
|
||||
|
||||
// SessionUDP holds the remote address and the associated
|
||||
// out-of-band data.
|
||||
type SessionUDP struct {
|
||||
raddr *net.UDPAddr
|
||||
context []byte
|
||||
}
|
||||
|
||||
// RemoteAddr returns the remote network address.
|
||||
func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
|
||||
|
||||
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
|
||||
// net.UDPAddr.
|
||||
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
||||
oob := make([]byte, 40)
|
||||
n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob)
|
||||
if err != nil {
|
||||
return n, nil, err
|
||||
}
|
||||
return n, &SessionUDP{raddr, oob[:oobn]}, err
|
||||
}
|
||||
|
||||
// WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr.
|
||||
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
|
||||
n, _, err := conn.WriteMsgUDP(b, session.context, session.raddr)
|
||||
return n, err
|
||||
}
|
||||
|
|
@ -4,31 +4,32 @@ package dns
|
|||
|
||||
import "net"
|
||||
|
||||
// SessionUDP holds the remote address
|
||||
type SessionUDP struct {
|
||||
raddr *net.UDPAddr
|
||||
}
|
||||
|
||||
// RemoteAddr returns the remote network address.
|
||||
func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
|
||||
|
||||
// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
|
||||
// net.UDPAddr.
|
||||
// TODO(fastest963): Once go1.10 is released, use ReadMsgUDP.
|
||||
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
|
||||
n, raddr, err := conn.ReadFrom(b)
|
||||
if err != nil {
|
||||
return n, nil, err
|
||||
}
|
||||
session := &SessionUDP{raddr.(*net.UDPAddr)}
|
||||
return n, session, err
|
||||
return n, &SessionUDP{raddr.(*net.UDPAddr)}, err
|
||||
}
|
||||
|
||||
// WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr.
|
||||
// WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr.
|
||||
// TODO(fastest963): Once go1.10 is released, use WriteMsgUDP.
|
||||
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
|
||||
n, err := conn.WriteTo(b, session.raddr)
|
||||
return n, err
|
||||
return conn.WriteTo(b, session.raddr)
|
||||
}
|
||||
|
||||
func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
|
||||
|
||||
// setUDPSocketOptions sets the UDP socket options.
|
||||
// This function is implemented on a per platform basis. See udp_*.go for more details
|
||||
func setUDPSocketOptions(conn *net.UDPConn) error {
|
||||
return nil
|
||||
}
|
||||
// TODO(fastest963): Once go1.10 is released and we can use *MsgUDP methods
|
||||
// use the standard method in udp.go for these.
|
||||
func setUDPSocketOptions(*net.UDPConn) error { return nil }
|
||||
func parseDstFromOOB([]byte, net.IP) net.IP { return nil }
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@ func (u *Msg) RRsetUsed(rr []RR) {
|
|||
u.Answer = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}})
|
||||
h := r.Header()
|
||||
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: h.Name, Ttl: 0, Rrtype: h.Rrtype, Class: ClassANY}})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -55,7 +56,8 @@ func (u *Msg) RRsetNotUsed(rr []RR) {
|
|||
u.Answer = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassNONE}})
|
||||
h := r.Header()
|
||||
u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: h.Name, Ttl: 0, Rrtype: h.Rrtype, Class: ClassNONE}})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +81,8 @@ func (u *Msg) RemoveRRset(rr []RR) {
|
|||
u.Ns = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: r.Header().Rrtype, Class: ClassANY}})
|
||||
h := r.Header()
|
||||
u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: h.Name, Ttl: 0, Rrtype: h.Rrtype, Class: ClassANY}})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -99,8 +102,9 @@ func (u *Msg) Remove(rr []RR) {
|
|||
u.Ns = make([]RR, 0, len(rr))
|
||||
}
|
||||
for _, r := range rr {
|
||||
r.Header().Class = ClassNONE
|
||||
r.Header().Ttl = 0
|
||||
h := r.Header()
|
||||
h.Class = ClassNONE
|
||||
h.Ttl = 0
|
||||
u.Ns = append(u.Ns, r)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
package dns
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Version is current version of this library.
|
||||
var Version = V{1, 1, 8}
|
||||
|
||||
// V holds the version of this library.
|
||||
type V struct {
|
||||
Major, Minor, Patch int
|
||||
}
|
||||
|
||||
func (v V) String() string {
|
||||
return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
|
@ -16,7 +17,7 @@ type Transfer struct {
|
|||
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds
|
||||
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds
|
||||
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds
|
||||
TsigSecret map[string]string // Secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
|
||||
TsigSecret map[string]string // Secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
|
||||
tsigTimersOnly bool
|
||||
}
|
||||
|
||||
|
|
@ -34,34 +35,40 @@ type Transfer struct {
|
|||
// channel, err := transfer.In(message, master)
|
||||
//
|
||||
func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) {
|
||||
switch q.Question[0].Qtype {
|
||||
case TypeAXFR, TypeIXFR:
|
||||
default:
|
||||
return nil, &Error{"unsupported question type"}
|
||||
}
|
||||
|
||||
timeout := dnsTimeout
|
||||
if t.DialTimeout != 0 {
|
||||
timeout = t.DialTimeout
|
||||
}
|
||||
|
||||
if t.Conn == nil {
|
||||
t.Conn, err = DialTimeout("tcp", a, timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := t.WriteMsg(q); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
env = make(chan *Envelope)
|
||||
go func() {
|
||||
if q.Question[0].Qtype == TypeAXFR {
|
||||
go t.inAxfr(q.Id, env)
|
||||
return
|
||||
}
|
||||
if q.Question[0].Qtype == TypeIXFR {
|
||||
go t.inIxfr(q.Id, env)
|
||||
return
|
||||
}
|
||||
}()
|
||||
switch q.Question[0].Qtype {
|
||||
case TypeAXFR:
|
||||
go t.inAxfr(q, env)
|
||||
case TypeIXFR:
|
||||
go t.inIxfr(q, env)
|
||||
}
|
||||
|
||||
return env, nil
|
||||
}
|
||||
|
||||
func (t *Transfer) inAxfr(id uint16, c chan *Envelope) {
|
||||
func (t *Transfer) inAxfr(q *Msg, c chan *Envelope) {
|
||||
first := true
|
||||
defer t.Close()
|
||||
defer close(c)
|
||||
|
|
@ -76,11 +83,15 @@ func (t *Transfer) inAxfr(id uint16, c chan *Envelope) {
|
|||
c <- &Envelope{nil, err}
|
||||
return
|
||||
}
|
||||
if id != in.Id {
|
||||
if q.Id != in.Id {
|
||||
c <- &Envelope{in.Answer, ErrId}
|
||||
return
|
||||
}
|
||||
if first {
|
||||
if in.Rcode != RcodeSuccess {
|
||||
c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}}
|
||||
return
|
||||
}
|
||||
if !isSOAFirst(in) {
|
||||
c <- &Envelope{in.Answer, ErrSoa}
|
||||
return
|
||||
|
|
@ -105,9 +116,11 @@ func (t *Transfer) inAxfr(id uint16, c chan *Envelope) {
|
|||
}
|
||||
}
|
||||
|
||||
func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
|
||||
serial := uint32(0) // The first serial seen is the current server serial
|
||||
first := true
|
||||
func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) {
|
||||
var serial uint32 // The first serial seen is the current server serial
|
||||
axfr := true
|
||||
n := 0
|
||||
qser := q.Ns[0].(*SOA).Serial
|
||||
defer t.Close()
|
||||
defer close(c)
|
||||
timeout := dnsTimeout
|
||||
|
|
@ -121,17 +134,15 @@ func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
|
|||
c <- &Envelope{nil, err}
|
||||
return
|
||||
}
|
||||
if id != in.Id {
|
||||
if q.Id != in.Id {
|
||||
c <- &Envelope{in.Answer, ErrId}
|
||||
return
|
||||
}
|
||||
if first {
|
||||
// A single SOA RR signals "no changes"
|
||||
if len(in.Answer) == 1 && isSOAFirst(in) {
|
||||
c <- &Envelope{in.Answer, nil}
|
||||
return
|
||||
}
|
||||
|
||||
if in.Rcode != RcodeSuccess {
|
||||
c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}}
|
||||
return
|
||||
}
|
||||
if n == 0 {
|
||||
// Check if the returned answer is ok
|
||||
if !isSOAFirst(in) {
|
||||
c <- &Envelope{in.Answer, ErrSoa}
|
||||
|
|
@ -139,21 +150,30 @@ func (t *Transfer) inIxfr(id uint16, c chan *Envelope) {
|
|||
}
|
||||
// This serial is important
|
||||
serial = in.Answer[0].(*SOA).Serial
|
||||
first = !first
|
||||
// Check if there are no changes in zone
|
||||
if qser >= serial {
|
||||
c <- &Envelope{in.Answer, nil}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Now we need to check each message for SOA records, to see what we need to do
|
||||
if !first {
|
||||
t.tsigTimersOnly = true
|
||||
// If the last record in the IXFR contains the servers' SOA, we should quit
|
||||
if v, ok := in.Answer[len(in.Answer)-1].(*SOA); ok {
|
||||
t.tsigTimersOnly = true
|
||||
for _, rr := range in.Answer {
|
||||
if v, ok := rr.(*SOA); ok {
|
||||
if v.Serial == serial {
|
||||
c <- &Envelope{in.Answer, nil}
|
||||
return
|
||||
n++
|
||||
// quit if it's a full axfr or the the servers' SOA is repeated the third time
|
||||
if axfr && n == 2 || n == 3 {
|
||||
c <- &Envelope{in.Answer, nil}
|
||||
return
|
||||
}
|
||||
} else if axfr {
|
||||
// it's an ixfr
|
||||
axfr = false
|
||||
}
|
||||
}
|
||||
c <- &Envelope{in.Answer, nil}
|
||||
}
|
||||
c <- &Envelope{in.Answer, nil}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -223,22 +243,18 @@ func (t *Transfer) WriteMsg(m *Msg) (err error) {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = t.Write(out); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
_, err = t.Write(out)
|
||||
return err
|
||||
}
|
||||
|
||||
func isSOAFirst(in *Msg) bool {
|
||||
if len(in.Answer) > 0 {
|
||||
return in.Answer[0].Header().Rrtype == TypeSOA
|
||||
}
|
||||
return false
|
||||
return len(in.Answer) > 0 &&
|
||||
in.Answer[0].Header().Rrtype == TypeSOA
|
||||
}
|
||||
|
||||
func isSOALast(in *Msg) bool {
|
||||
if len(in.Answer) > 0 {
|
||||
return in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
|
||||
}
|
||||
return false
|
||||
return len(in.Answer) > 0 &&
|
||||
in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA
|
||||
}
|
||||
|
||||
const errXFR = "bad xfr rcode: %d"
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,158 +0,0 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Parse the $GENERATE statement as used in BIND9 zones.
|
||||
// See http://www.zytrax.com/books/dns/ch8/generate.html for instance.
|
||||
// We are called after '$GENERATE '. After which we expect:
|
||||
// * the range (12-24/2)
|
||||
// * lhs (ownername)
|
||||
// * [[ttl][class]]
|
||||
// * type
|
||||
// * rhs (rdata)
|
||||
// But we are lazy here, only the range is parsed *all* occurrences
|
||||
// of $ after that are interpreted.
|
||||
// Any error are returned as a string value, the empty string signals
|
||||
// "no error".
|
||||
func generate(l lex, c chan lex, t chan *Token, o string) string {
|
||||
step := 1
|
||||
if i := strings.IndexAny(l.token, "/"); i != -1 {
|
||||
if i+1 == len(l.token) {
|
||||
return "bad step in $GENERATE range"
|
||||
}
|
||||
if s, e := strconv.Atoi(l.token[i+1:]); e == nil {
|
||||
if s < 0 {
|
||||
return "bad step in $GENERATE range"
|
||||
}
|
||||
step = s
|
||||
} else {
|
||||
return "bad step in $GENERATE range"
|
||||
}
|
||||
l.token = l.token[:i]
|
||||
}
|
||||
sx := strings.SplitN(l.token, "-", 2)
|
||||
if len(sx) != 2 {
|
||||
return "bad start-stop in $GENERATE range"
|
||||
}
|
||||
start, err := strconv.Atoi(sx[0])
|
||||
if err != nil {
|
||||
return "bad start in $GENERATE range"
|
||||
}
|
||||
end, err := strconv.Atoi(sx[1])
|
||||
if err != nil {
|
||||
return "bad stop in $GENERATE range"
|
||||
}
|
||||
if end < 0 || start < 0 || end < start {
|
||||
return "bad range in $GENERATE range"
|
||||
}
|
||||
|
||||
<-c // _BLANK
|
||||
// Create a complete new string, which we then parse again.
|
||||
s := ""
|
||||
BuildRR:
|
||||
l = <-c
|
||||
if l.value != zNewline && l.value != zEOF {
|
||||
s += l.token
|
||||
goto BuildRR
|
||||
}
|
||||
for i := start; i <= end; i += step {
|
||||
var (
|
||||
escape bool
|
||||
dom bytes.Buffer
|
||||
mod string
|
||||
err string
|
||||
offset int
|
||||
)
|
||||
|
||||
for j := 0; j < len(s); j++ { // No 'range' because we need to jump around
|
||||
switch s[j] {
|
||||
case '\\':
|
||||
if escape {
|
||||
dom.WriteByte('\\')
|
||||
escape = false
|
||||
continue
|
||||
}
|
||||
escape = true
|
||||
case '$':
|
||||
mod = "%d"
|
||||
offset = 0
|
||||
if escape {
|
||||
dom.WriteByte('$')
|
||||
escape = false
|
||||
continue
|
||||
}
|
||||
escape = false
|
||||
if j+1 >= len(s) { // End of the string
|
||||
dom.WriteString(fmt.Sprintf(mod, i+offset))
|
||||
continue
|
||||
} else {
|
||||
if s[j+1] == '$' {
|
||||
dom.WriteByte('$')
|
||||
j++
|
||||
continue
|
||||
}
|
||||
}
|
||||
// Search for { and }
|
||||
if s[j+1] == '{' { // Modifier block
|
||||
sep := strings.Index(s[j+2:], "}")
|
||||
if sep == -1 {
|
||||
return "bad modifier in $GENERATE"
|
||||
}
|
||||
mod, offset, err = modToPrintf(s[j+2 : j+2+sep])
|
||||
if err != "" {
|
||||
return err
|
||||
}
|
||||
j += 2 + sep // Jump to it
|
||||
}
|
||||
dom.WriteString(fmt.Sprintf(mod, i+offset))
|
||||
default:
|
||||
if escape { // Pretty useless here
|
||||
escape = false
|
||||
continue
|
||||
}
|
||||
dom.WriteByte(s[j])
|
||||
}
|
||||
}
|
||||
// Re-parse the RR and send it on the current channel t
|
||||
rx, e := NewRR("$ORIGIN " + o + "\n" + dom.String())
|
||||
if e != nil {
|
||||
return e.(*ParseError).err
|
||||
}
|
||||
t <- &Token{RR: rx}
|
||||
// Its more efficient to first built the rrlist and then parse it in
|
||||
// one go! But is this a problem?
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Convert a $GENERATE modifier 0,0,d to something Printf can deal with.
|
||||
func modToPrintf(s string) (string, int, string) {
|
||||
xs := strings.SplitN(s, ",", 3)
|
||||
if len(xs) != 3 {
|
||||
return "", 0, "bad modifier in $GENERATE"
|
||||
}
|
||||
// xs[0] is offset, xs[1] is width, xs[2] is base
|
||||
if xs[2] != "o" && xs[2] != "d" && xs[2] != "x" && xs[2] != "X" {
|
||||
return "", 0, "bad base in $GENERATE"
|
||||
}
|
||||
offset, err := strconv.Atoi(xs[0])
|
||||
if err != nil || offset > 255 {
|
||||
return "", 0, "bad offset in $GENERATE"
|
||||
}
|
||||
width, err := strconv.Atoi(xs[1])
|
||||
if err != nil || width > 255 {
|
||||
return "", offset, "bad width in $GENERATE"
|
||||
}
|
||||
switch {
|
||||
case width < 0:
|
||||
return "", offset, "bad width in $GENERATE"
|
||||
case width == 0:
|
||||
return "%" + xs[1] + xs[2], offset, ""
|
||||
}
|
||||
return "%0" + xs[1] + xs[2], offset, ""
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,974 +0,0 @@
|
|||
package dns
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type debugging bool
|
||||
|
||||
const debug debugging = false
|
||||
|
||||
func (d debugging) Printf(format string, args ...interface{}) {
|
||||
if d {
|
||||
log.Printf(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
const maxTok = 2048 // Largest token we can return.
|
||||
const maxUint16 = 1<<16 - 1
|
||||
|
||||
// Tokinize a RFC 1035 zone file. The tokenizer will normalize it:
|
||||
// * Add ownernames if they are left blank;
|
||||
// * Suppress sequences of spaces;
|
||||
// * Make each RR fit on one line (_NEWLINE is send as last)
|
||||
// * Handle comments: ;
|
||||
// * Handle braces - anywhere.
|
||||
const (
|
||||
// Zonefile
|
||||
zEOF = iota
|
||||
zString
|
||||
zBlank
|
||||
zQuote
|
||||
zNewline
|
||||
zRrtpe
|
||||
zOwner
|
||||
zClass
|
||||
zDirOrigin // $ORIGIN
|
||||
zDirTtl // $TTL
|
||||
zDirInclude // $INCLUDE
|
||||
zDirGenerate // $GENERATE
|
||||
|
||||
// Privatekey file
|
||||
zValue
|
||||
zKey
|
||||
|
||||
zExpectOwnerDir // Ownername
|
||||
zExpectOwnerBl // Whitespace after the ownername
|
||||
zExpectAny // Expect rrtype, ttl or class
|
||||
zExpectAnyNoClass // Expect rrtype or ttl
|
||||
zExpectAnyNoClassBl // The whitespace after _EXPECT_ANY_NOCLASS
|
||||
zExpectAnyNoTtl // Expect rrtype or class
|
||||
zExpectAnyNoTtlBl // Whitespace after _EXPECT_ANY_NOTTL
|
||||
zExpectRrtype // Expect rrtype
|
||||
zExpectRrtypeBl // Whitespace BEFORE rrtype
|
||||
zExpectRdata // The first element of the rdata
|
||||
zExpectDirTtlBl // Space after directive $TTL
|
||||
zExpectDirTtl // Directive $TTL
|
||||
zExpectDirOriginBl // Space after directive $ORIGIN
|
||||
zExpectDirOrigin // Directive $ORIGIN
|
||||
zExpectDirIncludeBl // Space after directive $INCLUDE
|
||||
zExpectDirInclude // Directive $INCLUDE
|
||||
zExpectDirGenerate // Directive $GENERATE
|
||||
zExpectDirGenerateBl // Space after directive $GENERATE
|
||||
)
|
||||
|
||||
// ParseError is a parsing error. It contains the parse error and the location in the io.Reader
|
||||
// where the error occurred.
|
||||
type ParseError struct {
|
||||
file string
|
||||
err string
|
||||
lex lex
|
||||
}
|
||||
|
||||
func (e *ParseError) Error() (s string) {
|
||||
if e.file != "" {
|
||||
s = e.file + ": "
|
||||
}
|
||||
s += "dns: " + e.err + ": " + strconv.QuoteToASCII(e.lex.token) + " at line: " +
|
||||
strconv.Itoa(e.lex.line) + ":" + strconv.Itoa(e.lex.column)
|
||||
return
|
||||
}
|
||||
|
||||
type lex struct {
|
||||
token string // text of the token
|
||||
tokenUpper string // uppercase text of the token
|
||||
length int // length of the token
|
||||
err bool // when true, token text has lexer error
|
||||
value uint8 // value: zString, _BLANK, etc.
|
||||
line int // line in the file
|
||||
column int // column in the file
|
||||
torc uint16 // type or class as parsed in the lexer, we only need to look this up in the grammar
|
||||
comment string // any comment text seen
|
||||
}
|
||||
|
||||
// Token holds the token that are returned when a zone file is parsed.
|
||||
type Token struct {
|
||||
// The scanned resource record when error is not nil.
|
||||
RR
|
||||
// When an error occurred, this has the error specifics.
|
||||
Error *ParseError
|
||||
// A potential comment positioned after the RR and on the same line.
|
||||
Comment string
|
||||
}
|
||||
|
||||
// NewRR reads the RR contained in the string s. Only the first RR is
|
||||
// returned. If s contains no RR, return nil with no error. The class
|
||||
// defaults to IN and TTL defaults to 3600. The full zone file syntax
|
||||
// like $TTL, $ORIGIN, etc. is supported. All fields of the returned
|
||||
// RR are set, except RR.Header().Rdlength which is set to 0.
|
||||
func NewRR(s string) (RR, error) {
|
||||
if len(s) > 0 && s[len(s)-1] != '\n' { // We need a closing newline
|
||||
return ReadRR(strings.NewReader(s+"\n"), "")
|
||||
}
|
||||
return ReadRR(strings.NewReader(s), "")
|
||||
}
|
||||
|
||||
// ReadRR reads the RR contained in q.
|
||||
// See NewRR for more documentation.
|
||||
func ReadRR(q io.Reader, filename string) (RR, error) {
|
||||
r := <-parseZoneHelper(q, ".", filename, 1)
|
||||
if r == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if r.Error != nil {
|
||||
return nil, r.Error
|
||||
}
|
||||
return r.RR, nil
|
||||
}
|
||||
|
||||
// ParseZone reads a RFC 1035 style zonefile from r. It returns *Tokens on the
|
||||
// returned channel, which consist out the parsed RR, a potential comment or an error.
|
||||
// If there is an error the RR is nil. The string file is only used
|
||||
// in error reporting. The string origin is used as the initial origin, as
|
||||
// if the file would start with: $ORIGIN origin .
|
||||
// The directives $INCLUDE, $ORIGIN, $TTL and $GENERATE are supported.
|
||||
// The channel t is closed by ParseZone when the end of r is reached.
|
||||
//
|
||||
// Basic usage pattern when reading from a string (z) containing the
|
||||
// zone data:
|
||||
//
|
||||
// for x := range dns.ParseZone(strings.NewReader(z), "", "") {
|
||||
// if x.Error != nil {
|
||||
// // log.Println(x.Error)
|
||||
// } else {
|
||||
// // Do something with x.RR
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Comments specified after an RR (and on the same line!) are returned too:
|
||||
//
|
||||
// foo. IN A 10.0.0.1 ; this is a comment
|
||||
//
|
||||
// The text "; this is comment" is returned in Token.Comment. Comments inside the
|
||||
// RR are discarded. Comments on a line by themselves are discarded too.
|
||||
func ParseZone(r io.Reader, origin, file string) chan *Token {
|
||||
return parseZoneHelper(r, origin, file, 10000)
|
||||
}
|
||||
|
||||
func parseZoneHelper(r io.Reader, origin, file string, chansize int) chan *Token {
|
||||
t := make(chan *Token, chansize)
|
||||
go parseZone(r, origin, file, t, 0)
|
||||
return t
|
||||
}
|
||||
|
||||
func parseZone(r io.Reader, origin, f string, t chan *Token, include int) {
|
||||
defer func() {
|
||||
if include == 0 {
|
||||
close(t)
|
||||
}
|
||||
}()
|
||||
s := scanInit(r)
|
||||
c := make(chan lex)
|
||||
// Start the lexer
|
||||
go zlexer(s, c)
|
||||
// 6 possible beginnings of a line, _ is a space
|
||||
// 0. zRRTYPE -> all omitted until the rrtype
|
||||
// 1. zOwner _ zRrtype -> class/ttl omitted
|
||||
// 2. zOwner _ zString _ zRrtype -> class omitted
|
||||
// 3. zOwner _ zString _ zClass _ zRrtype -> ttl/class
|
||||
// 4. zOwner _ zClass _ zRrtype -> ttl omitted
|
||||
// 5. zOwner _ zClass _ zString _ zRrtype -> class/ttl (reversed)
|
||||
// After detecting these, we know the zRrtype so we can jump to functions
|
||||
// handling the rdata for each of these types.
|
||||
|
||||
if origin == "" {
|
||||
origin = "."
|
||||
}
|
||||
origin = Fqdn(origin)
|
||||
if _, ok := IsDomainName(origin); !ok {
|
||||
t <- &Token{Error: &ParseError{f, "bad initial origin name", lex{}}}
|
||||
return
|
||||
}
|
||||
|
||||
st := zExpectOwnerDir // initial state
|
||||
var h RR_Header
|
||||
var defttl uint32 = defaultTtl
|
||||
var prevName string
|
||||
for l := range c {
|
||||
// Lexer spotted an error already
|
||||
if l.err == true {
|
||||
t <- &Token{Error: &ParseError{f, l.token, l}}
|
||||
return
|
||||
|
||||
}
|
||||
switch st {
|
||||
case zExpectOwnerDir:
|
||||
// We can also expect a directive, like $TTL or $ORIGIN
|
||||
h.Ttl = defttl
|
||||
h.Class = ClassINET
|
||||
switch l.value {
|
||||
case zNewline:
|
||||
st = zExpectOwnerDir
|
||||
case zOwner:
|
||||
h.Name = l.token
|
||||
if l.token[0] == '@' {
|
||||
h.Name = origin
|
||||
prevName = h.Name
|
||||
st = zExpectOwnerBl
|
||||
break
|
||||
}
|
||||
if h.Name[l.length-1] != '.' {
|
||||
h.Name = appendOrigin(h.Name, origin)
|
||||
}
|
||||
_, ok := IsDomainName(l.token)
|
||||
if !ok {
|
||||
t <- &Token{Error: &ParseError{f, "bad owner name", l}}
|
||||
return
|
||||
}
|
||||
prevName = h.Name
|
||||
st = zExpectOwnerBl
|
||||
case zDirTtl:
|
||||
st = zExpectDirTtlBl
|
||||
case zDirOrigin:
|
||||
st = zExpectDirOriginBl
|
||||
case zDirInclude:
|
||||
st = zExpectDirIncludeBl
|
||||
case zDirGenerate:
|
||||
st = zExpectDirGenerateBl
|
||||
case zRrtpe:
|
||||
h.Name = prevName
|
||||
h.Rrtype = l.torc
|
||||
st = zExpectRdata
|
||||
case zClass:
|
||||
h.Name = prevName
|
||||
h.Class = l.torc
|
||||
st = zExpectAnyNoClassBl
|
||||
case zBlank:
|
||||
// Discard, can happen when there is nothing on the
|
||||
// line except the RR type
|
||||
case zString:
|
||||
ttl, ok := stringToTtl(l.token)
|
||||
if !ok {
|
||||
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
||||
return
|
||||
}
|
||||
h.Ttl = ttl
|
||||
// Don't about the defttl, we should take the $TTL value
|
||||
// defttl = ttl
|
||||
st = zExpectAnyNoTtlBl
|
||||
|
||||
default:
|
||||
t <- &Token{Error: &ParseError{f, "syntax error at beginning", l}}
|
||||
return
|
||||
}
|
||||
case zExpectDirIncludeBl:
|
||||
if l.value != zBlank {
|
||||
t <- &Token{Error: &ParseError{f, "no blank after $INCLUDE-directive", l}}
|
||||
return
|
||||
}
|
||||
st = zExpectDirInclude
|
||||
case zExpectDirInclude:
|
||||
if l.value != zString {
|
||||
t <- &Token{Error: &ParseError{f, "expecting $INCLUDE value, not this...", l}}
|
||||
return
|
||||
}
|
||||
neworigin := origin // There may be optionally a new origin set after the filename, if not use current one
|
||||
l := <-c
|
||||
switch l.value {
|
||||
case zBlank:
|
||||
l := <-c
|
||||
if l.value == zString {
|
||||
if _, ok := IsDomainName(l.token); !ok || l.length == 0 || l.err {
|
||||
t <- &Token{Error: &ParseError{f, "bad origin name", l}}
|
||||
return
|
||||
}
|
||||
// a new origin is specified.
|
||||
if l.token[l.length-1] != '.' {
|
||||
if origin != "." { // Prevent .. endings
|
||||
neworigin = l.token + "." + origin
|
||||
} else {
|
||||
neworigin = l.token + origin
|
||||
}
|
||||
} else {
|
||||
neworigin = l.token
|
||||
}
|
||||
}
|
||||
case zNewline, zEOF:
|
||||
// Ok
|
||||
default:
|
||||
t <- &Token{Error: &ParseError{f, "garbage after $INCLUDE", l}}
|
||||
return
|
||||
}
|
||||
// Start with the new file
|
||||
r1, e1 := os.Open(l.token)
|
||||
if e1 != nil {
|
||||
t <- &Token{Error: &ParseError{f, "failed to open `" + l.token + "'", l}}
|
||||
return
|
||||
}
|
||||
if include+1 > 7 {
|
||||
t <- &Token{Error: &ParseError{f, "too deeply nested $INCLUDE", l}}
|
||||
return
|
||||
}
|
||||
parseZone(r1, l.token, neworigin, t, include+1)
|
||||
st = zExpectOwnerDir
|
||||
case zExpectDirTtlBl:
|
||||
if l.value != zBlank {
|
||||
t <- &Token{Error: &ParseError{f, "no blank after $TTL-directive", l}}
|
||||
return
|
||||
}
|
||||
st = zExpectDirTtl
|
||||
case zExpectDirTtl:
|
||||
if l.value != zString {
|
||||
t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
|
||||
return
|
||||
}
|
||||
if e, _ := slurpRemainder(c, f); e != nil {
|
||||
t <- &Token{Error: e}
|
||||
return
|
||||
}
|
||||
ttl, ok := stringToTtl(l.token)
|
||||
if !ok {
|
||||
t <- &Token{Error: &ParseError{f, "expecting $TTL value, not this...", l}}
|
||||
return
|
||||
}
|
||||
defttl = ttl
|
||||
st = zExpectOwnerDir
|
||||
case zExpectDirOriginBl:
|
||||
if l.value != zBlank {
|
||||
t <- &Token{Error: &ParseError{f, "no blank after $ORIGIN-directive", l}}
|
||||
return
|
||||
}
|
||||
st = zExpectDirOrigin
|
||||
case zExpectDirOrigin:
|
||||
if l.value != zString {
|
||||
t <- &Token{Error: &ParseError{f, "expecting $ORIGIN value, not this...", l}}
|
||||
return
|
||||
}
|
||||
if e, _ := slurpRemainder(c, f); e != nil {
|
||||
t <- &Token{Error: e}
|
||||
}
|
||||
if _, ok := IsDomainName(l.token); !ok {
|
||||
t <- &Token{Error: &ParseError{f, "bad origin name", l}}
|
||||
return
|
||||
}
|
||||
if l.token[l.length-1] != '.' {
|
||||
if origin != "." { // Prevent .. endings
|
||||
origin = l.token + "." + origin
|
||||
} else {
|
||||
origin = l.token + origin
|
||||
}
|
||||
} else {
|
||||
origin = l.token
|
||||
}
|
||||
st = zExpectOwnerDir
|
||||
case zExpectDirGenerateBl:
|
||||
if l.value != zBlank {
|
||||
t <- &Token{Error: &ParseError{f, "no blank after $GENERATE-directive", l}}
|
||||
return
|
||||
}
|
||||
st = zExpectDirGenerate
|
||||
case zExpectDirGenerate:
|
||||
if l.value != zString {
|
||||
t <- &Token{Error: &ParseError{f, "expecting $GENERATE value, not this...", l}}
|
||||
return
|
||||
}
|
||||
if e := generate(l, c, t, origin); e != "" {
|
||||
t <- &Token{Error: &ParseError{f, e, l}}
|
||||
return
|
||||
}
|
||||
st = zExpectOwnerDir
|
||||
case zExpectOwnerBl:
|
||||
if l.value != zBlank {
|
||||
t <- &Token{Error: &ParseError{f, "no blank after owner", l}}
|
||||
return
|
||||
}
|
||||
st = zExpectAny
|
||||
case zExpectAny:
|
||||
switch l.value {
|
||||
case zRrtpe:
|
||||
h.Rrtype = l.torc
|
||||
st = zExpectRdata
|
||||
case zClass:
|
||||
h.Class = l.torc
|
||||
st = zExpectAnyNoClassBl
|
||||
case zString:
|
||||
ttl, ok := stringToTtl(l.token)
|
||||
if !ok {
|
||||
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
||||
return
|
||||
}
|
||||
h.Ttl = ttl
|
||||
// defttl = ttl // don't set the defttl here
|
||||
st = zExpectAnyNoTtlBl
|
||||
default:
|
||||
t <- &Token{Error: &ParseError{f, "expecting RR type, TTL or class, not this...", l}}
|
||||
return
|
||||
}
|
||||
case zExpectAnyNoClassBl:
|
||||
if l.value != zBlank {
|
||||
t <- &Token{Error: &ParseError{f, "no blank before class", l}}
|
||||
return
|
||||
}
|
||||
st = zExpectAnyNoClass
|
||||
case zExpectAnyNoTtlBl:
|
||||
if l.value != zBlank {
|
||||
t <- &Token{Error: &ParseError{f, "no blank before TTL", l}}
|
||||
return
|
||||
}
|
||||
st = zExpectAnyNoTtl
|
||||
case zExpectAnyNoTtl:
|
||||
switch l.value {
|
||||
case zClass:
|
||||
h.Class = l.torc
|
||||
st = zExpectRrtypeBl
|
||||
case zRrtpe:
|
||||
h.Rrtype = l.torc
|
||||
st = zExpectRdata
|
||||
default:
|
||||
t <- &Token{Error: &ParseError{f, "expecting RR type or class, not this...", l}}
|
||||
return
|
||||
}
|
||||
case zExpectAnyNoClass:
|
||||
switch l.value {
|
||||
case zString:
|
||||
ttl, ok := stringToTtl(l.token)
|
||||
if !ok {
|
||||
t <- &Token{Error: &ParseError{f, "not a TTL", l}}
|
||||
return
|
||||
}
|
||||
h.Ttl = ttl
|
||||
// defttl = ttl // don't set the def ttl anymore
|
||||
st = zExpectRrtypeBl
|
||||
case zRrtpe:
|
||||
h.Rrtype = l.torc
|
||||
st = zExpectRdata
|
||||
default:
|
||||
t <- &Token{Error: &ParseError{f, "expecting RR type or TTL, not this...", l}}
|
||||
return
|
||||
}
|
||||
case zExpectRrtypeBl:
|
||||
if l.value != zBlank {
|
||||
t <- &Token{Error: &ParseError{f, "no blank before RR type", l}}
|
||||
return
|
||||
}
|
||||
st = zExpectRrtype
|
||||
case zExpectRrtype:
|
||||
if l.value != zRrtpe {
|
||||
t <- &Token{Error: &ParseError{f, "unknown RR type", l}}
|
||||
return
|
||||
}
|
||||
h.Rrtype = l.torc
|
||||
st = zExpectRdata
|
||||
case zExpectRdata:
|
||||
r, e, c1 := setRR(h, c, origin, f)
|
||||
if e != nil {
|
||||
// If e.lex is nil than we have encounter a unknown RR type
|
||||
// in that case we substitute our current lex token
|
||||
if e.lex.token == "" && e.lex.value == 0 {
|
||||
e.lex = l // Uh, dirty
|
||||
}
|
||||
t <- &Token{Error: e}
|
||||
return
|
||||
}
|
||||
t <- &Token{RR: r, Comment: c1}
|
||||
st = zExpectOwnerDir
|
||||
}
|
||||
}
|
||||
// If we get here, we and the h.Rrtype is still zero, we haven't parsed anything, this
|
||||
// is not an error, because an empty zone file is still a zone file.
|
||||
}
|
||||
|
||||
// zlexer scans the sourcefile and returns tokens on the channel c.
|
||||
func zlexer(s *scan, c chan lex) {
|
||||
var l lex
|
||||
str := make([]byte, maxTok) // Should be enough for any token
|
||||
stri := 0 // Offset in str (0 means empty)
|
||||
com := make([]byte, maxTok) // Hold comment text
|
||||
comi := 0
|
||||
quote := false
|
||||
escape := false
|
||||
space := false
|
||||
commt := false
|
||||
rrtype := false
|
||||
owner := true
|
||||
brace := 0
|
||||
x, err := s.tokenText()
|
||||
defer close(c)
|
||||
for err == nil {
|
||||
l.column = s.position.Column
|
||||
l.line = s.position.Line
|
||||
if stri >= maxTok {
|
||||
l.token = "token length insufficient for parsing"
|
||||
l.err = true
|
||||
debug.Printf("[%+v]", l.token)
|
||||
c <- l
|
||||
return
|
||||
}
|
||||
if comi >= maxTok {
|
||||
l.token = "comment length insufficient for parsing"
|
||||
l.err = true
|
||||
debug.Printf("[%+v]", l.token)
|
||||
c <- l
|
||||
return
|
||||
}
|
||||
|
||||
switch x {
|
||||
case ' ', '\t':
|
||||
if escape {
|
||||
escape = false
|
||||
str[stri] = x
|
||||
stri++
|
||||
break
|
||||
}
|
||||
if quote {
|
||||
// Inside quotes this is legal
|
||||
str[stri] = x
|
||||
stri++
|
||||
break
|
||||
}
|
||||
if commt {
|
||||
com[comi] = x
|
||||
comi++
|
||||
break
|
||||
}
|
||||
if stri == 0 {
|
||||
// Space directly in the beginning, handled in the grammar
|
||||
} else if owner {
|
||||
// If we have a string and its the first, make it an owner
|
||||
l.value = zOwner
|
||||
l.token = string(str[:stri])
|
||||
l.tokenUpper = strings.ToUpper(l.token)
|
||||
l.length = stri
|
||||
// escape $... start with a \ not a $, so this will work
|
||||
switch l.tokenUpper {
|
||||
case "$TTL":
|
||||
l.value = zDirTtl
|
||||
case "$ORIGIN":
|
||||
l.value = zDirOrigin
|
||||
case "$INCLUDE":
|
||||
l.value = zDirInclude
|
||||
case "$GENERATE":
|
||||
l.value = zDirGenerate
|
||||
}
|
||||
debug.Printf("[7 %+v]", l.token)
|
||||
c <- l
|
||||
} else {
|
||||
l.value = zString
|
||||
l.token = string(str[:stri])
|
||||
l.tokenUpper = strings.ToUpper(l.token)
|
||||
l.length = stri
|
||||
if !rrtype {
|
||||
if t, ok := StringToType[l.tokenUpper]; ok {
|
||||
l.value = zRrtpe
|
||||
l.torc = t
|
||||
rrtype = true
|
||||
} else {
|
||||
if strings.HasPrefix(l.tokenUpper, "TYPE") {
|
||||
t, ok := typeToInt(l.token)
|
||||
if !ok {
|
||||
l.token = "unknown RR type"
|
||||
l.err = true
|
||||
c <- l
|
||||
return
|
||||
}
|
||||
l.value = zRrtpe
|
||||
l.torc = t
|
||||
}
|
||||
}
|
||||
if t, ok := StringToClass[l.tokenUpper]; ok {
|
||||
l.value = zClass
|
||||
l.torc = t
|
||||
} else {
|
||||
if strings.HasPrefix(l.tokenUpper, "CLASS") {
|
||||
t, ok := classToInt(l.token)
|
||||
if !ok {
|
||||
l.token = "unknown class"
|
||||
l.err = true
|
||||
c <- l
|
||||
return
|
||||
}
|
||||
l.value = zClass
|
||||
l.torc = t
|
||||
}
|
||||
}
|
||||
}
|
||||
debug.Printf("[6 %+v]", l.token)
|
||||
c <- l
|
||||
}
|
||||
stri = 0
|
||||
// I reverse space stuff here
|
||||
if !space && !commt {
|
||||
l.value = zBlank
|
||||
l.token = " "
|
||||
l.length = 1
|
||||
debug.Printf("[5 %+v]", l.token)
|
||||
c <- l
|
||||
}
|
||||
owner = false
|
||||
space = true
|
||||
case ';':
|
||||
if escape {
|
||||
escape = false
|
||||
str[stri] = x
|
||||
stri++
|
||||
break
|
||||
}
|
||||
if quote {
|
||||
// Inside quotes this is legal
|
||||
str[stri] = x
|
||||
stri++
|
||||
break
|
||||
}
|
||||
if stri > 0 {
|
||||
l.value = zString
|
||||
l.token = string(str[:stri])
|
||||
l.length = stri
|
||||
debug.Printf("[4 %+v]", l.token)
|
||||
c <- l
|
||||
stri = 0
|
||||
}
|
||||
commt = true
|
||||
com[comi] = ';'
|
||||
comi++
|
||||
case '\r':
|
||||
escape = false
|
||||
if quote {
|
||||
str[stri] = x
|
||||
stri++
|
||||
break
|
||||
}
|
||||
// discard if outside of quotes
|
||||
case '\n':
|
||||
escape = false
|
||||
// Escaped newline
|
||||
if quote {
|
||||
str[stri] = x
|
||||
stri++
|
||||
break
|
||||
}
|
||||
// inside quotes this is legal
|
||||
if commt {
|
||||
// Reset a comment
|
||||
commt = false
|
||||
rrtype = false
|
||||
stri = 0
|
||||
// If not in a brace this ends the comment AND the RR
|
||||
if brace == 0 {
|
||||
owner = true
|
||||
owner = true
|
||||
l.value = zNewline
|
||||
l.token = "\n"
|
||||
l.length = 1
|
||||
l.comment = string(com[:comi])
|
||||
debug.Printf("[3 %+v %+v]", l.token, l.comment)
|
||||
c <- l
|
||||
l.comment = ""
|
||||
comi = 0
|
||||
break
|
||||
}
|
||||
com[comi] = ' ' // convert newline to space
|
||||
comi++
|
||||
break
|
||||
}
|
||||
|
||||
if brace == 0 {
|
||||
// If there is previous text, we should output it here
|
||||
if stri != 0 {
|
||||
l.value = zString
|
||||
l.token = string(str[:stri])
|
||||
l.tokenUpper = strings.ToUpper(l.token)
|
||||
|
||||
l.length = stri
|
||||
if !rrtype {
|
||||
if t, ok := StringToType[l.tokenUpper]; ok {
|
||||
l.value = zRrtpe
|
||||
l.torc = t
|
||||
rrtype = true
|
||||
}
|
||||
}
|
||||
debug.Printf("[2 %+v]", l.token)
|
||||
c <- l
|
||||
}
|
||||
l.value = zNewline
|
||||
l.token = "\n"
|
||||
l.length = 1
|
||||
debug.Printf("[1 %+v]", l.token)
|
||||
c <- l
|
||||
stri = 0
|
||||
commt = false
|
||||
rrtype = false
|
||||
owner = true
|
||||
comi = 0
|
||||
}
|
||||
case '\\':
|
||||
// comments do not get escaped chars, everything is copied
|
||||
if commt {
|
||||
com[comi] = x
|
||||
comi++
|
||||
break
|
||||
}
|
||||
// something already escaped must be in string
|
||||
if escape {
|
||||
str[stri] = x
|
||||
stri++
|
||||
escape = false
|
||||
break
|
||||
}
|
||||
// something escaped outside of string gets added to string
|
||||
str[stri] = x
|
||||
stri++
|
||||
escape = true
|
||||
case '"':
|
||||
if commt {
|
||||
com[comi] = x
|
||||
comi++
|
||||
break
|
||||
}
|
||||
if escape {
|
||||
str[stri] = x
|
||||
stri++
|
||||
escape = false
|
||||
break
|
||||
}
|
||||
space = false
|
||||
// send previous gathered text and the quote
|
||||
if stri != 0 {
|
||||
l.value = zString
|
||||
l.token = string(str[:stri])
|
||||
l.length = stri
|
||||
|
||||
debug.Printf("[%+v]", l.token)
|
||||
c <- l
|
||||
stri = 0
|
||||
}
|
||||
|
||||
// send quote itself as separate token
|
||||
l.value = zQuote
|
||||
l.token = "\""
|
||||
l.length = 1
|
||||
c <- l
|
||||
quote = !quote
|
||||
case '(', ')':
|
||||
if commt {
|
||||
com[comi] = x
|
||||
comi++
|
||||
break
|
||||
}
|
||||
if escape {
|
||||
str[stri] = x
|
||||
stri++
|
||||
escape = false
|
||||
break
|
||||
}
|
||||
if quote {
|
||||
str[stri] = x
|
||||
stri++
|
||||
break
|
||||
}
|
||||
switch x {
|
||||
case ')':
|
||||
brace--
|
||||
if brace < 0 {
|
||||
l.token = "extra closing brace"
|
||||
l.err = true
|
||||
debug.Printf("[%+v]", l.token)
|
||||
c <- l
|
||||
return
|
||||
}
|
||||
case '(':
|
||||
brace++
|
||||
}
|
||||
default:
|
||||
escape = false
|
||||
if commt {
|
||||
com[comi] = x
|
||||
comi++
|
||||
break
|
||||
}
|
||||
str[stri] = x
|
||||
stri++
|
||||
space = false
|
||||
}
|
||||
x, err = s.tokenText()
|
||||
}
|
||||
if stri > 0 {
|
||||
// Send remainder
|
||||
l.token = string(str[:stri])
|
||||
l.length = stri
|
||||
l.value = zString
|
||||
debug.Printf("[%+v]", l.token)
|
||||
c <- l
|
||||
}
|
||||
}
|
||||
|
||||
// Extract the class number from CLASSxx
|
||||
func classToInt(token string) (uint16, bool) {
|
||||
offset := 5
|
||||
if len(token) < offset+1 {
|
||||
return 0, false
|
||||
}
|
||||
class, ok := strconv.Atoi(token[offset:])
|
||||
if ok != nil || class > maxUint16 {
|
||||
return 0, false
|
||||
}
|
||||
return uint16(class), true
|
||||
}
|
||||
|
||||
// Extract the rr number from TYPExxx
|
||||
func typeToInt(token string) (uint16, bool) {
|
||||
offset := 4
|
||||
if len(token) < offset+1 {
|
||||
return 0, false
|
||||
}
|
||||
typ, ok := strconv.Atoi(token[offset:])
|
||||
if ok != nil || typ > maxUint16 {
|
||||
return 0, false
|
||||
}
|
||||
return uint16(typ), true
|
||||
}
|
||||
|
||||
// Parse things like 2w, 2m, etc, Return the time in seconds.
|
||||
func stringToTtl(token string) (uint32, bool) {
|
||||
s := uint32(0)
|
||||
i := uint32(0)
|
||||
for _, c := range token {
|
||||
switch c {
|
||||
case 's', 'S':
|
||||
s += i
|
||||
i = 0
|
||||
case 'm', 'M':
|
||||
s += i * 60
|
||||
i = 0
|
||||
case 'h', 'H':
|
||||
s += i * 60 * 60
|
||||
i = 0
|
||||
case 'd', 'D':
|
||||
s += i * 60 * 60 * 24
|
||||
i = 0
|
||||
case 'w', 'W':
|
||||
s += i * 60 * 60 * 24 * 7
|
||||
i = 0
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
i *= 10
|
||||
i += uint32(c) - '0'
|
||||
default:
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
return s + i, true
|
||||
}
|
||||
|
||||
// Parse LOC records' <digits>[.<digits>][mM] into a
|
||||
// mantissa exponent format. Token should contain the entire
|
||||
// string (i.e. no spaces allowed)
|
||||
func stringToCm(token string) (e, m uint8, ok bool) {
|
||||
if token[len(token)-1] == 'M' || token[len(token)-1] == 'm' {
|
||||
token = token[0 : len(token)-1]
|
||||
}
|
||||
s := strings.SplitN(token, ".", 2)
|
||||
var meters, cmeters, val int
|
||||
var err error
|
||||
switch len(s) {
|
||||
case 2:
|
||||
if cmeters, err = strconv.Atoi(s[1]); err != nil {
|
||||
return
|
||||
}
|
||||
fallthrough
|
||||
case 1:
|
||||
if meters, err = strconv.Atoi(s[0]); err != nil {
|
||||
return
|
||||
}
|
||||
case 0:
|
||||
// huh?
|
||||
return 0, 0, false
|
||||
}
|
||||
ok = true
|
||||
if meters > 0 {
|
||||
e = 2
|
||||
val = meters
|
||||
} else {
|
||||
e = 0
|
||||
val = cmeters
|
||||
}
|
||||
for val > 10 {
|
||||
e++
|
||||
val /= 10
|
||||
}
|
||||
if e > 9 {
|
||||
ok = false
|
||||
}
|
||||
m = uint8(val)
|
||||
return
|
||||
}
|
||||
|
||||
func appendOrigin(name, origin string) string {
|
||||
if origin == "." {
|
||||
return name + origin
|
||||
}
|
||||
return name + "." + origin
|
||||
}
|
||||
|
||||
// LOC record helper function
|
||||
func locCheckNorth(token string, latitude uint32) (uint32, bool) {
|
||||
switch token {
|
||||
case "n", "N":
|
||||
return LOC_EQUATOR + latitude, true
|
||||
case "s", "S":
|
||||
return LOC_EQUATOR - latitude, true
|
||||
}
|
||||
return latitude, false
|
||||
}
|
||||
|
||||
// LOC record helper function
|
||||
func locCheckEast(token string, longitude uint32) (uint32, bool) {
|
||||
switch token {
|
||||
case "e", "E":
|
||||
return LOC_EQUATOR + longitude, true
|
||||
case "w", "W":
|
||||
return LOC_EQUATOR - longitude, true
|
||||
}
|
||||
return longitude, false
|
||||
}
|
||||
|
||||
// "Eat" the rest of the "line". Return potential comments
|
||||
func slurpRemainder(c chan lex, f string) (*ParseError, string) {
|
||||
l := <-c
|
||||
com := ""
|
||||
switch l.value {
|
||||
case zBlank:
|
||||
l = <-c
|
||||
com = l.comment
|
||||
if l.value != zNewline && l.value != zEOF {
|
||||
return &ParseError{f, "garbage after rdata", l}, ""
|
||||
}
|
||||
case zNewline:
|
||||
com = l.comment
|
||||
case zEOF:
|
||||
default:
|
||||
return &ParseError{f, "garbage after rdata", l}, ""
|
||||
}
|
||||
return nil, com
|
||||
}
|
||||
|
||||
// Parse a 64 bit-like ipv6 address: "0014:4fff:ff20:ee64"
|
||||
// Used for NID and L64 record.
|
||||
func stringToNodeID(l lex) (uint64, *ParseError) {
|
||||
if len(l.token) < 19 {
|
||||
return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l}
|
||||
}
|
||||
// There must be three colons at fixes postitions, if not its a parse error
|
||||
if l.token[4] != ':' && l.token[9] != ':' && l.token[14] != ':' {
|
||||
return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l}
|
||||
}
|
||||
s := l.token[0:4] + l.token[5:9] + l.token[10:14] + l.token[15:19]
|
||||
u, e := strconv.ParseUint(s, 16, 64)
|
||||
if e != nil {
|
||||
return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l}
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue