dhcp6_nic.c

00001 /* dhcp6_nic.c
00002  *
00003  * Network Interface Configurator for the DHCPv6 IPv6 DHCP client library.
00004  *
00005  *  Copyright(C) Jason Vas Dias <jvdias@redhat.com> Red Hat Inc. May 2006
00006  *
00007  *  This program is free software; you can redistribute it and/or modify
00008  *  it under the terms of the GNU General Public License as published by
00009  *  the Free Software Foundation at 
00010  *           http://www.fsf.org/licensing/licenses/gpl.txt
00011  *  and included in this software distribution as the "LICENSE" file.
00012  *
00013  *  This program is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *  GNU General Public License for more details.
00017  */
00018 #include <sys/types.h>
00019 #include <unistd.h>
00020 #include <string.h>
00021 #include <netinet/in.h>
00022 #include <arpa/inet.h>
00023 #include <sys/socket.h>
00024 #include <linux/rtnetlink.h>
00025 #include <malloc.h>
00026 #include <stdio.h>
00027 
00028 #include <dhcp6_nic.h>
00029 extern int dhcpv6_client(LIBDHCP_Control *dhc_ctl, int argc, char **argv, char **envp);
00030 
00031 static void
00032 dhc6_log( LIBDHCP_Control *ctl, int priority, char *fmt, ...)
00033 {
00034     va_list va;
00035     va_start(va, fmt);
00036     ctl->eh(ctl, priority, fmt, va);
00037     va_end(va);
00038 }
00039 
00040 extern char **environ;
00041 
00042 DHCPv6_nic *do_dhcpv6
00043 (   LIBDHCP_Control *ctl, NLH_t nh, char *if_name   )
00044 {
00045     DHCPv6_nic *nic6 = calloc(1, sizeof(DHCPv6_nic));
00046     ctl->arg = nic6;
00047     nic6->nh = nh;
00048     nic6->nic = nic_by_name(nh, if_name);
00049     nic6->name= strdup(if_name);
00050     dhc6_log(ctl, LOG_INFO,"DHCPv6: NIC: %p %s %p", nic6, if_name, nic6->nic);
00051     STAILQ_INIT(&(nic6->address_list));
00052     STAILQ_INIT(&(nic6->route_list));
00053     STAILQ_INIT(&(nic6->dns_list));
00054     ctl->arg = nic6;
00055     libdhcp_call_client
00056     (  ctl, dhcpv6_client, "dhcp6c",
00057        "-Df", if_name, 0 
00058     );
00059     if( nic6->lease == 0 )
00060     { /* empty lease / failed to contact server */
00061         dhcpv6_nic_free(nic6);
00062         ctl->arg = 0;
00063         return 0;
00064     }
00065     return nic6;
00066 }
00067 
00068 DHCPv6_nic *dhcp6_nic_from_lease( LIBDHCP_Control *ctl, NLH_t nh, DHCPv6_lease *lease, NIC_t nic )
00069 {
00070     DHCPv6_nic *nic6 = calloc(1, sizeof(DHCPv6_nic));
00071     ctl->arg = nic6;
00072     nic6->nh = nh;
00073     nic6->nic = nic;
00074     nic6->name= strdup(nic_get_name(nic));
00075     STAILQ_INIT(&(nic6->address_list));
00076     STAILQ_INIT(&(nic6->route_list));
00077     STAILQ_INIT(&(nic6->dns_list));
00078     nic6->lease = lease;
00079     return nic6;
00080 }
00081 
00082 NIC_Res_t dhcpv6_nic( DHCPv6_nic *nic6 )
00083 {
00084     return 
00085         nic_configure
00086         (   nic6->nh,
00087             nic6->nic,
00088             &(nic6->address_list),
00089             &(nic6->route_list), /* no routes configured by DHCPv6 - for that, use radvd! */
00090             &(nic6->dns_list),
00091             nic6->search_list,
00092             0 /* no host name set - use host(1) to query PTR */
00093         );
00094 }
00095 
00096 extern
00097 int dhcp6_nic_callback
00098 (   LIBDHCP_Control *ctl,
00099     DHCP_State state, 
00100     void *arg
00101 )
00102 {
00103     DHCPv6_nic *nic = ctl->arg;
00104     char buf[64];
00105 
00106     dhc6_log
00107     (   ctl, LOG_INFO, "DHCPv6 %s - state: %s",
00108         nic->name,
00109         libdhcp_state_string(state,buf)
00110     );
00111 
00112     switch (state)
00113     {
00114     case DHC_TIMEDOUT:
00115         dhc6_log
00116         (   ctl, LOG_ERR, "DHCPv6 %s - TIMED OUT - failure.", nic->name,
00117             libdhcp_state_string(state,buf)
00118         );
00119         ctl -> finished = 1;
00120         break;
00121 
00122     case DHC6_BOUND:
00123     case DHC6_REBIND:
00124         {   /* record new lease */
00125             dhc6_log
00126             (   ctl, LOG_INFO, "DHCPv6 %s - BOUND", nic->name );
00127             nic->lease = dhcpv6_lease( arg );
00128             ctl -> finished = 1;    
00129         }
00130         break;
00131 
00132     case DHC6_RELEASE:
00133         /* remove existing lease */
00134         ctl -> finished = 1;
00135         break;
00136 
00137     default:
00138         dhc6_log
00139         (   ctl, LOG_DEBUG, "DHCPv6 %s - unhandled state.", nic->name );
00140     }
00141     return 0;
00142 }
00143 
00144 int dhcp6_process_lease( LIBDHCP_Control *ctl, DHCPv6_nic *nic )
00145 {
00146     if( ( nic == 0L ) || (nic->lease == 0L) ) return(0);
00147     DHCPv6_lease *lease = nic->lease;
00148     DHCPv6_lease_address *addr=0 ;
00149     char buf[128];
00150     IPaddr_t ip;
00151     IPaddr_list_node_t *n;
00152     int addresses = 0;
00153 
00154     STAILQ_FOREACH( addr, &(lease->addresses), link)
00155     {
00156         dhc6_log
00157         (   ctl, LOG_INFO, "DHCPv6 %s - lease address: %s/%d",  nic->name,
00158             inet_ntop(AF_INET6,&(addr->address),buf,sizeof(buf)),
00159             addr->prefix_length
00160         );
00161         ip_addr_t a6 = ip_addr_in6(&(addr->address)) ;
00162         ip = nic_addr(nic->nh, a6);
00163         nic_addr_set_prefix(ip, addr->prefix_length );
00164         struct ifa_cacheinfo ifa_ca = {0,0,0,0};
00165         ifa_ca.ifa_prefered = addr -> prefer_lifetime;
00166         ifa_ca.ifa_valid = addr -> valid_lifetime;
00167         nic_addr_set_cacheinfo( ip, &ifa_ca);
00168         n = calloc(1, sizeof(IPaddr_list_node_t));
00169         n->addr = ip;
00170         STAILQ_INSERT_TAIL(&(nic->address_list), n, link);
00171         addresses++;
00172     }
00173     if ( !STAILQ_EMPTY( &(lease->dns) ) )
00174     {
00175         IPv6_address *dns;
00176         STAILQ_FOREACH(dns, &(lease->dns), link)
00177         {
00178             dhc6_log
00179             (   ctl, LOG_INFO, "DHCPv6 %s - dns server address: %s", nic->name,
00180                 inet_ntop(AF_INET6,&(dns->address),buf,sizeof(buf))
00181             );
00182             ip_addr_t a6 = ip_addr_in6(&(dns->address)) ;
00183             ip = nic_addr(nic->nh, a6);
00184             n = calloc(1, sizeof(IPaddr_list_node_t));
00185             n->addr = ip;                   
00186             STAILQ_INSERT_TAIL(&(nic->dns_list), n, link);
00187         }
00188     }
00189     if ( lease->search_list )
00190     {
00191         dhc6_log
00192         (   ctl, LOG_INFO, "DHCPv6 %s - dns search_path: %s",   nic->name,
00193             lease->search_list
00194         );
00195         nic->search_list = strdup( lease->search_list );                
00196     }
00197     return addresses;
00198 }
00199 
00200 void dhcpv6_nic_free( DHCPv6_nic* nic6 )
00201 {
00202     if( nic6->lease )
00203     {
00204         dhcpv6_lease_free( nic6->lease );
00205         nic6->lease = 0;
00206     }
00207     if( ! STAILQ_EMPTY( &(nic6->address_list) ) )
00208         nic_address_list_free( &(nic6->address_list) );
00209     if( ! STAILQ_EMPTY( &(nic6->dns_list) ) )
00210         nic_address_list_free( &(nic6->dns_list) );
00211     if( nic6->search_list )
00212         free( nic6->search_list );
00213     if( nic6->name)
00214         free(nic6->name);
00215     free(nic6);
00216 }

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