Thoughts on DHCP Option Definition
Shawn Routhier
sar at isc.org
Fri Sep 28 19:12:43 UTC 2012
One general item I'm not sure is getting addressed - how will these
definitions and the code handle encapsulated options? I see lots
of discussion about an option name and an option value and things
seem to be moving along well there, but I don't see how it will
generalize to sub option spaces (but maybe I just missed something?)
On Sep 28, 2012, at 8:53 AM, Marcin Siodelski wrote:
> On 09/28/2012 02:35 PM, Tomek Mrugalski wrote:
>> On 28.09.2012 13:45, Stephen Morris wrote:
>>> After discussing the option definition issue with Marcin today, I
>>> thought that I'd put down my thoughts on how it would work:
>>
>>> When reading the options, user option definitions would override
>>> vendor-option definitions, which would in turn override pre-defined
>>> option definitions (any overriding being marked by a warning message
>>> written to the log file). At the end of the configuration process,
>>> the option definitions would be stored in some form of option
>>> interpreter object.
>> An approach that prints out warnings when used properly is flawed. We
>> talked about this with Marcin before. If the format user specifies is
>> covered by one of our option classes (integers list, addresses list,
>> fqdn etc), then we use it, because of their simplicity and
>> effectiveness. For stranger formats, there should be one custom class
>> that supports every possible combination, albeit at the cost of
>> increased complexity and lowered performance.
When people are referring to vendor-option definitions are they thinking
of options a vendor may have redefined or of options in the vendor space?
In general I'm having difficulty understanding why we want to restrict what
the user can do to "pre-defined" options. In the current code we use
different formats to describe pre-defined options and user-defined options.
(Though in the end they all get squashed into the same format for processing.)
In this case it makes sense to me to separate the two sets of options.
If we are going to define the pre-defined options and the vendor options
and the user options all in the same format I don't see a lot of use in trying
to separate the pieces. I would consider simply have one place for the
definitions (the .spec file I guess) and simply let the vendor or user
update the file if they wish. They could either add new options or change
the old ones. Yes, this would mean they can break things if they change
a pre-defined option incorrectly, but with power comes responsibility.
In our current code we (sort of anyway) require users to reproduce a bug
with an unmodified copy of the source before we try to fix the problem. I
could imagine the same general style in this case - if the user or vendor
have modified the options they need to either demonstrate the bug
without the changes or demonstrate that the changes won't affect the bug.
>>
>>> The option definitions are the first part of the configuration to be
>>> processed. During the rest of the configuration processing, when the
>>> setting of an option is encountered, the option name and its value is
>>> passed to the interpreter: the return value is a vector of bytes
>>> representing the wire format of the option.
>> I would very much prefer to avoid this, because it would throw away the
>> whole stack we wrote so far. Option definitions should return a pointer
>> to the Option factory instead. That will be used to parse incoming
>> options. Once value for known options are specified, those factories
>> should be used to instantiate objects, using aforementioned factories.
>> The returned Option object will then be used around, stuffed into server
>> responses, passed to hooks etc. Immediately producing on-wire format
>> would be much less useful and more difficult to work with.
>
> So I see it this way:
> * Option definitions are read and set of OptionXDefinition objects is
> created - one for each different option.
> * At this point I can query OptionXDefinition object for appropriate
> Factory() function. It will recognize that option definition is nothing
> more than say option holding uint8_t value and will pick up the Factory
> function that creates it.
> * Now I read the data from the config file. Config file would tell me
> that option foo code 255 for subnet X has the following data foo = "4"
> and for subnet Y it has the following data foo = { "5", "some_string" }.
> * At this point I would probably like to know if the input data matches
> the format specified so I would like to have the validate() function
> exposed by the OptionXDefinition object that says true or false. It
> would say true for subnet X and false for subnet Y. This validation
> could be achieved by simply trying to create the option instance with
> the appropriate Factory function.
> * If validation was successful I want to keep the validated data around
> so I can use it if the need to create particular option comes. I could
> use OptionXDefinition object which would have to have the map. This map
> would kave key poiting to subnet and the value pointing to
> OptionBufffer? This OptionBuffer would be simply a binary version of
> what user provided.
> * At this poit, if server wants to create new option instance it would
> ask appropriate OptionXDefinition object: "give me the Factory function
> to create the Option foo for subnet X. If I call this function I get my
> option.
>
> The only point is that it is in fact very similar to what Stephen
> proposed. The difference is that we do not create options upfront but
> feed option contents to the OptionXDefinition object and the data is
> used when needed.
I think we do want to build the options on the fly. We may include an optimization
to either pre-build the wire form of an option or to save it the first time we build it
if it won't change for example if the configuration indicates to always use a
certain value. I don't think we need that optimization now though.
In the current code the value an option takes can be built from random things
and can change on different invocations even for the same client. We are
hoping and planning to reduce the complexity of the configuration language
so I'm not sure how we wish to set the value for an option yet. (One way to
handle this is to only allow the configuration to set simple values of the
form "data = 4" or "data = 'a.b.c.d', 'e.f.g.h'" and anything complicated needs
to be handled via one or another hook.)
>
> We could possibly think about something that does not mix up data and
> option format in the same OptionXDefinition object but this seems to be
> simple. It may be the pain to have to maintain separate containers with
> data and separate containers with definitions.
>
>>
>>> I suppose the main question are:
>>>
>>> * Having the user being alter pre-defined option definitions -
>>> possibly unsuspectingly - may prove awkward. If, for example, they
>> Agree. That should not be possible at all.
>
> I don't fully understand what it means "alter". Is override any
> different than altering it?
>
>>
>>> change the definition of an option that holds a four-byte integer
>>> value to one that holds a two-byte value, then unless the code
>>> registered an overflow when setting it, the problem would not be
>>> discovered until the data were received at the client.
>>>
>>> * Do we want to allow user and vendor-defined options to override
>>> pre-defined ones?
>> Why would you want to predefine vendor options if you can't possibly
>> know its format?
>>
>> Tomek
>>
>
> Marcin
> _______________________________________________
> bind10-dhcp mailing list
> bind10-dhcp at lists.isc.org
> https://lists.isc.org/mailman/listinfo/bind10-dhcp
More information about the bind10-dhcp
mailing list