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 * The main dynamic DNS notifier class. 22 * 23 * This class provices functions to handle DNS notify requests as defined by RFC 1996. 24 * 25 * This is separate from the Net_DNS2_Resolver class, as while the underlying 26 * protocol is the same, the functionality is completely different. 27 * 28 * Generally, query (recursive) lookups are done against caching server, while 29 * notify requests are done against authoratative servers. 30 * 31 */ 32class Net_DNS2_Notifier extends Net_DNS2 33{ 34 /* 35 * a Net_DNS2_Packet_Request object used for the notify request 36 */ 37 private $_packet; 38 39 /** 40 * Constructor - builds a new Net_DNS2_Notifier objected used for doing 41 * DNS notification for a changed zone 42 * 43 * @param string $zone the domain name to use for DNS updates 44 * @param mixed $options an array of config options or null 45 * 46 * @throws Net_DNS2_Exception 47 * @access public 48 * 49 */ 50 public function __construct($zone, array $options = null) 51 { 52 parent::__construct($options); 53 54 // 55 // create the packet 56 // 57 $this->_packet = new Net_DNS2_Packet_Request( 58 strtolower(trim($zone, " \n\r\t.")), 'SOA', 'IN' 59 ); 60 61 // 62 // make sure the opcode on the packet is set to NOTIFY 63 // 64 $this->_packet->header->opcode = Net_DNS2_Lookups::OPCODE_NOTIFY; 65 } 66 67 /** 68 * checks that the given name matches the name for the zone we're notifying 69 * 70 * @param string $name The name to be checked. 71 * 72 * @return boolean 73 * @throws Net_DNS2_Exception 74 * @access private 75 * 76 */ 77 private function _checkName($name) 78 { 79 if (!preg_match('/' . $this->_packet->question[0]->qname . '$/', $name)) { 80 81 throw new Net_DNS2_Exception( 82 'name provided (' . $name . ') does not match zone name (' . 83 $this->_packet->question[0]->qname . ')', 84 Net_DNS2_Lookups::E_PACKET_INVALID 85 ); 86 } 87 88 return true; 89 } 90 91 /** 92 * 3.7 - Add RR to notify 93 * 94 * @param Net_DNS2_RR $rr the Net_DNS2_RR object to be sent in the notify message 95 * 96 * @return boolean 97 * @throws Net_DNS2_Exception 98 * @access public 99 * 100 */ 101 public function add(Net_DNS2_RR $rr) 102 { 103 $this->_checkName($rr->name); 104 // 105 // add the RR to the "notify" section 106 // 107 if (!in_array($rr, $this->_packet->answer)) { 108 $this->_packet->answer[] = $rr; 109 } 110 return true; 111 } 112 113 /** 114 * add a signature to the request for authentication 115 * 116 * @param string $keyname the key name to use for the TSIG RR 117 * @param string $signature the key to sign the request. 118 * 119 * @return boolean 120 * @access public 121 * @see Net_DNS2::signTSIG() 122 * @deprecated function deprecated in 1.1.0 123 * 124 */ 125 public function signature($keyname, $signature, $algorithm = Net_DNS2_RR_TSIG::HMAC_MD5) 126 { 127 return $this->signTSIG($keyname, $signature, $algorithm); 128 } 129 130 /** 131 * returns the current internal packet object. 132 * 133 * @return Net_DNS2_Packet_Request 134 * @access public 135 # 136 */ 137 public function packet() 138 { 139 // 140 // take a copy 141 // 142 $p = $this->_packet; 143 144 // 145 // check for an authentication method; either TSIG or SIG 146 // 147 if ( ($this->auth_signature instanceof Net_DNS2_RR_TSIG) 148 || ($this->auth_signature instanceof Net_DNS2_RR_SIG) 149 ) { 150 $p->additional[] = $this->auth_signature; 151 } 152 153 // 154 // update the counts 155 // 156 $p->header->qdcount = count($p->question); 157 $p->header->ancount = count($p->answer); 158 $p->header->nscount = count($p->authority); 159 $p->header->arcount = count($p->additional); 160 161 return $p; 162 } 163 164 /** 165 * executes the notify request 166 * 167 * @param Net_DNS2_Packet_Response &$response ref to the response object 168 * 169 * @return boolean 170 * @throws Net_DNS2_Exception 171 * @access public 172 * 173 */ 174 public function notify(&$response = null) 175 { 176 // 177 // check for an authentication method; either TSIG or SIG 178 // 179 if ( ($this->auth_signature instanceof Net_DNS2_RR_TSIG) 180 || ($this->auth_signature instanceof Net_DNS2_RR_SIG) 181 ) { 182 $this->_packet->additional[] = $this->auth_signature; 183 } 184 185 // 186 // update the counts 187 // 188 $this->_packet->header->qdcount = count($this->_packet->question); 189 $this->_packet->header->ancount = count($this->_packet->answer); 190 $this->_packet->header->nscount = count($this->_packet->authority); 191 $this->_packet->header->arcount = count($this->_packet->additional); 192 193 // 194 // make sure we have some data to send 195 // 196 if ($this->_packet->header->qdcount == 0) { 197 throw new Net_DNS2_Exception( 198 'empty headers- nothing to send!', 199 Net_DNS2_Lookups::E_PACKET_INVALID 200 ); 201 } 202 203 // 204 // send the packet and get back the response 205 // 206 $response = $this->sendPacket($this->_packet, $this->use_tcp); 207 208 // 209 // clear the internal packet so if we make another request, we don't have 210 // old data being sent. 211 // 212 $this->_packet->reset(); 213 214 // 215 // for notifies, we just need to know it worked- we don't actualy need to 216 // return the response object 217 // 218 return true; 219 } 220} 221