def put(self, msg=None, dport=67): ''' Put DHCP message. Parameters: * msg -- dhcp4msg instance * dport -- DHCP server port If `msg` is not provided, it is constructed as default BOOTREQUEST + DHCPDISCOVER. Examples:: sock.put(dhcp4msg({'op': BOOTREQUEST, 'chaddr': 'ff:11:22:33:44:55', 'options': {'message_type': DHCPREQUEST, 'parameter_list': [1, 3, 6, 12, 15], 'requested_ip': '172.16.101.2', 'server_id': '172.16.101.1'}})) The method returns dhcp4msg that was sent, so one can get from there `xid` (transaction id) and other details. ''' # DHCP layer dhcp = msg or dhcp4msg({'chaddr': self.l2addr}) # dhcp transaction id if dhcp['xid'] is None: dhcp['xid'] = self.xid_pool.alloc() data = dhcp.encode().buf # UDP layer udp = udpmsg({'sport': self.port, 'dport': dport, 'len': 8 + len(data)}) udph = udp4_pseudo_header({'dst': '255.255.255.255', 'len': 8 + len(data)}) udp['csum'] = self.csum(udph.encode().buf + udp.encode().buf + data) udp.reset() # IPv4 layer ip4 = ip4msg({'len': 20 + 8 + len(data), 'proto': 17, 'dst': '255.255.255.255'}) ip4['csum'] = self.csum(ip4.encode().buf) ip4.reset() # MAC layer eth = ethmsg({'dst': 'ff:ff:ff:ff:ff:ff', 'src': self.l2addr, 'type': 0x800}) data = eth.encode().buf +\ ip4.encode().buf +\ udp.encode().buf +\ data self.send(data) dhcp.reset() return dhcp
def get(self): ''' Get the next incoming packet from the socket and try to decode it as IPv4 DHCP. No analysis is done here, only MAC/IPv4/UDP headers are stripped out, and the rest is interpreted as DHCP. ''' (data, addr) = self.recvfrom(4096) eth = ethmsg(buf=data).decode() ip4 = ip4msg(buf=data, offset=eth.offset).decode() udp = udpmsg(buf=data, offset=ip4.offset).decode() return dhcp4msg(buf=data, offset=udp.offset).decode()
def put(self, msg=None, dport=67): ''' Put DHCP message. Parameters: * msg -- dhcp4msg instance * dport -- DHCP server port If `msg` is not provided, it is constructed as default BOOTREQUEST + DHCPDISCOVER. Examples:: sock.put(dhcp4msg({'op': BOOTREQUEST, 'chaddr': 'ff:11:22:33:44:55', 'options': {'message_type': DHCPREQUEST, 'parameter_list': [1, 3, 6, 12, 15], 'requested_ip': '172.16.101.2', 'server_id': '172.16.101.1'}})) The method returns dhcp4msg that was sent, so one can get from there `xid` (transaction id) and other details. ''' # DHCP layer dhcp = msg or dhcp4msg({'chaddr': self.l2addr}) # dhcp transaction id if dhcp['xid'] is None: dhcp['xid'] = self.xid_pool.alloc() data = dhcp.encode().buf # UDP layer udp = udpmsg({ 'sport': self.port, 'dport': dport, 'len': 8 + len(data) }) udph = udp4_pseudo_header({ 'dst': '255.255.255.255', 'len': 8 + len(data) }) udp['csum'] = self.csum(udph.encode().buf + udp.encode().buf + data) udp.reset() # IPv4 layer ip4 = ip4msg({ 'len': 20 + 8 + len(data), 'proto': 17, 'dst': '255.255.255.255' }) ip4['csum'] = self.csum(ip4.encode().buf) ip4.reset() # MAC layer eth = ethmsg({ 'dst': 'ff:ff:ff:ff:ff:ff', 'src': self.l2addr, 'type': 0x800 }) data = eth.encode().buf +\ ip4.encode().buf +\ udp.encode().buf +\ data self.send(data) dhcp.reset() return dhcp