Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.0.0: Can't display DHCP packets coming from iPXE #37

Closed
GoogleCodeExporter opened this issue May 22, 2015 · 5 comments
Closed

2.0.0: Can't display DHCP packets coming from iPXE #37

GoogleCodeExporter opened this issue May 22, 2015 · 5 comments

Comments

@GoogleCodeExporter
Copy link

I defined this trivial loadDHCPPacket function:

def loadDHCPPacket(packet, method, mac, definition, relay_ip, pxe, 
source_packet):
    print source_packet
    return True

and, it crashes with the following exception:

Exception in thread Thread-3:
Traceback (most recent call last):
  File "/usr/lib64/python2.6/threading.py", line 532, in __bootstrap_inner
    self.run()
  File "/usr/lib64/python2.6/threading.py", line 484, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/root/staticdhcpd-read-only-2/staticDHCPd/staticdhcpdlib/dhcp.py", line 391, in wrappedHandler
    f(self, wrapper)
  File "/root/staticdhcpd-read-only-2/staticDHCPd/staticdhcpdlib/dhcp.py", line 498, in _handleDHCPDiscover
    if wrapper.loadDHCPPacket(definition):
  File "/root/staticdhcpd-read-only-2/staticDHCPd/staticdhcpdlib/dhcp.py", line 346, in loadDHCPPacket
    self._original_packet
  File "/root/staticdhcpd-read-only-2/staticDHCPd/conf/conf.py", line 224, in loadDHCPPacket
    print source_packet
  File "/root/staticdhcpd-read-only-2/staticDHCPd/libpydhcpserver/dhcp_types/packet.py", line 1028, in __str__
    } for id in self.getSelectedOptions())
  File "/root/staticdhcpd-read-only-2/staticDHCPd/libpydhcpserver/dhcp_types/packet.py", line 1028, in <genexpr>
    } for id in self.getSelectedOptions())
KeyError: 175


As a reminder, the iPXE boot packet looks like this:

14:53:06.602518 IP (tos 0x0, ttl 64, id 1821, offset 0, flags [none], proto UDP 
(17), length 427)
    0.0.0.0.bootpc > 255.255.255.255.bootps: [udp sum ok] BOOTP/DHCP, Request from 52:54:00:9e:be:28, length 399, xid 0x65eea51e, secs 12, Flags [none] (0x0000)
          Client-Ethernet-Address 52:54:00:9e:be:28
          Vendor-rfc1048 Extensions
            Magic Cookie 0x63825363
            DHCP-Message Option 53, length 1: Discover
            MSZ Option 57, length 2: 1472
            ARCH Option 93, length 2: 0
            NDI Option 94, length 3: 1.2.1
            Vendor-Class Option 60, length 32: "PXEClient:Arch:00000:UNDI:002001"
            CLASS Option 77, length 4: "iPXE"
            Parameter-Request Option 55, length 22:
              Subnet-Mask, Default-Gateway, Domain-Name-Server, LOG
              Hostname, Domain-Name, RP, Vendor-Option
              Vendor-Class, TFTP, BF, Option 119
              Option 128, Option 129, Option 130, Option 131
              Option 132, Option 133, Option 134, Option 135
              Option 175, Option 203
            T175 Option 175, length 48: 



This seems to originate from DHCP_OPTIONS not having a setting for option 175.  
I'm not sure if a better solution is to just add it (which is what I did), or 
handle unknown IDs better.

Original issue reported on code.google.com by d...@devicenull.org on 3 Oct 2014 at 7:11

@GoogleCodeExporter
Copy link
Author

Part two of this:

Exception in thread Thread-5:
Traceback (most recent call last):
  File "/usr/lib64/python2.6/threading.py", line 532, in __bootstrap_inner
    self.run()
  File "/usr/lib64/python2.6/threading.py", line 484, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/root/staticdhcpd-read-only-2/staticDHCPd/staticdhcpdlib/dhcp.py", line 391, in wrappedHandler
    f(self, wrapper)
  File "/root/staticdhcpd-read-only-2/staticDHCPd/staticdhcpdlib/dhcp.py", line 498, in _handleDHCPDiscover
    if wrapper.loadDHCPPacket(definition):
  File "/root/staticdhcpd-read-only-2/staticDHCPd/staticdhcpdlib/dhcp.py", line 346, in loadDHCPPacket
    self._original_packet
  File "/root/staticdhcpd-read-only-2/staticDHCPd/conf/conf.py", line 224, in loadDHCPPacket
    print source_packet
  File "/root/staticdhcpd-read-only-2/staticDHCPd/libpydhcpserver/dhcp_types/packet.py", line 1030, in __str__
    result = _FORMAT_CONVERSION_DESERIAL[DHCP_OPTIONS_TYPES[option_id]](data)
KeyError: 'RFC3004_77'

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib64/python2.6/threading.py", line 532, in __bootstrap_inner
    self.run()
  File "/usr/lib64/python2.6/threading.py", line 484, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/root/staticdhcpd-read-only-2/staticDHCPd/staticdhcpdlib/dhcp.py", line 391, in wrappedHandler
    f(self, wrapper)
  File "/root/staticdhcpd-read-only-2/staticDHCPd/staticdhcpdlib/dhcp.py", line 498, in _handleDHCPDiscover
    if wrapper.loadDHCPPacket(definition):
  File "/root/staticdhcpd-read-only-2/staticDHCPd/staticdhcpdlib/dhcp.py", line 346, in loadDHCPPacket
    self._original_packet
  File "/root/staticdhcpd-read-only-2/staticDHCPd/conf/conf.py", line 224, in loadDHCPPacket
    print source_packet
  File "/root/staticdhcpd-read-only-2/staticDHCPd/libpydhcpserver/dhcp_types/packet.py", line 1030, in __str__
    result = _FORMAT_CONVERSION_DESERIAL[DHCP_OPTIONS_TYPES[option_id]](data)
KeyError: 'Unassigned'


I fixed all of these with the following patch:

Index: libpydhcpserver/dhcp_types/constants.py
===================================================================
--- libpydhcpserver/dhcp_types/constants.py     (revision 776)
+++ libpydhcpserver/dhcp_types/constants.py     (working copy)
@@ -218,7 +218,7 @@
  74: TYPE_IPV4_PLUS,
  75: TYPE_IPV4_PLUS,
  76: TYPE_IPV4_PLUS,
- 77: "RFC3004_77", #Not implemented; not necessary for static model
+ 77: TYPE_NONE, #Not implemented; not necessary for static model
  78: "RFC2610_78", #Implemented
  79: "RFC2610_79", #Implemented
  80: TYPE_NONE,
@@ -284,7 +284,7 @@
  163: "Unassigned", 164: "Unassigned", 165: "Unassigned", 166: "Unassigned",
  167: "Unassigned", 168: "Unassigned", 169: "Unassigned", 170: "Unassigned",
  171: "Unassigned", 172: "Unassigned", 173: "Unassigned", 174: "Unassigned",
- 175: "Unassigned", #Etherboot
+ 175: TYPE_NONE, #Etherboot
  176: "Unassigned", #IP Telephone
  177: "Unassigned", #Etherboot
  178: "Unassigned", 179: "Unassigned", 180: "Unassigned", 181: "Unassigned",
@@ -459,6 +459,7 @@
  'capwap_ac_v4': 138,
  'ipv4_mos': 139,
  'fqdn_mos': 140,
+ 'ipxe_test': 175,
  #hole
  'pxelinux_magic': 208,
  'configuration_file': 209,


Original comment by d...@devicenull.org on 3 Oct 2014 at 7:15

@GoogleCodeExporter
Copy link
Author

In r782, this is handled by making the string-serialiser less-naive when 
iterating over options. Providing a null implementation for something that is 
unsupported seems like a bad idea (because it doesn't explicitly mark it as 
untouched for anyone looking to extend functionality), but the net effect would 
be about the same.

Since you've got an iPXE setup, any practical data you can share could help 
with building a useful implementation for the protocol. (I'll be leaving this 
issue unclosed in case you want to follow up on it)

As always, thanks for the feedback!

Original comment by red.hamsterx on 9 Oct 2014 at 1:11

@GoogleCodeExporter
Copy link
Author

Original comment by red.hamsterx on 9 Oct 2014 at 1:11

  • Changed state: Started

@GoogleCodeExporter
Copy link
Author

iPXE uses this field to indicate some additional data about it's configuration 
(such as what protocols are supported).  This is documented at 
http://ipxe.org/howto/dhcpd#ipxe-specific_options

This does have some handy uses (for example, you can burn a trimmed down 
version of iPXE to your NIC's flash, and then load a fully featured version 
over the network).

However, it's a fairly uncommon feature (most people use the NIC's built in 
firmware to load iPXE, so feature checks are unnecessary)

Original comment by d...@devicenull.org on 9 Oct 2014 at 1:32

@GoogleCodeExporter
Copy link
Author

Somehow skipped over this one following your last reply. Sorry. :(

Merged in r785. I went with TYPE_STRING instead of TYPE_NONE, since that allows 
for the possibility of the operator entering their own data and parsing 
requests. If you can provide a raw packet capture at some point in the future, 
I'll reimplement it as a proper data-structure.

Original comment by red.hamsterx on 21 Mar 2015 at 4:12

@flan flan closed this as completed Jan 25, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants