[kea-dev] Strange behaviour with Option 53 - what am I missing?
Francis Dupont
fdupont at isc.org
Tue Jan 30 08:34:07 UTC 2018
Dave Cole writes:
> >>> from kea import *
> >>> p =3D Pkt4(DHCPDISCOVER, 0)
> >>> o =3D p.getOptions()[DHO_DHCP_MESSAGE_TYPE]
> >>> o.getUint8()
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> TypeError: Attempt to read uint8 from option 53 that has size 0
> >>> o.getString()
> '\x01'
>
> The implementation of getUint8 is:
>
> static PyObject *
> Option_getUint8(OptionObj *self, PyObject *args) {
> try {
> return (PyInt_FromLong(self->option_ptr->getUint8()));
> } catch (const exception &e) {
> return (raisePythonError(PyExc_TypeError, e.what()));
> }
> }
=> you don't use the right method: the option 53 dhcp-message-type is
decoded as an OptionInt<uint8_t> not as an Option so its content is
available by getValue().
If you look at the option_int.h file you can see the constructor
with begin/end content iterators does not pass them to the super class
but only to unpack.
You have the same for most of derived classes from Option, I believe
the idea is to save memory: as the content is decoded there is no need
to save it also in the super class object.
Of course this means you have to use a dynamic cast to the derived class
and specialized methods. Or you can repack the option in wire format
using toBinary() and works on the result.
> Whereas the getString is:
>
> static PyObject *
> Option_getString(OptionObj *self, PyObject *args) {
> try {
> vector<uint8_t> value = self->option_ptr->toBinary();
> return (PyString_FromStringAndSize((const char *) &value[0], value.=
> size()));
> } catch (const exception &e) {
> return (raisePythonError(PyExc_TypeError, e.what()));
> }
> }
>
> So when I step through the code with gdb it appears that DHO_DHCP_MESSAGE_T=
> YPE is an instance of OptionInt which does not use the data_ member of Opti=
> on, instead it has another member value_ of the type defined in the templat=
> e argument.
>
> Is it a deliberate choice in the code to require application code to just k=
> now that getUint8 does not work for OptionInt (which subclasses Option)?
=> it is.
> Someone with more of a clue about c++ than me might be able to tell me an e=
> asy (and efficient) way I can make my code notice an OptionInt and internal=
> ly use getValue() rather than getUint8(). Would a dynamic_pointer_cast<Opt=
> ionUint8>(self->option_ptr) be the way to go?
=> you should get the definition from either std_option_defs.h or
runtime libdhcp++ structures and work with it. Or simply repack the
option with toBinary(). In fact it depends on the option format: if it
is simple repacking is easier, if it is complex the OptionCustom provides
tools which makes redecoding useless.
Thanks
Francis Dupont <fdupont at isc.org>
More information about the kea-dev
mailing list