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
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
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
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
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 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
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 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 host_authenticated(host): """Return if host is authenticated """ au = mcutil.get(host_auth.get_key(host)) if (au == None): return False else: return True
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
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
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
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 @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
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
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