source: mainline/uspace/srv/net/il/arp/arp.c@ 522253c1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 522253c1 was 522253c1, checked in by Jakub Jermar <jakub@…>, 15 years ago

Move Internet layer modules messages definitions to standard library.

  • Property mode set to 100644
File size: 20.9 KB
RevLine 
[21580dd]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>
[19f857a]43#include <str.h>
[21580dd]44#include <task.h>
45#include <ipc/ipc.h>
46#include <ipc/services.h>
[514ee46]47#include <ipc/net.h>
[f87ec535]48#include <ipc/arp.h>
[522253c1]49#include <ipc/il.h>
[2687bdb]50#include <byteorder.h>
[c5b59ce]51#include <err.h>
[21580dd]52
[c7a8442]53#include <net/modules.h>
[e526f08]54#include <net/device.h>
[849ed54]55#include <arp_interface.h>
56#include <nil_interface.h>
57#include <protocol_map.h>
58#include <adt/measured_strings.h>
[c69d327]59#include <net/packet.h>
[0a866eeb]60#include <packet_client.h>
[14f1db0]61#include <packet_remote.h>
62#include <il_interface.h>
63#include <il_local.h>
[21580dd]64
65#include "arp.h"
66#include "arp_header.h"
67#include "arp_oc.h"
68#include "arp_module.h"
[849ed54]69
70
71/** ARP module name.
72 */
[24ab58b3]73#define NAME "arp"
[21580dd]74
75/** ARP global data.
76 */
77arp_globals_t arp_globals;
78
[a64c64d]79/** Clears the device specific data.
80 * @param[in] device The device specific data.
81 */
82void arp_clear_device(arp_device_ref device);
83
[21580dd]84/** Creates new protocol specific data.
85 * Allocates and returns the needed memory block as the proto parameter.
86 * @param[out] proto The allocated protocol specific data.
87 * @param[in] service The protocol module service.
88 * @param[in] address The actual protocol device address.
89 * @returns EOK on success.
90 * @returns ENOMEM if there is not enough memory left.
91 */
[aadf01e]92int arp_proto_create(arp_proto_ref * proto, services_t service, measured_string_ref address);
[21580dd]93
94/** @name Message processing functions
95 */
96/*@{*/
97
98/** Registers the device.
99 * Creates new device entry in the cache or updates the protocol address if the device with the device identifier and the driver service exists.
100 * @param[in] device_id The device identifier.
101 * @param[in] service The device driver service.
102 * @param[in] protocol The protocol service.
103 * @param[in] address The actual device protocol address.
104 * @returns EOK on success.
105 * @returns EEXIST if another device with the same device identifier and different driver service exists.
106 * @returns ENOMEM if there is not enough memory left.
107 * @returns Other error codes as defined for the measured_strings_return() function.
108 */
[aadf01e]109int arp_device_message(device_id_t device_id, services_t service, services_t protocol, measured_string_ref address);
[21580dd]110
[a64c64d]111/** Updates the device content length according to the new MTU value.
[21580dd]112 * @param[in] device_id The device identifier.
[a64c64d]113 * @param[in] mtu The new mtu value.
114 * @returns ENOENT if device is not found.
115 * @returns EOK on success.
[21580dd]116 */
[a64c64d]117int arp_mtu_changed_message(device_id_t device_id, size_t mtu);
[21580dd]118
119/** Processes the received ARP packet.
120 * Updates the source hardware address if the source entry exists or the packet is targeted to my protocol address.
121 * Responses to the ARP request if the packet is the ARP request and is targeted to my address.
122 * @param[in] device_id The source device identifier.
123 * @param[in,out] packet The received packet.
124 * @returns EOK on success and the packet is no longer needed.
125 * @returns 1 on success and the packet has been reused.
126 * @returns EINVAL if the packet is too small to carry an ARP packet.
127 * @returns EINVAL if the received address lengths differs from the registered values.
128 * @returns ENOENT if the device is not found in the cache.
129 * @returns ENOENT if the protocol for the device is not found in the cache.
130 * @returns ENOMEM if there is not enough memory left.
131 */
[aadf01e]132int arp_receive_message(device_id_t device_id, packet_t packet);
[21580dd]133
[a64c64d]134/** Returns the hardware address for the given protocol address.
135 * Sends the ARP request packet if the hardware address is not found in the cache.
[21580dd]136 * @param[in] device_id The device identifier.
[a64c64d]137 * @param[in] protocol The protocol service.
138 * @param[in] target The target protocol address.
139 * @returns The hardware address of the target.
140 * @returns NULL if the target parameter is NULL.
141 * @returns NULL if the device is not found.
142 * @returns NULL if the device packet is too small to send a&nbsp;request.
143 * @returns NULL if the hardware address is not found in the cache.
[21580dd]144 */
[a64c64d]145measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target);
[21580dd]146
147/*@}*/
148
[aadf01e]149DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t)
[21580dd]150
[aadf01e]151INT_MAP_IMPLEMENT(arp_protos, arp_proto_t)
[21580dd]152
[aadf01e]153GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t)
[21580dd]154
[a64c64d]155int arp_clean_cache_req(int arp_phone){
156 int count;
[aadf01e]157 arp_device_ref device;
[21580dd]158
[aadf01e]159 fibril_rwlock_write_lock(&arp_globals.lock);
[a64c64d]160 for(count = arp_cache_count(&arp_globals.cache) - 1; count >= 0; -- count){
161 device = arp_cache_get_index(&arp_globals.cache, count);
162 if(device){
163 arp_clear_device(device);
164 if(device->addr_data){
165 free(device->addr_data);
166 }
167 if(device->broadcast_data){
168 free(device->broadcast_data);
169 }
170 }
[21580dd]171 }
[a64c64d]172 arp_cache_clear(&arp_globals.cache);
[aadf01e]173 fibril_rwlock_write_unlock(&arp_globals.lock);
[a64c64d]174 printf("Cache cleaned\n");
[21580dd]175 return EOK;
176}
177
[aadf01e]178int arp_clear_address_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address){
179 arp_device_ref device;
180 arp_proto_ref proto;
[21580dd]181
[aadf01e]182 fibril_rwlock_write_lock(&arp_globals.lock);
183 device = arp_cache_find(&arp_globals.cache, device_id);
184 if(! device){
185 fibril_rwlock_write_unlock(&arp_globals.lock);
[21580dd]186 return ENOENT;
187 }
[aadf01e]188 proto = arp_protos_find(&device->protos, protocol);
189 if(! proto){
190 fibril_rwlock_write_unlock(&arp_globals.lock);
[21580dd]191 return ENOENT;
192 }
[aadf01e]193 arp_addr_exclude(&proto->addresses, address->value, address->length);
194 fibril_rwlock_write_unlock(&arp_globals.lock);
[21580dd]195 return EOK;
196}
197
[a64c64d]198void arp_clear_device(arp_device_ref device){
[aadf01e]199 int count;
[a64c64d]200 arp_proto_ref proto;
[aadf01e]201
[a64c64d]202 for(count = arp_protos_count(&device->protos) - 1; count >= 0; -- count){
203 proto = arp_protos_get_index(&device->protos, count);
204 if(proto){
205 if(proto->addr){
206 free(proto->addr);
[aadf01e]207 }
[a64c64d]208 if(proto->addr_data){
209 free(proto->addr_data);
[aadf01e]210 }
[a64c64d]211 arp_addr_destroy(&proto->addresses);
[21580dd]212 }
213 }
[a64c64d]214 arp_protos_clear(&device->protos);
[21580dd]215}
216
[a64c64d]217int arp_clear_device_req(int arp_phone, device_id_t device_id){
218 arp_device_ref device;
[21580dd]219
[a64c64d]220 fibril_rwlock_write_lock(&arp_globals.lock);
221 device = arp_cache_find(&arp_globals.cache, device_id);
222 if(! device){
223 fibril_rwlock_write_unlock(&arp_globals.lock);
[21580dd]224 return ENOENT;
225 }
[a64c64d]226 arp_clear_device(device);
227 printf("Device %d cleared\n", device_id);
[aadf01e]228 fibril_rwlock_write_unlock(&arp_globals.lock);
[21580dd]229 return EOK;
230}
231
[aadf01e]232int arp_device_message(device_id_t device_id, services_t service, services_t protocol, measured_string_ref address){
[21580dd]233 ERROR_DECLARE;
234
[aadf01e]235 arp_device_ref device;
236 arp_proto_ref proto;
237 int index;
238 hw_type_t hardware;
[21580dd]239
[aadf01e]240 fibril_rwlock_write_lock(&arp_globals.lock);
[21580dd]241 // an existing device?
[aadf01e]242 device = arp_cache_find(&arp_globals.cache, device_id);
243 if(device){
244 if(device->service != service){
245 printf("Device %d already exists\n", device->device_id);
246 fibril_rwlock_write_unlock(&arp_globals.lock);
[21580dd]247 return EEXIST;
248 }
[aadf01e]249 proto = arp_protos_find(&device->protos, protocol);
250 if(proto){
251 free(proto->addr);
252 free(proto->addr_data);
[21580dd]253 proto->addr = address;
254 proto->addr_data = address->value;
255 }else{
[aadf01e]256 if(ERROR_OCCURRED(arp_proto_create(&proto, protocol, address))){
257 fibril_rwlock_write_unlock(&arp_globals.lock);
[21580dd]258 return ERROR_CODE;
259 }
[aadf01e]260 index = arp_protos_add(&device->protos, proto->service, proto);
261 if(index < 0){
262 fibril_rwlock_write_unlock(&arp_globals.lock);
263 free(proto);
[21580dd]264 return index;
265 }
[aadf01e]266 printf("New protocol added:\n\tdevice id\t= %d\n\tproto\t= %d", device_id, protocol);
[21580dd]267 }
268 }else{
[aadf01e]269 hardware = hardware_map(service);
270 if(! hardware){
271 return ENOENT;
272 }
[21580dd]273 // create a new device
[aadf01e]274 device = (arp_device_ref) malloc(sizeof(arp_device_t));
275 if(! device){
276 fibril_rwlock_write_unlock(&arp_globals.lock);
[21580dd]277 return ENOMEM;
278 }
279 device->hardware = hardware;
280 device->device_id = device_id;
[aadf01e]281 if(ERROR_OCCURRED(arp_protos_initialize(&device->protos))
282 || ERROR_OCCURRED(arp_proto_create(&proto, protocol, address))){
283 fibril_rwlock_write_unlock(&arp_globals.lock);
284 free(device);
[21580dd]285 return ERROR_CODE;
286 }
[aadf01e]287 index = arp_protos_add(&device->protos, proto->service, proto);
288 if(index < 0){
289 fibril_rwlock_write_unlock(&arp_globals.lock);
290 arp_protos_destroy(&device->protos);
291 free(device);
[21580dd]292 return index;
293 }
294 device->service = service;
295 // bind the new one
[aadf01e]296 device->phone = nil_bind_service(device->service, (ipcarg_t) device->device_id, SERVICE_ARP, arp_globals.client_connection);
297 if(device->phone < 0){
298 fibril_rwlock_write_unlock(&arp_globals.lock);
299 arp_protos_destroy(&device->protos);
300 free(device);
[21580dd]301 return EREFUSED;
302 }
303 // get packet dimensions
[aadf01e]304 if(ERROR_OCCURRED(nil_packet_size_req(device->phone, device_id, &device->packet_dimension))){
305 fibril_rwlock_write_unlock(&arp_globals.lock);
306 arp_protos_destroy(&device->protos);
307 free(device);
[21580dd]308 return ERROR_CODE;
309 }
310 // get hardware address
[aadf01e]311 if(ERROR_OCCURRED(nil_get_addr_req(device->phone, device_id, &device->addr, &device->addr_data))){
312 fibril_rwlock_write_unlock(&arp_globals.lock);
313 arp_protos_destroy(&device->protos);
314 free(device);
[21580dd]315 return ERROR_CODE;
316 }
317 // get broadcast address
[aadf01e]318 if(ERROR_OCCURRED(nil_get_broadcast_addr_req(device->phone, device_id, &device->broadcast_addr, &device->broadcast_data))){
319 fibril_rwlock_write_unlock(&arp_globals.lock);
320 free(device->addr);
321 free(device->addr_data);
322 arp_protos_destroy(&device->protos);
323 free(device);
[21580dd]324 return ERROR_CODE;
325 }
[aadf01e]326 if(ERROR_OCCURRED(arp_cache_add(&arp_globals.cache, device->device_id, device))){
327 fibril_rwlock_write_unlock(&arp_globals.lock);
328 free(device->addr);
329 free(device->addr_data);
330 free(device->broadcast_addr);
331 free(device->broadcast_data);
332 arp_protos_destroy(&device->protos);
333 free(device);
[21580dd]334 return ERROR_CODE;
335 }
[24ab58b3]336 printf("%s: Device registered (id: %d, type: 0x%x, service: %d, proto: %d)\n",
337 NAME, device->device_id, device->hardware, device->service, protocol);
[21580dd]338 }
[aadf01e]339 fibril_rwlock_write_unlock(&arp_globals.lock);
[21580dd]340 return EOK;
341}
342
[a64c64d]343int arp_device_req(int arp_phone, device_id_t device_id, services_t protocol, services_t netif, measured_string_ref address){
344 ERROR_DECLARE;
345
346 measured_string_ref tmp;
347
348 // copy the given address for exclusive use
349 tmp = measured_string_copy(address);
350 if(ERROR_OCCURRED(arp_device_message(device_id, netif, protocol, tmp))){
351 free(tmp->value);
352 free(tmp);
353 }
354 return ERROR_CODE;
355}
356
357int arp_initialize(async_client_conn_t client_connection){
358 ERROR_DECLARE;
359
360 fibril_rwlock_initialize(&arp_globals.lock);
361 fibril_rwlock_write_lock(&arp_globals.lock);
362 arp_globals.client_connection = client_connection;
363 ERROR_PROPAGATE(arp_cache_initialize(&arp_globals.cache));
364 fibril_rwlock_write_unlock(&arp_globals.lock);
365 return EOK;
366}
367
[14f1db0]368int arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
369 ipc_call_t *answer, int *answer_count)
370{
[a64c64d]371 ERROR_DECLARE;
[14f1db0]372
[a64c64d]373 measured_string_ref address;
374 measured_string_ref translation;
375 char * data;
[aadf01e]376 packet_t packet;
[a64c64d]377 packet_t next;
[14f1db0]378
[a64c64d]379 *answer_count = 0;
[14f1db0]380 switch (IPC_GET_METHOD(*call)) {
[a64c64d]381 case IPC_M_PHONE_HUNGUP:
382 return EOK;
383 case NET_ARP_DEVICE:
384 ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
385 if(ERROR_OCCURRED(arp_device_message(IPC_GET_DEVICE(call), IPC_GET_SERVICE(call), ARP_GET_NETIF(call), address))){
386 free(address);
387 free(data);
388 }
389 return ERROR_CODE;
390 case NET_ARP_TRANSLATE:
391 ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
392 fibril_rwlock_read_lock(&arp_globals.lock);
393 translation = arp_translate_message(IPC_GET_DEVICE(call), IPC_GET_SERVICE(call), address);
394 free(address);
395 free(data);
396 if(! translation){
397 fibril_rwlock_read_unlock(&arp_globals.lock);
398 return ENOENT;
399 }
400 ERROR_CODE = measured_strings_reply(translation, 1);
401 fibril_rwlock_read_unlock(&arp_globals.lock);
402 return ERROR_CODE;
403 case NET_ARP_CLEAR_DEVICE:
404 return arp_clear_device_req(0, IPC_GET_DEVICE(call));
405 case NET_ARP_CLEAR_ADDRESS:
406 ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
407 arp_clear_address_req(0, IPC_GET_DEVICE(call), IPC_GET_SERVICE(call), address);
408 free(address);
409 free(data);
410 return EOK;
411 case NET_ARP_CLEAN_CACHE:
412 return arp_clean_cache_req(0);
413 case NET_IL_DEVICE_STATE:
414 // do nothing - keep the cache
415 return EOK;
416 case NET_IL_RECEIVED:
[14f1db0]417 if(! ERROR_OCCURRED(packet_translate_remote(arp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
[a64c64d]418 fibril_rwlock_read_lock(&arp_globals.lock);
419 do{
420 next = pq_detach(packet);
421 ERROR_CODE = arp_receive_message(IPC_GET_DEVICE(call), packet);
422 if(ERROR_CODE != 1){
[14f1db0]423 pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
[a64c64d]424 }
425 packet = next;
426 }while(packet);
427 fibril_rwlock_read_unlock(&arp_globals.lock);
428 }
429 return ERROR_CODE;
430 case NET_IL_MTU_CHANGED:
431 return arp_mtu_changed_message(IPC_GET_DEVICE(call), IPC_GET_MTU(call));
[aadf01e]432 }
[14f1db0]433
[a64c64d]434 return ENOTSUP;
435}
436
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);
[aadf01e]441 device = arp_cache_find(&arp_globals.cache, device_id);
442 if(! device){
[a64c64d]443 fibril_rwlock_write_unlock(&arp_globals.lock);
444 return ENOENT;
[aadf01e]445 }
[a64c64d]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;
[21580dd]458 }
[a64c64d]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;
[21580dd]465 }
[a64c64d]466 return EOK;
[21580dd]467}
468
[aadf01e]469int arp_receive_message(device_id_t device_id, packet_t packet){
[21580dd]470 ERROR_DECLARE;
471
[aadf01e]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)){
[21580dd]493 return EINVAL;
494 }
[aadf01e]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);
[21580dd]500 src_proto = src_hw + header->hardware_length;
501 des_hw = src_proto + header->protocol_length;
502 des_proto = des_hw + header->hardware_length;
[aadf01e]503 hw_source = arp_addr_find(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length));
[21580dd]504 // exists?
[aadf01e]505 if(hw_source){
506 if(hw_source->length != CONVERT_SIZE(uint8_t, char, header->hardware_length)){
[21580dd]507 return EINVAL;
508 }
[aadf01e]509 memcpy(hw_source->value, src_hw, hw_source->length);
[21580dd]510 }
511 // is my protocol address?
[aadf01e]512 if(proto->addr->length != CONVERT_SIZE(uint8_t, char, header->protocol_length)){
[21580dd]513 return EINVAL;
514 }
[aadf01e]515 if(! str_lcmp(proto->addr->value, (char *) des_proto, proto->addr->length)){
[21580dd]516 // not already upadted?
[aadf01e]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));
[21580dd]523 }
[aadf01e]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);
[21580dd]532 return 1;
533 }
534 }
535 return EOK;
536}
537
[a64c64d]538task_id_t arp_task_get_id(void){
539 return task_get_id();
[21580dd]540}
541
[a64c64d]542measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target){
[aadf01e]543 arp_device_ref device;
[a64c64d]544 arp_proto_ref proto;
545 measured_string_ref addr;
546 size_t length;
547 packet_t packet;
548 arp_header_ref header;
[21580dd]549
[a64c64d]550 if(! target){
551 return NULL;
552 }
[aadf01e]553 device = arp_cache_find(&arp_globals.cache, device_id);
554 if(! device){
[a64c64d]555 return NULL;
[21580dd]556 }
[a64c64d]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 }
[14f1db0]570 packet = packet_get_4_remote(arp_globals.net_phone, device->packet_dimension.addr_len, device->packet_dimension.prefix, length, device->packet_dimension.suffix);
[a64c64d]571 if(! packet){
572 return NULL;
573 }
574 header = (arp_header_ref) packet_suffix(packet, length);
575 if(! header){
[14f1db0]576 pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
[a64c64d]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){
[14f1db0]593 pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
[a64c64d]594 return NULL;
595 }
596 nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
597 return NULL;
[21580dd]598}
599
[849ed54]600/** Default thread for new connections.
601 *
602 * @param[in] iid The initial message identifier.
603 * @param[in] icall The initial message call structure.
604 *
605 */
606static void il_client_connection(ipc_callid_t iid, ipc_call_t * icall)
607{
608 /*
609 * Accept the connection
610 * - Answer the first IPC_M_CONNECT_ME_TO call.
611 */
612 ipc_answer_0(iid, EOK);
613
614 while(true) {
615 ipc_call_t answer;
616 int answer_count;
617
618 /* Clear the answer structure */
619 refresh_answer(&answer, &answer_count);
620
621 /* Fetch the next message */
622 ipc_call_t call;
623 ipc_callid_t callid = async_get_call(&call);
624
625 /* Process the message */
[14f1db0]626 int res = il_module_message_standalone(callid, &call, &answer,
627 &answer_count);
[849ed54]628
629 /* End if said to either by the message or the processing result */
630 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
631 return;
632
633 /* Answer the message */
634 answer_call(callid, res, &answer, answer_count);
635 }
636}
637
638/** Starts the module.
639 *
640 * @param argc The count of the command line arguments. Ignored parameter.
641 * @param argv The command line parameters. Ignored parameter.
642 *
643 * @returns EOK on success.
644 * @returns Other error codes as defined for each specific module start function.
645 *
646 */
647int main(int argc, char *argv[])
648{
649 ERROR_DECLARE;
650
651 /* Start the module */
[14f1db0]652 if (ERROR_OCCURRED(il_module_start_standalone(il_client_connection)))
[849ed54]653 return ERROR_CODE;
654
655 return EOK;
656}
657
[21580dd]658/** @}
659 */
Note: See TracBrowser for help on using the repository browser.