Documentation ¶
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var DefaultLoggingHooks = &Trace{ ClientHello: func(s *SessionHandler) { if s.ClientHello == nil { log.Printf("ClientHello id:%d message:%v\n", s.sid, s.ClientHello) } }, EndSession: func(s *SessionHandler, e error) { if e != nil { log.Printf("EndSession id:%d error:%v\n", s.sid, e) } }, Encoded: func(s *SessionHandler, e error) { if e != nil { log.Printf("Encoded id:%d error:%v\n", s.sid, e) } }, Decoded: func(s *SessionHandler, e error) { if e != nil { log.Printf("Decoded id:%d error:%v\n", s.sid, e) } }, }
DefaultLoggingHooks provides a default logging hook to report errors.
var DiagnosticLoggingHooks = &Trace{ ClientHello: func(s *SessionHandler) { log.Printf("ClientHello id:%d message:%v\n", s.sid, s.ClientHello) }, StartSession: func(s *SessionHandler) { log.Printf("StartSession id:%d remote:%s\n", s.sid, s.svrcon.RemoteAddr()) }, EndSession: func(s *SessionHandler, e error) { log.Printf("EndSession id:%d error:%v\n", s.sid, e) }, }
DiagnosticLoggingHooks provides a set of default diagnostic hooks
var NoOpLoggingHooks = &Trace{ StartSession: func(s *SessionHandler) {}, ClientHello: func(s *SessionHandler) {}, EndSession: func(s *SessionHandler, e error) {}, Encoded: func(s *SessionHandler, e error) {}, Decoded: func(s *SessionHandler, e error) {}, }
NoOpLoggingHooks provides set of hooks that do nothing.
Functions ¶
Types ¶
type RPCReplyMessage ¶ added in v2.5.0
type RPCReplyMessage struct { XMLName xml.Name `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 rpc-reply"` Errors []common.RPCError `xml:"rpc-error,omitempty"` Data ReplyData `xml:"data"` Ok bool `xml:",omitempty"` RawReply string `xml:"-"` MessageID string `xml:"message-id,attr"` }
RPCReplyMessage and ReplyData represent an rpc-reply message that will be sent to a client session, where the element type of the reply body (i.e. the content of the data element) is unknown.
type RPCRequest ¶
RPCRequest describes an RPC request.
type RPCRequestMessage ¶ added in v2.5.0
type RPCRequestMessage struct { XMLName xml.Name MessageID string `xml:"message-id,attr"` Request RPCRequest `xml:",any"` Body string `xml:",innerxml"` }
RPCRequestMessage and rpcRequest represent an RPC request from a client, where the element type of the request body is unknown.
type RequestHandler ¶
type RequestHandler func(h *SessionHandler, req *RPCRequestMessage)
RequestHandler is a function type that will be invoked by the session handler to handle an RPC request.
type Server ¶
Server represents a Netconf Server. It encapsulates a transport connection to an SSH server, and session handlers that will be invoked to handle netconf messages.
func NewServer ¶
func NewServer(ctx context.Context, address string, port int, sshcfg *xssh.ServerConfig, sf SessionFactory) (ncs *Server, err error)
NewServer creates a new Server that will accept Netconf localhost connections on an ephemeral port (available via Port()), with credentials defined by the sshcfg configuration.
Example ¶
//nolint:goconst package main import ( "context" "fmt" "github.com/damianoneill/net/v2/netconf/common" "github.com/damianoneill/net/v2/netconf/ops" "github.com/damianoneill/net/v2/netconf/server/ssh" xssh "golang.org/x/crypto/ssh" ) type exampleServer struct{} func (es *exampleServer) Capabilities() []string { return common.DefaultCapabilities } func (es *exampleServer) HandleRequest(req *RPCRequestMessage) *RPCReplyMessage { switch req.Request.XMLName.Local { case "get": return &RPCReplyMessage{Data: ReplyData{Data: `<top><sub attr="avalue"><child1>cvalue</child1></sub></top>`}, MessageID: req.MessageID} case "get-config": return &RPCReplyMessage{Errors: []common.RPCError{ {Severity: "error", Message: "oops"}, }, MessageID: req.MessageID} } return nil } func main() { sshcfg, _ := ssh.PasswordConfig("UserA", "PassA") server, _ := NewServer(context.Background(), "localhost", 0, sshcfg, func(sh *SessionHandler) SessionCallback { return &exampleServer{} }) defer server.Close() //---------------------------- sshConfig := &xssh.ClientConfig{ User: "UserA", Auth: []xssh.AuthMethod{xssh.Password("PassA")}, HostKeyCallback: xssh.InsecureIgnoreHostKey(), } ncs, _ := ops.NewSession(context.Background(), sshConfig, fmt.Sprintf("%s:%d", "localhost", server.Port())) defer ncs.Close() var result string _ = ncs.GetSubtree("/", &result) fmt.Println("Get:", result) err := ncs.GetConfigSubtree("/", ops.CandidateCfg, &result) fmt.Println("Get-Config:", err) }
Output: Get: <top><sub attr="avalue"><child1>cvalue</child1></sub></top> Get-Config: netconf rpc [error] 'oops'
type SessionCallback ¶
type SessionCallback interface { // Capabilities is called to retrieve the capabilities that should be advertised to the client. // If the callback returns nil, the default set of capabilities is used. Capabilities() []string // HandleRequest is called to handle an RPC request. HandleRequest(req *RPCRequestMessage) *RPCReplyMessage }
SessionCallback defines the caller supplied callback functions.
type SessionFactory ¶
type SessionFactory func(*SessionHandler) SessionCallback
type SessionHandler ¶
type SessionHandler struct { // The HelloMessage sent by the connecting client. ClientHello *common.HelloMessage // contains filtered or unexported fields }
SessionHandler represents the server side of an active netconf SSH session.
func (*SessionHandler) Close ¶
func (h *SessionHandler) Close()
Close initiates session tear-down by closing the underlying transport channel.
func (*SessionHandler) Handle ¶
func (h *SessionHandler) Handle(ch xssh.Channel)
Handle establishes a Netconf server session on a newly-connected SSH channel.
type Trace ¶
type Trace struct { *ssh.Trace StartSession func(s *SessionHandler) EndSession func(s *SessionHandler, e error) ClientHello func(s *SessionHandler) Encoded func(s *SessionHandler, e error) Decoded func(s *SessionHandler, e error) }
Trace defines a structure for handling trace events
func ContextNetconfTrace ¶
ContextNetconfTrace returns the Trace associated with the provided context. If none, it returns nil.