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  }