Package net.floodlightcontroller.firewall

Source Code of net.floodlightcontroller.firewall.FirewallRule

/**
*    Copyright 2011, Big Switch Networks, Inc.
*    Originally created by Amer Tahir
*   
*    Licensed under the Apache License, Version 2.0 (the "License"); you may
*    not use this file except in compliance with the License. You may obtain
*    a copy of the License at
*   
*         http://www.apache.org/licenses/LICENSE-2.0
*   
*    Unless required by applicable law or agreed to in writing, software
*    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
*    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
*    License for the specific language governing permissions and limitations
*    under the License.
**/

package net.floodlightcontroller.firewall;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.openflow.protocol.OFMatch;

import net.floodlightcontroller.packet.Ethernet;
import net.floodlightcontroller.packet.IPacket;
import net.floodlightcontroller.packet.IPv4;
import net.floodlightcontroller.packet.TCP;
import net.floodlightcontroller.packet.UDP;

@JsonSerialize(using=FirewallRuleSerializer.class)
public class FirewallRule implements Comparable<FirewallRule> {
    public int ruleid;

    public long dpid;
    public short in_port;
    public long dl_src;
    public long dl_dst;
    public short dl_type;
    public int nw_src_prefix;
    public int nw_src_maskbits;
    public int nw_dst_prefix;
    public int nw_dst_maskbits;
    public short nw_proto;
    public short tp_src;
    public short tp_dst;

    public boolean wildcard_dpid;
    public boolean wildcard_in_port;
    public boolean wildcard_dl_src;
    public boolean wildcard_dl_dst;
    public boolean wildcard_dl_type;
    public boolean wildcard_nw_src;
    public boolean wildcard_nw_dst;
    public boolean wildcard_nw_proto;
    public boolean wildcard_tp_src;
    public boolean wildcard_tp_dst;

    public int priority = 0;

    public FirewallAction action;

    public enum FirewallAction {
        /*
         * DENY: Deny rule
         * ALLOW: Allow rule
         */
        DENY, ALLOW
    }

    public FirewallRule() {
        this.in_port = 0;
        this.dl_src = 0;
        this.nw_src_prefix = 0;
        this.nw_src_maskbits = 0;
        this.dl_dst = 0;
        this.nw_proto = 0;
        this.tp_src = 0;
        this.tp_dst = 0;
        this.dl_dst = 0;
        this.nw_dst_prefix = 0;
        this.nw_dst_maskbits = 0;
        this.dpid = -1;
        this.wildcard_dpid = true;
        this.wildcard_in_port = true;
        this.wildcard_dl_src = true;
        this.wildcard_dl_dst = true;
        this.wildcard_dl_type = true;
        this.wildcard_nw_src = true;
        this.wildcard_nw_dst = true;
        this.wildcard_nw_proto = true;
        this.wildcard_tp_src = true;
        this.wildcard_tp_dst = true;
        this.priority = 0;
        this.action = FirewallAction.ALLOW;
        this.ruleid = 0;
    }

    /**
     * Generates a unique ID for the instance
     *
     * @return int representing the unique id
     */
    public int genID() {
        int uid = this.hashCode();
        if (uid < 0) {
            uid = Math.abs(uid);
            uid = uid * 15551;
        }
        return uid;
    }

    /**
     * Comparison method for Collections.sort method
     *
     * @param rule
     *            the rule to compare with
     * @return number representing the result of comparison 0 if equal negative
     *         if less than 'rule' greater than zero if greater priority rule
     *         than 'rule'
     */
    @Override
    public int compareTo(FirewallRule rule) {
        return this.priority - rule.priority;
    }

    /**
     * Determines if this instance matches an existing rule instance
     *
     * @param r
     *            : the FirewallRule instance to compare with
     * @return boolean: true if a match is found
     **/
    public boolean isSameAs(FirewallRule r) {
        if (this.action != r.action
                || this.wildcard_dl_type != r.wildcard_dl_type
                || (this.wildcard_dl_type == false && this.dl_type != r.dl_type)
                || this.wildcard_tp_src != r.wildcard_tp_src
                || (this.wildcard_tp_src == false && this.tp_src != r.tp_src)
                || this.wildcard_tp_dst != r.wildcard_tp_dst
                || (this.wildcard_tp_dst == false &&this.tp_dst != r.tp_dst)
                || this.wildcard_dpid != r.wildcard_dpid
                || (this.wildcard_dpid == false && this.dpid != r.dpid)
                || this.wildcard_in_port != r.wildcard_in_port
                || (this.wildcard_in_port == false && this.in_port != r.in_port)
                || this.wildcard_nw_src != r.wildcard_nw_src
                || (this.wildcard_nw_src == false && (this.nw_src_prefix != r.nw_src_prefix || this.nw_src_maskbits != r.nw_src_maskbits))
                || this.wildcard_dl_src != r.wildcard_dl_src
                || (this.wildcard_dl_src == false && this.dl_src != r.dl_src)
                || this.wildcard_nw_proto != r.wildcard_nw_proto
                || (this.wildcard_nw_proto == false && this.nw_proto != r.nw_proto)
                || this.wildcard_nw_dst != r.wildcard_nw_dst
                || (this.wildcard_nw_dst == false && (this.nw_dst_prefix != r.nw_dst_prefix || this.nw_dst_maskbits != r.nw_dst_maskbits))
                || this.wildcard_dl_dst != r.wildcard_dl_dst               
                || (this.wildcard_dl_dst == false && this.dl_dst != r.dl_dst)) {
            return false;
        }
        return true;
    }

    /**
     * Matches this rule to a given flow - incoming packet
     *
     * @param switchDpid
     *            the Id of the connected switch
     * @param inPort
     *            the switch port where the packet originated from
     * @param packet
     *            the Ethernet packet that arrives at the switch
     * @param wildcards
     *            the pair of wildcards (allow and deny) given by Firewall
     *            module that is used by the Firewall module's matchWithRule
     *            method to derive wildcards for the decision to be taken
     * @return true if the rule matches the given packet-in, false otherwise
     */
    public boolean matchesFlow(long switchDpid, short inPort, Ethernet packet,
            WildcardsPair wildcards) {
        IPacket pkt = packet.getPayload();

        // dl_type type
        IPv4 pkt_ip = null;

        // nw_proto types
        TCP pkt_tcp = null;
        UDP pkt_udp = null;

        // tp_src and tp_dst (tp port numbers)
        short pkt_tp_src = 0;
        short pkt_tp_dst = 0;

        // switchID matches?
        if (wildcard_dpid == false && dpid != switchDpid)
            return false;

        // in_port matches?
        if (wildcard_in_port == false && in_port != inPort)
            return false;
        if (action == FirewallRule.FirewallAction.DENY) {
            wildcards.drop &= ~OFMatch.OFPFW_IN_PORT;
        } else {
            wildcards.allow &= ~OFMatch.OFPFW_IN_PORT;
        }

        // mac address (src and dst) match?
        if (wildcard_dl_src == false
                && dl_src != packet.getSourceMAC().toLong())
            return false;
        if (action == FirewallRule.FirewallAction.DENY) {
            wildcards.drop &= ~OFMatch.OFPFW_DL_SRC;
        } else {
            wildcards.allow &= ~OFMatch.OFPFW_DL_SRC;
        }

        if (wildcard_dl_dst == false
                && dl_dst != packet.getDestinationMAC().toLong())
            return false;
        if (action == FirewallRule.FirewallAction.DENY) {
            wildcards.drop &= ~OFMatch.OFPFW_DL_DST;
        } else {
            wildcards.allow &= ~OFMatch.OFPFW_DL_DST;
        }

        // dl_type check: ARP, IP

        // if this is not an ARP rule but the pkt is ARP,
        // return false match - no need to continue protocol specific check
        if (wildcard_dl_type == false) {
            if (dl_type == Ethernet.TYPE_ARP) {
                if (packet.getEtherType() != Ethernet.TYPE_ARP)
                    return false;
                else {
                    if (action == FirewallRule.FirewallAction.DENY) {
                        wildcards.drop &= ~OFMatch.OFPFW_DL_TYPE;
                    } else {
                        wildcards.allow &= ~OFMatch.OFPFW_DL_TYPE;
                    }
                }
            } else if (dl_type == Ethernet.TYPE_IPv4) {
                if (packet.getEtherType() != Ethernet.TYPE_IPv4)
                    return false;
                else {
                    if (action == FirewallRule.FirewallAction.DENY) {
                        wildcards.drop &= ~OFMatch.OFPFW_NW_PROTO;
                    } else {
                        wildcards.allow &= ~OFMatch.OFPFW_NW_PROTO;
                    }
                    // IP packets, proceed with ip address check
                    pkt_ip = (IPv4) pkt;

                    // IP addresses (src and dst) match?
                    if (wildcard_nw_src == false
                            && this.matchIPAddress(nw_src_prefix,
                                    nw_src_maskbits, pkt_ip.getSourceAddress()) == false)
                        return false;
                    if (action == FirewallRule.FirewallAction.DENY) {
                        wildcards.drop &= ~OFMatch.OFPFW_NW_SRC_ALL;
                        wildcards.drop |= (nw_src_maskbits << OFMatch.OFPFW_NW_SRC_SHIFT);
                    } else {
                        wildcards.allow &= ~OFMatch.OFPFW_NW_SRC_ALL;
                        wildcards.allow |= (nw_src_maskbits << OFMatch.OFPFW_NW_SRC_SHIFT);
                    }

                    if (wildcard_nw_dst == false
                            && this.matchIPAddress(nw_dst_prefix,
                                    nw_dst_maskbits,
                                    pkt_ip.getDestinationAddress()) == false)
                        return false;
                    if (action == FirewallRule.FirewallAction.DENY) {
                        wildcards.drop &= ~OFMatch.OFPFW_NW_DST_ALL;
                        wildcards.drop |= (nw_dst_maskbits << OFMatch.OFPFW_NW_DST_SHIFT);
                    } else {
                        wildcards.allow &= ~OFMatch.OFPFW_NW_DST_ALL;
                        wildcards.allow |= (nw_dst_maskbits << OFMatch.OFPFW_NW_DST_SHIFT);
                    }

                    // nw_proto check
                    if (wildcard_nw_proto == false) {
                        if (nw_proto == IPv4.PROTOCOL_TCP) {
                            if (pkt_ip.getProtocol() != IPv4.PROTOCOL_TCP)
                                return false;
                            else {
                                pkt_tcp = (TCP) pkt_ip.getPayload();
                                pkt_tp_src = pkt_tcp.getSourcePort();
                                pkt_tp_dst = pkt_tcp.getDestinationPort();
                            }
                        } else if (nw_proto == IPv4.PROTOCOL_UDP) {
                            if (pkt_ip.getProtocol() != IPv4.PROTOCOL_UDP)
                                return false;
                            else {
                                pkt_udp = (UDP) pkt_ip.getPayload();
                                pkt_tp_src = pkt_udp.getSourcePort();
                                pkt_tp_dst = pkt_udp.getDestinationPort();
                            }
                        } else if (nw_proto == IPv4.PROTOCOL_ICMP) {
                            if (pkt_ip.getProtocol() != IPv4.PROTOCOL_ICMP)
                                return false;
                            else {
                                // nothing more needed for ICMP
                            }
                        }
                        if (action == FirewallRule.FirewallAction.DENY) {
                            wildcards.drop &= ~OFMatch.OFPFW_NW_PROTO;
                        } else {
                            wildcards.allow &= ~OFMatch.OFPFW_NW_PROTO;
                        }

                        // TCP/UDP source and destination ports match?
                        if (pkt_tcp != null || pkt_udp != null) {
                            // does the source port match?
                            if (tp_src != 0 && tp_src != pkt_tp_src)
                                return false;
                            if (action == FirewallRule.FirewallAction.DENY) {
                                wildcards.drop &= ~OFMatch.OFPFW_TP_SRC;
                            } else {
                                wildcards.allow &= ~OFMatch.OFPFW_TP_SRC;
                            }

                            // does the destination port match?
                            if (tp_dst != 0 && tp_dst != pkt_tp_dst)
                                return false;
                            if (action == FirewallRule.FirewallAction.DENY) {
                                wildcards.drop &= ~OFMatch.OFPFW_TP_DST;
                            } else {
                                wildcards.allow &= ~OFMatch.OFPFW_TP_DST;
                            }
                        }
                    }

                }
            } else {
                // non-IP packet - not supported - report no match
                return false;
            }
        }
        if (action == FirewallRule.FirewallAction.DENY) {
            wildcards.drop &= ~OFMatch.OFPFW_DL_TYPE;
        } else {
            wildcards.allow &= ~OFMatch.OFPFW_DL_TYPE;
        }

        // all applicable checks passed
        return true;
    }

    /**
     * Determines if rule's CIDR address matches IP address of the packet
     *
     * @param rulePrefix
     *            prefix part of the CIDR address
     * @param ruleBits
     *            the size of mask of the CIDR address
     * @param packetAddress
     *            the IP address of the incoming packet to match with
     * @return true if CIDR address matches the packet's IP address, false
     *         otherwise
     */
    protected boolean matchIPAddress(int rulePrefix, int ruleBits,
            int packetAddress) {
        boolean matched = true;

        int rule_iprng = 32 - ruleBits;
        int rule_ipint = rulePrefix;
        int pkt_ipint = packetAddress;
        // if there's a subnet range (bits to be wildcarded > 0)
        if (rule_iprng > 0) {
            // right shift bits to remove rule_iprng of LSB that are to be
            // wildcarded
            rule_ipint = rule_ipint >> rule_iprng;
            pkt_ipint = pkt_ipint >> rule_iprng;
            // now left shift to return to normal range, except that the
            // rule_iprng number of LSB
            // are now zeroed
            rule_ipint = rule_ipint << rule_iprng;
            pkt_ipint = pkt_ipint << rule_iprng;
        }
        // check if we have a match
        if (rule_ipint != pkt_ipint)
            matched = false;

        return matched;
    }

    @Override
    public int hashCode() {
        final int prime = 2521;
        int result = super.hashCode();
        result = prime * result + (int) dpid;
        result = prime * result + in_port;
        result = prime * result + (int) dl_src;
        result = prime * result + (int) dl_dst;
        result = prime * result + dl_type;
        result = prime * result + nw_src_prefix;
        result = prime * result + nw_src_maskbits;
        result = prime * result + nw_dst_prefix;
        result = prime * result + nw_dst_maskbits;
        result = prime * result + nw_proto;
        result = prime * result + tp_src;
        result = prime * result + tp_dst;
        result = prime * result + action.ordinal();
        result = prime * result + priority;
        result = prime * result + (new Boolean(wildcard_dpid)).hashCode();
        result = prime * result + (new Boolean(wildcard_in_port)).hashCode();
        result = prime * result + (new Boolean(wildcard_dl_src)).hashCode();
        result = prime * result + (new Boolean(wildcard_dl_dst)).hashCode();
        result = prime * result + (new Boolean(wildcard_dl_type)).hashCode();
        result = prime * result + (new Boolean(wildcard_nw_src)).hashCode();
        result = prime * result + (new Boolean(wildcard_nw_dst)).hashCode();
        result = prime * result + (new Boolean(wildcard_nw_proto)).hashCode();
        result = prime * result + (new Boolean(wildcard_tp_src)).hashCode();
        result = prime * result + (new Boolean(wildcard_tp_dst)).hashCode();
        return result;
    }
}
TOP

Related Classes of net.floodlightcontroller.firewall.FirewallRule

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.