summaryrefslogtreecommitdiff
path: root/lib/Vyatta/TypeChecker.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Vyatta/TypeChecker.pm')
-rwxr-xr-xlib/Vyatta/TypeChecker.pm229
1 files changed, 229 insertions, 0 deletions
diff --git a/lib/Vyatta/TypeChecker.pm b/lib/Vyatta/TypeChecker.pm
new file mode 100755
index 0000000..124dc17
--- /dev/null
+++ b/lib/Vyatta/TypeChecker.pm
@@ -0,0 +1,229 @@
+#!/usr/bin/perl
+
+# Author: An-Cheng Huang <ancheng@vyatta.com>
+# Date: 2007
+# Description: Type checking script
+
+# **** License ****
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2006, 2007, 2008 Vyatta, Inc.
+# All Rights Reserved.
+# **** End License ****
+
+# Perl module for type validation.
+# Usage 1: validate a value of a specific type.
+# use Vyatta::TypeChecker;
+# ...
+# if (validateType('ipv4', '1.1.1.1')) {
+# # valid
+# ...
+# } else {
+# # not valie
+# ...
+# }
+#
+# Usage 2: find the type of a value (from a list of candidates), returns
+# undef if the value is not valid for any of the candidates.
+# $valtype = findType('1.1.1.1', 'ipv4', 'ipv6');
+# if (!defined($valtype)) {
+# # neither ipv4 nor ipv6
+# ...
+# } else {
+# if ($valtype eq 'ipv4') {
+# ...
+# } else {
+# ...
+# }
+# }
+
+package Vyatta::TypeChecker;
+our @EXPORT = qw(findType validateType);
+use base qw(Exporter);
+
+use strict;
+
+my %type_handler = (
+ 'ipv4' => \&validate_ipv4,
+ 'ipv4net' => \&validate_ipv4net,
+ 'ipv4range' => \&validate_ipv4range,
+ 'ipv4_negate' => \&validate_ipv4_negate,
+ 'ipv4net_negate' => \&validate_ipv4net_negate,
+ 'ipv4range_negate' => \&validate_ipv4range_negate,
+ 'iptables4_addr' => \&validate_iptables4_addr,
+ 'protocol' => \&validate_protocol,
+ 'protocol_negate' => \&validate_protocol_negate,
+ 'macaddr' => \&validate_macaddr,
+ 'macaddr_negate' => \&validate_macaddr_negate,
+ 'ipv6' => \&validate_ipv6,
+ );
+
+sub validate_ipv4 {
+ $_ = shift;
+ return 0 if (!/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
+ return 0 if ($1 > 255 || $2 > 255 || $3 > 255 || $4 > 255);
+ return 1;
+}
+
+sub validate_ipv4net {
+ $_ = shift;
+ return 0 if (!/^(\d+)\.(\d+)\.(\d+)\.(\d+)\/(\d+)$/);
+ return 0 if ($1 > 255 || $2 > 255 || $3 > 255 || $4 > 255 || $5 > 32);
+ return 1;
+}
+
+sub validate_ipv4range {
+ $_ = shift;
+ return 0 if (!/^([^-]+)-([^-]+)$/);
+ my ($a1, $a2) = ($1, $2);
+ return 0 if (!validate_ipv4($a1) || !validate_ipv4($a2));
+ return 1;
+}
+
+sub validate_ipv4_negate {
+ my $value = shift;
+ if ($value =~ m/^\!(.*)$/) {
+ $value = $1;
+ }
+ return validate_ipv4($value);
+}
+
+sub validate_ipv4net_negate {
+ my $value = shift;
+ if ($value =~ m/^\!(.*)$/) {
+ $value = $1;
+ }
+ return validate_ipv4net($value);
+}
+
+sub validate_ipv4range_negate {
+ my $value = shift;
+ if ($value =~ m/^\!(.*)$/) {
+ $value = $1;
+ }
+ return validate_ipv4range($value);
+}
+
+sub validate_iptables4_addr {
+ my $value = shift;
+ return 0 if (!validate_ipv4_negate($value)
+ && !validate_ipv4net_negate($value)
+ && !validate_ipv4range_negate($value));
+ return 1;
+}
+
+sub validate_protocol {
+ my $value = shift;
+ $value = lc $value;
+ return 1 if ($value eq 'all');
+ if (!open(IN, "</etc/protocols")) {
+ print "can't open /etc/protocols";
+ return 0;
+ }
+ my $ret = 0;
+ while (<IN>) {
+ s/^([^#]*)#.*$/$1/;
+ if ((/^$value\s/) || (/^\S+\s+$value\s/)) {
+ $ret = 1;
+ last;
+ }
+ }
+ close IN;
+ return $ret;
+}
+
+sub validate_protocol_negate {
+ my $value = shift;
+ if ($value =~ m/^\!(.*)$/) {
+ $value = $1;
+ }
+ return validate_protocol($value);
+}
+
+sub validate_macaddr {
+ my $value = shift;
+ $value = lc $value;
+ my $byte = '[0-9a-f]{2}';
+ return 1 if ($value =~ /^$byte(:$byte){5}$/);
+}
+
+sub validate_macaddr_negate {
+ my $value = shift;
+ if ($value =~ m/^\!(.*)$/) {
+ $value = $1;
+ }
+ return validate_macaddr($value);
+}
+
+# IPv6 syntax definition
+my $RE_IPV4_BYTE = '((25[0-5])|(2[0-4][0-9])|([01][0-9][0-9])|([0-9]{1,2}))';
+my $RE_IPV4 = "$RE_IPV4_BYTE(\.$RE_IPV4_BYTE){3}";
+my $RE_H16 = '([a-fA-F0-9]{1,4})';
+my $RE_H16_COLON = "($RE_H16:)";
+my $RE_LS32 = "(($RE_H16:$RE_H16)|($RE_IPV4))";
+my $RE_IPV6_P1 = "($RE_H16_COLON)\{6\}$RE_LS32";
+my $RE_IPV6_P2 = "::($RE_H16_COLON)\{5\}$RE_LS32";
+my $RE_IPV6_P3 = "($RE_H16)?::($RE_H16_COLON)\{4\}$RE_LS32";
+my $RE_IPV6_P4 = "(($RE_H16_COLON)\{0,1\}$RE_H16)?"
+ . "::($RE_H16_COLON)\{3\}$RE_LS32";
+my $RE_IPV6_P5 = "(($RE_H16_COLON)\{0,2\}$RE_H16)?"
+ . "::($RE_H16_COLON)\{2\}$RE_LS32";
+my $RE_IPV6_P6 = "(($RE_H16_COLON)\{0,3\}$RE_H16)?"
+ . "::($RE_H16_COLON)\{1\}$RE_LS32";
+my $RE_IPV6_P7 = "(($RE_H16_COLON)\{0,4\}$RE_H16)?::$RE_LS32";
+my $RE_IPV6_P8 = "(($RE_H16_COLON)\{0,5\}$RE_H16)?::$RE_H16";
+my $RE_IPV6_P9 = "(($RE_H16_COLON)\{0,6\}$RE_H16)?::";
+my $RE_IPV6 = "($RE_IPV6_P1)|($RE_IPV6_P2)|($RE_IPV6_P3)|($RE_IPV6_P4)"
+ . "|($RE_IPV6_P5)|($RE_IPV6_P6)|($RE_IPV6_P7)|($RE_IPV6_P8)"
+ . "|($RE_IPV6_P9)";
+
+sub validate_ipv6 {
+ $_ = shift;
+ return 0 if (!/^$RE_IPV6$/);
+ return 1;
+}
+
+sub validateType {
+ my ($type, $value, $quiet) = @_;
+ if (!defined($type) || !defined($value)) {
+ return 0;
+ }
+ if (!defined($type_handler{$type})) {
+ print "type \"$type\" not defined\n" if (!defined($quiet));
+ return 0;
+ }
+ if (!&{$type_handler{$type}}($value)) {
+ print "\"$value\" is not a valid value of type \"$type\"\n"
+ if (!defined($quiet));
+ return 0;
+ }
+
+ return 1;
+}
+
+sub findType {
+ my ($value, @candidates) = @_;
+ if (!defined($value) || ((scalar @candidates) < 1)) {
+ return undef;
+ }
+ foreach my $type (@candidates) {
+ if (!defined($type_handler{$type})) {
+ next;
+ }
+ if (&{$type_handler{$type}}($value)) {
+ # the first valid type is returned
+ return $type;
+ }
+ }
+ return undef;
+}
+
+1;