mirror of
https://github.com/coredhcp/coredhcp.git
synced 2025-10-09 06:11:04 +02:00
server/dhcpv4: Send unicast responses to peers with no IP (#123)
When the broadcast bit isn't set in the request, send responses to the L3 address we're assigning, using the peer L2 address, as that's the preferred behavior according to the RFC Signed-off-by: Daniel Zainzinger <dza1@mailbox.org> Co-authored-by: Daniel Zainzinger <dza1@mailbox.org>
This commit is contained in:
parent
00cc6002b6
commit
15f169d55b
1
go.mod
1
go.mod
@ -4,6 +4,7 @@ go 1.13
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/chappjc/logrus-prefix v0.0.0-20180227015900-3a1d64819adb
|
github.com/chappjc/logrus-prefix v0.0.0-20180227015900-3a1d64819adb
|
||||||
|
github.com/google/gopacket v1.1.19
|
||||||
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 // indirect
|
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 // indirect
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20210120172423-cc9239ac6294
|
github.com/insomniacslk/dhcp v0.0.0-20210120172423-cc9239ac6294
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
|
||||||
|
7
go.sum
7
go.sum
@ -74,6 +74,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
|||||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||||
|
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
@ -281,6 +283,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
||||||
@ -300,11 +303,13 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
|
|||||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
golang.org/x/mod v0.1.0 h1:sfUMP1Gu8qASkorDVjnMuvgJzwFbTZSeXFiGBYAVdl4=
|
golang.org/x/mod v0.1.0 h1:sfUMP1Gu8qASkorDVjnMuvgJzwFbTZSeXFiGBYAVdl4=
|
||||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -410,7 +415,9 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn
|
|||||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
|
@ -108,7 +108,7 @@ func (l *listener4) HandleMsg4(buf []byte, oob *ipv4.ControlMessage, _peer net.A
|
|||||||
req, err := dhcpv4.FromBytes(buf)
|
req, err := dhcpv4.FromBytes(buf)
|
||||||
bufpool.Put(&buf)
|
bufpool.Put(&buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error parsing DHCPv6 request: %v", err)
|
log.Printf("Error parsing DHCPv4 request: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,6 +140,7 @@ func (l *listener4) HandleMsg4(buf []byte, oob *ipv4.ControlMessage, _peer net.A
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
|
useEthernet := false
|
||||||
var peer *net.UDPAddr
|
var peer *net.UDPAddr
|
||||||
if !req.GatewayIPAddr.IsUnspecified() {
|
if !req.GatewayIPAddr.IsUnspecified() {
|
||||||
// TODO: make RFC8357 compliant
|
// TODO: make RFC8357 compliant
|
||||||
@ -151,19 +152,14 @@ func (l *listener4) HandleMsg4(buf []byte, oob *ipv4.ControlMessage, _peer net.A
|
|||||||
} else if req.IsBroadcast() {
|
} else if req.IsBroadcast() {
|
||||||
peer = &net.UDPAddr{IP: net.IPv4bcast, Port: dhcpv4.ClientPort}
|
peer = &net.UDPAddr{IP: net.IPv4bcast, Port: dhcpv4.ClientPort}
|
||||||
} else {
|
} else {
|
||||||
// FIXME: we're supposed to unicast to a specific *L2* address, and an L3
|
//sends a layer2 frame so that we can define the destination MAC address
|
||||||
// address that's not yet assigned.
|
peer = &net.UDPAddr{IP: resp.YourIPAddr, Port: dhcpv4.ClientPort}
|
||||||
// I don't know how to do that with this API...
|
useEthernet = true
|
||||||
//peer = &net.UDPAddr{IP: resp.YourIPAddr, Port: dhcpv4.ClientPort}
|
|
||||||
log.Warn("Cannot handle non-broadcast-capable unspecified peers in an RFC-compliant way. " +
|
|
||||||
"Response will be broadcast")
|
|
||||||
|
|
||||||
peer = &net.UDPAddr{IP: net.IPv4bcast, Port: dhcpv4.ClientPort}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var woob *ipv4.ControlMessage
|
var woob *ipv4.ControlMessage
|
||||||
if peer.IP.Equal(net.IPv4bcast) || peer.IP.IsLinkLocalUnicast() {
|
if peer.IP.Equal(net.IPv4bcast) || peer.IP.IsLinkLocalUnicast() || useEthernet {
|
||||||
// Direct broadcasts and link-local to the interface the request was
|
// Direct broadcasts, link-local and layer2 unicasts to the interface the request was
|
||||||
// received on. Other packets should use the normal routing table in
|
// received on. Other packets should use the normal routing table in
|
||||||
// case of asymetric routing
|
// case of asymetric routing
|
||||||
switch {
|
switch {
|
||||||
@ -175,10 +171,22 @@ func (l *listener4) HandleMsg4(buf []byte, oob *ipv4.ControlMessage, _peer net.A
|
|||||||
log.Errorf("HandleMsg4: Did not receive interface information")
|
log.Errorf("HandleMsg4: Did not receive interface information")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, err := l.WriteTo(resp.ToBytes(), woob, peer); err != nil {
|
|
||||||
log.Printf("MainHandler4: conn.Write to %v failed: %v", peer, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if useEthernet {
|
||||||
|
intf, err := net.InterfaceByIndex(woob.IfIndex)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("MainHandler4: Can not get Interface for index %d %v", woob.IfIndex, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = sendEthernet(*intf, resp)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("MainHandler4: Cannot send Ethernet packet: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if _, err := l.WriteTo(resp.ToBytes(), woob, peer); err != nil {
|
||||||
|
log.Errorf("MainHandler4: conn.Write to %v failed: %v", peer, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Print("MainHandler4: dropping request because response is nil")
|
log.Print("MainHandler4: dropping request because response is nil")
|
||||||
}
|
}
|
||||||
|
96
server/sendEthernet.go
Normal file
96
server/sendEthernet.go
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// Copyright 2018-present the CoreDHCP Authors. All rights reserved
|
||||||
|
// This source code is licensed under the MIT license found in the
|
||||||
|
// LICENSE file in the root directory of this source tree.
|
||||||
|
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
"github.com/google/gopacket/layers"
|
||||||
|
"github.com/insomniacslk/dhcp/dhcpv4"
|
||||||
|
)
|
||||||
|
|
||||||
|
//this function sends an unicast to the hardware address defined in resp.ClientHWAddr,
|
||||||
|
//the layer3 destination address is still the broadcast address;
|
||||||
|
//iface: the interface where the DHCP message should be sent;
|
||||||
|
//resp: DHCPv4 struct, which should be sent;
|
||||||
|
func sendEthernet(iface net.Interface, resp *dhcpv4.DHCPv4) error {
|
||||||
|
|
||||||
|
eth := layers.Ethernet{
|
||||||
|
EthernetType: layers.EthernetTypeIPv4,
|
||||||
|
SrcMAC: iface.HardwareAddr,
|
||||||
|
DstMAC: resp.ClientHWAddr,
|
||||||
|
}
|
||||||
|
ip := layers.IPv4{
|
||||||
|
Version: 4,
|
||||||
|
TTL: 64,
|
||||||
|
SrcIP: resp.ServerIPAddr,
|
||||||
|
DstIP: resp.YourIPAddr,
|
||||||
|
Protocol: layers.IPProtocolUDP,
|
||||||
|
Flags: layers.IPv4DontFragment,
|
||||||
|
}
|
||||||
|
udp := layers.UDP{
|
||||||
|
SrcPort: dhcpv4.ServerPort,
|
||||||
|
DstPort: dhcpv4.ClientPort,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := udp.SetNetworkLayerForChecksum(&ip)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Send Ethernet: Couldn't set network layer: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := gopacket.NewSerializeBuffer()
|
||||||
|
opts := gopacket.SerializeOptions{
|
||||||
|
ComputeChecksums: true,
|
||||||
|
FixLengths: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode a packet
|
||||||
|
packet := gopacket.NewPacket(resp.ToBytes(), layers.LayerTypeDHCPv4, gopacket.NoCopy)
|
||||||
|
dhcpLayer := packet.Layer(layers.LayerTypeDHCPv4)
|
||||||
|
dhcp, ok := dhcpLayer.(gopacket.SerializableLayer)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Layer %s is not serializable", dhcpLayer.LayerType().String())
|
||||||
|
}
|
||||||
|
err = gopacket.SerializeLayers(buf, opts, ð, &ip, &udp, dhcp)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Cannot serialize layer: %v", err)
|
||||||
|
}
|
||||||
|
data := buf.Bytes()
|
||||||
|
|
||||||
|
fd, err := syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, 0)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Send Ethernet: Cannot open socket: %v", err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
err = syscall.Close(fd)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Send Ethernet: Cannot close socket: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Send Ethernet: Cannot set option for socket: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var hwAddr [8]byte
|
||||||
|
copy(hwAddr[0:6], resp.ClientHWAddr[0:6])
|
||||||
|
ethAddr := syscall.SockaddrLinklayer{
|
||||||
|
Protocol: 0,
|
||||||
|
Ifindex: iface.Index,
|
||||||
|
Halen: 6,
|
||||||
|
Addr: hwAddr, //not used
|
||||||
|
}
|
||||||
|
err = syscall.Sendto(fd, data, 0, ðAddr)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Cannot send frame via socket: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user