00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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 {
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),
00090 &(nic6->dns_list),
00091 nic6->search_list,
00092 0
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 {
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
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 }