Project

General

Profile

Download (18.3 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * status_ipsec.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2019 Rubicon Communications, LLC (Netgate)
7
 * All rights reserved.
8
 *
9
 * originally based on m0n0wall (http://m0n0.ch/wall)
10
 * Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
11
 * All rights reserved.
12
 *
13
 * Licensed under the Apache License, Version 2.0 (the "License");
14
 * you may not use this file except in compliance with the License.
15
 * You may obtain a copy of the License at
16
 *
17
 * http://www.apache.org/licenses/LICENSE-2.0
18
 *
19
 * Unless required by applicable law or agreed to in writing, software
20
 * distributed under the License is distributed on an "AS IS" BASIS,
21
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
 * See the License for the specific language governing permissions and
23
 * limitations under the License.
24
 */
25

    
26
##|+PRIV
27
##|*IDENT=page-status-ipsec
28
##|*NAME=Status: IPsec
29
##|*DESCR=Allow access to the 'Status: IPsec' page.
30
##|*MATCH=status_ipsec.php*
31
##|-PRIV
32

    
33
require_once("guiconfig.inc");
34
require_once("ipsec.inc");
35

    
36
global $g;
37

    
38
init_config_arr(array('ipsec', 'phase1'));
39

    
40
// If this is just an AJAX call to update the table body, just generate the body and quit
41
if ($_REQUEST['ajax']) {
42
	print_ipsec_body();
43
	exit;
44
}
45

    
46
if (($_POST['act'] == 'connect') || ($_POST['act'] == 'childconnect')) {
47
	if (ctype_digit($_POST['ikeid'])) {
48
		$ph1ent = ipsec_get_phase1($_POST['ikeid']);
49
		if (!empty($ph1ent)) {
50
			if (empty($ph1ent['iketype']) || ($ph1ent['iketype'] == 'ikev1') || isset($ph1ent['splitconn'])) {
51
				$ph2entries = ipsec_get_number_of_phase2($_POST['ikeid']);
52
				for ($i = 0; $i < $ph2entries; $i++) {
53
					$connid = escapeshellarg("con{$_POST['ikeid']}00{$i}");
54
					if ($_POST['act'] != 'childconnect') {
55
						mwexec_bg("/usr/local/sbin/ipsec down {$connid}");
56
					}
57
					mwexec_bg("/usr/local/sbin/ipsec up {$connid}");
58
				}
59
			} else {
60
				if ($_POST['act'] != 'childconnect') {
61
					mwexec_bg("/usr/local/sbin/ipsec down con" . escapeshellarg($_POST['ikeid'] . '000'));
62
				}
63
				mwexec_bg("/usr/local/sbin/ipsec up con" . escapeshellarg($_POST['ikeid'] . '000'));
64
			}
65
		}
66
	}
67
} else if ($_POST['act'] == 'ikedisconnect') {
68

    
69
	if (!empty($_POST['ikesaid']) && ctype_digit($_POST['ikesaid'])) {
70
		mwexec_bg("/usr/local/sbin/ipsec down " ."'" . escapeshellarg($_POST['ikeid']) . "[" . escapeshellarg($_POST['ikesaid']) . "]" . "'");
71
	} else {
72
		mwexec_bg("/usr/local/sbin/ipsec down " . escapeshellarg($_POST['ikeid']));
73
	}
74
} else if ($_POST['act'] == 'childdisconnect') {
75
	//pull out number from id
76
		if (!empty($_POST['ikesaid']) && ctype_digit($_POST['ikesaid'])) {
77
			mwexec_bg("/usr/local/sbin/ipsec down " . escapeshellarg($_POST['ikeid']) . "{" . escapeshellarg($_POST['ikesaid']) . "}");
78
		}
79
}
80

    
81
// Table body is composed here so that it can be more easily updated via AJAX
82
function print_ipsec_body() {
83
	global $config;
84
	$a_phase1 = &$config['ipsec']['phase1'];
85
	$status = ipsec_list_sa();
86
	$ipsecconnected = array();
87
	if (is_array($status)) {
88
		foreach ($status as $ikeid => $ikesa) {
89
			//check which array format
90
			if(isset($ikesa['con-id'])){
91
				$con_id = substr($ikesa['con-id'],3);
92
			}else{
93
				$con_id = filter_var($ikeid, FILTER_SANITIZE_NUMBER_INT);
94
			}
95
			if ($ikesa['version'] == 1) {
96
				$ph1idx = substr($con_id, 0, strrpos(substr($con_id, 0, -1), '00'));
97
				$ipsecconnected[$ph1idx] = $ph1idx;
98
			} else {
99
				if (!ipsec_ikeid_used($con_id)) {
100
					// probably a v2 with split connection then
101
					$ph1idx = substr($con_id, 0, strrpos(substr($con_id, 0, -1), '00'));
102
					$ipsecconnected[$ph1idx] = $ph1idx;
103
				} else {
104
					$ipsecconnected[$con_id] = $ph1idx = $con_id;
105
				}
106
			}
107

    
108
			print("<tr>\n");
109

    
110
			print("<td>\n");
111
			print(htmlspecialchars($ikesa['con-id'])) . ":\n";
112
			print('#' . htmlspecialchars($ikesa['uniqueid']));
113
			print("</td>\n");
114

    
115
			print("<td>\n");
116
			if (is_array($a_phase1) && htmlspecialchars(ipsec_get_descr($ph1idx)) == "") {
117
				foreach ($a_phase1 as $ph1) {
118
					if($con_id == $ph1['ikeid'] && isset($ph1['mobile']) ){
119
						print(htmlspecialchars($ph1['descr']));
120
						break;
121
					}
122
				}
123
			}
124
			print(htmlspecialchars(ipsec_get_descr($ph1idx)));
125
			print("</td>\n");
126

    
127
			print("<td>\n");
128

    
129
			if (!empty($ikesa['local-id'])) {
130
				if ($ikesa['local-id'] == '%any') {
131
					print(gettext('Any identifier'));
132
				} else {
133
					print(htmlspecialchars($ikesa['local-id']));
134
				}
135
			} else {
136
				print(gettext("Unknown"));
137
			}
138

    
139
			print("</td>\n");
140
			print("<td>\n");
141

    
142
			if (!empty($ikesa['local-host'])) {
143
				print(htmlspecialchars($ikesa['local-host']));
144
			} else {
145
				print(gettext("Unknown"));
146
			}
147

    
148
			/*
149
			 * XXX: local-nat-t was defined by pfSense
150
			 * When strongswan team accepted the change, they changed it to
151
			 * nat-local. Keep both for a while and remove local-nat-t in
152
			 * the future
153
			 */
154
			if (isset($ikesa['local-nat-t']) || isset($ikesa['nat-local'])) {
155
				print(" NAT-T");
156
			}
157

    
158
			print("</td>\n");
159
			print("<td>\n");
160

    
161
			$identity = "";
162
			if (!empty($ikesa['remote-id'])) {
163
				if ($ikesa['remote-id'] == '%any') {
164
					$identity = htmlspecialchars(gettext('Any identifier'));
165
				} else {
166
					$identity = htmlspecialchars($ikesa['remote-id']);
167
				}
168
			}
169

    
170
			if (!empty($ikesa['remote-xauth-id'])) {
171
				echo htmlspecialchars($ikesa['remote-xauth-id']);
172
				echo "<br/>{$identity}";
173
			} elseif (!empty($ikesa['remote-eap-id'])) {
174
				echo htmlspecialchars($ikesa['remote-eap-id']);
175
				echo "<br/>{$identity}";
176
			} else {
177
				if (empty($identity)) {
178
					print(gettext("Unknown"));
179
				} else {
180
					print($identity);
181
				}
182
			}
183

    
184
			print("</td>\n");
185
			print("<td>\n");
186

    
187
			if (!empty($ikesa['remote-host'])) {
188
				print(htmlspecialchars($ikesa['remote-host']));
189
			} else {
190
				print(gettext("Unknown"));
191
			}
192
			/*
193
			 * XXX: remote-nat-t was defined by pfSense
194
			 * When strongswan team accepted the change, they changed it to
195
			 * nat-remote. Keep both for a while and remove remote-nat-t in
196
			 * the future
197
			 */
198
			if (isset($ikesa['remote-nat-t']) || isset($ikesa['nat-remote'])) {
199
				print(" NAT-T");
200
			}
201

    
202
			print("</td>\n");
203
			print("<td>\n");
204
			print("IKEv" . htmlspecialchars($ikesa['version']));
205
			print("<br/>\n");
206

    
207
			if ($ikesa['initiator'] == 'yes') {
208
				print("initiator");
209
			} else {
210
				print("responder");
211
			}
212

    
213
			print("</td>\n");
214
			print("<td>\n");
215
			print(htmlspecialchars($ikesa['reauth-time']) . gettext(" seconds (") . convert_seconds_to_dhms($ikesa['reauth-time']) . ")");
216
			print("</td>\n");
217
			print("<td>\n");
218
			print(htmlspecialchars($ikesa['encr-alg']));
219
			print("<br/>");
220
			print(htmlspecialchars($ikesa['integ-alg']));
221
			print("<br/>");
222
			print(htmlspecialchars($ikesa['prf-alg']));
223
			print("<br/>\n");
224
			print(htmlspecialchars($ikesa['dh-group']));
225
			print("</td>\n");
226
			print("<td>\n");
227

    
228
			if ($ikesa['state'] == 'ESTABLISHED') {
229
				print('<span class="text-success">');
230
			} else {
231
				print('<span>');
232
			}
233

    
234
			print(ucfirst(htmlspecialchars($ikesa['state'])));
235

    
236
			if ($ikesa['state'] == 'ESTABLISHED') {
237
				print("<br/>");
238
				printf(gettext('%1$s seconds (%2$s) ago'), htmlspecialchars($ikesa['established']), convert_seconds_to_dhms($ikesa['established']));
239
			}
240

    
241
			print("</span><br /><br />");
242

    
243
			if ($ikesa['state'] != 'ESTABLISHED') {
244

    
245
				print('<a href="status_ipsec.php?act=connect&amp;ikeid=' . $con_id . '&amp;ikesaid=' .$ikesa['uniqueid'] . '" class="btn btn-xs btn-success" data-toggle="tooltip" title="' . gettext("Connect VPN"). '" usepost>');
246
				print('<i class="fa fa-sign-in icon-embed-btn"></i>');
247
				print(gettext("Connect VPN"));
248
				print("</a>\n");
249

    
250
			} else {
251

    
252
				print('<a href="status_ipsec.php?act=ikedisconnect&amp;ikeid=' . $ikesa['con-id']. '&amp;ikesaid=' .$ikesa['uniqueid'] . '"class="btn btn-xs btn-danger" data-toggle="tooltip" title="' . gettext("Disconnect VPN") . '" usepost>');
253
				print('<i class="fa fa-trash icon-embed-btn"></i>');
254
				print(gettext("Disconnect"));
255
				print("</a><br />\n");
256

    
257
			}
258
			if (empty($ikesa['child-sas'])) {
259
				print('<br/><a href="status_ipsec.php?act=childconnect&amp;ikeid=' . substr($con_id, 0, -3) . '" class="btn btn-xs btn-success" data-toggle="tooltip" title="' . gettext("Connect Children"). '" usepost>');
260
				print('<i class="fa fa-sign-in icon-embed-btn"></i>');
261
				print(gettext("Connect Children"));
262
				print("</a>\n");
263
			}
264

    
265
			print("</td>\n");
266
			print("</tr>\n");
267
			print("<tr>\n");
268
			print("<td colspan = 10>\n");
269

    
270
			if (is_array($ikesa['child-sas']) && (count($ikesa['child-sas']) > 0)) {
271
				$child_key = "";
272
				foreach ($ikesa['child-sas'] as $key => $val){
273
					$child_key = $key;
274
					break;
275
				}
276

    
277
				print('<div>');
278
				print('<a type="button" id="btnchildsa-'. $child_key .  '" class="btn btn-sm btn-info">');
279
				print('<i class="fa fa-plus-circle icon-embed-btn"></i>');
280
				print(sprintf(gettext('Show child SA entries (%d)'), count($ikesa['child-sas'])));
281
				print("</a>\n");
282
				print("	</div>\n");
283

    
284
				print('<table class="table table-hover table-condensed" id="childsa-'.$child_key . '" style="display:none">');
285
				print("<thead>\n");
286
				print('<tr class="bg-info">');
287
				print('<th>' . gettext("IPsec ID") . '</th>');
288
				print('<th>' . gettext("Local subnets") . '</th>');
289
				print('<th>' . gettext("Local SPI(s)") . '</th>');
290
				print('<th>' . gettext("Remote subnets") . '</th>');
291
				print('<th>' . gettext("Times") . '</th>');
292
				print('<th>' . gettext("Algo") . '</th>');
293
				print('<th>' . gettext("Stats") . '</th>');
294
				print('<th><!-- Buttons --></th>');
295
				print("</tr\n");
296
				print("</thead>\n");
297
				print("<tbody>\n");
298

    
299
				foreach ($ikesa['child-sas'] as $childid => $childsa) {
300
					print("<tr>");
301
					print("<td>\n");
302
					print($childsa['name'] . ":<br />");
303
					print("#" . $childsa['uniqueid']);
304
					print("</td>\n");
305
					print("<td>\n");
306

    
307
					if (is_array($childsa['local-ts'])) {
308
						foreach ($childsa['local-ts'] as $lnets) {
309
							print(htmlspecialchars(ipsec_fixup_network($lnets)) . "<br />");
310
						}
311
					} else {
312
						print(gettext("Unknown"));
313
					}
314

    
315
					print("</td>\n");
316
					print("<td>\n");
317

    
318
					if (isset($childsa['spi-in'])) {
319
						print(gettext("Local: ") . htmlspecialchars($childsa['spi-in']));
320
					}
321

    
322
					if (isset($childsa['spi-out'])) {
323
						print('<br/>' . gettext('Remote: ') . htmlspecialchars($childsa['spi-out']));
324
					}
325

    
326
					print("</td>\n");
327
					print("<td>\n");
328

    
329
					if (is_array($childsa['remote-ts'])) {
330
						foreach ($childsa['remote-ts'] as $rnets) {
331
							print(htmlspecialchars(ipsec_fixup_network($rnets)) . '<br />');
332
						}
333
					} else {
334
						print(gettext("Unknown"));
335
					}
336

    
337
					print("</td>\n");
338
					print("<td>\n");
339

    
340
					printf(gettext('Rekey: %1$s seconds (%2$s)'), htmlspecialchars($childsa['rekey-time']), convert_seconds_to_dhms($childsa['rekey-time']));
341
					print('<br/>');
342
					printf(gettext('Life: %1$s seconds (%2$s)'), htmlspecialchars($childsa['life-time']), convert_seconds_to_dhms($childsa['life-time']));
343
					print('<br/>');
344
					printf(gettext('Install: %1$s seconds (%2$s)'), htmlspecialchars($childsa['install-time']), convert_seconds_to_dhms($childsa['install-time']));
345

    
346

    
347
					print("</td>\n");
348
					print("<td>\n");
349

    
350
					print(htmlspecialchars($childsa['encr-alg']) . '<br/>');
351
					print(htmlspecialchars($childsa['integ-alg']) . '<br/>');
352

    
353
					if (!empty($childsa['prf-alg'])) {
354
						print(htmlspecialchars($childsa['prf-alg']) . '<br/>');
355
					}
356

    
357
					if (!empty($childsa['dh-group'])) {
358
						print(htmlspecialchars($childsa['dh-group']) . '<br/>');
359
					}
360

    
361
					if (!empty($childsa['esn'])) {
362
						print(htmlspecialchars($childsa['esn']) . '<br/>');
363
					}
364

    
365
					print(gettext("IPComp: "));
366
					if (!empty($childsa['cpi-in']) || !empty($childsa['cpi-out'])) {
367
						print(htmlspecialchars($childsa['cpi-in']) . " " . htmlspecialchars($childsa['cpi-out']));
368
					} else {
369
						print(gettext('none'));
370
					}
371

    
372
					print("</td>\n");
373
					print("<td>\n");
374

    
375
					print(gettext("Bytes-In: ") . htmlspecialchars(number_format($childsa['bytes-in'])) . ' (' . htmlspecialchars(format_bytes($childsa['bytes-in'])) . ')<br/>');
376
					print(gettext("Packets-In: ") . htmlspecialchars(number_format($childsa['packets-in'])) . '<br/>');
377
					print(gettext("Bytes-Out: ") . htmlspecialchars(number_format($childsa['bytes-out'])) . ' (' . htmlspecialchars(format_bytes($childsa['bytes-out'])) . ')<br/>');
378
					print(gettext("Packets-Out: ") . htmlspecialchars(number_format($childsa['packets-out'])) . '<br/>');
379

    
380
					print("</td>\n");
381
					print("<td>\n");
382
					print('<a href="status_ipsec.php?act=childdisconnect&amp;ikeid=' . $childsa['name'] . '&amp;ikesaid=' . $childsa['uniqueid'] . '" class="btn btn-xs btn-warning" data-toggle="tooltip" title="' . gettext('Disconnect Child SA') . '" usepost>');
383
					print('<i class="fa fa-trash icon-embed-btn"></i>');
384
					print(gettext("Disconnect"));
385
					print("</a>\n");
386
					print("</td>\n");
387
					print("</tr>\n");
388

    
389
				}
390

    
391
				print("</tbody>\n");
392
				print("	</table>\n");
393
				print("</td>\n");
394
				print("</tr>\n");
395

    
396
			}
397

    
398
			unset($con_id);
399
		}
400

    
401
	}
402

    
403
	$rgmap = array();
404
	if (is_array($a_phase1)) {
405
		foreach ($a_phase1 as $ph1ent) {
406
			if (isset($ph1ent['disabled'])) {
407
				continue;
408
			}
409

    
410
			$rgmap[$ph1ent['remote-gateway']] = $ph1ent['remote-gateway'];
411

    
412
			if ($ipsecconnected[$ph1ent['ikeid']]) {
413
				continue;
414
			}
415

    
416
			print("<tr>\n");
417
			print("<td></td>\n");
418
			print("<td>\n");
419
			print(htmlspecialchars($ph1ent['descr']));
420
			print("</td>\n");
421
			print("<td>\n");
422
			list ($myid_type, $myid_data) = ipsec_find_id($ph1ent, "local");
423

    
424
			if (empty($myid_data)) {
425
				print(gettext("Unknown"));
426
			} else {
427
				print(htmlspecialchars($myid_data));
428
			}
429

    
430
			print("</td>\n");
431
			print("<td>\n");
432
			$ph1src = ipsec_get_phase1_src($ph1ent);
433

    
434
			if (empty($ph1src)) {
435
				print(gettext("Unknown"));
436
			} else {
437
				print(htmlspecialchars(str_replace(',', ', ', $ph1src)));
438
			}
439

    
440
			print("</td>\n");
441
			print("<td>\n");
442

    
443
			list ($peerid_type, $peerid_data) = ipsec_find_id($ph1ent, "peer", $rgmap);
444

    
445
			if (empty($peerid_data)) {
446
				print(gettext("Unknown"));
447
			} else {
448
				print(htmlspecialchars($peerid_data));
449
			}
450
			print("			</td>\n");
451
			print("			<td>\n");
452
			$ph1src = ipsec_get_phase1_dst($ph1ent);
453

    
454
			if (empty($ph1src)) {
455
				print(gettext("Unknown"));
456
			} else {
457
				print(htmlspecialchars($ph1src));
458
			}
459

    
460
			print("</td>\n");
461
			print("<td>\n");
462
			print("</td>\n");
463
			print("<td>\n");
464
			print("</td>\n");
465
			print("<td>\n");
466
			print("</td>\n");
467

    
468
			if (isset($ph1ent['mobile'])) {
469

    
470
				print("<td>\n");
471
				print(gettext("Awaiting connections"));
472
				print("</td>\n");
473
				print("<td>\n");
474
				print("</td>\n");
475
				print("</td>\n");
476
			} else {
477

    
478
				print("<td>\n");
479
				print(gettext("Disconnected"));
480
				print("<br/>\n");
481
				print('<a href="status_ipsec.php?act=connect&amp;ikeid=' . $ph1ent['ikeid'] . '" class="btn btn-xs btn-success" usepost>');
482
				print('<i class="fa fa-sign-in icon-embed-btn"></i>');
483
				print(gettext("Connect VPN"));
484
				print("</a>\n");
485
				print("</td>\n");
486

    
487
			}
488
			print("</tr>\n");
489
		}
490
	}
491

    
492
	unset($ipsecconnected, $phase1, $rgmap);
493
}
494

    
495
$pgtitle = array(gettext("Status"), gettext("IPsec"), gettext("Overview"));
496
$pglinks = array("", "@self", "@self");
497
$shortcut_section = "ipsec";
498

    
499
include("head.inc");
500

    
501
$tab_array = array();
502
$tab_array[] = array(gettext("Overview"), true, "status_ipsec.php");
503
$tab_array[] = array(gettext("Leases"), false, "status_ipsec_leases.php");
504
$tab_array[] = array(gettext("SADs"), false, "status_ipsec_sad.php");
505
$tab_array[] = array(gettext("SPDs"), false, "status_ipsec_spd.php");
506
display_top_tabs($tab_array);
507
?>
508

    
509
<div class="panel panel-default">
510
	<div class="panel-heading"><h2 class="panel-title"><?=gettext("IPsec Status");?></h2></div>
511
	<div class="panel-body table-responsive">
512
		<table class="table table-striped table-condensed table-hover sortable-theme-bootstrap" data-sortable>
513
			<thead>
514
				<tr>
515
					<th><?=gettext("IPsec ID")?></th>
516
					<th><?=gettext("Description")?></th>
517
					<th><?=gettext("Local ID")?></th>
518
					<th><?=gettext("Local IP")?></th>
519
					<th><?=gettext("Remote ID")?></th>
520
					<th><?=gettext("Remote IP")?></th>
521
					<th><?=gettext("Role")?></th>
522
					<th><?=gettext("Reauth")?></th>
523
					<th><?=gettext("Algo")?></th>
524
					<th><?=gettext("Status")?></th>
525
					<th></th>
526
				</tr>
527
			</thead>
528
			<tbody id="ipsec-body">
529
				<tr>
530
					<td colspan="10">
531
						<?=print_info_box(gettext("Collecting IPsec status information."), "warning", "")?>
532
					</td>
533
				</tr>
534
			</tbody>
535
		</table>
536
	</div>
537
</div>
538

    
539
<?php
540
unset($status);
541

    
542
if (ipsec_enabled()) {
543
	print('<div class="infoblock">');
544
} else {
545
	print('<div class="infoblock blockopen">');
546
}
547

    
548
print_info_box(sprintf(gettext('IPsec can be configured %1$shere%2$s.'), '<a href="vpn_ipsec.php">', '</a>'), 'info', false);
549
?>
550
</div>
551

    
552
<script type="text/javascript">
553
//<![CDATA[
554

    
555
events.push(function() {
556
	ajax_lock = false;		// Mutex so we don't make a call until the previous call is finished
557
	sa_open = new Array();	// Array in which to keep the child SA show/hide state
558
	tryCount = 3;
559
	// Fetch the tbody contents from the server
560
	function update_table() {
561
		if (ajax_lock) {
562
			return;
563
		}
564

    
565
		ajax_lock = true;
566

    
567
		ajaxRequest = $.ajax(
568
			{
569
				url: "/status_ipsec.php",
570
				type: "post",
571
				data: {
572
					ajax: 	"ajax"
573
				},
574
				error: function(xhr, textStatus, errorThrown){
575
					//alert("error.... retrying");
576
					if (tryCount > 0){
577
						tryCount --;
578
						ajax_lock = false;
579
						update_table();
580
					}
581
					return;
582
				}
583
			}
584
		);
585

    
586
		// Deal with the results of the above ajax call
587
		ajaxRequest.done(function (response, textStatus, jqXHR) {
588
			if(textStatus === "success"){
589
				tryCount =3;
590
			}
591
			if (!response) {
592
				response = '<tr><td colspan="10"><?=print_info_box(addslashes(gettext("No IPsec status information available.")), "warning", "")?></td></tr>';
593
			}
594

    
595
			$('#ipsec-body').html(response);
596
			ajax_lock = false;
597

    
598
			// Update "Show child SA" handlers
599
			$('[id^=btnchildsa-]').click(function () {
600
				show_childsa($(this).prop("id").replace( 'btnchildsa-', ''));
601
			});
602

    
603
			// Check the sa_open array for child SAs that have been opened
604
			$('[id^=childsa-]').each(function(idx) {
605
				sa_idx = $(this).prop("id").replace( 'childsa-', '');
606

    
607
				if (sa_open[sa_idx]) {
608
					show_childsa(sa_idx);
609
				}
610
			});
611

    
612
			// re-attached the GET to POST handler
613
			interceptGET();
614

    
615
			// and do it again
616
			setTimeout(update_table, 5000);
617
		});
618
	}
619

    
620
	function show_childsa(said) {
621
		sa_open[said] = true;
622
		$('#childsa-' + said).show();
623
		$('#btnchildsa-' + said).hide();
624
	}
625

    
626
	// Populate the tbody on page load
627
	update_table();
628
});
629
//]]>
630
</script>
631

    
632
<?php
633
include("foot.inc"); ?>
(172-172/235)