00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <sys/types.h>
00025 #include <unistd.h>
00026 #include <sys/socket.h>
00027 #include <arpa/inet.h>
00028 #include <net/if.h>
00029 #include <resolv.h>
00030 #include <string.h>
00031 #include <time.h>
00032 #include <stdio.h>
00033
00034
00035
00036 #include <sys/queue.h>
00037
00038
00039
00040
00041 #define LIBDHCP
00042 #include <dhcpv6/dhcp6.h>
00043 #include <dhcpv6/config.h>
00044 #include <dhcpv6/lease.h>
00045 #undef malloc
00046 #undef realloc
00047 #undef calloc
00048 #undef free
00049 #undef strdup
00050 #include <malloc.h>
00051 #include <dhcp6_lease.h>
00052
00053
00054 DHCPv6_lease *dhcpv6_lease( struct dhcp6_optinfo *optinfo )
00055 {
00056 if ( TAILQ_EMPTY( &(client6_iaidaddr.lease_list) ) )
00057 return 0L;
00058
00059 DHCPv6_lease *lease = calloc(1, sizeof(DHCPv6_lease));
00060
00061 if( lease == 0L )
00062 return 0;
00063
00064 STAILQ_INIT(&(lease->addresses));
00065 STAILQ_INIT(&(lease->dns));
00066
00067 struct dhcp6_lease *l;
00068 for (l = TAILQ_FIRST( &(client6_iaidaddr.lease_list) ); l; l = TAILQ_NEXT(l,link))
00069 {
00070 if( ( l->state == DHCP6_ACTIVE )
00071 && ( l->lease_addr.type != DHCPv6_DELEGATED_PREFIX )
00072 && ( ( l->lease_addr.status_code == DH6OPT_STCODE_SUCCESS )
00073 ||( l->lease_addr.status_code == DH6OPT_STCODE_UNDEFINE )
00074 )
00075 )
00076 {
00077 DHCPv6_lease_address *addr = calloc(1, sizeof( DHCPv6_lease_address ) );
00078 if( addr == 0 )
00079 goto dhcpv6_lease_failure;
00080
00081 memcpy(&(addr->address), &(l->lease_addr.addr), sizeof(struct in6_addr));
00082
00083 addr -> prefix_length = l->lease_addr.plen;
00084 addr -> type = l->lease_addr.type;
00085 addr -> status = l->lease_addr.status_code;
00086 addr -> time_acquired = l->start_date;
00087 addr -> prefer_lifetime = l->lease_addr.preferlifetime;
00088 addr -> valid_lifetime = l->lease_addr.validlifetime;
00089
00090 STAILQ_INSERT_TAIL( &(lease->addresses), addr, link );
00091 }
00092 }
00093
00094 lease->rebind_time = client6_iaidaddr.client6_info.iaidinfo.rebindtime;
00095 lease->renew_time = client6_iaidaddr.client6_info.iaidinfo.renewtime;
00096 lease->iaid = client6_iaidaddr.client6_info.iaidinfo.iaid;
00097 lease->client_duid = malloc(client6_iaidaddr.client6_info.clientid.duid_len );
00098 if( lease->client_duid == 0L )
00099 goto dhcpv6_lease_failure;
00100 memcpy(lease->client_duid, client6_iaidaddr.client6_info.clientid.duid_id,
00101 client6_iaidaddr.client6_info.clientid.duid_len);
00102 lease->client_duid_len = client6_iaidaddr.client6_info.clientid.duid_len;
00103 lease->server_duid = malloc(client6_iaidaddr.client6_info.serverid.duid_len );
00104 lease->server_duid_len = client6_iaidaddr.client6_info.serverid.duid_len;
00105 if( lease->server_duid == 0L )
00106 goto dhcpv6_lease_failure;
00107 memcpy(lease->server_duid, client6_iaidaddr.client6_info.serverid.duid_id,
00108 client6_iaidaddr.client6_info.serverid.duid_len);
00109 memcpy(&(lease->server_address), &(optinfo->server_addr), sizeof(struct in6_addr) );
00110 if( (lease->if_name = strdup( client6_iaidaddr.ifp->ifname )) == 0L )
00111 goto dhcpv6_lease_failure;
00112 lease->if_index = if_nametoindex( lease->if_name );
00113
00114 if ( ! TAILQ_EMPTY( &(optinfo -> dns_list.addrlist) ) )
00115 {
00116 struct dhcp6_listval *v;
00117 IPv6_address *dns;
00118 int i=0;
00119 for (v = TAILQ_FIRST(&(optinfo->dns_list.addrlist)); v && (i < MAXNS); v = TAILQ_NEXT(v, link), i++)
00120 {
00121 dns = calloc(1, sizeof(IPv6_address));
00122 if( dns == 0L )
00123 goto dhcpv6_lease_failure;
00124 memcpy(&(dns->address), &(v->val_addr6), sizeof(struct in6_addr));
00125 STAILQ_INSERT_TAIL(&(lease->dns), dns, link);
00126 }
00127 }
00128 if ( optinfo -> dns_list.domainlist != 0 )
00129 {
00130 int i=0, len;
00131 struct domain_list *dlist;
00132 char search_list[256], *p=search_list;
00133 for (dlist = optinfo->dns_list.domainlist; dlist && (i < MAXDNSRCH); dlist = dlist->next, i++)
00134 {
00135 len = strlen(dlist->name);
00136 if ( (len + 1 + (p - search_list)) >= sizeof(search_list) )
00137 break;
00138 p += sprintf(p,"%s ", dlist->name);
00139 }
00140 if( p - search_list )
00141 if( ( lease->search_list = strdup(search_list) ) == 0L )
00142 goto dhcpv6_lease_failure;
00143 }
00144
00145 return lease;
00146
00147 dhcpv6_lease_failure:
00148 dhcpv6_lease_free( lease );
00149 return 0L;
00150 }
00151
00152 void dhcpv6_lease_free( DHCPv6_lease *lease )
00153 {
00154 if( !STAILQ_EMPTY(&(lease->addresses)) )
00155 {
00156 DHCPv6_lease_address *addr = STAILQ_FIRST( &(lease->addresses) ), *next;
00157 do
00158 {
00159 next = STAILQ_NEXT(addr, link);
00160 free( addr );
00161 addr = next;
00162 } while ( addr );
00163 }
00164 if ( !STAILQ_EMPTY( &(lease->dns) ) )
00165 {
00166 IPv6_address *addr = STAILQ_FIRST( &(lease->dns) ), *next;
00167 do
00168 {
00169 next = STAILQ_NEXT(addr, link);
00170 free( addr );
00171 addr = next;
00172 } while ( addr );
00173 }
00174 if ( lease->search_list )
00175 free(lease->search_list);
00176 if ( lease->if_name )
00177 free(lease->if_name);
00178 if ( lease->client_duid )
00179 free(lease->client_duid);
00180 if ( lease->server_duid )
00181 free(lease->server_duid);
00182 free(lease);
00183 }
00184
00185 #define DHC_PAD( type, total_length ) ( ( sizeof(type) - (total_length & (sizeof(type)-1) ) ) & (sizeof(type)-1) )
00186
00187 int dhcpv6_pack_lease( DHCPv6_lease* lease, uint8_t* buf, uint32_t len)
00188 {
00189 if( lease == 0 ) return 0;
00190
00191 uint8_t *bufp = buf ;
00192
00193 if( buf != 0 )
00194 *((uint32_t*)buf) = len;
00195
00196 bufp += sizeof(uint32_t);
00197
00198 if( buf != 0 )
00199 memcpy(bufp, lease, sizeof(DHCPv6_lease));
00200
00201 bufp += sizeof( DHCPv6_lease ) + DHC_PAD(uint32_t, sizeof(DHCPv6_lease));
00202
00203 uint32_t *n_addrs = (uint32_t*)bufp;
00204
00205 bufp += sizeof( uint32_t);
00206
00207 if ( !STAILQ_EMPTY( &(lease->addresses) ) )
00208 {
00209 DHCPv6_lease_address *addr = 0;
00210 if( buf )
00211 *n_addrs = 0;
00212 STAILQ_FOREACH( addr, &(lease->addresses), link )
00213 {
00214 if( buf )
00215 {
00216 ++(*n_addrs);
00217 memcpy(bufp, addr, sizeof(DHCPv6_lease_address));
00218 }
00219 bufp += sizeof(DHCPv6_lease_address) + DHC_PAD(uint32_t, sizeof(DHCPv6_lease_address));
00220 }
00221 }
00222 n_addrs = (uint32_t*)bufp;
00223 bufp += sizeof(uint32_t);
00224 if ( !STAILQ_EMPTY( &(lease->dns) ) )
00225 {
00226 IPv6_address *addr;
00227
00228 if( buf )
00229 *n_addrs = 0;
00230 STAILQ_FOREACH( addr, &(lease->dns), link )
00231 {
00232 if(buf)
00233 {
00234 ++(*n_addrs);
00235 memcpy(bufp, addr, sizeof(IPv6_address));
00236 }
00237 bufp += sizeof(IPv6_address) + DHC_PAD(uint32_t,sizeof(IPv6_address));
00238 }
00239 }
00240
00241 uint32_t search_list_len = lease->search_list ? strlen(lease->search_list) : 0,
00242 if_name_len = lease->if_name ? strlen(lease->if_name) : 0;
00243
00244 if(buf)
00245 *((uint32_t*)bufp) = search_list_len;
00246 bufp += sizeof(uint32_t);
00247 if( search_list_len )
00248 {
00249 if(buf)
00250 memcpy(bufp, lease->search_list, search_list_len);
00251 bufp += search_list_len + DHC_PAD(uint32_t,search_list_len);
00252 }
00253 if(buf)
00254 *((uint32_t*)bufp) = if_name_len;
00255 bufp += sizeof(uint32_t);
00256 if( if_name_len )
00257 {
00258 if( buf )
00259 memcpy(bufp, lease->if_name, if_name_len);
00260 bufp += if_name_len + DHC_PAD(uint32_t, if_name_len);
00261 }
00262 if( buf )
00263 memcpy(bufp, lease->client_duid, lease->client_duid_len);
00264 bufp += lease->client_duid_len;
00265 if( buf )
00266 memcpy(bufp, lease->server_duid, lease->server_duid_len);
00267 bufp += lease->server_duid_len;
00268 return (bufp - buf);
00269 }
00270
00271 DHCPv6_lease *dhcpv6_unpack_lease( uint8_t* buf )
00272 {
00273 if ( buf == 0 )
00274 return 0;
00275
00276 uint8_t *bufp = buf;
00277 uint32_t len = *((uint32_t*) bufp);
00278
00279 if( len < sizeof(DHCPv6_lease) )
00280 return 0L;
00281
00282 bufp += sizeof(uint32_t);
00283
00284 DHCPv6_lease *lease;
00285
00286 lease = calloc(1, sizeof(DHCPv6_lease));
00287
00288 memcpy(lease, bufp, sizeof( DHCPv6_lease ) );
00289
00290 lease->search_list = 0;
00291 lease->if_name = 0;
00292 lease->client_duid=0;
00293 lease->server_duid=0;
00294 STAILQ_INIT(&(lease->addresses));
00295 STAILQ_INIT(&(lease->dns));
00296
00297 bufp += sizeof( DHCPv6_lease ) + DHC_PAD(uint32_t, sizeof(DHCPv6_lease));
00298
00299 uint32_t *n_addrs =(uint32_t*) bufp;
00300
00301 bufp += sizeof(uint32_t);
00302
00303 if ( *n_addrs )
00304 {
00305 DHCPv6_lease_address *addr=0;
00306 int n = *n_addrs;
00307 for(; n ; --n)
00308 {
00309 addr = calloc(1, sizeof(DHCPv6_lease_address));
00310 memcpy(addr, bufp, sizeof(DHCPv6_lease_address));
00311 memset(&(addr->link),'\0',sizeof(addr->link));
00312 STAILQ_INSERT_TAIL(&(lease->addresses), addr, link);
00313 bufp += sizeof(DHCPv6_lease_address) + DHC_PAD(uint32_t, sizeof(DHCPv6_lease_address));
00314 }
00315 }
00316 n_addrs = (uint32_t*)bufp;
00317 bufp += sizeof(uint32_t);
00318 if( *n_addrs )
00319 {
00320 IPv6_address *addr=0;
00321 int n = *n_addrs;
00322 for(; n ; --n)
00323 {
00324 addr = calloc(1, sizeof(IPv6_address));
00325 memcpy(addr, bufp, sizeof(IPv6_address));
00326 memset(&(addr->link),'\0',sizeof(addr->link));
00327 STAILQ_INSERT_TAIL(&(lease->dns), addr, link);
00328 bufp += sizeof(IPv6_address) + DHC_PAD(uint32_t, sizeof(IPv6_address));
00329 }
00330 }
00331
00332 uint32_t search_list_len = *((uint32_t*)bufp);
00333
00334 bufp += sizeof(uint32_t);
00335
00336 if( search_list_len )
00337 {
00338 lease->search_list = calloc(1, search_list_len);
00339 memcpy( lease->search_list, bufp, search_list_len );
00340 bufp += search_list_len + DHC_PAD(uint32_t,search_list_len);
00341 }
00342
00343 uint32_t if_name_len = *((uint32_t*)bufp);
00344
00345 bufp += sizeof(uint32_t);
00346
00347 if( if_name_len )
00348 {
00349 lease->if_name = calloc(1, if_name_len);
00350 memcpy(lease->if_name, bufp, if_name_len);
00351 bufp += if_name_len + DHC_PAD(uint32_t, if_name_len);
00352 }
00353
00354 if( lease->client_duid_len )
00355 {
00356 lease->client_duid = calloc(1, lease->client_duid_len);
00357 memcpy(lease->client_duid, bufp, lease->client_duid_len);
00358 bufp += lease->client_duid_len;
00359 }
00360
00361 if( lease->server_duid_len )
00362 {
00363 lease->server_duid = calloc(1, lease->server_duid_len);
00364 memcpy(lease->server_duid, bufp, lease->server_duid_len);
00365 bufp += lease->server_duid_len;
00366 }
00367
00368 return lease;
00369 }