Example #1
0
File: dhcp.py Project: Robin131/NAT
    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)
Example #2
0
File: dhcp.py Project: John-Lin/nat
    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)
Example #3
0
    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)
Example #4
0
    def _send_dhcp_req_to_app(self, lport, options=None):
        req = dhcp.dhcp(op=dhcp.DHCP_DISCOVER,
                        chaddr='aa:aa:aa:aa:aa:aa',
                        options=dhcp.options(options))
        pkt = self._create_fake_empty_packet()
        dhcp_response_pkt = self.app._create_dhcp_response(
            pkt, req, dhcp.DHCP_OFFER, lport)

        return dhcp_response_pkt
Example #5
0
    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)
Example #6
0
    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
Example #7
0
    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
Example #8
0
    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
Example #9
0
    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
Example #10
0
    def _create_dhcp_response(self, packet, dhcp_request, response_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

        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

        option_list = self._build_dhcp_options(dhcp_request, response_type,
                                               lport, subnet,
                                               dhcp_server_address)

        options = dhcp.options(option_list=option_list)

        dhcp_server_address = subnet.dhcp_ip
        dhcp_response = ryu_packet.Packet()
        dhcp_response.add_protocol(
            ethernet.ethernet(ethertype=ether.ETH_TYPE_IP,
                              dst=pkt_ethernet.src,
                              src=pkt_ethernet.dst))
        dhcp_response.add_protocol(
            ipv4.ipv4(dst=pkt_ipv4.src,
                      src=dhcp_server_address,
                      proto=pkt_ipv4.proto))
        dhcp_response.add_protocol(
            udp.udp(src_port=const.DHCP_SERVER_PORT,
                    dst_port=const.DHCP_CLIENT_PORT))

        siaddr = lport.dhcp_params.siaddr or dhcp_server_address

        dhcp_response.add_protocol(
            dhcp.dhcp(op=dhcp.DHCP_BOOT_REPLY,
                      chaddr=pkt_ethernet.src,
                      siaddr=siaddr,
                      boot_file=dhcp_request.boot_file,
                      yiaddr=lport.ip,
                      xid=dhcp_request.xid,
                      options=options))
        return dhcp_response
Example #11
0
File: dhcp.py Project: Robin131/NAT
    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)
Example #12
0
File: dhcp.py Project: John-Lin/nat
    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)
Example #13
0
    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)
Example #14
0
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))
Example #15
0
    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
Example #16
0
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))
Example #17
0
    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