def _handle_change(self, flow_stats): """Handle flows to be changed based on flow stats reply @param flow_stats flow_stats event """ self.check_timeout() for f in flow_stats.flows: for (new, old) in self.ip_change.items(): if f.match.nw_src == old[0]: flow = flows.exact_entry( f.match, priority=f.priority, idle_timeout=f.idle_timeout, hard_timeout=f.hard_timeout ) flow.set_nw_src(new) flow.add_nw_rewrite(True, old) flow.actions.extend(f.actions) self.get_conn().send(flow.get_flow_mod(pyof.OFPFC_MODIFY, f.cookie).pack()) output.dbg(str(f) + " has old source IP (flow rule is added)", self.__class__.__name__) elif f.match.nw_dst == old[0]: flow = flows.exact_entry( f.match, priority=f.priority, idle_timeout=f.idle_timeout, hard_timeout=f.hard_timeout ) flow.add_nw_rewrite(False, new) flow.actions.extend(f.actions) self.get_conn().send(flow.get_flow_mod(pyof.OFPFC_MODIFY, f.cookie).pack()) output.dbg(str(f) + " has old destination IP (flow rule is modified)", self.__class__.__name__)
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 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
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 _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 _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 installflow(self, event, port): """Install flow @param event packet-in event @param port port to send flow to """ flow = flows.exact_entry(event.match) flow.dpkt = event.dpkt if (self.send_flow_removed): flow.set_flow_removed_flag() flow.set_buffer(event.pktin.buffer_id) flow.add_output(port) flow.install(self.conn, event.sock)
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 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
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
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 _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
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): """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