def assemble_ack(self, pkt): req_eth = pkt.get_protocol(ethernet.ethernet) req_ipv4 = pkt.get_protocol(ipv4.ipv4) req_udp = pkt.get_protocol(udp.udp) req = dhcp.dhcp.parser(pkt[3]) req[0].options.option_list.remove( next(opt for opt in req[0].options.option_list if opt.tag == 53)) req[0].options.option_list.insert(0, dhcp.option(tag=51, value='8640')) req[0].options.option_list.insert( 0, dhcp.option(tag=53, value='05'.decode('hex'))) ack_pkt = packet.Packet() ack_pkt.add_protocol( ethernet.ethernet(ethertype=req_eth.ethertype, dst=req_eth.src, src=self.hw_addr)) ack_pkt.add_protocol( ipv4.ipv4(dst=req_ipv4.dst, src=self.dhcp_server, proto=req_ipv4.proto)) ack_pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) ack_pkt.add_protocol( dhcp.dhcp(op=2, chaddr=req_eth.src, siaddr=self.dhcp_server, boot_file=req[0].boot_file, yiaddr=self.ip_addr, xid=req[0].xid, options=req[0].options)) self.logger.info("ASSEMBLED ACK: %s" % ack_pkt) return ack_pkt
def assemble_ack(self, pkt): req_eth = pkt.get_protocol(ethernet.ethernet) req_ipv4 = pkt.get_protocol(ipv4.ipv4) req_udp = pkt.get_protocol(udp.udp) req = pkt.get_protocol(dhcp.dhcp) req.options.option_list.remove( next(opt for opt in req.options.option_list if opt.tag == 53)) req.options.option_list.insert( 0, dhcp.option(tag=51, value=bytes.fromhex('8640'.encode().hex()))) req.options.option_list.insert(0, dhcp.option(tag=53, value=bytes([5]))) ack_pkt = packet.Packet() ack_pkt.add_protocol( ethernet.ethernet(ethertype=req_eth.ethertype, dst=req_eth.src, src=self.hw_addr)) ack_pkt.add_protocol( ipv4.ipv4(dst=req_ipv4.dst, src=self.dhcp_server, proto=req_ipv4.proto)) ack_pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) ack_pkt.add_protocol( dhcp.dhcp(op=2, chaddr=req_eth.src, siaddr=self.dhcp_server, boot_file=req.boot_file, yiaddr=self._cal_vm_ip(req), xid=req.xid, options=req.options)) self.logger.info("ASSEMBLED ACK: %s" % ack_pkt) return ack_pkt
def assemble_ack(self, pkt): response_eth = pkt.get_protocol(ethernet.ethernet) response_ipv4 = pkt.get_protocol(ipv4.ipv4) response = pkt.get_protocol(dhcp.dhcp) response.options.option_list.remove( next(opt for opt in response.options.option_list if opt.tag == 53)) response.options.option_list.insert(0, dhcp.option(tag=51, value='')) response.options.option_list.insert(0, dhcp.option(tag=53, value="")) ack_pkt = packet.Packet() ack_pkt.add_protocol( ethernet.ethernet(ethertype=response_eth.ethertype, dst=response_eth.src, src="")) ack_pkt.add_protocol( ipv4.ipv4(dst=response_ipv4.dst, src=self.dhcp_server, proto=response_ipv4.proto)) ack_pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) ack_pkt.add_protocol( dhcp.dhcp(op=2, chaddr=response_eth.src, siaddr="dhcp_server", boot_file=response.boot_file, yiaddr="ip_addr", xid=response.xid, options=response.options)) return ack_pkt
def assemble_ack(self, pkt, chaddr): chaddr_yiaddr = self.get_ip(chaddr) req_eth = pkt.get_protocol(ethernet.ethernet) req_ipv4 = pkt.get_protocol(ipv4.ipv4) req_udp = pkt.get_protocol(udp.udp) req = pkt.get_protocol(dhcp.dhcp) req.options.option_list.remove( next(opt for opt in req.options.option_list if opt.tag == 53)) req.options.option_list.insert( 0, dhcp.option(tag=51, value=str.encode('8640'))) req.options.option_list.insert( 0, dhcp.option(tag=53, value=str.encode('\x05'))) ack_pkt = packet.Packet() ack_pkt.add_protocol( ethernet.ethernet(ethertype=req_eth.ethertype, dst=req_eth.src, src=self.hw_addr)) ack_pkt.add_protocol( ipv4.ipv4(dst=req_ipv4.dst, src=self.dhcp_server, proto=req_ipv4.proto)) ack_pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) ack_pkt.add_protocol( dhcp.dhcp(op=2, chaddr=req_eth.src, siaddr=self.dhcp_server, boot_file=req.boot_file, yiaddr=chaddr_yiaddr, xid=req.xid, options=req.options)) self.logger.debug("ASSEMBLED ACK") return ack_pkt
def create_dhcp_ack(self, dhcp_packet, dp, port, dst_ip="255.255.255.255"): if self.temp_offered.get(dhcp_packet.xid) is None: return subnet_mask = self.space[dp.id].netmask yiaddr = self.temp_offered[dhcp_packet.xid]["yiaddr"] chaddr = self.temp_offered[dhcp_packet.xid]["chaddr"] # add new or update existing dhcp bindings # we remember only last used ip address self.database[chaddr] = yiaddr pkt = packet.Packet() dhcp_ack_msg_type = b"\x05" subnet_option = dhcp.option( tag=dhcp.DHCP_SUBNET_MASK_OPT, value=addrconv.ipv4.text_to_bin(subnet_mask), ) time_option = dhcp.option(tag=dhcp.DHCP_IP_ADDR_LEASE_TIME_OPT, value=bytearray(self.LEASE_TIME_ACK)) msg_option = dhcp.option(tag=dhcp.DHCP_MESSAGE_TYPE_OPT, value=dhcp_ack_msg_type) dhcp_server_option = dhcp.option(tag=dhcp.DHCP_SERVER_IDENTIFIER_OPT, value=bytearray(self._ip_to_int())) options = dhcp.options(option_list=[ msg_option, time_option, subnet_option, dhcp_server_option, ]) hlen = dhcp_packet.hlen dhcp_pkt = dhcp.dhcp( op=dhcp.DHCP_BOOT_REPLY, hlen=hlen, chaddr=dhcp_packet.chaddr, yiaddr=yiaddr, siaddr=self.DHCP_SERVER_IP, giaddr=dhcp_packet.giaddr, xid=dhcp_packet.xid, options=options, ) pkt.add_protocol( ethernet.ethernet(ethertype=ether.ETH_TYPE_IP, dst=chaddr, src=self.DHCP_SERVER_MAC)) pkt.add_protocol( ipv4.ipv4(dst=dst_ip, src=self.DHCP_SERVER_IP, proto=17)) pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) pkt.add_protocol(dhcp_pkt) pkt.serialize() self.inject_packet(pkt, dp, port)
def create_dhcp_offer(self, dhcp_packet, dp, port, dst_ip="255.255.255.255"): xid = dhcp_packet.xid # transaction id chaddr = dhcp_packet.chaddr yiaddr = None previous_ip = self.database.get(chaddr) if previous_ip: if previous_ip in self.pools[dp.id]: self.pools[dp.id].remove(previous_ip) yiaddr = previous_ip else: yiaddr = self.pools[dp.id].pop(-1) else: yiaddr = self.pools[dp.id].pop(-1) self.temp_offered[xid] = {"chaddr": chaddr, "yiaddr": yiaddr} pkt = packet.Packet() dhcp_offer_msg_type = b"\x02" hlen = dhcp_packet.hlen msg_option = dhcp.option(tag=dhcp.DHCP_MESSAGE_TYPE_OPT, value=dhcp_offer_msg_type) dhcp_server_option = dhcp.option(tag=dhcp.DHCP_SERVER_IDENTIFIER_OPT, value=bytearray(self._ip_to_int())) options = dhcp.options(option_list=[msg_option, dhcp_server_option]) pkt.add_protocol( ethernet.ethernet(ethertype=ether.ETH_TYPE_IP, dst=chaddr, src=self.DHCP_SERVER_MAC)) pkt.add_protocol( ipv4.ipv4(dst=dst_ip, src=self.DHCP_SERVER_IP, proto=17)) pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) pkt.add_protocol( dhcp.dhcp( hlen=hlen, op=dhcp.DHCP_BOOT_REPLY, yiaddr=yiaddr, siaddr=self.DHCP_SERVER_IP, xid=dhcp_packet.xid, giaddr=dhcp_packet.giaddr, chaddr=chaddr, options=options, )) pkt.serialize() self.inject_packet(pkt, dp, port)
def assemble_offer(cls, pkt, datapath): disc_eth = pkt.get_protocol(ethernet.ethernet) disc_ipv4 = pkt.get_protocol(ipv4.ipv4) disc_udp = pkt.get_protocol(udp.udp) disc = pkt.get_protocol(dhcp.dhcp) src = disc_eth.src if src in cls.wan_leases[datapath]: offer = cls.wan_leases[datapath][src] del cls.wan_leases[datapath][src] cls.wan_offers[datapath][src] = offer else: offer = cls.wan_offers[datapath].get(src) if offer is None: if len(cls.wan_pool[datapath]) == 0: # cls.logger.error("Out of IP addresses") # dhcp nak belum dibuat # cls.nak(pkt) return offer = cls.wan_pool[datapath][0] # jika request IP diminta belum dibuat cls.wan_pool[datapath].remove(offer) cls.wan_offers[datapath][src] = offer yiaddr = offer disc.options.option_list.remove(next(opt for opt in disc.options.option_list if opt.tag == 55)) disc.options.option_list.remove(next(opt for opt in disc.options.option_list if opt.tag == 53)) disc.options.option_list.remove(next(opt for opt in disc.options.option_list if opt.tag == 12)) disc.options.option_list.insert(0, dhcp.option(tag=1, value=cls.bin_netmask)) disc.options.option_list.insert(0, dhcp.option(tag=3, value=addrconv.ipv4.text_to_bin(cls.dhcp_server[datapath]))) disc.options.option_list.insert(0, dhcp.option(tag=6, value=cls.bin_dns)) # disc.options.option_list.insert(0, dhcp.option(tag=12, value=cls.hostname)) disc.options.option_list.insert(0, dhcp.option(tag=53, value='02'.decode('hex'))) disc.options.option_list.insert(0, dhcp.option(tag=54, value=addrconv.ipv4.text_to_bin(cls.dhcp_server[datapath]))) offer_pkt = packet.Packet() offer_pkt.add_protocol(ethernet.ethernet(ethertype=disc_eth.ethertype, dst=src, src=cls.hw_addr)) offer_pkt.add_protocol(ipv4.ipv4(dst=disc_ipv4.dst, src=cls.dhcp_server[datapath], proto=disc_ipv4.proto)) offer_pkt.add_protocol(udp.udp(src_port=67,dst_port=68)) offer_pkt.add_protocol(dhcp.dhcp(op=2, chaddr=src, hlen=6, # salah di len siaddr=cls.dhcp_server[datapath], boot_file=disc.boot_file, yiaddr=yiaddr, xid=disc.xid, options=disc.options)) # cls.logger.info("ASSEMBLED OFFER: %s" % offer_pkt) return offer_pkt
def handle_dhcp_discover(self, dhcp_pkt, datapath, port): try: # Choose a IP form IP pool list client_ip_addr = str(self.ip_pool_list.pop()) self.mac_to_client_ip[dhcp_pkt.chaddr] = client_ip_addr except IndexError: self.logger.info("EMPTY IP POOL") return # send dhcp_offer message. dhcp_offer_msg_type = '\x02' self.logger.info("Send DHCP message type %s" % (self.dhcp_msg_type_code[ord(dhcp_offer_msg_type)])) msg_option = dhcp.option(tag=dhcp.DHCP_MESSAGE_TYPE_OPT, value=dhcp_offer_msg_type) options = dhcp.options(option_list=[msg_option]) hlen = len(addrconv.mac.text_to_bin(dhcp_pkt.chaddr)) dhcp_pkt = dhcp.dhcp(hlen=hlen, op=dhcp.DHCP_BOOT_REPLY, chaddr=dhcp_pkt.chaddr, yiaddr=client_ip_addr, giaddr=dhcp_pkt.giaddr, xid=dhcp_pkt.xid, options=options) self._send_dhcp_packet(datapath, dhcp_pkt, port)
def _build_dhcp_options(self, dhcp_request, response_type, lport, subnet, srv_addr): """ according the RFC the server need to response with with all the option that "explicitly configured options" and supply as many of the "requested parameters" as possible https://www.ietf.org/rfc/rfc2131.txt (page 29) """ # explicitly configured options default_opts = self._build_response_default_options(response_type, lport, subnet, srv_addr) # requested options (according to dhcp_params.opt) response_opts = self._build_response_requested_options(dhcp_request, lport, default_opts) response_opts.update(default_opts) option_list = [dhcp.option(tag, value) for tag, value in response_opts.items()] return option_list
def _create_dhcp_ack(self, pkt, dhcp_packet, lport): pkt_ipv4 = pkt.get_protocol(ipv4.ipv4) pkt_ethernet = pkt.get_protocol(ethernet.ethernet) subnet = self._get_subnet_by_port(lport) if subnet is None: LOG.error(_LE("No subnet found for port <%s>") % lport.get_id()) return dns = self._get_dns_address_list_bin(subnet) host_routes = self._get_host_routes_list_bin(subnet) dhcp_server_address = str(self._get_dhcp_server_address(subnet)) gateway_address = self._get_port_gateway_address(subnet) netmask_bin = self._get_port_netmask(subnet).packed domain_name_bin = struct.pack('!256s', self.domain_name) lease_time_bin = struct.pack('!I', self.lease_time) option_list = [ dhcp.option(dhcp.DHCP_MESSAGE_TYPE_OPT, b'\x05', 1), dhcp.option(dhcp.DHCP_SUBNET_MASK_OPT, netmask_bin, 4), dhcp.option(dhcp.DHCP_GATEWAY_ADDR_OPT, gateway_address.packed, 4), dhcp.option(dhcp.DHCP_IP_ADDR_LEASE_TIME_OPT, lease_time_bin, 4), dhcp.option(dhcp.DHCP_DNS_SERVER_ADDR_OPT, dns, len(dns)), dhcp.option(DHCP_DOMAIN_NAME_OPT, domain_name_bin, len(self.domain_name)), dhcp.option(DHCP_CLASSLESS_ROUTE, host_routes, len(host_routes))] if self.advertise_mtu: intreface_mtu = self._get_port_mtu(lport) mtu_bin = struct.pack('!H', intreface_mtu) option_list.append(dhcp.option( DHCP_INTERFACE_MTU_OPT, mtu_bin, len(mtu_bin))) options = dhcp.options(option_list=option_list) dhcp_ack_pkt = ryu_packet.Packet() dhcp_ack_pkt.add_protocol(ethernet.ethernet( ethertype=ether.ETH_TYPE_IP, dst=pkt_ethernet.src, src=pkt_ethernet.dst)) dhcp_ack_pkt.add_protocol(ipv4.ipv4(dst=pkt_ipv4.src, src=dhcp_server_address, proto=pkt_ipv4.proto)) dhcp_ack_pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) dhcp_ack_pkt.add_protocol(dhcp.dhcp(op=2, chaddr=pkt_ethernet.src, siaddr=dhcp_server_address, boot_file=dhcp_packet.boot_file, yiaddr=lport.get_ip(), xid=dhcp_packet.xid, options=options)) return dhcp_ack_pkt
def _create_dhcp_ack(self, pkt, dhcp_packet, lport): pkt_ipv4 = pkt.get_protocol(ipv4.ipv4) pkt_ethernet = pkt.get_protocol(ethernet.ethernet) subnet = self._get_subnet_by_port(lport) if subnet is None: LOG.error(_LE("No subnet found for port <%s>") % lport.get_id()) return dns = self._get_dns_address_list_bin(subnet) host_routes = self._get_host_routes_list_bin(subnet, lport) dhcp_server_address = str(self._get_dhcp_server_address(subnet)) gateway_address = self._get_port_gateway_address(subnet) netmask_bin = self._get_port_netmask(subnet).packed domain_name_bin = struct.pack('!256s', self.domain_name) lease_time_bin = struct.pack('!I', self.lease_time) option_list = [ dhcp.option(dhcp.DHCP_MESSAGE_TYPE_OPT, b'\x05', 1), dhcp.option(dhcp.DHCP_SUBNET_MASK_OPT, netmask_bin, 4), dhcp.option(dhcp.DHCP_GATEWAY_ADDR_OPT, gateway_address.packed, 4), dhcp.option(dhcp.DHCP_IP_ADDR_LEASE_TIME_OPT, lease_time_bin, 4), dhcp.option(dhcp.DHCP_DNS_SERVER_ADDR_OPT, dns, len(dns)), dhcp.option(DHCP_DOMAIN_NAME_OPT, domain_name_bin, len(self.domain_name)), dhcp.option(DHCP_CLASSLESS_ROUTE, host_routes, len(host_routes))] if self.advertise_mtu: intreface_mtu = self._get_port_mtu(lport) mtu_bin = struct.pack('!H', intreface_mtu) option_list.append(dhcp.option( DHCP_INTERFACE_MTU_OPT, mtu_bin, len(mtu_bin))) options = dhcp.options(option_list=option_list) dhcp_ack_pkt = ryu_packet.Packet() dhcp_ack_pkt.add_protocol(ethernet.ethernet( ethertype=ether.ETH_TYPE_IP, dst=pkt_ethernet.src, src=pkt_ethernet.dst)) dhcp_ack_pkt.add_protocol(ipv4.ipv4(dst=pkt_ipv4.src, src=dhcp_server_address, proto=pkt_ipv4.proto)) dhcp_ack_pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) dhcp_ack_pkt.add_protocol(dhcp.dhcp(op=2, chaddr=pkt_ethernet.src, siaddr=dhcp_server_address, boot_file=dhcp_packet.boot_file, yiaddr=lport.get_ip(), xid=dhcp_packet.xid, options=options)) return dhcp_ack_pkt
def assemble_ack(self, pkt): #self.semaphore.acquire() #self.semaphore.release() req_eth = pkt.get_protocol(ethernet.ethernet) req_ipv4 = pkt.get_protocol(ipv4.ipv4) req_udp = pkt.get_protocol(udp.udp) req = pkt.get_protocol(dhcp.dhcp) req.options.option_list.remove( next(opt for opt in req.options.option_list if opt.tag == 53)) req.options.option_list.insert( 0, dhcp.option(tag=1, value=self.bin_netmask)) req.options.option_list.insert( 0, dhcp.option(tag=3, value=self.bin_server)) req.options.option_list.insert(0, dhcp.option(tag=6, value=self.bin_dns)) # disc.options.option_list.insert( # 0, dhcp.option(tag=12, value=self.hostname)) req.options.option_list.insert( 0, dhcp.option(tag=51, value=struct.pack('!I', self.release_time))) req.options.option_list.insert( 0, dhcp.option(tag=53, value=struct.pack('!B', 5))) # disc.options.option_list.insert( # 0, dhcp.option(tag=54, value=self.hostname)) req.options.option_list.insert( 0, dhcp.option(tag=58, value=struct.pack('!I', self.release_time // 2))) req.options.option_list.insert( 0, dhcp.option(tag=59, value=struct.pack('!I', self.release_time * 7 // 8))) if req_eth.src not in self.ip_pool: return # print(req_eth.src,end=" ") # print(self.ip_pool[req_eth.src][2], time.perf_counter()) self.ip_pool[req_eth.src][1] = time.perf_counter() ack_pkt = packet.Packet() ack_pkt.add_protocol( ethernet.ethernet(ethertype=req_eth.ethertype, dst=req_eth.src, src=self.hw_addr)) ack_pkt.add_protocol( ipv4.ipv4(dst=req_ipv4.dst, src=self.dhcp_server, proto=req_ipv4.proto)) ack_pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) ack_pkt.add_protocol( dhcp.dhcp(op=2, chaddr=req_eth.src, siaddr=self.dhcp_server, boot_file=req.boot_file, yiaddr=self.ip_pool[req_eth.src][0], xid=req.xid, options=req.options)) self.host_check() # self.logger.info("ASSEMBLED ACK: %s" % ack_pkt) return ack_pkt
def assemble_ack(self, pkt): req_eth = pkt.get_protocol(ethernet.ethernet) req_ipv4 = pkt.get_protocol(ipv4.ipv4) req_udp = pkt.get_protocol(udp.udp) req = dhcp.dhcp.parser(pkt[3]) req[0].options.option_list.remove(next(opt for opt in req[0].options.option_list if opt.tag == 53)) req[0].options.option_list.insert(0, dhcp.option(tag=51, value='8640')) req[0].options.option_list.insert(0, dhcp.option(tag=53, value='05'.decode('hex'))) ack_pkt = packet.Packet() ack_pkt.add_protocol(ethernet.ethernet(ethertype=req_eth.ethertype, dst=req_eth.src, src=self.hw_addr)) ack_pkt.add_protocol(ipv4.ipv4(dst=req_ipv4.dst, src=self.dhcp_server, proto=req_ipv4.proto)) ack_pkt.add_protocol(udp.udp(src_port=67,dst_port=68)) ack_pkt.add_protocol(dhcp.dhcp(op=2, chaddr=req_eth.src, siaddr=self.dhcp_server, boot_file=req[0].boot_file, yiaddr=self.ip_addr, xid=req[0].xid, options=req[0].options)) self.logger.info("ASSEMBLED ACK: %s" % ack_pkt) return ack_pkt
def assemble_ack(self, pkt): req_eth = pkt.get_protocol(ethernet.ethernet) req_ipv4 = pkt.get_protocol(ipv4.ipv4) req_udp = pkt.get_protocol(udp.udp) req = pkt.get_protocol(dhcp.dhcp) if not (self.networkMap.findActiveHostByMac(req_eth.src)): return req.options.option_list.remove( next(opt for opt in req.options.option_list if opt.tag == 53)) req.options.option_list.insert(0, dhcp.option(tag=51, value='8640')) req.options.option_list.insert( 0, dhcp.option(tag=53, value='05'.decode('hex'))) req.options.option_list.insert( 0, dhcp.option(tag=1, value=self.bin_netmask)) req.options.option_list.insert( 0, dhcp.option(tag=3, value=self.bin_server)) req.options.option_list.insert(0, dhcp.option(tag=6, value=self.bin_dns)) ack_pkt = packet.Packet() ack_pkt.add_protocol( ethernet.ethernet(ethertype=req_eth.ethertype, dst=req_eth.src, src=self.hw_addr)) ack_pkt.add_protocol( ipv4.ipv4(dst=req_ipv4.dst, src=self.dhcp_server, proto=req_ipv4.proto)) ack_pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) ack_pkt.add_protocol( dhcp.dhcp(op=2, chaddr=req_eth.src, siaddr=self.dhcp_server, boot_file=req.boot_file, yiaddr=(self.networkMap.findActiveHostByMac( req_eth.src).ip), xid=req.xid, options=req.options)) ack_pkt.serialize() return ack_pkt
def assemble_offer(self, pkt): disc_eth = pkt.get_protocol(ethernet.ethernet) disc_ipv4 = pkt.get_protocol(ipv4.ipv4) disc_udp = pkt.get_protocol(udp.udp) disc = dhcp.dhcp.parser(pkt[3]) disc[0].options.option_list.remove(next(opt for opt in disc[0].options.option_list if opt.tag == 55)) disc[0].options.option_list.remove(next(opt for opt in disc[0].options.option_list if opt.tag == 53)) disc[0].options.option_list.remove(next(opt for opt in disc[0].options.option_list if opt.tag == 12)) disc[0].options.option_list.insert(0, dhcp.option(tag=1, value=self.bin_netmask)) disc[0].options.option_list.insert(0, dhcp.option(tag=3, value=self.bin_server)) disc[0].options.option_list.insert(0, dhcp.option(tag=6, value=self.bin_dns)) disc[0].options.option_list.insert(0, dhcp.option(tag=12, value=self.hostname)) disc[0].options.option_list.insert(0, dhcp.option(tag=53, value='02'.decode('hex'))) disc[0].options.option_list.insert(0, dhcp.option(tag=54, value=self.bin_server)) offer_pkt = packet.Packet() offer_pkt.add_protocol(ethernet.ethernet(ethertype=disc_eth.ethertype, dst=disc_eth.src, src=self.hw_addr)) offer_pkt.add_protocol(ipv4.ipv4(dst=disc_ipv4.dst, src=self.dhcp_server, proto=disc_ipv4.proto)) offer_pkt.add_protocol(udp.udp(src_port=67,dst_port=68)) offer_pkt.add_protocol(dhcp.dhcp(op=2, chaddr=disc_eth.src, siaddr=self.dhcp_server, boot_file=disc[0].boot_file, yiaddr=self.ip_addr, xid=disc[0].xid, options=disc[0].options)) self.logger.info("ASSEMBLED OFFER: %s" % offer_pkt) return offer_pkt
def assemble_ack(cls, pkt, datapath, port): req_eth = pkt.get_protocol(ethernet.ethernet) req_ipv4 = pkt.get_protocol(ipv4.ipv4) req_udp = pkt.get_protocol(udp.udp) req = pkt.get_protocol(dhcp.dhcp) wanted_ip = cls.get_option_value(req, 50) src = req_eth.src got_ip = None if src in cls.wan_leases[datapath]: if wanted_ip != cls.wan_leases[datapath][src]: cls.wan_pool.append(cls.wan_leases[datapath][src]) del cls.wan_leases[datapath][src] else: got_ip = cls.wan_leases[datapath][src] if got_ip is None: if src in cls.wan_offers[datapath]: if wanted_ip != cls.wan_offers[datapath][src]: cls.wan_pool.append(cls.wan_offers[datapath][src]) del cls.wan_offers[datapath][src] else: got_ip = cls.wan_offers[datapath][src] if got_ip is None: if wanted_ip in cls.wan_pool[datapath]: cls.wan_pool[datapath].remove(wanted_ip) got_ip = wanted_ip if got_ip is None: # cls.log.warn("%s asked for un-offered %s", src, wanted_ip) # cls.nak(event) # nak return req.options.option_list.remove(next(opt for opt in req.options.option_list if opt.tag == 53)) req.options.option_list.insert(0, dhcp.option(tag=1, value=cls.bin_netmask)) req.options.option_list.insert(0, dhcp.option(tag=3, value=addrconv.ipv4.text_to_bin(cls.dhcp_server[datapath]))) req.options.option_list.insert(0, dhcp.option(tag=6, value=cls.bin_dns)) req.options.option_list.insert(0, dhcp.option(tag=51, value='8640')) req.options.option_list.insert(0, dhcp.option(tag=53, value='05'.decode('hex'))) req.options.option_list.insert(0, dhcp.option(tag=54, value=addrconv.ipv4.text_to_bin(cls.dhcp_server[datapath]))) ack_pkt = packet.Packet() ack_pkt.add_protocol(ethernet.ethernet(ethertype=req_eth.ethertype, dst=src, src=cls.hw_addr)) ack_pkt.add_protocol(ipv4.ipv4(dst=req_ipv4.dst, src=cls.dhcp_server[datapath], proto=req_ipv4.proto)) ack_pkt.add_protocol(udp.udp(src_port=67,dst_port=68)) ack_pkt.add_protocol(dhcp.dhcp(op=2, chaddr=src, hlen=6, # salah di len siaddr=cls.dhcp_server[datapath], boot_file=req.boot_file, yiaddr=wanted_ip, xid=req.xid, options=req.options)) # cls.logger.info("ASSEMBLED ACK: %s" % ack_pkt) # print(wanted_ip, src, datapath, port) cls.add_arp(wanted_ip, src, datapath, port) return ack_pkt
def _create_dhcp_offer(self, pkt, dhcp_packet, lport): pkt_ipv4 = pkt.get_protocol(ipv4.ipv4) pkt_ethernet = pkt.get_protocol(ethernet.ethernet) subnet = self._get_subnet_by_port(lport) if subnet is None: LOG.error(_LE("No subnet found for port <%s>") % lport.get_id()) return dns = self._get_dns_address_list_bin(subnet) dhcp_server_address = self._get_dhcp_server_address(subnet) netmask_bin = self._get_port_netmask(subnet).packed lease_time_bin = struct.pack('!I', self.lease_time) gateway_address = self._get_port_gateway_address(subnet) domain_name_bin = struct.pack('!256s', self.domain_name) option_list = [ dhcp.option(dhcp.DHCP_MESSAGE_TYPE_OPT, b'\x02', 1), dhcp.option(dhcp.DHCP_SUBNET_MASK_OPT, netmask_bin, 4), dhcp.option(dhcp.DHCP_DNS_SERVER_ADDR_OPT, dns, len(dns)), dhcp.option(dhcp.DHCP_IP_ADDR_LEASE_TIME_OPT, lease_time_bin, 4), dhcp.option(dhcp.DHCP_SERVER_IDENTIFIER_OPT, dhcp_server_address.packed, 4), dhcp.option(15, domain_name_bin, len(self.domain_name)) ] if gateway_address: option_list.append( dhcp.option(dhcp.DHCP_GATEWAY_ADDR_OPT, gateway_address.packed, 4)) options = dhcp.options(option_list=option_list) dhcp_offer_pkt = ryu_packet.Packet() dhcp_offer_pkt.add_protocol( ethernet.ethernet(ethertype=ether.ETH_TYPE_IP, dst=pkt_ethernet.src, src=pkt_ethernet.dst)) dhcp_offer_pkt.add_protocol( ipv4.ipv4(dst=pkt_ipv4.src, src=str(dhcp_server_address), proto=pkt_ipv4.proto)) dhcp_offer_pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) dhcp_offer_pkt.add_protocol( dhcp.dhcp(op=2, chaddr=pkt_ethernet.src, siaddr=str(dhcp_server_address), boot_file=dhcp_packet.boot_file, yiaddr=lport.get_ip(), xid=dhcp_packet.xid, options=options)) return dhcp_offer_pkt
def _create_dhcp_offer(self, pkt, dhcp_packet, lport): pkt_ipv4 = pkt.get_protocol(ipv4.ipv4) pkt_ethernet = pkt.get_protocol(ethernet.ethernet) subnet = self._get_subnet_by_port(lport) if subnet is None: LOG.error(_LE("No subnet found for port <%s>") % lport.get_id()) return dns = self._get_dns_address_list_bin(subnet) dhcp_server_address = self._get_dhcp_server_address(subnet) netmask_bin = self._get_port_netmask(subnet).packed lease_time_bin = struct.pack('!I', self.lease_time) gateway_address = self._get_port_gateway_address(subnet) domain_name_bin = struct.pack('!256s', self.domain_name) option_list = [ dhcp.option(dhcp.DHCP_MESSAGE_TYPE_OPT, b'\x02', 1), dhcp.option(dhcp.DHCP_SUBNET_MASK_OPT, netmask_bin, 4), dhcp.option(dhcp.DHCP_DNS_SERVER_ADDR_OPT, dns, len(dns)), dhcp.option(dhcp.DHCP_IP_ADDR_LEASE_TIME_OPT, lease_time_bin, 4), dhcp.option(dhcp.DHCP_SERVER_IDENTIFIER_OPT, dhcp_server_address.packed, 4), dhcp.option(15, domain_name_bin, len(self.domain_name))] if gateway_address: option_list.append(dhcp.option( dhcp.DHCP_GATEWAY_ADDR_OPT, gateway_address.packed, 4)) options = dhcp.options(option_list=option_list) dhcp_offer_pkt = ryu_packet.Packet() dhcp_offer_pkt.add_protocol(ethernet.ethernet( ethertype=ether.ETH_TYPE_IP, dst=pkt_ethernet.src, src=pkt_ethernet.dst)) dhcp_offer_pkt.add_protocol(ipv4.ipv4(dst=pkt_ipv4.src, src=str(dhcp_server_address), proto=pkt_ipv4.proto)) dhcp_offer_pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) dhcp_offer_pkt.add_protocol(dhcp.dhcp(op=2, chaddr=pkt_ethernet.src, siaddr=str(dhcp_server_address), boot_file=dhcp_packet.boot_file, yiaddr=lport.get_ip(), xid=dhcp_packet.xid, options=options)) return dhcp_offer_pkt
def assemble_offer(self, pkt): disc_eth = pkt.get_protocol(ethernet.ethernet) disc_ipv4 = pkt.get_protocol(ipv4.ipv4) disc_udp = pkt.get_protocol(udp.udp) disc = pkt.get_protocol(dhcp.dhcp) #remove pkt.dhcp.option.option_list , tag = 55 (Parameter Request List) disc.options.option_list.remove( next(opt for opt in disc.options.option_list if opt.tag == 55)) #remove pkt.dhcp.option.option_list , tag = 53 (DHCP Message Type) disc.options.option_list.remove( next(opt for opt in disc.options.option_list if opt.tag == 53)) # remove pkt.dhcp.option.option_list , tag = 12 (Host Name) disc.options.option_list.remove( next(opt for opt in disc.options.option_list if opt.tag == 12)) #insert pkt.dhcp.option.option_list , tag = 1 (Subnet Mask) disc.options.option_list.insert(0, dhcp.option(tag=1, value="")) # insert pkt.dhcp.option.option_list , tag = 3 (Router) disc.options.option_list.insert(0, dhcp.option(tag=3, value="")) # insert pkt.dhcp.option.option_list , tag = 6 (Domain Name Server 域名服务器) disc.options.option_list.insert(0, dhcp.option(tag=6, value="")) # insert pkt.dhcp.option.option_list , tag = 12 (Host Name) disc.options.option_list.insert(0, dhcp.option(tag=12, value="")) # insert pkt.dhcp.option.option_list , tag = 53 (DHCP Message Type) disc.options.option_list.insert(0, dhcp.option(tag=53, value='')) # insert pkt.dhcp.option.option_list , tag = 54 (Server Identifier) disc.options.option_list.insert(0, dhcp.option(tag=54, value="")) #Constructing a Packet offer_pkt = packet.Packet() #Packet protocol level one offer_pkt.add_protocol( ethernet.ethernet(ethertype=disc_eth.ethertype, dst=disc_eth.src, src=self.DHCP_MAC)) #Packet protocol level two offer_pkt.add_protocol( ipv4.ipv4(dst=disc_ipv4.dst, src=self.DHCP_server, proto=disc_ipv4.proto)) #Packet protocol level three offer_pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) #Packet protocol level four offer_pkt.add_protocol( dhcp.dhcp(op=2, chaddr=disc_eth.src, siaddr=self.DHCP_server, boot_file=disc.boot_file, yiaddr=self.ip_addr, xid=disc.xid, options=disc.options)) return offer_pkt
def _create_dhcp_reponse(self, dhcp_opts, requested): dhcp_params = {"opts": {} if not dhcp_opts else dhcp_opts} fake_lport = self._build_dhcp_test_fake_lport(dhcp_params) requested_option_connected = ''.join([chr(x) for x in requested]) option_list = [ dhcp.option(dhcp.DHCP_PARAMETER_REQUEST_LIST_OPT, requested_option_connected, len(requested)) ] dhcp_response_pkt = self._send_dhcp_req_to_app(fake_lport, option_list) dhcp_res = dhcp_response_pkt.get_protocol(dhcp.dhcp) self.assertTrue(dhcp_res.options) self.assertTrue(dhcp_res.options.option_list) return dhcp_res
def assemble_ack(self, pkt, datapath): req_eth = pkt.get_protocol(ethernet.ethernet) req_ipv4 = pkt.get_protocol(ipv4.ipv4) req = pkt.get_protocol(dhcp.dhcp) ipaddress, netmask, address, dhcpip = self.get_server_info(datapath) hostipaddress, hostname, dns = self.get_host_info(datapath, req_eth.src) if ipaddress: req.options.option_list.remove( next(opt for opt in req.options.option_list if opt.tag == 53)) req.options.option_list.insert( 0, dhcp.option(tag=51, value='8640')) req.options.option_list.insert( 0, dhcp.option(tag=1, value=netmask)) req.options.option_list.insert( 0, dhcp.option(tag=3, value=ipaddress)) req.options.option_list.insert( 0, dhcp.option(tag=6, value=dns)) req.options.option_list.insert( 0, dhcp.option(tag=12, value=hostname)) req.options.option_list.insert( 0, dhcp.option(tag=54, value=ipaddress)) req.options.option_list.insert( 0, dhcp.option(tag=53, value='05'.decode('hex'))) ack_pkt = packet.Packet() ack_pkt.add_protocol(ethernet.ethernet( ethertype=req_eth.ethertype, dst=req_eth.src, src=address)) ack_pkt.add_protocol( ipv4.ipv4(dst=req_ipv4.dst, src=dhcpip, proto=req_ipv4.proto)) ack_pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) ack_pkt.add_protocol(dhcp.dhcp(op=2, chaddr=req_eth.src, siaddr=dhcpip, boot_file=req.boot_file, yiaddr=hostipaddress[:-3], # to remove /24 xid=req.xid, options=req.options)) self.logger.info("ASSEMBLED ACK: %s -> %s" % (req_eth.src, hostipaddress)) return ack_pkt
def assemble_offer(self, pkt, datapath): disc_eth = pkt.get_protocol(ethernet.ethernet) disc_ipv4 = pkt.get_protocol(ipv4.ipv4) disc = pkt.get_protocol(dhcp.dhcp) offer_pkt = None ipaddress, netmask, address, dhcpip = self.get_server_info(datapath) hostipaddress, hostname, dns = self.get_host_info( datapath, disc_eth.src) if ipaddress: disc.options.option_list.remove( next(opt for opt in disc.options.option_list if opt.tag == 55)) disc.options.option_list.remove( next(opt for opt in disc.options.option_list if opt.tag == 53)) disc.options.option_list.remove( next(opt for opt in disc.options.option_list if opt.tag == 12)) disc.options.option_list.insert( 0, dhcp.option(tag=1, value=netmask)) disc.options.option_list.insert( 0, dhcp.option(tag=3, value=ipaddress)) disc.options.option_list.insert( 0, dhcp.option(tag=6, value=dns)) disc.options.option_list.insert( 0, dhcp.option(tag=12, value=hostname)) disc.options.option_list.insert( 0, dhcp.option(tag=53, value='02'.decode('hex'))) disc.options.option_list.insert( 0, dhcp.option(tag=54, value=ipaddress)) offer_pkt = packet.Packet() offer_pkt.add_protocol(ethernet.ethernet( ethertype=disc_eth.ethertype, dst=disc_eth.src, src=address)) offer_pkt.add_protocol( ipv4.ipv4(dst=disc_ipv4.dst, src=dhcpip, proto=disc_ipv4.proto)) offer_pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) offer_pkt.add_protocol(dhcp.dhcp(op=2, chaddr=disc_eth.src, siaddr=dhcpip, boot_file=disc.boot_file, yiaddr=hostipaddress[:-3], # to remove /24 xid=disc.xid, options=disc.options)) self.logger.info("ASSEMBLED OFFER: %s --> %s" % (disc_eth.src, hostipaddress)) return offer_pkt
def handle_dhcp_request(self, dhcp_pkt, datapath, port): # send dhcp_ack message. dhcp_ack_msg_type = '\x05' self.logger.info("Send DHCP message type %s" % (self.dhcp_msg_type_code[ord(dhcp_ack_msg_type)])) subnet_option = dhcp.option(tag=dhcp.DHCP_SUBNET_MASK_OPT, value=addrconv.ipv4.text_to_bin( self.ip_network.netmask)) gw_option = dhcp.option(tag=dhcp.DHCP_GATEWAY_ADDR_OPT, value=addrconv.ipv4.text_to_bin(self.gw_addr)) dns_option = dhcp.option(tag=dhcp.DHCP_DNS_SERVER_ADDR_OPT, value=addrconv.ipv4.text_to_bin( self.dns_addr)) time_option = dhcp.option(tag=dhcp.DHCP_IP_ADDR_LEASE_TIME_OPT, value='\xFF\xFF\xFF\xFF') msg_option = dhcp.option(tag=dhcp.DHCP_MESSAGE_TYPE_OPT, value=dhcp_ack_msg_type) id_option = dhcp.option(tag=dhcp.DHCP_SERVER_IDENTIFIER_OPT, value=addrconv.ipv4.text_to_bin( self.dhcp_addr)) options = dhcp.options(option_list=[ msg_option, id_option, time_option, subnet_option, gw_option, dns_option ]) hlen = len(addrconv.mac.text_to_bin(dhcp_pkt.chaddr)) # Look up IP by using client mac address client_ip_addr = self.mac_to_client_ip[dhcp_pkt.chaddr] dhcp_pkt = dhcp.dhcp(op=dhcp.DHCP_BOOT_REPLY, hlen=hlen, chaddr=dhcp_pkt.chaddr, yiaddr=client_ip_addr, giaddr=dhcp_pkt.giaddr, xid=dhcp_pkt.xid, options=options) self._send_dhcp_packet(datapath, dhcp_pkt, port)
def handle_dhcp_request(self, dhcp_pkt, datapath, port): # send dhcp_ack message. dhcp_ack_msg_type = '\x05' self.logger.info("Send DHCP message type %s" % (self.dhcp_msg_type_code[ord(dhcp_ack_msg_type)])) subnet_option = dhcp.option(tag=dhcp.DHCP_SUBNET_MASK_OPT, value=addrconv.ipv4.text_to_bin(self.ip_network.netmask)) gw_option = dhcp.option(tag=dhcp.DHCP_GATEWAY_ADDR_OPT, value=addrconv.ipv4.text_to_bin(self.gw_addr)) dns_option = dhcp.option(tag=dhcp.DHCP_DNS_SERVER_ADDR_OPT, value=addrconv.ipv4.text_to_bin(self.dns_addr)) time_option = dhcp.option(tag=dhcp.DHCP_IP_ADDR_LEASE_TIME_OPT, value='\xFF\xFF\xFF\xFF') msg_option = dhcp.option(tag=dhcp.DHCP_MESSAGE_TYPE_OPT, value=dhcp_ack_msg_type) id_option = dhcp.option(tag=dhcp.DHCP_SERVER_IDENTIFIER_OPT, value=addrconv.ipv4.text_to_bin(self.dhcp_addr)) options = dhcp.options(option_list=[msg_option, id_option, time_option, subnet_option, gw_option, dns_option]) hlen = len(addrconv.mac.text_to_bin(dhcp_pkt.chaddr)) # Look up IP by using client mac address client_ip_addr = self.mac_to_client_ip[dhcp_pkt.chaddr] dhcp_pkt = dhcp.dhcp(op=dhcp.DHCP_BOOT_REPLY, hlen=hlen, chaddr=dhcp_pkt.chaddr, yiaddr=client_ip_addr, giaddr=dhcp_pkt.giaddr, xid=dhcp_pkt.xid, options=options) self._send_dhcp_packet(datapath, dhcp_pkt, port)
class Test_dhcp_offer_with_hlen_zero(unittest.TestCase): op = dhcp.DHCP_BOOT_REPLY chaddr = 'aa:aa:aa:aa:aa:aa' htype = 1 hlen = 6 hops = 0 xid = 1 secs = 0 flags = 1 ciaddr = '192.168.10.10' yiaddr = '192.168.20.20' siaddr = '192.168.30.30' giaddr = '192.168.40.40' sname = 'abc' boot_file = '' option_list = [ dhcp.option(dhcp.DHCP_MESSAGE_TYPE_OPT, b'\x02', 1), dhcp.option(dhcp.DHCP_SUBNET_MASK_OPT, b'\xff\xff\xff\x00', 4), dhcp.option(dhcp.DHCP_GATEWAY_ADDR_OPT, b'\xc0\xa8\x0a\x09', 4), dhcp.option(dhcp.DHCP_DNS_SERVER_ADDR_OPT, b'\xc0\xa8\x0a\x09', 4), dhcp.option(dhcp.DHCP_IP_ADDR_LEASE_TIME_OPT, b'\x00\x03\xf4\x80', 4), dhcp.option(dhcp.DHCP_RENEWAL_TIME_OPT, b'\x00\x01\xfa\x40', 4), dhcp.option(dhcp.DHCP_REBINDING_TIME_OPT, b'\x00\x03\x75\xf0', 4), dhcp.option(dhcp.DHCP_SERVER_IDENTIFIER_OPT, b'\xc0\xa8\x0a\x09', 4) ] magic_cookie = '99.130.83.99' options = dhcp.options(option_list=option_list, options_len=50, magic_cookie=magic_cookie) dh = dhcp.dhcp(op, chaddr, options, htype=htype, hlen=0, hops=hops, xid=xid, secs=secs, flags=flags, ciaddr=ciaddr, yiaddr=yiaddr, siaddr=siaddr, giaddr=giaddr, sname=sname, boot_file=boot_file) def test_init(self): eq_(self.op, self.dh.op) eq_(self.htype, self.dh.htype) eq_(self.hlen, self.dh.hlen) eq_(self.hops, self.dh.hops) eq_(self.xid, self.dh.xid) eq_(self.secs, self.dh.secs) eq_(self.flags, self.dh.flags) eq_(self.ciaddr, self.dh.ciaddr) eq_(self.yiaddr, self.dh.yiaddr) eq_(self.siaddr, self.dh.siaddr) eq_(self.giaddr, self.dh.giaddr) eq_(self.chaddr, self.dh.chaddr) eq_(self.sname, self.dh.sname) eq_(self.boot_file, self.dh.boot_file) eq_(str(self.options), str(self.dh.options))
def _handle_dhcp(self, pkt_dhcp, datapath, in_port): dhcp_type = ord(pkt_dhcp.options.option_list[0].value) ofproto = datapath.ofproto parser = datapath.ofproto_parser # the message is DHCP_ DISCOVERY if dhcp_type == 1: self.logger.info("Recieve DHCP_DISCOVERY") dhcp_offer = '\x02' self.logger.info("Send DHCP_OFFER") msg_option = dhcp.option(tag=53, value=dhcp_offer) options = dhcp.options(option_list=[msg_option]) # allocate ip to host yiaddr = self.ip_pool[0] # generate the DHCP_OFFER packet pkt_dhcp = dhcp.dhcp(op=2, chaddr=pkt_dhcp.chaddr, options=options, hlen=6, htype=1, xid=pkt_dhcp.xid, ciaddr=pkt_dhcp.ciaddr, yiaddr=yiaddr) pkt = packet.Packet() pkt.add_protocol( ethernet.ethernet(src=self.hw_addr, dst="ff:ff:ff:ff:ff:ff")) pkt.add_protocol( ipv4.ipv4(src=self.ip, dst="255.255.255.255", proto=17)) pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) pkt.add_protocol(pkt_dhcp) self._send_packet(datapath, in_port, pkt) # the message is DHCP_REQUEST if dhcp_type == 3: self.logger.info("Recieve DHCP_REQUEST") dhcp_ack = '\x05' self.logger.info("Send DHCP_ACK") # set packet type msg_option = dhcp.option(tag=53, value=dhcp_ack) # set dhcp valid time time_option = dhcp.option(tag=51, value='\x00\xFF\xFF\xFF') # set net mask mask_option = dhcp.option(tag=1, value=self.netmask) options = dhcp.options( option_list=[msg_option, time_option, mask_option]) yiaddr = self.ip_pool[0] # delete the used ip self.ip_pool.pop(0) # generate the DHCP_ACK pkt_dhcp = dhcp.dhcp(op=5, chaddr=pkt_dhcp.chaddr, options=options, hlen=6, htype=1, xid=pkt_dhcp.xid, ciaddr=pkt_dhcp.ciaddr, yiaddr=yiaddr) pkt = packet.Packet() pkt.add_protocol( ethernet.ethernet(src=self.hw_addr, dst="ff:ff:ff:ff:ff:ff")) pkt.add_protocol( ipv4.ipv4(src=self.ip, dst="255.255.255.255", proto=17)) pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) pkt.add_protocol(pkt_dhcp) self._send_packet(datapath, in_port, pkt) # install flow table 0 cookie = 0 cookie_mask = 0 table_id = 0 next_table_id = 3 priority = 2000 buffer_id = ofproto.OFP_NO_BUFFER print(pkt_dhcp.chaddr) match = parser.OFPMatch(eth_type=0x800, eth_src=pkt_dhcp.chaddr, ip_proto=17, udp_src=68) instruction = [parser.OFPInstructionGotoTable(next_table_id)] req = parser.OFPFlowMod(datapath=datapath, command=ofproto.OFPFC_ADD, cookie=cookie, cookie_mask=cookie_mask, table_id=table_id, priority=priority, match=match, instructions=instruction) datapath.send_msg(req) # insatll flow table 3 table_id = 3 priority = 3000 instruction = [ parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, []) ] req = parser.OFPFlowMod(datapath=datapath, command=ofproto.OFPFC_ADD, cookie=cookie, cookie_mask=cookie_mask, table_id=table_id, priority=priority, out_port=ofproto.OFPP_ANY, match=match, instructions=instruction) datapath.send_msg(req)
def _create_dhcp_packet(self, packet, dhcp_packet, pkt_type, lport): pkt_ipv4 = packet.get_protocol(ipv4.ipv4) pkt_ethernet = packet.get_protocol(ethernet.ethernet) try: subnet = lport.subnets[0] except IndexError: LOG.warning("No subnet found for port %s", lport.id) return pkt_type_packed = struct.pack('!B', pkt_type) dns = self._get_dns_address_list_bin(subnet) host_routes = self._get_host_routes_list_bin(subnet, lport) dhcp_server_address = subnet.dhcp_ip if not dhcp_server_address: LOG.warning("Could not find DHCP server address for subnet %s", subnet.id) return netmask_bin = subnet.cidr.netmask.packed domain_name_bin = struct.pack('!%ss' % len(self.domain_name), self.domain_name) lease_time_bin = struct.pack('!I', self.lease_time) option_list = [ dhcp.option(dhcp.DHCP_MESSAGE_TYPE_OPT, pkt_type_packed), dhcp.option(dhcp.DHCP_SUBNET_MASK_OPT, netmask_bin), dhcp.option(dhcp.DHCP_IP_ADDR_LEASE_TIME_OPT, lease_time_bin), dhcp.option(dhcp.DHCP_SERVER_IDENTIFIER_OPT, dhcp_server_address.packed), dhcp.option(dhcp.DHCP_DNS_SERVER_ADDR_OPT, dns), dhcp.option(dhcp.DHCP_DOMAIN_NAME_OPT, domain_name_bin), dhcp.option(dhcp.DHCP_CLASSLESS_ROUTE_OPT, host_routes), ] gw_ip = self._get_port_gateway_address(subnet, lport) if gw_ip: option_list.append( dhcp.option(dhcp.DHCP_GATEWAY_ADDR_OPT, netaddr.IPAddress(gw_ip).packed)) if pkt_type == dhcp.DHCP_ACK: intreface_mtu = self._get_port_mtu(lport) mtu_bin = struct.pack('!H', intreface_mtu) option_list.append( dhcp.option(dhcp.DHCP_INTERFACE_MTU_OPT, mtu_bin)) options = dhcp.options(option_list=option_list) dhcp_pkt = ryu_packet.Packet() dhcp_pkt.add_protocol( ethernet.ethernet(ethertype=ether.ETH_TYPE_IP, dst=pkt_ethernet.src, src=pkt_ethernet.dst)) dhcp_pkt.add_protocol( ipv4.ipv4(dst=pkt_ipv4.src, src=dhcp_server_address, proto=pkt_ipv4.proto)) dhcp_pkt.add_protocol( udp.udp(src_port=const.DHCP_SERVER_PORT, dst_port=const.DHCP_CLIENT_PORT)) dhcp_pkt.add_protocol( dhcp.dhcp(op=dhcp.DHCP_BOOT_REPLY, chaddr=pkt_ethernet.src, siaddr=dhcp_server_address, boot_file=dhcp_packet.boot_file, yiaddr=lport.ip, xid=dhcp_packet.xid, options=options)) return dhcp_pkt
def _respond_dhcp(self, datapath, port, pool, pkt_ethernet, pkt_vlan, pkt_ip, pkt_udp, pkt_dhcp): # DHCP message type code options = dict() for option in pkt_dhcp.options.option_list: options[option.tag] = option.value src = pkt_dhcp.chaddr # RESPONSE MSG pkt = packet.Packet() pkt.add_protocol(ethernet.ethernet(ethertype=pkt_ethernet.ethertype, dst=pkt_ethernet.src, src='00:00:00:00:00:00')) if pkt_vlan: pkt.add_protocol(vlan.vlan(cfi=pkt_vlan.cfi, ethertype=pkt_vlan.ethertype, pcp=pkt_vlan.pcp, vid=pkt_vlan.vid)) pkt.add_protocol(ipv4.ipv4(src=pkt_ip.dst, dst=pkt_ip.src, proto=in_proto.IPPROTO_UDP)) pkt.add_protocol(udp.udp(src_port=pkt_udp.dst_port, dst_port=pkt_udp.src_port)) # DISCOVER MSG dhcp_msg_type = ord(options[dhcp.DHCP_MESSAGE_TYPE_OPT]) if dhcp_msg_type == dhcp.DHCP_DISCOVER: msg_type = dhcp.DHCP_OFFER if src in self.leases: offer = self.leases[src] del self.leases[src] self.offers[src] = offer else: offer = self.offers.get(src) if offer is None: if len(pool) == 0: LOG.error("Out of IP addresses") msg_type = dhcp.DHCP_NAK offer = pool[0] if dhcp.DHCP_REQUESTED_IP_ADDR_OPT in options: wanted_ip = IPAddr(addrconv.ipv4.bin_to_text(options[dhcp.DHCP_REQUESTED_IP_ADDR_OPT].value)) if wanted_ip in pool: offer = wanted_ip pool.remove(offer) self.offers[src] = offer wanted_opts = list() if dhcp.DHCP_PARAMETER_REQUEST_LIST_OPT in options: fmt = "s" * len(options[dhcp.DHCP_PARAMETER_REQUEST_LIST_OPT]) wanted_opt_set = struct.unpack(fmt, options[dhcp.DHCP_PARAMETER_REQUEST_LIST_OPT]) for i in wanted_opt_set: wanted_opts.append(ord(i)) option_list = list() option_list.append(dhcp.option(dhcp.DHCP_MESSAGE_TYPE_OPT, chr(msg_type), length=1)) if msg_type is not dhcp.DHCP_NAK: if dhcp.DHCP_SUBNET_MASK_OPT in wanted_opts: option_list.append(dhcp.option(dhcp.DHCP_SUBNET_MASK_OPT, addrconv.ipv4.text_to_bin(self.subnet.toStr()), length=4)) if dhcp.DHCP_GATEWAY_ADDR_OPT in wanted_opts and self.router_addr is not None: option_list.append(dhcp.option(dhcp.DHCP_GATEWAY_ADDR_OPT, addrconv.ipv4.text_to_bin(self.router_addr.toStr()), length=4)) if dhcp.DHCP_DNS_SERVER_ADDR_OPT in wanted_opts and self.dns_addr is not None: option_list.append(dhcp.option(dhcp.DHCP_DNS_SERVER_ADDR_OPT, addrconv.ipv4.text_to_bin(self.dns_addr.toStr()), length=4)) option_list.append(dhcp.option(dhcp.DHCP_IP_ADDR_LEASE_TIME_OPT, chr(self.lease_time), length=4)) option_list.append(dhcp.option(dhcp.DHCP_RENEWAL_TIME_OPT, chr(self.lease_time / 2), length=4)) option_list.append(dhcp.option(dhcp.DHCP_REBINDING_TIME_OPT, chr(self.lease_time * 7 / 8), length=4)) resp_options = dhcp.options(option_list=option_list) pkt.add_protocol(dhcp.dhcp(op=self._MSG_TYPE_BOOT_REPLY, chaddr=pkt_dhcp.chaddr, options=resp_options, xid=pkt_dhcp.xid, ciaddr=pkt_dhcp.ciaddr, yiaddr=offer.toStr(), siaddr=self.ip_addr.toStr(), giaddr='0.0.0.0', sname='', boot_file='')) # REQUEST MSG if dhcp_msg_type == dhcp.DHCP_REQUEST: msg_type = dhcp.DHCP_ACK if dhcp.DHCP_REQUESTED_IP_ADDR_OPT not in options: return wanted_ip = IPAddr(addrconv.ipv4.bin_to_text(options[dhcp.DHCP_REQUESTED_IP_ADDR_OPT])) got_ip = None if src in self.leases: if wanted_ip != self.leases[src]: pool.append(self.leases[src]) del self.leases[src] else: got_ip = self.leases[src] if got_ip is None: if src in self.offers: if wanted_ip != self.offers[src]: pool.append(self.offers[src]) del self.offers[src] else: got_ip = self.offers[src] if got_ip is None: if wanted_ip in pool: pool.remove(wanted_ip) got_ip = wanted_ip if got_ip is None: LOG.warn("%s asked for un-offered %s", src, wanted_ip.toStr()) msg_type = dhcp.DHCP_NAK wanted_opts = list() if dhcp.DHCP_PARAMETER_REQUEST_LIST_OPT in options: fmt = "s" * len(options[dhcp.DHCP_PARAMETER_REQUEST_LIST_OPT]) wanted_opt_set = struct.unpack(fmt, options[dhcp.DHCP_PARAMETER_REQUEST_LIST_OPT]) for i in wanted_opt_set: wanted_opts.append(ord(i)) # DHCP options tag code option_list = list() option_list.append(dhcp.option(dhcp.DHCP_MESSAGE_TYPE_OPT, chr(msg_type), length=1)) if msg_type is not dhcp.DHCP_NAK: if dhcp.DHCP_SUBNET_MASK_OPT in wanted_opts: option_list.append(dhcp.option(dhcp.DHCP_SUBNET_MASK_OPT, addrconv.ipv4.text_to_bin(self.subnet.toStr()), length=4)) if dhcp.DHCP_GATEWAY_ADDR_OPT in wanted_opts and self.router_addr is not None: option_list.append(dhcp.option(dhcp.DHCP_GATEWAY_ADDR_OPT, addrconv.ipv4.text_to_bin(self.router_addr.toStr()), length=4)) if dhcp.DHCP_DNS_SERVER_ADDR_OPT in wanted_opts and self.dns_addr is not None: option_list.append(dhcp.option(dhcp.DHCP_DNS_SERVER_ADDR_OPT, addrconv.ipv4.text_to_bin(self.dns_addr.toStr()), length=4)) option_list.append(dhcp.option(dhcp.DHCP_IP_ADDR_LEASE_TIME_OPT, chr(self.lease_time), length=4)) option_list.append(dhcp.option(dhcp.DHCP_RENEWAL_TIME_OPT, chr(self.lease_time / 2), length=4)) option_list.append(dhcp.option(dhcp.DHCP_REBINDING_TIME_OPT, chr(self.lease_time * 7 / 8), length=4)) resp_options = dhcp.options(option_list=option_list) pkt.add_protocol(dhcp.dhcp(op=self._MSG_TYPE_BOOT_REPLY, chaddr=pkt_dhcp.chaddr, options=resp_options, xid=pkt_dhcp.xid, ciaddr=pkt_dhcp.ciaddr, yiaddr=wanted_ip.toStr(), siaddr=self.ip_addr.toStr(), giaddr='0.0.0.0', sname='', boot_file='')) # RELEASE MSG if dhcp_msg_type == dhcp.DHCP_RELEASE: if self.leases.get(src).toStr() != pkt_dhcp.ciaddr: LOG.warn("%s tried to release unleased %s" % (src, pkt_dhcp.ciaddr)) return del self.leases[src] pool.append(pkt_dhcp.ciaddr) LOG.info("%s released %s" % (src, pkt_dhcp.ciaddr)) self._send_dhcp_reply(datapath, port, pkt) return True
def assemble_offer(self, port, pkt): #self.semaphore.acquire() disc_eth = pkt.get_protocol(ethernet.ethernet) disc_ipv4 = pkt.get_protocol(ipv4.ipv4) disc_udp = pkt.get_protocol(udp.udp) disc = pkt.get_protocol(dhcp.dhcp) try: disc.options.option_list.remove( next(opt for opt in disc.options.option_list if opt.tag == 50)) except: pass disc.options.option_list.remove( next(opt for opt in disc.options.option_list if opt.tag == 55)) disc.options.option_list.remove( next(opt for opt in disc.options.option_list if opt.tag == 53)) disc.options.option_list.remove( next(opt for opt in disc.options.option_list if opt.tag == 12)) disc.options.option_list.insert( 0, dhcp.option(tag=1, value=self.bin_netmask)) disc.options.option_list.insert( 0, dhcp.option(tag=3, value=self.bin_server)) disc.options.option_list.insert(0, dhcp.option(tag=6, value=self.bin_dns)) # disc.options.option_list.insert( # 0, dhcp.option(tag=12, value=self.hostname)) disc.options.option_list.insert( 0, dhcp.option(tag=51, value=struct.pack('!I', self.release_time))) disc.options.option_list.insert( 0, dhcp.option(tag=53, value=struct.pack('!B', 2))) # disc.options.option_list.insert( # 0, dhcp.option(tag=54, value=self.hostname)) disc.options.option_list.insert( 0, dhcp.option(tag=58, value=struct.pack('!I', self.release_time // 2))) disc.options.option_list.insert( 0, dhcp.option(tag=59, value=struct.pack('!I', self.release_time * 7 // 8))) if disc_eth.src not in self.ip_pool: nid = random.choice(self.usable_id) nip = self.ip_addr + str(nid) #print("new host in,mac:" + disc_eth.src + ",ip:" + nip) self.usable_id.remove(nid) self.ip_pool[disc_eth.src] = [nip, time.perf_counter()] else: self.ip_pool[disc_eth.src][1] = time.perf_counter() #print(disc_eth.src, str(self.mac_port[disc_eth.src][1])+":"+str(self.mac_port[disc_eth.src][1])) h = switches.Host( disc_eth.src, str(self.mac_port[disc_eth.src][0]) + ":" + str(self.mac_port[disc_eth.src][1])) h.ipv4.append(self.ip_pool[disc_eth.src][0]) self.send_event_to_observers(event.EventHostAdd(h)) nip = self.ip_pool[disc_eth.src][0] offer_pkt = packet.Packet() offer_pkt.add_protocol( ethernet.ethernet(ethertype=disc_eth.ethertype, dst=disc_eth.src, src=self.hw_addr)) offer_pkt.add_protocol( ipv4.ipv4(dst=disc_ipv4.dst, src=self.dhcp_server, proto=disc_ipv4.proto)) offer_pkt.add_protocol(udp.udp(src_port=67, dst_port=68)) offer_pkt.add_protocol( dhcp.dhcp(op=2, chaddr=disc_eth.src, siaddr=self.dhcp_server, boot_file=disc.boot_file, yiaddr=nip, xid=disc.xid, options=disc.options)) return offer_pkt
class Test_dhcp_offer(unittest.TestCase): op = dhcp.DHCP_BOOT_REPLY chaddr = 'aa:aa:aa:aa:aa:aa' htype = 1 hlen = 6 hops = 0 xid = 1 secs = 0 flags = 1 ciaddr = '192.168.10.10' yiaddr = '192.168.20.20' siaddr = '192.168.30.30' giaddr = '192.168.40.40' sname = 'abc' boot_file = b'' option_list = [ dhcp.option(dhcp.DHCP_MESSAGE_TYPE_OPT, b'\x02', 1), dhcp.option(dhcp.DHCP_SUBNET_MASK_OPT, b'\xff\xff\xff\x00', 4), dhcp.option(dhcp.DHCP_GATEWAY_ADDR_OPT, b'\xc0\xa8\x0a\x09', 4), dhcp.option(dhcp.DHCP_DNS_SERVER_ADDR_OPT, b'\xc0\xa8\x0a\x09', 4), dhcp.option(dhcp.DHCP_IP_ADDR_LEASE_TIME_OPT, b'\x00\x03\xf4\x80', 4), dhcp.option(dhcp.DHCP_RENEWAL_TIME_OPT, b'\x00\x01\xfa\x40', 4), dhcp.option(dhcp.DHCP_REBINDING_TIME_OPT, b'\x00\x03\x75\xf0', 4), dhcp.option(dhcp.DHCP_SERVER_IDENTIFIER_OPT, b'\xc0\xa8\x0a\x09', 4) ] magic_cookie = '99.130.83.99' options = dhcp.options(option_list=option_list, options_len=50, magic_cookie=magic_cookie) dh = dhcp.dhcp(op, chaddr, options, htype=htype, hlen=hlen, hops=hops, xid=xid, secs=secs, flags=flags, ciaddr=ciaddr, yiaddr=yiaddr, siaddr=siaddr, giaddr=giaddr, sname=sname, boot_file=boot_file) buf = b"\x02\x01\x06\x00\x00\x00\x00\x01\x00\x00\x00\x01\xc0\xa8\x0a\x0a"\ + b"\xc0\xa8\x14\x14\xc0\xa8\x1e\x1e\xc0\xa8\x28\x28\xaa\xaa\xaa\xaa"\ + b"\xaa\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x61\x62\x63\x00"\ + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\ + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\ + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\ + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\ + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\ + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\ + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\ + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\ + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\ + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\ + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\ + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x63\x82\x53\x63"\ + b"\x35\x01\x02\x01\x04\xff\xff\xff\x00\x03\x04\xc0\xa8\x0a\x09\x06"\ + b"\x04\xc0\xa8\x0a\x09\x33\x04\x00\x03\xf4\x80\x3a\x04\x00\x01\xfa"\ + b"\x40\x3b\x04\x00\x03\x75\xf0\x36\x04\xc0\xa8\x0a\x09\xff" def setUp(self): pass def tearDown(self): pass def test_init(self): eq_(self.op, self.dh.op) eq_(self.htype, self.dh.htype) eq_(self.hlen, self.dh.hlen) eq_(self.hops, self.dh.hops) eq_(self.xid, self.dh.xid) eq_(self.secs, self.dh.secs) eq_(self.flags, self.dh.flags) eq_(self.ciaddr, self.dh.ciaddr) eq_(self.yiaddr, self.dh.yiaddr) eq_(self.siaddr, self.dh.siaddr) eq_(self.giaddr, self.dh.giaddr) eq_(self.chaddr, self.dh.chaddr) eq_(self.sname, self.dh.sname) eq_(self.boot_file, self.dh.boot_file) eq_(str(self.options), str(self.dh.options)) def test_parser(self): _res = self.dh.parser(self.buf) if type(_res) is tuple: res = _res[0] else: res = _res eq_(self.op, res.op) eq_(self.htype, res.htype) eq_(self.hlen, res.hlen) eq_(self.hops, res.hops) eq_(self.xid, res.xid) eq_(self.secs, res.secs) eq_(self.flags, res.flags) eq_(self.ciaddr, res.ciaddr) eq_(self.yiaddr, res.yiaddr) eq_(self.siaddr, res.siaddr) eq_(self.giaddr, res.giaddr) eq_(self.chaddr, res.chaddr) # sname is 64 byte length. rest of data is filled by '\x00'. eq_(self.sname.ljust(64, '\x00'), res.sname) # boof_file is 128 byte length. rest of data is filled by '\x00'. eq_(self.boot_file.ljust(128, b'\x00'), res.boot_file) eq_(str(self.options), str(res.options)) def test_parser_corrupted(self): buf = self.buf[:128 - (14 + 20 + 8)] _res = self.dh.parser(buf) def test_serialize(self): data = bytearray() prev = None buf = self.dh.serialize(data, prev) res = struct.unpack_from(dhcp.dhcp._DHCP_PACK_STR, six.binary_type(buf)) eq_(self.op, res[0]) eq_(self.htype, res[1]) eq_(self.hlen, res[2]) eq_(self.hops, res[3]) eq_(self.xid, res[4]) eq_(self.secs, res[5]) eq_(self.flags, res[6]) eq_(self.ciaddr, addrconv.ipv4.bin_to_text(res[7])) eq_(self.yiaddr, addrconv.ipv4.bin_to_text(res[8])) eq_(self.siaddr, addrconv.ipv4.bin_to_text(res[9])) eq_(self.giaddr, addrconv.ipv4.bin_to_text(res[10])) eq_(self.chaddr, addrconv.mac.bin_to_text(res[11][:6])) # sname is 64 byte length. rest of data is filled by '\x00'. eq_(self.sname.ljust(64, '\x00'), res[12].decode('ascii')) # boof_file is 128 byte length. rest of data is filled by '\x00'. eq_(self.boot_file.ljust(128, b'\x00'), res[13]) options = dhcp.options.parser( buf[struct.calcsize(dhcp.dhcp._DHCP_PACK_STR):]) eq_(str(self.options), str(options)) def test_to_string(self): option_values = ['tag', 'length', 'value'] opt_str_list = [] for option in self.option_list: _opt_str = ','.join([ '%s=%s' % (k, repr(getattr(option, k))) for k, v in inspect.getmembers(option) if k in option_values ]) opt_str = '%s(%s)' % (dhcp.option.__name__, _opt_str) opt_str_list.append(opt_str) option_str = '[%s]' % ', '.join(opt_str_list) opts_vals = { 'magic_cookie': repr(self.magic_cookie), 'option_list': option_str, 'options_len': repr(self.options.options_len) } _options_str = ','.join([ '%s=%s' % (k, opts_vals[k]) for k, v in inspect.getmembers(self.options) if k in opts_vals ]) options_str = '%s(%s)' % (dhcp.options.__name__, _options_str) dhcp_values = { 'op': repr(self.op), 'htype': repr(self.htype), 'hlen': repr(self.hlen), 'hops': repr(self.hops), 'xid': repr(self.xid), 'secs': repr(self.secs), 'flags': repr(self.flags), 'ciaddr': repr(self.ciaddr), 'yiaddr': repr(self.yiaddr), 'siaddr': repr(self.siaddr), 'giaddr': repr(self.giaddr), 'chaddr': repr(self.chaddr), 'sname': repr(self.sname), 'boot_file': repr(self.boot_file), 'options': options_str } _dh_str = ','.join([ '%s=%s' % (k, dhcp_values[k]) for k, v in inspect.getmembers(self.dh) if k in dhcp_values ]) dh_str = '%s(%s)' % (dhcp.dhcp.__name__, _dh_str) eq_(str(self.dh), dh_str) eq_(repr(self.dh), dh_str) def test_json(self): jsondict = self.dh.to_jsondict() dh = dhcp.dhcp.from_jsondict(jsondict['dhcp']) eq_(str(self.dh), str(dh))