Exemplo n.º 1
0
    def send_dhcp_packet(self,
                         mac: MacAddress,
                         vlan: str,
                         state: DHCPState,
                         dhcp_desc: DHCPDescriptor = None):
        """
        Send DHCP packet and record state in dhcp_client_state.

        Args:
            mac: MAC address of interface
            state: state of DHCP packet
            dhcp_desc: DHCP protocol state.
        Returns:
        """
        ciaddr = None

        # generate DHCP request packet
        if state == DHCPState.DISCOVER:
            dhcp_opts = [("message-type", "discover")]
            dhcp_desc = DHCPDescriptor(mac=mac,
                                       ip="",
                                       vlan=vlan,
                                       state_requested=DHCPState.DISCOVER)
            self._msg_xid = self._msg_xid + 1
            pkt_xid = self._msg_xid
        elif state == DHCPState.REQUEST:
            dhcp_opts = [("message-type", "request"),
                         ("requested_addr", dhcp_desc.ip),
                         ("server_id", dhcp_desc.server_ip)]
            dhcp_desc.state_requested = DHCPState.REQUEST
            pkt_xid = dhcp_desc.xid
            ciaddr = dhcp_desc.ip
        elif state == DHCPState.RELEASE:
            dhcp_opts = [("message-type", "release"),
                         ("server_id", dhcp_desc.server_ip)]
            dhcp_desc.state_requested = DHCPState.RELEASE
            self._msg_xid = self._msg_xid + 1
            pkt_xid = self._msg_xid
            ciaddr = dhcp_desc.ip
        else:
            LOG.warning("Unknown egress request mac %s state %s", str(mac),
                        state)
            return

        dhcp_opts.append("end")
        dhcp_desc.xid = pkt_xid
        with self._dhcp_notify:
            self.dhcp_client_state[mac.as_redis_key(vlan)] = dhcp_desc

        pkt = Ether(src=str(mac), dst="ff:ff:ff:ff:ff:ff")
        if vlan and vlan != "0":
            pkt /= Dot1Q(vlan=int(vlan))
        pkt /= IP(src="0.0.0.0", dst="255.255.255.255")
        pkt /= UDP(sport=68, dport=67)
        pkt /= BOOTP(op=1, chaddr=mac.as_hex(), xid=pkt_xid, ciaddr=ciaddr)
        pkt /= DHCP(options=dhcp_opts)
        LOG.debug("DHCP pkt xmit %s", pkt.show(dump=True))

        sendp(pkt, iface=self._dhcp_interface, verbose=0)
Exemplo n.º 2
0
    def _process_dhcp_pkt(self, packet, state: DHCPState):
        mac_addr = create_mac_from_sid(packet[Ether].dst)
        mac_addr_key = mac_addr.as_redis_key()

        with self._dhcp_notify:
            if mac_addr_key in self.dhcp_client_state:
                ip_offered = packet[BOOTP].yiaddr
                subnet_mask = packet[DHCP].options[5][1]
                ip_subnet = IPv4Network(ip_offered + "/" + subnet_mask, strict=False)

                router_ip_addr = ip_address(packet[DHCP].options[7][1])
                lease_time = packet[DHCP].options[2][1]

                dhcp_state = DHCPDescriptor(mac_addr, ip_offered, state, str(ip_subnet),
                                            packet[IP].src, router_ip_addr, lease_time,
                                            packet[BOOTP].xid)
                LOG.info("Record mac %s IP %s", mac_addr_key, dhcp_state)

                self.dhcp_client_state[mac_addr_key] = dhcp_state

                self.dhcp_gw_info.update_ip(router_ip_addr)
                self._dhcp_notify.notifyAll()

                if state == DHCPState.OFFER:
                    #  let other thread work on fulfilling IP allocation request.
                    threading.Event().wait(self.THREAD_YIELD_TIME)
                    self.send_dhcp_packet(mac_addr, DHCPState.REQUEST, dhcp_state)
            else:
                LOG.debug("Unknown MAC: %s " % packet.summary())
                return
Exemplo n.º 3
0
    def _process_dhcp_pkt(self, packet, state: DHCPState):
        LOG.debug("DHCP pkt recv %s", packet.show(dump=True))

        mac_addr = MacAddress(hex_to_mac(packet[BOOTP].chaddr.hex()[0:12]))
        vlan = ""
        if Dot1Q in packet:
            vlan = str(packet[Dot1Q].vlan)
        mac_addr_key = mac_addr.as_redis_key(vlan)

        with self._dhcp_notify:
            if mac_addr_key in self.dhcp_client_state:
                state_requested = self.dhcp_client_state[
                    mac_addr_key].state_requested
                if BOOTP not in packet or packet[BOOTP].yiaddr is None:
                    LOG.error("no ip offered")
                    return

                ip_offered = packet[BOOTP].yiaddr
                subnet_mask = self._get_option(packet, "subnet_mask")
                if subnet_mask is not None:
                    ip_subnet = IPv4Network(ip_offered + "/" + subnet_mask,
                                            strict=False)
                else:
                    ip_subnet = IPv4Network(ip_offered + "/" + "32",
                                            strict=False)

                dhcp_router_opt = self._get_option(packet, "router")
                if dhcp_router_opt is not None:
                    router_ip_addr = ip_address(dhcp_router_opt)
                    self.dhcp_gw_info.update_ip(router_ip_addr, vlan)
                else:
                    router_ip_addr = None

                lease_expiration_time = self._get_option(packet, "lease_time")
                dhcp_state = DHCPDescriptor(
                    mac=mac_addr,
                    ip=ip_offered,
                    state=state,
                    vlan=vlan,
                    state_requested=state_requested,
                    subnet=str(ip_subnet),
                    server_ip=packet[IP].src,
                    router_ip=router_ip_addr,
                    lease_expiration_time=lease_expiration_time,
                    xid=packet[BOOTP].xid)
                LOG.info("Record DHCP for: %s state: %s", mac_addr_key,
                         dhcp_state)

                self.dhcp_client_state[mac_addr_key] = dhcp_state
                self._dhcp_notify.notifyAll()

                if state == DHCPState.OFFER:
                    #  let other thread work on fulfilling IP allocation request.
                    threading.Event().wait(self.THREAD_YIELD_TIME)
                    self.send_dhcp_packet(mac_addr, vlan, DHCPState.REQUEST,
                                          dhcp_state)
            else:
                LOG.debug("Unknown MAC: %s " % packet.summary())
                return
Exemplo n.º 4
0
    def add_record(self, args):
        """
        Add DHCP record.
        Args:
            args: All data required for DHCP state.

        Returns:

        """

        state = DHCPState(args.state)
        ipaddr = ip_address(args.ip)
        subnet = ip_network(args.subnet, strict=False)
        dhcp_ip = ip_address(args.dhcp)
        desc = DHCPDescriptor(args.mac, str(ipaddr), state, subnet, dhcp_ip, None,
                              args.lease, random.randint(0, 50000))
        mac = MacAddress(args.mac)
        self.dhcp_client_state[mac.as_redis_key()] = desc
        print("Added mac %s with DHCP rec %s" % str(mac), desc)