doxyOverview.h

00001 /**
00002  * @defgroup OV Overview
00003  * @{
00004 @verbatim
00005   -------------------------------------------------------------------------
00006   LIBDHCP : library programming interface to the ISC DHCP and DHPv6 clients
00007 
00008                              An Overview
00009 
00010     author: Jason Vas Dias<jvdias@redhat.com> Red Hat, Inc, May 2006
00011   -------------------------------------------------------------------------
00012 @endverbatim
00013 
00014 LIBDHCP enables programs to invoke the ISC dhclient (IPv4 DHCP) and DHCPv6 client
00015 (IPv6 DHCP) libraries, libdhcp4client and libdhcp6client, within one process, 
00016 to use the lease objects returned to configure network interface parameters, 
00017 and provides a full-featured Network Interface Configuration (NIC) library
00018 for static or dynamic network parameter configuration.
00019 
00020 The primary, tested, intended interface is as follows, though there are quite a few
00021 other ways of using the code (by no means all of them bug free ! :-).
00022 
00023 First, include the main interface header:
00024 
00025 @code
00026 #include <libdhcp/dhcp_nic.h>
00027 @endcode
00028 
00029 it will include all required headers from libdhcp.
00030 
00031 Choose which IPv6/IPv4 DHCP policy you wish libdhcp to implement, 
00032 from the  enum type "DHCP_Preference" in dhcp_nic.h :
00033 @code
00034     DHCPv4_DISABLE  = 1,  \/\* Don't do IPv4 DHCP \*\/
00035     DHCPv6_DISABLE  = 2,  \/\* Don't do IPv6 DHCP \*\/
00036     IPv6_PREFERENCE = 4,  \/\* Configure IPv6 addresses / routes / DNS first \*\/ 
00037     DHCPv4_DISABLE_ADDRESSES = 8,  \/\* Don't configure DHCPv4 addresses \*\/
00038     DHCPv4_DISABLE_ROUTES    = 16, \/\* Don't configure DHCPv4 routes \*\/
00039     DHCPv4_DISABLE_RESOLVER  = 32, \/\* Don't configure DHCPv4 resolv.conf entries \*\/
00040     DHCPv6_DISABLE_ADDRESSES = 64, \/\* Don't configure DHCPv6 address (ie. use radvd) \*\/
00041     DHCPv6_DISABLE_RESOLVER  = 128,\/\* Don't configure DHCPv6 resolv.conf entries \*\/
00042     DHCPv4_DISABLE_HOSTNAME_SET=256\/\* Don't set hostname if DHCPv4 host-name option sent \*\/ 
00043     DHCP_ACCEPT_FIRST_LEASE  = 512 \/\* If timeout == 0, v4 and v6 clients are in separate
00044                                     * processes; if this preference is set, the first client
00045                                     * to get a lease will cause that lease to be accepted
00046                                     * and the other client process to be terminated. \*\/
00047 
00048 @endcode
00049 
00050 You can specify the "capabilities" the DHCP clients are allowed to exercise, with
00051 enum type "DHCP_Capability" from libdhcp.h:
00052 
00053 @code
00054  \/\* DHCP client "capabilities" \*\/ 
00055     DHCP_USE_LEASE_DATABASE   = 1,      \/\* use / do not use persistent lease database files \*\/
00056     DHCP_USE_PID_FILE         = 2,      \/\* use / do not use pid file                        \*\/
00057  \/\*
00058   * DHCPv6 supports these capabilities in process, 
00059   * while the DHCPv4 client would fork and exec the dhclient-script to implement them if these
00060   * bits are set - otherwise, if no bits are set, the callback is called and the script is 
00061   * not run.
00062   \*\/
00063     DHCP_CONFIGURE_INTERFACES = 4,      \/\* configure interfaces UP/DOWN as required         \*\/
00064     DHCP_CONFIGURE_ADDRESSES  = 8,      \/\* configure interface addresses as required        \*\/
00065     DHCP_CONFIGURE_ROUTES     =16,      \/\* configure routes as required                     \*\/
00066     DHCP_CONFIGURE_RESOLVER   =32,      \/\* configure resolv.conf as required                \*\/
00067     \/\* DHCPv6 only: \*\/
00068     DHCP_CONFIGURE_RADVD      =64,      \/\* configure radvd.conf & restart radvd as required \*\/
00069 @endcode
00070 
00071 Then, call the main dhcp interface function, 'do_dhcp' (from dhcp_nic.h) with the values you
00072 chose:
00073 
00074 @code
00075 extern 
00076 NIC_Res_t *do_dhcp
00077 ( 
00078     DHCP_Preference preference,
00079     char                  *eth_if_name,
00080     LIBDHCP_Capability     dhc_cap, 
00081     time_t                 timeout,    
00082     LIBDHCP_Error_Handler  error_handler,
00083     uint8_t                log_level,
00084     ... \/\* extra DHCPv4 dhclient arguments;
00085          * last arg MUST be 0 .
00086          \*\/
00087 );
00088 @endcode
00089 
00090 The timeout is a hard timeout that each client has to contact the server,
00091 until it gives up.
00092 
00093 If the timeout is 0, and neither DHCPv4_DISABLE nor DHCPv6_DISABLE is
00094 specified, then each client will be run in a separate process, and each
00095 client will try to contact the server indefinitely until a lease is 
00096 obtained.
00097 
00098 You can define an error handler to handle all debug / error / info
00099 log messages emanating from the clients:
00100 
00101 @code
00102  int( *LIBDHCP_Error_Handler )
00103     ( struct libdhcp_control_s *ctl,
00104       int priority,  \/\* ala syslog(3): LOG_EMERG=0 - LOG_DEBUG=7 (+ LOG_FATAL=8 : finished -> 1)   \*\/
00105       const char *fmt,
00106       va_list ap
00107     );
00108 @endcode
00109 
00110 "log_level" in the dhcp_nic call sets the maximum level that will be logged.
00111 Two standard error handlers are defined:
00112 @verbatim
00113   libdhcp_stderr_logger  : writes log messages to stderr
00114   libdhcp_syslogger      : writes log messages to syslog
00115 @endverbatim
00116 No logging is done if "error_handler" is 0 .
00117 
00118 You can specify any normal dhclient command line arg in the va_list .
00119 
00120 ie. a call that specifies that libdhcp should runs DHCPv4 and DHCPv4,
00121 for interface named "eth0", with extra dhclient args to send the 
00122 dhcp-client-identifier, vendor-class-identifier, and host-name would be:
00123     
00124 @code
00125     NIC_Res_t r =
00126     dhcp_nic
00127     ( 0,
00128       "eth0",
00129       0,
00130       10, \/\* each client has 10 seconds to get a lease \*\/
00131       libdhcp_stderr_logger,
00132       LOG_INFO,
00133       "-V","i386-redhat-fc6",
00134       "-I", "1:00:0D:60:CF:98:E3",
00135       "-H", "mypc",
00136       0 \/\* !!! THE ESSENTIAL TRAILING 0 !!! \*\/
00137     );
00138 @endcode 
00139 This call would then actually invoke the clients in the same process as the
00140 caller (no forks / execs / system() calls involved) and would configure the
00141 network interface "eth0" with the parameters returned.
00142 
00143 You may want to inspect and modify the network parameters returned by DHCP
00144 before going ahead and configuring the interface. For this, the 'dhcp_nic'
00145 function is provided:
00146 
00147 @code
00148 extern 
00149 DHCP_nic *dhcp_nic
00150 ( 
00151     NLH_t nh, \/\* nic library handle \*\/
00152     DHCP_Preference preference,
00153     char                  *eth_if_name,
00154     LIBDHCP_Capability     dhc_cap, 
00155     time_t                 timeout,    
00156     LIBDHCP_Error_Handler  error_handler,
00157     uint8_t                log_level,
00158     ... \/\* extra DHCPv4 dhclient arguments;
00159          * last arg MUST be 0 .
00160          \*\/
00161 );
00162 @endcode
00163 
00164 This returns a "Network Interface Configuration" ( NIC ) structure - well, actually 
00165 two NIC structures, one for each client, encapsulated in the "DHCP_nic" structure -
00166 at this point, no actual interface configuration beyond setting the interface flags 
00167 to (IFF_UP & IFF_RUNNING) would have been done.
00168 
00169 ( That is, of course, only if you have both the DHCPv6 IPv6 DHCP dhcp6s 
00170   server and the IPv4 DHCP ISC dhcpd server running on your network.
00171   An example working /etc/dhcp6s.conf for dhcp6s is:
00172 @verbatim
00173   ---
00174   # /etc/dhcp6s.conf
00175   interface eth0 {
00176    link eth0 {
00177         range fec0::10 to fec0::19/64;
00178    };
00179   };
00180   ---
00181   - see 'man 5 dhcps.conf' and 'man 5 dhcpd.conf'.
00182 @endverbatim
00183 ).
00184 
00185 The dhcp_nic structure can then be configured on the network interfaces with the
00186 call:
00187 @code
00188    dhcp_nic_configure( nic );
00189 @endcode
00190 
00191 If this returns 0, all configuration parameters have been successfully applied.
00192 
00193 libdhcp contains an interface to the 'libnl' (lib NETLINK) library,
00194 ( by Thomas Graf, http://people.suug.ch/~tgr/libnl/ ), in the 
00195 "nic.[ch]" files, that implement its "Network Interface Configurator",
00196 which enables the DHCP client lease parameters to be configured on the
00197 network devices - it is also a full-featured static network configurator.
00198 
00199 For example, you can use this function:
00200 
00201 @code  
00202 extern
00203 NIC_Res_t 
00204 nic_configure
00205 (
00206     NLH_t          nh,
00207     NIC_t          nic,
00208     IPaddr_list_t  *addresses,
00209     IProute_list_t *routes,
00210     IPaddr_list_t  *dns_servers,
00211     char           *search_list,
00212     char           *host_name
00213 );
00214 @endcode
00215 
00216 to configure a list of addresses and routes on an interface ,
00217 and to configure resolv.conf and set the host name.
00218 Zero-valued pointer parameters are safely ignored.
00219 For instance, the calls :
00220 
00221 @code
00222         NIC_t nic = nic_by_name("eth0");
00223         IPaddr_t 
00224             a1 = nic_addr_from_text("172.16.80.1/22"),
00225             a2 = nic_addr_from_text("192.168.2.1/16"),
00226             a3 = nic_addr_from_text("2006:0:0:5::18/64"),
00227             gw1= nic_addr_from_text("192.168.2.254"),
00228             n2 = nic_addr_from_text("2006:0:0:6::/64"),
00229             gw2= nic_addr_from_text("2006:0:0:5::100"),
00230             ns1= nic_addr_from_text("192.168.2.200"),
00231             ns2= nic_addr_from_text("2006:0:0:5::200");
00232         int sa_len;
00233         IProute_t
00234             r1 = nic_route_new
00235                  (  nh,
00236                     nic_get_index(nic),
00237                     0,                             \/\* destination: 0 means "default" \*\/ 
00238                     32,                            \/\* destination prefix bits - 32 for default \*\/
00239                     nic_addr_sa(gw1,&sa_len),      \/\* gateway \*\/
00240                     -1,                            \/\* default scope: global \*\/
00241                     -1                          ,  \/\* no priority: increase if more than one default! \*\/
00242                     -1,                            \/\* table: default (local) \*\/
00243                     -1\/\*no iif\*\/, 0L,0\/\*no src\*\/                    
00244                   ),
00245              r2 = nic_route_new
00246                   ( nh, nic_get_index(nic), 
00247                     nic_addr_sa(n2,&sa_len), 
00248                     nic_addr_get_prefix(n2),
00249                     nic_addr_sa(gw2,&sa_len),
00250                     -1,-1,-1,-1, 0L, 0
00251                   );
00252         IPaddr_list_t 
00253              al = nic_address_list_new(a1,a2,a3,0),
00254              nl = nic_address_list_new(ns2,ns1,0);
00255         IProute_list_t
00256              rl = nic_route_list_new(r1,r2,0);
00257         nic_set_flags( nic, IFF_UP | IFF_RUNNING );
00258         nic_configure( nh, nic, al, rl, nl, "my.domain.com", "myhost");
00259 @endcode
00260 
00261 Would configure the "myhost.my.domain.com" interface eth0 with the 
00262 addresses 172.16.80.1/22, 192.168.2.1/16, and 2006:0:0:5::18/64,
00263 the default gateway 192.168.2.254, the additional route
00264 '2006:0:0:6::/64 via 2006:0:0:5::100', and DNS nameservers
00265 192.168.2.200 and 2006:0:0:5::1, IFF all goes according to
00266 plan (and you are running the program as root!).
00267 
00268 The complete details of each DHCP lease are also encapsulated in the
00269 DHCP_nic 'lease' field, including all the lease times - see 
00270 'dhcp4_lease.h' and 'dhcp6_lease.h' for details.
00271 
00272 DHCv6 does not return options of interest that are not handled by
00273 the default configurer, and there is no support in DHCPv6 for
00274 user defined options, as yet.
00275 
00276 But ISC IPv4 DHCP returns MANY options that are not handled in libdhcp,
00277 and supports user defined options, and libdhcp fully supports this also.
00278 
00279 Having obtained a DHCPv4_lease in a DHCP_nic 'nic' as nic->dhcp4_lease,
00280 you can define your own option handler:
00281 
00282 @code
00283 void dhcp4_nic_option_handler( DHCPv4_option *option, void *arg )
00284 {
00285     switch ( option->unicode )
00286     { 
00287     case DHCP_UNIVERSE:
00288         switch ( option->code )
00289         case MY_OPTION_CODE:
00290             struct my_option *opt = (void*)&(option->value);
00291             ...
00292     }
00293 }
00294 @endcode
00295 
00296 and the dhcp4_lease code will guarantee that the option is correctly
00297 laid out as a C structure according to the DHCP option format.
00298 
00299 For instance, you could have in your server dhcpd.conf and client
00300 dhclient.conf:
00301 @verbatim
00302 ' 
00303   option space redhat;
00304   option redhat.install-server code 1 = domain-name;
00305   option redhat.kickstart code 2 = string;
00306   option redhat.install-iso code 3 = string;
00307   option redhat.routes code 4 = array of { ip-address, int8, ip-address, int8, int16, int8, int32 };
00308 '
00309 @endverbatim
00310 
00311 And in the dhcpd server's dhcpd.conf:
00312 @verbatim
00313 '
00314   class "vendor-classes" {
00315          match option vendor-class-identifier;
00316        }
00317 
00318   subclass "vendor-classes" "i386-redhat-fc6" {
00319         option redhat.install-server my.i386repo.server.com;
00320         option redhat.kickstart "i386-fc6.ks";
00321   }
00322 
00323   subclass "vendor-classes" "ia64-redhat-fc6" {
00324         option redhat.install-server my.ia64repo.server.com;
00325         option redhat.kickstart "ia64-fc6.ks";
00326   }
00327   
00328   option redhat.routes 1.2.3.4 2 4.3.2.1 1 512 2 0xfabdab,
00329                        8.4.2.1 6 1.4.2.8 4 768 1 0xdabfab;
00330 
00331   option dhcp.redhat-encapsulation code 128 = encapsulate redhat;
00332 '
00333 @endverbatim
00334 
00335 And the client must be configured to request these options
00336 in dhclient.conf:
00337 @verbatim   
00338    request dhcp.redhat-encapsulation;
00339 @endverbatim
00340 
00341 Then you can define an option handler to handle these options:
00342 
00343 @code
00344 void dhcp4_nic_option_handler( DHCPv4_option *option, void *arg )
00345 {
00346     switch ( option->unicode )
00347     { 
00348     case REDHAT_UNIVERSE:
00349         switch ( option->code )
00350         case REDHAT_ROUTES:
00351             struct r_r
00352             {   
00353                u_int32_t ip1;
00354                u_int8_t   b1;   
00355                u_int32_t ip2;
00356                u_int16_t  s1;
00357                u_int8_t   b2;
00358                i_int32_t  i1;
00359             } * r = (void*) &(option->value),
00360               * e = &(((r_r*) &(option->value))[option->n_elements]);
00361             for(; r < e; r++)                           
00362                ...      
00363     }
00364 }
00365 @endcode
00366 
00367 and call the function:
00368 @code
00369      dhcpv4_process_options ( nic->lease.dhcpv4_lease, dhcp4_nic_option_handler, arg)
00370 @endcode
00371 and the dhcp4_nic_option_handler will be called for each DHCP optoin in the lease,
00372 and for the "REDHAT_ROUTES" option, the 'r_r' structure members will be correctly laid out
00373 for access by your C program.
00374 
00375 
00376 CAVEATS:
00377 
00378 ABOVE ALL: USE AT YOUR OWN RISK ! the code is very new and is still in further
00379 development and refinement. 
00380 
00381 Please report any issues / suggestions / ideas via Red Hat Bugzilla or by email
00382 to jvdias@redhat.com.
00383 /**@}*/
00384 /**
00385  * @defgroup LIBDHCP libdhcp library interface
00386  *  API for libdhcp, a minimal interface to the ISC dhcp IPv4 client library,
00387  *  libdhcp4client, and to the dhcpv6 DHCPv6 client library, libdhcp6client .
00388  * @defgroup IP Generic IP Addresses
00389  * Generic IP address representation and conversion utilities.
00390  * @defgroup DHCP DHCP Client Invocation and Control
00391  * @{
00392  * Network Interface Configurator for BOTH the ISC DHCP IPv4 client library
00393  * and the DHCPv6 IPv6 client library.
00394  * @defgroup DHCPv4 IPv4 DHCP Client Control and Configuration
00395  * @{
00396  * Network Interface Configurator for the ISC DHCP IPv4 client library.
00397  * @defgroup DHCPv4_lease IPv4 DHCP Lease Options
00398  * @defgroup
00399  * @}
00400  * @defgroup DHCPv6 IPv6 DHCP Client Control and Configuration
00401  * @{
00402  * Network Interface Configurator for the DHCPv6 IPv6 client library.
00403  * @defgroup DHCPv6_lease IPv6 DHCP Lease Options
00404  * @defgroup
00405  * @}
00406  * @defgroup
00407  * @}
00408  * @defgroup NIC Network Interface Configurator
00409  * @{
00410  *  Provides facilities for configuring network interfaces, addresses, and routes,
00411  *  with an interface to the libnl netlink library.
00412  * @defgroup NICH NIC Module Interface
00413  * NIC Module initialisation / shutdown and error logging.
00414  * @defgroup NICI Network Interfaces
00415  * Provides facilities for configuring network interface devices.
00416  * @defgroup NICA Addresses
00417  * Provides facilities for configuring addresses on network interfaces.
00418  * @defgroup NICR Routes
00419  * Provides facilities for configuring routes on network interfaces.
00420  * @defgroup NICG Global Configuration Operations
00421  * Provides facilites for configuring interfaces, address, routes, and resolver
00422  * with a single-call interface.
00423  * @defgroup
00424  * @}
00425 */

Generated on Fri Oct 13 18:20:33 2006 for libdhcp by  doxygen 1.4.7