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         );
00118         ctl -> finished = 1;
00119         break;
00120 
00121     case DHC6_BOUND:
00122     case DHC6_REBIND:
00123         {   /* record new lease */
00124             dhc6_log
00125             (   ctl, LOG_INFO, "DHCPv6 %s - BOUND", nic->name );
00126             nic->lease = dhcpv6_lease( arg );
00127             ctl -> finished = 1;    
00128         }
00129         break;
00130 
00131     case DHC6_RELEASE:
00132         /* remove existing lease */
00133         ctl -> finished = 1;
00134         break;
00135 
00136     default:
00137         dhc6_log
00138         (   ctl, LOG_DEBUG, "DHCPv6 %s - unhandled state.", nic->name );
00139     }
00140     return 0;
00141 }
00142 
00143 int dhcp6_process_lease( LIBDHCP_Control *ctl, DHCPv6_nic *nic )
00144 {
00145     if( ( nic == 0L ) || (nic->lease == 0L) ) return(0);
00146     DHCPv6_lease *lease = nic->lease;
00147     DHCPv6_lease_address *addr=0 ;
00148     char buf[128];
00149     IPaddr_t ip;
00150     IPaddr_list_node_t *n;
00151     int addresses = 0;
00152 
00153     STAILQ_FOREACH( addr, &(lease->addresses), link)
00154     {
00155         dhc6_log
00156         (   ctl, LOG_INFO, "DHCPv6 %s - lease address: %s/%d",  nic->name,
00157             inet_ntop(AF_INET6,&(addr->address),buf,sizeof(buf)),
00158             addr->prefix_length
00159         );
00160         ip_addr_t a6 = ip_addr_in6(&(addr->address)) ;
00161         ip = nic_addr(nic->nh, a6);
00162         nic_addr_set_prefix(ip, addr->prefix_length );
00163         struct ifa_cacheinfo ifa_ca = {0,0,0,0};
00164         ifa_ca.ifa_prefered = addr -> prefer_lifetime;
00165         ifa_ca.ifa_valid = addr -> valid_lifetime;
00166         nic_addr_set_cacheinfo( ip, &ifa_ca);
00167         n = calloc(1, sizeof(IPaddr_list_node_t));
00168         n->addr = ip;
00169         STAILQ_INSERT_TAIL(&(nic->address_list), n, link);
00170         addresses++;
00171     }
00172     if ( !STAILQ_EMPTY( &(lease->dns) ) )
00173     {
00174         IPv6_address *dns;
00175         STAILQ_FOREACH(dns, &(lease->dns), link)
00176         {
00177             dhc6_log
00178             (   ctl, LOG_INFO, "DHCPv6 %s - dns server address: %s", nic->name,
00179                 inet_ntop(AF_INET6,&(dns->address),buf,sizeof(buf))
00180             );
00181             ip_addr_t a6 = ip_addr_in6(&(dns->address)) ;
00182             ip = nic_addr(nic->nh, a6);
00183             n = calloc(1, sizeof(IPaddr_list_node_t));
00184             n->addr = ip;                   
00185             STAILQ_INSERT_TAIL(&(nic->dns_list), n, link);
00186         }
00187     }
00188     if ( lease->search_list )
00189     {
00190         dhc6_log
00191         (   ctl, LOG_INFO, "DHCPv6 %s - dns search_path: %s",   nic->name,
00192             lease->search_list
00193         );
00194         nic->search_list = strdup( lease->search_list );                
00195     }
00196     return addresses;
00197 }
00198 
00199 void dhcpv6_nic_free( DHCPv6_nic* nic6 )
00200 {
00201     if( nic6->lease )
00202     {
00203         dhcpv6_lease_free( nic6->lease );
00204         nic6->lease = 0;
00205     }
00206     if( ! STAILQ_EMPTY( &(nic6->address_list) ) )
00207         nic_address_list_free( &(nic6->address_list) );
00208     if( ! STAILQ_EMPTY( &(nic6->dns_list) ) )
00209         nic_address_list_free( &(nic6->dns_list) );
00210     if( nic6->search_list )
00211         free( nic6->search_list );
00212     if( nic6->name)
00213         free(nic6->name);
00214     free(nic6);
00215 }

Generated on Thu Aug 10 22:16:40 2006 for libdhcp by  doxygen 1.4.7