github.com/yggdrasil-network/yggdrasil-go@v0.5.6/src/ipv6rwc/icmpv6.go (about) 1 package ipv6rwc 2 3 // The ICMPv6 module implements functions to easily create ICMPv6 4 // packets. These functions, when mixed with the built-in Go IPv6 5 // and ICMP libraries, can be used to send control messages back 6 // to the host. Examples include: 7 // - NDP messages, when running in TAP mode 8 // - Packet Too Big messages, when packets exceed the session MTU 9 // - Destination Unreachable messages, when a session prohibits 10 // incoming traffic 11 12 import ( 13 "encoding/binary" 14 "net" 15 16 "golang.org/x/net/icmp" 17 "golang.org/x/net/ipv6" 18 ) 19 20 type ICMPv6 struct{} 21 22 // Marshal returns the binary encoding of h. 23 func ipv6Header_Marshal(h *ipv6.Header) ([]byte, error) { 24 b := make([]byte, 40) 25 b[0] |= byte(h.Version) << 4 26 b[0] |= byte(h.TrafficClass) >> 4 27 b[1] |= byte(h.TrafficClass) << 4 28 b[1] |= byte(h.FlowLabel >> 16) 29 b[2] = byte(h.FlowLabel >> 8) 30 b[3] = byte(h.FlowLabel) 31 binary.BigEndian.PutUint16(b[4:6], uint16(h.PayloadLen)) 32 b[6] = byte(h.NextHeader) 33 b[7] = byte(h.HopLimit) 34 copy(b[8:24], h.Src) 35 copy(b[24:40], h.Dst) 36 return b, nil 37 } 38 39 // Creates an ICMPv6 packet based on the given icmp.MessageBody and other 40 // parameters, complete with IP headers only, which can be written directly to 41 // a TUN adapter, or called directly by the CreateICMPv6L2 function when 42 // generating a message for TAP adapters. 43 func CreateICMPv6(dst net.IP, src net.IP, mtype ipv6.ICMPType, mcode int, mbody icmp.MessageBody) ([]byte, error) { 44 // Create the ICMPv6 message 45 icmpMessage := icmp.Message{ 46 Type: mtype, 47 Code: mcode, 48 Body: mbody, 49 } 50 51 // Convert the ICMPv6 message into []byte 52 icmpMessageBuf, err := icmpMessage.Marshal(icmp.IPv6PseudoHeader(src, dst)) 53 if err != nil { 54 return nil, err 55 } 56 57 // Create the IPv6 header 58 ipv6Header := ipv6.Header{ 59 Version: ipv6.Version, 60 NextHeader: 58, 61 PayloadLen: len(icmpMessageBuf), 62 HopLimit: 255, 63 Src: src, 64 Dst: dst, 65 } 66 67 // Convert the IPv6 header into []byte 68 ipv6HeaderBuf, err := ipv6Header_Marshal(&ipv6Header) 69 if err != nil { 70 return nil, err 71 } 72 73 // Construct the packet 74 responsePacket := make([]byte, ipv6.HeaderLen+ipv6Header.PayloadLen) 75 copy(responsePacket[:ipv6.HeaderLen], ipv6HeaderBuf) 76 copy(responsePacket[ipv6.HeaderLen:], icmpMessageBuf) 77 78 // Send it back 79 return responsePacket, nil 80 }