Changeset 7715994 in mainline for uspace/srv/net/il/arp/arp.c


Ignore:
Timestamp:
2010-03-13T12:17:02Z (14 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
6ba20a6b
Parents:
d0febca (diff), 2070570 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/il/arp/arp.c

    rd0febca r7715994  
    7373arp_globals_t   arp_globals;
    7474
     75/** Clears the device specific data.
     76 *  @param[in] device The device specific data.
     77 */
     78void arp_clear_device(arp_device_ref device);
     79
    7580/** Creates new protocol specific data.
    7681 *  Allocates and returns the needed memory block as the proto parameter.
     
    8186 *  @returns ENOMEM if there is not enough memory left.
    8287 */
    83 int     arp_proto_create( arp_proto_ref * proto, services_t service, measured_string_ref address );
    84 
    85 /** Clears the device specific data.
    86  *  @param[in] device The device specific data.
    87  */
    88 void    arp_clear_device( arp_device_ref device );
     88int arp_proto_create(arp_proto_ref * proto, services_t service, measured_string_ref address);
    8989
    9090/** @name Message processing functions
     
    103103 *  @returns Other error codes as defined for the measured_strings_return() function.
    104104 */
    105 int     arp_device_message( device_id_t device_id, services_t service, services_t protocol, measured_string_ref address );
    106 
    107 /** Returns the hardware address for the given protocol address.
    108  *  Sends the ARP request packet if the hardware address is not found in the cache.
     105int arp_device_message(device_id_t device_id, services_t service, services_t protocol, measured_string_ref address);
     106
     107/** Updates the device content length according to the new MTU value.
    109108 *  @param[in] device_id The device identifier.
    110  *  @param[in] protocol The protocol service.
    111  *  @param[in] target The target protocol address.
    112  *  @returns The hardware address of the target.
    113  *  @returns NULL if the target parameter is NULL.
    114  *  @returns NULL if the device is not found.
    115  *  @returns NULL if the device packet is too small to send a&nbsp;request.
    116  *  @returns NULL if the hardware address is not found in the cache.
    117  */
    118 measured_string_ref     arp_translate_message( device_id_t device_id, services_t protocol, measured_string_ref target );
     109 *  @param[in] mtu The new mtu value.
     110 *  @returns ENOENT if device is not found.
     111 *  @returns EOK on success.
     112 */
     113int arp_mtu_changed_message(device_id_t device_id, size_t mtu);
    119114
    120115/** Processes the received ARP packet.
     
    131126 *  @returns ENOMEM if there is not enough memory left.
    132127 */
    133 int     arp_receive_message( device_id_t device_id, packet_t packet );
    134 
    135 /** Updates the device content length according to the new MTU value.
     128int arp_receive_message(device_id_t device_id, packet_t packet);
     129
     130/** Returns the hardware address for the given protocol address.
     131 *  Sends the ARP request packet if the hardware address is not found in the cache.
    136132 *  @param[in] device_id The device identifier.
    137  *  @param[in] mtu The new mtu value.
    138  *  @returns ENOENT if device is not found.
    139  *  @returns EOK on success.
    140  */
    141 int     arp_mtu_changed_message( device_id_t device_id, size_t mtu );
     133 *  @param[in] protocol The protocol service.
     134 *  @param[in] target The target protocol address.
     135 *  @returns The hardware address of the target.
     136 *  @returns NULL if the target parameter is NULL.
     137 *  @returns NULL if the device is not found.
     138 *  @returns NULL if the device packet is too small to send a&nbsp;request.
     139 *  @returns NULL if the hardware address is not found in the cache.
     140 */
     141measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target);
    142142
    143143/*@}*/
    144144
    145 DEVICE_MAP_IMPLEMENT( arp_cache, arp_device_t )
    146 
    147 INT_MAP_IMPLEMENT( arp_protos, arp_proto_t )
    148 
    149 GENERIC_CHAR_MAP_IMPLEMENT( arp_addr, measured_string_t )
    150 
    151 task_id_t arp_task_get_id( void ){
    152         return task_get_id();
    153 }
    154 
    155 int arp_clear_device_req( int arp_phone, device_id_t device_id ){
    156         arp_device_ref  device;
    157 
    158         fibril_rwlock_write_lock( & arp_globals.lock );
    159         device = arp_cache_find( & arp_globals.cache, device_id );
    160         if( ! device ){
    161                 fibril_rwlock_write_unlock( & arp_globals.lock );
     145DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t)
     146
     147INT_MAP_IMPLEMENT(arp_protos, arp_proto_t)
     148
     149GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t)
     150
     151int arp_clean_cache_req(int arp_phone){
     152        int count;
     153        arp_device_ref device;
     154
     155        fibril_rwlock_write_lock(&arp_globals.lock);
     156        for(count = arp_cache_count(&arp_globals.cache) - 1; count >= 0; -- count){
     157                device = arp_cache_get_index(&arp_globals.cache, count);
     158                if(device){
     159                        arp_clear_device(device);
     160                        if(device->addr_data){
     161                                free(device->addr_data);
     162                        }
     163                        if(device->broadcast_data){
     164                                free(device->broadcast_data);
     165                        }
     166                }
     167        }
     168        arp_cache_clear(&arp_globals.cache);
     169        fibril_rwlock_write_unlock(&arp_globals.lock);
     170        printf("Cache cleaned\n");
     171        return EOK;
     172}
     173
     174int arp_clear_address_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address){
     175        arp_device_ref device;
     176        arp_proto_ref proto;
     177
     178        fibril_rwlock_write_lock(&arp_globals.lock);
     179        device = arp_cache_find(&arp_globals.cache, device_id);
     180        if(! device){
     181                fibril_rwlock_write_unlock(&arp_globals.lock);
    162182                return ENOENT;
    163183        }
    164         arp_clear_device( device );
    165         printf( "Device %d cleared\n", device_id );
    166         fibril_rwlock_write_unlock( & arp_globals.lock );
    167         return EOK;
    168 }
    169 
    170 int arp_clear_address_req( int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address ){
    171         arp_device_ref  device;
    172         arp_proto_ref   proto;
    173 
    174         fibril_rwlock_write_lock( & arp_globals.lock );
    175         device = arp_cache_find( & arp_globals.cache, device_id );
    176         if( ! device ){
    177                 fibril_rwlock_write_unlock( & arp_globals.lock );
     184        proto = arp_protos_find(&device->protos, protocol);
     185        if(! proto){
     186                fibril_rwlock_write_unlock(&arp_globals.lock);
    178187                return ENOENT;
    179188        }
    180         proto = arp_protos_find( & device->protos, protocol );
    181         if( ! proto ){
    182                 fibril_rwlock_write_unlock( & arp_globals.lock );
     189        arp_addr_exclude(&proto->addresses, address->value, address->length);
     190        fibril_rwlock_write_unlock(&arp_globals.lock);
     191        return EOK;
     192}
     193
     194void arp_clear_device(arp_device_ref device){
     195        int count;
     196        arp_proto_ref proto;
     197
     198        for(count = arp_protos_count(&device->protos) - 1; count >= 0; -- count){
     199                proto = arp_protos_get_index(&device->protos, count);
     200                if(proto){
     201                        if(proto->addr){
     202                                free(proto->addr);
     203                        }
     204                        if(proto->addr_data){
     205                                free(proto->addr_data);
     206                        }
     207                        arp_addr_destroy(&proto->addresses);
     208                }
     209        }
     210        arp_protos_clear(&device->protos);
     211}
     212
     213int arp_clear_device_req(int arp_phone, device_id_t device_id){
     214        arp_device_ref device;
     215
     216        fibril_rwlock_write_lock(&arp_globals.lock);
     217        device = arp_cache_find(&arp_globals.cache, device_id);
     218        if(! device){
     219                fibril_rwlock_write_unlock(&arp_globals.lock);
    183220                return ENOENT;
    184221        }
    185         arp_addr_exclude( & proto->addresses, address->value, address->length );
    186         fibril_rwlock_write_unlock( & arp_globals.lock );
    187         return EOK;
    188 }
    189 
    190 int arp_clean_cache_req( int arp_phone ){
    191         int                             count;
    192         arp_device_ref  device;
    193 
    194         fibril_rwlock_write_lock( & arp_globals.lock );
    195         for( count = arp_cache_count( & arp_globals.cache ) - 1; count >= 0; -- count ){
    196                 device = arp_cache_get_index( & arp_globals.cache, count );
    197                 if( device ){
    198                         arp_clear_device( device );
    199                         if( device->addr_data ) free( device->addr_data );
    200                         if( device->broadcast_data ) free( device->broadcast_data );
    201                 }
    202         }
    203         arp_cache_clear( & arp_globals.cache );
    204         fibril_rwlock_write_unlock( & arp_globals.lock );
    205         printf( "Cache cleaned\n" );
    206         return EOK;
    207 }
    208 
    209 int arp_device_req( int arp_phone, device_id_t device_id, services_t protocol, services_t netif, measured_string_ref address ){
     222        arp_clear_device(device);
     223        printf("Device %d cleared\n", device_id);
     224        fibril_rwlock_write_unlock(&arp_globals.lock);
     225        return EOK;
     226}
     227
     228int arp_connect_module(services_t service){
     229        if(service != SERVICE_ARP){
     230                return EINVAL;
     231        }
     232        return EOK;
     233}
     234
     235int arp_device_message(device_id_t device_id, services_t service, services_t protocol, measured_string_ref address){
    210236        ERROR_DECLARE;
    211237
    212         measured_string_ref tmp;
    213 
    214         // copy the given address for exclusive use
    215         tmp = measured_string_copy( address );
    216         if( ERROR_OCCURRED( arp_device_message( device_id, netif, protocol, tmp ))){
    217                 free( tmp->value );
    218                 free( tmp );
    219         }
    220         return ERROR_CODE;
    221 }
    222 
    223 int arp_translate_req( int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address, measured_string_ref * translation, char ** data ){
    224         measured_string_ref     tmp;
    225 
    226         fibril_rwlock_read_lock( & arp_globals.lock );
    227         tmp = arp_translate_message( device_id, protocol, address );
    228         if( tmp ){
    229                 * translation = measured_string_copy( tmp );
    230                 fibril_rwlock_read_unlock( & arp_globals.lock );
    231                 if( * translation ){
    232                         * data = ( ** translation ).value;
    233                         return EOK;
    234                 }else{
    235                         return ENOMEM;
    236                 }
    237         }else{
    238                 fibril_rwlock_read_unlock( & arp_globals.lock );
    239                 return ENOENT;
    240         }
    241 }
    242 
    243 int arp_initialize( async_client_conn_t client_connection ){
    244         ERROR_DECLARE;
    245 
    246         fibril_rwlock_initialize( & arp_globals.lock );
    247         fibril_rwlock_write_lock( & arp_globals.lock );
    248         arp_globals.client_connection = client_connection;
    249         ERROR_PROPAGATE( arp_cache_initialize( & arp_globals.cache ));
    250         fibril_rwlock_write_unlock( & arp_globals.lock );
    251         return EOK;
    252 }
    253 
    254 int arp_proto_create( arp_proto_ref * proto, services_t service, measured_string_ref address ){
    255         ERROR_DECLARE;
    256 
    257         * proto = ( arp_proto_ref ) malloc( sizeof( arp_proto_t ));
    258         if( !( * proto )) return ENOMEM;
    259         ( ** proto ).service = service;
    260         ( ** proto ).addr = address;
    261         ( ** proto ).addr_data = address->value;
    262         if( ERROR_OCCURRED( arp_addr_initialize( &( ** proto).addresses ))){
    263                 free( * proto );
    264                 return ERROR_CODE;
    265         }
    266         return EOK;
    267 }
    268 
    269 int arp_device_message( device_id_t device_id, services_t service, services_t protocol, measured_string_ref address ){
    270         ERROR_DECLARE;
    271 
    272         arp_device_ref  device;
    273         arp_proto_ref   proto;
    274         int                             index;
    275         hw_type_t               hardware;
    276 
    277         fibril_rwlock_write_lock( & arp_globals.lock );
     238        arp_device_ref device;
     239        arp_proto_ref proto;
     240        int index;
     241        hw_type_t hardware;
     242
     243        fibril_rwlock_write_lock(&arp_globals.lock);
    278244        // an existing device?
    279         device = arp_cache_find( & arp_globals.cache, device_id );
    280         if( device ){
    281                 if( device->service != service ){
    282                         printf( "Device %d already exists\n", device->device_id );
    283                         fibril_rwlock_write_unlock( & arp_globals.lock );
     245        device = arp_cache_find(&arp_globals.cache, device_id);
     246        if(device){
     247                if(device->service != service){
     248                        printf("Device %d already exists\n", device->device_id);
     249                        fibril_rwlock_write_unlock(&arp_globals.lock);
    284250                        return EEXIST;
    285251                }
    286                 proto = arp_protos_find( & device->protos, protocol );
    287                 if( proto ){
    288                         free( proto->addr );
    289                         free( proto->addr_data );
     252                proto = arp_protos_find(&device->protos, protocol);
     253                if(proto){
     254                        free(proto->addr);
     255                        free(proto->addr_data);
    290256                        proto->addr = address;
    291257                        proto->addr_data = address->value;
    292258                }else{
    293                         if( ERROR_OCCURRED( arp_proto_create( & proto, protocol, address ))){
    294                                 fibril_rwlock_write_unlock( & arp_globals.lock );
     259                        if(ERROR_OCCURRED(arp_proto_create(&proto, protocol, address))){
     260                                fibril_rwlock_write_unlock(&arp_globals.lock);
    295261                                return ERROR_CODE;
    296262                        }
    297                         index = arp_protos_add( & device->protos, proto->service, proto );
    298                         if( index < 0 ){
    299                                 fibril_rwlock_write_unlock( & arp_globals.lock );
    300                                 free( proto );
     263                        index = arp_protos_add(&device->protos, proto->service, proto);
     264                        if(index < 0){
     265                                fibril_rwlock_write_unlock(&arp_globals.lock);
     266                                free(proto);
    301267                                return index;
    302268                        }
    303                         printf( "New protocol added:\n\tdevice id\t= %d\n\tproto\t= %d", device_id, protocol );
     269                        printf("New protocol added:\n\tdevice id\t= %d\n\tproto\t= %d", device_id, protocol);
    304270                }
    305271        }else{
    306                 hardware = hardware_map( service );
    307                 if( ! hardware ) return ENOENT;
     272                hardware = hardware_map(service);
     273                if(! hardware){
     274                        return ENOENT;
     275                }
    308276                // create a new device
    309                 device = ( arp_device_ref ) malloc( sizeof( arp_device_t ));
    310                 if( ! device ){
    311                         fibril_rwlock_write_unlock( & arp_globals.lock );
     277                device = (arp_device_ref) malloc(sizeof(arp_device_t));
     278                if(! device){
     279                        fibril_rwlock_write_unlock(&arp_globals.lock);
    312280                        return ENOMEM;
    313281                }
    314282                device->hardware = hardware;
    315283                device->device_id = device_id;
    316                 if( ERROR_OCCURRED( arp_protos_initialize( & device->protos ))
    317                 || ERROR_OCCURRED( arp_proto_create( & proto, protocol, address ))){
    318                         fibril_rwlock_write_unlock( & arp_globals.lock );
    319                         free( device );
    320                         return ERROR_CODE;
    321                 }
    322                 index = arp_protos_add( & device->protos, proto->service, proto );
    323                 if( index < 0 ){
    324                         fibril_rwlock_write_unlock( & arp_globals.lock );
    325                         arp_protos_destroy( & device->protos );
    326                         free( device );
     284                if(ERROR_OCCURRED(arp_protos_initialize(&device->protos))
     285                        || ERROR_OCCURRED(arp_proto_create(&proto, protocol, address))){
     286                        fibril_rwlock_write_unlock(&arp_globals.lock);
     287                        free(device);
     288                        return ERROR_CODE;
     289                }
     290                index = arp_protos_add(&device->protos, proto->service, proto);
     291                if(index < 0){
     292                        fibril_rwlock_write_unlock(&arp_globals.lock);
     293                        arp_protos_destroy(&device->protos);
     294                        free(device);
    327295                        return index;
    328296                }
    329297                device->service = service;
    330298                // bind the new one
    331                 device->phone = nil_bind_service( device->service, ( ipcarg_t ) device->device_id, SERVICE_ARP, arp_globals.client_connection );
    332                 if( device->phone < 0 ){
    333                         fibril_rwlock_write_unlock( & arp_globals.lock );
    334                         arp_protos_destroy( & device->protos );
    335                         free( device );
     299                device->phone = nil_bind_service(device->service, (ipcarg_t) device->device_id, SERVICE_ARP, arp_globals.client_connection);
     300                if(device->phone < 0){
     301                        fibril_rwlock_write_unlock(&arp_globals.lock);
     302                        arp_protos_destroy(&device->protos);
     303                        free(device);
    336304                        return EREFUSED;
    337305                }
    338306                // get packet dimensions
    339                 if( ERROR_OCCURRED( nil_packet_size_req( device->phone, device_id, & device->packet_dimension ))){
    340                         fibril_rwlock_write_unlock( & arp_globals.lock );
    341                         arp_protos_destroy( & device->protos );
    342                         free( device );
     307                if(ERROR_OCCURRED(nil_packet_size_req(device->phone, device_id, &device->packet_dimension))){
     308                        fibril_rwlock_write_unlock(&arp_globals.lock);
     309                        arp_protos_destroy(&device->protos);
     310                        free(device);
    343311                        return ERROR_CODE;
    344312                }
    345313                // get hardware address
    346                 if( ERROR_OCCURRED( nil_get_addr_req( device->phone, device_id, & device->addr, & device->addr_data ))){
    347                         fibril_rwlock_write_unlock( & arp_globals.lock );
    348                         arp_protos_destroy( & device->protos );
    349                         free( device );
     314                if(ERROR_OCCURRED(nil_get_addr_req(device->phone, device_id, &device->addr, &device->addr_data))){
     315                        fibril_rwlock_write_unlock(&arp_globals.lock);
     316                        arp_protos_destroy(&device->protos);
     317                        free(device);
    350318                        return ERROR_CODE;
    351319                }
    352320                // get broadcast address
    353                 if( ERROR_OCCURRED( nil_get_broadcast_addr_req( device->phone, device_id, & device->broadcast_addr, & device->broadcast_data ))){
    354                         fibril_rwlock_write_unlock( & arp_globals.lock );
    355                         free( device->addr );
    356                         free( device->addr_data );
    357                         arp_protos_destroy( & device->protos );
    358                         free( device );
    359                         return ERROR_CODE;
    360                 }
    361                 if( ERROR_OCCURRED( arp_cache_add( & arp_globals.cache, device->device_id, device ))){
    362                         fibril_rwlock_write_unlock( & arp_globals.lock );
    363                         free( device->addr );
    364                         free( device->addr_data );
    365                         free( device->broadcast_addr );
    366                         free( device->broadcast_data );
    367                         arp_protos_destroy( & device->protos );
    368                         free( device );
    369                         return ERROR_CODE;
    370                 }
    371                 printf( "New device registered:\n\tid\t= %d\n\ttype\t= 0x%x\n\tservice\t= %d\n\tproto\t= %d\n", device->device_id, device->hardware, device->service, protocol );
    372         }
    373         fibril_rwlock_write_unlock( & arp_globals.lock );
    374         return EOK;
    375 }
    376 
    377 measured_string_ref arp_translate_message( device_id_t device_id, services_t protocol, measured_string_ref target ){
    378         arp_device_ref          device;
    379         arp_proto_ref           proto;
    380         measured_string_ref     addr;
    381         size_t                          length;
    382         packet_t                        packet;
    383         arp_header_ref          header;
    384 
    385         if( ! target ) return NULL;
    386         device = arp_cache_find( & arp_globals.cache, device_id );
    387         if( ! device ) return NULL;
    388         proto = arp_protos_find( & device->protos, protocol );
    389         if(( ! proto ) || ( proto->addr->length != target->length )) return NULL;
    390         addr = arp_addr_find( & proto->addresses, target->value, target->length );
    391         if( addr ) return addr;
    392         // ARP packet content size = header + ( address + translation ) * 2
    393         length = 8 + ( CONVERT_SIZE( char, uint8_t, proto->addr->length ) + CONVERT_SIZE( char, uint8_t, device->addr->length )) * 2;
    394         if( length > device->packet_dimension.content ) return NULL;
    395         packet = packet_get_4( arp_globals.net_phone, device->packet_dimension.addr_len, device->packet_dimension.prefix, length, device->packet_dimension.suffix );
    396         if( ! packet ) return NULL;
    397         header = ( arp_header_ref ) packet_suffix( packet, length );
    398         if( ! header ){
    399                 pq_release( arp_globals.net_phone, packet_get_id( packet ));
    400                 return NULL;
    401         }
    402         header->hardware = htons( device->hardware );
    403         header->hardware_length = ( uint8_t ) device->addr->length;
    404         header->protocol = htons( protocol_map( device->service, protocol ));
    405         header->protocol_length = ( uint8_t ) proto->addr->length;
    406         header->operation = htons( ARPOP_REQUEST );
    407         length = sizeof( arp_header_t );
    408         memcpy((( uint8_t * ) header ) + length, device->addr->value, device->addr->length );
    409         length += device->addr->length;
    410         memcpy((( uint8_t * ) header ) + length, proto->addr->value, proto->addr->length );
    411         length += proto->addr->length;
    412         bzero((( uint8_t * ) header ) + length, device->addr->length );
    413         length += device->addr->length;
    414         memcpy((( uint8_t * ) header ) + length, target->value, target->length );
    415         if( packet_set_addr( packet, ( uint8_t * ) device->addr->value, ( uint8_t * ) device->broadcast_addr->value, CONVERT_SIZE( char, uint8_t, device->addr->length )) != EOK ){
    416                 pq_release( arp_globals.net_phone, packet_get_id( packet ));
    417                 return NULL;
    418         }
    419         nil_send_msg( device->phone, device_id, packet, SERVICE_ARP );
    420         return NULL;
    421 }
    422 
    423 int arp_receive_message( device_id_t device_id, packet_t packet ){
     321                if(ERROR_OCCURRED(nil_get_broadcast_addr_req(device->phone, device_id, &device->broadcast_addr, &device->broadcast_data))){
     322                        fibril_rwlock_write_unlock(&arp_globals.lock);
     323                        free(device->addr);
     324                        free(device->addr_data);
     325                        arp_protos_destroy(&device->protos);
     326                        free(device);
     327                        return ERROR_CODE;
     328                }
     329                if(ERROR_OCCURRED(arp_cache_add(&arp_globals.cache, device->device_id, device))){
     330                        fibril_rwlock_write_unlock(&arp_globals.lock);
     331                        free(device->addr);
     332                        free(device->addr_data);
     333                        free(device->broadcast_addr);
     334                        free(device->broadcast_data);
     335                        arp_protos_destroy(&device->protos);
     336                        free(device);
     337                        return ERROR_CODE;
     338                }
     339                printf("New device registered:\n\tid\t= %d\n\ttype\t= 0x%x\n\tservice\t= %d\n\tproto\t= %d\n", device->device_id, device->hardware, device->service, protocol);
     340        }
     341        fibril_rwlock_write_unlock(&arp_globals.lock);
     342        return EOK;
     343}
     344
     345int arp_device_req(int arp_phone, device_id_t device_id, services_t protocol, services_t netif, measured_string_ref address){
    424346        ERROR_DECLARE;
    425347
    426         size_t                          length;
    427         arp_header_ref          header;
    428         arp_device_ref          device;
    429         arp_proto_ref           proto;
    430         measured_string_ref     hw_source;
    431         uint8_t *                       src_hw;
    432         uint8_t *                       src_proto;
    433         uint8_t *                       des_hw;
    434         uint8_t *                       des_proto;
    435 
    436         length = packet_get_data_length( packet );
    437         if( length <= sizeof( arp_header_t )) return EINVAL;
    438         device = arp_cache_find( & arp_globals.cache, device_id );
    439         if( ! device ) return ENOENT;
    440         header = ( arp_header_ref ) packet_get_data( packet );
    441         if(( ntohs( header->hardware ) != device->hardware )
    442         || ( length < sizeof( arp_header_t ) + header->hardware_length * 2u + header->protocol_length * 2u )){
    443                 return EINVAL;
    444         }
    445         proto = arp_protos_find( & device->protos, protocol_unmap( device->service, ntohs( header->protocol )));
    446         if( ! proto ) return ENOENT;
    447         src_hw = (( uint8_t * ) header ) + sizeof( arp_header_t );
    448         src_proto = src_hw + header->hardware_length;
    449         des_hw = src_proto + header->protocol_length;
    450         des_proto = des_hw + header->hardware_length;
    451         hw_source = arp_addr_find( & proto->addresses, ( char * ) src_proto, CONVERT_SIZE( uint8_t, char, header->protocol_length ));
    452         // exists?
    453         if( hw_source ){
    454                 if( hw_source->length != CONVERT_SIZE( uint8_t, char, header->hardware_length )){
    455                         return EINVAL;
    456                 }
    457                 memcpy( hw_source->value, src_hw, hw_source->length );
    458         }
    459         // is my protocol address?
    460         if( proto->addr->length != CONVERT_SIZE( uint8_t, char, header->protocol_length )){
    461                 return EINVAL;
    462         }
    463         if( ! str_lcmp( proto->addr->value, ( char * ) des_proto, proto->addr->length )){
    464                 // not already upadted?
    465                 if( ! hw_source ){
    466                         hw_source = measured_string_create_bulk(( char * ) src_hw, CONVERT_SIZE( uint8_t, char, header->hardware_length ));
    467                         if( ! hw_source ) return ENOMEM;
    468                         ERROR_PROPAGATE( arp_addr_add( & proto->addresses, ( char * ) src_proto, CONVERT_SIZE( uint8_t, char, header->protocol_length ), hw_source ));
    469                 }
    470                 if( ntohs( header->operation ) == ARPOP_REQUEST ){
    471                         header->operation = htons( ARPOP_REPLY );
    472                         memcpy( des_proto, src_proto, header->protocol_length );
    473                         memcpy( src_proto, proto->addr->value, header->protocol_length );
    474                         memcpy( src_hw, device->addr->value, device->packet_dimension.addr_len );
    475                         memcpy( des_hw, hw_source->value, header->hardware_length );
    476                         ERROR_PROPAGATE( packet_set_addr( packet, src_hw, des_hw, header->hardware_length ));
    477                         nil_send_msg( device->phone, device_id, packet, SERVICE_ARP );
    478                         return 1;
    479                 }
    480         }
    481         return EOK;
    482 }
    483 
    484 void arp_clear_device( arp_device_ref device ){
    485         int                             count;
    486         arp_proto_ref   proto;
    487 
    488         for( count = arp_protos_count( & device->protos ) - 1; count >= 0; -- count ){
    489                 proto = arp_protos_get_index( & device->protos, count );
    490                 if( proto ){
    491                         if( proto->addr ) free( proto->addr );
    492                         if( proto->addr_data ) free( proto->addr_data );
    493                         arp_addr_destroy( & proto->addresses );
    494                 }
    495         }
    496         arp_protos_clear( & device->protos );
    497 }
    498 
    499 int arp_connect_module( services_t service ){
    500         if( service != SERVICE_ARP ) return EINVAL;
    501         return EOK;
    502 }
    503 
    504 int arp_mtu_changed_message( device_id_t device_id, size_t mtu ){
    505         arp_device_ref  device;
    506 
    507         fibril_rwlock_write_lock( & arp_globals.lock );
    508         device = arp_cache_find( & arp_globals.cache, device_id );
    509         if( ! device ){
    510                 fibril_rwlock_write_unlock( & arp_globals.lock );
    511                 return ENOENT;
    512         }
    513         device->packet_dimension.content = mtu;
    514         printf( "arp - device %d changed mtu to %d\n\n", device_id, mtu );
    515         fibril_rwlock_write_unlock( & arp_globals.lock );
    516         return EOK;
    517 }
    518 
    519 int arp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
     348        measured_string_ref tmp;
     349
     350        // copy the given address for exclusive use
     351        tmp = measured_string_copy(address);
     352        if(ERROR_OCCURRED(arp_device_message(device_id, netif, protocol, tmp))){
     353                free(tmp->value);
     354                free(tmp);
     355        }
     356        return ERROR_CODE;
     357}
     358
     359int arp_initialize(async_client_conn_t client_connection){
    520360        ERROR_DECLARE;
    521361
    522         measured_string_ref     address;
    523         measured_string_ref     translation;
    524         char *                          data;
    525         packet_t                        packet;
    526         packet_t                        next;
    527 
    528 //      printf( "message %d - %d\n", IPC_GET_METHOD( * call ), NET_ARP_FIRST );
    529         * answer_count = 0;
    530         switch( IPC_GET_METHOD( * call )){
     362        fibril_rwlock_initialize(&arp_globals.lock);
     363        fibril_rwlock_write_lock(&arp_globals.lock);
     364        arp_globals.client_connection = client_connection;
     365        ERROR_PROPAGATE(arp_cache_initialize(&arp_globals.cache));
     366        fibril_rwlock_write_unlock(&arp_globals.lock);
     367        return EOK;
     368}
     369
     370int arp_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
     371        ERROR_DECLARE;
     372
     373        measured_string_ref address;
     374        measured_string_ref translation;
     375        char * data;
     376        packet_t packet;
     377        packet_t next;
     378
     379//      printf("message %d - %d\n", IPC_GET_METHOD(*call), NET_ARP_FIRST);
     380        *answer_count = 0;
     381        switch(IPC_GET_METHOD(*call)){
    531382                case IPC_M_PHONE_HUNGUP:
    532383                        return EOK;
    533384                case NET_ARP_DEVICE:
    534                         ERROR_PROPAGATE( measured_strings_receive( & address, & data, 1 ));
    535                         if( ERROR_OCCURRED( arp_device_message( IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ), ARP_GET_NETIF( call ), address ))){
    536                                 free( address );
    537                                 free( data );
     385                        ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
     386                        if(ERROR_OCCURRED(arp_device_message(IPC_GET_DEVICE(call), IPC_GET_SERVICE(call), ARP_GET_NETIF(call), address))){
     387                                free(address);
     388                                free(data);
    538389                        }
    539390                        return ERROR_CODE;
    540391                case NET_ARP_TRANSLATE:
    541                         ERROR_PROPAGATE( measured_strings_receive( & address, & data, 1 ));
    542                         fibril_rwlock_read_lock( & arp_globals.lock );
    543                         translation = arp_translate_message( IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ), address );
    544                         free( address );
    545                         free( data );
    546                         if( ! translation ){
    547                                 fibril_rwlock_read_unlock( & arp_globals.lock );
     392                        ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
     393                        fibril_rwlock_read_lock(&arp_globals.lock);
     394                        translation = arp_translate_message(IPC_GET_DEVICE(call), IPC_GET_SERVICE(call), address);
     395                        free(address);
     396                        free(data);
     397                        if(! translation){
     398                                fibril_rwlock_read_unlock(&arp_globals.lock);
    548399                                return ENOENT;
    549400                        }
    550                         ERROR_CODE = measured_strings_reply( translation, 1 );
    551                         fibril_rwlock_read_unlock( & arp_globals.lock );
     401                        ERROR_CODE = measured_strings_reply(translation, 1);
     402                        fibril_rwlock_read_unlock(&arp_globals.lock);
    552403                        return ERROR_CODE;
    553404                case NET_ARP_CLEAR_DEVICE:
    554                         return arp_clear_device_req( 0, IPC_GET_DEVICE( call ));
     405                        return arp_clear_device_req(0, IPC_GET_DEVICE(call));
    555406                case NET_ARP_CLEAR_ADDRESS:
    556                         ERROR_PROPAGATE( measured_strings_receive( & address, & data, 1 ));
    557                         arp_clear_address_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ), address );
    558                         free( address );
    559                         free( data );
     407                        ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
     408                        arp_clear_address_req(0, IPC_GET_DEVICE(call), IPC_GET_SERVICE(call), address);
     409                        free(address);
     410                        free(data);
    560411                        return EOK;
    561412                case NET_ARP_CLEAN_CACHE:
    562                         return arp_clean_cache_req( 0 );
     413                        return arp_clean_cache_req(0);
    563414                case NET_IL_DEVICE_STATE:
    564415                        // do nothing - keep the cache
    565416                        return EOK;
    566417                case NET_IL_RECEIVED:
    567                         if( ! ERROR_OCCURRED( packet_translate( arp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
    568                                 fibril_rwlock_read_lock( & arp_globals.lock );
     418                        if(! ERROR_OCCURRED(packet_translate(arp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     419                                fibril_rwlock_read_lock(&arp_globals.lock);
    569420                                do{
    570                                         next = pq_detach( packet );
    571                                         ERROR_CODE = arp_receive_message( IPC_GET_DEVICE( call ), packet );
    572                                         if( ERROR_CODE != 1 ) pq_release( arp_globals.net_phone, packet_get_id( packet ));
     421                                        next = pq_detach(packet);
     422                                        ERROR_CODE = arp_receive_message(IPC_GET_DEVICE(call), packet);
     423                                        if(ERROR_CODE != 1){
     424                                                pq_release(arp_globals.net_phone, packet_get_id(packet));
     425                                        }
    573426                                        packet = next;
    574                                 }while( packet );
    575                                 fibril_rwlock_read_unlock( & arp_globals.lock );
     427                                }while(packet);
     428                                fibril_rwlock_read_unlock(&arp_globals.lock);
    576429                        }
    577430                        return ERROR_CODE;
    578431                case NET_IL_MTU_CHANGED:
    579                         return arp_mtu_changed_message( IPC_GET_DEVICE( call ), IPC_GET_MTU( call ));
     432                        return arp_mtu_changed_message(IPC_GET_DEVICE(call), IPC_GET_MTU(call));
    580433        }
    581434        return ENOTSUP;
    582435}
    583436
     437int arp_mtu_changed_message(device_id_t device_id, size_t mtu){
     438        arp_device_ref device;
     439
     440        fibril_rwlock_write_lock(&arp_globals.lock);
     441        device = arp_cache_find(&arp_globals.cache, device_id);
     442        if(! device){
     443                fibril_rwlock_write_unlock(&arp_globals.lock);
     444                return ENOENT;
     445        }
     446        device->packet_dimension.content = mtu;
     447        printf("arp - device %d changed mtu to %d\n\n", device_id, mtu);
     448        fibril_rwlock_write_unlock(&arp_globals.lock);
     449        return EOK;
     450}
     451
     452int arp_proto_create(arp_proto_ref * proto, services_t service, measured_string_ref address){
     453        ERROR_DECLARE;
     454
     455        *proto = (arp_proto_ref) malloc(sizeof(arp_proto_t));
     456        if(!(*proto)){
     457                return ENOMEM;
     458        }
     459        (** proto).service = service;
     460        (** proto).addr = address;
     461        (** proto).addr_data = address->value;
     462        if(ERROR_OCCURRED(arp_addr_initialize(&(** proto).addresses))){
     463                free(*proto);
     464                return ERROR_CODE;
     465        }
     466        return EOK;
     467}
     468
     469int arp_receive_message(device_id_t device_id, packet_t packet){
     470        ERROR_DECLARE;
     471
     472        size_t length;
     473        arp_header_ref header;
     474        arp_device_ref device;
     475        arp_proto_ref proto;
     476        measured_string_ref hw_source;
     477        uint8_t * src_hw;
     478        uint8_t * src_proto;
     479        uint8_t * des_hw;
     480        uint8_t * des_proto;
     481
     482        length = packet_get_data_length(packet);
     483        if(length <= sizeof(arp_header_t)){
     484                return EINVAL;
     485        }
     486        device = arp_cache_find(&arp_globals.cache, device_id);
     487        if(! device){
     488                return ENOENT;
     489        }
     490        header = (arp_header_ref) packet_get_data(packet);
     491        if((ntohs(header->hardware) != device->hardware)
     492                || (length < sizeof(arp_header_t) + header->hardware_length * 2u + header->protocol_length * 2u)){
     493                return EINVAL;
     494        }
     495        proto = arp_protos_find(&device->protos, protocol_unmap(device->service, ntohs(header->protocol)));
     496        if(! proto){
     497                return ENOENT;
     498        }
     499        src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
     500        src_proto = src_hw + header->hardware_length;
     501        des_hw = src_proto + header->protocol_length;
     502        des_proto = des_hw + header->hardware_length;
     503        hw_source = arp_addr_find(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length));
     504        // exists?
     505        if(hw_source){
     506                if(hw_source->length != CONVERT_SIZE(uint8_t, char, header->hardware_length)){
     507                        return EINVAL;
     508                }
     509                memcpy(hw_source->value, src_hw, hw_source->length);
     510        }
     511        // is my protocol address?
     512        if(proto->addr->length != CONVERT_SIZE(uint8_t, char, header->protocol_length)){
     513                return EINVAL;
     514        }
     515        if(! str_lcmp(proto->addr->value, (char *) des_proto, proto->addr->length)){
     516                // not already upadted?
     517                if(! hw_source){
     518                        hw_source = measured_string_create_bulk((char *) src_hw, CONVERT_SIZE(uint8_t, char, header->hardware_length));
     519                        if(! hw_source){
     520                                return ENOMEM;
     521                        }
     522                        ERROR_PROPAGATE(arp_addr_add(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length), hw_source));
     523                }
     524                if(ntohs(header->operation) == ARPOP_REQUEST){
     525                        header->operation = htons(ARPOP_REPLY);
     526                        memcpy(des_proto, src_proto, header->protocol_length);
     527                        memcpy(src_proto, proto->addr->value, header->protocol_length);
     528                        memcpy(src_hw, device->addr->value, device->packet_dimension.addr_len);
     529                        memcpy(des_hw, hw_source->value, header->hardware_length);
     530                        ERROR_PROPAGATE(packet_set_addr(packet, src_hw, des_hw, header->hardware_length));
     531                        nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
     532                        return 1;
     533                }
     534        }
     535        return EOK;
     536}
     537
     538task_id_t arp_task_get_id(void){
     539        return task_get_id();
     540}
     541
     542measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target){
     543        arp_device_ref device;
     544        arp_proto_ref proto;
     545        measured_string_ref addr;
     546        size_t length;
     547        packet_t packet;
     548        arp_header_ref header;
     549
     550        if(! target){
     551                return NULL;
     552        }
     553        device = arp_cache_find(&arp_globals.cache, device_id);
     554        if(! device){
     555                return NULL;
     556        }
     557        proto = arp_protos_find(&device->protos, protocol);
     558        if((! proto) || (proto->addr->length != target->length)){
     559                return NULL;
     560        }
     561        addr = arp_addr_find(&proto->addresses, target->value, target->length);
     562        if(addr){
     563                return addr;
     564        }
     565        // ARP packet content size = header + (address + translation) * 2
     566        length = 8 + (CONVERT_SIZE(char, uint8_t, proto->addr->length) + CONVERT_SIZE(char, uint8_t, device->addr->length)) * 2;
     567        if(length > device->packet_dimension.content){
     568                return NULL;
     569        }
     570        packet = packet_get_4(arp_globals.net_phone, device->packet_dimension.addr_len, device->packet_dimension.prefix, length, device->packet_dimension.suffix);
     571        if(! packet){
     572                return NULL;
     573        }
     574        header = (arp_header_ref) packet_suffix(packet, length);
     575        if(! header){
     576                pq_release(arp_globals.net_phone, packet_get_id(packet));
     577                return NULL;
     578        }
     579        header->hardware = htons(device->hardware);
     580        header->hardware_length = (uint8_t) device->addr->length;
     581        header->protocol = htons(protocol_map(device->service, protocol));
     582        header->protocol_length = (uint8_t) proto->addr->length;
     583        header->operation = htons(ARPOP_REQUEST);
     584        length = sizeof(arp_header_t);
     585        memcpy(((uint8_t *) header) + length, device->addr->value, device->addr->length);
     586        length += device->addr->length;
     587        memcpy(((uint8_t *) header) + length, proto->addr->value, proto->addr->length);
     588        length += proto->addr->length;
     589        bzero(((uint8_t *) header) + length, device->addr->length);
     590        length += device->addr->length;
     591        memcpy(((uint8_t *) header) + length, target->value, target->length);
     592        if(packet_set_addr(packet, (uint8_t *) device->addr->value, (uint8_t *) device->broadcast_addr->value, CONVERT_SIZE(char, uint8_t, device->addr->length)) != EOK){
     593                pq_release(arp_globals.net_phone, packet_get_id(packet));
     594                return NULL;
     595        }
     596        nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
     597        return NULL;
     598}
     599
     600int arp_translate_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address, measured_string_ref * translation, char ** data){
     601        measured_string_ref tmp;
     602
     603        fibril_rwlock_read_lock(&arp_globals.lock);
     604        tmp = arp_translate_message(device_id, protocol, address);
     605        if(tmp){
     606                *translation = measured_string_copy(tmp);
     607                fibril_rwlock_read_unlock(&arp_globals.lock);
     608                if(*translation){
     609                        *data = (** translation).value;
     610                        return EOK;
     611                }else{
     612                        return ENOMEM;
     613                }
     614        }else{
     615                fibril_rwlock_read_unlock(&arp_globals.lock);
     616                return ENOENT;
     617        }
     618}
     619
    584620/** @}
    585621 */
Note: See TracChangeset for help on using the changeset viewer.