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
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__)
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)
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
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
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
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
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())
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
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
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)
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
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
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
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
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__)
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__)
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 = []
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
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__)
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
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__)
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
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
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__)
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
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
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
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