1<?php
2
3/**
4 * DNS Library for handling lookups and updates.
5 *
6 * Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
7 *
8 * See LICENSE for more details.
9 *
10 * @category  Networking
11 * @package   Net_DNS2
12 * @author    Mike Pultz <mike@mikepultz.com>
13 * @copyright 2020 Mike Pultz <mike@mikepultz.com>
14 * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License
15 * @link      https://netdns2.com/
16 * @since     File available since Release 0.6.0
17 *
18 */
19
20/**
21 * This class handles building new DNS request packets; packets used for DNS
22 * queries and updates.
23 *
24 */
25class Net_DNS2_Packet_Request extends Net_DNS2_Packet
26{
27    /**
28     * Constructor - builds a new Net_DNS2_Packet_Request object
29     *
30     * @param string $name  the domain name for the packet
31     * @param string $type  the DNS RR type for the packet
32     * @param string $class the DNS class for the packet
33     *
34     * @throws Net_DNS2_Exception
35     * @access public
36     *
37     */
38    public function __construct($name, $type = null, $class = null)
39    {
40        $this->set($name, $type, $class);
41    }
42
43    /**
44     * builds a new Net_DNS2_Packet_Request object
45     *
46     * @param string $name  the domain name for the packet
47     * @param string $type  the DNS RR type for the packet
48     * @param string $class the DNS class for the packet
49     *
50     * @return boolean
51     * @throws Net_DNS2_Exception
52     * @access public
53     *
54     */
55    public function set($name, $type = 'A', $class = 'IN')
56    {
57        //
58        // generate a new header
59        //
60        $this->header = new Net_DNS2_Header;
61
62        //
63        // add a new question
64        //
65        $q = new Net_DNS2_Question();
66
67        //
68        // allow queries directly to . for the root name servers
69        //
70        if ($name != '.') {
71            $name = trim(strtolower($name), " \t\n\r\0\x0B.");
72        }
73
74        $type = strtoupper(trim($type));
75        $class = strtoupper(trim($class));
76
77        //
78        // check that the input string has some data in it
79        //
80        if (empty($name)) {
81
82            throw new Net_DNS2_Exception(
83                'empty query string provided',
84                Net_DNS2_Lookups::E_PACKET_INVALID
85            );
86        }
87
88        //
89        // if the type is "*", rename it to "ANY"- both are acceptable.
90        //
91        if ($type == '*') {
92
93            $type = 'ANY';
94        }
95
96        //
97        // check that the type and class are valid
98        //
99        if (   (!isset(Net_DNS2_Lookups::$rr_types_by_name[$type]))
100            || (!isset(Net_DNS2_Lookups::$classes_by_name[$class]))
101        ) {
102            throw new Net_DNS2_Exception(
103                'invalid type (' . $type . ') or class (' . $class . ') specified.',
104                Net_DNS2_Lookups::E_PACKET_INVALID
105            );
106        }
107
108        if ($type == 'PTR') {
109
110            //
111            // if it's a PTR request for an IP address, then make sure we tack on
112            // the arpa domain.
113            //
114            // there are other types of PTR requests, so if an IP adress doesn't match,
115            // then just let it flow through and assume it's a hostname
116            //
117            if (Net_DNS2::isIPv4($name) == true) {
118
119                //
120                // IPv4
121                //
122                $name = implode('.', array_reverse(explode('.', $name)));
123                $name .= '.in-addr.arpa';
124
125            } else if (Net_DNS2::isIPv6($name) == true) {
126
127                //
128                // IPv6
129                //
130                $e = Net_DNS2::expandIPv6($name);
131                if ($e !== false) {
132
133                    $name = implode(
134                        '.', array_reverse(str_split(str_replace(':', '', $e)))
135                    );
136
137                    $name .= '.ip6.arpa';
138
139                } else {
140
141                    throw new Net_DNS2_Exception(
142                        'unsupported PTR value: ' . $name,
143                        Net_DNS2_Lookups::E_PACKET_INVALID
144                    );
145                }
146            }
147        }
148
149        //
150        // store the data
151        //
152        $q->qname           = $name;
153        $q->qtype           = $type;
154        $q->qclass          = $class;
155
156        $this->question[]   = $q;
157
158        //
159        // the answer, authority and additional are empty; they can be modified
160        // after the request is created for UPDATE requests if needed.
161        //
162        $this->answer       = [];
163        $this->authority    = [];
164        $this->additional   = [];
165
166        return true;
167    }
168}
169