Project

General

Profile

Download (33.4 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	services.inc
5
	part of m0n0wall (http://m0n0.ch/wall)
6

    
7
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
8
	All rights reserved.
9

    
10
	Redistribution and use in source and binary forms, with or without
11
	modification, are permitted provided that the following conditions are met:
12

    
13
	1. Redistributions of source code must retain the above copyright notice,
14
	   this list of conditions and the following disclaimer.
15

    
16
	2. Redistributions in binary form must reproduce the above copyright
17
	   notice, this list of conditions and the following disclaimer in the
18
	   documentation and/or other materials provided with the distribution.
19

    
20
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
24
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
	POSSIBILITY OF SUCH DAMAGE.
30
*/
31

    
32
/* include all configuration functions */
33
require_once("functions.inc");
34

    
35
function services_dhcpd_configure() {
36
	global $config, $g;
37
	
38
	if($g['services_dhcp_server_enable'] == false) 
39
		return;
40

    
41
	if(isset($config['system']['developerspew'])) {
42
		$mt = microtime();
43
		echo "services_dhcpd_configure($if) being called $mt\n";
44
	}
45
	
46
	/* kill any running dhcpd */
47
	if(is_process_running("dhcpd"))
48
		mwexec("killall dhcpd", true);
49

    
50
	/* DHCP enabled on any interfaces? */
51
	if (!is_dhcp_server_enabled())
52
		return 0;
53

    
54
	/* if OLSRD is enabled, allow WAN to house DHCP. */
55
	if($config['installedpackages']['olsrd'])
56
		foreach($config['installedpackages']['olsrd']['config'] as $olsrd)
57
				if($olsrd['enable'])
58
					$is_olsr_enabled = true;
59

    
60
	/* configure DHCPD chroot */
61
	$fd = fopen("/tmp/dhcpd.sh","w");
62
	$status = `mount | grep "{$g['dhcpd_chroot_path']}/dev"`;
63
	fwrite($fd, "mkdir -p {$g['dhcpd_chroot_path']}\n");
64
	fwrite($fd, "mkdir -p {$g['dhcpd_chroot_path']}/dev\n");
65
	fwrite($fd, "mkdir -p {$g['dhcpd_chroot_path']}/etc\n");
66
	fwrite($fd, "mkdir -p {$g['dhcpd_chroot_path']}/usr/local/sbin\n");
67
	fwrite($fd, "mkdir -p {$g['dhcpd_chroot_path']}/var/db\n");
68
	fwrite($fd, "mkdir -p {$g['dhcpd_chroot_path']}/usr\n");
69
	fwrite($fd, "mkdir -p {$g['dhcpd_chroot_path']}/lib\n");
70
	fwrite($fd, "mkdir -p {$g['dhcpd_chroot_path']}/run\n");
71
	fwrite($fd, "chown -R dhcpd:_dhcp {$g['dhcpd_chroot_path']}/*\n");
72
	fwrite($fd, "cp /lib/libc.so.* {$g['dhcpd_chroot_path']}/lib/\n");
73
	fwrite($fd, "cp /usr/local/sbin/dhcpd {$g['dhcpd_chroot_path']}/usr/local/sbin/\n");
74
	fwrite($fd, "chmod a+rx {$g['dhcpd_chroot_path']}/usr/local/sbin/dhcpd\n");
75
	if(!trim($status))
76
		fwrite($fd, "mount -t devfs devfs {$g['dhcpd_chroot_path']}/dev\n");
77
	fclose($fd);
78
	mwexec("/bin/sh /tmp/dhcpd.sh");
79

    
80
	$syscfg = $config['system'];
81
	$dhcpdcfg = $config['dhcpd'];
82
	$Iflist = get_configured_interface_list();
83
		
84
	if ($g['booting'])
85
		echo "Starting DHCP service...";
86
	else
87
		sleep(1);
88

    
89
	/* write dhcpd.conf */
90
	$fd = fopen("{$g['dhcpd_chroot_path']}/etc/dhcpd.conf", "w");
91
	if (!$fd) {
92
		printf("Error: cannot open dhcpd.conf in services_dhcpd_configure().\n");
93
		return 1;
94
	}
95

    
96

    
97

    
98
	$dhcpdconf = <<<EOD
99
	
100
option domain-name "{$syscfg['domain']}";
101
option ldap-server code 95 = text;
102
option domain-search-list code 119 = text;
103
default-lease-time 7200;
104
max-lease-time 86400;
105
log-facility local7;
106
ddns-update-style none;
107
one-lease-per-client true;
108
deny duplicates;
109
ping-check true;
110

    
111
EOD;
112

    
113
	if(isset($dhcpifconf['alwaysbroadcast'])) 
114
		$dhcpdconf .= "always-broadcast on\n";
115

    
116
	$dhcpdifs = array();
117

    
118
	/*    loop through and deterimine if we need to setup
119
	 *    failover peer "bleh" entries
120
	 */
121
	$dhcpnum = 0;
122
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
123

    
124
		if (!isset($dhcpifconf['enable']))
125
			continue;
126

    
127
		if(!isset($dhcpifconf['disableauthoritative']))
128
			$dhcpdconf .= "authoritative;\n";
129

    
130
		if($dhcpifconf['failover_peerip'] <> "") {
131
			/*
132
			 *    yep, failover peer is defined.
133
			 *    does it match up to a defined vip?
134
			 */
135
			$skew = 110;
136
			$a_vip = &$config['virtualip']['vip'];
137
			if(is_array($a_vip)) {
138
				foreach ($a_vip as $vipent) {
139
					$int = guess_interface_from_ip($dhcpifconf['failover_peerip']);
140
					$intip = find_interface_ip($int);
141
					$real_dhcpif = convert_friendly_interface_to_real_interface_name($dhcpif);
142
					if($int == $real_dhcpif) {
143
						/* this is the interface! */
144
						if($vipent['advskew'] < "20")
145
							$skew = 0;
146
					}
147
				}
148
			} else {
149
				log_error("Warning!  DHCP Failover setup and no CARP virtual IP's defined!");
150
			}
151
			if($skew > 10) {
152
				$type = "secondary";
153
				$dhcpdconf_pri  = "mclt 600;\n";
154
				$my_port = "520";
155
				$peer_port = "519";
156
			} else {
157
				$my_port = "519";
158
				$peer_port = "520";
159
				$type = "primary";
160
				$dhcpdconf_pri  = "split 128;\n";
161
				$dhcpdconf_pri .= "  mclt 600;\n";
162
			}
163
			$dhcpdconf .= <<<EOPP
164
failover peer "dhcp{$dhcpnum}" {
165
  {$type};
166
  address {$intip};
167
  port {$my_port};
168
  peer address {$dhcpifconf['failover_peerip']};
169
  peer port {$peer_port};
170
  max-response-delay 10;
171
  max-unacked-updates 10;
172
  {$dhcpdconf_pri}
173
  load balance max seconds 3;
174
}
175

    
176
EOPP;
177
		$dhcpnum++;
178
		}
179
	}
180

    
181
	$dhcpnum = 0;
182

    
183
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
184

    
185
		$ifcfg = $config['interfaces'][$dhcpif];
186

    
187
		if (!isset($dhcpifconf['enable']) || !isset($Iflist[$dhcpif]))
188
			continue;
189

    
190
		$subnet = gen_subnet($ifcfg['ipaddr'], $ifcfg['subnet']);
191
		$subnetmask = gen_subnet_mask($ifcfg['subnet']);
192

    
193
		if($is_olsr_enabled == true)
194
			if($dhcpifconf['netmask'])
195
				$subnetmask = gen_subnet_mask($dhcpifconf['netmask']);
196

    
197
		$dnscfg = "";
198

    
199
		if ($dhcpifconf['domain']) {
200
			$dnscfg .= "	option domain-name \"{$dhcpifconf['domain']}\";\n";
201
		}
202
		
203
    		if($dhcpifconf['domainsearchlist'] <> "") {
204
			$dnscfg .= "	option domain-search-list \"{$dhcpifconf['domainsearchlist']}\";\n";
205
    		}
206

    
207
		if (isset($dhcpifconf['ddnsupdate'])) {
208
			if($dhcpifconf['ddnsdomain'] <> "") {
209
				$dnscfg .= "	ddns-domainname \"{$dhcpifconf['ddnsdomain']}\";\n";
210
			}
211
			$dnscfg .= "	ddns-update-style interim;\n";
212
		}
213

    
214
		if (is_array($dhcpifconf['dnsserver']) && ($dhcpifconf['dnsserver'][0])) {
215
			$dnscfg .= "	option domain-name-servers " . join(",", $dhcpifconf['dnsserver']) . ";";
216
		} else if (isset($config['dnsmasq']['enable'])) {
217
			$dnscfg .= "	option domain-name-servers " . $ifcfg['ipaddr'] . ";";
218
		} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
219
			$dnscfg .= "	option domain-name-servers " . join(",", $syscfg['dnsserver']) . ";";
220
		}
221

    
222
		$dhcpdconf .= "subnet $subnet netmask $subnetmask {\n";
223
		$dhcpdconf .= "	pool {\n";
224

    
225
		/* is failover dns setup? */
226
		if (is_array($dhcpifconf['dnsserver']) && $dhcpifconf['dnsserver'][0] <> "") {
227
			$dhcpdconf .= "		option domain-name-servers {$dhcpifconf['dnsserver'][0]}";
228
			if($dhcpifconf['dnsserver'][1] <> "")
229
				$dhcpdconf .= ",{$dhcpifconf['dnsserver'][1]}";
230
			$dhcpdconf .= ";\n";
231
		}
232

    
233
		if($dhcpifconf['failover_peerip'] <> "")
234
			$dhcpdconf .= "		deny dynamic bootp clients;\n";
235

    
236
		if (isset($dhcpifconf['denyunknown']))
237
		   $dhcpdconf .= "		deny unknown clients;\n";
238

    
239
		if ($dhcpifconf['gateway'])
240
			$routers = $dhcpifconf['gateway'];
241
		else
242
			$routers = $ifcfg['ipaddr'];
243

    
244
		if($dhcpifconf['failover_peerip'] <> "") {
245
			$dhcpdconf .= "		failover peer \"dhcp{$dhcpnum}\";\n";
246
			$dhcpnum++;
247
		}
248

    
249
		$dhcpdconf .= <<<EOD
250
		range {$dhcpifconf['range']['from']} {$dhcpifconf['range']['to']};
251
	}
252
	option routers {$routers};
253
$dnscfg
254

    
255
EOD;
256
    
257
    		if ($dhcpifconf['defaultleasetime'])
258
			$dhcpdconf .= "	default-lease-time {$dhcpifconf['defaultleasetime']};\n";
259
		if ($dhcpifconf['maxleasetime'])
260
			$dhcpdconf .= "	max-lease-time {$dhcpifconf['maxleasetime']};\n";
261

    
262
		if (is_array($dhcpifconf['winsserver']) && $dhcpifconf['winsserver'][0]) {
263
			$dhcpdconf .= "	option netbios-name-servers " . join(",", $dhcpifconf['winsserver']) . ";\n";
264
			$dhcpdconf .= "	option netbios-node-type 8;\n";
265
		}
266

    
267
		if (is_array($dhcpifconf['ntpserver']) && $dhcpifconf['ntpserver'][0])
268
			$dhcpdconf .= "	option ntp-servers " . join(",", $dhcpifconf['ntpserver']) . ";\n";
269

    
270
		if ($dhcpifconf['tftp'] <> "")
271
			$dhcpdconf .= "	option tftp-server-name \"{$dhcpifconf['tftp']}\";\n";
272

    
273
    if ($dhcpifconf['ldap'] <> "")
274
			$dhcpdconf .= "	option ldap-server \"{$dhcpifconf['ldap']}\";\n";
275

    
276
		if(isset($dhcpifconf['netboot'])) {
277
			if (($dhcpifconf['next-server'] <> "") && ($dhcpifconf['filename'] <> "")) {
278
				$dhcpdconf .= "	next-server {$dhcpifconf['next-server']};\n";
279
				$dhcpdconf .= "	filename \"{$dhcpifconf['filename']}\";\n";
280
			}
281
			if ($dhcpifconf['rootpath'] <> "") {
282
				$dhcpdconf .= "	option root-path \"{$dhcpifconf['rootpath']}\";\n";
283
      }
284
		}
285
		
286
		$dhcpdconf .= <<<EOD
287
}
288

    
289
EOD;
290

    
291
		/* add static mappings */
292
		if (is_array($dhcpifconf['staticmap'])) {
293

    
294
			$i = 0;
295
			foreach ($dhcpifconf['staticmap'] as $sm) {
296
				$dhcpdconf .= <<<EOD
297
host s_{$dhcpif}_{$i} {
298
	hardware ethernet {$sm['mac']};
299

    
300
EOD;
301
				if ($sm['ipaddr'])
302
					$dhcpdconf .= "	fixed-address {$sm['ipaddr']};\n";
303

    
304
				if ($sm['hostname'])
305
					$dhcpdconf .= "	option host-name {$sm['hostname']};\n";
306

    
307
				$dhcpdconf .= "}\n";
308
				$i++;
309
			}
310
		}
311

    
312
		$dhcpdifs[] = get_real_interface($dhcpif);
313
	}
314

    
315
	fwrite($fd, $dhcpdconf);
316
	fclose($fd);
317

    
318
	/* create an empty leases database */
319
	touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases");
320

    
321
	/* fire up dhcpd in a chroot */
322
	mwexec("/usr/local/sbin/dhcpd -user dhcpd -group _dhcp -chroot {$g['dhcpd_chroot_path']} -cf {$g['dhcpd_chroot_path']}/etc/dhcpd.conf " .
323
		join(" ", $dhcpdifs));
324

    
325
	if ($g['booting']) {
326
		print "done.\n";
327
	}
328

    
329
	return 0;
330
}
331

    
332
function services_igmpproxy_configure() {
333
        global $config, $g;
334

    
335
        $iflist = get_configured_interface_list();
336

    
337
        /* kill any running igmpproxy */
338
        killbyname("igmpproxy");
339

    
340
	if (!is_array($config['igmpproxy']['igmpentry']))
341
		return 1;
342

    
343
        $igmpconf = <<<EOD
344

    
345
##------------------------------------------------------
346
## Enable Quickleave mode (Sends Leave instantly)
347
##------------------------------------------------------
348
quickleave
349

    
350
EOD;
351

    
352
        foreach ($config['igmpproxy']['igmpentry'] as $igmpcf) {
353
                unset($iflist[$igmpcf['ifname']]);
354
                $realif = get_real_interface($igmpcf['ifname']);
355
                if (empty($igmpcf['threshold']))
356
                        $threshld = 1;
357
                else
358
                        $threshld = $igmpcf['threshold'];
359
                $igmpconf .= "phyint {$realif} {$igmpcf['type']} ratelimit 0 threshold {$threshld}\n";
360

    
361
                if ($igmpcf['address'] <> "") {
362
                        $item = explode(" ", $igmpcf['address']);
363
                        foreach($item as $iww)
364
                                $igmpconf .= "altnet {$iww}\n";
365
                }
366
                $igmpconf .= "\n";
367
        }
368
        foreach ($iflist as $ifn) {
369
                $realif = get_real_interface($ifn);
370
                $igmpconf .= "phyint {$realif} disabled\n";
371
        }
372

    
373
        $igmpfl = fopen($g['tmp_path'] . "/igmpproxy.conf", "w");
374
        if (!$igmpfl) {
375
                log_error("Could not write Igmpproxy configuration file!");
376
                return;
377
        }
378
        fwrite($igmpfl, $igmpconf);
379
        fclose($igmpfl);
380

    
381
        mwexec("/usr/local/sbin/igmpproxy -c " . $g['tmp_path'] . "/igmpproxy.conf");
382
        log_error("Started Igmpproxy service sucsesfully.");
383

    
384
        return 0;
385
}
386

    
387
function interfaces_staticarp_configure($if) {
388
	global $config, $g;
389
	if(isset($config['system']['developerspew'])) {
390
		$mt = microtime();
391
		echo "interfaces_staticarp_configure($if) being called $mt\n";
392
	}
393

    
394
        $ifcfg = $config['interfaces'][$if];
395

    
396
        /* Enable staticarp, if enabled */
397
        if(isset($config['dhcpd'][$if]['staticarp'])) {
398
                mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " staticarp " );
399
                mwexec("/usr/sbin/arp -ad > /dev/null 2>&1 ");
400
                if (is_array($config['dhcpd'][$if]['staticmap'])) {
401

    
402
                        foreach ($config['dhcpd'][$if]['staticmap'] as $arpent) {
403
                                mwexec("/usr/sbin/arp -s " . escapeshellarg($arpent['ipaddr']) . " " . escapeshellarg($arpent['mac']));
404

    
405
                        }
406

    
407
                }
408
        } else {
409
                mwexec("/sbin/ifconfig " . escapeshellarg($ifcfg['if']) . " -staticarp " );
410
                mwexec("/usr/sbin/arp -da > /dev/null 2>&1 ");
411
        }
412

    
413
        return 0;
414
}
415

    
416
function services_dhcrelay_configure() {
417
	global $config, $g;
418
	if(isset($config['system']['developerspew'])) {
419
		$mt = microtime();
420
		echo "services_dhcrelay_configure() being called $mt\n";
421
	}
422

    
423
	/* kill any running dhcrelay */
424
	killbypid("{$g['varrun_path']}/dhcrelay.pid");
425

    
426
	$dhcrelaycfg = $config['dhcrelay'];
427

    
428
	/* DHCPRelay enabled on any interfaces? */
429
	$dhcrelayenable = false;
430
	if(is_array($dhcrelaycfg)) {
431
		foreach ($dhcrelaycfg as $dhcrelayif => $dhcrelayifconf) {
432
			if (isset($dhcrelayifconf['enable']) &&
433
				(($dhcrelayif == "lan") ||
434
				(isset($config['interfaces'][$dhcrelayif]['enable']) &&
435
				$config['interfaces'][$dhcrelayif]['if'] && (!link_interface_to_bridge($dhcrelayif)))))
436
				$dhcrelayenable = true;
437
		}
438
	}
439

    
440
	if (!$dhcrelayenable)
441
		return 0;
442

    
443
	if ($g['booting'])
444
		echo "Starting DHCP relay service...";
445
	else
446
		sleep(1);
447

    
448
	$dhcrelayifs = array();
449
	foreach ($dhcrelaycfg as $dhcrelayif => $dhcrelayifconf) {
450

    
451
		$ifcfg = $config['interfaces'][$dhcrelayif];
452

    
453
		if (!isset($dhcrelayifconf['enable']) ||
454
			(($dhcrelayif != "lan") &&
455
			(!isset($ifcfg['enable']) || !$ifcfg['if'] || 
456
			link_interface_to_bridge($dhcrelayif))))
457
			continue;
458

    
459
		$dhcrelayifs[] = $ifcfg['if'];
460
	}
461

    
462
	/* In order for the relay to work, it needs to be active on the
463
	   interface in which the destination server sits */
464
	foreach ($config['interfaces'] as $ifname) {
465
		$subnet = $ifname['ipaddr'] . "/" . $ifname['subnet'];
466
		if (ip_in_subnet($dhcrelaycfg['server'],$subnet))
467
			$destif = $ifname['if'];
468
	}
469

    
470
	if (!isset($destif))
471
		$destif = $config['interfaces']['wan']['if'];
472

    
473
	$dhcrelayifs[] = $destif;
474
	$dhcrelayifs = array_unique($dhcrelayifs);
475

    
476
	/* fire up dhcrelay */
477
	$cmd = "/usr/local/sbin/dhcrelay -i " .  join(" -i ", $dhcrelayifs);
478

    
479
	if (isset($dhcrelaycfg['agentoption']))
480
		$cmd .=  " -a -m replace";
481

    
482
	$cmd .= " {$dhcrelaycfg['server']}";
483
	mwexec($cmd);
484

    
485
	if (!$g['booting']) {
486
		/* set the reload filter dity flag */
487
		filter_configure();
488
	}
489

    
490
	return 0;
491
}
492

    
493
function services_dyndns_reset($interface = "wan" ) {
494
	global $config, $g;
495
	if(isset($config['system']['developerspew'])) {
496
		$mt = microtime();
497
		echo "services_dyndns_reset() being called $mt\n";
498
	}
499

    
500
	$dyndnscfg = $config['dyndnses']['dyndns'];
501

    
502
        if (is_array($dyndnscfg)) {
503
                foreach ($dyndnscfg as $dyndns) {
504
                        if (!isset($dyndns['enable']))
505
                                continue;
506
			if ($dyndns['interface'] != $interface)
507
				continue;
508

    
509
                        services_dyndns_configure_client($dyndns);
510

    
511
                        sleep(1);
512
                }
513

    
514
        }
515

    
516
	return 0;
517
}
518

    
519
function services_dyndns_configure_client($conf) {
520

    
521
	/* load up the dyndns.class */
522
	require_once("dyndns.class");
523

    
524
	log_error("DynDns: Running updatedns()");
525

    
526
	$dns = new updatedns($dnsService = $conf['type'],
527
		$dnsHost = $conf['host'],
528
		$dnsUser = $conf['username'],
529
		$dnsPass = $conf['password'],
530
		$dnsWilcard = $conf['wildcard'],
531
		$dnsMX = $conf['mx'], $dnsIf = "{$conf['interface']}");
532

    
533
}
534

    
535
function services_dyndns_configure() {
536
	global $config, $g;
537
	if(isset($config['system']['developerspew'])) {
538
		$mt = microtime();
539
		echo "services_dyndns_configure() being called $mt\n";
540
	}
541

    
542
	$dyndnscfg = $config['dyndnses']['dyndns'];
543

    
544
	if (is_array($dyndnscfg)) {
545
		if ($g['booting']) 
546
			echo "Starting DynDNS clients...";
547

    
548
		foreach ($dyndnscfg as $dyndns) {
549
			if (!isset($dyndns['enable']))
550
				continue;
551

    
552
			services_dyndns_configure_client($dyndns);
553

    
554
			sleep(1);
555
		}
556

    
557
		if ($g['booting'])
558
			echo "done.\n";
559
	}
560

    
561
	return 0;
562
}
563

    
564
function services_dnsmasq_configure() {
565
	global $config, $g;
566
	$return = 0;
567
	
568
	if(isset($config['system']['developerspew'])) {
569
		$mt = microtime();
570
		echo "services_dnsmasq_configure() being called $mt\n";
571
	}
572

    
573
	/* kill any running dnsmasq */
574
	sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", "TERM");
575

    
576
	if (isset($config['dnsmasq']['enable'])) {
577

    
578
		if ($g['booting'])
579
			echo "Starting DNS forwarder...";
580
		else
581
			sleep(1);
582

    
583
		/* generate hosts file */
584
		if(system_hosts_generate()!=0)
585
			$return = 1;
586

    
587
		$args = "";
588

    
589
		if (isset($config['dnsmasq']['regdhcp'])) {
590

    
591
			$args .= " -l {$g['dhcpd_chroot_path']}/var/db/dhcpd.leases" .
592
				" -s {$config['system']['domain']}";
593
		}
594

    
595
                if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
596
                        foreach($config['dnsmasq']['domainoverrides'] as $override) {
597
                                $args .= ' --server=/' . $override['domain'] . '/' . $override['ip'];
598
                        }
599
                }
600

    
601
		/* suppose that dnsmasq handles our domain and don't send
602
		requests for our local domain to upstream servers */
603
		//if (!empty($config['system']['domain'])) {
604
		//	$args .= sprintf(' --local=/%s/', $config['system']['domain']);
605
		//}
606

    
607
		/* run dnsmasq */
608
		mwexec("/usr/local/sbin/dnsmasq --cache-size=5000 {$args}");
609

    
610
		if ($g['booting'])
611
			echo "done.\n";
612
	}
613

    
614
	if (!$g['booting']) {
615
		if(services_dhcpd_configure()!=0)
616
			$return = 1;
617
	}
618

    
619
	return $return;
620
}
621

    
622
function services_snmpd_configure() {
623
	global $config, $g;
624
	if(isset($config['system']['developerspew'])) {
625
		$mt = microtime();
626
		echo "services_snmpd_configure() being called $mt\n";
627
	}
628

    
629
	/* kill any running snmpd */
630
	sigkillbypid("{$g['varrun_path']}/snmpd.pid", "TERM");
631
	if(is_process_running("bsnmpd")) 
632
		mwexec("/usr/bin/killall bsnmpd", true);
633

    
634
	if (isset($config['snmpd']['enable'])) {
635

    
636
		if ($g['booting'])
637
			echo "Starting SNMP daemon... ";
638

    
639
		/* generate snmpd.conf */
640
		$fd = fopen("{$g['varetc_path']}/snmpd.conf", "w");
641
		if (!$fd) {
642
			printf("Error: cannot open snmpd.conf in services_snmpd_configure().\n");
643
			return 1;
644
		}
645

    
646

    
647
		$snmpdconf = <<<EOD
648
location := "{$config['snmpd']['syslocation']}"
649
contact := "{$config['snmpd']['syscontact']}"
650
read := "{$config['snmpd']['rocommunity']}"
651

    
652
EOD;
653

    
654
/* No docs on what write strings do there for disable for now.
655
		if(isset($config['snmpd']['rwenable']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
656
		    $snmpdconf .= <<<EOD
657
# write string
658
write := "{$config['snmpd']['rwcommunity']}"
659

    
660
EOD;
661
		}
662
*/
663

    
664

    
665
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
666
		    $snmpdconf .= <<<EOD
667
# SNMP Trap support.
668
traphost := {$config['snmpd']['trapserver']}
669
trapport := {$config['snmpd']['trapserverport']}
670
trap := "{$config['snmpd']['trapstring']}"
671

    
672

    
673
EOD;
674
		}
675

    
676

    
677
		$snmpdconf .= <<<EOD
678
system := 1     # pfSense
679
%snmpd
680
begemotSnmpdDebugDumpPdus       = 2
681
begemotSnmpdDebugSyslogPri      = 7
682
begemotSnmpdCommunityString.0.1 = $(read)
683

    
684
EOD;
685

    
686
/* No docs on what write strings do there for disable for now.
687
		if(isset($config['snmpd']['rwcommunity']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
688
		    $snmpdconf .= <<<EOD
689
begemotSnmpdCommunityString.0.2 = $(write)
690

    
691
EOD;
692
		}
693
*/
694

    
695

    
696
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
697
		    $snmpdconf .= <<<EOD
698
begemotTrapSinkStatus.[$(traphost)].$(trapport) = 4
699
begemotTrapSinkVersion.[$(traphost)].$(trapport) = 2
700
begemotTrapSinkComm.[$(traphost)].$(trapport) = $(trap)
701

    
702
EOD;
703
		}
704

    
705

    
706
		$snmpdconf .= <<<EOD
707
begemotSnmpdCommunityDisable    = 1
708

    
709
EOD;
710

    
711
		if(isset($config['snmpd']['bindlan'])) {
712
			$bind_to_ip = $config['interfaces']['lan']['ipaddr'];
713
		} else {
714
			$bind_to_ip = "0.0.0.0";
715
		}
716

    
717
		if(is_port( $config['snmpd']['pollport'] )) {
718
		    $snmpdconf .= <<<EOD
719
begemotSnmpdPortStatus.{$bind_to_ip}.{$config['snmpd']['pollport']} = 1
720

    
721
EOD;
722

    
723
		}
724

    
725
		$snmpdconf .= <<<EOD
726
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
727
begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4
728

    
729
# These are bsnmp macros not php vars.
730
sysContact      = $(contact)
731
sysLocation     = $(location)
732
sysObjectId     = 1.3.6.1.4.1.12325.1.1.2.1.$(system)
733

    
734
snmpEnableAuthenTraps = 2
735

    
736
EOD;
737

    
738
		if (is_array( $config['snmpd']['modules'] )) {
739
		    if(isset($config['snmpd']['modules']['mibii'])) {
740
			$snmpdconf .= <<<EOD
741
begemotSnmpdModulePath."mibII"  = "/usr/lib/snmp_mibII.so"
742

    
743
EOD;
744
		    }
745

    
746
		    if(isset($config['snmpd']['modules']['netgraph'])) {
747
			$snmpdconf .= <<<EOD
748
begemotSnmpdModulePath."netgraph" = "/usr/lib/snmp_netgraph.so"
749
%netgraph
750
begemotNgControlNodeName = "snmpd"
751

    
752
EOD;
753
		    }
754

    
755
		    if(isset($config['snmpd']['modules']['pf'])) {
756
			$snmpdconf .= <<<EOD
757
begemotSnmpdModulePath."pf"     = "/usr/lib/snmp_pf.so"
758

    
759
EOD;
760
		    }
761

    
762
		    if(isset($config['snmpd']['modules']['hostres'])) {
763
			$snmpdconf .= <<<EOD
764
begemotSnmpdModulePath."hostres"     = "/usr/lib/snmp_hostres.so"
765

    
766
EOD;
767
		    }
768
		    if(isset($config['snmpd']['modules']['bridge'])) {
769
			$snmpdconf .= <<<EOD
770
begemotSnmpdModulePath."bridge"     = "/usr/lib/snmp_bridge.so"
771
# config must end with blank line
772

    
773

    
774
EOD;
775
		    }
776
		}
777

    
778
		fwrite($fd, $snmpdconf);
779
		fclose($fd);
780

    
781
		if (isset($config['snmpd']['bindlan'])) {
782
			$bindlan = "";
783
		}
784

    
785
		/* run bsnmpd */
786
		mwexec("/usr/sbin/bsnmpd -c {$g['varetc_path']}/snmpd.conf" .
787
			"{$bindlan} -p {$g['varrun_path']}/snmpd.pid");
788

    
789
		if ($g['booting'])
790
			echo "done.\n";
791
	}
792

    
793
	return 0;
794
}
795

    
796
function services_proxyarp_configure() {
797
	global $config, $g;
798
	if(isset($config['system']['developerspew'])) {
799
		$mt = microtime();
800
		echo "services_proxyarp_configure() being called $mt\n";
801
	}
802

    
803
	/* kill any running choparp */
804
	killbyname("choparp");
805

    
806
	if (isset($config['virtualip']) && is_array($config['virtualip']['vip'])) {
807
		$paa = array();
808

    
809
		/* group by interface */
810
		foreach ($config['virtualip']['vip'] as $vipent) {
811
			if ($vipent['mode'] === "proxyarp") {
812
				if ($vipent['interface'])
813
					$if = $vipent['interface'];
814
				else
815
					$if = "wan";
816

    
817
				if (!is_array($paa[$if]))
818
					$paa[$if] = array();
819

    
820
				$paa[$if][] = $vipent;
821
			}
822
		}
823

    
824
		if (count($paa))
825
		foreach ($paa as $paif => $paents) {
826
			if (!(is_ipaddr($config['interfaces'][$paif]['ipaddr'])))
827
                               continue;
828

    
829
			$args = $config['interfaces'][$paif]['if'] . " auto";
830

    
831
			foreach ($paents as $paent) {
832

    
833
				if (isset($paent['subnet']))
834
					$args .= " " . escapeshellarg("{$paent['subnet']}/{$paent['subnet_bits']}");
835
				else if (isset($paent['range']))
836
					$args .= " " . escapeshellarg($paent['range']['from'] . "-" .
837
						$paent['range']['to']);
838
			}
839

    
840
			mwexec_bg("/usr/local/sbin/choparp " . $args);
841
		}
842
	}
843
}
844

    
845
function services_dnsupdate_process() {
846
	global $config, $g;
847
	if(isset($config['system']['developerspew'])) {
848
		$mt = microtime();
849
		echo "services_dnsupdate_process() being called $mt\n";
850
	}
851

    
852
	/* Dynamic DNS updating active? */
853
	if (is_array($config['dnsupdates']['dnsupdate'])) {
854
		foreach ($config['dnsupdates']['dnsupdate'] as $i => $dnsupdate) {
855
		if (!isset($dyndns['enable']))
856
				continue;
857
			/* determine interface name */
858
			if ($dyndns['interface'] == "wan")
859
				$if = get_real_interface();
860
			else
861
				$if = convert_friendly_interface_to_real_interface_name($dyndns['interface']);
862

    
863
			$wanip = get_interface_ip($if);
864
			if ($wanip) {
865

    
866
				$keyname = $dnsupdate['keyname'];
867
				/* trailing dot */
868
				if (substr($keyname, -1) != ".")
869
					$keyname .= ".";
870

    
871
				$hostname = $dnsupdate['host'];
872
				/* trailing dot */
873
				if (substr($hostname, -1) != ".")
874
					$hostname .= ".";
875

    
876
				/* write private key file
877
				   this is dumb - public and private keys are the same for HMAC-MD5,
878
				   but nsupdate insists on having both */
879
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.private", "w");
880
				$privkey .= <<<EOD
881
Private-key-format: v1.2
882
Algorithm: 157 (HMAC)
883
Key: {$dnsupdate['keydata']}
884

    
885
EOD;
886
				fwrite($fd, $privkey);
887
				fclose($fd);
888

    
889
				/* write public key file */
890
				if ($dnsupdate['keytype'] == "zone") {
891
					$flags = 257;
892
					$proto = 3;
893
				} else if ($dnsupdate['keytype'] == "host") {
894
					$flags = 513;
895
					$proto = 3;
896
				} else if ($dnsupdate['keytype'] == "user") {
897
					$flags = 0;
898
					$proto = 2;
899
				}
900

    
901
				$fd = fopen("{$g['varetc_path']}/K{$keyname}+157+00000.key", "w");
902
				fwrite($fd, "{$keyname} IN KEY {$flags} {$proto} 157 {$dnsupdate['keydata']}\n");
903
				fclose($fd);
904

    
905
				/* generate update instructions */
906
				$upinst = "";
907
				if (!empty($dnsupdate['server']))
908
					$upinst .= "server {$dnsupdate['server']}\n";
909
				$upinst .= "update delete {$dnsupdate['host']} A\n";
910
				$upinst .= "update add {$dnsupdate['host']} {$dnsupdate['ttl']} A {$wanip}\n";
911
				$upinst .= "\n";	/* mind that trailing newline! */
912

    
913
				$fd = fopen("{$g['varetc_path']}/nsupdatecmds{$i}", "w");
914
				fwrite($fd, $upinst);
915
				fclose($fd);
916

    
917
				/* invoke nsupdate */
918
				$cmd = "/usr/sbin/nsupdate -k {$g['varetc_path']}/K{$i}{$keyname}+157+00000.key";
919
				if (isset($dnsupdate['usetcp']))
920
					$cmd .= " -v";
921
				$cmd .= " {$g['varetc_path']}/nsupdatecmds{$i}";
922
	
923
				mwexec_bg($cmd);
924
			}
925
		}
926
	}
927

    
928
	return 0;
929
}
930

    
931
function setup_wireless_olsr() {
932
	global $config, $g;
933
	if(!$config['installedpackages']['olsrd'] || !$config['installedpackages'])
934
		return;
935
	if(isset($config['system']['developerspew'])) {
936
		$mt = microtime();
937
		echo "setup_wireless_olsr($interface) being called $mt\n";
938
	}
939
	conf_mount_rw();
940
	foreach($config['installedpackages']['olsrd']['config'] as $olsrd) {
941
		$olsr_enable = $olsrd['enable'];
942
		if($olsr_enable <> "on")
943
			return;
944
		$fd = fopen("{$g['varetc_path']}/olsr.conf", "w");
945

    
946
		if($olsrd['announcedynamicroute'] or $olsrd['enableannounce'] == "on") {
947
			$enableannounce .= "\nHna4\n";
948
			$enableannounce .= "{\n";
949
		if($olsrd['announcedynamicroute'])
950
			$enableannounce .= "\t{$olsrd['announcedynamicroute']}\n";
951
		if($olsrd['enableannounce'] == "on")
952
			$enableannounce .= "0.0.0.0 0.0.0.0";
953
			$enableannounce .= "\n}\n";
954
		} else {
955
			$enableannounce = "";
956
		}
957

    
958
		$olsr .= <<<EODA
959
#
960
# olsr.org OLSR daemon config file
961
#
962
# Lines starting with a # are discarded
963
#
964
# This file was generated by setup_wireless_olsr() in services.inc
965
#
966

    
967
# This file is an example of a typical
968
# configuration for a mostly static
969
# network(regarding mobility) using
970
# the LQ extention
971

    
972
# Debug level(0-9)
973
# If set to 0 the daemon runs in the background
974

    
975
DebugLevel	2
976

    
977
# IP version to use (4 or 6)
978

    
979
IpVersion	4
980

    
981
# Clear the screen each time the internal state changes
982

    
983
ClearScreen     yes
984

    
985
{$enableannounce}
986

    
987
# Should olsrd keep on running even if there are
988
# no interfaces available? This is a good idea
989
# for a PCMCIA/USB hotswap environment.
990
# "yes" OR "no"
991

    
992
AllowNoInt	yes
993

    
994
# TOS(type of service) value for
995
# the IP header of control traffic.
996
# If not set it will default to 16
997

    
998
#TosValue	16
999

    
1000
# The fixed willingness to use(0-7)
1001
# If not set willingness will be calculated
1002
# dynamically based on battery/power status
1003
# if such information is available
1004

    
1005
#Willingness    	4
1006

    
1007
# Allow processes like the GUI front-end
1008
# to connect to the daemon.
1009

    
1010
IpcConnect
1011
{
1012
     # Determines how many simultaneously
1013
     # IPC connections that will be allowed
1014
     # Setting this to 0 disables IPC
1015

    
1016
     MaxConnections  0
1017

    
1018
     # By default only 127.0.0.1 is allowed
1019
     # to connect. Here allowed hosts can
1020
     # be added
1021

    
1022
     Host            127.0.0.1
1023
     #Host            10.0.0.5
1024

    
1025
     # You can also specify entire net-ranges
1026
     # that are allowed to connect. Multiple
1027
     # entries are allowed
1028

    
1029
     #Net             192.168.1.0 255.255.255.0
1030
}
1031

    
1032
# Wether to use hysteresis or not
1033
# Hysteresis adds more robustness to the
1034
# link sensing but delays neighbor registration.
1035
# Used by default. 'yes' or 'no'
1036

    
1037
UseHysteresis	no
1038

    
1039
# Hysteresis parameters
1040
# Do not alter these unless you know
1041
# what you are doing!
1042
# Set to auto by default. Allowed
1043
# values are floating point values
1044
# in the interval 0,1
1045
# THR_LOW must always be lower than
1046
# THR_HIGH.
1047

    
1048
#HystScaling	0.50
1049
#HystThrHigh	0.80
1050
#HystThrLow	0.30
1051

    
1052

    
1053
# Link quality level
1054
# 0 = do not use link quality
1055
# 1 = use link quality for MPR selection
1056
# 2 = use link quality for MPR selection and routing
1057
# Defaults to 0
1058

    
1059
LinkQualityLevel	{$olsrd['enablelqe']}
1060

    
1061
# Link quality window size
1062
# Defaults to 10
1063

    
1064
LinkQualityWinSize	10
1065

    
1066
# Polling rate in seconds(float).
1067
# Default value 0.05 sec
1068

    
1069
Pollrate	0.05
1070

    
1071

    
1072
# TC redundancy
1073
# Specifies how much neighbor info should
1074
# be sent in TC messages
1075
# Possible values are:
1076
# 0 - only send MPR selectors
1077
# 1 - send MPR selectors and MPRs
1078
# 2 - send all neighbors
1079
#
1080
# defaults to 0
1081

    
1082
TcRedundancy	2
1083

    
1084
#
1085
# MPR coverage
1086
# Specifies how many MPRs a node should
1087
# try select to reach every 2 hop neighbor
1088
#
1089
# Can be set to any integer >0
1090
#
1091
# defaults to 1
1092

    
1093
MprCoverage	3
1094

    
1095
# Example plugin entry with parameters:
1096

    
1097
EODA;
1098

    
1099
if($olsrd['enablehttpinfo'] == "on") {
1100
	$olsr .= <<<EODB
1101

    
1102
LoadPlugin "/usr/local/lib/olsrd_httpinfo.so.0.1"
1103
{
1104
    PlParam     "port"   "{$olsrd['port']}"
1105
    PlParam     "Net"    "{$olsrd['allowedhttpinfohost']} {$olsrd['allowedhttpinfosubnet']}"
1106
}
1107

    
1108
EODB;
1109

    
1110
}
1111

    
1112
if($olsrd['enabledsecure'] == "on") {
1113
	$olsr .= <<<EODC
1114

    
1115
LoadPlugin "/usr/local/lib/olsrd_secure.so.0.5"
1116
{
1117
    PlParam     "Keyfile"   "/usr/local/etc/olsrkey.txt"
1118
}
1119

    
1120
EODC;
1121

    
1122
}
1123

    
1124
if($olsrd['enabledyngw'] == "on") {
1125

    
1126
	/* unset default route, olsr auto negotiates */
1127
	mwexec("/sbin/route delete default");
1128

    
1129
	$olsr .= <<<EODE
1130

    
1131
LoadPlugin "/usr/local/lib/olsrd_dyn_gw.so.0.4"
1132
{
1133
    # how often to look for a inet gw, in seconds
1134
    # defaults to 5 secs, if commented out
1135
    PlParam     "Interval"   "{$olsrd['polling']}"
1136

    
1137
    # if one or more IPv4 addresses are given, do a ping on these in
1138
    # descending order to validate that there is not only an entry in
1139
    # routing table, but also a real internet connection. If any of
1140
    # these addresses could be pinged successfully, the test was
1141
    # succesful, i.e. if the ping on the 1st address was successful,the
1142
    # 2nd won't be pinged
1143
    PlParam     "Ping"       "{$olsrd['ping']}"
1144
    #PlParam     "HNA"   "192.168.81.0 255.255.255.0"
1145
}
1146

    
1147
EODE;
1148

    
1149
}
1150

    
1151
foreach($config['installedpackages']['olsrd']['config'] as $conf) {
1152
	$interfaces = explode(',', $conf['iface_array']);
1153
	foreach($interfaces as $interface) {
1154
		$realinterface = convert_friendly_interface_to_real_interface_name($interface);
1155
$olsr .= <<<EODAD
1156
Interface "{$realinterface}"
1157
{
1158

    
1159
    # Hello interval in seconds(float)
1160
    HelloInterval    2.0
1161

    
1162
    # HELLO validity time
1163
    HelloValidityTime	20.0
1164

    
1165
    # TC interval in seconds(float)
1166
    TcInterval        5.0
1167

    
1168
    # TC validity time
1169
    TcValidityTime	30.0
1170

    
1171
    # MID interval in seconds(float)
1172
    MidInterval	5.0
1173

    
1174
    # MID validity time
1175
    MidValidityTime	30.0
1176

    
1177
    # HNA interval in seconds(float)
1178
    HnaInterval	5.0
1179

    
1180
    # HNA validity time
1181
    HnaValidityTime 	30.0
1182

    
1183
    # When multiple links exist between hosts
1184
    # the weight of interface is used to determine
1185
    # the link to use. Normally the weight is
1186
    # automatically calculated by olsrd based
1187
    # on the characteristics of the interface,
1188
    # but here you can specify a fixed value.
1189
    # Olsrd will choose links with the lowest value.
1190

    
1191
    # Weight 0
1192

    
1193

    
1194
}
1195

    
1196
EODAD;
1197

    
1198
	}
1199
	break;
1200
}
1201
		fwrite($fd, $olsr);
1202
		fclose($fd);
1203
	}
1204

    
1205
	if(is_process_running("olsrd"))
1206
		mwexec("/usr/bin/killall olsrd", true);
1207

    
1208
	sleep(2);
1209

    
1210
	mwexec_bg("/usr/local/sbin/olsrd -f {$g['varetc_path']}/olsr.conf");
1211

    
1212
	conf_mount_ro();
1213
}
1214

    
1215
/* configure cron service */
1216
function configure_cron() {
1217
	global $g, $config;
1218
	conf_mount_rw();
1219
	/* preserve existing crontab entries */
1220
	$crontab_contents = file_get_contents("/etc/crontab");
1221
	$crontab_contents_a = split("\n", $crontab_contents);
1222
	
1223
	for ($i = 0; $i < count($crontab_contents_a); $i++) {
1224
		$item =& $crontab_contents_a[$i];
1225
		if (strpos($item, "# pfSense specific crontab entries") !== false) {
1226
			array_splice($crontab_contents_a, $i - 1);
1227
			break;
1228
		}
1229
	}
1230
	$crontab_contents = implode("\n", $crontab_contents_a) . "\n";
1231
	
1232
	
1233
	if (is_array($config['cron']['item'])) {
1234
		$crontab_contents .= "#\n";
1235
		$crontab_contents .= "# pfSense specific crontab entries\n";
1236
		$crontab_contents .= "# Created: " . date("F j, Y, g:i a") . "\n";
1237
		$crontab_contents .= "#\n";
1238

    
1239
		foreach ($config['cron']['item'] as $item) {
1240
			$crontab_contents .= "\n{$item['minute']}\t";
1241
			$crontab_contents .= "{$item['hour']}\t";
1242
			$crontab_contents .= "{$item['mday']}\t";
1243
			$crontab_contents .= "{$item['month']}\t";
1244
			$crontab_contents .= "{$item['wday']}\t";
1245
			$crontab_contents .= "{$item['who']}\t";
1246
			$crontab_contents .= "{$item['command']}";
1247
		}
1248
    
1249
		$crontab_contents .= "\n#\n";
1250
		$crontab_contents .= "# If possible do not add items to this file manually.\n";
1251
		$crontab_contents .= "# If you do so, this file must be terminated with a blank line (e.g. new line)\n";
1252
		$crontab_contents .= "#\n\n";
1253
	}
1254
	
1255
	/* please maintain the newline at the end of file */
1256
	file_put_contents("/etc/crontab", $crontab_contents);
1257
	
1258
	if (!$g['booting'])
1259
		conf_mount_ro();
1260
}
1261

    
1262
function upnp_action ($action) {
1263
	switch($action) {
1264
		case "start":
1265
			if(file_exists('/var/etc/miniupnpd.conf'))
1266
				mwexec_bg('/usr/local/sbin/miniupnpd -f /var/etc/miniupnpd.conf');
1267
			break;
1268
		case "stop":
1269
			while((int)exec("pgrep miniupnpd | wc -l") > 0)
1270
				mwexec('killall miniupnpd 2>/dev/null', true);
1271
			mwexec('/sbin/pfctl -aminiupnpd -Fr 2>&1 >/dev/null');
1272
			mwexec('/sbin/pfctl -aminiupnpd -Fn 2>&1 >/dev/null');
1273
			break;
1274
		case "restart":
1275
			upnp_action('stop');
1276
			upnp_action('start');
1277
			break;
1278
	}
1279
}
1280

    
1281
function upnp_start() {
1282
	global $config, $g;
1283
	if($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
1284
		if($g['booting']) {
1285
			echo "Starting UPnP service... ";
1286
			include('/usr/local/pkg/miniupnpd.inc');
1287
			sync_package_miniupnpd();
1288
			echo "done.\n";
1289
		}
1290
		else {
1291
			upnp_action('start');
1292
		}
1293
	}
1294
}
1295

    
1296
?>
(29-29/39)