add all files from Hong
This commit is contained in:
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
|
||||
}
|
||||
Reference in New Issue
Block a user