[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15. Extending dhcp-client

dhcp-client uses guile (GNU's Ubiquitous Intelligent Language for Extensions) to extend itself. Extensions can currently be written for handling DHCP options during system configuration time. Essentially, the extension script defines how the client configures the local system according to the DHCP options passed.

The rest of this section assumes you are familiar with the Scheme programming language. If you are not familiar with the Scheme programming language then you cannot extend the client to configure options it is not programmed to handle.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.1 The Client Sysconf Script

dhcp-client calls a sysconf script which is placed in the same directory as the configuration file. This script, like the configuration file, can be named either "default.sysconf" or after an interface name. The file naming convention is the same as the configuration file. See section 11. Configuring dhcp-client.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.2 Looking At The Sysconf Script

The default sysconf script which is shipped with dhcp-agent is made up of several lambda expressions which are placed inside closures. If you're not familiar with the concept of closures, refer to the guile documentation.

Under each closure is a configure/unconfigure lambda expression which are bound to top level symbols. These symbols are then placed in two hooks, one for the bound state, and one for the release state.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.2.1 The DNS Configuration: An Example

We'll walk through the DNS configuration (a very simple example) to see how it was written. After this example a more in-depth discussion follows. If you notice some details are skipped over, don't worry. It will become clear later.

 
(define configure-dns #f)
(define unconfigure-dns #f)

First we define two top level symbols to false. We'll later bind against these in the closure.

 
(let ((configured-domain-name #f)
       (configured-domain-name-servers #f)

We begin the closure by defining two variables which will be used to hold any configured domain name and domain name servers. For DNS configuration these aren't useful, but for other sysconf code keeping the values of configured data is useful when it comes time to unconfigure the system on a DHCP RELEASE.

 
      ; check to see if we really need to configure
       (do-configure 
        (lambda()
          (and (client-configure? client-control
          'dhcp-domain-name-servers) 
               (client-configure? client-control 'dhcp-domain-name)
               (defined? 'dhcp-domain-name-servers)
               (defined? 'dhcp-domain-name)))))

Here we define a lambda expression which will tell us whether or not we should be performing any configuration for dns. The expression will return true if the options "domain-name-servers" and "domain-name" have been passed to us by the DHCP server. Also it checks if the user has requested that we configure these options.

 
  ; configure dns options
  (set! configure-dns

        (lambda ()
          (if (do-configure)
              (let ((resolv-conf-file-port (open "/etc/resolv.conf" (logior O_WRONLY O_TRUNC)  0644)))
                (client-info-message "configuring resolver")
                (map-in-order
                 (lambda (dns-server)
                   (simple-format resolv-conf-file-port "nameserver ~A\n" dns-server))  dhcp-domain-name-servers)
                (simple-format resolv-conf-file-port "search ~A\n" dhcp-domain-name)
                (close-port resolv-conf-file-port)

                                        ; now setup the options so we can use them again in unconfigure.
                (set! configured-domain-name dhcp-domain-name)
                (set! configured-domain-name-servers dhcp-domain-name-servers)))))

The "configure-dns" function will first check if "do-configure" returns true. It will then open "/etc/resolv.conf" and notify the user that the resolver is being configured. It then writes out the contents of the string list "dhcp-domain-name-servers" to the file prefixing each string with the keyword "nameserver." Finally the "search" keyword is written with the domain name.

After the configuration is complete, the values are stored in "configured-domain-name" and "configured-domain-name-servers." This allows us to remember the values in the event of unconfiguring the system.

 
                                        ; unconfigure dns options
  (set! unconfigure-dns
        (lambda()

         ; We shouldn't really be doing anything. Any name server
         ; is a good server :-)

          #t)))

As mentioned in the comment there's no need to do any unconfiguration. We'd rather have a resolv.conf than delete it. You can always modify this to delete the file, or insert a different set of values.

 
(add-hook! dhcp-bind-hook configure-dns)
(add-hook! dhcp-release-hook unconfigure-dns)

Finally the two routines are bound to the DHCP BIND and DHCP RELEASE hooks. It is important to add the option handlers in reverse order. You'll notice "configure-interface" is added last so that the interface is configured first.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.2.2 The DHCP BOUND and DHCP RELEASE hooks

Two hooks are defined at the top level by the client. "dhcp-bind-hook" and "dhcp-release-hook." When the client wants to configure itself it will call "dhcp-bind-hook" and when it releases its lease it will call "dhcp-release-hook."


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.2.3 How DHCP Options Are Passed To The Sysconf Script

When the DHCP BOUND hook is called, all the options are defined as top level symbols which refer to either a string, or a list of strings depending on whether the option is a single atom, or a list of atoms [ TODO: make list of handled options along with their types. ]

In order to check for the existance of an option, simple use "defined?" to check if the symbol is bound.

 
; check for the routers option

(defined? 'dhcp-routers)

This will return a boolean value of true of false depending on whether the DHCP option has been bound at the top level.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

15.3 Scheme Procedures Provided By The Client

At the top level a "client-control" symbol is bound to a control object which is used in every invocation of routines provided by the client.

Client Sysconf Routine: client-configure? client-control option-symbol

Returns #t of #f depending on whether or not the user has explicitly stated that the dhcp option should be configured.

Client Sysconf Routine: client-interface-up client-control ip-address netmask mtu

Initializes the network interface the client is handling and assigns the requested ip-address, the netmask and mtu.

Client Sysconf Routine: client-set-default-route client-control ip-address

Sets the default route to the ip-address specified.

Client Sysconf Routine: client-remove-default-route client-control ip-address

Removes the default route to the ip-address specified.

Client Sysconf Routine: client-get-default-mtu client-control

Returns the default mtu specified by the user.

Client Sysconf Routine: client-get-default-subnet-mask client-control

Returns the default subnet-mask specified by the user.

Client Sysconf Routine: client-info-message string

Prints out the string using the client's info_message routine.

Client Sysconf Routine: client-error-message string

Prints out the string using the client's error_message routine.

Client Sysconf Routine: client-fatal-message string

Prints out the string using the client's fatal_message routine. This exits after passing the message to the user.

Client Sysconf Routine: client-shutdown client-control

Invokes the shutdown routine in the client and causes the client to exit as cleanly as possible, relinquishing any leases it has. Warning! This should not be called from within a release hook.

Client Sysconf Routine: client-discover-icmp-latency client-control address-list

Accepts a list of addresses address-list and performs ICMP ECHO latency tests to determine which host is responding fastest. A list of address/average-latency pairs is returned.

Client Sysconf Routine: client-do-discover-icmp-latency client-control

Returns #t if the user enabled "do-measure-router-latency" or #f if not.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Thamer Alharbash on July, 22 2003 using texi2html