dhcp6_nic.c

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

Generated on Mon Aug 14 17:25:56 2006 for libdhcp by  doxygen 1.4.7