mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 03:05:07 +03:00 
			
		
		
		
	Merge pull request #14 from neilalexander/icmpv6
Replace ndp.go with icmpv6.go
This commit is contained in:
		
						commit
						a3a9696880
					
				
					 3 changed files with 245 additions and 180 deletions
				
			
		
							
								
								
									
										226
									
								
								src/yggdrasil/icmpv6.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										226
									
								
								src/yggdrasil/icmpv6.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,226 @@
 | 
				
			||||||
 | 
					package yggdrasil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The NDP functions are needed when you are running with a
 | 
				
			||||||
 | 
					// TAP adapter - as the operating system expects neighbor solicitations
 | 
				
			||||||
 | 
					// for on-link traffic, this goroutine provides them
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "net"
 | 
				
			||||||
 | 
					import "golang.org/x/net/ipv6"
 | 
				
			||||||
 | 
					import "golang.org/x/net/icmp"
 | 
				
			||||||
 | 
					import "encoding/binary"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type macAddress [6]byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ETHER = 14
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type icmpv6 struct {
 | 
				
			||||||
 | 
						tun        *tunDevice
 | 
				
			||||||
 | 
						peermac    macAddress
 | 
				
			||||||
 | 
						peerlladdr net.IP
 | 
				
			||||||
 | 
						mylladdr   net.IP
 | 
				
			||||||
 | 
						mymac      macAddress
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Marshal returns the binary encoding of h.
 | 
				
			||||||
 | 
					func ipv6Header_Marshal(h *ipv6.Header) ([]byte, error) {
 | 
				
			||||||
 | 
						b := make([]byte, 40)
 | 
				
			||||||
 | 
						b[0] |= byte(h.Version) << 4
 | 
				
			||||||
 | 
						b[0] |= byte(h.TrafficClass) >> 4
 | 
				
			||||||
 | 
						b[1] |= byte(h.TrafficClass) << 4
 | 
				
			||||||
 | 
						b[1] |= byte(h.FlowLabel >> 16)
 | 
				
			||||||
 | 
						b[2] = byte(h.FlowLabel >> 8)
 | 
				
			||||||
 | 
						b[3] = byte(h.FlowLabel)
 | 
				
			||||||
 | 
						binary.BigEndian.PutUint16(b[4:6], uint16(h.PayloadLen))
 | 
				
			||||||
 | 
						b[6] = byte(h.NextHeader)
 | 
				
			||||||
 | 
						b[7] = byte(h.HopLimit)
 | 
				
			||||||
 | 
						copy(b[8:24], h.Src)
 | 
				
			||||||
 | 
						copy(b[24:40], h.Dst)
 | 
				
			||||||
 | 
						return b, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (i *icmpv6) init(t *tunDevice) {
 | 
				
			||||||
 | 
						i.tun = t
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Our MAC address and link-local address
 | 
				
			||||||
 | 
						copy(i.mymac[:], []byte{
 | 
				
			||||||
 | 
							0x02, 0x00, 0x00, 0x00, 0x00, 0x02})
 | 
				
			||||||
 | 
						i.mylladdr = net.IP{
 | 
				
			||||||
 | 
							0xFE, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
				
			||||||
 | 
							0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFE}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (i *icmpv6) parse_packet(datain []byte) {
 | 
				
			||||||
 | 
						var response []byte
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Parse the frame/packet
 | 
				
			||||||
 | 
						if i.tun.iface.IsTAP() {
 | 
				
			||||||
 | 
							response, err = i.parse_packet_tap(datain)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							response, err = i.parse_packet_tun(datain)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Write the packet to TUN/TAP
 | 
				
			||||||
 | 
						i.tun.iface.Write(response)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (i *icmpv6) parse_packet_tap(datain []byte) ([]byte, error) {
 | 
				
			||||||
 | 
						// Store the peer MAC address
 | 
				
			||||||
 | 
						copy(i.peermac[:6], datain[6:12])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Ignore non-IPv6 frames
 | 
				
			||||||
 | 
						if binary.BigEndian.Uint16(datain[12:14]) != uint16(0x86DD) {
 | 
				
			||||||
 | 
							return nil, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Hand over to parse_packet_tun to interpret the IPv6 packet
 | 
				
			||||||
 | 
						ipv6packet, err := i.parse_packet_tun(datain[ETHER:])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create the response buffer
 | 
				
			||||||
 | 
						dataout := make([]byte, ETHER+ipv6.HeaderLen+32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Populate the response ethernet headers
 | 
				
			||||||
 | 
						copy(dataout[:6], datain[6:12])
 | 
				
			||||||
 | 
						copy(dataout[6:12], i.mymac[:])
 | 
				
			||||||
 | 
						binary.BigEndian.PutUint16(dataout[12:14], uint16(0x86DD))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Copy the returned packet to our response ethernet frame
 | 
				
			||||||
 | 
						copy(dataout[ETHER:], ipv6packet)
 | 
				
			||||||
 | 
						return dataout, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (i *icmpv6) parse_packet_tun(datain []byte) ([]byte, error) {
 | 
				
			||||||
 | 
						// Parse the IPv6 packet headers
 | 
				
			||||||
 | 
						ipv6Header, err := ipv6.ParseHeader(datain[:ipv6.HeaderLen])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check if the packet is IPv6
 | 
				
			||||||
 | 
						if ipv6Header.Version != ipv6.Version {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check if the packet is ICMPv6
 | 
				
			||||||
 | 
						if ipv6Header.NextHeader != 58 {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Store the peer link local address, it will come in useful later
 | 
				
			||||||
 | 
						copy(i.peerlladdr[:], ipv6Header.Src[:])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Parse the ICMPv6 message contents
 | 
				
			||||||
 | 
						icmpv6Header, err := icmp.ParseMessage(58, datain[ipv6.HeaderLen:])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check for a supported message type
 | 
				
			||||||
 | 
						switch icmpv6Header.Type {
 | 
				
			||||||
 | 
						case ipv6.ICMPTypeNeighborSolicitation:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								response, err := i.handle_ndp(datain[ipv6.HeaderLen:])
 | 
				
			||||||
 | 
								if err == nil {
 | 
				
			||||||
 | 
									// Create our ICMPv6 response
 | 
				
			||||||
 | 
									responsePacket, err := i.create_icmpv6_tun(ipv6Header.Src, ipv6.ICMPTypeNeighborAdvertisement, 0, response)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										return nil, err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Fix the checksum because I don't even know why, net/icmp is stupid
 | 
				
			||||||
 | 
									responsePacket[17] ^= 0x4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									// Send it back
 | 
				
			||||||
 | 
									return responsePacket, nil
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (i *icmpv6) create_icmpv6_tap(dstmac macAddress, dst net.IP, mtype ipv6.ICMPType, mcode int, mbody []byte) ([]byte, error) {
 | 
				
			||||||
 | 
						// Pass through to create_icmpv6_tun
 | 
				
			||||||
 | 
						ipv6packet, err := i.create_icmpv6_tun(dst, mtype, mcode, mbody)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create the response buffer
 | 
				
			||||||
 | 
						dataout := make([]byte, ETHER+ipv6.HeaderLen+len(mbody))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Populate the response ethernet headers
 | 
				
			||||||
 | 
						copy(dataout[:6], dstmac[:6])
 | 
				
			||||||
 | 
						copy(dataout[6:12], i.mymac[:])
 | 
				
			||||||
 | 
						binary.BigEndian.PutUint16(dataout[12:14], uint16(0x86DD))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Copy the returned packet to our response ethernet frame
 | 
				
			||||||
 | 
						copy(dataout[ETHER:], ipv6packet)
 | 
				
			||||||
 | 
						return dataout, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (i *icmpv6) create_icmpv6_tun(dst net.IP, mtype ipv6.ICMPType, mcode int, mbody []byte) ([]byte, error) {
 | 
				
			||||||
 | 
						// Create the IPv6 header
 | 
				
			||||||
 | 
						ipv6Header := ipv6.Header{
 | 
				
			||||||
 | 
							Version:    ipv6.Version,
 | 
				
			||||||
 | 
							NextHeader: 58,
 | 
				
			||||||
 | 
							PayloadLen: len(mbody),
 | 
				
			||||||
 | 
							HopLimit:   255,
 | 
				
			||||||
 | 
							Src:        i.mylladdr,
 | 
				
			||||||
 | 
							Dst:        dst,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create the ICMPv6 message
 | 
				
			||||||
 | 
						icmpMessage := icmp.Message{
 | 
				
			||||||
 | 
							Type: mtype,
 | 
				
			||||||
 | 
							Code: mcode,
 | 
				
			||||||
 | 
							Body: &icmp.DefaultMessageBody{Data: mbody},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Convert the IPv6 header into []byte
 | 
				
			||||||
 | 
						ipv6HeaderBuf, err := ipv6Header_Marshal(&ipv6Header)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Convert the ICMPv6 message into []byte
 | 
				
			||||||
 | 
						icmpMessageBuf, err := icmpMessage.Marshal(icmp.IPv6PseudoHeader(ipv6Header.Dst, ipv6Header.Src))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Construct the packet
 | 
				
			||||||
 | 
						responsePacket := make([]byte, ipv6.HeaderLen+ipv6Header.PayloadLen)
 | 
				
			||||||
 | 
						copy(responsePacket[:ipv6.HeaderLen], ipv6HeaderBuf)
 | 
				
			||||||
 | 
						copy(responsePacket[ipv6.HeaderLen:], icmpMessageBuf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Send it back
 | 
				
			||||||
 | 
						return responsePacket, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (i *icmpv6) handle_ndp(in []byte) ([]byte, error) {
 | 
				
			||||||
 | 
						// Ignore NDP requests for anything outside of fd00::/8
 | 
				
			||||||
 | 
						if in[8] != 0xFD {
 | 
				
			||||||
 | 
							return nil, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create our NDP message body response
 | 
				
			||||||
 | 
						body := make([]byte, 32)
 | 
				
			||||||
 | 
						binary.BigEndian.PutUint32(body[:4], uint32(0x20000000))
 | 
				
			||||||
 | 
						copy(body[4:20], in[8:24]) // Target address
 | 
				
			||||||
 | 
						body[20] = uint8(2)
 | 
				
			||||||
 | 
						body[21] = uint8(1)
 | 
				
			||||||
 | 
						copy(body[22:28], i.mymac[:6])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Send it back
 | 
				
			||||||
 | 
						return body, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,165 +0,0 @@
 | 
				
			||||||
package yggdrasil
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// The NDP functions are needed when you are running with a
 | 
					 | 
				
			||||||
// TAP adapter - as the operating system expects neighbor solicitations
 | 
					 | 
				
			||||||
// for on-link traffic, this goroutine provides them
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import "golang.org/x/net/icmp"
 | 
					 | 
				
			||||||
import "encoding/binary"
 | 
					 | 
				
			||||||
import "unsafe" // TODO investigate if this can be done without resorting to unsafe
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type macAddress [6]byte
 | 
					 | 
				
			||||||
type ipv6Address [16]byte
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const ETHER = 14
 | 
					 | 
				
			||||||
const IPV6 = 40
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ndp struct {
 | 
					 | 
				
			||||||
	tun        *tunDevice
 | 
					 | 
				
			||||||
	peermac    macAddress
 | 
					 | 
				
			||||||
	peerlladdr ipv6Address
 | 
					 | 
				
			||||||
	mymac      macAddress
 | 
					 | 
				
			||||||
	mylladdr   ipv6Address
 | 
					 | 
				
			||||||
	recv       chan []byte
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type etherHeader struct {
 | 
					 | 
				
			||||||
	destination macAddress
 | 
					 | 
				
			||||||
	source      macAddress
 | 
					 | 
				
			||||||
	ethertype   [2]byte
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ipv6Header struct {
 | 
					 | 
				
			||||||
	preamble    [4]byte
 | 
					 | 
				
			||||||
	length      [2]byte
 | 
					 | 
				
			||||||
	nextheader  byte
 | 
					 | 
				
			||||||
	hoplimit    byte
 | 
					 | 
				
			||||||
	source      ipv6Address
 | 
					 | 
				
			||||||
	destination ipv6Address
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type icmpv6Header struct {
 | 
					 | 
				
			||||||
	messagetype byte
 | 
					 | 
				
			||||||
	code        byte
 | 
					 | 
				
			||||||
	checksum    uint16
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type icmpv6PseudoHeader struct {
 | 
					 | 
				
			||||||
	source      ipv6Address
 | 
					 | 
				
			||||||
	destination ipv6Address
 | 
					 | 
				
			||||||
	length      [4]byte
 | 
					 | 
				
			||||||
	zero        [3]byte
 | 
					 | 
				
			||||||
	nextheader  byte
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type icmpv6Packet struct {
 | 
					 | 
				
			||||||
	ether            etherHeader
 | 
					 | 
				
			||||||
	ipv6             ipv6Header
 | 
					 | 
				
			||||||
	icmpv6           icmpv6Header
 | 
					 | 
				
			||||||
	flags            [4]byte
 | 
					 | 
				
			||||||
	targetaddress    ipv6Address
 | 
					 | 
				
			||||||
	optiontype       byte
 | 
					 | 
				
			||||||
	optionlength     byte
 | 
					 | 
				
			||||||
	linklayeraddress macAddress
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (n *ndp) init(t *tunDevice) {
 | 
					 | 
				
			||||||
	n.tun = t
 | 
					 | 
				
			||||||
	n.recv = make(chan []byte)
 | 
					 | 
				
			||||||
	copy(n.mymac[:], []byte{0x02, 0x00, 0x00, 0x00, 0x00, 0x02})
 | 
					 | 
				
			||||||
	copy(n.mylladdr[:], []byte{
 | 
					 | 
				
			||||||
		0xFE, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
					 | 
				
			||||||
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFE})
 | 
					 | 
				
			||||||
	go n.listen()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (n *ndp) listen() {
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		// Receive from the channel and check if we're using TAP instead
 | 
					 | 
				
			||||||
		// of TUN mode - NDP is only relevant for TAP
 | 
					 | 
				
			||||||
		datain := <-n.recv
 | 
					 | 
				
			||||||
		if !n.tun.iface.IsTAP() {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Create our return frame buffer and also the unsafe pointers to
 | 
					 | 
				
			||||||
		// map them to the structs
 | 
					 | 
				
			||||||
		dataout := make([]byte, ETHER+IPV6+32)
 | 
					 | 
				
			||||||
		in := (*icmpv6Packet)(unsafe.Pointer(&datain[0]))
 | 
					 | 
				
			||||||
		out := (*icmpv6Packet)(unsafe.Pointer(&dataout[0]))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Store peer MAC address and link-local IP address -
 | 
					 | 
				
			||||||
		// these will be used later by tun.go
 | 
					 | 
				
			||||||
		copy(n.peermac[:6], in.ether.source[:6])
 | 
					 | 
				
			||||||
		copy(n.peerlladdr[:16], in.ipv6.source[:16])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Ignore non-IPv6 packets
 | 
					 | 
				
			||||||
		if binary.BigEndian.Uint16(in.ether.ethertype[:]) != uint16(0x86DD) {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Ignore non-ICMPv6 packets
 | 
					 | 
				
			||||||
		if in.ipv6.nextheader != uint8(0x3A) {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Ignore non-NDP Solicitation packets
 | 
					 | 
				
			||||||
		if in.icmpv6.messagetype != uint8(135) {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Ignore NDP requests for anything outside of fd00::/8
 | 
					 | 
				
			||||||
		if in.targetaddress[0] != 0xFD {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Populate the out ethernet headers
 | 
					 | 
				
			||||||
		copy(out.ether.destination[:], in.ether.destination[:])
 | 
					 | 
				
			||||||
		copy(out.ether.source[:], n.mymac[:])
 | 
					 | 
				
			||||||
		binary.BigEndian.PutUint16(out.ether.ethertype[:], uint16(0x86DD))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// And for now just copy the rest of the packet we were sent
 | 
					 | 
				
			||||||
		copy(dataout[ETHER:ETHER+IPV6], datain[ETHER:ETHER+IPV6])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Update the source and destination addresses in the IPv6 header
 | 
					 | 
				
			||||||
		copy(out.ipv6.destination[:], in.ipv6.source[:])
 | 
					 | 
				
			||||||
		copy(out.ipv6.source[:], n.mylladdr[:])
 | 
					 | 
				
			||||||
		binary.BigEndian.PutUint16(out.ipv6.length[:], uint16(32))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Copy the payload
 | 
					 | 
				
			||||||
		copy(dataout[ETHER+IPV6:], datain[ETHER+IPV6:])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Update the ICMPv6 headers
 | 
					 | 
				
			||||||
		out.icmpv6.messagetype = uint8(136)
 | 
					 | 
				
			||||||
		out.icmpv6.code = uint8(0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Update the ICMPv6 payload
 | 
					 | 
				
			||||||
		copy(out.targetaddress[:], in.targetaddress[:])
 | 
					 | 
				
			||||||
		out.optiontype = uint8(2)
 | 
					 | 
				
			||||||
		out.optionlength = uint8(1)
 | 
					 | 
				
			||||||
		copy(out.linklayeraddress[:], n.mymac[:])
 | 
					 | 
				
			||||||
		binary.BigEndian.PutUint32(out.flags[:], uint32(0x20000000))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Generate the pseudo-header for the checksum
 | 
					 | 
				
			||||||
		ps := make([]byte, 44)
 | 
					 | 
				
			||||||
		pseudo := (*icmpv6PseudoHeader)(unsafe.Pointer(&ps[0]))
 | 
					 | 
				
			||||||
		copy(pseudo.destination[:], out.ipv6.destination[:])
 | 
					 | 
				
			||||||
		copy(pseudo.source[:], out.ipv6.source[:])
 | 
					 | 
				
			||||||
		binary.BigEndian.PutUint32(pseudo.length[:], uint32(binary.BigEndian.Uint16(out.ipv6.length[:])))
 | 
					 | 
				
			||||||
		pseudo.nextheader = out.ipv6.nextheader
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Lazy-man's checksum using the icmp library
 | 
					 | 
				
			||||||
		icmpv6, err := icmp.ParseMessage(0x3A, dataout[ETHER+IPV6:])
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		payload, err := icmpv6.Marshal(ps)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		copy(dataout[ETHER+IPV6:], payload)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Send the frame back to the TAP adapter
 | 
					 | 
				
			||||||
		n.tun.iface.Write(dataout)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,7 @@ type tunInterface interface {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type tunDevice struct {
 | 
					type tunDevice struct {
 | 
				
			||||||
	core   *Core
 | 
						core   *Core
 | 
				
			||||||
	ndp   ndp
 | 
						icmpv6 icmpv6
 | 
				
			||||||
	send   chan<- []byte
 | 
						send   chan<- []byte
 | 
				
			||||||
	recv   <-chan []byte
 | 
						recv   <-chan []byte
 | 
				
			||||||
	mtu    int
 | 
						mtu    int
 | 
				
			||||||
| 
						 | 
					@ -27,7 +27,7 @@ type tunDevice struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (tun *tunDevice) init(core *Core) {
 | 
					func (tun *tunDevice) init(core *Core) {
 | 
				
			||||||
	tun.core = core
 | 
						tun.core = core
 | 
				
			||||||
	tun.ndp.init(tun)
 | 
						tun.icmpv6.init(tun)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (tun *tunDevice) write() error {
 | 
					func (tun *tunDevice) write() error {
 | 
				
			||||||
| 
						 | 
					@ -36,8 +36,8 @@ func (tun *tunDevice) write() error {
 | 
				
			||||||
		if tun.iface.IsTAP() {
 | 
							if tun.iface.IsTAP() {
 | 
				
			||||||
			var frame ethernet.Frame
 | 
								var frame ethernet.Frame
 | 
				
			||||||
			frame.Prepare(
 | 
								frame.Prepare(
 | 
				
			||||||
				tun.ndp.peermac[:6], // Destination MAC address
 | 
									tun.icmpv6.peermac[:6], // Destination MAC address
 | 
				
			||||||
				tun.ndp.mymac[:6],   // Source MAC address
 | 
									tun.icmpv6.mymac[:6],   // Source MAC address
 | 
				
			||||||
				ethernet.NotTagged,     // VLAN tagging
 | 
									ethernet.NotTagged,     // VLAN tagging
 | 
				
			||||||
				ethernet.IPv6,          // Ethertype
 | 
									ethernet.IPv6,          // Ethertype
 | 
				
			||||||
				len(data))              // Payload length
 | 
									len(data))              // Payload length
 | 
				
			||||||
| 
						 | 
					@ -68,9 +68,6 @@ func (tun *tunDevice) read() error {
 | 
				
			||||||
		o := 0
 | 
							o := 0
 | 
				
			||||||
		if tun.iface.IsTAP() {
 | 
							if tun.iface.IsTAP() {
 | 
				
			||||||
			o = ETHER_HEADER_LENGTH
 | 
								o = ETHER_HEADER_LENGTH
 | 
				
			||||||
			b := make([]byte, n)
 | 
					 | 
				
			||||||
			copy(b, buf)
 | 
					 | 
				
			||||||
			tun.ndp.recv <- b
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if buf[o]&0xf0 != 0x60 ||
 | 
							if buf[o]&0xf0 != 0x60 ||
 | 
				
			||||||
			n != 256*int(buf[o+4])+int(buf[o+5])+IPv6_HEADER_LENGTH+o {
 | 
								n != 256*int(buf[o+4])+int(buf[o+5])+IPv6_HEADER_LENGTH+o {
 | 
				
			||||||
| 
						 | 
					@ -78,6 +75,13 @@ func (tun *tunDevice) read() error {
 | 
				
			||||||
			//panic("Should not happen in testing")
 | 
								//panic("Should not happen in testing")
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if buf[o+6] == 58 {
 | 
				
			||||||
 | 
								// Found an ICMPv6 packet
 | 
				
			||||||
 | 
								b := make([]byte, n)
 | 
				
			||||||
 | 
								copy(b, buf)
 | 
				
			||||||
 | 
								// tun.icmpv6.recv <- b
 | 
				
			||||||
 | 
								go tun.icmpv6.parse_packet(b)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		packet := append(util_getBytes(), buf[o:n]...)
 | 
							packet := append(util_getBytes(), buf[o:n]...)
 | 
				
			||||||
		tun.send <- packet
 | 
							tun.send <- packet
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue