Annotation of embedaddon/dhcp/doc/api+protocol, revision 1.1

1.1     ! misho       1: This file documents the protocol that the ISC DHCP server and ISC
        !             2: Object Management clients (clients that use the ISC Object Management
        !             3: API) speak between one another.
        !             4: 
        !             5: Protocol:
        !             6: 
        !             7: All multi-byte numbers are represented in network byte order.
        !             8: 
        !             9: On startup, each side sends a status message indicating what version
        !            10: of the protocol they are speaking.   The status message looks like
        !            11: this:
        !            12: 
        !            13: +---------+---------+
        !            14: | version | hlength |
        !            15: +---------+---------+
        !            16: 
        !            17: version - a 32-bit fixed-point number with the decimal point between
        !            18:          the third and second decimal digits from the left,
        !            19:          representing the version of the protocol.   The current
        !            20:          protocol version is 1.00.   If the field were considered as
        !            21:          a 32-bit integer, this would correspond to a value of 100
        !            22:          decimal, or 0x64.
        !            23: 
        !            24: hlength - a 32-bit integer representing the length of the fixed-length
        !            25:          header in subsequent messages.   This is normally 56, but
        !            26:          can be changed to a value larger than 56 by either side
        !            27:          without upgrading the revision number.
        !            28: 
        !            29: 
        !            30: The startup message is not authenticated.   Either side may reject the
        !            31: other side's startup message as invalid by simply closing the
        !            32: connection.   The only fixed part of the startup message is the
        !            33: version number - future versions may delete hlength, or add further
        !            34: startup information.
        !            35: 
        !            36: Following the startup message, all messages have the same format.
        !            37: Currently, the format includes a fixed-length header (the length in
        !            38: hlength, above)
        !            39: 
        !            40: +--------+----+--------+----+-----+---------+------------+------------+-----+
        !            41: | authid | op | handle | id | rid | authlen | msg values | obj values | sig |
        !            42: +--------+----+--------+----+-----+---------+------------+------------+-----+
        !            43: 
        !            44: The fixed-length header consists of:
        !            45: 
        !            46: authid = a 32-bit authenticator handle.
        !            47:        For an original message (one not in response to some other
        !            48:        message), this will be chosen by the originator.   For a
        !            49:        message in response to another message, the authenticator for
        !            50:        that message is used, except if the response is an error
        !            51:        message indicating that the authenticator used was unknown,
        !            52:        in which case the null authenticator is used.   Messages that
        !            53:        are generated as the result of a notify registration use the
        !            54:        authenticator used in the original notify registration.
        !            55:        The authenticator itself is generated by having one side of
        !            56:        the connection send an object of type "authenticator" to the
        !            57:        other side with values that indicate what kind of
        !            58:        authentication mechanism to use and what key to use.   The two
        !            59:        most likely things here are a Kerberos V principal name or the
        !            60:        name of a shared secret that can be used to calculate an MD5
        !            61:        hash.   The mechanism for doing this has yet to be finalized.
        !            62:        If authid is zero, the message is not authenticated.
        !            63: 
        !            64: op = 32-bit opcode, one of:
        !            65:        open = 1
        !            66:        refresh = 2
        !            67:        update = 3
        !            68:        notify = 4
        !            69:        error = 5
        !            70:        delete = 6
        !            71: handle = 32-bit object handle
        !            72:        A handle on the object being opened, created, refreshed or
        !            73:        updated.   If no handle is yet available (e.g., with open and
        !            74:        new), then the value zero is sent.
        !            75: id = 32-bit transaction id of the message - a monotonically increasing
        !            76:      number that starts with some randomly chosen number at the
        !            77:      beginning of the life of the connection.   The value should never
        !            78:      be zero.
        !            79: rid = 32-bit transaction ID of the message to which this message is a
        !            80:       response, or zero if this message is not in response to a
        !            81:       message from the other side.
        !            82: 
        !            83: authlen = a 32-bit number representing the length of the authenticator
        !            84: 
        !            85: msg values = a series of name+value pairs, specific to this message.
        !            86:         Each name+value pair starts with a 16-bit name length,
        !            87:         followed by that many bytes of name, followed by a 32-bit
        !            88:         value length, followed by that many bytes of value.   If the
        !            89:         length is zero, this is a value of the blank string.   If the
        !            90:         length is all ones (2^32-1), then there is no value - for an
        !            91:         update, this means the value for this name and the name
        !            92:         itself should be deleted from the object, which may or may
        !            93:         not be possible.   The list of name/value pairs ends with a
        !            94:         zero-length name, which is not followed by a value
        !            95:         length/value pair.
        !            96: 
        !            97: obj values = a series of name+value pairs, as above, specific to the
        !            98:        object being created, updated or refreshed.
        !            99: 
        !           100: signature = authlen bytes of data signing the message.   The signature
        !           101:            algorithm is a property of the authenticator handle.
        !           102: 
        !           103: Message types:
        !           104: 
        !           105: 1: open
        !           106:    relevant input values:
        !           107:        object-type = the name of the type of object
        !           108:        open:create = boolean - create the object if it doesn't yet exist
        !           109:        open:exclusive = boolean - don't open the object if it does exist
        !           110:        open:update = boolean - update the object with included values
        !           111:                      if it matches.
        !           112:        the handle should always be the null handle
        !           113: 
        !           114:    The input value must also contain key information for the type of
        !           115:    object being searched that uniquely identifies an object, or search
        !           116:    information that matches only one object.  Each object has a key
        !           117:    specification (a key is something that uniquely identifies an
        !           118:    object), so see the key specification for that object to see
        !           119:    what to send here.   An open message with the create flag set must
        !           120:    specify a key, and not merely matching criteria.   Some objects may
        !           121:    allow more than one key, and it may be that the union of those keys
        !           122:    is required to uniquely identify the object, or it may be that any
        !           123:    one such key will uniquely identify the object.   The documentation
        !           124:    for the type of object will specify this.
        !           125: 
        !           126:    An open message will result in an immediate response message whose
        !           127:    opcode will either be "error" or "update".   The error message may
        !           128:    include an error:reason value containing a text string explaining
        !           129:    the error, and will always include an error:code value which will
        !           130:    be the numeric error code for what went wrong.   Possible error
        !           131:    codes are:
        !           132: 
        !           133:        not found - no such object exists
        !           134:        already exists - object already exists, and exclusive flag was
        !           135:                         set.
        !           136:        not unique - more than one object matching the specification
        !           137:                     exists.
        !           138:        permission denied - the authenticator ID specified does not
        !           139:                            have authorization to access this object,
        !           140:                            or if the update flag was specified, to
        !           141:                            update the object.
        !           142: 
        !           143:    If the response is an update message, the update message will
        !           144:    include the object handle and all of the name/value pairs
        !           145:    associated with that object.
        !           146: 
        !           147: 2: refresh
        !           148: 
        !           149:    no input values except the handle need be specified.   The null
        !           150:    handle may not be specified.   If the handle is valid, and the
        !           151:    authenticator ID specified has permission to examine the object,
        !           152:    then an update message will be sent for that object.   Otherwise,
        !           153:    one of the following errors will be sent:
        !           154: 
        !           155:        invalid handle - the handle does not refer to a known object
        !           156:        permisson denied - the handle refers to an object that the
        !           157:                           requestor does not have permission to
        !           158:                           examine. 
        !           159: 
        !           160: 3: update
        !           161: 
        !           162:    Requests that the contents of the specified object be updated with
        !           163:    the values included.   Values that are not specified are not
        !           164:    updated.   The response will be either an error message or an
        !           165:    update-ok message.   If rid is nonzero, no response will be
        !           166:    generated, even if there was an error.   Possible errors include:
        !           167: 
        !           168:        invalid handle - no such object was found
        !           169:        permission denied - the handle refers to an object that the
        !           170:                            requestor does not have permission to
        !           171:                            modify.
        !           172:        not confirmed - the update could not be committed due to some
        !           173:                        kind of resource problem, for example
        !           174:                        insufficient memory or a disk failure.
        !           175: 
        !           176: 4: notify
        !           177: 
        !           178:    Requests that whenever the object with the specified handle is
        !           179:    modified, an update be sent.   If there is something wrong with the
        !           180:    request, an error message will be returned immediately.
        !           181:    Otherwise, whenever a change is made to the object, an update
        !           182:    message will be sent containing whatever changes were made (or
        !           183:    possibly all the values associated with the object, depending on
        !           184:    the implementation).   Possible errors:
        !           185: 
        !           186:        invalid handle
        !           187:        permission denied - the handle refers to an object that the
        !           188:                            requestor does not have permission to
        !           189:                            examine.
        !           190:        not supported - the object implementation does not support
        !           191:                        notifications
        !           192: 
        !           193: 5: status
        !           194: 
        !           195:    Sends a status code in response to a message.  Always sent in
        !           196:    response to a message sent by the other side.  There should never
        !           197:    be a response to this message.
        !           198: 
        !           199: 6: delete
        !           200: 
        !           201:    Deletes the specified object.   Response will be either request-ok,
        !           202:    or error.   Possible errors include:
        !           203: 
        !           204:        invalid handle - no such object was found
        !           205:        permission denied - the handle refers to an object that the
        !           206:                            requestor does not have permission to
        !           207:                            modify.
        !           208:        not confirmed - the deletion could not be committed due to
        !           209:                        some kind of resource problem, for example
        !           210:                        insufficient memory or a disk failure.
        !           211: 
        !           212: 7: notify-cancel
        !           213: 
        !           214:    Like notify, but requests that an existing notification be cancelled.
        !           215: 
        !           216: 8: notify-cancelled
        !           217: 
        !           218:    Indicates that because of a local change, a notification that had
        !           219:    been registered can no longer be performed.   This could be as a
        !           220:    result of the permissions on a object changing, or an object being
        !           221:    deleted.   There should never be a response to this message.
        !           222: 
        !           223: internals:
        !           224: 
        !           225: Both client and server use same protocol and infrastructure.   There
        !           226: are many object types, each of which is stored in a registry.
        !           227: Objects whose type is not recognized can either be handled by the
        !           228: generic object type, which is registered with the type "*".   If no
        !           229: generic object type is registered, then objects with unknown types are
        !           230: simply not supported.   On the client, there are probably no special
        !           231: object handlers (although this is by no means forbidden).   On the
        !           232: server, probably everything is a special object.
        !           233: 
        !           234: Each object type has the following methods:
        !           235: 
        !           236: 
        !           237: 
        !           238: 
        !           239: dhcpctl_status dhcpctl_connect (dhcpctl_handle *connection,
        !           240:                                char *server_name, int port,
        !           241:                                dhcpctl_handle *authinfo)
        !           242:        synchronous
        !           243:        returns nonzero status code if it didn't connect, zero otherwise
        !           244:        stores connection handle through connection, which can be used
        !           245:        for subsequent access to the specified server. 
        !           246:        server_name is the name of the server, and port is the TCP
        !           247:        port on which it is listening.
        !           248:        authinfo is the handle to an object containing authentication
        !           249:        information.
        !           250: 
        !           251: dhcpctl_status dhcpctl_open_object (dhcpctl_handle h,
        !           252:                                    dhcpctl_handle connection,
        !           253:                                    int flags)
        !           254:        asynchronous - just queues the request
        !           255:        returns nonzero status code if open couldn't be queued
        !           256:        returns zero if open was queued
        !           257:        h is a handle to an object created by dhcpctl_new_object
        !           258:        connection is a connection to a DHCP server
        !           259:        flags include:
        !           260:           DHCPCTL_CREATE - if the object doesn't exist, create it
        !           261:           DHCPCTL_UPDATE - update the object on the server using the
        !           262:                            attached parameters 
        !           263:           DHCPCTL_EXCL - error if the object exists and DHCPCTL_CREATE
        !           264:                          was also specified
        !           265: 
        !           266: dhcpctl_status dhcpctl_new_object (dhcpctl_handle *h,
        !           267:                                   dhcpctl_handle connection,
        !           268:                                   char *object_type)
        !           269:        synchronous - creates a local handle for a host entry.
        !           270:        returns nonzero status code if the local host entry couldn't
        !           271:        be created
        !           272:        stores handle to host through h if successful, and returns zero.
        !           273:        object_type is a pointer to a NUL-terminated string containing
        !           274:        the ascii name of the type of object being accessed - e.g., "host"
        !           275: 
        !           276: dhcpctl_status dhcpctl_set_callback (dhcpctl_handle h, void *data,
        !           277:                                     void (*callback) (dhcpctl_handle,
        !           278:                                                       dhcpctl_status, void *))
        !           279:        synchronous, with asynchronous aftereffect
        !           280:        handle is some object upon which some kind of process has been
        !           281:        started - e.g., an open, an update or a refresh.
        !           282:        data is an anonymous pointer containing some information that
        !           283:        the callback will use to figure out what event completed.
        !           284:        return value of 0 means callback was successfully set, a nonzero
        !           285:        status code is returned otherwise.
        !           286:        Upon completion of whatever task is in process, the callback
        !           287:        will be passed the handle to the object, a status code
        !           288:        indicating what happened, and the anonymous pointer passed to 
        !           289: 
        !           290: dhcpctl_status dhcpctl_wait_for_completion (dhcpctl_handle h,
        !           291:                                            dhcpctl_status *s)
        !           292:        synchronous
        !           293:        returns zero if the callback completes, a nonzero status if
        !           294:        there was some problem relating to the wait operation.   The
        !           295:        status of the queued request will be stored through s, and
        !           296:        will also be either zero for success or nonzero for some kind
        !           297:        of failure.    Never returns until completion or until the
        !           298:        connection to the server is lost.   This performs the same
        !           299:        function as dhcpctl_set_callback and the subsequent callback,
        !           300:        for programs that want to do inline execution instead of using
        !           301:        callbacks.
        !           302: 
        !           303: dhcpctl_status dhcpctl_get_value (data_string *result,
        !           304:                                  dhcpctl_handle h, char *value_name)
        !           305:        synchronous
        !           306:        returns zero if the call succeeded, a nonzero status code if
        !           307:        it didn't. 
        !           308:        result is the address of an empty data string (initialized
        !           309:        with bzero or cleared with data_string_forget).   On
        !           310:        successful completion, the addressed data string will contain
        !           311:        the value that was fetched.
        !           312:        dhcpctl_handle refers to some dhcpctl item
        !           313:        value_name refers to some value related to that item - e.g.,
        !           314:        for a handle associated with a completed host lookup, value
        !           315:        could be one of "hardware-address", "dhcp-client-identifier",
        !           316:        "known" or "client-hostname".
        !           317: 
        !           318: dhcpctl_status dhcpctl_get_boolean (int *result,
        !           319:                                    dhcpctl_handle h, char *value_name)
        !           320:        like dhcpctl_get_value, but more convenient for boolean
        !           321:        values, since no data_string needs to be dealt with.
        !           322: 
        !           323: dhcpctl_status dhcpctl_set_value (dhcpctl_handle h, data_string value,
        !           324:                                  char *value_name)
        !           325:        Sets a value on an object referred to by a dhcpctl_handle.
        !           326:        The opposite of dhcpctl_get_value.   Does not update the
        !           327:        server - just sets the value on the handle.
        !           328: 
        !           329: dhcpctl_status dhcpctl_set_string_value (dhcpctl_handle h, char *value,
        !           330:                                         char *value_name)
        !           331:        Sets a NUL-terminated ASCII value on an object referred to by
        !           332:        a dhcpctl_handle.   like dhcpctl_set_value, but saves the
        !           333:        trouble of creating a data_string for a NUL-terminated string.
        !           334:        Does not update the server - just sets the value on the handle.
        !           335: 
        !           336: dhcpctl_status dhcpctl_set_boolean (dhcpctl_handle h, int value,
        !           337:                                    char *value_name)
        !           338:        Sets a boolean value on an object - like dhcpctl_set_value,
        !           339:        only more convenient for booleans.
        !           340: 
        !           341: dhcpctl_status dhcpctl_object_update (dhcpctl_handle h)
        !           342:        Queues an update on the object referenced by the handle (there
        !           343:        can't be any other work in progress on the handle).   An
        !           344:        update means local parameters will be sent to the server.
        !           345: 
        !           346: dhcpctl_status dhcpctl_object_refresh (dhcpctl_handle h)
        !           347:        Queues an update on the object referenced by the handle (there
        !           348:        can't be any other work in progress on the handle).   An
        !           349:        update means local parameters will be sent to the server.
        !           350: 
        !           351: dhcpctl_status dhcpctl_object_delete (dhcpctl_handle h)
        !           352:        Queues a delete of the object referenced by the handle (there
        !           353:        can't be any other work in progress on the handle).   A
        !           354:        delete means that the object will be permanently deleted on
        !           355:        the remote end, assuming the remote end supports object
        !           356:        persistence.
        !           357: 
        !           358: So a sample program that would update a host declaration would look
        !           359: something like this:
        !           360: 
        !           361:        /* Create a local object into which to store authentication
        !           362:           information. */
        !           363:        if ((status = dhcpctl_new_object (&auth, dhcpctl_null_handle,
        !           364:                                          "authentication-information")))
        !           365:                dhcpctl_error ("Can't create authentication information: %m");
        !           366: 
        !           367:        /* Set up the authenticator with an algorithm type, user name and
        !           368:           password. */
        !           369:        if ((status = dhcpctl_set_string_value (&auth, "mellon", "username")))
        !           370:                dhcpctl_error ("Can't set username: %m", status);
        !           371:        if ((status = dhcpctl_set_string_value (&auth, "three blind mice",
        !           372:                                                "password")))
        !           373:                dhcpctl_error ("Can't set password: %m", status);
        !           374:        if ((status = dhcpctl_set_string_value (&auth, "md5-hash",
        !           375:                                                "algorithm")))
        !           376:                dhcpctl_error ("Can't set authentication algorithm: %m.",
        !           377:                               status);
        !           378: 
        !           379:        /* Connect to the server. */
        !           380:        if ((status = dhcpctl_connect (&c, "dhcp.server.com", 612, &auth)))
        !           381: 
        !           382:                dhcpctl_error ("Can't connect to dhcp.server.com: %m",
        !           383:                               status);
        !           384: 
        !           385:        /* Create a host object. */
        !           386:        if ((status = dhcpctl_new_object (&hp, c, "host")))
        !           387:                dhcpctl_error ("Host create failed: %m", status);
        !           388: 
        !           389:        /* Create a data_string to contain the host's client
        !           390:           identifier, and set it. */
        !           391:        if ((status =
        !           392:             data_string_create_from_hex (&client_id,
        !           393:                                          "1:08:00:2b:34:1a:c3")))
        !           394:                dhcpctl_error ("Can't create client identifier: %m");
        !           395:        if ((status = dhcpctl_set_value (hp, client_id,
        !           396:                                         "dhcp-client-identifier")))
        !           397:                dhcpctl_error ("Host client identifier set failed.");
        !           398:        /* Set the known flag to 1. */
        !           399:        if ((status = dhcpctl_set_boolean (hp, 1, "known")))
        !           400:                dhcpctl_error ("Host known set failed.");
        !           401: 
        !           402:        /* Open an existing host object that matches the client identifier,
        !           403:           and update it from the local context, or if no host entry
        !           404:           yet exists matching the identifier, create one and
        !           405:           initialize it. */
        !           406:        if ((status = dhcpctl_open_object (&hp, c,
        !           407:                                           DHCPCTL_CREATE | DHCPCTL_UPDATE)))
        !           408:                dhcpctl_error ("Can't open host: %m", status);
        !           409: 
        !           410:        /* Wait for the process to complete, check status. */
        !           411:        if ((status = dhcpctl_wait_for_completion (hp, &wait_status)))
        !           412:                dhcpctl_error ("Host create/lookup wait failed: %m", status);
        !           413:        if (waitstatus)
        !           414:                dhcpctl_error ("Host create/lookup failed: %m", status);
        !           415: 
        !           416: The API is a bit complicated, for a couple of reasons.   I want to
        !           417: make it general, so that there aren't a bazillion functions to call,
        !           418: one for each data type.   I want it to be thread-safe, which is why
        !           419: each function returns a status and the error printer requires a status
        !           420: code for input.   I want it to be possible to make it asynchronous, so
        !           421: that it can work in tandem with, for example, an X toolkit.   If
        !           422: you're just writing a simple update cgi program, you probably won't
        !           423: want to bother to use the asynchronous callbacks, and indeed the above
        !           424: example doesn't.
        !           425: 
        !           426: I glossed over data strings above - basically, they're objects with a
        !           427: pointer to a reference-counted buffer structure, an offset into that
        !           428: buffer, and a length.   These are used within the DHCP server, so you
        !           429: can get an idea of how they work - basically, they're a convenient and
        !           430: efficient way to store a string with a length such that substrings can
        !           431: easily be taken and such that more than one user at a time can have a
        !           432: pointer to the string.
        !           433: 
        !           434: I will also probably add locking primitives, so that you can get the
        !           435: value of something and be sure that some other updator process won't
        !           436: modify it while you have the lock.

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>