~martin-decky/helenos/rcu

« back to all changes in this revision

Viewing changes to uspace/srv/net/il/arp/arp.c

  • Committer: Pavel Rimsky
  • Date: 2010-02-20 20:54:53 UTC
  • mfrom: (292 head)
  • mto: This revision was merged to the branch mainline in revision 296.
  • Revision ID: pavel@pavel-laptop-20100220205453-70sim280j709dgp3
Synchronize with head.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2009 Lukas Mejdrech
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 *
 
9
 * - Redistributions of source code must retain the above copyright
 
10
 *   notice, this list of conditions and the following disclaimer.
 
11
 * - Redistributions in binary form must reproduce the above copyright
 
12
 *   notice, this list of conditions and the following disclaimer in the
 
13
 *   documentation and/or other materials provided with the distribution.
 
14
 * - The name of the author may not be used to endorse or promote products
 
15
 *   derived from this software without specific prior written permission.
 
16
 *
 
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
27
 */
 
28
 
 
29
/** @addtogroup arp
 
30
 *  @{
 
31
 */
 
32
 
 
33
/** @file
 
34
 *  ARP module implementation.
 
35
 *  @see arp.h
 
36
 */
 
37
 
 
38
#include <async.h>
 
39
#include <malloc.h>
 
40
#include <mem.h>
 
41
#include <fibril_synch.h>
 
42
#include <stdio.h>
 
43
#include <string.h>
 
44
#include <task.h>
 
45
 
 
46
#include <ipc/ipc.h>
 
47
#include <ipc/services.h>
 
48
 
 
49
#include "../../err.h"
 
50
#include "../../messages.h"
 
51
#include "../../modules.h"
 
52
 
 
53
#include "../../include/byteorder.h"
 
54
#include "../../include/device.h"
 
55
#include "../../include/arp_interface.h"
 
56
#include "../../include/nil_interface.h"
 
57
#include "../../include/protocol_map.h"
 
58
 
 
59
#include "../../structures/measured_strings.h"
 
60
#include "../../structures/packet/packet.h"
 
61
#include "../../structures/packet/packet_client.h"
 
62
 
 
63
#include "../il_messages.h"
 
64
 
 
65
#include "arp.h"
 
66
#include "arp_header.h"
 
67
#include "arp_oc.h"
 
68
#include "arp_module.h"
 
69
#include "arp_messages.h"
 
70
 
 
71
/** ARP global data.
 
72
 */
 
73
arp_globals_t   arp_globals;
 
74
 
 
75
/** Creates new protocol specific data.
 
76
 *  Allocates and returns the needed memory block as the proto parameter.
 
77
 *  @param[out] proto The allocated protocol specific data.
 
78
 *  @param[in] service The protocol module service.
 
79
 *  @param[in] address The actual protocol device address.
 
80
 *  @returns EOK on success.
 
81
 *  @returns ENOMEM if there is not enough memory left.
 
82
 */
 
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 );
 
89
 
 
90
/** @name Message processing functions
 
91
 */
 
92
/*@{*/
 
93
 
 
94
/** Registers the device.
 
95
 *  Creates new device entry in the cache or updates the protocol address if the device with the device identifier and the driver service exists.
 
96
 *  @param[in] device_id The device identifier.
 
97
 *  @param[in] service The device driver service.
 
98
 *  @param[in] protocol The protocol service.
 
99
 *  @param[in] address The actual device protocol address.
 
100
 *  @returns EOK on success.
 
101
 *  @returns EEXIST if another device with the same device identifier and different driver service exists.
 
102
 *  @returns ENOMEM if there is not enough memory left.
 
103
 *  @returns Other error codes as defined for the measured_strings_return() function.
 
104
 */
 
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.
 
109
 *  @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 );
 
119
 
 
120
/** Processes the received ARP packet.
 
121
 *  Updates the source hardware address if the source entry exists or the packet is targeted to my protocol address.
 
122
 *  Responses to the ARP request if the packet is the ARP request and is targeted to my address.
 
123
 *  @param[in] device_id The source device identifier.
 
124
 *  @param[in,out] packet The received packet.
 
125
 *  @returns EOK on success and the packet is no longer needed.
 
126
 *  @returns 1 on success and the packet has been reused.
 
127
 *  @returns EINVAL if the packet is too small to carry an ARP packet.
 
128
 *  @returns EINVAL if the received address lengths differs from the registered values.
 
129
 *  @returns ENOENT if the device is not found in the cache.
 
130
 *  @returns ENOENT if the protocol for the device is not found in the cache.
 
131
 *  @returns ENOMEM if there is not enough memory left.
 
132
 */
 
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.
 
136
 *  @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 );
 
142
 
 
143
/*@}*/
 
144
 
 
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 );
 
162
                return ENOENT;
 
163
        }
 
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 );
 
178
                return ENOENT;
 
179
        }
 
180
        proto = arp_protos_find( & device->protos, protocol );
 
181
        if( ! proto ){
 
182
                fibril_rwlock_write_unlock( & arp_globals.lock );
 
183
                return ENOENT;
 
184
        }
 
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 ){
 
210
        ERROR_DECLARE;
 
211
 
 
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 );
 
278
        // 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 );
 
284
                        return EEXIST;
 
285
                }
 
286
                proto = arp_protos_find( & device->protos, protocol );
 
287
                if( proto ){
 
288
                        free( proto->addr );
 
289
                        free( proto->addr_data );
 
290
                        proto->addr = address;
 
291
                        proto->addr_data = address->value;
 
292
                }else{
 
293
                        if( ERROR_OCCURRED( arp_proto_create( & proto, protocol, address ))){
 
294
                                fibril_rwlock_write_unlock( & arp_globals.lock );
 
295
                                return ERROR_CODE;
 
296
                        }
 
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 );
 
301
                                return index;
 
302
                        }
 
303
                        printf( "New protocol added:\n\tdevice id\t= %d\n\tproto\t= %d", device_id, protocol );
 
304
                }
 
305
        }else{
 
306
                hardware = hardware_map( service );
 
307
                if( ! hardware ) return ENOENT;
 
308
                // 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 );
 
312
                        return ENOMEM;
 
313
                }
 
314
                device->hardware = hardware;
 
315
                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 );
 
327
                        return index;
 
328
                }
 
329
                device->service = service;
 
330
                // 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 );
 
336
                        return EREFUSED;
 
337
                }
 
338
                // 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 );
 
343
                        return ERROR_CODE;
 
344
                }
 
345
                // 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 );
 
350
                        return ERROR_CODE;
 
351
                }
 
352
                // 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 ){
 
424
        ERROR_DECLARE;
 
425
 
 
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 ){
 
520
        ERROR_DECLARE;
 
521
 
 
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 )){
 
531
                case IPC_M_PHONE_HUNGUP:
 
532
                        return EOK;
 
533
                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 );
 
538
                        }
 
539
                        return ERROR_CODE;
 
540
                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 );
 
548
                                return ENOENT;
 
549
                        }
 
550
                        ERROR_CODE = measured_strings_reply( translation, 1 );
 
551
                        fibril_rwlock_read_unlock( & arp_globals.lock );
 
552
                        return ERROR_CODE;
 
553
                case NET_ARP_CLEAR_DEVICE:
 
554
                        return arp_clear_device_req( 0, IPC_GET_DEVICE( call ));
 
555
                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 );
 
560
                        return EOK;
 
561
                case NET_ARP_CLEAN_CACHE:
 
562
                        return arp_clean_cache_req( 0 );
 
563
                case NET_IL_DEVICE_STATE:
 
564
                        // do nothing - keep the cache
 
565
                        return EOK;
 
566
                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 );
 
569
                                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 ));
 
573
                                        packet = next;
 
574
                                }while( packet );
 
575
                                fibril_rwlock_read_unlock( & arp_globals.lock );
 
576
                        }
 
577
                        return ERROR_CODE;
 
578
                case NET_IL_MTU_CHANGED:
 
579
                        return arp_mtu_changed_message( IPC_GET_DEVICE( call ), IPC_GET_MTU( call ));
 
580
        }
 
581
        return ENOTSUP;
 
582
}
 
583
 
 
584
/** @}
 
585
 */