github.com/20yyq/packet@v0.1.4-0.20231013092308-386a004a3baa/ethernet.go (about) 1 // @@ 2 // @ Author : Eacher 3 // @ Date : 2023-07-13 14:02:39 4 // @ LastEditTime : 2023-09-15 10:32:23 5 // @ LastEditors : Eacher 6 // @ --------------------------------------------------------------------------------< 7 // @ Description : 8 // @ --------------------------------------------------------------------------------< 9 // @ FilePath : /20yyq/packet/ethernet.go 10 // @@ 11 package packet 12 13 import ( 14 _ "net" 15 "unsafe" 16 "encoding/binary" 17 ) 18 19 const ( 20 SizeofEthernetPacket = 0x0e 21 ) 22 23 type HardwareAddr [6]byte 24 type IPv4 [4]byte 25 26 const hexDigit = "0123456789abcdef" 27 const maxIPv4StringLen = len("255.255.255.255") 28 29 var Broadcast = HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 30 31 /* 32 33 //来源 https://www.rfc-editor.org/rfc/rfc1071 [Page 6] 34 35 4.1 "C" 36 37 in 6 { 38 // Compute Internet Checksum for "count" bytes 39 // beginning at location "addr". 40 // 41 register long sum = 0; 42 43 while( count > 1 ) { 44 // This is the inner loop 45 sum += * (unsigned short) addr++; 46 count -= 2; 47 } 48 // Add left-over byte, if any 49 if( count > 0 ) 50 sum += * (unsigned char *) addr; 51 52 // Fold 32-bit sum to 16 bits 53 while (sum>>16) 54 sum = (sum & 0xffff) + (sum >> 16); 55 checksum = ~sum; 56 } 57 */ 58 59 func CheckSum(b []byte) uint16 { 60 l, i, sum := len(b) - 1, 0, uint64(0) 61 for ; i < l; i += 2 { 62 sum += uint64(*(*uint16)(unsafe.Pointer(&b[i]))) 63 } 64 if i == l { 65 sum += uint64(b[i]) 66 } 67 for sum >> 16 > 0 { 68 sum = (sum & 0b1111111111111111) + (sum >> 16) 69 } 70 return uint16(^sum) 71 } 72 73 //go:linkname ubtoa net.ubtoa 74 func ubtoa([]byte, int, byte) int 75 76 func (h HardwareAddr) String() string { 77 if len(h) == 0 { 78 return "" 79 } 80 buf := make([]byte, 0, len(h)*3-1) 81 for i, b := range h { 82 if i > 0 { 83 buf = append(buf, ':') 84 } 85 buf = append(buf, hexDigit[b>>4]) 86 buf = append(buf, hexDigit[b&0xF]) 87 } 88 return string(buf) 89 } 90 91 func (v4 IPv4) String() string { 92 if len(v4) == 0 { 93 return "" 94 } 95 b := make([]byte, maxIPv4StringLen) 96 97 n := ubtoa(b, 0, v4[0]) 98 b[n] = '.' 99 n++ 100 101 n += ubtoa(b, n, v4[1]) 102 b[n] = '.' 103 n++ 104 105 n += ubtoa(b, n, v4[2]) 106 b[n] = '.' 107 n++ 108 109 n += ubtoa(b, n, v4[3]) 110 return string(b[:n]) 111 } 112 113 /* 114 Ethernet transmission layer (not necessarily accessible to the user): 115 6.byte 48.bit: Ethernet address of destination 116 6.byte 48.bit: Ethernet address of sender 117 2.byte 16.bit: Protocol type = ether_type$ADDRESS_RESOLUTION Ethernet packet data: 118 // N.byte packet 119 */ 120 type EthernetPacket struct { 121 HeadMAC [2]HardwareAddr 122 FrameType uint16 123 } 124 125 func NewEthernetPacket(b [SizeofEthernetPacket]byte) (eth EthernetPacket) { 126 eth = *(*EthernetPacket)(unsafe.Pointer(&b[0])) 127 eth.FrameType = binary.BigEndian.Uint16(b[12:14]) 128 return 129 } 130 131 func (eth EthernetPacket) WireFormat() []byte { 132 var b [SizeofEthernetPacket]byte 133 *(*HardwareAddr)(b[0:6]) = eth.HeadMAC[0] 134 *(*HardwareAddr)(b[6:12]) = eth.HeadMAC[1] 135 binary.BigEndian.PutUint16(b[12:14], eth.FrameType) 136 return b[:] 137 }