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