server
import "github.com/TheManticoreProject/Manticore/network/llmnr/server"
Index
- func HandlerDescribePacket(server *Server, remoteAddr net.Addr, writer ResponseWriter, message *message.Message) bool
- func HandlerDescribePacketJson(server *Server, remoteAddr net.Addr, writer ResponseWriter, message *message.Message) bool
- type Handler
- type HandlerFunc
- type ResponseWriter
- type Server
- func NewIPv4Server() (*Server, error)
- func NewIPv4ServerWithHandlers(handlers []Handler) (*Server, error)
- func NewIPv6Server() (*Server, error)
- func NewIPv6ServerWithHandlers(handlers []Handler) (*Server, error)
- func NewServer(network string, handlers []Handler) (*Server, error)
- func (s *Server) Close() error
- func (s *Server) IsIPv4() bool
- func (s *Server) IsIPv6() bool
- func (s *Server) ListenAndServe() error
- func (s *Server) RegisterHandler(handler Handler)
- func (s *Server) Serve() error
- func (s *Server) SetDebug(debug bool)
func HandlerDescribePacket
func HandlerDescribePacket(server *Server, remoteAddr net.Addr, writer ResponseWriter, message *message.Message) bool
HandlerDescribePacket logs detailed information about an LLMNR packet received by the
Parameters: - server: A pointer to the Server that received the packet. - remoteAddr: The address of the remote client that sent the packet. - writer: A ResponseWriter to send responses back to the client. - message: The LLMNR message received from the client.
The function logs the following details about the received LLMNR packet: - The remote address of the client that sent the packet. - The number of questions in the packet, and for each question:
- The class of the question.
- The type of the question.
- The name in the question.
- The number of answers in the packet, and for each answer:
- The class of the answer.
- The type of the answer.
- The name in the answer.
- The TTL (Time to Live) of the answer.
- The RDLENGTH (length of the RDATA field) of the answer.
- The RDATA (resource data) of the answer.
- The number of authority records in the packet, and for each authority record:
- The class of the authority record.
- The type of the authority record.
- The name in the authority record.
- The TTL (Time to Live) of the authority record.
- The RDLENGTH (length of the RDATA field) of the authority record.
- The RDATA (resource data) of the authority record.
The function uses a logger to output the information in a structured format, with indentation to represent the hierarchy of the packet’s contents. The logger is locked during the function execution to ensure thread-safe logging.
func HandlerDescribePacketJson
func HandlerDescribePacketJson(server *Server, remoteAddr net.Addr, writer ResponseWriter, message *message.Message) bool
HandlerDescribePacketJson logs the details of the LLMNR message in JSON format.
Parameters: - server: A pointer to the Server that received the packet. - remoteAddr: The address of the remote client that sent the packet. - writer: A ResponseWriter to send responses back to the client. - message: The LLMNR message received from the client.
The function logs the details of the LLMNR message in JSON format.
type Handler
Handler defines the interface for processing LLMNR queries
type Handler interface {
Run(server *Server, remoteAddr net.Addr, writer ResponseWriter, message *message.Message) bool
}
type HandlerFunc
HandlerFunc is an adapter to allow regular functions to serve as LLMNR handlers
type HandlerFunc func(*Server, net.Addr, ResponseWriter, *message.Message) bool
func (HandlerFunc) Run
func (f HandlerFunc) Run(server *Server, remoteAddr net.Addr, writer ResponseWriter, message *message.Message) bool
Run executes the handler function to process an LLMNR query.
Parameters: - server: The Server instance that received the query. - remoteAddr: The address of the client that sent the query. - writer: The ResponseWriter used to send responses back to the client. - message: The Message received from the client.
The function calls the handler function with the provided ResponseWriter and Message. It allows regular functions to be used as LLMNR handlers by adapting them to the Handler interface.
Example usage:
handlerFunc := func(w ResponseWriter, r *message.Message) {
// Process the LLMNR query and write a response
}
handler := HandlerFunc(handlerFunc)
RegisterHandler(handler)
This function is typically called internally by the Server when a new LLMNR query is received.
type ResponseWriter
ResponseWriter interface is used by an LLMNR handler to construct a response
type ResponseWriter interface {
WriteMessage(*message.Message) error
GetRemoteAddr() net.Addr
}
func NewResponseWriter
func NewResponseWriter(server *Server, remoteAddr net.Addr) ResponseWriter
NewResponseWriter creates a new ResponseWriter instance.
Parameters: - server: The Server instance that received the query. - remoteAddr: The address of the client that sent the query.
Returns: - A new ResponseWriter instance.
type Server
Server represents an LLMNR server.
The Server struct contains the necessary fields and methods to handle LLMNR (Link-Local Multicast Name Resolution) requests and responses. It supports both IPv4 and IPv6 communication over UDP.
Fields:
- Handlers: A slice of Handler interfaces that process incoming LLMNR messages.
- Network: A string representing the network type. Known networks are “tcp”, “tcp4” (IPv4-only), “tcp6” (IPv6-only), “udp”, “udp4” (IPv4-only), “udp6” (IPv6-only), “ip”, “ip4” (IPv4-only), “ip6” (IPv6-only), “unix”, “unixgram”, and “unixpacket”.
- Address: A pointer to a net.UDPAddr struct representing the server’s address.
- Conn: A pointer to a net.UDPConn struct representing the server’s UDP connection.
- CloseOnce: A sync.Once struct to ensure the server is closed only once.
- Closed: A channel that is closed when the server is shut down.
- Debug: A boolean flag indicating whether debug mode is enabled.
type Server struct {
// Handlers is a slice of Handler interfaces that process incoming LLMNR messages.
Handlers []Handler
// Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only),
// "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4"
// (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and
// "unixpacket".
Network string
// Address is the address of the server.
Address *net.UDPAddr
// Conn is the connection of the server.
Conn *net.UDPConn
// CloseOnce is a sync.Once struct to ensure the server is closed only once.
CloseOnce sync.Once
// Closed is a channel that is closed when the server is shut down.
Closed chan struct{}
// Debug is a boolean flag indicating whether debug mode is enabled.
Debug bool
}
func NewIPv4Server
func NewIPv4Server() (*Server, error)
NewIPv4Server creates a new LLMNR server for IPv4.
This function initializes a new Server instance configured to use the “udp4” network type for IPv4 communication. It does not accept any handlers and initializes the server with an empty list of The server’s internal state, including the handlers, closed channel, and debug flag, is initialized.
Returns: - A pointer to the newly created Server instance. - An error if the server creation fails.
Example usage:
server, err := llmnr.NewIPv4Server()
if err != nil {
log.Fatalf("Failed to create IPv4 server: %v", err)
}
if server.IsIPv4() {
fmt.Println("The server is using an IPv4 address.")
} else {
fmt.Println("The server is not using an IPv4 address.")
}
func NewIPv4ServerWithHandlers
func NewIPv4ServerWithHandlers(handlers []Handler) (*Server, error)
NewIPv4ServerWithHandlers creates a new LLMNR server for IPv4 with the specified
This function initializes a new Server instance configured to use the “udp4” network type for IPv4 communication. It accepts a list of handlers that will be used to process incoming LLMNR requests. The server’s internal state, including the handlers, closed channel, and debug flag, is initialized.
Parameters: - handlers: A slice of Handler instances to handle incoming LLMNR requests.
Returns: - A pointer to the newly created Server instance. - An error if the server creation fails.
Example usage:
handlers := []llmnr.Handler{
llmnr.HandlerFunc(myHandlerFunc),
}
server, err := llmnr.NewIPv4ServerWithHandlers(handlers)
if err != nil {
log.Fatalf("Failed to create IPv4 server: %v", err)
}
if server.IsIPv4() {
fmt.Println("The server is using an IPv4 address.")
} else {
fmt.Println("The server is not using an IPv4 address.")
}
func NewIPv6Server
func NewIPv6Server() (*Server, error)
NewIPv6Server creates a new LLMNR server for IPv6.
This function initializes a new Server instance configured to use the “udp6” network type for IPv6 communication. It does not accept any handlers and initializes the server with an empty list of The server’s internal state, including the handlers, closed channel, and debug flag, is initialized.
Returns: - A pointer to the newly created Server instance. - An error if the server creation fails.
Example usage:
server, err := llmnr.NewIPv6Server()
if err != nil {
log.Fatalf("Failed to create IPv6 server: %v", err)
}
if server.IsIPv6() {
fmt.Println("The server is using an IPv6 address.")
} else {
fmt.Println("The server is not using an IPv6 address.")
}
func NewIPv6ServerWithHandlers
func NewIPv6ServerWithHandlers(handlers []Handler) (*Server, error)
NewIPv6ServerWithHandlers creates a new LLMNR server for IPv6 with the specified
This function initializes a new Server instance configured to use the “udp6” network type for IPv6 communication. It accepts a list of handlers that will be used to process incoming LLMNR requests. The server’s internal state, including the handlers, closed channel, and debug flag, is initialized.
Parameters: - handlers: A slice of Handler instances to handle incoming LLMNR requests.
Returns: - A pointer to the newly created Server instance. - An error if the server creation fails.
Example usage:
handlers := []llmnr.Handler{
llmnr.HandlerFunc(myHandlerFunc),
}
server, err := llmnr.NewIPv6ServerWithHandlers(handlers)
if err != nil {
log.Fatalf("Failed to create IPv6 server: %v", err)
}
if server.IsIPv6() {
fmt.Println("The server is using an IPv6 address.")
} else {
fmt.Println("The server is not using an IPv6 address.")
}
func NewServer
func NewServer(network string, handlers []Handler) (*Server, error)
NewServer creates a new LLMNR server with the specified network and
This function initializes a new Server instance with the provided network type and a list of The server is configured to use the specified network (e.g., “udp4” for IPv4, “udp6” for IPv6) and initializes its internal state, including the handlers, closed channel, and debug flag.
Parameters: - network: A string specifying the network type (e.g., “udp4”, “udp6”). - handlers: A slice of Handler instances to handle incoming LLMNR requests.
Returns: - A pointer to the newly created Server instance. - An error if the server creation fails.
Example usage:
handlers := []llmnr.Handler{
llmnr.HandlerFunc(myHandlerFunc),
}
server, err := llmnr.NewServer("udp4", handlers)
if err != nil {
log.Fatalf("Failed to create server: %v", err)
}
if server.IsIPv4() {
fmt.Println("The server is using an IPv4 address.")
} else {
fmt.Println("The server is not using an IPv4 address.")
}
func (*Server) Close
func (s *Server) Close() error
Close gracefully shuts down the LLMNR server by closing the UDP connection and signaling the server to stop. It ensures that the server is closed only once, even if Close is called multiple times.
The function uses a sync.Once to guarantee that the server’s resources are released only once. It closes the server’s closed channel to signal any goroutines to stop, and if the server has an active UDP connection, it closes the connection.
Returns: - An error if the server fails to close the UDP connection or encounters an error during the shutdown process.
Example usage: server, err := llmnr.NewServer(handler)
if err != nil {
log.Fatalf("Failed to create server: %v", err)
}
err = server.ListenAndServe()
if err != nil {
log.Fatalf("Server encountered an error: %v", err)
}
// When you want to stop the server err = server.Close()
if err != nil {
log.Fatalf("Failed to close server: %v", err)
}
func (*Server) IsIPv4
func (s *Server) IsIPv4() bool
IsIPv4 checks if the server’s address is an IPv4 address.
Returns: - A boolean value: true if the server’s address is an IPv4 address, false otherwise.
The function uses the net.IP.To4 method to determine if the IP address is an IPv4 address. If the IP address is not an IPv4 address, the method will return nil, and the function will return false.
Example usage: server, err := llmnr.NewIPv4Server()
if err != nil {
log.Fatalf("Failed to create server: %v", err)
}
if server.IsIPv4() {
fmt.Println("The server is using an IPv4 address.")
} else {
fmt.Println("The server is not using an IPv4 address.")
}
func (*Server) IsIPv6
func (s *Server) IsIPv6() bool
IsIPv6 checks if the server’s address is an IPv6 address.
Returns: - A boolean value: true if the server’s address is an IPv6 address, false otherwise.
An address is considered IPv6 when it has a valid 16-byte representation and cannot be represented as an IPv4 address (net.IP.To4 returns nil). Checking only To16() would incorrectly classify IPv4 addresses as IPv6, because net.IP.To16() also returns a non-nil 16-byte representation for IPv4.
Example usage: server, err := llmnr.NewIPv6Server()
if err != nil {
log.Fatalf("Failed to create server: %v", err)
}
if server.IsIPv6() {
fmt.Println("The server is using an IPv6 address.")
} else {
fmt.Println("The server is not using an IPv6 address.")
}
func (*Server) ListenAndServe
func (s *Server) ListenAndServe() error
ListenAndServe starts the LLMNR server and begins listening for incoming UDP packets on the IPv4 multicast address. It creates a UDP connection and assigns it to the server’s connection field. The function then enters a loop to continuously read from the UDP connection, decode incoming messages, and pass them to the server’s handler.
Returns: - An error if the server fails to start listening on the UDP connection or encounters an error during execution.
Example usage: server, err := llmnr.NewServer(handler)
if err != nil {
log.Fatalf("Failed to create server: %v", err)
}
err = server.ListenAndServe()
if err != nil {
log.Fatalf("Server encountered an error: %v", err)
}
func (*Server) RegisterHandler
func (s *Server) RegisterHandler(handler Handler)
RegisterHandler registers a new handler to the LLMNR
Parameters: - handler: The Handler to be registered. It must implement the Handler interface.
The function appends the provided handler to the server’s list of handlers. These handlers will be invoked to process incoming LLMNR queries. Handlers are executed in the order they are registered.
Example usage:
handler := &MyHandler{}
RegisterHandler(handler)
This function is typically called before starting the server to ensure that all necessary handlers are in place to process incoming queries.
func (*Server) Serve
func (s *Server) Serve() error
Serve handles incoming LLMNR requests and processes them in a loop until the server is closed.
The function reads packets from the UDP connection, decodes the messages, and handles LLMNR queries. It uses a buffer to read the incoming packets and processes each packet in a separate goroutine.
The function also supports debugging, printing detailed information about the received packets and errors.
Returns: - An error if the server encounters an issue while reading from the UDP connection.
Example usage: server, err := llmnr.NewServer(handler)
if err != nil {
log.Fatalf("Failed to create server: %v", err)
}
err = server.ListenAndServe()
if err != nil {
log.Fatalf("Server encountered an error: %v", err)
}
// When you want to stop the server err = server.Close()
if err != nil {
log.Fatalf("Failed to close server: %v", err)
}
func (*Server) SetDebug
func (s *Server) SetDebug(debug bool)
SetDebug enables or disables debug mode for the LLMNR server.
Parameters: - debug: A boolean value indicating whether to enable (true) or disable (false) debug mode.
When debug mode is enabled, the server will print detailed information about incoming packets, decoded messages, and any errors encountered during processing. This can be useful for troubleshooting and understanding the server’s behavior.
Example usage: server, err := llmnr.NewServer(handler)
if err != nil {
log.Fatalf("Failed to create server: %v", err)
}
server.SetDebug(true)
err = server.ListenAndServe()
if err != nil {
log.Fatalf("Server encountered an error: %v", err)
}