00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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 {
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),
00095 &(nic6->dns_list),
00096 nic6->search_list,
00097 0
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 {
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
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 }