xcast.c

00001 /* Copyright 2008 Michael Marsh, University of Maryland.
00002  *
00003  * This file is part of pydtn.
00004  *
00005  * pydtn is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation, either version 3 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * pydtn is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with pydtn.  If not, see <http://www.gnu.org/licenses/>.
00017  *
00018  * The views and conclusions contained in the software and documentation
00019  * are those of the authors and should not be interpreted as representing
00020  * official policies, either expressed or implied, of the University
00021  * of Maryland.
00022  *
00023  * pydtn extends and embeds the Python interpreter, which is
00024  * Copyright 2001-2006 Python Software Foundation, All Rights Reserved,
00025  * and is released under the PSF License Agreement.
00026  *
00027  * RANLUX random number generation uses the Boost library,
00028  * Copyright 1994-2006 by various authors (details in individual files),
00029  * which is released under the Boost Software License, Version 1.0.
00030  */
00031 
00032 #include <netinet/in.h>
00033 #include <string.h>
00034 #include "aodv.h"
00035 
00036 static int
00037 _put8( unsigned char** pData, unsigned int* pLength, uint8_t b )
00038 {
00039    if ( *pLength < 1 )
00040    {
00041       return 0;
00042    }
00043    if ( NULL == pData )
00044    {
00045       return 0;
00046    }
00047    if ( NULL == *pData )
00048    {
00049       return 0;
00050    }
00051 
00052    (*pData)[0] = b;
00053    *pData += 1;
00054    *pLength -= 1;
00055    return 1;
00056 }
00057 
00058 static int
00059 _put16( unsigned char** pData, unsigned int* pLength, uint16_t s )
00060 {
00061    unsigned char* data;
00062    union
00063    {
00064          uint16_t s;
00065          unsigned char c[2];
00066    } temp;
00067 
00068    if ( *pLength < 2 )
00069    {
00070       return 0;
00071    }
00072    if ( NULL == pData )
00073    {
00074       return 0;
00075    }
00076    if ( NULL == *pData )
00077    {
00078       return 0;
00079    }
00080    data = *pData;
00081 
00082    temp.s = s;
00083    data[0] = temp.c[0];
00084    data[1] = temp.c[1];
00085 
00086    *pData += 2;
00087    *pLength -= 2;
00088    return 1;
00089 }
00090 
00091 static int
00092 _put32( unsigned char** pData, unsigned int* pLength, uint32_t l )
00093 {
00094    unsigned char* data;
00095    union
00096    {
00097          uint32_t l;
00098          unsigned char c[4];
00099    } temp;
00100 
00101    if ( *pLength < 4 )
00102    {
00103       return 0;
00104    }
00105    if ( NULL == pData )
00106    {
00107       return 0;
00108    }
00109    if ( NULL == *pData )
00110    {
00111       return 0;
00112    }
00113    data = *pData;
00114 
00115    temp.l = l;
00116    data[0] = temp.c[0];
00117    data[1] = temp.c[1];
00118    data[2] = temp.c[2];
00119    data[3] = temp.c[3];
00120 
00121    *pData += 4;
00122    *pLength -= 4;
00123    return 1;
00124 }
00125 
00126 static int
00127 _put_addr( unsigned char** pData, unsigned int* pLength, const aodv_addr_t* a )
00128 {
00129    if ( NULL == pData ) return 0;
00130    if ( NULL == *pData ) return 0;
00131    if ( NULL == pLength ) return 0;
00132    if ( NULL == a ) return 0;
00133    if ( NULL == a->data ) return 0;
00134    if ( 0 == a->length ) return 0;
00135    if ( *pLength < (2+a->length) ) return 0;
00136 
00137    _put16( pData, pLength, htons(a->length) );
00138    memcpy( *pData, a->data, a->length );
00139    *pData += a->length;
00140    *pLength -= a->length;
00141 
00142    return 1;
00143 }
00144 
00145 static aodv_chunk_t*
00146 _serialize_rreq( const aodv_rreq_t* rreq )
00147 {
00148    unsigned char* pData;
00149    aodv_chunk_t* retval = NULL;
00150    aodv_chunk_t* tail;
00151    aodv_node_list_t* ncurr;
00152    unsigned int length;
00153    uint16_t flags = 0;
00154 
00155    /* first chunk -- fixed size data */
00156    length = 1 + sizeof(uint16_t) + sizeof(unsigned char) + sizeof(uint32_t);
00157    retval = new_aodv_chunk( length );
00158    if ( NULL == retval )
00159    {
00160       return NULL;
00161    }
00162    pData = retval->data;
00163    _put8( &pData, &length, 1 );
00164 
00165    if ( rreq->dest_only_flag) flags |= kAodvRreqD;
00166    if ( rreq->grat_rrep_flag) flags |= kAodvRreqG;
00167    _put16( &pData, &length, htons(flags) );
00168    _put8( &pData, &length, rreq->hop_count );
00169    _put32( &pData, &length, htonl(rreq->rreq_id) );
00170    tail = retval;
00171 
00172    /* second chunk -- destination information */
00173    length =
00174       sizeof(uint16_t) +
00175       rreq->destination.length*sizeof(unsigned char) +
00176       sizeof(uint32_t);
00177    tail->next = new_aodv_chunk( length );
00178    if ( NULL == tail->next )
00179    {
00180       return NULL;
00181    }
00182    tail = tail->next;
00183    pData = tail->data;
00184    _put_addr(&pData,&length,&(rreq->destination));
00185    _put32(&pData,&length,htonl(rreq->dest_seq));
00186 
00187    /* third chunk -- originator information */
00188    length =
00189       sizeof(uint16_t) +
00190       rreq->originator.length*sizeof(unsigned char) +
00191       sizeof(uint32_t);
00192    tail->next = new_aodv_chunk( length );
00193    if ( NULL == tail->next )
00194    {
00195       return NULL;
00196    }
00197    tail = tail->next;
00198    pData = tail->data;
00199    _put_addr(&pData,&length,&(rreq->originator));
00200    _put32(&pData,&length,htonl(rreq->orig_seq));
00201 
00202    /* additional chunks -- path information */
00203    ncurr = rreq->path;
00204    if ( NULL != ncurr )
00205    {
00206       do
00207       {
00208          length =
00209             sizeof(uint16_t) +
00210             ncurr->node.length*sizeof(unsigned char) +
00211             sizeof(uint32_t);
00212          tail->next = new_aodv_chunk( length );
00213          if ( NULL == tail->next )
00214          {
00215             return NULL;
00216          }
00217          tail = tail->next;
00218          pData = tail->data;
00219          _put_addr(&pData,&length,&(ncurr->node));
00220          _put32(&pData,&length,htonl(ncurr->seq));
00221          ncurr = ncurr->next;
00222       } while ( ncurr != rreq->path );
00223    }
00224 
00225    /* collapse into a single chunk */
00226    tail = retval;
00227    retval = collapse_chunk( tail );
00228 
00229    return retval;
00230 }
00231 
00238 void
00239 aodv_bcast_rreq( aodv_state_t* state, const aodv_rreq_t* request )
00240 {
00241    aodv_chunk_t*  msg;
00242    aodv_msghdr_t  hdrs;
00243    unsigned int      i;
00244 
00245    if ( NULL == state ) return;
00246    if ( NULL == state->interfaces.interfaces ) return;
00247 
00248    aodv_set_bcast_addr( &(hdrs.addr) );
00249    hdrs.ttl  = state->params.net_diameter;
00250 
00251    msg = _serialize_rreq( request );
00252    if ( NULL == msg ) return;
00253 
00254    aodv_log_rreq_s( state, request, &hdrs );
00255 
00256    for ( i = 0 ; i < state->interfaces.nifaces ; ++i )
00257    {
00258       hdrs.interface = state->interfaces.interfaces[i];
00259       aodv_send_message( state, &hdrs, msg );
00260    }
00261 
00262    free_aodv_chunk( msg );
00263 }
00264 
00265 
00266 static aodv_chunk_t*
00267 _serialize_rrep( const aodv_rrep_t* rrep )
00268 {
00269    unsigned char* pData;
00270    aodv_chunk_t* retval = NULL;
00271    aodv_node_list_t* ncurr;
00272    unsigned int length = k_aodv_rrep_min_len;
00273    uint16_t flags = 0;
00274    unsigned int i;
00275 
00276    length += rrep->destination.addr.length + rrep->originator.length;
00277    ncurr = rrep->path;
00278    if ( NULL != ncurr )
00279    {
00280       do
00281       {
00282          length += 6 + ncurr->node.length;
00283          ncurr = ncurr->next;
00284       } while ( ncurr != rrep->path );
00285    }
00286 
00287    retval = new_aodv_chunk( length );
00288    if ( NULL == retval )
00289    {
00290       return NULL;
00291    }
00292 
00293    pData = retval->data;
00294    _put8( &pData, &length, 2 );
00295 
00296    if ( rrep->ack_flag) flags |= kAodvRrepA;
00297    for ( i = 0 ; i < 5 ; ++i )
00298    {
00299       if (rrep->destination.prefix & (1<<i))
00300       {
00301          flags |= (1 << i);
00302       }
00303       if (rrep->apn_count & (1<<i))
00304       {
00305          flags |= (1 << (i+5));
00306       }
00307    }
00308    _put16( &pData, &length, htons(flags) );
00309 
00310    _put8( &pData, &length, rrep->hop_count );
00311 
00312    _put_addr( &pData, &length, &(rrep->destination.addr) );
00313    _put32( &pData, &length, htonl(rrep->dest_seq) );
00314    _put_addr( &pData, &length, &(rrep->originator) );
00315    _put32( &pData, &length, htonl(rrep->orig_seq) );
00316 
00317    ncurr = rrep->path;
00318    if ( NULL != ncurr )
00319    {
00320       do
00321       {
00322          _put_addr( &pData, &length, &(ncurr->node) );
00323          _put32( &pData, &length, htonl(ncurr->seq) );
00324          ncurr = ncurr->next;
00325       } while ( ncurr != rrep->path );
00326    }
00327 
00328    return retval;
00329 }
00330 
00337 void
00338 aodv_unicast_rrep( aodv_state_t* state, const aodv_rrep_t* response )
00339 {
00340    aodv_chunk_t*  msg;
00341    aodv_msghdr_t  hdrs;
00342 
00343    const aodv_node_list_t*  selfnode;
00344    aodv_table_entry_t*      next_hop;
00345 
00346    if ( NULL == state ) return;
00347    if ( NULL == response ) return;
00348 
00349    hdrs.addr.data = NULL;
00350    hdrs.addr.length = 0U;
00351 
00352    selfnode = aodv_find_in_node_list( response->path, &(state->self) );
00353    if ( ( NULL == selfnode ) ||
00354         ( selfnode == selfnode->prev ) )
00355    {
00356       next_hop = aodv_lookup( &(state->routing_table),
00357                               &(response->originator) );
00358       if ( NULL == next_hop ) return;
00359       set_aodv_addr( &(hdrs.addr), &(next_hop->next_hop) );
00360       hdrs.interface = next_hop->interface;
00361    }
00362    else
00363    {
00364       set_aodv_addr( &(hdrs.addr), &(selfnode->prev->node) );
00365       next_hop = aodv_lookup( &(state->routing_table), &(hdrs.addr) );
00366       if ( NULL == next_hop ) return;
00367       hdrs.interface = next_hop->interface;
00368    }
00369    hdrs.ttl = state->params.net_diameter;
00370 
00371    msg = _serialize_rrep( response );
00372    if ( NULL == msg ) return;
00373 
00374    aodv_log_rrep_s( state, response, &hdrs );
00375 
00376    aodv_send_message( state, &hdrs, msg );
00377 
00378    free_aodv_chunk( msg );
00379 }
00380 
00381 static aodv_chunk_t*
00382 _serialize_rerr( const aodv_rerr_t* rerr )
00383 {
00384    unsigned char* pData;
00385    aodv_chunk_t* retval = NULL;
00386    aodv_node_list_t* ncurr;
00387    unsigned int length = k_aodv_rerr_min_len;
00388    unsigned char ucount = 0;
00389 
00390    ncurr = rerr->unreachable;
00391    if ( NULL != ncurr )
00392    {
00393       do
00394       {
00395          ++ucount;
00396          length += 6 + ncurr->node.length;
00397          ncurr = ncurr->next;
00398       } while ( ncurr != rerr->unreachable );
00399    }
00400 
00401    if ( ucount != rerr->dest_count )
00402    {
00403       return NULL;
00404    }
00405 
00406    retval = new_aodv_chunk( length );
00407    if ( NULL == retval )
00408    {
00409       return NULL;
00410    }
00411 
00412    pData = retval->data;
00413    _put8( &pData, &length, 3 );
00414    _put16( &pData, &length, 0 );
00415    _put8( &pData, &length, rerr->dest_count );
00416 
00417    ncurr = rerr->unreachable;
00418    if ( NULL != ncurr )
00419    {
00420       do
00421       {
00422          _put_addr( &pData, &length, &(ncurr->node) );
00423          _put32( &pData, &length, htonl(ncurr->seq) );
00424          ncurr = ncurr->next;
00425       } while ( ncurr != rerr->unreachable );
00426    }
00427 
00428    return retval;
00429 }
00430 
00437 void
00438 aodv_bcast_rerr( aodv_state_t* state, const aodv_rerr_t* rerr )
00439 {
00440    aodv_chunk_t*  msg;
00441    aodv_msghdr_t  hdrs;
00442    unsigned int      i;
00443 
00444    if ( NULL == state ) return;
00445    if ( NULL == state->interfaces.interfaces ) return;
00446 
00447    aodv_set_bcast_addr( &(hdrs.addr) );
00448    hdrs.ttl  = 1;
00449 
00450    msg = _serialize_rerr( rerr );
00451    if ( NULL == msg ) return;
00452 
00453    aodv_log_rerr_s( state, rerr, &hdrs );
00454 
00455    for ( i = 0 ; i < state->interfaces.nifaces ; ++i )
00456    {
00457       hdrs.interface = state->interfaces.interfaces[i];
00458       aodv_send_message( state, &hdrs, msg );
00459    }
00460 
00461    free_aodv_chunk( msg );
00462 }
00463 
00464 static aodv_chunk_t*
00465 _serialize_rrep_ack()
00466 {
00467    unsigned char* pData;
00468    aodv_chunk_t* retval = NULL;
00469    unsigned int length = k_aodv_rrep_ack_len;
00470 
00471    retval = new_aodv_chunk( length );
00472    if ( NULL == retval )
00473    {
00474       return NULL;
00475    }
00476 
00477    pData = retval->data;
00478    _put8( &pData, &length, 4 );
00479    _put8( &pData, &length, 0 );
00480 
00481    return retval;
00482 }
00483 
00490 void
00491 aodv_unicast_rrep_ack( aodv_state_t* state,
00492                        const aodv_msghdr_t* inhdrs )
00493 {
00494    aodv_chunk_t*  msg;
00495    aodv_msghdr_t  hdrs;
00496 
00497    if ( NULL == state ) return;
00498    if ( NULL == inhdrs ) return;
00499 
00500    hdrs.addr.length = 0;
00501    hdrs.addr.data = NULL;
00502    set_aodv_addr( &(hdrs.addr), &(inhdrs->addr) );
00503 
00504    hdrs.interface = inhdrs->interface;
00505    hdrs.ttl       = 1;
00506 
00507    msg = _serialize_rrep_ack();
00508    if ( NULL == msg ) return;
00509 
00510    aodv_log_rrep_ack_s( state, &hdrs );
00511 
00512    aodv_send_message( state, &hdrs, msg );
00513 
00514    free_aodv_chunk( msg );
00515 }
00516 

Generated on Mon Mar 24 11:15:45 2008 for Pydtn Simulator by  doxygen 1.5.4