def handle_request(self, query: Packet, answer: Packet): b_hwaddr = query.chaddr s_hwaddr = self.fmt_hwaddr(b_hwaddr, query.hlen) b_ipaddr = query.opts.get(dhcplib.DHCPOPT_IPADDR) lease, offer = self.leases.pop(s_hwaddr, None), self.offers.pop(s_hwaddr, None) if offer: b_ipaddr, options = offer else: if b_ipaddr is None: b_ipaddr = self.allocate(s_hwaddr) elif self.get_ip_hwaddr(self.offers, b_ipaddr): b_ipaddr = self.allocate(s_hwaddr) elif self.get_ip_hwaddr(self.leases, b_ipaddr): b_ipaddr = self.allocate(s_hwaddr) elif not self.addr_in_network(b_ipaddr): b_ipaddr = self.allocate(s_hwaddr) options = self.get_options(s_hwaddr, query) self.leases[s_hwaddr] = (b_ipaddr, options) answer.opts[dhcplib.DHCPOPT_MSG_TYPE] = struct.pack('!B', dhcplib.DHCPACK) answer.yiaddr = b_ipaddr for (k, v) in options.items(): answer.opts[k] = v self.finalize(s_hwaddr, query, answer)
def handle(self, interface, query: Packet): answer = query.reply() for middleware in self.middleware: if middleware[0].handle_dhcp_packet(interface, query, answer): return answer, middleware[0] return answer, None
def read(self): buf, ancdata, _, addr = self._sock.recvmsg(512, socket.CMSG_SPACE(100)) interface = self._get_cmsg_to(ancdata) try: query = Packet.parse(buf) answer, pool = self._handler.handle(interface, query) if not pool: return if answer.is_broadcast(): print('dhcp: got net broadcast on %s', interface) self.broadcast(answer, interface, addr[1]) elif addr[0] == '0.0.0.0': print('dhcp: got adr broadcast on %s', interface) addr = (socket.inet_ntoa(pool.broadcast), addr[1]) self._queue.append((addr, answer)) else: print('dhcp: got unicast from %s', addr[0]) self._queue.append((addr, answer)) except Exception as e: traceback.print_exc()