示例#1
0
文件: ovs.py 项目: yapkke/yapc
    def __process_switch_json(self, event):
        """Process JSON messages for switch

        @param event JSON message event for switch
        """
        reply = {}
        reply["type"] = "coin"
        reply["subtype"] = "ovs"

        if event.message["command"] == "add_if":
            self.add_if(event.message["name"])
            reply["executed"] = True
        elif event.message["command"] == "del_if":
            self.datapaths[COIN_DP_NAME].del_if(event.message["name"])
            reply["executed"] = True
        elif event.message["command"] == "get_interfaces":
            dpidsl = mc.get(swstate.dp_features.DP_SOCK_LIST)
            if dpidsl != None:
                reply["interfaces"] = []
                if len(dpidsl) > 1:
                    output.warn(str(len(dpidsl)) + " datapaths connected to COIN", self.__class__.__name__)
                f = mc.get(dpidsl[0])
                output.dbg("Updated switch features:\n" + f.show("\t"), self.__class__.__name__)
                for p in f.ports:
                    reply["interfaces"].append(p.name)
            else:
                output.warn("No datapaths connected to COIN", self.__class__.__name__)
                reply["error"] = "No datapath connected"
        else:
            reply["error"] = "Unknown command"

        return reply
示例#2
0
文件: nat.py 项目: yapkke/yapc
 def get_intf_n_range(self):
     """Retrieve dictionary of interface and their ip range
     """
     r = {}
     sf = mc.get(nat.SW_FEATURE)
     for p in sf.ports:
         ipr = mc.get(nat.get_ip_range_key(p.port_no))
         if ipr != None:
             r[p.port_no] = ipr
     return r
示例#3
0
文件: switches.py 项目: yapkke/yapc
    def processevent(self, event):
        """Process OpenFlow message for switch status
        
        @param event OpenFlow message event to process
        @return True
        """
        if isinstance(event, ofevents.features_reply):
            # Maintain list of datapath socket
            key = self.get_key(event.sock)
            dpidsl = mc.get(dp_features.DP_SOCK_LIST)
            if dpidsl == None:
                dpidsl = []
            if key not in dpidsl:
                dpidsl.append(key)
            mc.set(dp_features.DP_SOCK_LIST, dpidsl)

            # Maintain dp features in memcache
            mc.set(key, event.features)

        elif isinstance(event, ofevents.port_status):
            # Port status
            if event.header.type == pyof.OFPT_PORT_STATUS:
                key = self.get_key(event.sock)
                sw = mc.get(key)
                if sw == None:
                    output.warn("Port status from unknown datapath", self.__class__.__name__)
                else:
                    output.dbg("Received port status:\n" + event.port.show("\t"), self.__class__.__name__)
                    if event.port.reason == pyof.OFPPR_DELETE or event.port.reason == pyof.OFPPR_MODIFY:
                        for p in sw.ports:
                            if p.port_no == event.port.desc.port_no:
                                sw.ports.remove(p)
                    if event.port.reason == pyof.OFPPR_ADD or event.port.reason == pyof.OFPPR_MODIFY:
                        sw.ports.append(event.port.desc)
                    output.dbg("Updated switch features:\n" + sw.show("\t"), self.__class__.__name__)
                    mc.set(key, sw)

        elif isinstance(event, comm.event):
            # Socket close
            if event.event == comm.event.SOCK_CLOSE:
                key = self.get_key(event.sock)
                sw = mc.get(key)
                if sw != None:
                    output.info("Datapath %x leaves" % sw.datapath_id, self.__class__.__name__)
                    # Maintain list of datapath socket
                    dpidsl = mc.get(dp_features.DP_SOCK_LIST)
                    if dpidsl != None:
                        if key in dpidsl:
                            dpidsl.remove(key)
                        mc.set(dp_features.DP_SOCK_LIST, dpidsl)

                    # Remove features
                    mc.delete(key)

        return True
示例#4
0
文件: bridge.py 项目: yapkke/yapc
    def get_ext_intf(self):
        """Retrieve dictionary of external ports
        """
        r = {}
        sf = mc.get(bridge.SW_FEATURE)
        iport = mc.get(bridge.SW_INNER_PORT)
        for p in sf.ports:
            if (p.port_no != iport) and (p.port_no <= pyof.OFPP_MAX):
                r[p.port_no] = p.name

        return r
示例#5
0
文件: nat.py 项目: yapkke/yapc
    def _process_inbound(self, pktin, intfs, iport, lointf):
        """Event handler for inbound packet

        @param pktin packet in event to handle
        @param intfs dictionary of interfaces (with ip range)
        @param iport port no of local interface
        @param lointf local interface address (ip, mac)
        @return false
        """
        try:
            ipr = intfs[pktin.match.in_port]
        except KeyError:
            output.vdbg("IP packet received on unknown/uninitialized interface", self.__class__.__name__)
            return False

        if ipr[2] != pktin.match.dl_dst:
            return False

        flow = flows.exact_entry(pktin.match)
        flow.add_nw_rewrite(False, lointf[0])
        flow.add_dl_rewrite(False, lointf[1])
        flow.add_output(iport)
        if pktin.pktin.buffer_id != flow.buffer_id:
            flow.set_buffer(pktin.pktin.buffer_id)
            self.get_conn().send(flow.get_flow_mod(pyof.OFPFC_ADD, cookie=self.cookie).pack())
            self.cookie += 1
        else:
            self.get_conn().send(flow.get_flow_mod(pyof.OFPFC_ADD, cookie=self.cookie).pack())
            self.cookie += 1
            ofpkt.nw_rewrite(pktin.dpkt, False, lointf[0])
            ofpkt.dl_rewrite(pktin.dpkt, False, lointf[1])
            self.get_conn().send(flow.get_packet_out(pyof.OFPFC_ADD).pack() + pktin.dpkt.pack())

        gw = mc.get(nat.get_gw_key(flow.match.in_port))
        gwmac = mc.get(nat.get_gw_mac_key(gw))
        if gwmac == None:
            return False

        if (ipr[0] & ipr[1]) != (pktin.match.nw_src & ipr[1]):
            # Global address
            rflow = flow.reverse(iport)
            rflow.match.nw_src = lointf[0]
            rflow.match.dl_src = lointf[1]
            rflow.add_nw_rewrite(True, ipr[0])
            rflow.add_dl_rewrite(True, ipr[2])
            rflow.add_dl_rewrite(False, pu.hex_str2array(gwmac))
            rflow.add_output(flow.match.in_port)
            if (rflow.match.wildcards & pyof.OFPFW_DL_TYPE) != 0:
                output.dbg(rflow.match.show(), self.__class__.__name__)
            self.get_conn().send(rflow.get_flow_mod(pyof.OFPFC_ADD, cookie=self.cookie).pack())
            self.cookie += 1

        return False
示例#6
0
文件: ovs.py 项目: yapkke/yapc
 def get_sw_feature(self):
     """Get switch description
     
     @return switch features else None
     """
     dpidsl = mc.get(swstate.dp_features.DP_SOCK_LIST)
     if dpidsl != None:
         if len(dpidsl) > 1:
             output.warn(str(len(dpidsl)) + " datapaths connected to COIN", self.__class__.__name__)
         f = mc.get(dpidsl[0])
         return f
     else:
         return None
示例#7
0
文件: nat.py 项目: yapkke/yapc
    def processevent(self, event):
        """Event handler

        @param event event to handle
        @return false if processed else true
        """
        if isinstance(event, yapc.priv_callback):
            self.__sf = mc.get(nat.SW_FEATURE)
            if self.__sf != None:
                bwquery = ns.bandwidth_query(ns.bandwidth_query.MODE_TOTAL_MAX)
                for p in self.__sf.ports:
                    if mc.get(nat.get_ip_range_key(p.port_no)) != None:
                        # Port exist
                        bwquery.interfaces.append(p.name)
                if len(bwquery.interfaces) != 0:
                    self.server.post_event(bwquery)

            # Query for bandwidth of intervals
            if self.bwinterval != 0:
                self.server.post_event(yapc.priv_callback(self), self.bwinterval)

        elif isinstance(event, coini.queryresponse) and isinstance(event.query, ns.bandwidth_query):
            for p in self.__sf.ports:
                if event.response[0]["interface"] == p.name:
                    self.max_bw_port = p.port_no
                    output.vdbg(
                        "Port " + str(p.port_no) + "(" + str(p.name) + ") has most bandwidth", self.__class__.__name__
                    )

        elif (
            isinstance(event, ofevents.pktin)
            and
            # Handle packet in
            event.match.dl_type == dpkt.ethernet.ETH_TYPE_IP
        ):
            iport = mc.get(nat.SW_INNER_PORT)
            intfs = self.get_intf_n_range()
            lointf = mc.get(nat.SW_INNER_PORT_ADDR)
            if iport == None:
                output.err("No inner port recorded!  Are we connected?", self.__class__.__name__)
                return True

            if event.match.in_port == iport:
                return self._process_outbound(event, intfs, iport, lointf)
            else:
                return self._process_inbound(event, intfs, iport, lointf)

        return True
示例#8
0
文件: bridge.py 项目: yapkke/yapc
    def processevent(self, event):
        """Event handler

        @param event event to handle
        @return false if processed else true
        """
        if isinstance(event, ofevents.pktin):
            iport = mc.get(bridge.SW_INNER_PORT)
            intfs = self.get_ext_intf()
            if iport == None:
                output.err("No inner port recorded!  Are we connected?", self.__class__.__name__)
                return True

            flow = flows.exact_entry(event.match)
            if event.match.in_port == iport:
                flow.add_output(self.get_out_port(intfs))
            else:
                flow.add_output(iport)

            if flow.buffer_id != event.pktin.buffer_id:
                flow.set_buffer(event.pktin.buffer_id)
                self.get_conn().send(flow.get_flow_mod(pyof.OFPFC_ADD).pack())
            else:
                self.get_conn().send(flow.get_flow_mod(pyof.OFPFC_ADD).pack())
                self.get_conn().send(flow.get_packet_out(pyof.OFPFC_ADD).pack() + event.dpkt.pack())
                return False

        return True
示例#9
0
def host_authenticated(host):
    """Return if host is authenticated
    """
    au = mcutil.get(host_auth.get_key(host))
    if (au == None):
        return False
    else:
        return True
示例#10
0
def host_auth_server(host):
    """Return server host is going to authenticate with
    """
    au = mcutil.get(host_auth.get_auth_key(host))
    if (au == None):
        return None
    else:
        return au
示例#11
0
def host_authenticated(host):
    """Return if host is authenticated
    """
    au = mcutil.get(host_auth.get_key(host))
    if (au == None):
        return False
    else:
        return True
示例#12
0
def host_auth_server(host):
    """Return server host is going to authenticate with
    """
    au = mcutil.get(host_auth.get_auth_key(host))
    if (au == None):
        return None
    else:
        return au
示例#13
0
文件: nat.py 项目: yapkke/yapc
    def processevent(self, event):
        """Event handler (for ARP only)

        @param event event to handle
        @return false if processed else true
        """
        if isinstance(event, ofevents.pktin) and event.match.dl_type == dpkt.ethernet.ETH_TYPE_ARP:
            iport = mc.get(nat.SW_INNER_PORT)
            intfs = self.get_intf_n_range()
            lointf = mc.get(nat.SW_INNER_PORT_ADDR)
            if iport == None:
                output.err("No inner port recorded!  Are we connected?", self.__class__.__name__)
                return True

            if event.match.in_port == iport:
                return self._process_outbound(event, intfs, iport, lointf)
            else:
                return self._process_inbound(event, intfs, iport, lointf)

        return True
示例#14
0
文件: switches.py 项目: yapkke/yapc
    def processevent(self, event):
        """Process OpenFlow message for config reply
        
        @param event OpenFlow message event to process
        @return True
        """
        if isinstance(event, ofevents.features_reply):
            # Get config
            getconfig = pyof.ofp_header()
            getconfig.type = pyof.OFPT_GET_CONFIG_REQUEST
            self.conn.send(event.sock, getconfig.pack())

        elif isinstance(event, ofevents.config_reply):
            # Check if I should set config
            desired_flags = (event.config.flags | self.default_on_config_flags) & ~self.default_off_config_flags
            desired_miss_send_len = event.config.miss_send_len
            if self.default_miss_send_len != None:
                desired_miss_send_len = self.default_miss_send_len
            if (event.config.flags != desired_flags) or (desired_miss_send_len != event.config.miss_send_len):
                # Change config to desired
                output.dbg(
                    "Set config to desired with flag %x " % desired_flags
                    + "and miss_send_len "
                    + str(desired_miss_send_len),
                    self.__class__.__name__,
                )
                setconfig = pyof.ofp_switch_config()
                setconfig.header.type = pyof.OFPT_SET_CONFIG
                setconfig.flags = desired_flags
                setconfig.miss_send_len = desired_miss_send_len
                self.conn.send(event.sock, setconfig.pack())

                # Get config again after set
                getconfig = pyof.ofp_header()
                getconfig.type = pyof.OFPT_GET_CONFIG_REQUEST
                self.conn.send(event.sock, getconfig.pack())
            else:
                # Remember config
                key = self.get_key(event.sock)
                mc.set(key, event.config)
                output.dbg("Updated config with key " + key, self.__class__.__name__)

        elif isinstance(event, comm.event):
            # Socket close, so remove config
            if event.event == comm.event.SOCK_CLOSE:
                key = self.get_key(event.sock)
                c = mc.get(key)
                if c != None:
                    mc.delete(key)

        return True
示例#15
0
文件: bridge.py 项目: yapkke/yapc
    def processevent(self, event):
        """Event handler

        @param event event to handle
        @return True
        """
        if isinstance(event, ofevents.pktin):
            self.check_timeout()
            iport = mc.get(bridge.SW_INNER_PORT)
            intfs = self.get_ext_intf()
            if iport == None:
                output.err("No inner port recorded!  Are we connected?", self.__class__.__name__)
                return True

            flow = flows.exact_entry(event.match)

            # Change IP?
            if flow.match.nw_src in self.ip_change:
                new_ip = flow.match.nw_src
                old_ip = self.ip_change[new_ip][0]

                flow.add_nw_rewrite(True, old_ip)
                ofpkt.nw_rewrite(event.dpkt, True, old_ip)
                output.dbg("Adding rewrite for changing flow", self.__class__.__name__)

                ipflow = flows.ethertype_entry(dpkt.ethernet.ETH_TYPE_IP)
                ipflow.set_nw_dst(old_ip)
                (sr, fsr) = ipflow.get_flow_stats_request()
                self.get_conn().send(sr.pack() + fsr.pack())

            # Decide output port
            if event.match.in_port == iport:
                flow.add_output(self.get_out_port(intfs))
            else:
                flow.add_output(iport)

            # Send appropriately
            if flow.buffer_id != event.pktin.buffer_id:
                flow.set_buffer(event.pktin.buffer_id)
                self.get_conn().send(flow.get_flow_mod(pyof.OFPFC_ADD).pack())
            else:
                self.get_conn().send(flow.get_flow_mod(pyof.OFPFC_ADD).pack())
                self.get_conn().send(flow.get_packet_out(pyof.OFPFC_ADD).pack() + event.dpkt.pack())
                return False

        elif isinstance(event, udpjson.message):
            self._handle_json(event)
        elif isinstance(event, ofevents.flow_stats):
            self._handle_change(event)

        return True
示例#16
0
文件: bridge.py 项目: yapkke/yapc
    def processevent(self, event):
        """Event handler

        @param event event to handle
        @return True
        """
        if isinstance(event, ofevents.pktin):
            self.check_timeout()
            iport = mc.get(bridge.SW_INNER_PORT)
            intfs = self.get_ext_intf()
            if iport == None:
                output.err("No inner port recorded!  Are we connected?", self.__class__.__name__)
                return True

            flow = flows.exact_entry(event.match)

            # Indirection given?
            if flow.match.nw_src in self.m2m:
                from_ip = flow.match.nw_dst
                from_eth = flow.match.dl_dst[:]
                to_eth = flow.match.dl_src[:]
                to_ip = self.m2m[from_ip][0]

                flow.add_nw_rewrite(True, from_ip)
                flow.add_dl_rewrite(True, from_eth)
                flow.add_nw_rewrite(False, to_ip)
                flow.add_dl_rewrite(False, to_eth)

                ofpkt.nw_rewrite(event.dpkt, True, from_ip)
                ofpkt.dl_rewrite(event.dpkt, True, from_eth)
                ofpkt.nw_rewrite(event.dpkt, False, to_ip)
                ofpkt.dl_rewrite(event.dpkt, False, to_eth)

                flow.add_output(py.OFPP_IN_PORT)

                if flow.buffer_id != event.pktin.buffer_id:
                    flow.set_buffer(event.pktin.buffer_id)
                    self.get_conn().send(flow.get_flow_mod(pyof.OFPFC_ADD).pack())
                else:
                    self.get_conn().send(flow.get_flow_mod(pyof.OFPFC_ADD).pack())
                    self.get_conn().send(flow.get_packet_out(pyof.OFPFC_ADD).pack() + event.dpkt.pack())

                output.dbg("Indirecting flow...", self.__class__.__name__)

                return False

        elif isinstance(event, udpjson.message):
            self._handle_json(event)

        return True
示例#17
0
    def processevent(self, event):
        """Event handler

        @param event event to handle
        @return false if flow can be installed, else true
        """
        if (isinstance(event, ofevents.pktin)):
            #Forward packet/flow
            if (pu.is_multicast_mac(event.match.dl_dst)):
                return True
            
            key = swhost.mac2sw_binding.get_key(event.sock,
                                                event.match.dl_dst)
            port = mc.get(key)
            if (port != None):
                self.installflow(event, port)
                return False
            else:
                output.dbg("No binding found for mac %x"  % pu.array2val(event.match.dl_dst),
                           self.__class__.__name__)
            
        return True     
示例#18
0
    def processevent(self, event):
        """Handle event
        """
        if isinstance(event, ofevents.pktin):
            #Check for LLDP and discover/maintain links
            if (event.dpkt.type == lldppkt.LLDP_ETH):
                lldp = lldppkt.LLDP(event.dpkt.data)
                src_dpid = int(lldp.value[1:], 16)
                src_port = int(lldp.data.value[1:])
                dst_dpid = self.conn.db[event.sock].dpid
                dst_port = event.pktin.in_port
                self.link_maintain.update(src_dpid, src_port,
                                          dst_dpid, dst_port)
                output.vdbg("%x:" % dst_dpid + str(dst_port)+\
                            " receive LLDP packet from %x" % src_dpid+\
                            ":"+str(src_port),
                            self.__class__.__name__)
                
                return False
        
        elif isinstance(event, ofevents.port_status):
            #New port, so let's try to find a new link fast
            self.send_lldp(self.conn.db[event.sock].dpid,
                           event.port.desc)

        elif isinstance(event, ofevents.features_reply):
            #New switch, so let's try to find new links fast
            for p in event.features.ports:
                self.send_lldp(event.features.datapath_id, p)

        elif isinstance(event, yapc.priv_callback):
            if (event.magic ==True):
                #Periodic enumeration of switch port to maintain
                dpidsl = mc.get(swstate.dp_features.DP_SOCK_LIST)
                if (dpidsl != None):
                    for key in dpidsl:
                        sw = mc.get(key)
                        for p in sw.ports:
                            if (p.port_no <= pyof.OFPP_MAX and
                                (sw.datapath_id, p) not in self.__sw_port):
                                self.__sw_port.append((sw.datapath_id, p))
                    if (len(self.__sw_port) != 0):
                        self.__minterval = float(self.interval)/len(self.__sw_port)
                        self.server.post_event(yapc.priv_callback(self, False),0)
                    output.vdbg("Gather "+str(len(self.__sw_port))+" to send LLDP to",
                               self.__class__.__name__)
                else:
                    output.dbg("No switch port to send LLDP to",
                               self.__class__.__name__)
                self.server.post_event(yapc.priv_callback(self, True),
                                  self.interval)
            else:
                #Sending of LLDP for maintenance
                if (len(self.__sw_port) > 0):
                    (sw,port) = self.__sw_port.pop()
                    self.send_lldp(sw, port)
                    self.server.post_event(yapc.priv_callback(self, False),
                                           self.__minterval)
                self.link_maintain.check_expire()
                
        return True
示例#19
0
    def processevent(self, event):
        """Process event
        """
        if (isinstance(event, ofevents.pktin)):
            ##Allow flow to authenticate even when yet authenticated
            if ((event.match.nw_dst == AUTH_DST_IP and
                 (event.match.tp_dst == AUTH_DST_PORT1 or event.match.tp_dst == AUTH_DST_PORT2)) or
                (event.match.nw_src == AUTH_DST_IP and
                 (event.match.tp_src == AUTH_DST_PORT1 or event.match.tp_src == AUTH_DST_PORT2))):
                if (event.match.nw_dst == AUTH_DST_IP and event.match.tp_dst == 8080):
                    owglobal.last_host_redirect = (self.conn.db[event.sock].dpid,
                                                   event.match.dl_src)
                output.dbg("Approving "+\
                               pu.ip_val2string(event.match.nw_src) + ":"+str(event.match.tp_src)+\
                               "=>"+\
                               pu.ip_val2string(event.match.nw_dst) + ":"+str(event.match.tp_dst),
                           self.__class__.__name__)
                return True

            #Authenticated host
            if (host_authenticated(event.match.dl_src) or 
                host_authenticated(event.match.dl_dst)):
                output.vdbg("Authenticated host flow "+\
                                pu.ip_val2string(event.match.nw_src) + ":"+str(event.match.tp_src)+\
                                "=>"+\
                                pu.ip_val2string(event.match.nw_dst) + ":"+str(event.match.tp_dst),
                            self.__class__.__name__)
                return True

            ##Allow special website access without authentication
            if (event.match.nw_dst in BYPASS_IP or
                event.match.nw_src in BYPASS_IP):
                output.dbg("Allow bypass for special server",
                           self.__class__.__name__)
                return True

            ##Allow 
            # (1) ARP
            # (2) ICMP
            # (3) DHCP
            # (4) DNS
            if ((event.match.dl_type == dpkt.ethernet.ETH_TYPE_ARP) or 
                (event.match.dl_type == dpkt.ethernet.ETH_TYPE_IP and
                 event.match.nw_proto == dpkt.ip.IP_PROTO_ICMP) or 
                (event.match.dl_type == dpkt.ethernet.ETH_TYPE_IP and 
                 event.match.nw_proto == dpkt.ip.IP_PROTO_UDP and
                 (event.match.tp_dst == 67 or 
                  event.match.tp_dst == 68)) or
                (event.match.dl_type == dpkt.ethernet.ETH_TYPE_IP and 
                 event.match.nw_proto == dpkt.ip.IP_PROTO_UDP and
                 (event.match.tp_dst == 53 or event.match.tp_src == 53))):
                return True

            ##Allow route to OpenID provider (should be in HTTPS)
            if (event.match.tp_dst == HTTPS_PORT or 
                event.match.tp_dst == 8080 or 
                event.match.tp_dst == 80 or
                event.match.tp_src == HTTPS_PORT or 
                event.match.tp_src == 8080 or 
                event.match.tp_src == 80):
                auth_s = None
                if (event.match.tp_dst == HTTPS_PORT or 
                    event.match.tp_dst == 8080 or 
                    event.match.tp_dst == 80):
                    auth_s = mcutil.get(host_auth.get_auth_key(event.match.dl_src))
                else:
                    auth_s = mcutil.get(host_auth.get_auth_key(event.match.dl_dst))

                if (auth_s != None):
                    output.dbg(pu.ip_val2string(event.match.nw_dst)+" associated with "+\
                                   " auth server "+str(auth_s)+" "+str(event.match.dl_src),
                               self.__class__.__name__)
                    return True
                
            ##Redirect unauthenticated host if HTTP
            if (event.match.dl_type == dpkt.ethernet.ETH_TYPE_IP and 
                event.match.nw_proto == dpkt.ip.IP_PROTO_TCP and
                (event.match.tp_dst == 80 or event.match.tp_dst == 8080)):
                output.dbg("Redirecting %x to authenticate" % pu.array2val(event.match.dl_src),
                           self.__class__.__name__)

                #Forward flow
                flow = flows.exact_entry(event.match)
                key = swhost.mac2sw_binding.get_key(event.sock,
                                                    event.match.dl_dst)
                port = mcutil.get(key)
                if (port != None):
                    flow.set_buffer(event.pktin.buffer_id)
                    flow.add_nw_rewrite(False, AUTH_DST_IP)
                    flow.add_output(port)
                    self.conn.send(event.sock,flow.get_flow_mod(pyof.OFPFC_MODIFY).pack())
                    
                    #Reverse flow
                    rflow = flow.reverse(port)
                    rflow.match.nw_src = AUTH_DST_IP
                    rflow.add_nw_rewrite(True, event.match.nw_dst)
                    rflow.add_output(event.pktin.in_port)
                    self.conn.send(event.sock,rflow.get_flow_mod(pyof.OFPFC_MODIFY).pack())
                
                return False
           
            #Drop remaining flows
            flow = flows.exact_entry(event.match)
            flow.set_buffer(event.pktin.buffer_id)
            self.conn.send(event.sock,flow.get_flow_mod(pyof.OFPFC_ADD).pack())
            output.dbg("Dropping "+\
                           pu.ip_val2string(event.match.nw_src) + ":"+str(event.match.tp_src)+\
                           "=>"+pu.ip_val2string(event.match.nw_dst) + ":"+str(event.match.tp_dst),
                       self.__class__.__name__)
            return False

        return True
示例#20
0
文件: nat.py 项目: yapkke/yapc
    def _process_outbound(self, pktin, intfs, iport, lointf):
        """Event handler for outbound IP packet

        @param pktin packet in event to handle
        @param intfs dictionary of interfaces (with ip range)
        @param iport port no of local interface
        @param lointf local interface address (ip, mac)
        @return false if processed else true
        """
        flow = flows.exact_entry(pktin.match)

        for portno, ipr in intfs.items():
            if (ipr[0] & ipr[1]) == (pktin.match.nw_dst & ipr[1]):
                # Local address
                flow.set_buffer(pktin.pktin.buffer_id)
                flow.add_nw_rewrite(True, ipr[0])
                flow.add_dl_rewrite(True, ipr[2])
                flow.add_output(portno)
                if flow.buffer_id != pktin.pktin.buffer_id:
                    flow.set_buffer(pktin.pktin.buffer_id)
                    self.get_conn().send(flow.get_flow_mod(pyof.OFPFC_ADD).pack())
                else:
                    self.get_conn().send(flow.get_flow_mod(pyof.OFPFC_ADD).pack())
                    ofpkt.nw_rewrite(pktin.dpkt, True, ipr[0])
                    ofpkt.dl_rewrite(pktin.dpkt, True, ipr[2])
                    self.get_conn().send(flow.get_packet_out(pyof.OFPFC_ADD).pack() + pktin.dpkt.pack())
                return False

        # Global address
        cportl = []
        if (
            (pktin.match.nw_proto == 17)
            and (pktin.match.tp_dst == 53)
            and (self.coin.config["dns_select_interface"] != None)
        ):
            output.dbg("DNS packet", self.__class__.__name__)
            tcport = self.dns_select_intf(intfs)
            if tcport != None:
                cportl.append(tcport)
        else:
            output.dbg("non-DNS packet", self.__class__.__name__)
            tcport = self.select_intf(intfs)
            if tcport != None:
                cportl.append(tcport)

        for cport in cportl:
            gw = mc.get(nat.get_gw_key(cport))
            gwmac = mc.get(nat.get_gw_mac_key(gw))
            ipr = intfs[cport]
            if (gw == None) or (gwmac == None):
                output.warn("Packet ignored since gateway for interface not found!", self.__class__.__name__)
                return False

            # Outbound
            flow.add_nw_rewrite(True, ipr[0])
            flow.add_dl_rewrite(True, ipr[2])
            flow.add_dl_rewrite(False, pu.hex_str2array(gwmac))
            flow.add_output(cport)
            if pktin.pktin.buffer_id != flow.buffer_id:
                flow.set_buffer(pktin.pktin.buffer_id)
                self.get_conn().send(flow.get_flow_mod(pyof.OFPFC_ADD, cookie=self.cookie).pack())
                self.cookie += 1
            else:
                self.get_conn().send(flow.get_flow_mod(pyof.OFPFC_ADD, cookie=self.cookie).pack())
                self.cookie += 1
                ofpkt.nw_rewrite(pktin.dpkt, True, ipr[0])
                ofpkt.dl_rewrite(pktin.dpkt, True, ipr[2])
                ofpkt.dl_rewrite(pktin.dpkt, False, pu.hex_str2array(gwmac))
                self.get_conn().send(flow.get_packet_out(pyof.OFPFC_ADD).pack() + pktin.dpkt.pack())

            # Inbound
            rflow = flow.reverse(cport)
            rflow.match.nw_dst = ipr[0]
            rflow.match.dl_dst = ipr[2]
            rflow.add_nw_rewrite(False, lointf[0])
            rflow.add_dl_rewrite(False, lointf[1])
            rflow.add_output(iport)
            self.get_conn().send(rflow.get_flow_mod(pyof.OFPFC_ADD, cookie=self.cookie).pack())
            self.cookie += 1

            return False

        return True
示例#21
0
    def processevent(self, event):
        """Process event
        """
        if (isinstance(event, ofevents.pktin)):
            ##Allow flow to authenticate even when yet authenticated
            if ((event.match.nw_dst == AUTH_DST_IP and
                 (event.match.tp_dst == AUTH_DST_PORT1
                  or event.match.tp_dst == AUTH_DST_PORT2))
                    or (event.match.nw_src == AUTH_DST_IP and
                        (event.match.tp_src == AUTH_DST_PORT1
                         or event.match.tp_src == AUTH_DST_PORT2))):
                if (event.match.nw_dst == AUTH_DST_IP
                        and event.match.tp_dst == 8080):
                    owglobal.last_host_redirect = (
                        self.conn.db[event.sock].dpid, event.match.dl_src)
                output.dbg("Approving "+\
                               pu.ip_val2string(event.match.nw_src) + ":"+str(event.match.tp_src)+\
                               "=>"+\
                               pu.ip_val2string(event.match.nw_dst) + ":"+str(event.match.tp_dst),
                           self.__class__.__name__)
                return True

            #Authenticated host
            if (host_authenticated(event.match.dl_src)
                    or host_authenticated(event.match.dl_dst)):
                output.vdbg("Authenticated host flow "+\
                                pu.ip_val2string(event.match.nw_src) + ":"+str(event.match.tp_src)+\
                                "=>"+\
                                pu.ip_val2string(event.match.nw_dst) + ":"+str(event.match.tp_dst),
                            self.__class__.__name__)
                return True

            ##Allow special website access without authentication
            if (event.match.nw_dst in BYPASS_IP
                    or event.match.nw_src in BYPASS_IP):
                output.dbg("Allow bypass for special server",
                           self.__class__.__name__)
                return True

            ##Allow
            # (1) ARP
            # (2) ICMP
            # (3) DHCP
            # (4) DNS
            if ((event.match.dl_type == dpkt.ethernet.ETH_TYPE_ARP)
                    or (event.match.dl_type == dpkt.ethernet.ETH_TYPE_IP
                        and event.match.nw_proto == dpkt.ip.IP_PROTO_ICMP)
                    or (event.match.dl_type == dpkt.ethernet.ETH_TYPE_IP
                        and event.match.nw_proto == dpkt.ip.IP_PROTO_UDP and
                        (event.match.tp_dst == 67 or event.match.tp_dst == 68))
                    or
                (event.match.dl_type == dpkt.ethernet.ETH_TYPE_IP
                 and event.match.nw_proto == dpkt.ip.IP_PROTO_UDP and
                 (event.match.tp_dst == 53 or event.match.tp_src == 53))):
                return True

            ##Allow route to OpenID provider (should be in HTTPS)
            if (event.match.tp_dst == HTTPS_PORT or event.match.tp_dst == 8080
                    or event.match.tp_dst == 80
                    or event.match.tp_src == HTTPS_PORT
                    or event.match.tp_src == 8080 or event.match.tp_src == 80):
                auth_s = None
                if (event.match.tp_dst == HTTPS_PORT
                        or event.match.tp_dst == 8080
                        or event.match.tp_dst == 80):
                    auth_s = mcutil.get(
                        host_auth.get_auth_key(event.match.dl_src))
                else:
                    auth_s = mcutil.get(
                        host_auth.get_auth_key(event.match.dl_dst))

                if (auth_s != None):
                    output.dbg(pu.ip_val2string(event.match.nw_dst)+" associated with "+\
                                   " auth server "+str(auth_s)+" "+str(event.match.dl_src),
                               self.__class__.__name__)
                    return True

            ##Redirect unauthenticated host if HTTP
            if (event.match.dl_type == dpkt.ethernet.ETH_TYPE_IP
                    and event.match.nw_proto == dpkt.ip.IP_PROTO_TCP and
                (event.match.tp_dst == 80 or event.match.tp_dst == 8080)):
                output.dbg(
                    "Redirecting %x to authenticate" %
                    pu.array2val(event.match.dl_src), self.__class__.__name__)

                #Forward flow
                flow = flows.exact_entry(event.match)
                key = swhost.mac2sw_binding.get_key(event.sock,
                                                    event.match.dl_dst)
                port = mcutil.get(key)
                if (port != None):
                    flow.set_buffer(event.pktin.buffer_id)
                    flow.add_nw_rewrite(False, AUTH_DST_IP)
                    flow.add_output(port)
                    self.conn.send(event.sock,
                                   flow.get_flow_mod(pyof.OFPFC_MODIFY).pack())

                    #Reverse flow
                    rflow = flow.reverse(port)
                    rflow.match.nw_src = AUTH_DST_IP
                    rflow.add_nw_rewrite(True, event.match.nw_dst)
                    rflow.add_output(event.pktin.in_port)
                    self.conn.send(
                        event.sock,
                        rflow.get_flow_mod(pyof.OFPFC_MODIFY).pack())

                return False

            #Drop remaining flows
            flow = flows.exact_entry(event.match)
            flow.set_buffer(event.pktin.buffer_id)
            self.conn.send(event.sock,
                           flow.get_flow_mod(pyof.OFPFC_ADD).pack())
            output.dbg("Dropping "+\
                           pu.ip_val2string(event.match.nw_src) + ":"+str(event.match.tp_src)+\
                           "=>"+pu.ip_val2string(event.match.nw_dst) + ":"+str(event.match.tp_dst),
                       self.__class__.__name__)
            return False

        return True