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 );
00118 ctl -> finished = 1;
00119 break;
00120
00121 case DHC6_BOUND:
00122 case DHC6_REBIND:
00123 {
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
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 }