dhcp6_lease.c

00001 /* dhcp6_lease.c
00002  *
00003  *  Representation of DHCPv6 lease options for libdhcp
00004  *
00005  * Copyright (C) 2006  Red Hat, Inc. All rights reserved.
00006  *
00007  * This copyrighted material is made available to anyone wishing to use,
00008  * modify, copy, or redistribute it subject to the terms and conditions of
00009  * the GNU General Public License v.2.  This program is distributed in the
00010  * hope that it will be useful, but WITHOUT ANY WARRANTY expressed or
00011  * implied, including the implied warranties of MERCHANTABILITY or FITNESS
00012  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
00013  * details.  You should have received a copy of the GNU General Public
00014  * License along with this program; if not, write to the Free Software
00015  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
00016  * USA. Any Red Hat trademarks that are incorporated in the source code or
00017  * documentation are not subject to the GNU General Public License and may
00018  * only be used or replicated with the express permission of Red Hat, Inc.
00019  *
00020  * Red Hat Author(s): Jason Vas Dias
00021  *                    David Cantrell
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 /* dhcpv6 includes: */
00035 
00036 #include <sys/queue.h>
00037 /* #include <queue.h> 
00038  * dhcpv6 uses an older copy of BSD queue.h, which 
00039  * is happily compatible with the new version in glibc
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 }

Generated on Fri Oct 13 18:20:33 2006 for libdhcp by  doxygen 1.4.7