<?php
namespace React\Dns\Model;
use React\Dns\Query\Query;
class Message
{
const TYPE_A = 1;
const TYPE_NS = 2;
const TYPE_CNAME = 5;
const TYPE_SOA = 6;
const TYPE_PTR = 12;
const TYPE_MX = 15;
const TYPE_TXT = 16;
const TYPE_AAAA = 28;
const TYPE_SRV = 33;
const TYPE_ANY = 255;
const CLASS_IN = 1;
const OPCODE_QUERY = 0;
const OPCODE_IQUERY = 1; // inverse query
const OPCODE_STATUS = 2;
const RCODE_OK = 0;
const RCODE_FORMAT_ERROR = 1;
const RCODE_SERVER_FAILURE = 2;
const RCODE_NAME_ERROR = 3;
const RCODE_NOT_IMPLEMENTED = 4;
const RCODE_REFUSED = 5;
/**
* Creates a new request message for the given query
*
* @param Query $query
* @return self
*/
public static function createRequestForQuery(Query $query)
{
$request = new Message();
$request->header->set('id', self::generateId());
$request->header->set('rd', 1);
$request->questions[] = (array) $query;
$request->prepare();
return $request;
}
/**
* Creates a new response message for the given query with the given answer records
*
* @param Query $query
* @param Record[] $answers
* @return self
*/
public static function createResponseWithAnswersForQuery(Query $query, array $answers)
{
$response = new Message();
$response->header->set('id', self::generateId());
$response->header->set('qr', 1);
$response->header->set('opcode', Message::OPCODE_QUERY);
$response->header->set('rd', 1);
$response->header->set('rcode', Message::RCODE_OK);
$response->questions[] = (array) $query;
foreach ($answers as $record) {
$response->answers[] = $record;
}
$response->prepare();
return $response;
}
/**
* generates a random 16 bit message ID
*
* This uses a CSPRNG so that an outside attacker that is sending spoofed
* DNS response messages can not guess the message ID to avoid possible
* cache poisoning attacks.
*
* The `random_int()` function is only available on PHP 7+ or when
* https://github.com/paragonie/random_compat is installed. As such, using
* the latest supported PHP version is highly recommended. This currently
* falls back to a less secure random number generator on older PHP versions
* in the hope that this system is properly protected against outside
* attackers, for example by using one of the common local DNS proxy stubs.
*
* @return int
* @see self::getId()
* @codeCoverageIgnore
*/
private static function generateId()
{
if (function_exists('random_int')) {
return random_int(0, 0xffff);
}
return mt_rand(0, 0xffff);
}
public $header;
public $questions = array();
public $answers = array();
public $authority = array();
public $additional = array();
/**
* @deprecated still used internally for BC reasons, should not be used externally.
*/
public $data = '';
/**
* @deprecated still used internally for BC reasons, should not be used externally.
*/
public $consumed = 0;
public function __construct()
{
$this->header = new HeaderBag();
}
/**
* Returns the 16 bit message ID
*
* The response message ID has to match the request message ID. This allows
* the receiver to verify this is the correct response message. An outside
* attacker may try to inject fake responses by "guessing" the message ID,
* so this should use a proper CSPRNG to avoid possible cache poisoning.
*
* @return int
* @see self::generateId()
*/
public function getId()
{
return $this->header->get('id');
}
/**
* Returns the response code (RCODE)
*
* @return int see self::RCODE_* constants
*/
public function getResponseCode()
{
return $this->header->get('rcode');
}
public function prepare()
{
$this->header->populateCounts($this);
}
}