telnet

package module
v0.0.0-...-2560197 Latest Latest
Warning

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

Go to latest
Published: Apr 12, 2021 License: MIT Imports: 2 Imported by: 0

README

Package telnet

The telnet package provides basic telnet client and server implementations for Go, including handling of IACs and extensible telnet option negotiation.

Currently both the basic client and server are implemented, as well as a NAWS client/server handler as a working example. Additional handlers may be added to the core library over time (feel free to submit a PR if you've written one you'd like to see added!)

Usage

Running a server:

svr := telnet.NewServer(":9999", telnet.HandleFunc(func(c *telnet.Connection){
	log.Printf("Connection received: %s", c.RemoteAddr())
	c.Write([]byte("Hello world!\r\n"))
	c.Close()
}))
svr.ListenAndServe()

The server API is modeled after the net/http API, so it should be easy to get your bearings; of course, telnet and HTTP are very different beasts, so the similarities are somewhat limited. The server listens on a TCP address for new connections. Whenever a new connection is received, the connection handler is called with the connection object. This object is a wrapper for the underlying TCP connection, which aims to transparently handle IAC. There is a slightly more complex example located in the example package.

Running a client is pretty simple:

conn, err := telnet.Dial("127.0.0.1:9999")

This is really straightforward - dial out, get a telnet connection handler back. Again, this handles IAC transparently, and like the Server, can take a list of optional IAC handlers. Bear in mind that some handlers - for example, the included NAWS handler - use different Option functions to register them with a client versus a server; this is because they may behave differently at each end. See the documentation for the options for more details.

Linereader

A sub-package, linereader, exposes a simple reader intended to be run in a Goroutine, which consumes lines from an io.Reader and sends them over a channel for asynchronous handling.

Documentation

Overview

The telnet package provides basic telnet client and server implementations. It includes handling of IACs and extensible telnet option negotiation for both clients and servers.

Running a server:

svr := telnet.NewServer(":9999", telnet.HandleFunc(func(c *telnet.Connection){
	log.Printf("Connection received: %s", c.RemoteAddr())
	c.Write([]byte("Hello world!\r\n"))
	c.Close()
}))
svr.ListenAndServe()

The server API is modeled after the net/http API, so it should be easy to get your bearings; of course, telnet and HTTP are very different beasts, so the similarities are somewhat limited. The server listens on a TCP address for new connections. Whenever a new connection is received, the connection handler is called with the connection object. This object is a wrapper for the underlying TCP connection, which aims to transparently handle IAC.

Running a client is pretty simple:

conn, err := telnet.Dial("127.0.0.1:9999")

This is really straightforward - dial out, get a telnet connection handler back. Again, this handles IAC transparently, and like the Server, can take a list of optional IAC handlers. Bear in mind that some handlers - for example, the included NAWS handler - use different Option functions to register them with a client versus a server; this is because they may behave differently at each end. See the documentation for the options for more details.

Index

Constants

View Source
const (
	TeloptBINARY         = byte(0)   // 8-bit data path
	TeloptECHO           = byte(1)   // echo
	TeloptRCP            = byte(2)   // prepare to reconnect
	TeloptSGA            = byte(3)   // suppress go ahead
	TeloptNAMS           = byte(4)   // approximate message size
	TeloptSTATUS         = byte(5)   // give status
	TeloptTM             = byte(6)   // timing mark
	TeloptRCTE           = byte(7)   // remote controlled transmission and echo
	TeloptNAOL           = byte(8)   // negotiate about output line width
	TeloptNAOP           = byte(9)   // negotiate about output page size
	TeloptNAOCRD         = byte(10)  // negotiate about CR disposition
	TeloptNAOHTS         = byte(11)  // negotiate about horizontal tabstops
	TeloptNAOHTD         = byte(12)  // negotiate about horizontal tab disposition
	TeloptNAOFFD         = byte(13)  // negotiate about formfeed disposition
	TeloptNAOVTS         = byte(14)  // negotiate about vertical tab stops
	TeloptNAOVTD         = byte(15)  // negotiate about vertical tab disposition
	TeloptNAOLFD         = byte(16)  // negotiate about output LF disposition
	TeloptXASCII         = byte(17)  // extended ascii character set
	TeloptLOGOUT         = byte(18)  // force logout
	TeloptBM             = byte(19)  // byte macro
	TeloptDET            = byte(20)  // data entry terminal
	TeloptSUPDUP         = byte(21)  // supdup protocol
	TeloptSUPDUPOUTPUT   = byte(22)  // supdup output
	TeloptSNDLOC         = byte(23)  // send location
	TeloptTTYPE          = byte(24)  // terminal type
	TeloptEOR            = byte(25)  // end or record
	TeloptTUID           = byte(26)  // TACACS user identification
	TeloptOUTMRK         = byte(27)  // output marking
	TeloptTTYLOC         = byte(28)  // terminal location number
	Telopt3270REGIME     = byte(29)  // 3270 regime
	TeloptX3PAD          = byte(30)  // X.3 PAD
	TeloptNAWS           = byte(31)  // window size
	TeloptTSPEED         = byte(32)  // terminal speed
	TeloptLFLOW          = byte(33)  // remote flow control
	TeloptLINEMODE       = byte(34)  // Linemode option
	TeloptXDISPLOC       = byte(35)  // X Display Location
	TeloptOLDENVIRON     = byte(36)  // Old - Environment variables
	TeloptAUTHENTICATION = byte(37)  // Authenticate
	TeloptENCRYPT        = byte(38)  // Encryption option
	TeloptNEWENVIRON     = byte(39)  // New - Environment variables
	TeloptEXOPL          = byte(255) // extended-options-list
)

Telnet Options

View Source
const (
	TelQualIS    = byte(0) // option is...
	TelQualSEND  = byte(1) // send option
	TelQualINFO  = byte(2) // ENVIRON: informational version of IS
	TelQualREPLY = byte(2) // AUTHENTICATION: client version of IS
	TelQualNAME  = byte(3) // AUTHENTICATION: client version of IS

	LFlowOFF        = byte(0) // Disable remote flow control
	LFlowON         = byte(1) // Enable remote flow control
	LFlowRESTARTANY = byte(2) // Restart output on any char
	LFlowRESTARTXON = byte(3) // Restart output only on XON
)

sub-option qualifiers

View Source
const (
	EncryptIS       = byte(0) // I pick encryption type ...
	EncryptSUPPORT  = byte(1) // I support encryption types ...
	EncryptREPLY    = byte(2) // Initial setup response
	EncryptSTART    = byte(3) // Am starting to send encrypted
	EncryptEND      = byte(4) // Am ending encrypted
	EncryptREQSTART = byte(5) // Request you start encrypting
	EncryptREQEND   = byte(6) // Request you send encrypting
	EncryptENCKEYID = byte(7)
	EncryptDECKEYID = byte(8)
	EncryptCNT      = byte(9)

	EncTypeANY      = byte(0)
	EncTypeDESCFB64 = byte(1)
	EncTypeDESOFB64 = byte(2)
	EncTypeCNT      = byte(3)
)

ENCRYPTion suboptions

View Source
const (
	SUSP  = byte(237)
	ABORT = byte(238)
	EOR   = byte(239)
	SE    = byte(240)
	NOP   = byte(241)
	DM    = byte(242)
	BRK   = byte(243)
	IP    = byte(244)
	AO    = byte(245)
	AYT   = byte(246)
	EC    = byte(247)
	EL    = byte(248)
	GA    = byte(249)
	SB    = byte(250)
	WILL  = byte(251)
	WONT  = byte(252)
	DO    = byte(253)
	DONT  = byte(254)
	IAC   = byte(255)
)

Telnet IAC constants

View Source
const Escape = byte('\033')

Variables

View Source
var (
	// styles
	Reset        = []byte("\033[0m")
	Bold         = []byte("\033[1m")
	Underline    = []byte("\033[4m")
	Conceal      = []byte("\033[8m")
	NormalWeight = []byte("\033[22m")
	NoUnderline  = []byte("\033[24m")
	Reveal       = []byte("\033[28m")
	// colors - foreground
	FGBlack   = []byte("\033[30m")
	FGRed     = []byte("\033[31m")
	FGGreen   = []byte("\033[32m")
	FGYellow  = []byte("\033[33m")
	FGBlue    = []byte("\033[34m")
	FGMagenta = []byte("\033[35m")
	FGCyan    = []byte("\033[36m")
	FGWhite   = []byte("\033[37m")
	FGDefault = []byte("\033[39m")
	// background
	BGBlack   = []byte("\033[40m")
	BGRed     = []byte("\033[41m")
	BGGreen   = []byte("\033[42m")
	BGYellow  = []byte("\033[43m")
	BGBlue    = []byte("\033[44m")
	BGMagenta = []byte("\033[45m")
	BGCyan    = []byte("\033[46m")
	BGWhite   = []byte("\033[47m")
	BGDefault = []byte("\033[49m")
	// xterm
	TitleBarFmt = "\033]0;%s\a"
)

ANSI control sequences

View Source
var EncTypeNames = []string{
	"ANY", "DES_CFB64", "DES_OFB64"}

EncTypeNames is a mapping of bytes to strings for EncType constants.

View Source
var EncryptNames = []string{
	"IS", "SUPPORT", "REPLY", "START", "END",
	"REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID"}

EncryptNames is a mapping of bytes to strings for Encrypt constants.

View Source
var TelOpts = []string{"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
	"STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP",
	"NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",
	"NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
	"DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
	"SEND LOCATION", "TERMINAL TYPE", "END OF RECORD",
	"TACACS UID", "OUTPUT MARKING", "TTYLOC",
	"3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW",
	"LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
	"ENCRYPT", "NEW-ENVIRON"}

TelOpts gives you a mapping of index to a textual representation of the telnet option.

Functions

This section is empty.

Types

type Connection

type Connection struct {
	// The underlying network connection.
	net.Conn

	// OptionHandlers handle IAC options; the key is the IAC option code.
	OptionHandlers map[byte]Negotiator
	// contains filtered or unexported fields
}

Connection to the telnet server. This lightweight TCPConn wrapper handles telnet control sequences transparently in reads and writes, and provides handling of supported options.

func Dial

func Dial(addr string, options ...Option) (conn *Connection, err error)

Dial establishes a telnet connection with the remote host specified by addr in host:port format. Any specified option handlers will be applied to the connection if it is successful.

func NewConnection

func NewConnection(c net.Conn, options []Option) *Connection

NewConnection initializes a new Connection for this given TCPConn. It will register all the given Option handlers and call Offer() on each, in order.

func (*Connection) RawWrite

func (c *Connection) RawWrite(b []byte) (n int, err error)

RawWrite writes raw data to the connection, without escaping done by Write. Use of RawWrite over Conn.Write allows Connection to do any additional handling necessary, so long as it does not modify the raw data sent.

func (*Connection) Read

func (c *Connection) Read(b []byte) (n int, err error)

Read from the connection, transparently removing and handling IAC control sequences. It may attempt multiple reads against the underlying connection if it receives back only IAC which gets stripped out of the stream.

func (*Connection) SetWindowTitle

func (c *Connection) SetWindowTitle(title string)

SetWindowTitle attempts to set the client's telnet window title. Clients may or may not support this.

func (*Connection) Write

func (c *Connection) Write(b []byte) (n int, err error)

Write to the connection, escaping IAC as necessary.

type HandleFunc

type HandleFunc func(conn *Connection)

HandleFunc makes it easy to pass a function as a Handler instead of a full type.

func (HandleFunc) HandleTelnet

func (f HandleFunc) HandleTelnet(conn *Connection)

HandleTelnet implements Handler, and simply calls the function.

type Handler

type Handler interface {
	HandleTelnet(conn *Connection)
}

Handler is a telnet connection handler. The Handler passed to a server will be called for all incoming connections.

type Negotiator

type Negotiator interface {
	// OptionCode returns the 1-byte option code that indicates this option.
	OptionCode() byte
	// Offer is called when a new connection is initiated. It offers the handler
	// an opportunity to advertise or request an option.
	Offer(conn *Connection)
	// HandleDo is called when an IAC DO command is received for this option,
	// indicating the client is requesting the option to be enabled.
	HandleDo(conn *Connection)
	// HandleWill is called when an IAC WILL command is received for this
	// option, indicating the client is willing to enable this option.
	HandleWill(conn *Connection)
	// HandleSB is called when a subnegotiation command is received for this
	// option. body contains the bytes between `IAC SB <OptionCode>` and `IAC
	// SE`.
	HandleSB(conn *Connection, body []byte)
}

Negotiator defines the requirements for a telnet option handler.

type Option

type Option func(c *Connection) Negotiator

Option functions add handling of a telnet option to a Server. The Option function takes a connection (which it can store but needn't) and returns a Negotiator; it is up to the Option function whether a single instance of the Negotiator is reused or if a new instance is created for each connection.

type Server

type Server struct {
	// Address is the addres the Server listens on.
	Address string
	// contains filtered or unexported fields
}

Server listens for telnet connections.

func NewServer

func NewServer(addr string, handler Handler, options ...Option) *Server

NewServer constructs a new telnet server.

func (*Server) ListenAndServe

func (s *Server) ListenAndServe() error

ListenAndServe runs the telnet server by creating a new Listener using the current Server.Address, and then calling Serve().

func (*Server) Serve

func (s *Server) Serve(l net.Listener) error

Serve runs the telnet server. This function does not return and should probably be run in a goroutine.

func (*Server) Stop

func (s *Server) Stop()

Stop the telnet server. This stops listening for new connections, but does not affect any active connections already opened.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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