Skip to content

Commit 03cb277

Browse files
authored
build: support for !linux builds (#6)
Makes ARP magic optional.
1 parent f6d1736 commit 03cb277

File tree

8 files changed

+118
-32
lines changed

8 files changed

+118
-32
lines changed

.github/workflows/goreleaser.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- name: Set up Go
1717
uses: actions/setup-go@v2
1818
with:
19-
go-version: 1.16.x
19+
go-version: 1.17.x
2020

2121
- name: Run GoReleaser
2222
uses: goreleaser/goreleaser-action@v2

.goreleaser.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,13 @@ builds:
99
- -s -w -X github.com/DSpeichert/netbootd/cmd.version={{.Version}} -X github.com/DSpeichert/netbootd/cmd.commit={{.ShortCommit}} -X github.com/DSpeichert/netbootd/cmd.date={{.Date}}
1010
goos:
1111
- linux
12+
- darwin
1213
goarch:
1314
- amd64
15+
- arm
16+
- arm64
17+
goarm:
18+
- 7
1419

1520
archives:
1621
- wrap_in_directory: true

cmd/arpinject.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package cmd
22

33
import (
4-
"github.com/DSpeichert/netbootd/dhcpd"
4+
"github.com/DSpeichert/netbootd/dhcpd/arp"
55
"github.com/rs/zerolog/log"
66
"github.com/spf13/cobra"
77
"net"
@@ -31,7 +31,7 @@ var arpInjectCmd = &cobra.Command{
3131
Err(err).
3232
Msg("cannot parse mac")
3333
}
34-
if err = dhcpd.InjectArp(parsedIp, parsedMac, dhcpd.ATF_COM, device); err != nil {
34+
if err = arp.InjectArp(parsedIp, parsedMac, arp.ATF_COM, device); err != nil {
3535
log.Error().
3636
Err(err).
3737
Msg("cannot inject arp entry")

dhcpd/arp/arp.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package arp
2+
3+
import (
4+
"syscall"
5+
)
6+
7+
// ARP Flag values
8+
// these are not in golang.org/x/sys/unix
9+
const (
10+
// completed entry (ha valid)
11+
ATF_COM = 0x02
12+
// permanent entry
13+
ATF_PERM = 0x04
14+
// publish entry
15+
ATF_PUBL = 0x08
16+
// has requested trailers
17+
ATF_USETRAILERS = 0x10
18+
// want to use a netmask (only for proxy entries)
19+
ATF_NETMASK = 0x20
20+
// don't answer this addresses
21+
ATF_DONTPUB = 0x40
22+
)
23+
24+
// https://man7.org/linux/man-pages/man7/arp.7.html
25+
type arpReq struct {
26+
ArpPa syscall.RawSockaddrInet4
27+
ArpHa syscall.RawSockaddr
28+
Flags int32
29+
Netmask syscall.RawSockaddr
30+
Dev [16]byte
31+
}

dhcpd/arp/arp_linux.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//go:build linux && !amd64 && !arm64
2+
// +build linux,!amd64,!arm64
3+
4+
package arp
5+
6+
import (
7+
"net"
8+
"os"
9+
"syscall"
10+
"unsafe"
11+
12+
"golang.org/x/sys/unix"
13+
)
14+
15+
// InjectArp injects an ARP entry into dev's ARP table
16+
// syscalls roughly based on https://www.unix.com/302447674-post3.html
17+
// see:
18+
// https://github.com/torvalds/linux/blob/8cf8821e15cd553339a5b48ee555a0439c2b2742/net/ipv4/arp.c#L1179
19+
// https://github.com/torvalds/linux/blob/8cf8821e15cd553339a5b48ee555a0439c2b2742/net/ipv4/arp.c#L1024
20+
func InjectArp(ip net.IP, mac net.HardwareAddr, flags int32, dev string) (err error) {
21+
fd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, unix.IPPROTO_UDP)
22+
if err != nil {
23+
return
24+
}
25+
f := os.NewFile(uintptr(fd), "")
26+
defer f.Close()
27+
28+
return InjectArpFd(uintptr(fd), ip, mac, flags, dev)
29+
}
30+
31+
func InjectArpFd(fd uintptr, ip net.IP, mac net.HardwareAddr, flags int32, dev string) (err error) {
32+
arpReq := arpReq{
33+
ArpPa: syscall.RawSockaddrInet4{
34+
Family: syscall.AF_INET,
35+
},
36+
//Flags: 0x02 | 0x04, // ATF_COM | ATF_PERM;
37+
Flags: flags,
38+
}
39+
copy(arpReq.ArpPa.Addr[:], ip.To4())
40+
copy(arpReq.ArpHa.Data[:], mac)
41+
copy(arpReq.Dev[:], dev)
42+
43+
_, _, errno := unix.Syscall(unix.SYS_IOCTL, fd, unix.SIOCSARP, uintptr(unsafe.Pointer(&arpReq)))
44+
if errno != 0 {
45+
return errno
46+
}
47+
48+
return
49+
}

dhcpd/arp.go renamed to dhcpd/arp/arp_linux_64.go

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,19 @@
1-
package dhcpd
1+
//go:build linux && (amd64 || arm64)
2+
// +build linux
3+
// +build amd64 arm64
4+
5+
package arp
26

37
import (
4-
"golang.org/x/sys/unix"
58
"net"
69
"os"
710
"syscall"
811
"unsafe"
9-
)
1012

11-
// ARP Flag values
12-
// these are not in golang.org/x/sys/unix
13-
const (
14-
// completed entry (ha valid)
15-
ATF_COM = 0x02
16-
// permanent entry
17-
ATF_PERM = 0x04
18-
// publish entry
19-
ATF_PUBL = 0x08
20-
// has requested trailers
21-
ATF_USETRAILERS = 0x10
22-
// want to use a netmask (only for proxy entries)
23-
ATF_NETMASK = 0x20
24-
// don't answer this addresses
25-
ATF_DONTPUB = 0x40
13+
"golang.org/x/sys/unix"
2614
)
2715

28-
// https://man7.org/linux/man-pages/man7/arp.7.html
29-
type arpReq struct {
30-
ArpPa syscall.RawSockaddrInet4
31-
ArpHa syscall.RawSockaddr
32-
Flags int32
33-
Netmask syscall.RawSockaddr
34-
Dev [16]byte
35-
}
36-
16+
// InjectArp injects an ARP entry into dev's ARP table
3717
// syscalls roughly based on https://www.unix.com/302447674-post3.html
3818
// see:
3919
// https://github.com/torvalds/linux/blob/8cf8821e15cd553339a5b48ee555a0439c2b2742/net/ipv4/arp.c#L1179

dhcpd/arp/arp_notlinux.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//go:build !linux
2+
// +build !linux
3+
4+
package arp
5+
6+
import (
7+
"errors"
8+
"net"
9+
)
10+
11+
// InjectArp injects an ARP entry into dev's ARP table
12+
func InjectArp(ip net.IP, mac net.HardwareAddr, flags int32, dev string) (err error) {
13+
return errors.New("not implemented")
14+
}
15+
16+
func InjectArpFd(fd uintptr, ip net.IP, mac net.HardwareAddr, flags int32, dev string) (err error) {
17+
return errors.New("not implemented")
18+
}

dhcpd/handler.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ package dhcpd
55
import (
66
"errors"
77
"net"
8+
"runtime"
89
"strings"
910

11+
"github.com/DSpeichert/netbootd/dhcpd/arp"
1012
mfest "github.com/DSpeichert/netbootd/manifest"
1113
"github.com/insomniacslk/dhcp/dhcpv4"
1214
"golang.org/x/net/ipv4"
@@ -69,6 +71,7 @@ func (server *Server) HandleMsg4(buf []byte, oob *ipv4.ControlMessage, peer net.
6971
if err != nil {
7072
server.logger.Error().
7173
Err(err).
74+
Int("ifIndex", ifIndex).
7275
Msg("failed to find local interface")
7376
resp = nil
7477
goto response
@@ -187,9 +190,9 @@ response:
187190
rawConn, err := server.UdpConn.SyscallConn()
188191
if device != "" && err == nil {
189192
rawConn.Control(func(fd uintptr) {
190-
err = InjectArpFd(fd, resp.YourIPAddr, req.ClientHWAddr, ATF_COM, device)
193+
err = arp.InjectArpFd(fd, resp.YourIPAddr, req.ClientHWAddr, arp.ATF_COM, device)
191194
})
192-
if err != nil {
195+
if err != nil && runtime.GOOS == "linux" {
193196
server.logger.Error().
194197
Err(err).
195198
Msg("ioctl failed")

0 commit comments

Comments
 (0)