classify.xml 49.5 KB
Newer Older
1
<!--
2
 - Copyright (C) 2015-2019 Internet Systems Consortium, Inc. ("ISC")
3
4
5
 -
 - This Source Code Form is subject to the terms of the Mozilla Public
 - License, v. 2.0. If a copy of the MPL was not distributed with this
6
 - file, you can obtain one at http://mozilla.org/MPL/2.0/.
7
-->
8

9
10
<!-- Converted by db4-upgrade version 1.1 -->
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="classify">
11
12
13
14
15
16
  <title>Client Classification</title>

  <section>
    <title>Client Classification Overview</title>
      <para>
      In certain cases it is useful to differentiate between different
17
      types of clients and treat them accordingly. Common reasons include:
18
19
      <itemizedlist>
      <listitem><para>
20
      The clients represent different pieces of topology, e.g. a cable
21
      modem is not the same as the clients behind that modem.
22
23
      </para></listitem>
      <listitem><para>
24
      The clients have different behavior, e.g. a smart phone behaves
Suzanne Goldlust's avatar
Suzanne Goldlust committed
25
      differently from a laptop.
26
27
      </para></listitem>
      <listitem><para>
28
      The clients require different values for some options, e.g. a docsis3.0
29
      cable modem requires different settings from a docsis2.0 cable modem.
30
31
32
33
34
      </para></listitem>
      </itemizedlist>
      </para>

      <para>
35
36
      To make management easier, different clients can be grouped into a client class to receive
      common options.
37
38
39
      </para>

      <para>
Francis Dupont's avatar
Francis Dupont committed
40
      An incoming packet can be associated with a client class in
41
      several ways:
Francis Dupont's avatar
Francis Dupont committed
42
43
      <itemizedlist>
      <listitem><para>
44
      Implicitly, using a vendor class option or another builtin condition.
Francis Dupont's avatar
Francis Dupont committed
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
      </para></listitem>
      <listitem><para>
      Using an expression which evaluates to true.
      </para></listitem>
      <listitem><para>
      Using static host reservations, a shared network, a subnet, etc.
      </para></listitem>
      <listitem><para>
      Using a hook.
      </para></listitem>
      </itemizedlist>
      </para>

      <para>
      It is envisaged that client classification will be used for
      changing the behavior of almost any part of the DHCP message
61
62
      processing.
      There are currently five mechanisms that take advantage of
Francis Dupont's avatar
Francis Dupont committed
63
64
      client classification: subnet selection, pool selection,
      definition of DHCPv4 private (codes 224-254) and code 43
65
      options, assignment of different options, and, for DHCPv4 cable
Francis Dupont's avatar
Francis Dupont committed
66
67
68
69
70
      modems, the setting of specific options for use with the TFTP
      server address and the boot file field.
      </para>

      <para>
71
      The classification process is conducted in several steps:
72
73
      <orderedlist>
      <listitem><para>
Francis Dupont's avatar
Francis Dupont committed
74
75
76
77
78
79
      The ALL class is associated with the incoming packet.
      </para></listitem>
      <listitem><para>
      Vendor class options are processed.
      </para></listitem>
      <listitem><para>
80
      Classes with matching expressions and not marked for later ("on
81
82
      request" or depending on the KNOWN/UNKNOWN builtin classes)
      evaluation are processed in the order they are defined in the
83
84
      configuration; the boolean expression is evaluated and, if it
      returns true ("match"), the incoming packet is associated with the
85
      class.
86
87
      </para></listitem>
      <listitem><para>
88
89
      If a private or code 43 DHCPv4 option is received, it is decoded
      following its client class or global (or, for option 43, last
90
91
92
      resort) definition.
      </para></listitem>
      <listitem><para>
93
94
95
      A subnet is chosen, possibly based on the class information when
      some subnets are reserved. More precisely: when choosing a subnet,
      the server iterates over all of the subnets that are
Francis Dupont's avatar
Francis Dupont committed
96
      feasible given the information found in the packet (client
97
98
99
      address, relay address, etc). It uses the first subnet it
      finds that either doesn't have a class associated with it, or
      has a class which matches one of the packet's classes.
100
101
      </para></listitem>
      <listitem><para>
102
      The server looks for host reservations. If an identifier from the
103
      incoming packet matches a host reservation in the subnet or
104
105
      shared network, the packet is associated with the KNOWN class
      and all classes of the host reservation. If a reservation is not
106
      found, the packet is assigned to the UNKNOWN class.
107
108
      </para></listitem>
      <listitem><para>
109
      Classes with matching expressions - directly or indirectly using
110
      the KNOWN/UNKNOWN builtin classes and not marked for later ("on
111
112
113
114
115
      request") evaluation - are processed in the order they are defined
      in the configuration; the boolean expression is evaluated and,
      if it returns true ("match"), the incoming packet is associated
      with the class. After a subnet is selected, the server determines whether there is a reservation
      for a given client. Therefore, it
116
117
      is not possible to use KNOWN/UNKNOWN classes to select a shared
      network or a subnet.
118
119
      </para></listitem>
      <listitem><para>
Francis Dupont's avatar
Francis Dupont committed
120
121
      If needed, addresses and prefixes from pools are assigned,
      possibly based on the class information when some pools are
122
      reserved for class members.
123
124
      </para></listitem>
      <listitem><para>
125
126
127
      Classes marked as "required" are evaluated in the order in which they
      are listed: first the shared network, then the subnet,
      and finally the pools that assigned resources belong to.
Francis Dupont's avatar
Francis Dupont committed
128
129
      </para></listitem>
      <listitem><para>
130
131
132
      Options are assigned, again possibly based on the class information
      in the order that classes were associated with the incoming packet.
      For DHCPv4 private and code 43 options, this includes class local
133
      option definitions.
134
135
      </para></listitem>
      </orderedlist>
136
137
      </para>

Francis Dupont's avatar
Francis Dupont committed
138
      <note>
139
      <para>
140
      Client classes in Kea follow the order
141
      in which they are specified in the configuration
142
      (vs. alphabetical order). Required classes
143
      follow the order in which they are required.
144
      </para>
Francis Dupont's avatar
Francis Dupont committed
145
      </note>
146

147
      <para>
148
      When determining which options to include in the response, the
149
150
151
152
      server examines the union of options from all of the
      assigned classes. If two or more classes include the
      same option, the value from the first class examined is
      used; classes are examined in the order they were associated,
Francis Dupont's avatar
Francis Dupont committed
153
154
      so ALL is always the first class and matching required classes
      are last.
155
156
      </para>

157
      <para>
Francis Dupont's avatar
Francis Dupont committed
158
      As an example, imagine that an incoming packet matches two
159
160
      classes. Class "foo" defines values for an NTP server (option
      42 in DHCPv4) and an SMTP server (option 69 in DHCPv4), while
Francis Dupont's avatar
Francis Dupont committed
161
      class "bar" defines values for an NTP server and a POP3 server
162
163
164
165
      (option 70 in DHCPv4). The server examines the three
      options - NTP, SMTP, and POP3 - and returns any that the
      client requested. As the NTP server was defined twice, the
      server chooses only one of the values for the reply; the
Francis Dupont's avatar
Francis Dupont committed
166
      class from which the value is obtained is unspecified.
167
168
169
170
171
      </para>

      <note>
      <para>
        Care should be taken with client classification as it is easy for
172
        clients that do not meet any class criteria to be denied service altogether.
173
174
175
176
      </para>
      </note>
  </section>

177
  <section xml:id="classification-using-vendor">
Francis Dupont's avatar
Francis Dupont committed
178
    <title>Builtin Client Classes</title>
179
      <para>
180
      Some classes are builtin, so they do not need to be defined. The main
Francis Dupont's avatar
Francis Dupont committed
181
182
183
184
185
      example uses Vendor Class information: The server checks whether
      an incoming DHCPv4 packet includes the vendor class identifier
      option (60) or an incoming DHCPv6 packet includes the vendor
      class option (16). If it does, the content of that option is
      prepended with &quot;VENDOR_CLASS_&quot; and the result is
186
187
188
      interpreted as a class. For example, modern cable modems
      send this option with value &quot;docsis3.0&quot;, so the
      packet belongs to class &quot;VENDOR_CLASS_docsis3.0&quot;.
Francis Dupont's avatar
Francis Dupont committed
189
190
      </para>

191
192
193
194
      <para>The &quot;HA_&quot; prefix is used by the High Availability
      hooks library to designate certain servers to process DHCP packets
      as a result of load balancing. The class name is constructed by
      prepending the &quot;HA_&quot; prefix to the name of the server
195
196
      which should process the DHCP packet. This server will use an appropriate
      pool or subnet to allocate IP addresses (and/or prefixes), based on
197
      the assigned client classes. The details can be found in
198
199
      <xref linkend="high-availability-library"/>.</para>

200
201
202
      <para>Other examples are: the ALL class, which all incoming packets
      belong to, and the KNOWN class, assigned when host reservations exist
      for a particular client. By convention, builtin classes' names
203
      begin with all capital letters.
204
      </para>
205

206
      <para>Currently recognized builtin class names are ALL, KNOWN
207
208
209
210
      and UNKNOWN, and prefixes VENDOR_CLASS_, HA_, AFTER_, and
      EXTERNAL_. Although the AFTER_ prefix is a provision for an as-yet-unwritten
      hook, the EXTERNAL_ prefix can be freely used; builtin
      classes are implicitly defined so they never raise warnings if they
211
      do not appear in the configuration.
212
      </para>
213

214
215
  </section>

216
  <section xml:id="classification-using-expressions">
217
    <title>Using Expressions in Classification</title>
218
      <para>
Suzanne Goldlust's avatar
Suzanne Goldlust committed
219
      The expression portion of a classification definition contains operators and
220
      values. All values are currently strings; operators take a
Francis Dupont's avatar
Francis Dupont committed
221
      string or strings and return another string. When all the
222
223
      operations have completed, the result should be a value of
      &quot;true&quot; or &quot;false&quot;. The packet belongs to
Francis Dupont's avatar
Francis Dupont committed
224
225
226
      the class (and the class name is added to the list of classes)
      if the result is &quot;true&quot;. Expressions are written in
      standard format and can be nested.
227
228
229
      </para>

      <para>
Francis Dupont's avatar
Francis Dupont committed
230
231
232
      Expressions are pre-processed during the parsing of the
      configuration file and converted to an internal
      representation. This allows certain types of errors to be caught
233
234
235
236
      and logged during parsing. Examples of these errors include an
      incorrect number or type of argument to an operator. The
      evaluation code also checks for this class of error and
      generally throws an exception, though this should not occur in a
Francis Dupont's avatar
Francis Dupont committed
237
      normally functioning system.
238
239
240
241
242
243
      </para>

      <para>
      Other issues, for example the starting position of a substring being
      outside of the substring or an option not existing in the packet, result
      in the operator returning an empty string.
244
245
246
      </para>

      <para>
247
      Dependencies between classes are also checked. For instance,
248
      forward dependencies are rejected when the configuration is
249
250
      parsed; an expression can only depend on already-defined classes
      (including builtin classes) which are evaluated in a
251
252
      previous or the same evaluation phase. This does not apply to
      the KNOWN or UNKNOWN classes.
Francis Dupont's avatar
Francis Dupont committed
253
254
      </para>

255
      <para>
256
        <table frame="all" xml:id="classification-values-list">
257
          <title>List of Classification Values</title>
258
259
260
261
          <tgroup cols="3">
          <colspec colname="name"/>
          <colspec colname="example"/>
          <colspec colname="description"/>
262
263
264
          <thead>
            <row>
              <entry>Name</entry>
Francis Dupont's avatar
Francis Dupont committed
265
266
              <entry>Example expression</entry>
              <entry>Example value</entry>
267
268
269
              <entry>Description</entry>
            </row>
          </thead>
Francis Dupont's avatar
Francis Dupont committed
270

271
          <tbody>
Francis Dupont's avatar
Francis Dupont committed
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
            <row>
              <entry>String literal</entry>
              <entry>'example'</entry>
              <entry>'example'</entry>
              <entry>A string</entry>
            </row>
            <row>
              <entry>Hexadecimal string literal</entry>
              <entry>0x5a7d</entry>
              <entry>'Z}'</entry>
              <entry>A hexadecimal string</entry>
            </row>
            <row>
              <entry>IP address literal</entry>
              <entry>10.0.0.1</entry>
              <entry>0x0a000001</entry>
              <entry>An IP address</entry>
            </row>
            <row>
              <entry>Integer literal</entry>
              <entry>123</entry>
              <entry>'123'</entry>
294
              <entry>A 32-bit unsigned integer value</entry>
Francis Dupont's avatar
Francis Dupont committed
295
            </row>
296
            <row/>
Francis Dupont's avatar
Francis Dupont committed
297
298
299
300
301
302
303
            <row>
              <entry>Binary content of the option</entry>
              <entry>option[123].hex</entry>
              <entry>'(content of the option)'</entry>
              <entry>The value of the option with given code from the
              packet as hex</entry>
            </row>
304
<!-- Text option not fully defined yet, leave it out
Francis Dupont's avatar
Francis Dupont committed
305
306
307
308
309
310
311
            <row>
              <entry>Option Text</entry>
              <entry>option[123].text</entry>
              <entry>'foobar'</entry>
              <entry>The value of the option with given code from the
              packet as text</entry>
            </row>
312
-->
Francis Dupont's avatar
Francis Dupont committed
313
314
            <row>
              <entry>Option existence</entry>
315
              <entry>option[123].exists</entry>
Francis Dupont's avatar
Francis Dupont committed
316
317
318
319
              <entry>'true'</entry>
              <entry>If the option with given code is present in the
              packet "true" else "false"</entry>
            </row>
Francis Dupont's avatar
Francis Dupont committed
320
321
322
323
324
325
326
            <row>
              <entry>Client class membership</entry>
              <entry>member('foobar')</entry>
              <entry>'true'</entry>
              <entry>If the packet belongs to the given client class
              "true" else "false"</entry>
            </row>
Francis Dupont's avatar
Francis Dupont committed
327
328
329
330
331
332
333
334
335
336
337
            <row>
              <entry>Known client</entry>
              <entry>known</entry>
              <entry>member('KNOWN')</entry>
              <entry>If there is a host reservation for the client
              "true" else "false"</entry>
            </row>
            <row>
              <entry>Unknown client</entry>
              <entry>unknown</entry>
              <entry>not member('KNOWN')</entry>
338
              <entry>If there is a host reservation for the client
Francis Dupont's avatar
Francis Dupont committed
339
340
              "false" else "true"</entry>
            </row>
Francis Dupont's avatar
Francis Dupont committed
341
342
343
344
345
346
347
            <row>
              <entry>DHCPv4 relay agent sub-option</entry>
              <entry>relay4[123].hex</entry>
              <entry>'(content of the RAI sub-option)'</entry>
              <entry>The value of sub-option with given code from the
              DHCPv4 Relay Agent Information option (option 82)</entry>
            </row>
348
349
350
            <row>
              <entry>DHCPv6 Relay Options</entry>
              <entry>relay6[nest].option[code].hex</entry>
351
              <entry>(value of the option)</entry>
352
353
354
355
356
357
              <entry>The value of the option with code "code" from the
              relay encapsulation "nest"</entry>
            </row>
            <row>
              <entry>DHCPv6 Relay Peer Address</entry>
              <entry>relay6[nest].peeraddr</entry>
358
              <entry>2001:DB8::1</entry>
359
360
361
362
363
364
              <entry>The value of the peer address field from the
              relay encapsulation "nest"</entry>
            </row>
            <row>
              <entry>DHCPv6 Relay Link Address</entry>
              <entry>relay6[nest].linkaddr</entry>
365
              <entry>2001:DB8::1</entry>
366
367
368
              <entry>The value of the link address field from the
              relay encapsulation "nest"</entry>
            </row>
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
            <row>
              <entry>Interface name of packet</entry>
              <entry>pkt.iface</entry>
              <entry>eth0</entry>
              <entry>The name of the incoming interface of a DHCP packet.</entry>
            </row>
            <row>
              <entry>Source address of packet</entry>
              <entry>pkt.src</entry>
              <entry>10.1.2.3</entry>
              <entry>The IP source address of a DHCP packet.</entry>
            </row>
            <row>
              <entry>Destination address of packet</entry>
              <entry>pkt.dst</entry>
              <entry>10.1.2.3</entry>
              <entry>The IP destination address of a DHCP packet.</entry>
            </row>
            <row>
              <entry>Length of packet</entry>
              <entry>pkt.len</entry>
390
              <entry>513</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
391
              <entry>The length of a DHCP packet (UDP header field), expressed
392
              as a 32-bit unsigned integer.</entry>
393
            </row>
Francis Dupont's avatar
Francis Dupont committed
394
395
396
397
            <row>
              <entry>Hardware address in DHCPv4 packet</entry>
              <entry>pkt4.mac</entry>
              <entry>0x010203040506</entry>
398
              <entry>The value of the chaddr field of the DHCPv4 packet, hlen (0 to 16) bytes</entry>
Francis Dupont's avatar
Francis Dupont committed
399
400
401
402
            </row>
            <row>
              <entry>Hardware length in DHCPv4 packet</entry>
              <entry>pkt4.hlen</entry>
403
              <entry>6</entry>
Francis Dupont's avatar
Francis Dupont committed
404
              <entry>The value of the hlen field of the DHCPv4 packet padded to 4 bytes</entry>
Francis Dupont's avatar
Francis Dupont committed
405
406
407
408
            </row>
            <row>
              <entry>Hardware type in DHCPv4 packet</entry>
              <entry>pkt4.htype</entry>
409
              <entry>6</entry>
Francis Dupont's avatar
Francis Dupont committed
410
              <entry>The value of the htype field of the DHCPv4 packet padded to 4 bytes</entry>
Francis Dupont's avatar
Francis Dupont committed
411
412
413
414
415
            </row>
            <row>
              <entry>ciaddr field in DHCPv4 packet</entry>
              <entry>pkt4.ciaddr</entry>
              <entry>192.0.2.1</entry>
416
              <entry>The value of the ciaddr field of the DHCPv4 packet (IPv4 address, 4 bytes)</entry>
Francis Dupont's avatar
Francis Dupont committed
417
418
419
420
421
            </row>
            <row>
              <entry>giaddr field in DHCPv4 packet</entry>
              <entry>pkt4.giaddr</entry>
              <entry>192.0.2.1</entry>
422
              <entry>The value of the giaddr field of the DHCPv4 packet (IPv4 address, 4 bytes)</entry>
Francis Dupont's avatar
Francis Dupont committed
423
424
425
426
427
            </row>
            <row>
              <entry>yiaddr field in DHCPv4 packet</entry>
              <entry>pkt4.yiaddr</entry>
              <entry>192.0.2.1</entry>
428
              <entry>The value of the yiaddr field of the DHCPv4 packet (IPv4 address, 4 bytes)</entry>
Francis Dupont's avatar
Francis Dupont committed
429
430
431
432
433
            </row>
            <row>
              <entry>siaddr field in DHCPv4 packet</entry>
              <entry>pkt4.siaddr</entry>
              <entry>192.0.2.1</entry>
434
              <entry>The value of the siaddr field of the DHCPv4 packet (IPv4 address, 4 bytes)</entry>
Francis Dupont's avatar
Francis Dupont committed
435
            </row>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
436
            <row>
437
              <entry>Message type in DHCPv4 packet</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
438
439
440
              <entry>pkt4.msgtype</entry>
              <entry>1</entry>
              <entry>The value of the message type field in the DHCPv4
441
              packet (expressed as a 32-bit unsigned integer).</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
442
443
444
445
446
447
            </row>
            <row>
              <entry>Transaction ID (xid) in DHCPv4 packet</entry>
              <entry>pkt4.transid</entry>
              <entry>12345</entry>
              <entry>The value of the transaction id in the DHCPv4
448
              packet (expressed as a 32-bit unsigned integer).</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
449
            </row>
450
            <row>
451
              <entry>Message type in DHCPv6 packet</entry>
452
              <entry>pkt6.msgtype</entry>
453
              <entry>1</entry>
454
              <entry>The value of the message type field in the DHCPv6
455
              packet (expressed as a 32-bit unsigned integer).</entry>
456
457
458
459
            </row>
            <row>
              <entry>Transaction ID in DHCPv6 packet</entry>
              <entry>pkt6.transid</entry>
460
              <entry>12345</entry>
461
              <entry>The value of the transaction id in the DHCPv6
462
              packet (expressed as a 32-bit unsigned integer).</entry>
463
            </row>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
464
465
466

            <row>
              <entry>Vendor option existence (any vendor)</entry>
467
              <entry>vendor[*].exists</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
              <entry>true</entry>
              <entry>Returns whether a vendor option from any vendor
              is present ('true') or absent ('false').</entry>
            </row>
            <row>
              <entry>Vendor option existence (specific vendor)</entry>
              <entry>vendor[4491].exists</entry>
              <entry>true</entry>
              <entry>Returns whether a vendor option from specified
              vendor (determined by its enterprise-id)
              is present ('true') or absent ('false').</entry>
            </row>
            <row>
              <entry>Enterprise-id from vendor option</entry>
              <entry>vendor.enterprise</entry>
483
              <entry>4491</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
484
485
              <entry>If the vendor option is present, it returns the
              value of the enterprise-id field padded to 4
486
              bytes. Returns "" otherwise.</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
            </row>
            <row>
              <entry>Vendor sub-option existence</entry>
              <entry>vendor[4491].option[1].exists</entry>
              <entry>true</entry>
              <entry>Returns 'true' if there is vendor option with
              specified enterprise-id and given sub-option is present.
              Returns 'false' otherwise.</entry>
            </row>
            <row>
              <entry>Vendor sub-option content</entry>
              <entry>vendor[4491].option[1].hex</entry>
              <entry>docsis3.0</entry>
              <entry>Returns content of the specified sub-option of
              a vendor option with specified enterprise id. Returns
              '' if no such option or sub-option is present.
              </entry>
            </row>

            <row>
              <entry>Vendor class option existence (any vendor)</entry>
508
              <entry>vendor-class[*].exists</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
              <entry>true</entry>
              <entry>Returns whether a vendor class option from any vendor
              is present ('true') or absent ('false').</entry>
            </row>
            <row>
              <entry>Vendor class option existence (specific vendor)</entry>
              <entry>vendor-class[4491].exists</entry>
              <entry>true</entry>
              <entry>Returns whether a vendor class option from specified
              vendor (determined by its enterprise-id)
              is present ('true') or absent ('false').</entry>
            </row>
            <row>
              <entry>Enterprise-id from vendor class option</entry>
              <entry>vendor-class.enterprise</entry>
524
              <entry>4491</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
525
526
              <entry>If the vendor option is present, it returns the
              value of the enterprise-id field padded to 4
527
              bytes. Returns "" otherwise.</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
528
529
530
531
            </row>
            <row>
              <entry>First data chunk from vendor class option</entry>
              <entry>vendor-class[4491].data</entry>
532
              <entry>docsis3.0</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
533
534
              <entry>Returns content of the first data chunk from
              the vendor class option with specified enterprise-id.
535
              Returns "" if missing.</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
536
537
538
539
540
541
542
543
544
545
            </row>
            <row>
              <entry>Specific data chunk from vendor class option</entry>
              <entry>vendor-class[4491].data[3]</entry>
              <entry>docsis3.0</entry>
              <entry>Returns content of the specified data chunk of
              a vendor class option with specified enterprise id. Returns
              '' if no such option or data chunk is present.
              </entry>
            </row>
546
547
548
          </tbody>
          </tgroup>
        </table>
549
550
551
552
553
554
        Notes:
      </para>

      <itemizedlist>

      <listitem><para>
555
556
      Hexadecimal strings are converted into a string as expected. The starting "0X" or
      "0x" is removed, and if the string is an odd number of characters a
557
      "0" is prepended to it.
558
      </para></listitem>
559

560
      <listitem><para>
Francis Dupont's avatar
Francis Dupont committed
561
      IP addresses are converted into strings of length 4 or 16. IPv4, IPv6,
562
      and IPv4-embedded IPv6 (e.g., IPv4-mapped IPv6) addresses are supported.
563
      </para></listitem>
Francis Dupont's avatar
Francis Dupont committed
564

565
      <listitem><para>
566
567
      Integers in an expression are converted to 32-bit unsigned integers and
      are represented as four-byte strings; for example, 123 is represented as
568
      0x0000007b. All expressions that return numeric values use 32-bit
569
      unsigned integers, even if the field in the packet is smaller. In general,
Tomek Mrugalski's avatar
Tomek Mrugalski committed
570
      it is easier to use decimal notation to represent integers, but it is also
Suzanne Goldlust's avatar
Suzanne Goldlust committed
571
572
      possible to use hexadecimal notation. When writing an integer in hexadecimal,
      care should be taken to make sure the value is represented as 32
573
574
575
      bits, e.g. use 0x00000001 instead of 0x1 or 0x01. Also, make
      sure the value is specified in network order, e.g. 1 is
      represented as 0x00000001.
576
      </para></listitem>
577

578
      <listitem><para>
Francis Dupont's avatar
Francis Dupont committed
579
      "option[code].hex" extracts the value of the option with the code "code"
580
      from the incoming packet. If the packet doesn't contain the option, it
581
582
      returns an empty string. The string is presented as a byte string of
      the option payload, without the type code or length fields.
583
      </para></listitem>
584

585
      <listitem><para>
586
      "option[code].exists" checks whether an option with the code "code" is present
Francis Dupont's avatar
Francis Dupont committed
587
      in the incoming packet. It can be used with empty options.
588
      </para></listitem>
Francis Dupont's avatar
Francis Dupont committed
589

Francis Dupont's avatar
Francis Dupont committed
590
      <listitem><para>
591
592
593
594
      "member('foobar')" checks whether the packet belongs to the client
      class "foobar". To avoid dependency loops, the configuration file
      parser verifies whether client classes were already defined or are
      builtin, i.e., beginning by &quot;VENDOR_CLASS_&quot;,
Francis Dupont's avatar
Francis Dupont committed
595
      &quot;AFTER__&quot; (for the to come "after" hook) and
Francis Dupont's avatar
Francis Dupont committed
596
      &quot;EXTERNAL_&quot; or equal to &quot;ALL&quot;, &quot;KNOWN&quot;,
597
      &quot;UNKNOWN&quot;etc.
Francis Dupont's avatar
Francis Dupont committed
598
599
600
601
602
      </para>
      <para>"known" and "unknown" are short hands for "member('KNOWN')" and
      "not member('KNOWN')". Note the evaluation of any expression using
      directly or indirectly the &quot;KNOWN&quot; class is deferred
      after the host reservation lookup (i.e. when the &quot;KNOWN&quot;
603
      or &quot;UNKNOWN&quot; partition is determined).
Francis Dupont's avatar
Francis Dupont committed
604
605
      </para></listitem>

606
607
608
609
610
611
612
613
614
      <listitem><para>
      "relay4[code].hex" attempts to extract the value of the sub-option
      "code" from the option inserted as the DHCPv4 Relay Agent Information
      (82) option. If the packet doesn't contain a RAI option, or the RAI
      option doesn't contain the requested sub-option, the expression returns
      an empty string. The string is presented as a byte string of the
      option payload without the type code or length fields. This
      expression is allowed in DHCPv4 only.
      </para></listitem>
615

616
617
618
619
      <listitem><para>
      "relay4" shares the same representation types as "option", for
      instance "relay4[code].exists" is supported.
      </para></listitem>
620

621
622
623
624
      <listitem><para>
      "relay6[nest]" allows access to the encapsulations used by any DHCPv6
      relays that forwarded the packet.  The "nest" level specifies the relay
      from which to extract the information, with a value of 0 indicating
Francis Dupont's avatar
Francis Dupont committed
625
626
      the relay closest to the DHCPv6 server. Negative values allow to
      specify relays counted from the DHCPv6 client, -1 indicating the
627
628
      relay closest to the client. In general negative "nest" level is
      the same as the number of relays + "nest" level.
Francis Dupont's avatar
Francis Dupont committed
629
630
      If the requested encapsulation doesn't exist an empty string ""
      is returned.  This expression is allowed in DHCPv6 only.
631
      </para></listitem>
632

633
634
635
636
      <listitem><para>
      "relay6[nest].option[code]" shares the same representation types as
      "option", for instance "relay6[nest].option[code].exists" is supported.
      </para></listitem>
637

638
639
640
641
      <listitem><para>
       Expressions starting with "pkt4" can be used only in DHCPv4.
       They allows access to DHCPv4 message fields.
      </para></listitem>
Francis Dupont's avatar
Francis Dupont committed
642

643
644
645
646
647
648
649
      <listitem><para>
      "pkt6" refers to information from the client request.  To access any
      information from an intermediate relay use "relay6".  "pkt6.msgtype"
      and "pkt6.transid" output a 4 byte binary string for the message type
      or transaction id.  For example the message type SOLICIT will be
      "0x00000001" or simply 1 as in "pkt6.msgtype == 1".
      </para></listitem>
650

651
652
      <listitem><para>
      Vendor option means Vendor-Identifying Vendor-specific Information
653
      option in DHCPv4 (code 125, see
654
      <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://tools.ietf.org/html/rfc3925#section-4">Section 4 of RFC 3925</link>) and
655
      Vendor-specific Information Option in DHCPv6 (code 17, defined in
656
657
      <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://tools.ietf.org/html/rfc8415#section-21.17">Section 21.17 of
      RFC 8415</link>). Vendor class option means Vendor-Identifying Vendor
658
      Class Option in DHCPv4 (code 124, see
659
      <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://tools.ietf.org/html/rfc3925#section-3">Section 3 of RFC 3925</link>) in DHCPv4 and
660
      Class Option in DHCPv6 (code 16, see
661
      <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://tools.ietf.org/html/rfc8415#section-21.16">Section 21.16 of RFC 8415</link>).
662
663
664
665
666
667
      Vendor options may
      have sub-options that are referenced by their codes. Vendor class
      options do not have sub-options, but rather data chunks, which are
      referenced by index value. Index 0 means the first data chunk, Index 1
      is for the second data chunk (if present), etc.
      </para></listitem>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
668

669
670
      <listitem><para>
      In the vendor and vendor-class constructs Asterisk (*) or 0 can be
Tomek Mrugalski's avatar
Tomek Mrugalski committed
671
      used to specify a wildcard enterprise-id value, i.e. it will match any
672
673
      enterprise-id value.
      </para></listitem>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
674

675
676
      <listitem><para>Vendor Class Identifier (option 60 in DHCPv4) can be
      accessed using option[60] expression.</para></listitem>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
677

678
      <listitem><para>
679
680
      <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://tools.ietf.org/html/rfc3925">RFC 3925</link> and
      <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://tools.ietf.org/html/rfc8415">RFC 8415</link>
681
      allow for multiple instances of vendor options
Tomek Mrugalski's avatar
Tomek Mrugalski committed
682
683
684
685
      to appear in a single message. The client classification code currently
      examines the first instance if more than one appear. For vendor.enterprise
      and vendor-class.enterprise expressions, the value from the first instance
      is returned. Please submit a feature request on Kea website if you need
686
687
688
689
      support for multiple instances.
      </para></listitem>

      </itemizedlist>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
690

691
      <para>
692
        <table frame="all" xml:id="classification-expressions-list">
693
          <title>List of Classification Expressions</title>
694
695
696
697
          <tgroup cols="3">
          <colspec colname="name"/>
          <colspec colname="example"/>
          <colspec colname="description"/>
698
699
700
701
702
703
704
705
706
          <thead>
            <row>
              <entry>Name</entry>
              <entry>Example</entry>
              <entry>Description</entry>
            </row>
          </thead>
          <tbody>
<row><entry>Equal</entry> <entry>'foo' == 'bar'</entry><entry>Compare the two values and return "true" or "false"</entry></row>
Francis Dupont's avatar
Francis Dupont committed
707
708
709
<row><entry>Not</entry> <entry>not ('foo' == 'bar')</entry><entry>Logical negation</entry></row>
<row><entry>And</entry> <entry>('foo' == 'bar') and ('bar' == 'foo')</entry><entry>Logical and</entry></row>
<row><entry>Or</entry> <entry>('foo' == 'bar') or ('bar' == 'foo')</entry><entry>Logical or</entry></row>
710
<row><entry>Substring</entry><entry>substring('foobar',0,3)</entry><entry>Return the requested substring</entry></row>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
711
712
<row><entry>Concat</entry><entry>concat('foo','bar')</entry><entry>Return the
concatenation of the strings</entry></row>
Francis Dupont's avatar
Francis Dupont committed
713
<row><entry>Ifelse</entry><entry>ifelse('foo' == 'bar','us','them')</entry><entry>Return the branch value according to the condition</entry></row>
714
<row><entry>Hexstring</entry><entry>hexstring('foo', '-')</entry><entry>Converts the value to a hexadecimal string, e.g. 0a:1b:2c:3e</entry></row>
715
716
717
          </tbody>
          </tgroup>
        </table>
718
719
      </para>

Francis Dupont's avatar
Francis Dupont committed
720
721
722
      <section>
        <title>Logical operators</title>
        The Not, And and Or logical operators are the common operators. Not
723
        has the highest precedence and Or the lowest. And and Or are (left)
Francis Dupont's avatar
Francis Dupont committed
724
725
        associative, parentheses around a logical expression can be used
        to enforce a specific grouping, for instance in "A and (B or C)"
726
        (without parentheses "A and B or C" means "(A and B) or C").
Francis Dupont's avatar
Francis Dupont committed
727
728
      </section>

729
730
731
732
733
734
735
736
737
738
739
      <section>
        <title>Substring</title>
        The substring operator "substring(value, start, length)" accepts both positive and
        negative values for the starting position and the length.  For "start", a value of
        0 is the first byte in the string while -1 is the last byte.  If the starting
        point is outside of the original string an empty string is returned.  "length"
        is the number of bytes to extract.  A negative number means to count towards
        the beginning of the string but doesn't include the byte pointed to by "start".
        The special value "all" means to return all bytes from start to the end of the
        string.  If length is longer than the remaining portion of the string then
        the entire remaining portion is returned.  Some examples may be helpful:
740

741
          <screen>
742
743
744
745
746
        substring('foobar', 0, 6) == 'foobar'
        substring('foobar', 3, 3) == 'bar'
        substring('foobar', 3, all) == 'bar'
        substring('foobar', 1, 4) == 'ooba'
        substring('foobar', -5, 4) == 'ooba'
747
748
        substring('foobar', -1, -3) == 'oba'
        substring('foobar', 4, -2) == 'ob'
749
        substring('foobar', 10, 2) == ''
750
751
          </screen>
      </section>
752
753
754
755
756
757
758
759
      <section>
        <title>Concat</title>
        The concat function "concat(string1, string2)" returns the
        concatenation of its two arguments. For instance:
          <screen>
        concat('foo', 'bar') == 'foobar'
          </screen>
       </section>
Francis Dupont's avatar
Francis Dupont committed
760
761
762
763
764
765
766
767
768
       <section>
         <title>Ifelse</title>
         The ifelse function "ifelse(cond, iftrue, ifelse)" returns the
         "iftrue" or "ifelse" branch value following the boolean
         condition "cond". For instance:
           <screen>
         ifelse(option[230].exists, option[230].hex, 'none')
           </screen>
        </section>
769
770
771
772
        <section>
          <title>Hexstring</title>
          The hexstring function "hexstring(binary, separator)" returns
          the binary value as its hexadecimal string representation:
773
774
          pairs of hexadecimal digits separated by the separator, e.g
          ':', '-', '' (empty separator).
775
776
777
778
            <screen>
          hexstring(pkt4.mac, ':')
            </screen>
        </section>
779
    </section>
780

781
782
783
784
785
  <note>
  <para>
    The expression for each class is executed on each packet received.
    If the expressions are overly complex, the time taken to execute
    them may impact the performance of the server. If you need
786
    complex or time consuming expressions you should write a <link linkend="hooks-libraries">hook</link> to perform the necessary work.
787
788
  </para> </note>

789
  <section xml:id="classification-configuring">
790
791
    <title>Configuring Classes</title>
      <para>
792
      A class contains five items: a name, a test expression, option data,
793
      option definition and only-if-required flag.
794
      The name must exist and must be unique amongst all classes. The test
795
      expression, option data and definition, and only-if-required flag are
796
      optional.
797
      </para>
798

799
800
801
802
803
804
805
806
807
808
809
810
      <para>
      The test expression is a string containing the logical expression used to
      determine membership in the class.  The entire expression is in double
      quotes.
      </para>

      <para>
      The option data is a list which defines any options that should be assigned
      to members of this class.
      </para>

      <para>
811
812
813
814
815
816
817
818
819
      The option definition is for DHCPv4 option 43 (<xref
      linkend="dhcp4-vendor-opts"/> and DHCPv4 private options
      (<xref linkend="dhcp4-private-opts"/>).
      </para>

      <para>
      Usually the test expression is evaluated before subnet selection
      but in some cases it is useful to evaluate it later when the
      subnet, shared-network or pools are known but output option
820
821
      processing not yet done. The only-if-required flag, false by default,
      allows to perform the evaluation of the test expression only
822
823
      when it was required, i.e. in a require-client-classes list of the
      selected subnet, shared-network or pool.
824
825
826
      </para>

      <para>
827
      The require-client-classes list which is valid for shared-network,
828
829
830
831
      subnet and pool scope specifies the classes which are evaluated
      in the second pass before output option processing.
      The list is built in the reversed precedence order of option
      data, i.e. an option data in a subnet takes precedence on one
832
      in a shared-network but required class in a subnet is added
833
      after one in a shared-network.
834
835
      The mechanism is related to the only-if-required flag but it is
      not mandatory that the flag was set to true.
836
837
      </para>

838
      <para>
839
      In the following example the class named &quot;Client_foo&quot; is defined.
840
      It is comprised of all clients whose client ids (option 61) start with the
841
      string "foo". Members of this class will be given 192.0.2.1 and
842
843
      192.0.2.2 as their domain name servers.

844
845
        <screen>
"Dhcp4": {
846
    "client-classes": [<userinput>
847
848
        {
            "name": "Client_foo",
849
            "test": "substring(option[61].hex,0,3) == 'foo'",
850
851
            "option-data": [
                {
852
                    "name": "domain-name-servers",
853
854
855
856
857
858
                    "code": 6,
                    "space": "dhcp4",
                    "csv-format": true,
                    "data": "192.0.2.1, 192.0.2.2"
                }
            ]
859
860
861
        },
        ...
    ],</userinput>
862
863
864
865
866
    ...
}</screen>
      </para>

      <para>
867
      This example shows a client class being defined for use by the DHCPv6 server.
868
      In it the class named "Client_enterprise" is defined.  It is comprised
869
870
871
872
873
874
875
876
      of all clients who's client identifiers start with the given hex string (which
      would indicate a DUID based on an enterprise id of 0xAABBCCDD). Members of this
      class will be given an 2001:db8:0::1 and 2001:db8:2::1 as their domain name servers.
        <screen>
"Dhcp6": {
    "client-classes": [<userinput>
        {
            "name": "Client_enterprise",
877
            "test": "substring(option[1].hex,0,6) == 0x0002AABBCCDD'",
878
879
880
881
882
883
884
885
886
887
888
889
890
891
            "option-data": [
                {
                    "name": "dns-servers",
                    "code": 23,
                    "space": "dhcp6",
                    "csv-format": true,
                    "data": "2001:db8:0::1, 2001:db8:2::1"
                }
            ]
        },
        ...
    ],</userinput>
    ...
}</screen>
892
893
894
      </para>
  </section>

Francis Dupont's avatar
Francis Dupont committed
895
896
897
898
899
900
901
902
  <section id="classification-using-host-reservations">
    <title>Using Static Host Reservations In Classification</title>
    <para>Classes can be statically assigned to the clients using techniques described
    in <xref linkend="reservation4-client-classes"/> and
    <xref linkend="reservation6-client-classes"/>.
    </para>
  </section>

903
  <section xml:id="classification-subnets">
904
905
906
    <title>Configuring Subnets With Class Information</title>
      <para>
        In certain cases it beneficial to restrict access to certain subnets
907
        only to clients that belong to a given class, using the "client-class"
908
909
910
911
        keyword when defining the subnet.
      </para>

      <para>
912
913
914
915
        Let's assume that the server is connected to a network segment that uses
        the 192.0.2.0/24 prefix. The Administrator of that network has decided
        that addresses from range 192.0.2.10 to 192.0.2.20 are going to be
        managed by the DHCP4 server. Only clients belonging to client class
916
        Client_foo  are allowed to use this subnet. Such a
917
918
919
        configuration can be achieved in the following way:
        <screen>
"Dhcp4": {
920
    "client-classes": [
921
922
        {
            "name": "Client_foo",
923
            "test": "substring(option[61].hex,0,3) == 'foo'",
924
925
            "option-data": [
                {
926
                    "name": "domain-name-servers",
927
928
929
930
931
932
                    "code": 6,
                    "space": "dhcp4",
                    "csv-format": true,
                    "data": "192.0.2.1, 192.0.2.2"
                }
            ]
933
934
935
936
937
938
939
940
        },
        ...
    ],<userinput>
    "subnet4": [
        {
            "subnet": "192.0.2.0/24",
            "pools": [ { "pool": "192.0.2.10 - 192.0.2.20" } ],
            "client-class": "Client_foo"
941
942
943
944
945
946
947
948
        },
        ...
    ],</userinput>,
    ...
}</screen>
      </para>

      <para>
Francis Dupont's avatar
Francis Dupont committed
949
        The following example shows restricting access to a DHCPv6 subnet.  This
950
951
952
953
954
955
956
957
        configuration will restrict use of the addresses 2001:db8:1::1 to
        2001:db8:1::FFFF to members of the "Client_enterprise" class.

        <screen>
"Dhcp6": {
    "client-classes": [
        {
            "name": "Client_enterprise",
958
            "test": "substring(option[1].hex,0,6) == 0x0002AABBCCDD'",
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
            "option-data": [
                {
                    "name": "dns-servers",
                    "code": 23,
                    "space": "dhcp6",
                    "csv-format": true,
                    "data": "2001:db8:0::1, 2001:db8:2::1"
                }
            ]
        },
        ...
    ], <userinput>
    "subnet6": [
        {
            "subnet": "2001:db8:1::/64",
            "pools": [ { "pool": "2001:db8:1::-2001:db8:1::ffff" } ],
            "client-class": "Client_enterprise"
976
        }
977
    ],</userinput>
978
979
980
981
982
    ...
}</screen>
      </para>
  </section>

983
984
985
 <section id="classification-pools">
   <title>Configuring Pools With Class Information</title>
     <para>
986
987
988
       Similar to subnets in certain cases access to certain address or
       prefix pools must be restricted to only clients that belong to a
       given class, using the "client-class" when defining the pool.
989
990
991
     </para>

     <para>
992
       Let's assume that the server is connected to a network segment that uses
993
       the 192.0.2.0/24 prefix. The Administrator of that network has decided
994
995
996
997
       that addresses from range 192.0.2.10 to 192.0.2.20 are going to be
       managed by the DHCP4 server. Only clients belonging to client class
       Client_foo are allowed to use this pool. Such a
       configuration can be achieved in the following way:
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
       <screen>
"Dhcp4": {
    "client-classes": [
        {
            "name": "Client_foo",
            "test": "substring(option[61].hex,0,3) == 'foo'",
            "option-data": [
                {
                    "name": "domain-name-servers",
                    "code": 6,
                    "space": "dhcp4",
                    "csv-format": true,
                    "data": "192.0.2.1, 192.0.2.2"
                }
            ]
        },
        ...
1015
    ],<userinput>
1016
1017
1018
1019
1020
1021
    "subnet4": [
        {
            "subnet": "192.0.2.0/24",
            "pools": [
                {
                    "pool": "192.0.2.10 - 192.0.2.20",
1022
                    "client-class": "Client_foo"
1023
                }
1024
            ]
1025
1026
        },
        ...
1027
    ],</userinput>,
1028

1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
}</screen>
      </para>

     <para>
       The following example shows restricting access to an address pool.
       This configuration will restrict use of the addresses 2001:db8:1::1
       to 2001:db8:1::FFFF to members of the "Client_enterprise" class.
       <screen>
"Dhcp6": {
    "client-classes": [
        {
            "name": "Client_enterprise_",
            "test": "substring(option[1].hex,0,6) == 0x0002AABBCCDD'",
            "option-data": [
                {
                    "name": "dns-servers",
                    "code": 23,
                    "space": "dhcp6",
                    "csv-format": true,
                    "data": "2001:db8:0::1, 2001:db8:2::1"
                }
1050
1051
1052
            ]
        },
        ...
1053
1054
1055
1056
1057
1058
1059
1060
    ],
    "subnet6": [
        {
            "subnet": "2001:db8:1::/64",
            <userinput>
            "pools": [
                {
                    "pool": "2001:db8:1::-2001:db8:1::ffff",
1061
                    "client-class": "Client_foo"
1062
1063
1064
1065
1066
                }
            ]</userinput>
        },
        ...
    ],
1067
1068
1069
1070
1071
    ...
}</screen>
      </para>
  </section>

1072
1073
1074
1075
  <section>
    <title>Using Classes</title>
      <para>
      Currently classes can be used for two functions.  They can supply options
1076
1077
      to the members of the class and they can be used to choose a subnet from which an
      address will be assigned to the class member.
1078
1079
1080
      </para>

      <para>
1081
      When supplying options, options defined as part of the class definition
1082
      are considered "class globals".  They will override any global options that
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
      may be defined and in turn will be overridden by any options defined for an
      individual subnet.
      </para>
  </section>

  <section>
    <title>Classes and Hooks</title>
      <para>
      You may use a hook to classify your packets. This may be useful if the
      expression would either be complex or time consuming and be easier or
      better to write as code.  Once the hook has added the proper class name
      to the packet the rest of the classification system will work as normal
1095
      in choosing a subnet and selecting options.  For a description of
1096
      hooks see <xref linkend="hooks-libraries"/>, for a description on
1097
      configuring classes see <xref linkend="classification-configuring"/>
1098
      and <xref linkend="classification-subnets"/>.
1099
1100
1101
      </para>
  </section>

1102
1103
1104
1105
1106
1107
1108
1109
1110
  <section>
   <title>Debugging Expressions</title>
     <para>
     While you are constructing your classification expressions you may
     find it useful to enable logging see <xref linkend="logging"/> for
     a more complete description of the logging facility.
     </para>

     <para>
Francis Dupont's avatar
Francis Dupont committed
1111
     To enable the debug statements in the classification system you will
1112
1113
1114
1115
     need to set the severity to "DEBUG" and the debug level to at least 55.
     The specific loggers are "kea-dhcp4.eval" and "kea-dhcp6.eval".
     </para>

1116
     <para>
Suzanne Goldlust's avatar
Suzanne Goldlust committed
1117
1118
1119
     In order to understand the logging statements, one must understand a
     bit about how expressions are evaluated; for a more complete description
     refer to the design document at <uri xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://gitlab.isc.org/isc-projects/kea/wikis/design%20documents">https://gitlab.isc.org/isc-projects/kea/wikis/design%20documents</uri>.
Thomas Markwalder's avatar
Thomas Markwalder committed
1120
     In brief there are two structures used during the evaluation of an expression:
1121
1122
1123
1124
1125
1126
1127
     a list of tokens which represent the expressions and a value stack which
     represents the values being manipulated.
     </para>

     <para>
     The list of tokens is created when the configuration file is processed with
     most expressions and values being converted to a token.  The list is organized
1128
     in reverse Polish notation.  During execution, the list will be traversed
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
     in order.  As each token is executed it will be able to pop values
     from the top of the stack and eventually push its result on the top of the
     stack.  Imagine the following expression:
       <screen>
       "test": "substring(option[61].hex,0,3) == 'foo'",
       </screen>
     This will result in the following tokens:
       <screen>
       option, number (0), number (3), substring, text ('foo'), equals
       </screen>
     In this example the first three tokens will simply push values onto the
     stack.  The substring token will then remove those three values and
     compute a result that it places on the stack.  The text option also
     places a value on the stack and finally the equals token removes the
     two tokens on the stack and places its result on the stack.
     </para>

1146
     <para>
1147
1148
     When debug logging is enabled, each time a token is evaluated it will
     emit a log message indicating the values of any objects that were popped
1149
1150
1151
1152
1153
1154
     off of the value stack and any objects that were pushed onto the value
     stack.
     </para>

     <para>
     The values will be displayed as either text if the command is known
1155
     to use text values or hexadecimal if the command either uses binary values or
1156
     can manipulate either text or binary values.  For expressions that
1157
     pop multiple values off the stack, the values will be displayed in
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
     the order they were popped.  For most expressions this won't matter
     but for the concat expression the values are displayed in reverse
     order from how they are written in the expression.
     </para>

     <para>
     Let us assume that the following test has been entered into the configuration.
     This example skips most of the configuration to concentrate on the test.
       <screen>
       "test": "substring(option[61].hex,0,3) == 'foo'",
       </screen>
     The logging might then resemble this:
       <screen>
       2016-05-19 13:35:04.163 DEBUG [kea.eval/44478] EVAL_DEBUG_OPTION Pushing option 61 with value 0x666F6F626172
1172
1173
       2016-05-19 13:35:04.164 DEBUG [kea.eval/44478] EVAL_DEBUG_STRING Pushing text string '0'
       2016-05-19 13:35:04.165 DEBUG [kea.eval/44478] EVAL_DEBUG_STRING Pushing text string '3'
1174
       2016-05-19 13:35:04.166 DEBUG [kea.eval/44478] EVAL_DEBUG_SUBSTRING Popping length 3, start 0, string 0x666F6F626172 pushing result 0x666F6F
1175
1176
       2016-05-19 13:35:04.167 DEBUG [kea.eval/44478] EVAL_DEBUG_STRING Pushing text string 'foo'
       2016-05-19 13:35:04.168 DEBUG [kea.eval/44478] EVAL_DEBUG_EQUAL Popping 0x666F6F and 0x666F6F pushing result 'true'
1177
1178
1179
1180
1181
       </screen>
     </para>

     <note><para>
     The debug logging may be quite verbose if you have a number of expressions
1182
     to evaluate.  It is intended as an aid in helping you create and debug
1183
     your expressions.  You should plan to disable debug logging when you have your
1184
1185
1186
1187
1188
1189
     expressions working correctly.  You also may wish to include only one set of
     expressions at a time in the configuration file while debugging them in order
     to limit the log statements.  For example when adding a new set of expressions
     you might find it more convenient to create a configuration file that only
     includes the new expressions until you have them working correctly and then
     add the new set to the main configuration file.
1190
1191
1192
     </para></note>
  </section>

1193
</chapter>