small refactor*
This commit is contained in:
parent
b6b541e050
commit
24a4d30275
232 changed files with 2164 additions and 1906 deletions
server/pkg/go-nfs
230
server/pkg/go-nfs/errors.go
Normal file
230
server/pkg/go-nfs/errors.go
Normal file
|
@ -0,0 +1,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[:])
|
||||
)
|
Loading…
Add table
Add a link
Reference in a new issue