Project

General

Profile

« Previous | Next » 

Revision 60120e37

Added by Ermal Luçi over 16 years ago

  • Convert schedules to pf(4).
    This allows to schedule the whole feature of the rules like queues/limiters/gateways/blocks/allows/etc...
  • Whitespace cleaning on filter.inc
  • Move schedule backend logic from pfsense-utils.inc to filter.inc and prefix with filter_.
  • Small bugfixes here and there.

View differences:

etc/inc/pfsense-utils.inc
131 131
	return "/tmp/tmp-" . time();
132 132
}
133 133

  
134
/****f* pfsense-utils/tdr_install_cron
135
 * NAME
136
 *   tdr_install_cron
137
 * INPUTS
138
 *   $should_install true if the cron entry should be installed, false
139
 *   if the entry should be removed if it is present
140
 * RESULT
141
 *   none
142
 ******/
143
function tdr_install_cron($should_install) {
144
	global $config, $g;
145
	if($g['booting']==true) 
146
		return;
147
	$is_installed = false;
148
	if(!$config['cron']['item'])
149
		return;
150
	$x=0;
151
	foreach($config['cron']['item'] as $item) {
152
		if(strstr($item['command'], "filter_configure_sync")) {
153
			$is_installed = true;
154
			break;
155
		}
156
		$x++;
157
	}
158
	switch($should_install) {
159
		case true:
160
			if(!$is_installed) {
161
				$cron_item = array();
162
				$cron_item['minute'] = "0,15,30,45";
163
				$cron_item['hour'] = "*";
164
				$cron_item['mday'] = "*";
165
				$cron_item['month'] = "*";
166
				$cron_item['wday'] = "*";
167
				$cron_item['who'] = "root";
168
				$cron_item['command'] = "/etc/rc.filter_configure_sync";		
169
				$config['cron']['item'][] = $cron_item;
170
				write_config("Installed 15 minute filter reload for Time Based Rules");
171
				configure_cron();
172
			}
173
		break;
174
		case false:
175
			if($is_installed == true) {
176
				if($x > 0) {
177
					unset($config['cron']['item'][$x]);
178
					write_config();
179
				}
180
				configure_cron();
181
			}
182
		break;
183
	}
184
}
185

  
186
/****f* pfsense-utils/tdr_create_ipfw_rule
187
 * NAME
188
 *   tdr_create_ipfw_rule
189
 * INPUTS
190
 *   $rule xml firewall rule array, $type allow or deny
191
 * RESULT
192
 *   text string with ipfw rule already formatted
193
 ******/
194
function tdr_create_ipfw_rule($rule, $type) {
195
	global $config, $g, $tdr_get_next_ipfw_rule, $FilterIflist;
196

  
197
	if (isset($rule['disabled']))
198
		return "";
199

  
200
	$int = "";
201
	/* Check to see if the interface is in our list */
202
	if (isset($rule['floating'])) {
203
		if (isset($rule['interface']) && $rule['interface'] <> "") 
204
			$aline['interface'] = "multiple"; /* XXX */
205
		else
206
			$aline['interface'] = "";
207
	} else if (!array_key_exists($rule['interface'], $FilterIflist)) 
208
			return "# {$rule['interface']} does not exist or is disabled for " . $rule['descr'];
209
	else {
210
		if ($rule['interface'] == "pptp" || $rule['interface'] == "pppoe" || $rule['interface'] == "l2tp")
211
			$aline['interface'] = "ng*";
212
		else
213
			$aline['interface'] = " " . $FilterIflist[$rule['interface']]['if'] . " ";
214
	}
215

  
216
	$ifcfg = $FilterIflist[$rule['interface']];
217
	if ($pptpdcfg['mode'] != "server") {
218
		if (($rule['source']['network'] == "pptp") ||
219
			($rule['destination']['network'] == "pptp")) 
220
				return "# source network or destination network == pptp on " . $rule['descr'];
221
	}
222
	if ($rule['source']['network'] && strstr($rule['source']['network'], "opt")) {
223
		if (!array_key_exists($rule['source']['network'], $FilterIflist)) {
224
			$optmatch = "";
225
			if (preg_match("/opt([0-999])/", $rule['source']['network'], $optmatch)) {
226
				$opt_ip = $FilterIflist["opt{$optmatch[1]}"]['ip'];
227
				if(!is_ipaddr($opt_ip))
228
					return "# unresolvable optarray $optmatch[0] - $opt_ip";
229
			} else {
230
				return "# tdr {$rule['source']['network']} !array_key_exists source network " . $rule['descr'];
231
			}
232
		}
233
	}
234
	if ($rule['destination']['network'] && strstr($rule['destination']['network'], "opt")) {
235
		if (!array_key_exists($rule['destination']['network'], $FilterIflist)) {
236
			if(preg_match("/opt([0-999])/", $rule['destination']['network'], $optmatch)) {
237
				$opt_ip = $FilterIflist["opt{$optmatch[1]}"]['ip'];
238
				if(!is_ipaddr($opt_ip))
239
					return "# unresolvable oparray $optmatch[0] - $opt_ip";
240
			} else {
241
				return "# tdr {$item} {$rule['destination']['network']} !array_key_exists dest network " . $rule['descr'];
242
			}
243
		}
244
	}
245
	/* check for unresolvable aliases */
246
	if ($rule['source']['address'] && !alias_expand($rule['source']['address'])) {
247
		file_notice("Filter_Reload", "# unresolvable source aliases {$rule['descr']}");
248
		return "# tdr unresolvable source aliases {$rule['descr']}";
249
	}
250
	if ($rule['destination']['address'] && !alias_expand($rule['destination']['address'])) {
251
		file_notice("Filter_Reload", "# unresolvable dest aliases {$rule['descr']}");
252
		return "# tdr unresolvable dest aliases {$rule['descr']}";
253
	}
254

  
255
	if (isset($rule['protocol'])) {
256
		if($rule['protocol'] == "tcp/udp")
257
			$aline['prot'] = "ip ";
258
		else if($rule['protocol'] == "icmp")
259
			$aline['prot'] = "icmp ";
260
		else
261
			$aline['prot'] = "{$rule['protocol']} ";
262
	} else {
263
		if($rule['source']['port'] <> "" || $rule['destination']['port'] <> "")
264
			$aline['prot'] = "tcp ";
265
	}
266

  
267
	/* source address */
268
	if (isset($rule['source']['any']))
269
		$src = "any";
270
	else if ($rule['source']['network']) {
271
		if (strstr($rule['source']['network'], "opt")) {
272
			$src = $FilterIflist[$rule['source']['network']]['sa'] . "/" .
273
				$FilterIflist[$rule['source']['network']]['sn'];
274
			if (isset($rule['source']['not'])) 
275
				$src = " not {$src}";
276
			/* check for opt$NUMip here */
277
			$matches = "";
278
			if (preg_match("/opt([0-9999])ip/", $rule['source']['network'], $matches)) {
279
				$optnum = $matches[1];
280
				$src = $FilterIflist["opt{$optnum}"]['ip'];
281
			}
282
		} else {
283
			switch ($rule['source']['network']) {
284
				case 'wanip':
285
					$src = $FilterIflist["wan"]['ip'];
286
					break;
287
				case 'lanip':
288
					$src = $FilterIflist["lan"]['ip'];
289
					break;
290
				case 'lan':
291
					$lansa = $FilterIflist['lan']['sa'];
292
					$lansn = $FilterIflist['lan']['sn'];
293
					$src = "{$lansa}/{$lansn}";
294
					break;
295
				case 'pptp':
296
					$pptpsa = gen_subnet($FilterIflist['pptp']['ip'], $FilterIflist['pptp']['sn']);
297
					$pptpsn = $FilterIflist['pptp']['sn'];
298
					$src = "{$pptpsa}/{$pptpsn}";
299
					break;
300
				case 'pppoe':
301
					$pppoesa = gen_subnet($FilterIflist['pppoe']['ip'], $FilterIflist['pppoe']['sn']);
302
					$pppoesn = $FilterIflist['pppoe']['sn'];
303
					$src = "{$pppoesa}/{$pppoesn}";
304
					break;
305
			}
306
			if (isset($rule['source']['not'])) 
307
				$src = " not {$src}";
308
		}
309
	} else if ($rule['source']['address']) {
310
		$expsrc = alias_expand_value($rule['source']['address']);
311
		if(!$expsrc) 
312
			$expsrc = $rule['source']['address'];
313
				
314
		if (isset($rule['source']['not']))
315
			$not = " not";
316
		else
317
			$not = "";
318

  
319
		if (alias_expand_value($rule['source']['address'])) {
320
			$src = "{";
321
			$first_item = true;
322
			foreach(preg_split("/[\s]+/", alias_expand_value($rule['source']['address'])) as $item) {
323
				if($item != "") {
324
					if(!$first_item) 
325
						$src .= " or";
326
						$src .= " {$not}{$item}";
327
						$first_item = false;
328
					}
329
				}
330
					$src .= " }";
331
		} else
332
			$src = "{$not}" . $expsrc;
333
	}
334
	if (!$src || ($src == "/")) 
335
		return "# tdr at the break!";
336
	
337
	$aline['src'] = "from $src ";
338

  
339
	$srcporta = "";
340
	if (in_array($rule['protocol'], array("tcp","udp","tcp/udp"))) {
341
		if ($rule['source']['port']) {
342
			$srcport = explode("-", $rule['source']['port']);
343
			if(alias_expand($srcport[0])) {
344
				$first_time = true;
345
				foreach(preg_split("/[\s]+/", alias_expand_value($srcport[0])) as $item) {
346
					if(!$first_time) 
347
						$srcporta .= ",";				
348
					$srcporta .= $item;
349
					$first_time = false;
350
				}
351
			} else 
352
				$srcporta = $srcport[0];
353
			
354
			if ((!$srcport[1]) || ($srcport[0] == $srcport[1])) {
355
				if(alias_expand($srcport[0]))
356
					$aline['srcport'] = "{$srcporta} ";
357
				else
358
					$aline['srcport'] = "{$srcporta} ";
359
			} else if (($srcport[0] == 1) && ($srcport[1] == 65535)) {
360
				/* no need for a port statement here */
361
			} else if ($srcport[1] == 65535) 
362
				$aline['srcport'] = ">={$srcport[0]} ";
363
			else if ($srcport[0] == 1) 
364
				$aline['srcport']= "<={$srcport[1]} ";
365
			else 
366
				$aline['srcport'] = "{$srcport[0]}-{$srcport[1]} ";
367
		}
368
	}
369

  
370
	/* destination address */
371
	if (isset($rule['destination']['any']))
372
		$dst = "any";
373
	else if ($rule['destination']['network']) {
374
		if (strstr($rule['destination']['network'], "opt")) {
375
			$dst = $FilterIflist[$rule['destination']['network']]['sa'] . "/" .
376
				$FilterIflist[$rule['destination']['network']]['sn'];
377
			if (isset($rule['destination']['not'])) 
378
				$dst = " not {$dst}";
379
			/* check for opt$NUMip here */
380
			$matches = "";
381
			if (preg_match("/opt([0-9999])ip/", $rule['destination']['network'], $matches)) {
382
				$optnum = $matches[1];
383
				$dst = $FilterIflist["opt{$optnum}"]['ip'];
384
			}
385
		} else {
386
			switch ($rule['source']['network']) {
387
				case 'wanip':
388
					$dst = $FilterIflist["wan"]['ip'];
389
					break;
390
				case 'lanip':
391
					$dst = $FilterIflist["lan"]['ip'];
392
					break;
393
				case 'lan':
394
					$lansa = $FilterIflist['lan']['sa'];
395
					$lansn = $FilterIflist['lan']['sn'];
396
					$dst = "{$lansa}/{$lansn}";
397
					break;
398
				case 'pptp':
399
					$pptpsa = gen_subnet($FilterIflist['pptp']['ip'], $FilterIflist['pptp']['sn']);
400
					$pptpsn = $FilterIflist['pptp']['sn'];
401
					$dst = "{$pptpsa}/{$pptpsn}";
402
					break;
403
				case 'pppoe':
404
					$pppoesa = gen_subnet($FilterIflist['pppoe']['ip'], $FilterIflist['pppoe']['sn']);
405
					$pppoesn = $FilterIflist['pppoe']['sn'];
406
					$dst = "{$pppoesa}/{$pppoesn}";
407
					break;
408
			}
409
			if (isset($rule['destination']['not'])) 
410
				$dst = " not {$dst}";
411
		}
412
	} else if ($rule['destination']['address']) {
413
		$expdst = alias_expand_value($rule['destination']['address']);
414
		if(!$expdst) 
415
			$expdst = $rule['destination']['address'];
416
				
417
		if (isset($rule['destination']['not']))
418
			$not = " not";
419
		else
420
			$not = "";
421

  
422
		if (alias_expand_value($rule['destination']['address'])) {
423
			$dst = "{";
424
			$first_item = true;
425
			foreach(preg_split("/[\s]+/", alias_expand_value($rule['destination']['address'])) as $item) {
426
				if($item != "") {
427
					if(!$first_item) 
428
						$dst .= " or";
429
						$dst .= " {$not}{$item}";
430
						$first_item = false;
431
					}
432
				}
433
					$dst .= " }";
434
		} else
435
			$dst = "{$not}" . $expdst;
436
	}
437

  
438
	if (!$dst || ($dst == "/")) 
439
		return "# returning at dst $dst == \"/\"";
440

  
441
	$aline['dst'] = "to $dst ";
442
	$dstporta = "";
443
	if (in_array($rule['protocol'], array("tcp","udp","tcp/udp"))) {
444
		if ($rule['destination']['port']) {
445
			$dstport = explode("-", $rule['destination']['port']);
446
			if(alias_expand($dstport[0])) {
447
				$first_time = true;
448
				foreach(preg_split("/[\s]+/", alias_expand_value($dstport[0])) as $item) {
449
					if(!$first_time)
450
				 		$dstporta .= ",";
451
					$dstporta .= $item;			
452
					$first_time = false;
453
				}
454
			} else 
455
				$dstporta = $dstport[0];
456
		
457
			if ((!$dstport[1]) || ($dstport[0] == $dstport[1])) {
458
				if(alias_expand($dstport[0]))
459
					$aline['dstport'] = "{$dstporta} ";
460
				else
461
					$aline['dstport'] = "{$dstporta} ";
462
			} else if (($dstport[0] == 1) && ($dstport[1] == 65535)) {
463
				/* no need for a port statement here */
464
			} else if ($dstport[1] == 65535) 
465
				$aline['dstport'] = ">= {$dstport[0]} ";
466
			else if ($dstport[0] == 1)
467
				$aline['dstport'] = "<= {$dstport[1]} ";
468
			else
469
				$aline['dstport'] = "{$dstport[0]}-{$dstport[1]} ";
470
		}
471
	}
472
	
473
	if($aline['prot'] == "")
474
		$aline['prot'] = "ip ";
475

  
476
	tdr_get_next_ipfw_rule();
477

  
478
 	/* piece together the actual user rule */
479
	if($type == "skipto") {
480
		$next_rule = tdr_get_next_ipfw_rule();
481
		$next_rule = $next_rule+1;
482
		$type = "skipto $next_rule";
483
	}
484

  
485
	/* piece together the actual user rule */
486
	if ($aline['interface'] == "multiple") {
487
		$tmpline = $type . " " . $aline['prot'] . $aline['src'] . 
488
			$aline['srcport'] . $aline['dst'] . $aline['dstport'] . " in recv ";
489
		$interfaces = explode(",", $rule['interface']);
490
		$ifliste = "";
491
		foreach ($interfaces as $iface) {
492
			if (array_key_exists($iface, $FilterIflist)) 
493
				$line .= "{$tmpline} " . $FilterIflist[$iface]['if'] . "; ";/* XXX */
494
		}
495
	} else if ($aline['interface'] == "")
496
		$line .= $type . " " . $aline['prot'] . $aline['src'] . 
497
			$aline['srcport'] . $aline['dst'] . $aline['dstport'] . " in ";
498
	else
499
		$line .= $type . " " . $aline['prot'] . $aline['src'] . 
500
			$aline['srcport'] . $aline['dst'] . $aline['dstport'] . " in recv " .
501
			$aline['interface'];
502

  
503
	return $line;
504
}
505

  
506
/****f* pfsense-utils/tdr_install_rule
507
 * NAME
508
 *   tdr_install_rule
509
 * INPUTS
510
 *   $rule - ascii string containing the ifpw rule to add
511
 * RESULT
512
 *   none
513
 ******/
514
function tdr_install_rule($rule) {
515
	global $tdr_next_ipfw_rule, $g;
516

  
517
	log_error("installing {$rule}");
518
	$lines = explode(";", $rule);
519
	if (count($lines) > 1) {
520
		foreach ($lines as $line) {
521
			if ($g['debug'])
522
				log_error("Executing /sbin/ipfw -f add {$tdr_next_ipfw_rule} set 9 $line");
523
			mwexec("/sbin/ipfw -f add {$tdr_next_ipfw_rule} set 9 $line");
524
			$tdr_next_ipfw_rule++;
525
		}
526
	} else {
527
		if ($g['debug'])
528
			log_error("Executing /sbin/ipfw -f add {$tdr_next_ipfw_rule} set 9 $rules");
529
		mwexec("/sbin/ipfw -f add $tdr_next_ipfw_rule set 9 $rule");
530
	}
531
	$tdr_next_ipfw_rule++;
532
}
533

  
534
/****f* pfsense-utils/tdr_get_next_ipfw_rule
535
 * NAME
536
 *   tdr_get_next_ipfw_rule
537
 * INPUTS
538
 *  none
539
 * RESULT
540
 *   returns the next available ipfw rule number
541
 ******/
542
function tdr_get_next_ipfw_rule() {
543
	global $tdr_next_ipfw_rule;
544
	if(intval($tdr_next_ipfw_rule) < 2) 
545
		$tdr_next_ipfw_rule = 2;
546
	return $tdr_next_ipfw_rule;
547
 }
548

  
549
/****f* pfsense-utils/tdr_install_set
550
 * NAME
551
 *   tdr_install_set
552
 * INPUTS
553
 *  none
554
 * RESULT
555
 *   swaps in the temporary ipfw time based rule set
556
 ******/
557
function tdr_install_set() {
558
	global $config;
559
	
560
	mwexec("/sbin/ipfw delete 1");
561
	mwexec("/sbin/ipfw add 1 check-state");
562
	mwexec("/sbin/ipfw delete 65534");
563
	mwexec("/sbin/ipfw add 1 allow all from me to any keep-state");
564
	if (!isset ($config['system']['webgui']['noantilockout']) && count($config['interfaces']) > 1) {
565
		/* lan ip lockout */
566
		$lanip = get_interface_ip("lan");
567
		$lansn = get_interface_subnet("lan");
568
		$lansa = gen_subnet($lanip, $lansn);
569
		mwexec("/sbin/ipfw add 1 allow all from {$lansa}/{$lansn} to $lanip keep-state");
570
	}
571
	mwexec("/sbin/ipfw add 65534 check-state");
572
	/* set 8 contains time based rules */
573
	mwexec("/sbin/ipfw -f delete set 8");
574
	mwexec("/sbin/ipfw -f set swap 9 8");
575
}
576

  
577
/****f* pfsense-utils/get_time_based_rule_status
578
 * NAME
579
 *   get_time_based_rule_status
580
 * INPUTS
581
 *   xml schedule block
582
 * RESULT
583
 *   true/false - true if the rule should be installed
584
 ******/
585
/*
586
 <schedules>
587
   <schedule>
588
     <name>ScheduleMultipleTime</name>
589
     <descr>main descr</descr>
590
     <time>
591
       <position>0,1,2</position>
592
       <hour>0:0-24:0</hour>
593
       <desc>time range 2</desc>
594
     </time>
595
     <time>
596
       <position>4,5,6</position>
597
       <hour>0:0-24:0</hour>
598
       <desc>time range 1</desc>
599
     </time>
600
   </schedule>
601
 </schedules>
602
*/
603
function get_time_based_rule_status($schedule) {
604
	$should_add_rule = false;
605
	/* no schedule? rule should be installed */
606
	if($schedule == "") 
607
		return true;
608
	/*
609
	 * iterate through time blocks and deterimine
610
	 * if the rule should be installed or not.
611
	 */
612
	foreach($schedule['timerange'] as $timeday) {
613
		if($timeday['month']) 
614
			$month = $timeday['month'];
615
		else 
616
			$week = "";	
617
		if($timeday['day']) 
618
			$day = $timeday['day'];
619
		else 
620
			$day = "";
621
		if($timeday['hour']) 
622
			$hour = $timeday['hour'];
623
		else 
624
			$hour = "";
625
		if($timeday['position']) 
626
			$position = $timeday['position'];
627
		else 
628
			$position = "";
629
		if($timeday['desc']) 
630
			$desc = $timeday['desc'];
631
		else 
632
			$desc = "";
633
		if($month) {
634
			$monthstatus = tdr_month($month);
635
		} else {
636
			$monthstatus = true;
637
		}
638
		if($day) {
639
			$daystatus = tdr_day($day);
640
		} else {
641
			$daystatus = true;
642
		}
643
		if($hour) {
644
			$hourstatus = tdr_hour($hour);
645
		} else {
646
			$hourstatus = true;
647
		}
648
		if($position) {
649
			$positionstatus = tdr_position($position);
650
		} else {
651
			$positionstatus = true;
652
		}
653

  
654
		if($monthstatus == true) 
655
			if($daystatus == true) 
656
				if($positionstatus == true) 
657
					if($hourstatus == true) {
658
						$should_add_rule = true;
659
					}
660
	}
661
	
662
	return $should_add_rule;
663
}
664

  
665
function tdr_day($schedule) {
666
	/*
667
	 * Calculate day of month. 
668
	 * IE: 29th of may
669
	 */
670
	$weekday	= date("w");
671
	if ($weekday == 0)
672
		$weekday = 7;
673
	$date	 	= date("d");
674
	$defined_days = split(",", $schedule);
675
	log_error("[TDR DEBUG] tdr_day($schedule)");
676
	foreach($defined_days as $dd) {
677
		if($date == $dd) {
678
			return true;
679
		}
680
	}
681
	return false;
682
}
683

  
684
function tdr_hour($schedule) {
685
	/* $schedule should be a string such as 16:00-19:00 */
686
	$tmp = split("-", $schedule);
687
	$starting_time = strtotime($tmp[0]);
688
	$ending_time = strtotime($tmp[1]);
689
	$now = strtotime("now");
690
	log_error("[TDR DEBUG] S: $starting_time E: $ending_time N: $now");
691
	if($now >= $starting_time and $now <= $ending_time) {
692
		return true;
693
	}
694
	return false;
695
}
696

  
697
function tdr_position($schedule) {
698
	/*
699
	 * Calculate possition, ie: day of week.
700
	 * Sunday = 7, Monday = 1, Tuesday = 2
701
	 * Weds = 3, Thursday = 4, Friday = 5,
702
	 * Saturday = 6
703
	 * ...
704
	 */
705
	$weekday	= date("w");
706
	log_error("[TDR DEBUG] tdr_position($schedule) $weekday");
707
	if ($weekday == 0)
708
		$weekday = 7;
709
	$schedule_days = split(",", $schedule);
710
	foreach($schedule_days as $day) {
711
		if($day == $weekday) {
712
			return true;
713
		}
714
	}
715
	return false;
716
}
717

  
718
function tdr_month($schedule) {
719
	/*
720
	 * Calculate month
721
	 */
722
	$todays_month = date("n");
723
	$months = split(",", $schedule);
724
	log_error("[TDR DEBUG] tdr_month($schedule)");
725
	foreach($months as $month) {
726
		if($month == $todays_month) {
727
			return true;
728
		}
729
	}
730
	return false;
731
}
732

  
733 134
/****f* pfsense-utils/find_number_of_needed_carp_interfaces
734 135
 * NAME
735 136
 *   find_number_of_needed_carp_interfaces

Also available in: Unified diff