Project

General

Profile

Download (36 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	services.inc
5
	part of the pfSense project (http://www.pfsense.com)
6

    
7
	originally part of m0n0wall (http://m0n0.ch/wall)
8
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
9
	Copyright (C) 2010	Ermal Lu?i
10
	All rights reserved.
11

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

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

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

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

    
34
/*
35
	pfSense_BUILDER_BINARIES:	/usr/bin/killall	/bin/pgrep	/bin/sh	/usr/local/sbin/dhcpd	/usr/local/sbin/igmpproxy
36
	pfSense_BUILDER_BINARIES:	/sbin/ifconfig	/usr/sbin/arp	/sbin/ifconfig	/usr/local/sbin/dnsmasq
37
	pfSense_BUILDER_BINARIES:	/usr/sbin/bsnmpd	/sbin/route	/usr/local/sbin/olsrd
38
	pfSense_BUILDER_BINARIES:	/usr/local/sbin/miniupnpd	
39
	pfSense_MODULE:	utils
40
*/
41

    
42
function services_dhcpd_configure() {
43
	global $config, $g;
44
	
45
	if($g['services_dhcp_server_enable'] == false) 
46
		return;
47

    
48
	if(isset($config['system']['developerspew'])) {
49
		$mt = microtime();
50
		echo "services_dhcpd_configure($if) being called $mt\n";
51
	}
52
	
53
	/* kill any running dhcpd */
54
	if(is_process_running("dhcpd"))
55
		mwexec("killall dhcpd", true);
56

    
57
	/* DHCP enabled on any interfaces? */
58
	if (!is_dhcp_server_enabled())
59
		return 0;
60

    
61
	/* if OLSRD is enabled, allow WAN to house DHCP. */
62
	if($config['installedpackages']['olsrd'])
63
		foreach($config['installedpackages']['olsrd']['config'] as $olsrd)
64
				if($olsrd['enable'])
65
					$is_olsr_enabled = true;
66

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

    
88
	if ($g['booting']) {
89
		if ($g['platform'] != "pfSense") {
90
			/* restore the leases, if we have them */
91
			if (file_exists("{$g['cf_conf_path']}/dhcpleases.tgz")) {
92
				$dhcprestore = "";
93
				$dhcpreturn = "";
94
				exec("cd /;LANG=C /usr/bin/tar -xzf {$g['cf_conf_path']}/dhcpleases.tgz 2>&1", $dhcprestore, $dhcpreturn);
95
				$dhcprestore = implode(" ", $dhcprestore);
96
				if($dhcpreturn <> 0) {
97
					log_error("DHCP leases restore failed exited with $dhcpreturn, the error is: $dhcprestore\n");
98
				}
99
			}
100
		}
101
	}
102

    
103
	$syscfg = $config['system'];
104
	$dhcpdcfg = $config['dhcpd'];
105
	$Iflist = get_configured_interface_list();
106
		
107
	if ($g['booting'])
108
		echo "Starting DHCP service...";
109
	else
110
		sleep(1);
111

    
112
	/* write dhcpd.conf */
113
	$fd = fopen("{$g['dhcpd_chroot_path']}/etc/dhcpd.conf", "w");
114
	if (!$fd) {
115
		printf("Error: cannot open dhcpd.conf in services_dhcpd_configure().\n");
116
		return 1;
117
	}
118

    
119
	$custoptions = "";
120
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {	
121
		if(is_array($dhcpifconf['numberoptions']) && is_array($dhcpifconf['numberoptions']['item'])) {
122
			foreach($dhcpifconf['numberoptions']['item'] as $itemidx => $item) {
123
				if(!empty($item['type']))
124
					$itemtype = $item['type'];
125
				else
126
					$itemtype = "text";
127
				$custoptions .= "option custom-{$dhcpif}-{$itemidx} code {$item['number']} = {$itemtype};\n";
128
			}
129
		}
130
	}
131

    
132
	$dhcpdconf = <<<EOD
133
	
134
option domain-name "{$syscfg['domain']}";
135
option ldap-server code 95 = text;
136
option domain-search-list code 119 = text;
137
{$custoptions}
138
default-lease-time 7200;
139
max-lease-time 86400;
140
log-facility local7;
141
ddns-update-style none;
142
one-lease-per-client true;
143
deny duplicates;
144
ping-check true;
145

    
146
EOD;
147

    
148
	if(!isset($dhcpifconf['disableauthoritative']))
149
		$dhcpdconf .= "authoritative;\n";
150

    
151
	if(isset($dhcpifconf['alwaysbroadcast'])) 
152
		$dhcpdconf .= "always-broadcast on\n";
153

    
154
	$dhcpdifs = array();
155

    
156
	/*    loop through and determine if we need to setup
157
	 *    failover peer "bleh" entries
158
	 */
159
	$dhcpnum = 0;
160
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
161

    
162
		interfaces_staticarp_configure($dhcpif);
163

    
164
		if (!isset($dhcpifconf['enable']))
165
			continue;
166

    
167
		if($dhcpifconf['failover_peerip'] <> "") {
168
			$int = guess_interface_from_ip($dhcpifconf['failover_peerip']);
169
			$intip = find_interface_ip($int);
170
			$real_dhcpif = convert_friendly_interface_to_real_interface_name($dhcpif);
171
			/*
172
			 *    yep, failover peer is defined.
173
			 *    does it match up to a defined vip?
174
			 */
175
			$skew = 110;
176
			$a_vip = &$config['virtualip']['vip'];
177
			if(is_array($a_vip)) {
178
				foreach ($a_vip as $vipent) {
179
					if($int == $real_dhcpif) {
180
						/* this is the interface! */
181
						if(is_numeric($vipent['advskew']) && ($vipent['advskew'] < "20"))
182
							$skew = 0;
183
					}
184
				}
185
			} else {
186
				log_error("Warning!  DHCP Failover setup and no CARP virtual IP's defined!");
187
			}
188
			if($skew > 10) {
189
				$type = "secondary";
190
				$dhcpdconf_pri  = "mclt 600;\n";
191
				$my_port = "520";
192
				$peer_port = "519";
193
			} else {
194
				$my_port = "519";
195
				$peer_port = "520";
196
				$type = "primary";
197
				$dhcpdconf_pri  = "split 128;\n";
198
				$dhcpdconf_pri .= "  mclt 600;\n";
199
			}
200
			$dhcpdconf .= <<<EOPP
201
failover peer "dhcp{$dhcpnum}" {
202
  {$type};
203
  address {$intip};
204
  port {$my_port};
205
  peer address {$dhcpifconf['failover_peerip']};
206
  peer port {$peer_port};
207
  max-response-delay 10;
208
  max-unacked-updates 10;
209
  {$dhcpdconf_pri}
210
  load balance max seconds 3;
211
}
212

    
213
EOPP;
214
		$dhcpnum++;
215
		}
216
	}
217

    
218
	$dhcpnum = 0;
219

    
220
	foreach ($dhcpdcfg as $dhcpif => $dhcpifconf) {
221

    
222
		$ifcfg = $config['interfaces'][$dhcpif];
223

    
224
		if (!isset($dhcpifconf['enable']) || !isset($Iflist[$dhcpif]))
225
			continue;
226
		$ifcfgip = get_interface_ip($dhcpif);
227
		$ifcfgsn = get_interface_subnet($dhcpif);
228
		$subnet = gen_subnet($ifcfgip, $ifcfgsn);
229
		$subnetmask = gen_subnet_mask($ifcfgsn);
230

    
231
		if (!is_ipaddr($subnet))
232
			continue;
233

    
234
		if($is_olsr_enabled == true)
235
			if($dhcpifconf['netmask'])
236
				$subnetmask = gen_subnet_mask($dhcpifconf['netmask']);
237

    
238
		$dnscfg = "";
239

    
240
		if ($dhcpifconf['domain']) {
241
			$dnscfg .= "	option domain-name \"{$dhcpifconf['domain']}\";\n";
242
		}
243
		
244
    		if($dhcpifconf['domainsearchlist'] <> "") {
245
			$dnscfg .= "	option domain-search-list \"{$dhcpifconf['domainsearchlist']}\";\n";
246
    		}
247

    
248
		if (isset($dhcpifconf['ddnsupdate'])) {
249
			if($dhcpifconf['ddnsdomain'] <> "") {
250
				$dnscfg .= "	ddns-domainname \"{$dhcpifconf['ddnsdomain']}\";\n";
251
			}
252
			$dnscfg .= "	ddns-update-style interim;\n";
253
		}
254

    
255
		if (is_array($dhcpifconf['dnsserver']) && ($dhcpifconf['dnsserver'][0])) {
256
			$dnscfg .= "	option domain-name-servers " . join(",", $dhcpifconf['dnsserver']) . ";";
257
		} else if (isset($config['dnsmasq']['enable'])) {
258
			$dnscfg .= "	option domain-name-servers {$ifcfgip};";
259
		} else if (is_array($syscfg['dnsserver']) && ($syscfg['dnsserver'][0])) {
260
			$dnscfg .= "	option domain-name-servers " . join(",", $syscfg['dnsserver']) . ";";
261
		}
262

    
263
		$dhcpdconf .= "subnet {$subnet} netmask {$subnetmask} {\n";
264
		$dhcpdconf .= "	pool {\n";
265

    
266
		/* is failover dns setup? */
267
		if (is_array($dhcpifconf['dnsserver']) && $dhcpifconf['dnsserver'][0] <> "") {
268
			$dhcpdconf .= "		option domain-name-servers {$dhcpifconf['dnsserver'][0]}";
269
			if($dhcpifconf['dnsserver'][1] <> "")
270
				$dhcpdconf .= ",{$dhcpifconf['dnsserver'][1]}";
271
			$dhcpdconf .= ";\n";
272
		}
273

    
274
		if($dhcpifconf['failover_peerip'] <> "")
275
			$dhcpdconf .= "		deny dynamic bootp clients;\n";
276

    
277
		if (isset($dhcpifconf['denyunknown']))
278
		   $dhcpdconf .= "		deny unknown-clients;\n";
279

    
280
		if ($dhcpifconf['gateway'])
281
			$routers = $dhcpifconf['gateway'];
282
		else
283
			$routers = $ifcfgip;
284

    
285
		if($dhcpifconf['failover_peerip'] <> "") {
286
			$dhcpdconf .= "		failover peer \"dhcp{$dhcpnum}\";\n";
287
			$dhcpnum++;
288
		}
289

    
290
		$dhcpdconf .= <<<EOD
291
		range {$dhcpifconf['range']['from']} {$dhcpifconf['range']['to']};
292
	}
293
	option routers {$routers};
294
$dnscfg
295

    
296
EOD;
297
    
298
		// default-lease-time
299
		if ($dhcpifconf['defaultleasetime'])
300
			$dhcpdconf .= "	default-lease-time {$dhcpifconf['defaultleasetime']};\n";
301

    
302
		// max-lease-time
303
		if ($dhcpifconf['maxleasetime'])
304
			$dhcpdconf .= "	max-lease-time {$dhcpifconf['maxleasetime']};\n";
305

    
306
		// netbios-name*
307
		if (is_array($dhcpifconf['winsserver']) && $dhcpifconf['winsserver'][0]) {
308
			$dhcpdconf .= "	option netbios-name-servers " . join(",", $dhcpifconf['winsserver']) . ";\n";
309
			$dhcpdconf .= "	option netbios-node-type 8;\n";
310
		}
311

    
312
		// ntp-servers
313
		if (is_array($dhcpifconf['ntpserver']) && $dhcpifconf['ntpserver'][0])
314
			$dhcpdconf .= "	option ntp-servers " . join(",", $dhcpifconf['ntpserver']) . ";\n";
315

    
316
		// tftp-server-name
317
		if ($dhcpifconf['tftp'] <> "")
318
			$dhcpdconf .= "	option tftp-server-name \"{$dhcpifconf['tftp']}\";\n";
319

    
320
		// Handle option, number rowhelper values
321
		$dhcpdconf .= "\n";
322
		if($dhcpifconf['numberoptions']['item']) {
323
			foreach($dhcpifconf['numberoptions']['item'] as $itemidx => $item) {
324
				if(empty($item['type']) || $item['type'] == "text")
325
					$dhcpdconf .= "	option custom-{$dhcpif}-{$itemidx} \"{$item['value']}\";\n";
326
				else
327
					$dhcpdconf .= "	option custom-{$dhcpif}-{$itemidx} {$item['value']};\n";
328
			}
329
		}
330

    
331
		// ldap-server
332
		if ($dhcpifconf['ldap'] <> "")
333
			$dhcpdconf .= "	option ldap-server \"{$dhcpifconf['ldap']}\";\n";
334

    
335
		// net boot information
336
		if(isset($dhcpifconf['netboot'])) {
337
			if (($dhcpifconf['next-server'] <> "") && ($dhcpifconf['filename'] <> "")) {
338
				$dhcpdconf .= "	next-server {$dhcpifconf['next-server']};\n";
339
				$dhcpdconf .= "	filename \"{$dhcpifconf['filename']}\";\n";
340
			}
341
			if ($dhcpifconf['rootpath'] <> "") {
342
				$dhcpdconf .= "	option root-path \"{$dhcpifconf['rootpath']}\";\n";
343
      		}
344
		}
345
		
346
		$dhcpdconf .= <<<EOD
347
}
348

    
349
EOD;
350

    
351
		/* add static mappings */
352
		if (is_array($dhcpifconf['staticmap'])) {
353

    
354
			$i = 0;
355
			foreach ($dhcpifconf['staticmap'] as $sm) {
356
				$dhcpdconf .= <<<EOD
357
host s_{$dhcpif}_{$i} {
358
	hardware ethernet {$sm['mac']};
359

    
360
EOD;
361
				if ($sm['ipaddr'])
362
					$dhcpdconf .= "	fixed-address {$sm['ipaddr']};\n";
363

    
364
				if ($sm['hostname']) {
365
					$dhhostname = str_replace(" ", "_", $sm['hostname']);
366
					$dhhostname = str_replace(".", "_", $dhhostname);
367
					$dhcpdconf .= "	option host-name \"{$dhhostname}\";\n";
368
				}
369
				if ($sm['netbootfile'])
370
					$dhcpdconf .= "	filename \"{$sm['netbootfile']}\";\n";
371

    
372
				$dhcpdconf .= "}\n";
373
				$i++;
374
			}
375
		}
376

    
377
		$dhcpdifs[] = get_real_interface($dhcpif);
378
	}
379

    
380
	fwrite($fd, $dhcpdconf);
381
	fclose($fd);
382

    
383
	/* create an empty leases database */
384
	touch("{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases");
385
	touch("{$g['varrun_path']}/dhcpd.pid");
386
	
387

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

    
392
	if ($g['booting']) {
393
		print "done.\n";
394
	}
395

    
396
	return 0;
397
}
398

    
399
function services_igmpproxy_configure() {
400
        global $config, $g;
401

    
402
        /* kill any running igmpproxy */
403
        killbyname("igmpproxy");
404

    
405
	if (!is_array($config['igmpproxy']['igmpentry']))
406
		return 1;
407

    
408
        $iflist = get_configured_interface_list();
409

    
410
        $igmpconf = <<<EOD
411

    
412
##------------------------------------------------------
413
## Enable Quickleave mode (Sends Leave instantly)
414
##------------------------------------------------------
415
quickleave
416

    
417
EOD;
418

    
419
        foreach ($config['igmpproxy']['igmpentry'] as $igmpcf) {
420
                unset($iflist[$igmpcf['ifname']]);
421
                $realif = get_real_interface($igmpcf['ifname']);
422
                if (empty($igmpcf['threshold']))
423
                        $threshld = 1;
424
                else
425
                        $threshld = $igmpcf['threshold'];
426
                $igmpconf .= "phyint {$realif} {$igmpcf['type']} ratelimit 0 threshold {$threshld}\n";
427

    
428
                if ($igmpcf['address'] <> "") {
429
                        $item = explode(" ", $igmpcf['address']);
430
                        foreach($item as $iww)
431
                                $igmpconf .= "altnet {$iww}\n";
432
                }
433
                $igmpconf .= "\n";
434
        }
435
        foreach ($iflist as $ifn) {
436
                $realif = get_real_interface($ifn);
437
                $igmpconf .= "phyint {$realif} disabled\n";
438
        }
439
	$igmpconf .= "\n";
440

    
441
        $igmpfl = fopen($g['tmp_path'] . "/igmpproxy.conf", "w");
442
        if (!$igmpfl) {
443
                log_error("Could not write Igmpproxy configuration file!");
444
                return;
445
        }
446
        fwrite($igmpfl, $igmpconf);
447
        fclose($igmpfl);
448

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

    
452
        return 0;
453
}
454

    
455
function services_dhcrelay_configure() {
456
	global $config, $g;
457
	if(isset($config['system']['developerspew'])) {
458
		$mt = microtime();
459
		echo "services_dhcrelay_configure() being called $mt\n";
460
	}
461

    
462
	/* kill any running dhcrelay */
463
	killbypid("{$g['varrun_path']}/dhcrelay.pid");
464

    
465
	$dhcrelaycfg =& $config['dhcrelay'];
466

    
467
	/* DHCPRelay enabled on any interfaces? */
468
	if (!isset($dhcrelaycfg['enable']))
469
		return 0;
470

    
471
	if ($g['booting'])
472
		echo "Starting DHCP relay service...";
473
	else
474
		sleep(1);
475

    
476
	$iflist = get_configured_interface_list();
477

    
478
	$dhcifaces = explode(",", $dhcrelaycfg['interface']);
479
	foreach ($dhcifaces as $dhcrelayif) {
480
		if (!isset($iflist[$dhcrelayif]) ||
481
			link_interface_to_bridge($dhcrelayif))
482
			continue;
483

    
484
		if (is_ipaddr(get_interface_ip($dhcrelayif)))
485
			$dhcrelayifs[] = get_real_interface($dhcrelayif);
486
	}
487

    
488
	/* 
489
	 * In order for the relay to work, it needs to be active
490
	 * on the interface in which the destination server sits.
491
	 */
492
	$srvips = explode(",", $dhcrelaycfg['server']);
493
	foreach ($srvips as $srcidx => $srvip) {
494
		unset($destif);
495
		foreach ($iflist as $ifname) {
496
			$subnet = get_interface_ip($ifname);
497
			if (!is_ipaddr($subnet))
498
				continue;
499
			$subnet .=  "/" . get_interface_subnet($ifname);
500
			if (ip_in_subnet($srvip, $subnet)) {
501
				$destif = get_real_interface($ifname);
502
				break;
503
			}
504
		}
505
		if (!isset($destif)) {
506
			if (is_array($config['staticroutes']['route'])) {
507
				foreach ($config['staticroutes']['route'] as $rtent) {
508
					if (ip_in_subnet($srvip, $rtent['network'])) {
509
						$a_gateways = return_gateways_array(true);
510
						$destif = $a_gateways[$rtent['gateway']]['interface'];
511
						break;
512
					}
513
				}
514
			}
515
		}
516

    
517
		if (!isset($destif)) {
518
			/* Create a array from the existing route table */
519
        		exec("/usr/bin/netstat -rnWf inet", $route_str);
520
        		array_shift($route_str);
521
        		array_shift($route_str);
522
        		array_shift($route_str);
523
        		array_shift($route_str);
524
        		$route_arr = array();
525
        		foreach($route_str as $routeline) {
526
                		$items = preg_split("/[ ]+/i", $routeline);
527
				if (ip_in_subnet($srvip, $items[0])) {
528
					$destif = trim($items[6]);
529
					break;
530
				}
531
        		}
532
		}
533
	
534
		if (!isset($destif)) {
535
			if (is_array($config['gateways']['gateway_item'])) {
536
				foreach ($config['gateways']['gateway_item'] as $gateway) {
537
					if (isset($gateway['defaultgw'])) {
538
						$a_gateways = return_gateways_array(true);
539
                                        	$destif = $a_gateways[$rtent['gateway']]['interface'];
540
						break;
541
					}		
542
				}
543
			} else
544
				$destif = get_real_interface("wan");
545
		}
546

    
547
		if (!empty($destif))
548
			$dhcrelayifs[] = $destif;
549
	}
550
	$dhcrelayifs = array_unique($dhcrelayifs);
551

    
552
	/* fire up dhcrelay */
553
	if (empty($dhcrelayifs)) {
554
		log_error("No suitable interface found for running dhcrelay!");
555
		return; /* XXX */
556
	}
557

    
558
	$cmd = "/usr/local/sbin/dhcrelay -i " .  implode(" -i ", $dhcrelayifs);
559

    
560
	if (isset($dhcrelaycfg['agentoption']))
561
		$cmd .=  " -a -m replace";
562

    
563
	$cmd .= " " . implode(" ", $srvips);
564
	mwexec($cmd);
565

    
566
	return 0;
567
}
568

    
569
function services_dyndns_configure_client($conf) {
570

    
571
	if (!isset($conf['enable']))
572
		return;
573

    
574
	/* load up the dyndns.class */
575
	require_once("dyndns.class");
576

    
577
	$dns = new updatedns($dnsService = $conf['type'],
578
		$dnsHost = $conf['host'],
579
		$dnsUser = $conf['username'],
580
		$dnsPass = $conf['password'],
581
		$dnsWilcard = $conf['wildcard'],
582
		$dnsMX = $conf['mx'], 
583
		$dnsIf = "{$conf['interface']}");
584
}
585

    
586
function services_dyndns_configure($int = "") {
587
	global $config, $g;
588
	if(isset($config['system']['developerspew'])) {
589
		$mt = microtime();
590
		echo "services_dyndns_configure() being called $mt\n";
591
	}
592

    
593
	$dyndnscfg = $config['dyndnses']['dyndns'];
594

    
595
	if (is_array($dyndnscfg)) {
596
		if ($g['booting']) 
597
			echo "Starting DynDNS clients...";
598

    
599
		foreach ($dyndnscfg as $dyndns) {
600
			if (!empty($int) && $int != $dyndns['interface'])
601
				continue;
602

    
603
			services_dyndns_configure_client($dyndns);
604

    
605
			sleep(1);
606
		}
607

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

    
612
	return 0;
613
}
614

    
615
function services_dnsmasq_configure() {
616
	global $config, $g;
617
	$return = 0;
618
	
619
	if(isset($config['system']['developerspew'])) {
620
		$mt = microtime();
621
		echo "services_dnsmasq_configure() being called $mt\n";
622
	}
623

    
624
	/* kill any running dnsmasq */
625
	if (file_exists("{$g['varrun_path']}/dnsmasq.pid"))
626
		sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", "TERM");
627

    
628
	if (isset($config['dnsmasq']['enable'])) {
629

    
630
		if ($g['booting'])
631
			echo "Starting DNS forwarder...";
632
		else
633
			sleep(1);
634

    
635
		/* generate hosts file */
636
		if(system_hosts_generate()!=0)
637
			$return = 1;
638

    
639
		$args = "";
640

    
641
		if (isset($config['dnsmasq']['regdhcp'])) {
642
			$args .= " --dhcp-hostsfile={$g['varetc_path']}/hosts ";
643
		}
644
		
645
		/* Setup forwarded domains */
646
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
647
			foreach($config['dnsmasq']['domainoverrides'] as $override) {
648
			        $args .= ' --server=/' . $override['domain'] . '/' . $override['ip'];
649
			}
650
		}
651

    
652
		/* Allow DNS Rebind for forwarded domains */
653
		if (isset($config['dnsmasq']['domainoverrides']) && is_array($config['dnsmasq']['domainoverrides'])) {
654
			if(!isset($config['system']['webgui']['nodnsrebindcheck'])) {
655
				foreach($config['dnsmasq']['domainoverrides'] as $override) {
656
					$args .= ' --rebind-domain-ok=/' . $override['domain'] . '/ ';
657
				}
658
			}
659
		}
660

    
661
		if(!isset($config['system']['webgui']['nodnsrebindcheck']))
662
			$dns_rebind = "--rebind-localhost-ok --stop-dns-rebind";
663

    
664
		if ($config['dnsmasq']['custom_options']) {
665
			foreach (preg_split('/\s+/', $config['dnsmasq']['custom_options']) as $c)
666
				$args .= " --$c";
667
		}
668

    
669
		/* run dnsmasq */
670
		mwexec_bg("/usr/local/sbin/dnsmasq --local-ttl 1 --all-servers {$dns_rebind} --dns-forward-max=5000 --cache-size=10000 {$args}");
671

    
672
		if ($g['booting'])
673
			echo "done.\n";
674
	}
675

    
676
	if (!$g['booting']) {
677
		if(services_dhcpd_configure()!=0)
678
			$return = 1;
679
	}
680

    
681
	return $return;
682
}
683

    
684
function services_snmpd_configure() {
685
	global $config, $g;
686
	if(isset($config['system']['developerspew'])) {
687
		$mt = microtime();
688
		echo "services_snmpd_configure() being called $mt\n";
689
	}
690

    
691
	/* kill any running snmpd */
692
	sigkillbypid("{$g['varrun_path']}/snmpd.pid", "TERM");
693
	sleep(2);
694
	if(is_process_running("bsnmpd")) 
695
		mwexec("/usr/bin/killall bsnmpd", true);
696

    
697
	if (isset($config['snmpd']['enable'])) {
698

    
699
		if ($g['booting'])
700
			echo "Starting SNMP daemon... ";
701

    
702
		/* generate snmpd.conf */
703
		$fd = fopen("{$g['varetc_path']}/snmpd.conf", "w");
704
		if (!$fd) {
705
			printf("Error: cannot open snmpd.conf in services_snmpd_configure().\n");
706
			return 1;
707
		}
708

    
709

    
710
		$snmpdconf = <<<EOD
711
location := "{$config['snmpd']['syslocation']}"
712
contact := "{$config['snmpd']['syscontact']}"
713
read := "{$config['snmpd']['rocommunity']}"
714

    
715
EOD;
716

    
717
/* No docs on what write strings do there for disable for now.
718
		if(isset($config['snmpd']['rwenable']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
719
		    $snmpdconf .= <<<EOD
720
# write string
721
write := "{$config['snmpd']['rwcommunity']}"
722

    
723
EOD;
724
		}
725
*/
726

    
727

    
728
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
729
		    $snmpdconf .= <<<EOD
730
# SNMP Trap support.
731
traphost := {$config['snmpd']['trapserver']}
732
trapport := {$config['snmpd']['trapserverport']}
733
trap := "{$config['snmpd']['trapstring']}"
734

    
735

    
736
EOD;
737
		}
738

    
739

    
740
		$snmpdconf .= <<<EOD
741
system := 1     # pfSense
742
%snmpd
743
begemotSnmpdDebugDumpPdus       = 2
744
begemotSnmpdDebugSyslogPri      = 7
745
begemotSnmpdCommunityString.0.1 = $(read)
746

    
747
EOD;
748

    
749
/* No docs on what write strings do there for disable for now.
750
		if(isset($config['snmpd']['rwcommunity']) && preg_match('/^\S+$/', $config['snmpd']['rwcommunity'])){
751
		    $snmpdconf .= <<<EOD
752
begemotSnmpdCommunityString.0.2 = $(write)
753

    
754
EOD;
755
		}
756
*/
757

    
758

    
759
		if(isset($config['snmpd']['trapenable']) && preg_match('/^\S+$/', $config['snmpd']['trapserver'])){
760
		    $snmpdconf .= <<<EOD
761
begemotTrapSinkStatus.[$(traphost)].$(trapport) = 4
762
begemotTrapSinkVersion.[$(traphost)].$(trapport) = 2
763
begemotTrapSinkComm.[$(traphost)].$(trapport) = $(trap)
764

    
765
EOD;
766
		}
767

    
768

    
769
		$snmpdconf .= <<<EOD
770
begemotSnmpdCommunityDisable    = 1
771

    
772
EOD;
773

    
774
		if (isset($config['snmpd']['bindlan'])) {
775
			$config['snmpd']['bindip'] = 'lan';
776
			unset($config['snmpd']['bindlan']);
777
		}
778
		$bind_to_ip = "0.0.0.0";
779
		if(isset($config['snmpd']['bindip'])) {
780
			if (is_ipaddr($config['snmpd']['bindip'])) {
781
				$bind_to_ip = $config['snmpd']['bindip'];
782
			} else {
783
				$if = get_real_interface($config['snmpd']['bindip']);
784
				if (does_interface_exist($if))
785
					$bind_to_ip = find_interface_ip($if);
786
			}
787
		}
788

    
789
		if(is_port( $config['snmpd']['pollport'] )) {
790
		    $snmpdconf .= <<<EOD
791
begemotSnmpdPortStatus.{$bind_to_ip}.{$config['snmpd']['pollport']} = 1
792

    
793
EOD;
794

    
795
		}
796

    
797
		$snmpdconf .= <<<EOD
798
begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1
799
begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4
800

    
801
# These are bsnmp macros not php vars.
802
sysContact      = $(contact)
803
sysLocation     = $(location)
804
sysObjectId     = 1.3.6.1.4.1.12325.1.1.2.1.$(system)
805

    
806
snmpEnableAuthenTraps = 2
807

    
808
EOD;
809

    
810
		if (is_array( $config['snmpd']['modules'] )) {
811
		    if(isset($config['snmpd']['modules']['mibii'])) {
812
			$snmpdconf .= <<<EOD
813
begemotSnmpdModulePath."mibII"  = "/usr/lib/snmp_mibII.so"
814

    
815
EOD;
816
		    }
817

    
818
		    if(isset($config['snmpd']['modules']['netgraph'])) {
819
			$snmpdconf .= <<<EOD
820
begemotSnmpdModulePath."netgraph" = "/usr/lib/snmp_netgraph.so"
821
%netgraph
822
begemotNgControlNodeName = "snmpd"
823

    
824
EOD;
825
		    }
826

    
827
		    if(isset($config['snmpd']['modules']['pf'])) {
828
			$snmpdconf .= <<<EOD
829
begemotSnmpdModulePath."pf"     = "/usr/lib/snmp_pf.so"
830

    
831
EOD;
832
		    }
833

    
834
		    if(isset($config['snmpd']['modules']['hostres'])) {
835
			$snmpdconf .= <<<EOD
836
begemotSnmpdModulePath."hostres"     = "/usr/lib/snmp_hostres.so"
837

    
838
EOD;
839
		    }
840
		    if(isset($config['snmpd']['modules']['bridge'])) {
841
			$snmpdconf .= <<<EOD
842
begemotSnmpdModulePath."bridge"     = "/usr/lib/snmp_bridge.so"
843
# config must end with blank line
844

    
845

    
846
EOD;
847
		    }
848
		}
849

    
850
		fwrite($fd, $snmpdconf);
851
		fclose($fd);
852

    
853
		if (isset($config['snmpd']['bindlan'])) {
854
			$bindlan = "";
855
		}
856

    
857
		/* run bsnmpd */
858
		mwexec("/usr/sbin/bsnmpd -c {$g['varetc_path']}/snmpd.conf" .
859
			"{$bindlan} -p {$g['varrun_path']}/snmpd.pid");
860

    
861
		if ($g['booting'])
862
			echo "done.\n";
863
	}
864

    
865
	return 0;
866
}
867

    
868
function services_dnsupdate_process($int = "") {
869
	global $config, $g;
870
	if(isset($config['system']['developerspew'])) {
871
		$mt = microtime();
872
		echo "services_dnsupdate_process() being called $mt\n";
873
	}
874

    
875
	/* Dynamic DNS updating active? */
876
	if (is_array($config['dnsupdates']['dnsupdate'])) {
877
		foreach ($config['dnsupdates']['dnsupdate'] as $i => $dnsupdate) {
878
			if (!isset($dnsupdate['enable']))
879
				continue;
880
			if (!empty($int) && $int != $dnsupdate['interface'])
881
				continue;
882

    
883
			/* determine interface name */
884
			$if = get_real_interface($dnsupdate['interface']);
885
			$wanip = get_interface_ip($dnsupdate['interface']);
886
			if ($wanip) {
887

    
888
				$keyname = $dnsupdate['keyname'];
889
				/* trailing dot */
890
				if (substr($keyname, -1) != ".")
891
					$keyname .= ".";
892

    
893
				$hostname = $dnsupdate['host'];
894
				/* trailing dot */
895
				if (substr($hostname, -1) != ".")
896
					$hostname .= ".";
897

    
898
				/* write private key file
899
				   this is dumb - public and private keys are the same for HMAC-MD5,
900
				   but nsupdate insists on having both */
901
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.private", "w");
902
				$privkey = <<<EOD
903
Private-key-format: v1.2
904
Algorithm: 157 (HMAC)
905
Key: {$dnsupdate['keydata']}
906

    
907
EOD;
908
				fwrite($fd, $privkey);
909
				fclose($fd);
910

    
911
				/* write public key file */
912
				if ($dnsupdate['keytype'] == "zone") {
913
					$flags = 257;
914
					$proto = 3;
915
				} else if ($dnsupdate['keytype'] == "host") {
916
					$flags = 513;
917
					$proto = 3;
918
				} else if ($dnsupdate['keytype'] == "user") {
919
					$flags = 0;
920
					$proto = 2;
921
				}
922

    
923
				$fd = fopen("{$g['varetc_path']}/K{$i}{$keyname}+157+00000.key", "w");
924
				fwrite($fd, "{$keyname} IN KEY {$flags} {$proto} 157 {$dnsupdate['keydata']}\n");
925
				fclose($fd);
926

    
927
				/* generate update instructions */
928
				$upinst = "";
929
				if (!empty($dnsupdate['server']))
930
					$upinst .= "server {$dnsupdate['server']}\n";
931
				$upinst .= "update delete {$dnsupdate['host']} A\n";
932
				$upinst .= "update add {$dnsupdate['host']} {$dnsupdate['ttl']} A {$wanip}\n";
933
				$upinst .= "\n";	/* mind that trailing newline! */
934

    
935
				$fd = fopen("{$g['varetc_path']}/nsupdatecmds{$i}", "w");
936
				fwrite($fd, $upinst);
937
				fclose($fd);
938

    
939
				/* invoke nsupdate */
940
				$cmd = "/usr/bin/nsupdate -k {$g['varetc_path']}/K{$i}{$keyname}+157+00000.key";
941
				if (isset($dnsupdate['usetcp']))
942
					$cmd .= " -v";
943
				$cmd .= " {$g['varetc_path']}/nsupdatecmds{$i}";
944
	
945
				mwexec_bg($cmd);
946
			}
947
		}
948
	}
949

    
950
	return 0;
951
}
952

    
953
function setup_wireless_olsr() {
954
	global $config, $g;
955
	if(!$config['installedpackages']['olsrd'] || !$config['installedpackages'])
956
		return;
957
	if(isset($config['system']['developerspew'])) {
958
		$mt = microtime();
959
		echo "setup_wireless_olsr($interface) being called $mt\n";
960
	}
961
	conf_mount_rw();
962
	foreach($config['installedpackages']['olsrd']['config'] as $olsrd) {
963
		$olsr_enable = $olsrd['enable'];
964
		if($olsr_enable <> "on") {
965
			if (is_process_running("olsrd"))
966
				mwexec("/usr/bin/killall olsrd", true);
967
			return;
968
		}
969
		$fd = fopen("{$g['varetc_path']}/olsr.conf", "w");
970

    
971
		if($olsrd['announcedynamicroute'] or $olsrd['enableannounce'] == "on") {
972
			$enableannounce .= "\nHna4\n";
973
			$enableannounce .= "{\n";
974
		if($olsrd['announcedynamicroute'])
975
			$enableannounce .= "\t{$olsrd['announcedynamicroute']}\n";
976
		if($olsrd['enableannounce'] == "on")
977
			$enableannounce .= "0.0.0.0 0.0.0.0";
978
			$enableannounce .= "\n}\n";
979
		} else {
980
			$enableannounce = "";
981
		}
982

    
983
		$olsr .= <<<EODA
984
#
985
# olsr.org OLSR daemon config file
986
#
987
# Lines starting with a # are discarded
988
#
989
# This file was generated by setup_wireless_olsr() in services.inc
990
#
991

    
992
# This file is an example of a typical
993
# configuration for a mostly static
994
# network(regarding mobility) using
995
# the LQ extention
996

    
997
# Debug level(0-9)
998
# If set to 0 the daemon runs in the background
999

    
1000
DebugLevel	2
1001

    
1002
# IP version to use (4 or 6)
1003

    
1004
IpVersion	4
1005

    
1006
# Clear the screen each time the internal state changes
1007

    
1008
ClearScreen     yes
1009

    
1010
{$enableannounce}
1011

    
1012
# Should olsrd keep on running even if there are
1013
# no interfaces available? This is a good idea
1014
# for a PCMCIA/USB hotswap environment.
1015
# "yes" OR "no"
1016

    
1017
AllowNoInt	yes
1018

    
1019
# TOS(type of service) value for
1020
# the IP header of control traffic.
1021
# If not set it will default to 16
1022

    
1023
#TosValue	16
1024

    
1025
# The fixed willingness to use(0-7)
1026
# If not set willingness will be calculated
1027
# dynamically based on battery/power status
1028
# if such information is available
1029

    
1030
#Willingness    	4
1031

    
1032
# Allow processes like the GUI front-end
1033
# to connect to the daemon.
1034

    
1035
IpcConnect
1036
{
1037
     # Determines how many simultaneously
1038
     # IPC connections that will be allowed
1039
     # Setting this to 0 disables IPC
1040

    
1041
     MaxConnections  0
1042

    
1043
     # By default only 127.0.0.1 is allowed
1044
     # to connect. Here allowed hosts can
1045
     # be added
1046

    
1047
     Host            127.0.0.1
1048
     #Host            10.0.0.5
1049

    
1050
     # You can also specify entire net-ranges
1051
     # that are allowed to connect. Multiple
1052
     # entries are allowed
1053

    
1054
     #Net             192.168.1.0 255.255.255.0
1055
}
1056

    
1057
# Wether to use hysteresis or not
1058
# Hysteresis adds more robustness to the
1059
# link sensing but delays neighbor registration.
1060
# Used by default. 'yes' or 'no'
1061

    
1062
UseHysteresis	no
1063

    
1064
# Hysteresis parameters
1065
# Do not alter these unless you know
1066
# what you are doing!
1067
# Set to auto by default. Allowed
1068
# values are floating point values
1069
# in the interval 0,1
1070
# THR_LOW must always be lower than
1071
# THR_HIGH.
1072

    
1073
#HystScaling	0.50
1074
#HystThrHigh	0.80
1075
#HystThrLow	0.30
1076

    
1077

    
1078
# Link quality level
1079
# 0 = do not use link quality
1080
# 1 = use link quality for MPR selection
1081
# 2 = use link quality for MPR selection and routing
1082
# Defaults to 0
1083

    
1084
LinkQualityLevel	{$olsrd['enablelqe']}
1085

    
1086
# Link quality window size
1087
# Defaults to 10
1088

    
1089
LinkQualityWinSize	10
1090

    
1091
# Polling rate in seconds(float).
1092
# Default value 0.05 sec
1093

    
1094
Pollrate	0.05
1095

    
1096

    
1097
# TC redundancy
1098
# Specifies how much neighbor info should
1099
# be sent in TC messages
1100
# Possible values are:
1101
# 0 - only send MPR selectors
1102
# 1 - send MPR selectors and MPRs
1103
# 2 - send all neighbors
1104
#
1105
# defaults to 0
1106

    
1107
TcRedundancy	2
1108

    
1109
#
1110
# MPR coverage
1111
# Specifies how many MPRs a node should
1112
# try select to reach every 2 hop neighbor
1113
#
1114
# Can be set to any integer >0
1115
#
1116
# defaults to 1
1117

    
1118
MprCoverage	3
1119

    
1120
# Example plugin entry with parameters:
1121

    
1122
EODA;
1123

    
1124
if($olsrd['enablehttpinfo'] == "on") {
1125
	$olsr .= <<<EODB
1126

    
1127
LoadPlugin "/usr/local/lib/olsrd_httpinfo.so.0.1"
1128
{
1129
    PlParam     "port"   "{$olsrd['port']}"
1130
    PlParam     "Net"    "{$olsrd['allowedhttpinfohost']} {$olsrd['allowedhttpinfosubnet']}"
1131
}
1132

    
1133
EODB;
1134

    
1135
}
1136

    
1137
if($olsrd['enabledsecure'] == "on") {
1138
	$olsr .= <<<EODC
1139

    
1140
LoadPlugin "/usr/local/lib/olsrd_secure.so.0.5"
1141
{
1142
    PlParam     "Keyfile"   "/usr/local/etc/olsrkey.txt"
1143
}
1144

    
1145
EODC;
1146

    
1147
}
1148

    
1149
if($olsrd['enabledyngw'] == "on") {
1150

    
1151
	/* unset default route, olsr auto negotiates */
1152
	mwexec("/sbin/route delete default");
1153

    
1154
	$olsr .= <<<EODE
1155

    
1156
LoadPlugin "/usr/local/lib/olsrd_dyn_gw.so.0.4"
1157
{
1158
    # how often to look for a inet gw, in seconds
1159
    # defaults to 5 secs, if commented out
1160
    PlParam     "Interval"   "{$olsrd['polling']}"
1161

    
1162
    # if one or more IPv4 addresses are given, do a ping on these in
1163
    # descending order to validate that there is not only an entry in
1164
    # routing table, but also a real internet connection. If any of
1165
    # these addresses could be pinged successfully, the test was
1166
    # succesful, i.e. if the ping on the 1st address was successful,the
1167
    # 2nd won't be pinged
1168
    PlParam     "Ping"       "{$olsrd['ping']}"
1169
    #PlParam     "HNA"   "192.168.81.0 255.255.255.0"
1170
}
1171

    
1172
EODE;
1173

    
1174
}
1175

    
1176
foreach($config['installedpackages']['olsrd']['config'] as $conf) {
1177
	$interfaces = explode(',', $conf['iface_array']);
1178
	foreach($interfaces as $interface) {
1179
		$realinterface = convert_friendly_interface_to_real_interface_name($interface);
1180
$olsr .= <<<EODAD
1181
Interface "{$realinterface}"
1182
{
1183

    
1184
    # Hello interval in seconds(float)
1185
    HelloInterval    2.0
1186

    
1187
    # HELLO validity time
1188
    HelloValidityTime	20.0
1189

    
1190
    # TC interval in seconds(float)
1191
    TcInterval        5.0
1192

    
1193
    # TC validity time
1194
    TcValidityTime	30.0
1195

    
1196
    # MID interval in seconds(float)
1197
    MidInterval	5.0
1198

    
1199
    # MID validity time
1200
    MidValidityTime	30.0
1201

    
1202
    # HNA interval in seconds(float)
1203
    HnaInterval	5.0
1204

    
1205
    # HNA validity time
1206
    HnaValidityTime 	30.0
1207

    
1208
    # When multiple links exist between hosts
1209
    # the weight of interface is used to determine
1210
    # the link to use. Normally the weight is
1211
    # automatically calculated by olsrd based
1212
    # on the characteristics of the interface,
1213
    # but here you can specify a fixed value.
1214
    # Olsrd will choose links with the lowest value.
1215

    
1216
    # Weight 0
1217

    
1218

    
1219
}
1220

    
1221
EODAD;
1222

    
1223
	}
1224
	break;
1225
}
1226
		fwrite($fd, $olsr);
1227
		fclose($fd);
1228
	}
1229

    
1230
	if (is_process_running("olsrd"))
1231
		mwexec("/usr/bin/killall olsrd", true);
1232

    
1233
	sleep(2);
1234

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

    
1237
	conf_mount_ro();
1238
}
1239

    
1240
/* configure cron service */
1241
function configure_cron() {
1242
	global $g, $config;
1243

    
1244
	conf_mount_rw();
1245
	/* preserve existing crontab entries */
1246
	$crontab_contents = file("/etc/crontab", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
1247
	
1248
	for ($i = 0; $i < count($crontab_contents); $i++) {
1249
		$cron_item =& $crontab_contents[$i];
1250
		if (strpos($cron_item, "# pfSense specific crontab entries") !== false) {
1251
			array_splice($crontab_contents, $i - 1);
1252
			break;
1253
		}
1254
	}
1255
	$crontab_contents = implode("\n", $crontab_contents) . "\n";
1256
	
1257
	
1258
	if (is_array($config['cron']['item'])) {
1259
		$crontab_contents .= "#\n";
1260
		$crontab_contents .= "# pfSense specific crontab entries\n";
1261
		$crontab_contents .= "# Created: " . date("F j, Y, g:i a") . "\n";
1262
		$crontab_contents .= "#\n";
1263

    
1264
		foreach ($config['cron']['item'] as $item) {
1265
			$crontab_contents .= "\n{$item['minute']}\t";
1266
			$crontab_contents .= "{$item['hour']}\t";
1267
			$crontab_contents .= "{$item['mday']}\t";
1268
			$crontab_contents .= "{$item['month']}\t";
1269
			$crontab_contents .= "{$item['wday']}\t";
1270
			$crontab_contents .= "{$item['who']}\t";
1271
			$crontab_contents .= "{$item['command']}";
1272
		}
1273
    
1274
		$crontab_contents .= "\n#\n";
1275
		$crontab_contents .= "# If possible do not add items to this file manually.\n";
1276
		$crontab_contents .= "# If you do so, this file must be terminated with a blank line (e.g. new line)\n";
1277
		$crontab_contents .= "#\n\n";
1278
	}
1279
	
1280
	/* please maintain the newline at the end of file */
1281
	file_put_contents("/etc/crontab", $crontab_contents);
1282

    
1283
	/* do a HUP kill to force sync changes */
1284
	exec('/bin/pkill -HUP cron');
1285

    
1286
	conf_mount_ro();
1287
}
1288

    
1289
function upnp_action ($action) {
1290
	global $g, $config;
1291
	switch($action) {
1292
		case "start":
1293
			if (file_exists('/var/etc/miniupnpd.conf')) {
1294
				@unlink("{$g['varrun_path']}/miniupnpd.pid");
1295
				mwexec_bg("/usr/local/sbin/miniupnpd -f /var/etc/miniupnpd.conf -P {$g['varrun_path']}/miniupnpd.pid");
1296
			}
1297
			break;
1298
		case "stop":
1299
			killbypid("{$g['varrun_path']}/miniupnpd.pid");
1300
			while((int)exec("/bin/pgrep -a miniupnpd | wc -l") > 0)
1301
				mwexec('killall miniupnpd 2>/dev/null', true);
1302
			mwexec('/sbin/pfctl -aminiupnpd -Fr 2>&1 >/dev/null');
1303
			mwexec('/sbin/pfctl -aminiupnpd -Fn 2>&1 >/dev/null');
1304
			break;
1305
		case "restart":
1306
			upnp_action('stop');
1307
			upnp_action('start');
1308
			break;
1309
	}
1310
}
1311

    
1312
function upnp_start() {
1313
	global $config;
1314

    
1315
	if(!isset($config['installedpackages']['miniupnpd']['config']))
1316
		return;
1317

    
1318
	if($config['installedpackages']['miniupnpd']['config'][0]['enable']) {
1319
		echo "Starting UPnP service... ";
1320
		require_once('/usr/local/pkg/miniupnpd.inc');
1321
		sync_package_miniupnpd();
1322
		echo "done.\n";
1323
	}
1324
}
1325

    
1326
function install_cron_job($command, $active=false, $minute="0", $hour="*", $monthday="*", $month="*", $weekday="*", $who="root") {
1327
	global $config, $g;
1328

    
1329
	$is_installed = false;
1330

    
1331
	if(!$config['cron']['item'])
1332
		return;
1333

    
1334
	$x=0;
1335
	foreach($config['cron']['item'] as $item) {
1336
		if(strstr($item['command'], $command)) {
1337
			$is_installed = true;
1338
			break;
1339
		}
1340
		$x++;
1341
	}
1342

    
1343
	if($active) {
1344
		$cron_item = array();
1345
		$cron_item['minute'] = $minute;
1346
		$cron_item['hour'] = $hour;
1347
		$cron_item['mday'] = $monthday;
1348
		$cron_item['month'] = $month;
1349
		$cron_item['wday'] = $weekday;
1350
		$cron_item['who'] = $who;
1351
		$cron_item['command'] = $command;
1352
		if(!$is_installed) {
1353
			$config['cron']['item'][] = $cron_item;
1354
			write_config("Installed cron job for {$command}");
1355
		} else {
1356
			$config['cron']['item'][$x] = $cron_item;
1357
			write_config("Updated cron job for {$command}");
1358
		}
1359
	} else {
1360
		if(($is_installed == true) && ($x > 0)) {
1361
			unset($config['cron']['item'][$x]);
1362
			write_config("Remvoed cron job for {$command}");
1363
		}
1364
	}
1365
	configure_cron();
1366
}
1367

    
1368
?>
(45-45/62)