-
Notifications
You must be signed in to change notification settings - Fork 76
/
errors.go
230 lines (200 loc) · 6.04 KB
/
errors.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
package nfs
import (
"encoding"
"encoding/binary"
"errors"
"fmt"
)
// RPCError provides the error interface for errors thrown by
// procedures to be transmitted over the XDR RPC channel
type RPCError interface {
// An RPCError is an `error` with this method
Error() string
// Code is the RPC Response code to send
Code() ResponseCode
// BinaryMarshaler is the on-wire representation of this error
encoding.BinaryMarshaler
}
// AuthStat is an enumeration of why authentication ahs failed
type AuthStat uint32
// AuthStat Codes
const (
AuthStatOK AuthStat = iota
AuthStatBadCred
AuthStatRejectedCred
AuthStatBadVerifier
AuthStatRejectedVerfier
AuthStatTooWeak
AuthStatInvalidResponse
AuthStatFailed
AuthStatKerbGeneric
AuthStatTimeExpire
AuthStatTktFile
AuthStatDecode
AuthStatNetAddr
AuthStatRPCGSSCredProblem
AuthStatRPCGSSCTXProblem
)
// AuthError is an RPCError
type AuthError struct {
AuthStat
}
// Code for AuthErrors is ResponseCodeAuthError
func (a *AuthError) Code() ResponseCode {
return ResponseCodeAuthError
}
// Error is a textual representaiton of the auth error. From the RFC
func (a *AuthError) Error() string {
switch a.AuthStat {
case AuthStatOK:
return "Auth Status: OK"
case AuthStatBadCred:
return "Auth Status: bad credential"
case AuthStatRejectedCred:
return "Auth Status: client must begin new session"
case AuthStatBadVerifier:
return "Auth Status: bad verifier"
case AuthStatRejectedVerfier:
return "Auth Status: verifier expired or replayed"
case AuthStatTooWeak:
return "Auth Status: rejected for security reasons"
case AuthStatInvalidResponse:
return "Auth Status: bogus response verifier"
case AuthStatFailed:
return "Auth Status: reason unknown"
case AuthStatKerbGeneric:
return "Auth Status: kerberos generic error"
case AuthStatTimeExpire:
return "Auth Status: time of credential expired"
case AuthStatTktFile:
return "Auth Status: problem with ticket file"
case AuthStatDecode:
return "Auth Status: can't decode authenticator"
case AuthStatNetAddr:
return "Auth Status: wrong net address in ticket"
case AuthStatRPCGSSCredProblem:
return "Auth Status: no credentials for user"
case AuthStatRPCGSSCTXProblem:
return "Auth Status: problem with context"
}
return "Auth Status: Unknown"
}
// MarshalBinary sends the specific auth status
func (a *AuthError) MarshalBinary() (data []byte, err error) {
var resp [4]byte
binary.LittleEndian.PutUint32(resp[:], uint32(a.AuthStat))
return resp[:], nil
}
// RPCMismatchError is an RPCError
type RPCMismatchError struct {
Low uint32
High uint32
}
// Code for RPCMismatchError is ResponseCodeRPCMismatch
func (r *RPCMismatchError) Code() ResponseCode {
return ResponseCodeRPCMismatch
}
func (r *RPCMismatchError) Error() string {
return fmt.Sprintf("RPC Mismatch: Expected version between %d and %d.", r.Low, r.High)
}
// MarshalBinary sends the specific rpc mismatch range
func (r *RPCMismatchError) MarshalBinary() (data []byte, err error) {
var resp [8]byte
binary.LittleEndian.PutUint32(resp[0:4], uint32(r.Low))
binary.LittleEndian.PutUint32(resp[4:8], uint32(r.High))
return resp[:], nil
}
// ResponseCodeProcUnavailableError is an RPCError
type ResponseCodeProcUnavailableError struct {
}
// Code for ResponseCodeProcUnavailableError
func (r *ResponseCodeProcUnavailableError) Code() ResponseCode {
return ResponseCodeProcUnavailable
}
func (r *ResponseCodeProcUnavailableError) Error() string {
return "The requested procedure is unexported"
}
// MarshalBinary - this error has no associated body
func (r *ResponseCodeProcUnavailableError) MarshalBinary() (data []byte, err error) {
return []byte{}, nil
}
// ResponseCodeSystemError is an RPCError
type ResponseCodeSystemError struct {
}
// Code for ResponseCodeSystemError
func (r *ResponseCodeSystemError) Code() ResponseCode {
return ResponseCodeSystemErr
}
func (r *ResponseCodeSystemError) Error() string {
return "memory allocation failure"
}
// MarshalBinary - this error has no associated body
func (r *ResponseCodeSystemError) MarshalBinary() (data []byte, err error) {
return []byte{}, nil
}
// basicErrorFormatter is the default error handler for response errors.
// if the error is already formatted, it is directly written. Otherwise,
// ResponseCodeSystemError is sent to the client.
func basicErrorFormatter(err error) RPCError {
var rpcErr RPCError
if errors.As(err, &rpcErr) {
return rpcErr
}
return &ResponseCodeSystemError{}
}
// NFSStatusError represents an error at the NFS level.
type NFSStatusError struct {
NFSStatus
WrappedErr error
}
// Error is The wrapped error
func (s *NFSStatusError) Error() string {
message := s.NFSStatus.String()
if s.WrappedErr != nil {
message = fmt.Sprintf("%s: %v", message, s.WrappedErr)
}
return message
}
// Code for NFS issues are successful RPC responses
func (s *NFSStatusError) Code() ResponseCode {
return ResponseCodeSuccess
}
// MarshalBinary - The binary form of the code.
func (s *NFSStatusError) MarshalBinary() (data []byte, err error) {
var resp [4]byte
binary.BigEndian.PutUint32(resp[0:4], uint32(s.NFSStatus))
return resp[:], nil
}
// Unwrap unpacks wrapped errors
func (s *NFSStatusError) Unwrap() error {
return s.WrappedErr
}
// StatusErrorWithBody is an NFS error with a payload.
type StatusErrorWithBody struct {
NFSStatusError
Body []byte
}
// MarshalBinary provides the wire format of the error response
func (s *StatusErrorWithBody) MarshalBinary() (data []byte, err error) {
head, err := s.NFSStatusError.MarshalBinary()
return append(head, s.Body...), err
}
// errFormatterWithBody appends a provided body to errors
func errFormatterWithBody(body []byte) func(err error) RPCError {
return func(err error) RPCError {
if nerr, ok := err.(*NFSStatusError); ok {
return &StatusErrorWithBody{*nerr, body[:]}
}
var rErr RPCError
if errors.As(err, &rErr) {
return rErr
}
return &ResponseCodeSystemError{}
}
}
var (
opAttrErrorBody = [4]byte{}
opAttrErrorFormatter = errFormatterWithBody(opAttrErrorBody[:])
wccDataErrorBody = [8]byte{}
wccDataErrorFormatter = errFormatterWithBody(wccDataErrorBody[:])
)