dhcp6_lease.c

00001 /* dhcp6_lease.c
00002  *
00003  *  Representation of DHCPv6 lease options for libdhcp
00004  *
00005  *  Copyright(C) Jason Vas Dias<jvdias@redhat.com> Red Hat Inc. May 2006
00006  *
00007  *  This program is free software; you can redistribute it and/or modify
00008  *  it under the terms of the GNU General Public License as published by
00009  *  the Free Software Foundation at 
00010  *           http://www.fsf.org/licensing/licenses/gpl.txt
00011  *  and included in this software distribution as the "LICENSE" file.
00012  *
00013  *  This program is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *  GNU General Public License for more details.
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 /* dhcpv6 includes: */
00030 
00031 #include <sys/queue.h>
00032 /* #include <queue.h> 
00033  * dhcpv6 uses an older copy of BSD queue.h, which 
00034  * is happily compatible with the new version in glibc
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 }

Generated on Thu Aug 10 22:16:40 2006 for libdhcp by  doxygen 1.4.7