-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcutebind.php
More file actions
280 lines (244 loc) · 12.6 KB
/
cutebind.php
File metadata and controls
280 lines (244 loc) · 12.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
<?php
ini_set('display_errors','On');
ini_set('display_warnings','On');
error_reporting(E_ALL);
define('APP_ROOT',realpath(dirname(__FILE__)).'/');
define('DNS_CACHE_SIZE', 1024 * 32); // Size of shared memory used for cache (Bytes) . Default is 32Kb
/*
Below are minimum default configuration parameters needed to start server without errors.
Do not change these values here. Use config.php to override it with your user-defined setting.
*/
$settings = array(
'listen' => '127.0.0.1', // IP to listen on (IP addr of this host)
'listen_port' => 53, // DNS-server port
'minDNSworkers' => 10, // Minimum/Initial number of workers
'maxDNSworkers' => 20, // Maximum number of workers
'pidfile' => APP_ROOT.'cutebind.pid', // Default pid-file
'ipcdir' => APP_ROOT.'ipc/', // Directory for IPC
'configfile' => APP_ROOT.'config.php', // Config-file
'cutebind_path' => 'cutebind', // Path to CuteBind's executable file.
'accesslog' => APP_ROOT.'logs/%DATE=Y-m-d%.log', // Log storage. This field has special syntax, but it allows simple path.
'errorlog' => APP_ROOT.'logs/error.log', // Error log storage.
'cache_dump' => APP_ROOT.'logs/cache_dump.json', // Cache dump file.
'tmpfile' => '/tmp/cutebind.tmp', // Temporary report file. CuteBind processes must have write access to this location.
'setuser' => '', // You can set user of master process (sudo).
'setgroup' => '', // You can set group of master process (sudo).
'use_fork' => TRUE, // Enables multi-threading if possible.
'logging'=> array(
'date_format' => 'Y-m-d H:i:s', // 'r' for RFC2822 formatted date (Tue, 29 Jul 2014 09:00:09 +0000). See PHP function date() to make your own format.
'level' => 1 // Logging level (currently is not used)
),
'DNS' => array(
'TTL'=> 60, // Default Time-To-Life (TTL). If DNS record has its own 'ttl', that ttl will be used (regardless of the record source). Otherwise this value.
'TC' => 0, // Truncate to 512 bytes
'RA' => 1, // Recursive queries enabled? (1/0)
'RR' => 15 // Use roundrobin for: 1=Inline hash-table, 2=Cached records, 4=Resolver/DB, 8=Lookups, 15=All of the above, 0=none/disabled
),
'SBL' => array( // See README.txt
'hostmatch' => '.sbl.example.tld.',
'return_ip' => '127.0.0.2',
'txt' => 'www.example.com/sbl'
),
'DEBUG' => FALSE,
'table' => array( // Simple resolving hash-table (static/permanent/lmhosts).
'localhost.' => array( // keep it - it acts as cache
'A' => array('127.0.0.1' => array('ttl' => 600)),
'AAAA'=> array('::1' => array('ttl' => 600))
),
'127.0.0.1' => array( // keep it - it acts as cache
'PTR' => array('localhost' => array('ttl' => 600))
),
),
);
$ver = '2.3';
if (!function_exists('cli_set_process_title')) {function cli_set_process_title($t) {}}
require_once APP_ROOT.'include/common.php'; // Various common functions that are used from this point on.
require_once APP_ROOT.'include/dns-cache.php'; // Everything related to runtime cache feature
$runmode = isset($_SERVER['argv'][1]) ? str_replace('-','',$_SERVER['argv'][1]) : '';
$_SERVER['argv'][1] = '';
$args = getArgs($_SERVER['argv']);
$args_ex = '';
// Load configuration file (in order of priority)
if (isset($args['configfile'])) { // 1. See if alternative configuration file is specified in the command line.
$settings['configfile'] = $args['configfile']; // update $settings['configfile']
} elseif( file_exists(APP_ROOT.'config.my.php') ) { // 2. See if used-defined configuration file exists in APP_ROOT directory.
$settings['configfile'] = APP_ROOT.'config.my.php'; // update $settings['configfile']
} elseif( file_exists('config.my.php') ) { // 3. See if used-defined configuration file exists in current directory.
$settings['configfile'] = 'config.my.php'; // update $settings['configfile']
} elseif( $settings['configfile'] !== '') {
//nothing // 4. Use default configuration file specified in $settings['configfile'] (APP_ROOT.'config.php')
}
include $settings['configfile']; // and load this file.
echo "\n";
echo '[INIT] Configuration file: '.$settings['configfile']."\n";
if (!function_exists('resolver')) { // Test whether function resolver() is defined
function resolver(&$q,&$a) {return false;} // If not, define a dummy resolver() that does nothing.
echo '[INIT] User-defined resolver() function is not declared. Using dummy recolver() which does nothing.'."\n";
} else {
resolver($null,$null,TRUE); // Call resolver() to init database connection (No longer necessary since $db is now global)
echo '[INIT] User-defined resolver() function exists.'."\n";
}
foreach ($args as $k => $v) { // Iterate command line parameters and update $settings
$ok = TRUE;
switch($k) {
case 'pidfile' : $settings[$k] = $v; break;
case 'listen' : $settings['listen'] = $v; break;
case 'listenport' : $settings['listen_port'] = $v; break;
case 'cutebindpath': $settings[$k] = $v; break;
//case 'configfile' : $settings[$k] = $v; break; // already taken care above
case 'logging' : $settings[$k] = (int) $v; break;
case 'logstorage' : $settings[$k] = $v; break;
case 'setuser' : $settings[$k] = $v; break;
case 'setgroup' : $settings[$k] = $v; break;
case 'tmpfile' : $settings[$k] = $v; break;
case 'debug' : $settings['DEBUG'] = true; break;
default:
fwrite(STDERR,'[WARN] Unknown parameter \''.$k."'\n");
$ok = FALSE;
}
if ($ok) {$args_ex .= ($args_ex !== ''?' ':'').'--'.$k.'=\''.$v.'\'';}
}
unset($args); // don't need it anymore
if (!file_exists($settings['pidfile'])) {
touch($settings['pidfile']);
if (!file_exists($settings['pidfile'])) {
log_error("[ERROR] Can't create process id file $settings[pidfile]\n");
exit(1);
}
}
if ($runmode != 'master') { // We are control script (Command Line Interface)
// Reason for having it in separate include file is that the master process nor workers
// ever use any of this code, so they don't need to know about it. Also, makes program
// easier to read.
require_once APP_ROOT.'include/cli.php';
exit(0);
}
// Now, we are the master or the worker (pre-worker). Let's init environment...
cli_set_process_title('cutebind: master process');
$dns_sockets = array();
$zmap = array();
$ipc = array();
$ipc_keys = array();
$ipc_files = array();
$ipc_prefix = dechex(crc32($settings['pidfile']));
define('MASTER_PID',getmypid());
if (version_compare(PHP_VERSION,'5.3.0','<')) declare(ticks = 1);
if (!function_exists('shmop_open')) { // Test if php_ipc is installed
echo "[ERROR] shmop_open() is not found. Please add PHP shared memory library (php5-shmop) to your PHP instalation.\n";
exit(1);
}
// --- BEGIN --- SHARED MEMORY INITIALIZATION FOR 'dns-status-map' ---------------------------
touch($tp = $settings['ipcdir'].$ipc_prefix.'.dns-status-map.cbt');
$ipc_files[] = $tp;
$ipc_keys['dns-status-map'] = ftok($tp,'t');
if (defined('IS_64b')) $ipc_keys['dns-status-map'] = $ipc_keys['dns-status-map']+($ipc_keys['dns-status-map']/pow(10,strlen($ipc_keys['dns-status-map'])));
@$ipc['dns-status-map'] = shmop_open($ipc_keys['dns-status-map'],'w',0,0);
if ($ipc['dns-status-map']) {
echo "[INIT] Attached to existing shared memory segment 'dns-status-map'\n";
} else {
$ipc['dns-status-map'] = shmop_open($ipc_keys['dns-status-map'],'c',0644, $settings['maxDNSworkers']*17); // block #1 = 1 byte per worker, block #2 = 16 bytes per worker
if($ipc['dns-status-map']) {
echo "[INIT] Created new shared memory segment 'dns-status-map' (".($settings['maxDNSworkers']*17)." bytes)\n";
shmop_write($ipc['dns-status-map'],str_repeat("\x00",$settings['maxDNSworkers']*17),0); // write a bunch of nulls into this memory segment
} else {
log_error("[ERROR] Couldn't create shared memory segment 'dns-q-counter'\n");
exit(1);
}
}
// --- END --- SHARED MEMORY INITIALIZATION FOR 'dns-status-map' ---------------------------
// --- BEGIN --- SHARED MEMORY INITIALIZATION FOR 'dns-q-counter' ---------------------------
touch($tp = $settings['ipcdir'].$ipc_prefix.'.dns-q-counter.cbt');
$ipc_files[] = $tp;
$ipc_keys['dns-q-counter'] = ftok($tp,'t');
//if (defined('IS_64b')) $ipc_keys['dns-status-map'] = $ipc_keys['dns-status-map']+($ipc_keys['dns-status-map']/pow(10,strlen($ipc_keys['dns-status-map'])));
@$ipc['dns-q-counter'] = shmop_open($ipc_keys['dns-q-counter'],'w',0,0);
if ($ipc['dns-q-counter']) {
echo "[INIT] Attached to existing shared memory segment 'dns-q-counter'\n";
} else {
$ipc['dns-q-counter'] = shmop_open($ipc_keys['dns-q-counter'],'c',0644,$settings['maxDNSworkers']*4); // 4 bytes (dword) per worker
if($ipc['dns-q-counter']) {
echo "[INIT] Created new shared memory segment 'dns-q-counter' (".($settings['maxDNSworkers']*4)." bytes)\n";
} else {
log_error("[ERROR] Couldn't create shared memory segment 'dns-q-counter'\n");
exit(1);
}
}
shmop_write($ipc['dns-q-counter'],str_repeat("\x00",$settings['maxDNSworkers']*4),0); // write a bunch of nulls into this memory segment
// --- END --- SHARED MEMORY INITIALIZATION FOR 'dns-q-counter' ---------------------------
// --- BEGIN --- SHARED MEMORY INITIALIZATION FOR 'dns-cache' ---------------------------
touch($tp = $settings['ipcdir'].$ipc_prefix.'.dns-cache.cbt');
$ipc_files[] = $tp;
$ipc_keys['dns-cache'] = ftok($tp,'t');
@$ipc['dns-cache'] = shmop_open($ipc_keys['dns-cache'],'w',0,0);
if ($ipc['dns-cache']) {
echo "[INIT] Attached to existing shared memory segment 'dns-cache'\n";
if( shmop_size($ipc['dns-cache']) != DNS_CACHE_SIZE ) {
//if($settings['DEBUG'])
echo '[DEBUG] Size of shared memory allocated to cache ('.(shmop_size($ipc['dns-cache'])/1024).' Kb) does not match DNS_CACHE_SIZE constant ('.(DNS_CACHE_SIZE/1024)." Kb) - attempting to recreate.\n";
if(shmop_delete($ipc['dns-cache'])) {
echo "[DEBUG] shared memory block is deleted\n";
if(shmop_close ($ipc['dns-cache'])) {
echo "[DEBUG] shared memory segment is closed\n";
} else {
echo "[DEBUG] shared memory segment is NOT closed\n";
}
} else {
echo "[DEBUG] shared memory block is NOT deleted\n";
}
// Recreate shared memory block with proper size
$ipc['dns-cache'] = shmop_open($ipc_keys['dns-cache'],'c',0644,DNS_CACHE_SIZE);
if($ipc['dns-cache']) {
echo "[DEBUG] Created new shared memory segment 'dns-cache' (".DNS_CACHE_SIZE." bytes)\n";
} else {
log_error("[ERROR] Couldn\'t create shared memory segment 'dns-cache'\n");
exit(1);
}
if( shmop_size($ipc['dns-cache']) != DNS_CACHE_SIZE ) {
echo '[ERROR] Size of shared memory allocated to cache ('.(shmop_size($ipc['dns-cache'])/1024).' Kb) does not match DNS_CACHE_SIZE constant ('.(DNS_CACHE_SIZE/1024)." Kb).\n";
exit(1);
}
}
} else {
$ipc['dns-cache'] = shmop_open($ipc_keys['dns-cache'],'c',0644,DNS_CACHE_SIZE);
if($ipc['dns-cache']) {
echo "[INIT] Created new shared memory segment 'dns-cache' (".DNS_CACHE_SIZE." bytes)\n";
} else {
log_error("[ERROR] Couldn't create shared memory segment 'dns-cache'\n");
exit(1);
}
}
$s = rtrim(shmop_read($ipc['dns-cache'],0,DNS_CACHE_SIZE));
$i = strlen($s);
if( $i ) {
// Check shared memory. If not empty, load it into $dns_cache object overwriting default values.
echo str_pad('[INIT] Loading dns-cache from shared memory',55,'.');
echo ((dns_cache_get()) ? 'OK' : 'FAILED')."\n";
//if($dns_cache['DEBUG']) print_r($dns_cache);
} else {
// write our initial $dns_cache object into this memory. No need to write a bunch of nulls because dns_cache_put() pads json string with nulls.
echo str_pad('[INIT] Initializing dns-cache using template',55,'.');
//$dns_cache['DIRTY'] = TRUE; // Set to TRUE to force write into shared memory
echo ((dns_cache_put()) ? 'OK' : 'FAILED')."\n";
}
unset($s);
// --- END --- SHARED MEMORY INITIALIZATION FOR 'dns-cache' ---------------------------
// Init database connection (this is going to be single connection shared by all workers)
if(isset($settings['mysql']['host'])) {
echo str_pad('[INIT] Connecting to MySQL server '.$settings['mysql']['host'],55,'.');
$db = connect_db();
if($db) {
echo "OK\n";
} else {
echo "FAILED\n";
echo mysqli_connect_error()."\n";
echo "[WARN] All functions that require database access will not be available.\n";
}
unset($db);
}
echo "[STATUS] Cache: ".((int)DNS_CACHE_SIZE/1024).' KB; '.count($dns_cache['table']).' hosts, '.$i.' bytes, '.round($i*100/DNS_CACHE_SIZE,2).'% usage; TTL '.$dns_cache['TTL']." sec.\n";
require_once APP_ROOT.'include/worker.php';
if ($runmode == 'master') {
// We are the master. Include module that has additional functionality that only master process uses.
require_once APP_ROOT.'include/master.php';
}
?>