netconf

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 3, 2026 License: MIT Imports: 8 Imported by: 0

README

netconf — NETCONF protocol library for Go

A pure-Go implementation of the NETCONF management protocol, covering:

  • RFC 6241 — NETCONF base protocol, all 13 operations
  • RFC 6242 — SSH transport with both EOM (]]>]]>) and chunked framing
  • RFC 7803 — capability URN validation

Packages

Import path Description
github.com/GabrielNunesIT/netconf Core protocol types: Hello, RPC, RPCReply messages; session management; capability negotiation; operation structs for all 13 RFC 6241 operations; error model
github.com/GabrielNunesIT/netconf/client NETCONF client with typed methods for all 13 operations, concurrent RPC dispatch, context support
github.com/GabrielNunesIT/netconf/server NETCONF server with handler registration, RPC dispatch loop, built-in close-session handling
github.com/GabrielNunesIT/netconf/transport Transport interface, EOM and chunked framers, loopback transport for testing
github.com/GabrielNunesIT/netconf/transport/ssh SSH client and server transports using golang.org/x/crypto/ssh

Requirements

  • Go 1.26 or later

Installation

go get github.com/GabrielNunesIT/netconf

Quick Start

package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"path/filepath"

	netconf "github.com/GabrielNunesIT/netconf"
	"github.com/GabrielNunesIT/netconf/client"
	gossh "golang.org/x/crypto/ssh"
	"golang.org/x/crypto/ssh/knownhosts"
)

func main() {
	home, err := os.UserHomeDir()
	if err != nil {
		log.Fatal(err)
	}
	hostKeyCallback, err := knownhosts.New(filepath.Join(home, ".ssh", "known_hosts"))
	if err != nil {
		log.Fatal(err)
	}

	sshCfg := &gossh.ClientConfig{
		User: "admin",
		Auth: []gossh.AuthMethod{
			gossh.Password("secret"),
		},
		HostKeyCallback: hostKeyCallback,
	}

	ctx := context.Background()

	localCaps := netconf.NewCapabilitySet([]string{netconf.BaseCap10, netconf.BaseCap11})

	c, err := client.Dial(ctx, "router.example.com:830", sshCfg, localCaps)
	if err != nil {
		log.Fatal(err)
	}
	defer c.Close()

	data, err := c.GetConfig(ctx, netconf.Running, nil)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("running config:\n%s\n", data.Body)

	if err := c.CloseSession(ctx); err != nil {
		log.Fatal(err)
	}
}

Testing

Run the full test suite — unit tests across all packages plus the RFC 6241 conformance tests:

go test ./...

Run only the conformance tests with verbose output:

go test ./netconf/conformance/... -v -count=1

Run static analysis:

go vet ./...

License

MIT — see LICENSE.

Documentation

Overview

Package netconf implements the NETCONF network configuration protocol (RFC 6241) and its key extensions.

Overview

NETCONF is a standards-based protocol for network device configuration and state retrieval. It uses XML-encoded RPCs over a secured transport (SSH per RFC 6242, or TLS per RFC 7589) and a capability-negotiated hello exchange that determines the operation set and framing mode.

This package provides the core types: capability negotiation, session establishment, XML wire messages, RFC 6241 operation structs, RFC 5277 notifications, and RFC 6470 notification body types.

Quick start

Connect as a client and retrieve the running configuration:

import (
    "context"
    "os"
    "path/filepath"
    "golang.org/x/crypto/ssh"
    "golang.org/x/crypto/ssh/knownhosts"
    netconf "github.com/GabrielNunesIT/netconf"
    "github.com/GabrielNunesIT/netconf/client"
)

home, err := os.UserHomeDir()
if err != nil { /* handle */ }
hostKeyCallback, err := knownhosts.New(filepath.Join(home, ".ssh", "known_hosts"))
if err != nil { /* handle */ }

cfg := &ssh.ClientConfig{
    User: "admin",
    Auth: []ssh.AuthMethod{ssh.Password("secret")},
    HostKeyCallback: hostKeyCallback,
}
caps := netconf.NewCapabilitySet([]string{netconf.BaseCap10, netconf.BaseCap11})

cli, err := client.Dial(context.Background(), "192.0.2.1:830", cfg, caps)
if err != nil { /* handle */ }
defer cli.Close()

dr, err := cli.GetConfig(context.Background(), netconf.Datastore{Running: &struct{}{}}, nil)
if err != nil { /* handle */ }
// dr.Content holds the raw inner XML of the <data> element.

Package layout

The library is split into focused packages:

Session lifecycle

ClientSession and ServerSession perform the RFC 6241 §8.1 hello exchange: both peers send their capabilities simultaneously (required to avoid deadlock on unbuffered transports), then negotiate framing. If both advertise base:1.1, the transport is upgraded to chunked framing (FramingChunked); otherwise it stays in EOM framing (FramingEOM).

Capabilities

CapabilitySet is an ordered list of capability URNs. NewCapabilitySet constructs one from a string slice. ValidateURN checks RFC 7803 format. The predefined constants (BaseCap10, BaseCap11, CapabilityCandidate, …) cover all standard RFC 6241 and related extension capabilities.

Operations

Each RFC 6241 §7 operation is a Go struct that xml.Marshal encodes correctly. Pass one to [client.Client.Do] or use a typed convenience method:

// Typed method:
dr, err := cli.GetConfig(ctx, netconf.Datastore{Running: &struct{}{}}, nil)

// Raw RPC (any marshalable op):
reply, err := cli.Do(ctx, &netconf.EditConfig{
    Target: netconf.Datastore{Running: &struct{}{}},
    Config: []byte(`<config>…</config>`),
})

Error handling

RPCError is the structured NETCONF error type (RFC 6241 §4.3). It implements the error interface and is returned by typed client methods when the server replies with an <rpc-error> element. Use errors.As to extract it:

dr, err := cli.GetConfig(ctx, source, nil)
var rpcErr netconf.RPCError
if errors.As(err, &rpcErr) {
    log.Printf("server error: tag=%s message=%s", rpcErr.Tag, rpcErr.Message)
}

Notifications (RFC 5277) RFC 5277)" aria-label="Go to Notifications (RFC 5277)">¶

Subscribe and receive notifications:

notifCh, err := cli.Subscribe(ctx, netconf.CreateSubscription{})
if err != nil { /* handle */ }
for n := range notifCh {
    // n.EventTime is the xs:dateTime timestamp.
    // n.Body is the raw inner XML of the notification content.
}

Index

Constants

View Source
const NetconfNS = "urn:ietf:params:xml:ns:netconf:base:1.0"

NetconfNS is the XML namespace for all NETCONF base messages (RFC 6241 §3.1).

View Source
const NetconfNotificationsNS = "urn:ietf:params:xml:ns:yang:ietf-netconf-notifications"

NetconfNotificationsNS is the XML namespace for RFC 6470 NETCONF notification body types (ietf-netconf-notifications YANG module, RFC 6470 §5).

This namespace is distinct from NotificationNS (RFC 5277 envelope namespace) and from NetconfNS (RFC 6241 base namespace).

View Source
const NotificationNS = "urn:ietf:params:xml:ns:netconf:notification:1.0"

NotificationNS is the XML namespace for NETCONF notification messages (RFC 5277 §4). It is distinct from NetconfNS and is used by the <notification> element and the <create-subscription> operation.

View Source
const WithDefaultsNS = "urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults"

WithDefaultsNS is the XML namespace for the with-defaults parameter (RFC 6243 §4).

Variables

View Source
var HelloName = xml.Name{Space: NetconfNS, Local: "hello"}

HelloName is the xml.Name constant for the <hello> element.

View Source
var NotificationName = xml.Name{Space: NotificationNS, Local: "notification"}

NotificationName is the xml.Name constant for the <notification> element (RFC 5277 §4). Its namespace is NotificationNS, not NetconfNS.

View Source
var RPCName = xml.Name{Space: NetconfNS, Local: "rpc"}

RPCName is the xml.Name constant for the <rpc> element.

View Source
var RPCReplyName = xml.Name{Space: NetconfNS, Local: "rpc-reply"}

RPCReplyName is the xml.Name constant for the <rpc-reply> element.

Functions

func ValidateURN

func ValidateURN(s string) error

ValidateURN checks that s conforms to the RFC 7803 NETCONF capability URN format. It returns nil on success and a descriptive error otherwise.

Types

type CancelCommit

type CancelCommit struct {
	XMLName   xml.Name `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 cancel-commit"`
	PersistID string   `xml:"persist-id,omitempty"`
}

CancelCommit cancels an ongoing confirmed commit (RFC 6241 §8.4.9). Requires CapabilityConfirmedCommit. PersistID, when non-empty, identifies the persistent confirmed commit to cancel.

type Capability

type Capability = string

Capability is a NETCONF capability URN string.

Capability URNs follow the IANA registry format defined in RFC 7803:

urn:ietf:params:netconf:base:<version>
urn:ietf:params:netconf:capability:<name>:<version>
const (
	// BaseCap10 is the base:1.0 capability (RFC 6241 EOM framing).
	BaseCap10 Capability = "urn:ietf:params:netconf:base:1.0"

	// BaseCap11 is the base:1.1 capability (RFC 6242 chunked framing).
	BaseCap11 Capability = "urn:ietf:params:netconf:base:1.1"
)

Base capability constants — the two NETCONF framing versions.

const (
	// CapabilityNotification is the :notification capability (RFC 5277 §3.1).
	// When present, the device supports the create-subscription operation and
	// can send <notification> messages to the client.
	CapabilityNotification Capability = "urn:ietf:params:netconf:capability:notification:1.0"

	// CapabilityInterleave is the :interleave capability (RFC 5277 §6.2).
	// When present, the device supports interleaving RPC requests with an active
	// notification subscription on the same session.
	CapabilityInterleave Capability = "urn:ietf:params:netconf:capability:interleave:1.0"
)

Notification capability constants defined in RFC 5277. These URNs follow the same urn:ietf:params:netconf:capability format as the RFC 6241 capabilities and pass ValidateURN.

const (
	// CapabilityCandidate is the :candidate capability (RFC 6241 §8.3).
	// When present, the device supports a candidate configuration datastore.
	CapabilityCandidate Capability = "urn:ietf:params:netconf:capability:candidate:1.0"

	// CapabilityConfirmedCommit is the :confirmed-commit:1.1 capability (RFC 6241 §8.4).
	// When present, the device supports confirmed-commit with a rollback timeout.
	CapabilityConfirmedCommit Capability = "urn:ietf:params:netconf:capability:confirmed-commit:1.1"

	// CapabilityRollbackOnError is the :rollback-on-error capability (RFC 6241 §8.5).
	// When present, the error-option "rollback-on-error" is available for edit-config.
	CapabilityRollbackOnError Capability = "urn:ietf:params:netconf:capability:rollback-on-error:1.0"

	// CapabilityValidate is the :validate:1.1 capability (RFC 6241 §8.6).
	// When present, the device supports the <validate> operation.
	CapabilityValidate Capability = "urn:ietf:params:netconf:capability:validate:1.1"

	// CapabilityStartup is the :startup capability (RFC 6241 §8.7).
	// When present, the device supports a separate startup configuration datastore.
	CapabilityStartup Capability = "urn:ietf:params:netconf:capability:startup:1.0"

	// CapabilityURL is the :url capability (RFC 6241 §8.8).
	// When present, the device supports specifying a URL as a configuration source/target.
	CapabilityURL Capability = "urn:ietf:params:netconf:capability:url:1.0"

	// CapabilityXPath is the :xpath capability (RFC 6241 §8.9).
	// When present, the device supports XPath filter expressions in <get> and <get-config>.
	CapabilityXPath Capability = "urn:ietf:params:netconf:capability:xpath:1.0"

	// CapabilityWritableRunning is the :writable-running capability (RFC 6241 §8.2).
	// When present, the device supports direct writes to the running configuration.
	CapabilityWritableRunning Capability = "urn:ietf:params:netconf:capability:writable-running:1.0"
)

Standard optional capability constants defined in RFC 6241 §8 and related RFCs. All URNs pass ValidateURN and follow the RFC 7803 urn:ietf:params:netconf:capability format.

const (
	// CapabilityWithDefaults is the :with-defaults capability (RFC 6243 §4).
	// When present, the device supports the with-defaults parameter on <get>,
	// <get-config>, and <copy-config> operations to control how default values
	// are included in returned configuration data.
	CapabilityWithDefaults Capability = "urn:ietf:params:netconf:capability:with-defaults:1.0"

	// CapabilityPartialLock is the :partial-lock capability (RFC 5717 §2.4).
	// When present, the device supports locking selected portions of the
	// configuration datastore using XPath select expressions via the
	// <partial-lock> and <partial-unlock> operations.
	CapabilityPartialLock Capability = "urn:ietf:params:netconf:capability:partial-lock:1.0"
)

Extended capability constants for with-defaults (RFC 6243) and partial-lock (RFC 5717).

type CapabilityChange

type CapabilityChange struct {
	XMLName            xml.Name  `xml:"urn:ietf:params:xml:ns:yang:ietf-netconf-notifications netconf-capability-change"`
	ChangedBy          ChangedBy `xml:"changed-by"`
	AddedCapability    []string  `xml:"added-capability,omitempty"`
	DeletedCapability  []string  `xml:"deleted-capability,omitempty"`
	ModifiedCapability []string  `xml:"modified-capability,omitempty"`
}

CapabilityChange is the RFC 6470 netconf-capability-change notification body. It is generated when a server's capabilities change at runtime. Callers unmarshal this from [Notification.Body] using the synthetic-wrapper pattern described in the package godoc.

  • ChangedBy: who initiated the capability change.
  • AddedCapability: list of newly added capability URIs; omitted when empty.
  • DeletedCapability: list of removed capability URIs; omitted when empty.
  • ModifiedCapability: list of modified capability URIs; omitted when empty.

type CapabilitySet

type CapabilitySet []Capability

CapabilitySet is an ordered list of capability URNs.

func NewCapabilitySet

func NewCapabilitySet(caps []string) CapabilitySet

NewCapabilitySet creates a CapabilitySet from a string slice.

func (CapabilitySet) Contains

func (cs CapabilitySet) Contains(c Capability) bool

Contains reports whether the set contains the given capability URN. The comparison is case-sensitive (URNs are case-sensitive per RFC 2141) and exact — query parameters are not stripped.

Note: some devices advertise the with-defaults capability with query parameters (e.g. "urn:…:with-defaults:1.0?basic-mode=explicit"). Such a value will not match CapabilityWithDefaults by exact string comparison. Callers that need to detect the with-defaults capability from a real device hello should use strings.HasPrefix(uri, CapabilityWithDefaults) in addition to Contains.

func (CapabilitySet) Supports10

func (cs CapabilitySet) Supports10() bool

Supports10 reports whether the capability set includes base:1.0. RFC 6241 requires all NETCONF implementations to support base:1.0.

func (CapabilitySet) Supports11

func (cs CapabilitySet) Supports11() bool

Supports11 reports whether the capability set includes base:1.1. This is used during hello exchange to determine whether chunked framing should be negotiated.

type ChangedBy

type ChangedBy struct {
	Server     *struct{} `xml:"server,omitempty"`
	Username   string    `xml:"username,omitempty"`
	SessionID  uint32    `xml:"session-id,omitempty"`
	SourceHost string    `xml:"source-host,omitempty"`
}

ChangedBy encodes the YANG choice "server-or-user" used by several RFC 6470 notification types to identify the initiator of a change.

Mutual exclusion is enforced by callers: set Server to &struct{}{} for a server-initiated change, or populate Username/SessionID/SourceHost for a user-initiated change. The library does not validate the choice at runtime.

  • Server: present as <server/> when the change was made by the server itself.
  • Username: NETCONF username of the user session (user-initiated change).
  • SessionID: NETCONF session-id of the user session; omitted when zero.
  • SourceHost: IP address or hostname of the session source; omitted when empty.

type CloseSession

type CloseSession struct {
	XMLName xml.Name `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 close-session"`
}

CloseSession requests a graceful termination of the current NETCONF session (RFC 6241 §7.8). It carries no body fields.

type Commit

type Commit struct {
	XMLName        xml.Name  `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 commit"`
	Confirmed      *struct{} `xml:"confirmed,omitempty"`
	ConfirmTimeout uint32    `xml:"confirm-timeout,omitempty"`
	Persist        string    `xml:"persist,omitempty"`
	PersistID      string    `xml:"persist-id,omitempty"`
}

Commit commits the candidate configuration as the device's new running configuration (RFC 6241 §8.3). Requires CapabilityCandidate.

Optional confirmed-commit fields (RFC 6241 §8.4, requires CapabilityConfirmedCommit):

  • Confirmed: when non-nil, initiates a confirmed commit
  • ConfirmTimeout: timeout in seconds (default 600 per RFC)
  • Persist: token to identify a persistent confirmed commit
  • PersistID: confirms a prior persistent confirmed commit

type ConfigChange

type ConfigChange struct {
	XMLName   xml.Name     `xml:"urn:ietf:params:xml:ns:yang:ietf-netconf-notifications netconf-config-change"`
	ChangedBy ChangedBy    `xml:"changed-by"`
	Datastore string       `xml:"datastore,omitempty"`
	Edit      []EditRecord `xml:"edit,omitempty"`
}

ConfigChange is the RFC 6470 netconf-config-change notification body. It is generated by the server when the NETCONF configuration datastore is modified. Callers unmarshal this from [Notification.Body] using the synthetic-wrapper pattern described in the package godoc.

  • ChangedBy: who initiated the change (server or user session).
  • Datastore: which datastore was changed; omitted when empty (implies "running").
  • Edit: list of individual edit records; omitted when empty.

type ConfirmedCommit

type ConfirmedCommit struct {
	XMLName      xml.Name `xml:"urn:ietf:params:xml:ns:yang:ietf-netconf-notifications netconf-confirmed-commit"`
	Username     string   `xml:"username,omitempty"`
	SessionID    uint32   `xml:"session-id,omitempty"`
	SourceHost   string   `xml:"source-host,omitempty"`
	ConfirmEvent string   `xml:"confirm-event"`
	Timeout      uint32   `xml:"timeout,omitempty"`
}

ConfirmedCommit is the RFC 6470 netconf-confirmed-commit notification body. It is generated at each stage of a confirmed-commit sequence. Callers unmarshal this from [Notification.Body] using the synthetic-wrapper pattern described in the package godoc.

  • Username: NETCONF username; omitted when ConfirmEvent is "timeout" (no session).
  • SessionID: session-id; omitted when ConfirmEvent is "timeout" (no session).
  • SourceHost: client IP or hostname; omitted when absent.
  • ConfirmEvent: event type (required). One of: "start", "cancel", "timeout", "extend", "complete".
  • Timeout: remaining timeout in seconds; omitted when not applicable.

type CopyConfig

type CopyConfig struct {
	XMLName      xml.Name           `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 copy-config"`
	Target       Datastore          `xml:"target"`
	Source       Datastore          `xml:"source"`
	WithDefaults *WithDefaultsParam `xml:",omitempty"`
}

CopyConfig creates or replaces an entire configuration datastore with the contents of another (RFC 6241 §7.3). WithDefaults is optional; when nil the parameter is omitted (backward compatible). Requires CapabilityWithDefaults on the device when set.

type CreateSubscription

type CreateSubscription struct {
	XMLName   xml.Name `xml:"urn:ietf:params:xml:ns:netconf:notification:1.0 create-subscription"`
	Stream    string   `xml:"stream,omitempty"`
	Filter    *Filter  `xml:"filter,omitempty"`
	StartTime string   `xml:"startTime,omitempty"`
	StopTime  string   `xml:"stopTime,omitempty"`
}

CreateSubscription requests the creation of a notification subscription (RFC 5277 §2.1.1). Requires CapabilityNotification.

The XMLName uses the RFC 5277 notification namespace (urn:ietf:params:xml:ns:netconf:notification:1.0), which is distinct from the base NETCONF namespace. This is critical for correct wire encoding.

All fields are optional:

  • Stream: name of the event stream to subscribe to (default: NETCONF)
  • Filter: subtree or XPath filter to select events
  • StartTime: xs:dateTime replay start (requires stored events)
  • StopTime: xs:dateTime replay end (only valid with StartTime)

type DataReply

type DataReply struct {
	XMLName xml.Name `xml:"data"`
	Content []byte   `xml:",innerxml"`
}

DataReply wraps the <data> element returned in the body of a get or get-config response. Unmarshal RPCReply.Body into a DataReply to access the raw configuration content without writing a schema.

Example:

var dr netconf.DataReply
if err := xml.Unmarshal(reply.Body, &dr); err != nil { … }
// dr.Content holds the raw inner XML of <data>

type Datastore

type Datastore struct {
	Running   *struct{} `xml:"running,omitempty"`
	Candidate *struct{} `xml:"candidate,omitempty"`
	Startup   *struct{} `xml:"startup,omitempty"`
	URL       string    `xml:"url,omitempty"`
}

Datastore represents a NETCONF configuration datastore reference. It is used as the Source or Target in operations such as GetConfig, EditConfig, CopyConfig, DeleteConfig, Lock, Unlock, and Validate.

Exactly one field should be non-nil / non-empty for a valid datastore selector. Each field encodes as a child element within the enclosing <source> or <target>:

  • Running: <running/>
  • Candidate: <candidate/>
  • Startup: <startup/>
  • URL: <url>https://…</url>

Using *struct{} for the boolean datastores gives omitempty semantics with child-element encoding. A non-nil pointer marshals as an empty element.

type DeleteConfig

type DeleteConfig struct {
	XMLName xml.Name  `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 delete-config"`
	Target  Datastore `xml:"target"`
}

DeleteConfig deletes a configuration datastore (RFC 6241 §7.4). The running datastore cannot be deleted.

type DiscardChanges

type DiscardChanges struct {
	XMLName xml.Name `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 discard-changes"`
}

DiscardChanges reverts the candidate configuration to the current running configuration (RFC 6241 §8.3.4). Requires CapabilityCandidate. It carries no body fields.

type EditConfig

type EditConfig struct {
	XMLName          xml.Name  `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 edit-config"`
	Target           Datastore `xml:"target"`
	DefaultOperation string    `xml:"default-operation,omitempty"`
	TestOption       string    `xml:"test-option,omitempty"`
	ErrorOption      string    `xml:"error-option,omitempty"`
	Config           []byte    `xml:",innerxml"`
}

EditConfig loads part or all of a specified configuration into the target datastore (RFC 6241 §7.2).

DefaultOperation, TestOption, and ErrorOption are optional string fields; when non-empty they encode as child elements. Config holds the raw inner XML of the <config> element (arbitrary configuration content).

type EditRecord

type EditRecord struct {
	Target    string `xml:"target"`
	Operation string `xml:"operation"`
}

EditRecord describes a single edit operation within a ConfigChange notification (RFC 6470 §4.1).

  • Target: canonical name of the datastore edited (e.g. "running").
  • Operation: NETCONF edit operation applied (e.g. "merge", "replace", "delete").

type Filter

type Filter struct {
	Type    string `xml:"type,attr,omitempty"`
	Select  string `xml:"select,attr,omitempty"`
	Content []byte `xml:",innerxml"`
}

Filter represents a NETCONF filter element used in <get> and <get-config>. RFC 6241 §6 defines two filter types:

  • Subtree (type="subtree"): Content holds the raw inner XML of the filter criteria. Use the innerxml tag so arbitrary filter subtrees are preserved verbatim without requiring a schema.

  • XPath (type="xpath"): Select holds the XPath expression. Requires the :xpath capability (CapabilityXPath) to be advertised by the device.

The Type attribute discriminates between the two modes.

type FramingMode

type FramingMode int

FramingMode describes the active framing layer on a session.

const (
	// FramingEOM is base:1.0 end-of-message framing (]]>]]> delimiter).
	FramingEOM FramingMode = iota
	// FramingChunked is base:1.1 chunked framing (RFC 6242 §4.2).
	FramingChunked
)

type Get

type Get struct {
	XMLName      xml.Name           `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 get"`
	Filter       *Filter            `xml:"filter,omitempty"`
	WithDefaults *WithDefaultsParam `xml:",omitempty"`
}

Get retrieves running configuration and state data (RFC 6241 §7.7). Filter is optional; when nil all data is returned. WithDefaults is optional; when nil the parameter is omitted (backward compatible). Requires CapabilityWithDefaults on the device when set.

type GetConfig

type GetConfig struct {
	XMLName      xml.Name           `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 get-config"`
	Source       Datastore          `xml:"source"`
	Filter       *Filter            `xml:"filter,omitempty"`
	WithDefaults *WithDefaultsParam `xml:",omitempty"`
}

GetConfig retrieves all or part of a specified configuration datastore (RFC 6241 §7.1). Source identifies the datastore; Filter is optional. WithDefaults is optional; when nil the parameter is omitted (backward compatible). Requires CapabilityWithDefaults on the device when set.

type Hello

type Hello struct {
	XMLName      xml.Name `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 hello"`
	Capabilities []string `xml:"capabilities>capability"`
	SessionID    uint32   `xml:"session-id,omitempty"`
}

Hello represents a NETCONF <hello> message (RFC 6241 §8.1).

In the client→server direction, SessionID is zero (not included). In the server→client direction, SessionID carries the assigned session id.

Marshaling note: encoding/xml emits the namespace as xmlns="…" on the root element when XMLName.Space is set, which is correct per RFC 6241.

type KillSession

type KillSession struct {
	XMLName   xml.Name `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 kill-session"`
	SessionID uint32   `xml:"session-id"`
}

KillSession forces the termination of another NETCONF session (RFC 6241 §7.9). SessionID identifies the session to terminate.

type Lock

type Lock struct {
	XMLName xml.Name  `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 lock"`
	Target  Datastore `xml:"target"`
}

Lock locks the entire configuration datastore for the current session (RFC 6241 §7.5). Target identifies the datastore to lock.

type Notification

type Notification struct {
	XMLName   xml.Name `xml:"urn:ietf:params:xml:ns:netconf:notification:1.0 notification"`
	EventTime string   `xml:"eventTime"`
	Body      []byte   `xml:",innerxml"`
}

Notification represents a NETCONF <notification> event message (RFC 5277 §4).

The XMLName uses the RFC 5277 notification namespace (NotificationNS), which is distinct from the base NETCONF namespace. EventTime is the mandatory xs:dateTime timestamp of the event. Body holds the raw inner XML of the event-specific content (everything inside <notification> after <eventTime>).

Marshaling note: encoding/xml emits xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0" on the root element when XMLName.Space is set, which is correct per RFC 5277.

type PartialLock

type PartialLock struct {
	XMLName xml.Name `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 partial-lock"`
	Select  []string `xml:"select"`
}

PartialLock locks a subset of the configuration datastore described by XPath select expressions (RFC 5717 §2.1). Requires CapabilityPartialLock.

Each string in Select must be a valid XPath 1.0 expression that identifies the configuration nodes to lock. The device returns a PartialLockReply containing the assigned lock-id and the list of locked node instances.

RFC 5717 §3.1 uses the NETCONF base namespace for this operation element.

type PartialLockReply

type PartialLockReply struct {
	XMLName    xml.Name `xml:"partial-lock-reply"`
	LockID     uint32   `xml:"lock-id"`
	LockedNode []string `xml:"locked-node"`
}

PartialLockReply deserializes the reply body returned by a <partial-lock> RPC (RFC 5717 §2.1.3). After a successful partial-lock operation, unmarshal RPCReply.Body into this type to retrieve the assigned LockID and the canonical XPath expressions of the locked nodes.

Example usage:

var plr netconf.PartialLockReply
if err := xml.Unmarshal(reply.Body, &plr); err != nil { … }
// plr.LockID holds the lock-id to pass to PartialUnlock
// plr.LockedNode holds the locked-node list

Note: The <partial-lock-reply> element is sent without a namespace prefix inside the base-namespace <rpc-reply> body; matching on local name only.

type PartialUnlock

type PartialUnlock struct {
	XMLName xml.Name `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 partial-unlock"`
	LockID  uint32   `xml:"lock-id"`
}

PartialUnlock releases a partial lock previously acquired via PartialLock (RFC 5717 §2.2). Requires CapabilityPartialLock.

LockID must be the lock-id value returned in the PartialLockReply for the lock being released.

type RPC

type RPC struct {
	XMLName   xml.Name `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 rpc"`
	MessageID string   `xml:"message-id,attr"`
	Body      []byte   `xml:",innerxml"`
}

RPC represents a NETCONF <rpc> request message (RFC 6241 §4.1).

Body holds the raw inner XML of the operation element (e.g. <get-config>). Callers marshal the operation into Body before marshaling the RPC wrapper.

type RPCError

type RPCError struct {
	XMLName  xml.Name `xml:"rpc-error"`
	Type     string   `xml:"error-type"`
	Tag      string   `xml:"error-tag"`
	Severity string   `xml:"error-severity"`
	AppTag   string   `xml:"error-app-tag,omitempty"`
	Path     string   `xml:"error-path,omitempty"`
	Message  string   `xml:"error-message,omitempty"`
	// Info captures the raw inner XML of any <error-info> children verbatim.
	// Using innerxml preserves arbitrary vendor-specific sub-elements without
	// requiring a schema — a future parser can decode specific sub-elements.
	Info []byte `xml:",innerxml"`
}

RPCError represents a single NETCONF <rpc-error> element as defined in RFC 6241 §4.3. It implements the standard error interface so it can be returned directly from Go functions.

Field mapping (RFC 6241 §4.3 → XML element → Go field):

error-type     → Type     — one of: transport, rpc, protocol, application
error-tag      → Tag      — machine-readable error identifier
error-severity → Severity — "error" or "warning"
error-app-tag  → AppTag   — device/application-specific tag (optional)
error-path     → Path     — XPath to the element causing the error (optional)
error-message  → Message  — human-readable description (optional)
error-info     → Info     — raw inner XML of arbitrary <error-info> children

func ParseRPCErrors

func ParseRPCErrors(reply *RPCReply) ([]RPCError, error)

ParseRPCErrors extracts all <rpc-error> elements from reply.Body.

RPCReply.Body is raw innerxml — it may contain zero or more <rpc-error> siblings with no enclosing root element. This function wraps the bytes in a synthetic <wrapper> element so that encoding/xml can decode the sibling list as a slice.

Return values:

  • (nil, nil) — reply.Body is empty or contains no rpc-error elements
  • ([]RPCError, nil) — one or more errors were decoded successfully
  • (nil, err) — Body is non-empty but not valid XML

func (RPCError) Error

func (e RPCError) Error() string

Error implements the error interface. The string includes the error type, tag, severity, and human-readable message so it is immediately actionable in log output and error chains.

type RPCErrors

type RPCErrors = []RPCError

RPCErrors is a slice of RPCError values returned by ParseRPCErrors. Defining it as a named type lets callers range over it cleanly and makes function signatures self-documenting.

type RPCReply

type RPCReply struct {
	XMLName   xml.Name  `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 rpc-reply"`
	MessageID string    `xml:"message-id,attr"`
	Ok        *struct{} `xml:"ok"`
	Body      []byte    `xml:",innerxml"`
}

RPCReply represents a NETCONF <rpc-reply> response message (RFC 6241 §4.2).

For successful operations with no data, Ok will be non-nil and Body will be nil. For operations returning data, Body contains the raw inner XML. For errors, Body contains one or more <rpc-error> elements.

type Session

type Session struct {
	// contains filtered or unexported fields
}

Session represents an established NETCONF session. It holds negotiated state (session-id, capabilities, framing mode) and the underlying transport.

All exported methods are safe to call after a successful call to ClientSession or ServerSession. Concurrent calls are not safe unless the caller serialises them.

func ClientSession

func ClientSession(trp transport.Transport, localCaps CapabilitySet) (*Session, error)

ClientSession performs the NETCONF hello exchange from the client side (RFC 6241 §8.1):

  1. Sends a <hello> with localCaps (no session-id) concurrently with reading the server's <hello>. Both must happen simultaneously because the underlying transport may be unbuffered (e.g. io.Pipe).
  2. Validates that the server hello contains base:1.0 and extracts the session-id and server capabilities.
  3. Negotiates framing: upgrades to chunked if both peers advertise base:1.1.

Returns an initialised Session on success, or a descriptive error on failure. The transport is NOT closed on error; the caller is responsible for cleanup. On error, closing the transport will unblock any in-flight send goroutine.

func ServerSession

func ServerSession(trp transport.Transport, localCaps CapabilitySet, sessionID uint32) (*Session, error)

ServerSession performs the NETCONF hello exchange from the server side:

  1. Sends a <hello> with localCaps and the provided sessionID concurrently with reading the client's <hello>. Both must happen simultaneously because the underlying transport may be unbuffered (e.g. io.Pipe).
  2. Validates that the client hello contains base:1.0 and extracts the client capabilities.
  3. Negotiates framing: upgrades to chunked if both peers advertise base:1.1.

Returns an initialised Session on success, or a descriptive error on failure. The transport is NOT closed on error; the caller is responsible for cleanup. On error, closing the transport will unblock any in-flight send goroutine.

func (*Session) Close

func (s *Session) Close() error

Close closes the underlying transport, releasing all associated resources. After Close, the session must not be used.

func (*Session) FramingMode

func (s *Session) FramingMode() FramingMode

FramingMode returns the negotiated framing mode: FramingEOM or FramingChunked.

func (*Session) LocalCapabilities

func (s *Session) LocalCapabilities() CapabilitySet

LocalCapabilities returns the capabilities advertised by this peer.

func (*Session) Recv

func (s *Session) Recv() ([]byte, error)

Recv reads exactly one complete NETCONF message from the transport. It blocks until a full message is available or the transport is closed. It must be called from a single goroutine — the client dispatcher goroutine.

func (*Session) RecvStream

func (s *Session) RecvStream() (io.ReadCloser, error)

RecvStream returns a ReadCloser for the next complete NETCONF message.

Unlike Recv, the message bytes are NOT materialised into a []byte —the caller reads directly from the framing-layer buffer. The caller MUST Close the returned reader before calling RecvStream (or Recv) again.

This is the low-allocation path for callers (such as the client dispatcher) that feed the message bytes directly into an xml.Decoder without needing the raw []byte. For callers that do need the raw bytes, use Recv instead.

func (*Session) RemoteCapabilities

func (s *Session) RemoteCapabilities() CapabilitySet

RemoteCapabilities returns the capabilities advertised by the remote peer.

func (*Session) Send

func (s *Session) Send(msg []byte) error

Send writes a complete NETCONF message to the transport. It is NOT safe for concurrent use; callers that require concurrent sends must serialise access externally (e.g. with a sync.Mutex).

func (*Session) SessionID

func (s *Session) SessionID() uint32

SessionID returns the server-assigned session identifier (RFC 6241 §8.1). For client sessions this value comes from the server's hello; for server sessions it is the value supplied to ServerSession.

type SessionEnd

type SessionEnd struct {
	XMLName           xml.Name `xml:"urn:ietf:params:xml:ns:yang:ietf-netconf-notifications netconf-session-end"`
	Username          string   `xml:"username"`
	SessionID         uint32   `xml:"session-id"`
	SourceHost        string   `xml:"source-host,omitempty"`
	KilledBy          uint32   `xml:"killed-by,omitempty"`
	TerminationReason string   `xml:"termination-reason"`
}

SessionEnd is the RFC 6470 netconf-session-end notification body. It is generated when an existing NETCONF session is terminated. Callers unmarshal this from [Notification.Body] using the synthetic-wrapper pattern described in the package godoc.

  • Username: NETCONF username of the terminated session (required).
  • SessionID: NETCONF session-id of the terminated session (required).
  • SourceHost: IP address or hostname of the client; omitted when absent.
  • KilledBy: session-id of the session that issued <kill-session>; zero (omitted) when TerminationReason is not "killed".
  • TerminationReason: reason for termination (required). One of: "closed", "killed", "dropped", "timeout", "bad-hello", "other".

type SessionStart

type SessionStart struct {
	XMLName    xml.Name `xml:"urn:ietf:params:xml:ns:yang:ietf-netconf-notifications netconf-session-start"`
	Username   string   `xml:"username"`
	SessionID  uint32   `xml:"session-id"`
	SourceHost string   `xml:"source-host,omitempty"`
}

SessionStart is the RFC 6470 netconf-session-start notification body. It is generated when a new NETCONF session is established. Callers unmarshal this from [Notification.Body] using the synthetic-wrapper pattern described in the package godoc.

  • Username: NETCONF username of the new session (required).
  • SessionID: NETCONF session-id assigned to the session (required).
  • SourceHost: IP address or hostname of the client; omitted when absent.

type Unlock

type Unlock struct {
	XMLName xml.Name  `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 unlock"`
	Target  Datastore `xml:"target"`
}

Unlock releases the lock held on a configuration datastore by this session (RFC 6241 §7.6). Target identifies the datastore to unlock.

type Validate

type Validate struct {
	XMLName xml.Name  `xml:"urn:ietf:params:xml:ns:netconf:base:1.0 validate"`
	Source  Datastore `xml:"source"`
}

Validate validates the contents of a configuration datastore (RFC 6241 §8.6). Requires CapabilityValidate. Source identifies the datastore (or candidate) to validate.

type WithDefaultsMode

type WithDefaultsMode string

WithDefaultsMode is the mode value for the with-defaults parameter (RFC 6243 §3). It controls which default values appear in the device's response.

const (
	// WithDefaultsReportAll causes all default values to be reported (RFC 6243 §3.1).
	WithDefaultsReportAll WithDefaultsMode = "report-all"

	// WithDefaultsTrim causes default values to be omitted from the reply (RFC 6243 §3.2).
	WithDefaultsTrim WithDefaultsMode = "trim"

	// WithDefaultsExplicit causes only explicitly set values to be reported (RFC 6243 §3.3).
	WithDefaultsExplicit WithDefaultsMode = "explicit"

	// WithDefaultsReportAllTagged causes all default values to be reported with
	// a wd:default="true" annotation (RFC 6243 §3.4).
	WithDefaultsReportAllTagged WithDefaultsMode = "report-all-tagged"
)

type WithDefaultsParam

type WithDefaultsParam struct {
	XMLName xml.Name         `xml:"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults with-defaults"`
	Mode    WithDefaultsMode `xml:",chardata"`
}

WithDefaultsParam encodes the <with-defaults> parameter element required by RFC 6243 §4. The element uses the with-defaults YANG namespace and carries the mode as character data.

Example wire output:

<with-defaults xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults">report-all</with-defaults>

Directories

Path Synopsis
Package client provides the NETCONF client API.
Package client provides the NETCONF client API.
cmd
netconf command
Command netconf is an interactive REPL for exploring NETCONF devices.
Command netconf is an interactive REPL for exploring NETCONF devices.
netconf/repl
Package repl implements the interactive REPL loop for the netconf CLI tool.
Package repl implements the interactive REPL loop for the netconf CLI tool.
Package monitoring implements the ietf-netconf-monitoring YANG module (RFC 6022).
Package monitoring implements the ietf-netconf-monitoring YANG module (RFC 6022).
Package nacm implements the ietf-netconf-acm YANG module (RFC 8341).
Package nacm implements the ietf-netconf-acm YANG module (RFC 8341).
Package nmda implements the ietf-netconf-nmda YANG module (RFC 8526).
Package nmda implements the ietf-netconf-nmda YANG module (RFC 8526).
Package server provides the NETCONF server-side dispatch library.
Package server provides the NETCONF server-side dispatch library.
Package subscriptions implements the ietf-subscriptions YANG module (RFC 8639) and the ietf-netconf-subscriptions YANG module (RFC 8640).
Package subscriptions implements the ietf-subscriptions YANG module (RFC 8639) and the ietf-netconf-subscriptions YANG module (RFC 8640).
Package transport provides the framing layer and transport interface for the NETCONF protocol.
Package transport provides the framing layer and transport interface for the NETCONF protocol.
ssh
Package ssh provides SSH transport implementations for NETCONF.
Package ssh provides SSH transport implementations for NETCONF.
tls
Package tls provides TLS transport implementations for NETCONF.
Package tls provides TLS transport implementations for NETCONF.
Package yanglibrary implements the ietf-yang-library YANG module (RFC 8525).
Package yanglibrary implements the ietf-yang-library YANG module (RFC 8525).
Package yangpush implements the ietf-yang-push YANG module (RFC 8641).
Package yangpush implements the ietf-yang-push YANG module (RFC 8641).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL