Package arp implements the ARP protocol, as described in RFC 826. MIT Licensed.

arp Build Status GoDoc Go Report Card

Package arp implements the ARP protocol, as described in RFC 826. MIT Licensed.

Portions of this code are taken from the Go standard library. The Go standard library is Copyright (c) 2012 The Go Authors. All rights reserved. The Go license can be found at https://golang.org/LICENSE.

Owner
Matt Layher
Software Engineer. Go, Linux, and open source software enthusiast. On and ever upward.
Matt Layher
Comments
  • Support infiniband device

    Support infiniband device

    Trying to use a downsteam package that references this repo. I ran into an issue using IP over Infiniband device type in a mix ethernet/infiniband environment.

     ib0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 4092 qdisc mq state UP mode DEFAULT group default qlen 256
        link/infiniband 20:00:00:67:fe:80:00:00:00:00:00:00:e0:07:1b:ff:ff:7d:e2:e8 brd 00:ff:ff:ff:ff:12:40:1b:ff:ff:00:00:00:00:00:00:ff:ff:ff:ff
    

    Infiniband devices use 12 digit mac addresses and this probably unnecessary sanity check in packet.go causes error. Lines 90-92:

    	if len(srcHW) != len(dstHW) {
    		return nil, ErrInvalidHardwareAddr
    	}
    

    It assumes all MAC addresses are 6 character. Removing the check and recompiling allowed downstream Metallb to work on my IP over Infiniband interconnects.

  • How is SetDeadline supposed to work?

    How is SetDeadline supposed to work?

    My code:

    	arpInterface, err := net.InterfaceByName("en0"); if err != nil {
    		panic("Cannot open en0")
    	}
    	arpClient, err := arp.Dial(arpInterface); if err != nil {
    		panic("sendArp: Cannot bind client to interface")
    	}
    
    	fmt.Println("ip = ", ip)
    	timeout := time.Now().Add(3*time.Second)
    	fmt.Println("timeout set to ", timeout )
    	arpClient.SetDeadline(timeout)
    	macaddr, err := arpClient.Resolve(ip); if err != nil {
    		fmt.Println("Request error is ", err)
    	} else {
    		fmt.Println("Resolved ", ip, " to ", macaddr)
    	}
    

    When I try to resolve a nonexistent IP, arpClient.Resolve() hangs indefinitely. I'd like to specify a timeout, and I thought that SetDeadline or SetReadDeadline would work. Obviously I'm doing something wrong. Advice appreciated.

  • *: restructure API

    *: restructure API

    This change completely overhauls the API.

    It gets rid of the server and client distinction. From a traditional networking standpoint, there are no ARP clients and servers. Each device will send requests, and it will answer to requests. From a Go perspective, having the distinction made some sense – many users will probably only ever send requests, not answer them. However, the distinction made it harder for people who do have to do both. It also lacked a way for sending many requests at once with a single client. While this could've been fixed by adding more APIs, it seemed a lot more straightforward to unify the client and server responsibilities. This gets rid of the server, the muxer and the request type.

    Instead, we provide the 2 basic building blocks (reading packets and writing packets) and some high level functions:

    • Read, which reads a single packet. The packet may be a request, or it may be a response. The user can determine this based on the Operation and act accordingly. This allows to work as a server, or as a client dealing with many responses, or a mixture of both.
    • Write, which will send a packet.
    • Request, which sends a single request. It does not wait for a response. The response will be read via Read.
    • Respond, which will send a response to a request.
    • Resolve, which will send a single request, then wait for a response. This provides a high-level way for resolving an IP to a MAC address, without having to deal with individual packets or filtering out other noise. On the other hand, it cannot be used concurrently with Read, as the two would conflict with each other. It's an either-or choice.

    Additionally, the following helpers were added:

    • IsReply, to check if a packet is a response to a request.
    • IsReplyFrom, like IsReply but also check for a specific IP.
  • go generate produces error

    go generate produces error

    Hi thanks for this package.

    I was looking through the source and seeing that string.go and packet.go are generated (this comes from the go std lib I assume) as such 'go generate' does not work:

    packet.go:26: running "stringer": exec: "stringer": executable file not found in $PATH
    

    string.go also has some lint issues; I don't know if you want to keep this "this is generated code" in these files or clean them up?

  • Linux (docker and raspberry pi): Resolve() not returning

    Linux (docker and raspberry pi): Resolve() not returning

    I have the following code:

    func sendArp(ip net.IP, arpClient *arp.Client, config chirpdconfig) (net.HardwareAddr, error) {
    
    	l.Println("sendArp: in sendarp for ", ip)
    	timeout := time.Now().Add(config.arpResponseTimeout)
    	l.Println("sendArp: timeout = ", timeout)
    	err := arpClient.SetDeadline(timeout)
    	if  err != nil {
    		panic(fmt.Sprintln("sendArp: cannot set deadline: ", err))
    	}
    
    	l.Println("sendArp: post SetDeadline")
    	macaddr, err := arpClient.Resolve(ip)
    	l.Println("sendArp: post Resolve")
    	if err != nil {
    		l.Println("sendArp: err = ", err)
    	}
    	l.Println("macaddr = ", macaddr)
    	return macaddr, err
    }
    

    I get the following output:

    2017/10/12 sendArp: in sendarp for  10.0.1.222
    2017/10/12 sendArp: timeout =  2017-10-12 21:19:36.879028782 -0700 PDT m=+7.533864643
    2017/10/12 sendArp: post SetDeadline
    

    and then things just hang.

    I understand from #12 that SetDeadline doesn't work on MacOS, so that might explain the linux/docker failure, but I tried this on a raspberry pi running raspbian and it's not working either. What am I doing wrong?

  • Allow the user to create a Client from a PacketConn

    Allow the user to create a Client from a PacketConn

    In particular, on Linux, this will allow the user to create an arp.Client in promiscious mode, by having raw.ListenPacket call socket(2) with htons(ETH_P_ALL) by passing syscall.ETH_P_ALL into it.

    An example replacement of an existing call site would look something like:

    dev, err := net.InterfaceByName("name0")
    if err != nil {
        return err
    }
    packetConn, err := raw.ListenPacket(dev, syscall.ETH_P_ALL)
    if err != nil {
        return err
    }
    arpClient, err := arp.NewClientPacketConn(dev, packetConn)
    ...
    
  • Operation not permitted

    Operation not permitted

    Hi, I'm trying to use this library for sending some ARP requests, and I get an

    operation not permitted

    error when I try to create a client. I'm getting the interfacing, passing it's pointer to the NewClient method. like so:

    ifaces, _ := net.Interfaces()
    // The third for me is the relevant one.
    client, err := arp.NewClient(&ifaces[2])
    if err != nil {
        fmt.Println(err)
    }
    
    target := net.ParseIP("10.0.18.70")
    err = client.Request(target)
    if err != nil {
        fmt.Println(err)
    }
    

    So I then get a nil error when I call client.Request, because the original client is not permitted. Is this the correct way to proceed? Should I be using sudo? When I do that it complains that the GOPATH isn't set, and things get tricky.

  • client: make WriteTo use addr argument for the Ethernet frame

    client: make WriteTo use addr argument for the Ethernet frame

    According to RFC 826, the target hardware address in the ARP packet isn't important (in one place even marked as "don't care"), and it specifically says that the address lacks meaning in the request form. Nevertheless, hardware exists that (regardless of whether or not it's compliant) imposes requirements on the target address.

    Previously, the WriteTo function in this library has disregarded its addr parameter and instead used the target MAC address from inside the ARP packet for the Ethernet destination address. This made it impossible to communicate with hardware that has expectations on the target MAC address field as you couldn't use an ARP target MAC address that's distinct from the Ethernet frame's destination address.

    Example

    package main
    
    import (
    	"net"
    
    	"github.com/mdlayher/arp"
    	"github.com/mdlayher/ethernet"
    )
    
    func main() {
    	sourceMAC := net.HardwareAddr{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}
    	sourceIP := net.IPv4(10, 1, 2, 3)
    	targetMAC := net.HardwareAddr{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
    	targetIP := net.IPv4(10, 1, 2, 4)
    	packet, _ := arp.NewPacket(arp.OperationRequest, sourceMAC, sourceIP, targetMAC, targetIP)
    
    	iface, _ := net.InterfaceByName("wlp3s0")
    	client, _ := arp.Dial(iface)
    	destinationMAC := ethernet.Broadcast // this one's ignored and replaced with zeroes
    	client.WriteTo(packet, destinationMAC)
    }
    

    Before

    15:55:02.410404 ARP, Request who-has 10.1.2.4 tell 10.1.2.3, length 46
    	0x0000:  0000 0000 0000 1234 5678 9abc 0806 0001  .......4Vx......
    	0x0010:  0800 0604 0001 1234 5678 9abc 0a01 0203  .......4Vx......
    	0x0020:  0000 0000 0000 0a01 0204 0000 0000 0000  ................
    	0x0030:  0000 0000 0000 0000 0000 0000            ............
    

    After

    15:57:30.886322 ARP, Request who-has 10.1.2.4 tell 10.1.2.3, length 46
    	0x0000:  ffff ffff ffff 1234 5678 9abc 0806 0001  .......4Vx......
    	0x0010:  0800 0604 0001 1234 5678 9abc 0a01 0203  .......4Vx......
    	0x0020:  0000 0000 0000 0a01 0204 0000 0000 0000  ................
    	0x0030:  0000 0000 0000 0000 0000 0000            ............
    
  • client: relax reply checks, remove IsReply and IsReplyFor

    client: relax reply checks, remove IsReply and IsReplyFor

    RFC 826 doesn't say that we should check the target hardware address or target protocol address when processing replies. Instead, replies should be considered unconditionally.

    RFC 5227 (page 16) goes a step further, and explicitly calls out broken implementations that make such checks.

    Furthermore, ARP replies can be broadcasts.

    This removes IsReply and IsReplyFor, as they'd become trivial.

  • migrate from net.IP to netip.Addr

    migrate from net.IP to netip.Addr

    This PR removes all use of net.IP in favor of the (smaller, faster, immutable) netip.Addr. net is still needed for the hardware address datastructures, but this will allow the results of the package to be used in maps and will permit other conveniences (like reasonable equality testing).

  • WriteTo doesn't respect destination hardware address

    WriteTo doesn't respect destination hardware address

    I need to send broadcast ARP requests to devices that only respond when the ARP target MAC address is set to 00:00:00:00:00:00. The Ethernet frame destination MAC address still needs to be FF:FF:FF:FF:FF:FF, though. I would have expected to be able to accomplish this by using distinct MAC addresses when calling NewPacket and when calling WriteTo. However, it turns out that WriteTo reuses the packet-internal target address (p.TargetHardwareAddr) when setting the Ethernet destination address, rather than using the addr parameter. https://github.com/mdlayher/arp/blob/98a83c8a27177c5179d02d41ad50b0cce8e59338/client.go#L151-L162 Is there a reason for this, or is it a bug?

  • Indirect dependency library `golang.org/x/textv0.3.0` has a security issue

    Indirect dependency library `golang.org/x/textv0.3.0` has a security issue

    Indirect dependency golang.org/x/textv0.3.0 has a security issue, please found this dependency library at: https://github.com/mdlayher/arp/blob/master/go.sum#L13
    CVE link: https://nvd.nist.gov/vuln/detail/CVE-2020-14040
    Could you consider to upgrade this library to version v0.3.7?

  • Suggestion: provide a New...() for mock/fake client

    Suggestion: provide a New...() for mock/fake client

    Hey @mdlayher, thanks for this package and the others you've provided. They've been very helpful.

    I want to be able to unit test code that is using arp.Client and see the packets that I'm sending by providing a mock PacketConn. The code in client_test.go is pretty close to what I want to do, but users of this package cannot set the PacketConn on the client without using New(), which requires a net.Interface. I believe creating a net.Interface for my tests would require NET_ADMIN capabilities.

    I could mock out the Client as an interface, but then I cannot see the packets that go on the wire.

    Is it possible that another New...() function could be created that allows you to set the net.IP, net.HardwareAddr and net.PacketConn directly for use in testing?

    This might require adjustments to the Client struct. I believe you only use the net.Interface to get Addrs() during initialization and for getting the HardwareAddr during various functions.

    My suggestion would look something like this and I can submit a PR if you're willing to accept it :) I'm iffy on the name, love to hear your suggestions if you don't like it.

    type Client struct {
            addr net.HardwareAddr
    	ip  net.IP
    	p   net.PacketConn
    }
    
    func NewForTesting(addr net.HardwareAddr, ip net.IP, p net.PacketConn) *Client { ... }
    
Related tags
Package ethernet implements marshaling and unmarshaling of IEEE 802.3 Ethernet II frames and IEEE 802.1Q VLAN tags. MIT Licensed.

ethernet Package ethernet implements marshaling and unmarshaling of IEEE 802.3 Ethernet II frames and IEEE 802.1Q VLAN tags. MIT Licensed. For more in

Dec 29, 2022
Package raw enables reading and writing data at the device driver level for a network interface. MIT Licensed.

raw Package raw enables reading and writing data at the device driver level for a network interface. MIT Licensed. For more information about using ra

Dec 28, 2022
Package socket provides a low-level network connection type which integrates with Go's runtime network poller to provide asynchronous I/O and deadline support. MIT Licensed.

socket Package socket provides a low-level network connection type which integrates with Go's runtime network poller to provide asynchronous I/O and d

Dec 14, 2022
A go implementation of the STUN client (RFC 3489 and RFC 5389)

go-stun go-stun is a STUN (RFC 3489, 5389) client implementation in golang (a.k.a. UDP hole punching). RFC 3489: STUN - Simple Traversal of User Datag

Jan 5, 2023
CoreRAD is an extensible and observable IPv6 Neighbor Discovery Protocol router advertisement daemon. Apache 2.0 Licensed.
CoreRAD is an extensible and observable IPv6 Neighbor Discovery Protocol router advertisement daemon. Apache 2.0 Licensed.

CoreRAD CoreRAD is an extensible and observable IPv6 Neighbor Discovery Protocol router advertisement daemon. Apache 2.0 Licensed. To get started with

Nov 14, 2022
Diameter stack and Base Protocol (RFC 6733) for the Go programming language

Diameter Base Protocol Package go-diameter is an implementation of the Diameter Base Protocol RFC 6733 and a stack for the Go programming language. St

Dec 28, 2022
Rabbitio - Rabbit stream cipher package RFC 4503 for Go

rabbitio rabbitio is a rabbit stream cipher packge based on RFC 4503 for golang

Dec 14, 2022
Gmqtt is a flexible, high-performance MQTT broker library that fully implements the MQTT protocol V3.1.1 and V5 in golang

中文文档 Gmqtt News: MQTT V5 is now supported. But due to those new features in v5, there area lots of breaking changes. If you have any migration problem

Jan 5, 2023
TritonHTTP - A simple web server that implements a subset of the HTTP/1.1 protocol specification

TritonHTTP Spec Summary Here we provide a concise summary of the TritonHTTP spec. You should read the spec doc for more details and clarifications. HT

Nov 5, 2022
CoAP Client/Server implementing RFC 7252 for the Go Language

Canopus Canopus is a client/server implementation of the Constrained Application Protocol (CoAP) Updates 25.11.2016 I've added basic dTLS Support base

Nov 18, 2022
Fast RFC 5389 STUN implementation in go

STUN Package stun implements Session Traversal Utilities for NAT (STUN) [RFC5389] protocol and client with no external dependencies and zero allocatio

Nov 28, 2022
URI Templates (RFC 6570) implemented in Go

uritemplates -- import "github.com/jtacoma/uritemplates" Package uritemplates is a level 4 implementation of RFC 6570 (URI Template, http://tools.ietf

Jan 15, 2022
Fast RFC 5389 STUN implementation in go

STUN Package stun implements Session Traversal Utilities for NAT (STUN) [RFC5389] protocol and client with no external dependencies and zero allocatio

Jan 1, 2023
RFC 1413 compliant fake identd

RFC 1413 compliant fake identd. It is an implementation of the Ident Protocol, but it lies to the clients and always returns fake identities of queried users.

Oct 29, 2022
wire protocol for multiplexing connections or streams into a single connection, based on a subset of the SSH Connection Protocol

qmux qmux is a wire protocol for multiplexing connections or streams into a single connection. It is based on the SSH Connection Protocol, which is th

Dec 26, 2022
A simple tool to convert socket5 proxy protocol to http proxy protocol

Socket5 to HTTP 这是一个超简单的 Socket5 代理转换成 HTTP 代理的小工具。 如何安装? Golang 用户 # Required Go 1.17+ go install github.com/mritd/s2h@master Docker 用户 docker pull m

Jan 2, 2023
Gcra - Package gcra implements the generic cell rate algorithm

gcra Package gcra implements the generic cell rate algorithm (GCRA). Example opt

Jan 23, 2022
Inspired by go-socks5,This package provides full functionality of socks5 protocol.
Inspired by go-socks5,This package provides full functionality of socks5 protocol.

The protocol described here is designed to provide a framework for client-server applications in both the TCP and UDP domains to conveniently and securely use the services of a network firewall.

Dec 16, 2022