code: func (c *IPHAConn) readIPv6Packet() (*packet, error) {
  	b := recvBuffer
  	oob := oobBuffer
  	n, oobn, _, raddr, err := c.recvConn.ReadMsgIP(b, oob)
  	if err != nil {
  		return nil, err
  	}
  	scm, err := syscall.ParseSocketControlMessage(oob[:oobn])
  	if err != nil {
  		return nil, err
  	}
  	var dst net.IP
  	var ttl uint8
  	haveTTL := false
  	for _, sc := range scm {
  		if sc.Header.Level != syscall.IPPROTO_IPV6 {
  			continue
  		}
  		switch sc.Header.Type {
  		case syscall.IPV6_2292HOPLIMIT:
  			if len(sc.Data) == 0 {
  				return nil, fmt.Errorf("IPHAConn.readIPv6Packet: Invalid HOPLIMIT")
  			}
  			ttl = sc.Data[0]
  			haveTTL = true
  		case syscall.IPV6_2292PKTINFO:
  			if len(sc.Data) < 16 {
  				return nil, fmt.Errorf("IPHAConn.readIPv6Packet: Invalid destination address")
  			}
  			dst = net.IP(sc.Data[:16])
  		}
  	}
  
  	if !haveTTL {
  		return nil, fmt.Errorf("IPHAConn.readIPv6Packet: HOPLIMIT not found")
  	}
  	if dst == nil {
  		return nil, fmt.Errorf("IPHAConn.readIPv6Packet: Destination address not found")
  	}
  	return &packet{
  		src:     raddr.IP,
  		dst:     dst,
  		ttl:     ttl,
  		payload: b[:n],
  	}, nil
  }
docs: // readIPv6Packet reads an IPv6 packet. For IPv6, the Read* functions do not
  // include the IP header, so the HOPLIMIT and destination address are read from
  // the control message data (see RFCs 3542 and 2292). The source address is
  // taken from the ReadMsgIP return values.