Example #1
0
    def processevent(self, event):
        """Process all the events registered for

        Check for packet-in and :
          create packet out with FLOOD action
          send it (oops.. do check the buffer id to see if buffered)

        @param event event to handle
        """
        if (isinstance(event, ofevents.pktin)):
            output.dbg("Receive an OpenFLow packet in :\n"+\
                       event.pktin.show(),
                       self.__class__.__name__)

            flow = flows.exact_entry(event.match)
            flow.set_buffer(event.pktin.buffer_id)
            flow.add_output(pyof.OFPP_FLOOD)
            
            if (event.pktin.buffer_id == flows.UNBUFFERED_ID):
                ##Not buffered
                self.conn.send(event.sock, flow.get_packet_out().pack()+event.pkt)
                output.vdbg("Flood unbuffered packet with match "+\
                                event.match.show().replace('\n',';'))
          
            else:
                ##Buffered packet
                self.conn.send(event.sock,flow.get_packet_out().pack())
                output.vdbg("Flood buffered packet with match "+\
                                event.match.show().replace('\n',';'))

        return True
Example #2
0
    def __init__(self, sock, msg, stats_reply=None, reply=None):
        """Initialize

        @param sock reference to socket
        @param msg message
        """
        ofcomm.message.__init__(self, sock, msg)

        ##Stats reply header
        self.stats_reply = stats_reply
        
        remaining = reply
        if (self.stats_reply == None) or (remaining == None):
            self.stats_reply = pyof.ofp_stats_reply()
            remaining = self.stats_reply.unpack(msg)
        
        ##Flow stats of individual flows
        self.flows = []
        while (len(remaining) >= pyof.OFP_FLOW_STATS_BYTES):
            flow = pyof.ofp_flow_stats()
            flow.unpack(remaining)
            self.unpack_actions(remaining[pyof.OFP_FLOW_STATS_BYTES:flow.length], flow.actions)
            remaining = remaining[flow.length:]
            self.flows.append(flow)

        if (len(remaining) > 0):
            output.warn("Flow stats reply is of irregular length with "+\
                            str(len(remaining))+" bytes remaining.",
                        self.__class__.__name__)
        output.vdbg("Received "+str(len(self.flows))+" flow stats.",
                   self.__class__.__name__)
Example #3
0
    def send(self, message, addr, action, timeout=3, retry=10, tried=0):
        """Send snmp.message

        @param message SNMP message to send
        @param addr (host, port) to send to
        @param timeout timeout in how many seconds
        @param retry number of times to retry (if None, try indefinitely)
        """
        pdu=None
        if (action == self.GET):
            pdu = message.pack_get_pdu()
        elif (action == self.SET):
            pdu = message.pack_set_pdu()
        elif (action == self.WALK):
            pdu = message.pack_walk_pdu()
            
        msg = message.pack_msg(pdu)
        reqId = message.get_req_id(pdu)
        output.vdbg("Transmitting SNMP message with id "+str(reqId)+\
                   " for the no. "+str(tried+1)+ " time",
                   self.__class__.__name__)
        self.client.send(msg, addr)
        self.messages[reqId] = {"timeout": timeout,
                                "retry": retry,
                                "tried": tried+1,
                                "request": message,
                                "addr": addr,
                                "action": action}
        self.server.post_event(yapc.priv_callback(self, reqId), timeout)
Example #4
0
File: nat.py Project: yapkke/yapc
    def _process_inbound(self, pktin, intfs, iport, lointf):
        """Event handler for inbound ARP packets

        @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("ARP packet received on unknown/uninitialized interface", self.__class__.__name__)
            return False

        flow = flows.exact_entry(pktin.match)
        if flow.buffer_id != pktin.pktin.buffer_id:
            output.warn("Buffered inbound ARP packet (cannot be rewritten properly)!", self.__class__.__name__)
        elif flow.match.nw_dst != ipr[0]:
            output.vdbg("Inbound ARP packet not destined for this host, ignored.", self.__class__.__name__)
        else:
            flow.add_output(iport)
            if pu.array2val(pktin.match.dl_dst) != 0xFFFFFFFFFFFF:
                ofpkt.dl_rewrite(pktin.dpkt, False, lointf[1])
            ofpkt.nw_rewrite(pktin.dpkt, False, lointf[0])
            self.get_conn().send(flow.get_packet_out().pack() + pktin.dpkt.pack())
        return False
Example #5
0
File: nat.py Project: yapkke/yapc
    def _process_outbound(self, pktin, intfs, iport, lointf):
        """Event handler for outbound ARP packets

        @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
        """
        for portno, ipr in intfs.items():
            if (ipr[0] & ipr[1]) == (pktin.match.nw_dst & ipr[1]):
                flow = flows.exact_entry(pktin.match)
                if flow.buffer_id != pktin.pktin.buffer_id:
                    output.warn("Buffered outbound ARP packet (cannot be rewritten properly)!", self.__class__.__name__)
                else:
                    flow.add_output(portno)
                    ofpkt.dl_rewrite(pktin.dpkt, True, ipr[2])
                    ofpkt.nw_rewrite(pktin.dpkt, True, ipr[0])
                    self.get_conn().send(flow.get_packet_out().pack() + pktin.dpkt.pack())
                    output.vdbg(
                        "ARP to " + pu.ip_val2string(pktin.match.nw_dst) + " sent to port " + str(portno),
                        self.__class__.__name__,
                    )
                return False
        output.warn("ARP for " + pu.ip_val2string(pktin.match.nw_dst) + " unknown subnet", self.__class__.__name__)
        return False
Example #6
0
    def processevent(self, event):
        """Process event

        @param event event to process
        @return True
        """
        if (isinstance(event, yapc.priv_callback)):
            lastr = self.lastresult
            r = self.get_stat()
            output.vdbg(r)

            if (lastr == None):
                self._server.post_event(yapc.priv_callback(self), self.interval)
                return True

            for k,v in r.items():
                for k2 in ["transmit", "receive"]:
                    try:
                        v[k2]["bps"] = (float(v[k2]["bytes"] - lastr[k][k2]["bytes"])*8.0/
                                        (v["timestamp"]-lastr[k]["timestamp"]))
                        v[k2]["pps"] = (float(v[k2]["packets"] - lastr[k][k2]["packets"])/
                                        (v["timestamp"]-lastr[k]["timestamp"]))
                    except KeyError:
                        output.warn("Interface "+str(k)+" is new or removed",
                                    self.__class__.__name__)

            self._server.post_event(yapc.priv_callback(self), self.interval)

        return True
Example #7
0
 def open(self):
     """Open database
     """
     if (self.connection == None):
         self.connection = sqlite3.connect(self.filename)
         output.vdbg("Opening database "+self.filename,
                     self.__class__.__name__)
         self.connection.row_factory = sqlite3.Row
Example #8
0
    def create(self, db):
        """Create table in database

        @param db reference to database
        """
        self.db = db
        output.vdbg("Create table "+self.name+" in "+str(db),
                    self.__class__.__name__)
        db.execute(self.create_stmt())
Example #9
0
 def close(self):
     """Close database
     """
     if (self.connection != None):
         output.vdbg("Closing database",
                     self.__class__.__name__)
         self.connection.commit()
         self.connection.close()
         self.connection = None
Example #10
0
 def execute(self, stmt, close=True):
     """Execute statement
     """
     self.open()
     output.vdbg(stmt, self.__class__.__name__)
     r = self.connection.execute(stmt)
     if (close):
         self.close()
     return r
Example #11
0
 def processpacket(self, packet):
     """Function to process packet
     
     (Dummy function that print packet verbatim)
     """
     output.vdbg("Receive OpenFlow packet of "+\
                     self.__header.show().strip().replace("\n",";"),
                self.__class__.__name__)
     msg = message(self.sock, packet)
     self.scheduler.post_event(msg)
Example #12
0
    def processevent(self, event):
        """Process event

        @param event event to process
        @return True
        """
        if (isinstance(event, yapc.priv_callback)):
            output.vdbg(self.get_stat())
            self._server.post_event(yapc.priv_callback(self), self.interval)

        return True
Example #13
0
    def processevent(self, event):
        """Process publish and query events

        @param event Event to handler
        @return True
        """
        if isinstance(event, publish):
            #Publish event
            try:
                logger = self.loggers[event.eventname]
            except KeyError:
                output.warn("No logger registered for "+event.eventname+"! Hence data dropped.",
                            self.__class__.__name__)
                return True

            for i in event.get_dict():
                d = []
                for k in logger.get_col_names():
                    d.append(i[k])
                logger.table.add_row(tuple(d))
                output.vdbg("Recorded measurement of "+str(i),
                            self.__class__.__name__)
                
        elif isinstance(event, query):
            #Query event
            try:
                logger = self.loggers[event.table]
            except KeyError:
                output.warn("No logger registered for "+str(event.table)+"!  Hence, no querying.",
                            self.__class__.__name__)
                return True
            
            self.db.flush()

            q = event.get_query()
            try:
                r = logger.table.select(q[0], q[1], q[2])
            except sqlite3.OperationalError:
                output.warn(logger.table.select_stmt(q[0], q[1], q[2])+" failed",
                            self.__class__.__name__)
                return True

            #Extract result
            qresponse = queryresponse(event)
            for row in r:
                res = {}
                for k in row.keys():
                    res[k] = row[k]
                qresponse.response.append(res)
            r.close()

            self.server.post_event(qresponse)
        return True       
Example #14
0
File: nat.py Project: 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
Example #15
0
    def processevent(self, event):
        """Event handler

        @param event event to handle
        """
        if (isinstance(event, ofevents.pktin)):
            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.vdbg("Dropping flow with match "+\
                            event.match.show().replace('\n',';'))

        return True
Example #16
0
    def send_lldp(self, sw, port):
        """Send LLDP to switch and port

        @param sw datapath id of switch
        @param port phy port
        """
        self.__po.xid = ofutil.get_xid()
        self.__po.actions[0].port = port.port_no
        switch = self.conn.get_conn(sw)
        if (switch != None):
            switch.send(self.__po.pack()+\
                        self.form_eth_lldp(sw, port))
            output.vdbg("Sending LLDP to %x:" % sw +str(port.port_no),
                        self.__class__.__name__)
Example #17
0
    def add_row(self, row):
        """Add data to the table

        @param row  is a tuple of data
        """
        if (len(row) == len(self.columns)):
            output.vdbg("Add row :"+str(row))
            self.data_cache.append(row)
            if (len(self.data_cache) >= self.cache_size):
                self.flush_cache()
        else:
            output.warn("Adding row "+str(row)+" with "+len(row)+" items"+\
                            " when there is "+len(self.columns)+" columns",
                        self.__class__.__name__)
Example #18
0
    def flush_cache(self, close=True):
        """Flush data in cache in database
        """
        if (self.db == None):
            output.warn("No database to flush data into",
                        self.__class__.__name__)
            return

        output.vdbg("Flush cache of "+str(len(self.data_cache))+" items",
                    self.__class__.__name__)
        stmt = "?,"*len(self.columns)
        self.db.executemany("INSERT INTO "+self.name+\
                                " VALUES ("+stmt[:-1]+")",
                            self.data_cache, close)
        self.data_cache = []
Example #19
0
File: nat.py Project: 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
Example #20
0
 def send(self, msg):
     """Send OpenFlow message
     """
     header = pyopenflow.ofp_header()
     if (len(msg) < len(header)):
         output.warn("Cannot send OpenFlow of length "+str(len(msg)))
     else:
         remain = header.unpack(msg)
         header.length = len(msg)
         output.vdbg("Send message "+header.show().strip().replace("\n",";"),
                     self.__class__.__name__)
         try:
             self.sock.send(header.pack()+remain)
         except socket.error:
             output.warn("Broken pipe, message not sent",
                         self.__class__.__name__)
Example #21
0
    def processevent(self, event):
        """Event handler

        @param event event to handle
        """
        key = self.get_key(event.sock, event.match.dl_src)

        #Broadcast mac
        if (pu.is_multicast_mac(event.match.dl_src)):
            return True

        mc.set(key, event.pktin.in_port, mac2sw_binding.TIMEOUT)
        output.vdbg("Learn that %x " % pu.array2val(event.match.dl_src) +\
                       "is connected to port " + \
                       str(event.pktin.in_port)+" of switch with "+\
                       str(event.sock),
                   self.__class__.__name__)

        return True
Example #22
0
    def __init__(self, sock, msg):
        """Initialize

        @param sock reference to socket
        @param msg message
        """
        ofcomm.message.__init__(self, sock, msg)

        ##Packet in header
        self.pktin = None
        ##Packet included parsed by dpkt
        self.dpkt = None
        ##Binary packet
        self.pkt = None
        ##Exact match for match
        self.match = None

        if (self.header.type == pyof.OFPT_PACKET_IN):
            self.pktin = pyof.ofp_packet_in()
            self.pkt = self.pktin.unpack(msg)
            output.vdbg("Packet in\n"+self.pktin.show("\t"),
                        self.__class__.__name__)
            (self.match, self.dpkt) = ofutil.get_ofp_match(self.pktin.in_port, 
                                                           self.pkt)
            output.vdbg("Packet has match\n"+self.match.show("\t"),
                        self.__class__.__name__)
            output.vdbg(str(`self.dpkt`),
                        self.__class__.__name__)
Example #23
0
    def processevent(self, event):
        """Handle event to sniff domain name-IP address binding
        """
        if (isinstance(event, ofevents.pktin)):
            if (event.match.tp_src == 53):
                try:
                    dnsreply = dpkt.dns.DNS(event.dpkt["data"]["data"]["data"])
                except:
                    return True
                nameaddr = {}

                for rr in dnsreply["an"]:
                    if (rr["type"] == 1):
                        #Record address for domain name
                        if (rr["name"] not in nameaddr):
                            nameaddr[rr["name"]] = []
                        nameaddr[rr["name"]].append(rr["rdata"])
                        #Record domain name for address
                        mc.set(host_dns.get_addr_key(rr["rdata"]), rr["name"], rr["ttl"])
                        output.vdbg("AN: "+socket.inet_ntoa(rr["rdata"])+" set to "+rr["name"]+\
                                        " with TTL "+str(rr["ttl"]),
                                    self.__class__.__name__)

                for rr in dnsreply["ar"]:
                    if (rr["type"] == 1):
                        #Record domain name for address
                        mc.set(host_dns.get_addr_key(rr["rdata"]), rr["name"], rr["ttl"])
                        output.vdbg("AR: "+socket.inet_ntoa(rr["rdata"])+" set to "+rr["name"]+\
                                        " with TTL "+str(rr["ttl"]),
                                    self.__class__.__name__)

                for name,val in nameaddr.items():
                    if (len(val) != 0):
                        mc.set(host_dns.get_name_key(event.match.dl_src, name), val)
                        output.dbg(name+"=>"+str(len(val))+" IP addresses",
                                   self.__class__.__name__)
                    


        return True
Example #24
0
    def processevent(self, event):
        """Event handler

        @param event event to handle
        """
        if (isinstance(event, ofevents.pktin)):
            flow = flows.exact_entry(event.match)
            flow.dpkt = event.dpkt
            flow.set_buffer(event.pktin.buffer_id)
            flow.add_output(pyof.OFPP_FLOOD)
            
           
            if (event.pktin.buffer_id == flows.UNBUFFERED_ID):
                self.conn.send(event.sock, flow.get_packet_out().pack()+event.pkt)
                output.vdbg("Flood unbuffered packet with match "+\
                                event.match.show().replace('\n',';'))
            else:
                self.conn.send(event.sock,flow.get_packet_out().pack())
                output.vdbg("Flood buffered packet with match "+\
                                event.match.show().replace('\n',';'),
                            self.__class__.__name__)
        return True
Example #25
0
    def _dispatch_event(self, event):
        """Dispatch next event

        @param event event to dispatch
        """
        #Dispatch event
        if (isinstance(event, yapc.priv_callback)):
            self.__handle_event(event.handler, event)
            output.vvdbg("Event "+event.name+" dispatched to "+
                         event.handler.__class__.__name__,
                         self.__class__.__name__)
        else:
            try:
                for handler in self._processors[event.name]:
                    output.vvdbg("Dispatch "+event.name+\
                                     " to "+handler.__class__.__name__,
                                 self.__class__.__name__)
                    if (not self.__handle_event(handler, event)):
                        break
            except KeyError:
                #No handler, so pass
                output.vdbg("Event "+str(event.name)+" does not have handler",
                            self.__class__.__name__)
Example #26
0
def get_client(servers=memcache_servers, debug=DEBUG):
    """Get client for memcache

    @param servers list of servers
    @param debug debug mode
    """
    global memcache_client
    global memcache_servers
    global memcache_mode
    if memcache_mode == MEMCACHE_MODE["OFF"]:
        output.vdbg("Not using memcache")
        return

    if memcache_client == None:
        if memcache_mode == MEMCACHE_MODE["ON"]:
            import memcache

            memcache_client = memcache.Client(servers, debug)
            memcache_client.flush_all()
            output.vdbg("Using memcache")
        elif memcache_mode == MEMCACHE_MODE["LOCAL"]:
            memcache_client = local_memcache()
            output.vdbg("Using local memcache")
    return memcache_client
Example #27
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
Example #28
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
Example #29
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