classify.xml 49.8 KB
Newer Older
1 2 3 4 5 6 7
<!--
 - Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC")
 -
 - 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
 - file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
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 21
      The clients represent different pieces of topology, e.g. a cable
      modem is different to the clients behind that modem.
22 23
      </para></listitem>
      <listitem><para>
24
      The clients have different behavior, e.g. a smart phone behaves
25
      differently to a laptop.
26 27
      </para></listitem>
      <listitem><para>
28 29
      The clients require different values for some options, e.g. a docsis3.0
      cable modem requires different settings to docsis2.0 cable modem.
30 31 32 33 34
      </para></listitem>
      </itemizedlist>
      </para>

      <para>
35 36
      Conversely, different clients can be grouped into a client class to get a
      common option.
37 38 39
      </para>

      <para>
Francis Dupont's avatar
Francis Dupont committed
40 41 42 43
      An incoming packet can be associated with a client class in
      serveral ways:
      <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. In the current release of the software however,
      there are only five mechanisms that take advantage of
Francis Dupont's avatar
Francis Dupont committed
63 64 65 66 67 68 69 70 71
      client classification: subnet selection, pool selection,
      definition of DHCPv4 private (codes 224-254) and code 43
      options, assignment of different options and, for DHCPv4 cable
      modems, the setting of specific options for use with the TFTP
      server address and the boot file field.
      </para>

      <para>
      The process of doing classification 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 83 84 85
      request" or depending on the KNOWN/UNKNOWN builtin classes)
      evaluation are processed in the order they are defined in the
      configuration: the boolean expression is evaluated and when it
      returns true ("match") the incoming packet is associated to the
      class.
86 87
      </para></listitem>
      <listitem><para>
88 89 90 91 92
      If a private or code 43 DHCPv4 option is received, decoding it
      following its client class or global (or for option 43 last
      resort) definition.
      </para></listitem>
      <listitem><para>
Francis Dupont's avatar
Francis Dupont committed
93
      Choose a subnet, possibly based on the class information when
94
      some subnets are guarded. More precisely: when choosing a subnet,
Francis Dupont's avatar
Francis Dupont committed
95 96 97 98 99
      the server will iterate over all of the subnets that are
      feasible given the information found in the packet (client
      address, relay address etc). It will use the first subnet it
      finds that either doesn't have a class associated with it or
      that has a class which matches one of the packet's classes.
100 101
      </para></listitem>
      <listitem><para>
102 103
      Host reservations are looked for. If an identifier from the
      incoming packet matches a host reservation in the subnet or
104 105 106
      shared network, the packet is associated with the KNOWN class
      and all classes of the host reservation. If a reservation is not
      found, the packet is assigned to UNKNOWN class.
107 108
      </para></listitem>
      <listitem><para>
Francis Dupont's avatar
Francis Dupont committed
109
      Classes with matching expressions using directly or indirectly
110 111 112 113
      the KNOWN/UNKNOWN builtin classes and not marked for later ("on
      request") evaluation are processed in the order they are defined
      in the configuration: the boolean expression is evaluated and
      when it returns true ("match") the incoming packet is associated
114 115 116 117
      to the class. The determination whether there is a reservation
      for a given client is made after a subnet is selected. As such, it
      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 122
      If needed, addresses and prefixes from pools are assigned,
      possibly based on the class information when some pools are
      reserved to class members.
123 124
      </para></listitem>
      <listitem><para>
125 126 127
      Evaluate classes marked as "required" in the order in which they
      are listed as required: first shared network, then the subnet
      and to finally pools assigned resources belong too.
Francis Dupont's avatar
Francis Dupont committed
128 129 130 131
      </para></listitem>
      <listitem><para>
      Assign options, again possibly based on the class information
      in order classes were associated with the incoming packet.
132 133
      For DHCPv4 private and code 43 options this includes class local
      option definitions.
134 135
      </para></listitem>
      </orderedlist>
136 137
      </para>

Francis Dupont's avatar
Francis Dupont committed
138
      <note>
139
      <para>
140 141
      Beginning with Kea 1.4.0 release,  client classes follow the order
      in which they are specified in the configuration
142 143
      (vs. alphabetical order in previous releases). Required classes
      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
Francis Dupont's avatar
Francis Dupont committed
149
      server will examine the union of options from all of the
150
      assigned classes. In case when two or more classes include the
Francis Dupont's avatar
Francis Dupont committed
151 152 153 154
      same option, the value from the first class examined will be
      used, and classes are examined in the order they were associated
      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 159 160 161 162 163 164 165 166
      As an example, imagine that an incoming packet matches two
      classes.  Class "foo" defines values for an NTP server (option
      42 in DHCPv4) and an SMTP server (option 69 in DHCPv4) while
      class "bar" defines values for an NTP server and a POP3 server
      (option 70 in DHCPv4).  The server will examine the three
      options NTP, SMTP and POP3 and return any of them that the
      client requested.  As the NTP server was defined twice the
      server will choose only one of the values for the reply: the
      class from which the value is obtained is unspecified.
167 168 169 170 171 172 173 174 175 176
      </para>

      <note>
      <para>
        Care should be taken with client classification as it is easy for
        clients that do not meet class criteria to be denied any service altogether.
      </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>
Francis Dupont's avatar
Francis Dupont committed
180 181 182 183 184 185 186 187 188 189 190
      Some classes are builtin so do not need to be defined. The main
      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
      interpreted as a class. For example, modern cable modems will
      send this option with value &quot;docsis3.0&quot; and so the
      packet will belong to class &quot;VENDOR_CLASS_docsis3.0&quot;.
      </para>

191 192 193 194 195 196
      <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
      which should process the DHCP packet. This server will use appropriate
      pool or subnet to allocate IP addresses (and/or prefixes) from, based on
197
      the assigned client classes. The details can be found in
198 199
      <xref linkend="high-availability-library"/>.</para>

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

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

214 215
  </section>

216
  <section xml:id="classification-using-expressions">
217 218
    <title>Using Expressions In Classification</title>
      <para>
Francis Dupont's avatar
Francis Dupont committed
219 220 221 222 223 224 225 226
      The expression portion of classification contains operators and
      values.  All values are currently strings and operators take a
      string or strings and return another string. When all the
      operations have completed the result should be a value of
      &quot;true&quot; or &quot;false&quot;.  The packet belongs to
      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 233 234 235 236 237
      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
      and logged during parsing.  Examples of these errors include an
      incorrect number or types of arguments to an operator.  The
      evaluation code will also check for this class of error and
      generally throw an exception, though this should not occur in a
      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
      Expressions are a work in progress and the supported operators and
248
      values are limited. The expectation is that additional operators and values
249
      will be added over time, however the basic mechanisms will
250 251 252
      remain the same.
      </para>

Francis Dupont's avatar
Francis Dupont committed
253
      <para>
254 255 256 257 258 259
      Dependencies between classes are checked too: for instance
      forward dependencies are rejected when the configuration is
      parsed: an expression can only depend on already defined classes
      (including builtin classes) and which are evaluated in a
      previous or the same evaluation phase. This does not apply to
      the KNOWN or UNKNOWN classes.
Francis Dupont's avatar
Francis Dupont committed
260 261
      </para>

262
      <para>
263
        <table frame="all" xml:id="classification-values-list">
264
          <title>List of Classification Values</title>
265 266 267 268
          <tgroup cols="3">
          <colspec colname="name"/>
          <colspec colname="example"/>
          <colspec colname="description"/>
269 270 271
          <thead>
            <row>
              <entry>Name</entry>
Francis Dupont's avatar
Francis Dupont committed
272 273
              <entry>Example expression</entry>
              <entry>Example value</entry>
274 275 276
              <entry>Description</entry>
            </row>
          </thead>
Francis Dupont's avatar
Francis Dupont committed
277

278
          <tbody>
Francis Dupont's avatar
Francis Dupont committed
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
            <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>
301
              <entry>A 32 bit unsigned integer value</entry>
Francis Dupont's avatar
Francis Dupont committed
302
            </row>
303
            <row/>
Francis Dupont's avatar
Francis Dupont committed
304 305 306 307 308 309 310
            <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>
311
<!-- Text option not fully defined yet, leave it out
Francis Dupont's avatar
Francis Dupont committed
312 313 314 315 316 317 318
            <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>
319
-->
Francis Dupont's avatar
Francis Dupont committed
320 321
            <row>
              <entry>Option existence</entry>
322
              <entry>option[123].exists</entry>
Francis Dupont's avatar
Francis Dupont committed
323 324 325 326
              <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
327 328 329 330 331 332 333
            <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
334 335 336 337 338 339 340 341 342 343 344
            <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>
345
              <entry>If there is a host reservation for the client
Francis Dupont's avatar
Francis Dupont committed
346 347
              "false" else "true"</entry>
            </row>
Francis Dupont's avatar
Francis Dupont committed
348 349 350 351 352 353 354
            <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>
355 356 357
            <row>
              <entry>DHCPv6 Relay Options</entry>
              <entry>relay6[nest].option[code].hex</entry>
358
              <entry>(value of the option)</entry>
359 360 361 362 363 364
              <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>
365
              <entry>2001:DB8::1</entry>
366 367 368 369 370 371
              <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>
372
              <entry>2001:DB8::1</entry>
373 374 375
              <entry>The value of the link address field from the
              relay encapsulation "nest"</entry>
            </row>
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
            <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>
397
              <entry>513</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
398
              <entry>The length of a DHCP packet (UDP header field), expressed
399
              as a 32 bit unsigned integer.</entry>
400
            </row>
Francis Dupont's avatar
Francis Dupont committed
401 402 403 404
            <row>
              <entry>Hardware address in DHCPv4 packet</entry>
              <entry>pkt4.mac</entry>
              <entry>0x010203040506</entry>
405
              <entry>The value of the chaddr field of the DHCPv4 packet, hlen (0 to 16) bytes</entry>
Francis Dupont's avatar
Francis Dupont committed
406 407 408 409
            </row>
            <row>
              <entry>Hardware length in DHCPv4 packet</entry>
              <entry>pkt4.hlen</entry>
410
              <entry>6</entry>
Francis Dupont's avatar
Francis Dupont committed
411
              <entry>The value of the hlen field of the DHCPv4 packet padded to 4 bytes</entry>
Francis Dupont's avatar
Francis Dupont committed
412 413 414 415
            </row>
            <row>
              <entry>Hardware type in DHCPv4 packet</entry>
              <entry>pkt4.htype</entry>
416
              <entry>6</entry>
Francis Dupont's avatar
Francis Dupont committed
417
              <entry>The value of the htype field of the DHCPv4 packet padded to 4 bytes</entry>
Francis Dupont's avatar
Francis Dupont committed
418 419 420 421 422
            </row>
            <row>
              <entry>ciaddr field in DHCPv4 packet</entry>
              <entry>pkt4.ciaddr</entry>
              <entry>192.0.2.1</entry>
423
              <entry>The value of the ciaddr field of the DHCPv4 packet (IPv4 address, 4 bytes)</entry>
Francis Dupont's avatar
Francis Dupont committed
424 425 426 427 428
            </row>
            <row>
              <entry>giaddr field in DHCPv4 packet</entry>
              <entry>pkt4.giaddr</entry>
              <entry>192.0.2.1</entry>
429
              <entry>The value of the giaddr field of the DHCPv4 packet (IPv4 address, 4 bytes)</entry>
Francis Dupont's avatar
Francis Dupont committed
430 431 432 433 434
            </row>
            <row>
              <entry>yiaddr field in DHCPv4 packet</entry>
              <entry>pkt4.yiaddr</entry>
              <entry>192.0.2.1</entry>
435
              <entry>The value of the yiaddr field of the DHCPv4 packet (IPv4 address, 4 bytes)</entry>
Francis Dupont's avatar
Francis Dupont committed
436 437 438 439 440
            </row>
            <row>
              <entry>siaddr field in DHCPv4 packet</entry>
              <entry>pkt4.siaddr</entry>
              <entry>192.0.2.1</entry>
441
              <entry>The value of the siaddr field of the DHCPv4 packet (IPv4 address, 4 bytes)</entry>
Francis Dupont's avatar
Francis Dupont committed
442
            </row>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
443 444 445 446 447
            <row>
              <entry>Message Type in DHCPv4 packet</entry>
              <entry>pkt4.msgtype</entry>
              <entry>1</entry>
              <entry>The value of the message type field in the DHCPv4
448
              packet (expressed as a 32 bit unsigned integer).</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
449 450 451 452 453 454
            </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
455
              packet (expressed as a 32 bit unsigned integer).</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
456
            </row>
457 458 459
            <row>
              <entry>Message Type in DHCPv6 packet</entry>
              <entry>pkt6.msgtype</entry>
460
              <entry>1</entry>
461
              <entry>The value of the message type field in the DHCPv6
462
              packet (expressed as a 32 bit unsigned integer).</entry>
463 464 465 466
            </row>
            <row>
              <entry>Transaction ID in DHCPv6 packet</entry>
              <entry>pkt6.transid</entry>
467
              <entry>12345</entry>
468
              <entry>The value of the transaction id in the DHCPv6
469
              packet (expressed as a 32 bit unsigned integer).</entry>
470
            </row>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
471 472 473

            <row>
              <entry>Vendor option existence (any vendor)</entry>
474
              <entry>vendor[*].exists</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
              <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>
490
              <entry>4491</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
491 492
              <entry>If the vendor option is present, it returns the
              value of the enterprise-id field padded to 4
493
              bytes. Returns "" otherwise.</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
            </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>
515
              <entry>vendor-class[*].exists</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
              <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>
531
              <entry>4491</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
532 533
              <entry>If the vendor option is present, it returns the
              value of the enterprise-id field padded to 4
534
              bytes. Returns "" otherwise.</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
535 536 537 538
            </row>
            <row>
              <entry>First data chunk from vendor class option</entry>
              <entry>vendor-class[4491].data</entry>
539
              <entry>docsis3.0</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
540 541
              <entry>Returns content of the first data chunk from
              the vendor class option with specified enterprise-id.
542
              Returns "" if missing.</entry>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
543 544 545 546 547 548 549 550 551 552
            </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>
553 554 555
          </tbody>
          </tgroup>
        </table>
556 557 558 559 560 561
        Notes:
      </para>

      <itemizedlist>

      <listitem><para>
562 563 564
      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
      "0" is prepended to it.
565
      </para></listitem>
566

567
      <listitem><para>
Francis Dupont's avatar
Francis Dupont committed
568
      IP addresses are converted into strings of length 4 or 16. IPv4, IPv6,
569
      and IPv4 embedded IPv6 (e.g., IPv4 mapped IPv6) addresses are supported.
570
      </para></listitem>
Francis Dupont's avatar
Francis Dupont committed
571

572
      <listitem><para>
573
      Integers in an expression are converted to 32 bit unsigned integers and
574 575
      are represented as four-byte strings. For example 123 is represented as
      0x0000007b. All expressions that return numeric values use 32-bit
Tomek Mrugalski's avatar
Tomek Mrugalski committed
576 577 578 579
      unsigned integers, even if the field in the packet is smaller.  In general
      it is easier to use decimal notation to represent integers, but it is also
      possible to use hex notation. When using hex notation to represent an
      integer care should be taken to make sure the value is represented as 32
580 581 582
      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.
583
      </para></listitem>
584

585
      <listitem><para>
Francis Dupont's avatar
Francis Dupont committed
586
      "option[code].hex" extracts the value of the option with the code "code"
587
      from the incoming packet. If the packet doesn't contain the option, it
588 589
      returns the empty string. The string is presented as a byte string of
      the option payload without the type code or length fields.
590
      </para></listitem>
591

592
      <listitem><para>
593
      "option[code].exists" checks if an option with the code "code" is present
Francis Dupont's avatar
Francis Dupont committed
594
      in the incoming packet. It can be used with empty options.
595
      </para></listitem>
Francis Dupont's avatar
Francis Dupont committed
596

Francis Dupont's avatar
Francis Dupont committed
597 598 599 600 601 602
      <listitem><para>
      "member('foobar')" checks if the packet belongs to the client
      class "foobar". To avoid dependency loops the configuration file
      parser checks if client classes were already defined or are
      built-in, i.e., beginning by &quot;VENDOR_CLASS_&quot;,
      &quot;AFTER__&quot; (for the to come "after" hook) and
Francis Dupont's avatar
Francis Dupont committed
603
      &quot;EXTERNAL_&quot; or equal to &quot;ALL&quot;, &quot;KNOWN&quot;,
604
      &quot;UNKNOWN&quot;etc.
Francis Dupont's avatar
Francis Dupont committed
605 606 607 608 609
      </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;
610
      or &quot;UNKNOWN&quot; partition is determined).
Francis Dupont's avatar
Francis Dupont committed
611 612
      </para></listitem>

613 614 615 616 617 618 619 620 621
      <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>
622

623 624 625 626
      <listitem><para>
      "relay4" shares the same representation types as "option", for
      instance "relay4[code].exists" is supported.
      </para></listitem>
627

628 629 630 631
      <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
632 633
      the relay closest to the DHCPv6 server. Negative values allow to
      specify relays counted from the DHCPv6 client, -1 indicating the
634 635
      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
636 637
      If the requested encapsulation doesn't exist an empty string ""
      is returned.  This expression is allowed in DHCPv6 only.
638
      </para></listitem>
639

640 641 642 643
      <listitem><para>
      "relay6[nest].option[code]" shares the same representation types as
      "option", for instance "relay6[nest].option[code].exists" is supported.
      </para></listitem>
644

645 646 647 648
      <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
649

650 651 652 653 654 655 656
      <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>
657

658 659
      <listitem><para>
      Vendor option means Vendor-Identifying Vendor-specific Information
660
      option in DHCPv4 (code 125, see
661
      <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
662
      Vendor-specific Information Option in DHCPv6 (code 17, defined in
663 664
      <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
665
      Class Option in DHCPv4 (code 124, see
666
      <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
667
      Class Option in DHCPv6 (code 16, see
668
      <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>).
669 670 671 672 673 674
      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
675

676 677
      <listitem><para>
      In the vendor and vendor-class constructs Asterisk (*) or 0 can be
Tomek Mrugalski's avatar
Tomek Mrugalski committed
678
      used to specify a wildcard enterprise-id value, i.e. it will match any
679 680
      enterprise-id value.
      </para></listitem>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
681

682 683
      <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
684

685
      <listitem><para>
686 687
      <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>
688
      allow for multiple instances of vendor options
Tomek Mrugalski's avatar
Tomek Mrugalski committed
689 690 691 692
      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
693 694 695 696
      support for multiple instances.
      </para></listitem>

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

698
      <para>
699
        <table frame="all" xml:id="classification-expressions-list">
700
          <title>List of Classification Expressions</title>
701 702 703 704
          <tgroup cols="3">
          <colspec colname="name"/>
          <colspec colname="example"/>
          <colspec colname="description"/>
705 706 707 708 709 710 711 712 713
          <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
714 715 716
<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>
717
<row><entry>Substring</entry><entry>substring('foobar',0,3)</entry><entry>Return the requested substring</entry></row>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
718 719
<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
720
<row><entry>Ifelse</entry><entry>ifelse('foo' == 'bar','us','them')</entry><entry>Return the branch value according to the condition</entry></row>
721
<row><entry>Hexstring</entry><entry>hexstring('foo', '-')</entry><entry>Converts the value to a hexadecimal string, e.g. 0a:1b:2c:3e</entry></row>
722 723 724
          </tbody>
          </tgroup>
        </table>
725 726
      </para>

Francis Dupont's avatar
Francis Dupont committed
727 728 729
      <section>
        <title>Logical operators</title>
        The Not, And and Or logical operators are the common operators. Not
730
        has the highest precedence and Or the lowest. And and Or are (left)
Francis Dupont's avatar
Francis Dupont committed
731 732
        associative, parentheses around a logical expression can be used
        to enforce a specific grouping, for instance in "A and (B or C)"
733
        (without parentheses "A and B or C" means "(A and B) or C").
Francis Dupont's avatar
Francis Dupont committed
734 735
      </section>

736 737 738 739 740 741 742 743 744 745 746
      <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:
747

748
          <screen>
749 750 751 752 753
        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'
754 755
        substring('foobar', -1, -3) == 'oba'
        substring('foobar', 4, -2) == 'ob'
756
        substring('foobar', 10, 2) == ''
757 758
          </screen>
      </section>
759 760 761 762 763 764 765 766
      <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
767 768 769 770 771 772 773 774 775
       <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>
776 777 778 779
        <section>
          <title>Hexstring</title>
          The hexstring function "hexstring(binary, separator)" returns
          the binary value as its hexadecimal string representation:
780 781
          pairs of hexadecimal digits separated by the separator, e.g
          ':', '-', '' (empty separator).
782 783 784 785
            <screen>
          hexstring(pkt4.mac, ':')
            </screen>
        </section>
786
    </section>
787

788 789 790 791 792
  <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
793
    complex or time consuming expressions you should write a <link linkend="hooks-libraries">hook</link> to perform the necessary work.
794 795
  </para> </note>

796
  <section xml:id="classification-configuring">
797 798
    <title>Configuring Classes</title>
      <para>
799
      A class contains five items: a name, a test expression, option data,
800
      option definition and only-if-required flag.
801
      The name must exist and must be unique amongst all classes. The test
802
      expression, option data and definition, and only-if-required flag are
803
      optional.
804
      </para>
805

806 807 808 809 810 811 812 813 814 815 816 817
      <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>
818 819 820 821 822 823 824 825 826
      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
827 828
      processing not yet done. The only-if-required flag, false by default,
      allows to perform the evaluation of the test expression only
829 830
      when it was required, i.e. in a require-client-classes list of the
      selected subnet, shared-network or pool.
831 832 833
      </para>

      <para>
834
      The require-client-classes list which is valid for shared-network,
835 836 837 838
      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
839
      in a shared-network but required class in a subnet is added
840
      after one in a shared-network.
841 842
      The mechanism is related to the only-if-required flag but it is
      not mandatory that the flag was set to true.
843 844
      </para>

845
      <para>
846
      In the following example the class named &quot;Client_foo&quot; is defined.
847
      It is comprised of all clients whose client ids (option 61) start with the
848
      string "foo". Members of this class will be given 192.0.2.1 and
849 850
      192.0.2.2 as their domain name servers.

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

      <para>
874
      This example shows a client class being defined for use by the DHCPv6 server.
875
      In it the class named "Client_enterprise" is defined.  It is comprised
876 877 878 879 880 881 882 883
      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",
884
            "test": "substring(option[1].hex,0,6) == 0x0002AABBCCDD'",
885 886 887 888 889 890 891 892 893 894 895 896 897 898
            "option-data": [
                {
                    "name": "dns-servers",
                    "code": 23,
                    "space": "dhcp6",
                    "csv-format": true,
                    "data": "2001:db8:0::1, 2001:db8:2::1"
                }
            ]
        },
        ...
    ],</userinput>
    ...
}</screen>
899 900 901
      </para>
  </section>

Francis Dupont's avatar
Francis Dupont committed
902 903 904 905 906 907 908 909
  <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>

910
  <section xml:id="classification-subnets">
911 912 913
    <title>Configuring Subnets With Class Information</title>
      <para>
        In certain cases it beneficial to restrict access to certain subnets
914
        only to clients that belong to a given class, using the "client-class"
915 916 917 918
        keyword when defining the subnet.
      </para>

      <para>
919 920 921 922
        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
923
        Client_foo  are allowed to use this subnet. Such a
924 925 926
        configuration can be achieved in the following way:
        <screen>
"Dhcp4": {
927
    "client-classes": [
928 929
        {
            "name": "Client_foo",
930
            "test": "substring(option[61].hex,0,3) == 'foo'",
931 932
            "option-data": [
                {
933
                    "name": "domain-name-servers",
934 935 936 937 938 939
                    "code": 6,
                    "space": "dhcp4",
                    "csv-format": true,
                    "data": "192.0.2.1, 192.0.2.2"
                }
            ]
940 941 942 943 944 945 946 947
        },
        ...
    ],<userinput>
    "subnet4": [
        {
            "subnet": "192.0.2.0/24",
            "pools": [ { "pool": "192.0.2.10 - 192.0.2.20" } ],
            "client-class": "Client_foo"
948 949 950 951 952 953 954 955
        },
        ...
    ],</userinput>,
    ...
}</screen>
      </para>

      <para>
Francis Dupont's avatar
Francis Dupont committed
956
        The following example shows restricting access to a DHCPv6 subnet.  This
957 958 959 960 961 962 963 964
        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",
965
            "test": "substring(option[1].hex,0,6) == 0x0002AABBCCDD'",
966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982
            "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"
983
        }
984
    ],</userinput>
985 986 987 988 989
    ...
}</screen>
      </para>
  </section>

990 991 992
 <section id="classification-pools">
   <title>Configuring Pools With Class Information</title>
     <para>
993 994 995
       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.
996 997 998
     </para>

     <para>
999
       Let's assume that the server is connected to a network segment that uses
1000
       the 192.0.2.0/24 prefix. The Administrator of that network has decided
1001 1002 1003 1004
       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:
1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
       <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"
                }
            ]
        },
        ...
1022
    ],<userinput>
1023 1024 1025 1026 1027 1028
    "subnet4": [
        {
            "subnet": "192.0.2.0/24",
            "pools": [
                {
                    "pool": "192.0.2.10 - 192.0.2.20",
1029
                    "client-class": "Client_foo"
1030
                }
1031
            ]
1032 1033
        },
        ...
1034
    ],</userinput>,
1035

1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
}</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"
                }
1057 1058 1059
            ]
        },
        ...
1060 1061 1062 1063 1064 1065 1066 1067
    ],
    "subnet6": [
        {
            "subnet": "2001:db8:1::/64",
            <userinput>
            "pools": [
                {
                    "pool": "2001:db8:1::-2001:db8:1::ffff",
1068
                    "client-class": "Client_foo"
1069 1070 1071 1072 1073
                }
            ]</userinput>
        },
        ...
    ],
1074 1075 1076 1077 1078
    ...
}</screen>
      </para>
  </section>

1079 1080 1081 1082
  <section>
    <title>Using Classes</title>
      <para>
      Currently classes can be used for two functions.  They can supply options
1083 1084
      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.
1085 1086 1087
      </para>

      <para>
1088
      When supplying options, options defined as part of the class definition
1089
      are considered "class globals".  They will override any global options that
1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101
      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
1102
      in choosing a subnet and selecting options.  For a description of
1103
      hooks see <xref linkend="hooks-libraries"/>, for a description on
1104
      configuring classes see <xref linkend="classification-configuring"/>
1105
      and <xref linkend="classification-subnets"/>.
1106 1107 1108
      </para>
  </section>

1109 1110 1111 1112 1113 1114 1115 1116 1117
  <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
1118
     To enable the debug statements in the classification system you will
1119 1120 1121 1122
     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>

1123
     <para>
Suzanne Goldlust's avatar
Suzanne Goldlust committed
1124 1125 1126
     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
1127
     In brief there are two structures used during the evaluation of an expression:
1128 1129 1130 1131 1132 1133 1134
     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
1135
     in reverse Polish notation.  During execution, the list will be traversed
1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152
     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>

1153
     <para>
1154 1155
     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
1156 1157 1158 1159 1160 1161
     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
1162
     to use text values or hexadecimal if the command either uses binary values or
1163
     can manipulate either text or binary values.  For expressions that
1164
     pop multiple values off the stack, the values will be displayed in
1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178
     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
1179 1180
       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'
1181
       2016-05-19 13:35:04.166 DEBUG [kea.eval/44478] EVAL_DEBUG_SUBSTRING Popping length 3, start 0, string 0x666F6F626172 pushing result 0x666F6F
1182 1183
       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'
1184 1185 1186 1187 1188
       </screen>
     </para>

     <note><para>
     The debug logging may be quite verbose if you have a number of expressions
1189
     to evaluate.  It is intended as an aid in helping you create and debug
1190
     your expressions.  You should plan to disable debug logging when you have your