OpenWrt Forum Archive

Topic: firewall.sh and validate.awk support for netmask ipaddresses

The content of this topic has been archived on 31 Mar 2018. There are no obvious gaps in this topic, but there may still be some posts missing at the end.

Tried to enter a firewall rule using netmask notation and was told it was bad. Tracked it to validate.awk. Updated the section starting with
#FIXME: add proper netmask validation to the following:
/usr/lib/webif/validate.awk

# FIXME: add proper netmask validation.. OK. Done.
($1 == "ip") || ($1 == "netmask") {
        valid_type = 1
        if ((value != "") && (value !~ /^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\/?[0-9]?[0-9]?$/))  valid=0
        else {
                split(value, ipaddr, "\\.")
                for (i = 1; i <= 4; i++) {
                        if ((ipaddr[i] < 0) || (ipaddr[i] > 255)) valid = 0
                        if ((i = 4) && ($1 == "netmask")){
                          split(ipaddr[4],lastoctet,"\\/")
                          if((lastoctet[1]<0) || (lastoctet[1]>255)) valid = 0
                          if((lastoctet[2]<0) || (lastoctet[2]>32)) valid = 0
                        }
                        else if ((ipaddr[i] < 0) || (ipaddr[i] > 255)) valid = 0
                }
        }

        if (valid == 0) verr = "@TR<<Invalid value>>"
}

Fields that require netmask, such as now send "netmask" instead of "ip" to the validator. This is nice for source and destination firewall rules. I think the only place is these lines:
/www/cgi-bin/webif/firewall.sh

int|proto_valid|@TR<<Protocol>>||$proto_valid
string|FORM_target|@TR<<Target>>|required|$FORM_target
string|FORM_proto|@TR<<Protocol>>||$FORM_proto
netmask|FORM_src|@TR<<Source IP>>||$FORM_src
netmask|FORM_dest|@TR<<Destination IP>>||$FORM_dest
ports|FORM_sport|@TR<<Source Ports>>||$FORM_sport
ports|FORM_dport|@TR<<Destination Ports>>||$FORM_dport
ip|FORM_target_ip|@TR<<Forward to>>||$FORM_target_ip
port|FORM_target_port|@TR<<Port>>||$FORM_target_port

If I knew how to submit a proper patch, I would.

EDIT: I just realized that by netmask I was refering to something like 192.168.1.0/24 whereas the origional author meant the netmask from the lan.sh, or something like 255.255.255.0. Proper netmask filtering should then be checking the IP class and seeing if the subnet mask makes sense. I think my thing is still good, but it should be called something different.. maybe ipmask, or something. Left as above someone could enter "255.255.255.0/24" into the lan.sh netmask field... not good.

EDIT2: Fixed functional mistake in line. (valid=0 was cut out by copy/paste).

(Last edited by bobpaul on 31 Jul 2006, 14:26)

In RC5 ipcalc was converted to an awk script and a few ip calculations were added to common.awk; you may want to use those instead of adding your own.

[s]Well, I can't use them because I can't figure out how to make @include work... (tried @include ../common.awk at the top of the script and was told "awk: /usr/lib/webif/validate.awk:1: Unexpected token")[/s]

But if I could use them, I would submit this:

/usr/lib/webif/validation.awk

($1 == "ip") || ($1 == "netmask") || ($1 == "ipmask"){
        valid_type = 1
        if (value != "")  #for some reason && stopped working with this...
                if (value !~ /^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\/?[0-9]*$/) valid = 0
        else {
                split(value, ipaddr, "\\/")
                if ((ipaddr[2] == "")||($1 != "ipmask"))  ipaddr[1]=value
                if (($1=="ipmask") && ((ipaddr[2]<0) || (ipaddr[2]>32))) valid = 0
                ip_int=ip2int(ipaddr[1])
                if (ipaddr[1] != int2ip(ip_int)) valid = 0
        }
        if (valid == 0) verr = "@TR<<Invalid value>>"
}

and change the firewall page accordingly:
/www/cgi-bin/webif/firewall.sh

int|proto_valid|@TR<<Protocol>>||$proto_valid
string|FORM_target|@TR<<Target>>|required|$FORM_target
string|FORM_proto|@TR<<Protocol>>||$FORM_proto
ipmask|FORM_src|@TR<<Source IP>>||$FORM_src
ipmask|FORM_dest|@TR<<Destination IP>>||$FORM_dest
ports|FORM_sport|@TR<<Source Ports>>||$FORM_sport
ports|FORM_dport|@TR<<Destination Ports>>||$FORM_dport
ip|FORM_target_ip|@TR<<Forward to>>||$FORM_target_ip
port|FORM_target_port|@TR<<Port>>||$FORM_target_port

I had to break the if statement in line 4 because it stopped working as a giant if statement for some reason. Empty values would come up as invalid, when there were previously (and should) be ignored. [s]I tested this all by copy/pasting the ip2int and int2ip functions into validate.awk, but I should be able to include /usr/lib/common.awk somehow, shouldn't I?[/s]

Edit: I fixed a minor bug above and below is how to make it use the common.awk library. I still don't know why I had to seperate that if statement into 2 seperate if statements, but it still works, so whatever. Also added bold. Later strikethroughs.

Just change the validate function in webif to also parse common.awk.
/usr/lib/webif/webif.sh/

validate() {
        if empty "$1"; then
                eval "$(awk -f /usr/lib/common.awk -f /usr/lib/webif/validate.awk)"
        else
                eval "$(echo "$1" | awk -f /usr/lib/common.awk -f /usr/lib/webif/validate.awk)"
        fi
}

(Last edited by bobpaul on 1 Aug 2006, 02:11)

I think you should try something like that :

. /path/to/your/shell/library

Well, in a shell script that would definately work but I thought awk required the include directive. Eitherway I still get the same "Unexpected token" error, and I can't find another awk script on the router that uses another *.awk as a library

Wait, I figured it out. the @include directive doesn't really exist except for the purposes of this turorial where he wrote a shell script "igawk.sh" that accepts that directive and then runs awk.

I got it working by editing the contents of /usr/lib/webif/webif.sh. I was wondering how the validate.awk script was getting called wink I also found a bug in my lasted code, so I'm going to edit the above post with the final changes that are necessary.

The discussion might have continued from here.