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

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

Cleanup arp.

  • Property mode set to 100644
File size: 20.8 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
[e9caf47]30 * @{
[21580dd]31 */
32
33/** @file
[e9caf47]34 * ARP module implementation.
35 * @see arp.h
[21580dd]36 */
37
[e9caf47]38#include "arp.h"
39#include "arp_header.h"
40#include "arp_oc.h"
41#include "arp_module.h"
42
[21580dd]43#include <async.h>
44#include <malloc.h>
45#include <mem.h>
46#include <fibril_synch.h>
47#include <stdio.h>
[19f857a]48#include <str.h>
[21580dd]49#include <task.h>
[e9caf47]50#include <adt/measured_strings.h>
[21580dd]51#include <ipc/ipc.h>
52#include <ipc/services.h>
[514ee46]53#include <ipc/net.h>
[f87ec535]54#include <ipc/arp.h>
[522253c1]55#include <ipc/il.h>
[2687bdb]56#include <byteorder.h>
[c5b59ce]57#include <err.h>
[21580dd]58
[c7a8442]59#include <net/modules.h>
[e526f08]60#include <net/device.h>
[e9caf47]61#include <net/packet.h>
62
[849ed54]63#include <nil_interface.h>
64#include <protocol_map.h>
[0a866eeb]65#include <packet_client.h>
[14f1db0]66#include <packet_remote.h>
67#include <il_interface.h>
68#include <il_local.h>
[21580dd]69
[849ed54]70
[e9caf47]71/** ARP module name. */
[24ab58b3]72#define NAME "arp"
[21580dd]73
[e9caf47]74/** ARP global data. */
75arp_globals_t arp_globals;
[21580dd]76
[e9caf47]77DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t);
78INT_MAP_IMPLEMENT(arp_protos, arp_proto_t);
79GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t);
[21580dd]80
[e9caf47]81/** Clears the device specific data.
82 *
83 * @param[in] device The device specific data.
[21580dd]84 */
[e9caf47]85static void arp_clear_device(arp_device_ref device)
86{
87 int count;
88 arp_proto_ref proto;
[21580dd]89
[e9caf47]90 for (count = arp_protos_count(&device->protos) - 1; count >= 0;
91 count--) {
92 proto = arp_protos_get_index(&device->protos, count);
93 if (proto) {
94 if (proto->addr)
95 free(proto->addr);
96 if (proto->addr_data)
97 free(proto->addr_data);
98 arp_addr_destroy(&proto->addresses);
99 }
100 }
101 arp_protos_clear(&device->protos);
102}
[21580dd]103
[e9caf47]104static int arp_clean_cache_req(int arp_phone)
105{
[a64c64d]106 int count;
[aadf01e]107 arp_device_ref device;
[21580dd]108
[aadf01e]109 fibril_rwlock_write_lock(&arp_globals.lock);
[e9caf47]110 for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
111 count--) {
[a64c64d]112 device = arp_cache_get_index(&arp_globals.cache, count);
[e9caf47]113 if (device) {
[a64c64d]114 arp_clear_device(device);
[e9caf47]115 if (device->addr_data)
[a64c64d]116 free(device->addr_data);
[e9caf47]117 if (device->broadcast_data)
[a64c64d]118 free(device->broadcast_data);
119 }
[21580dd]120 }
[a64c64d]121 arp_cache_clear(&arp_globals.cache);
[aadf01e]122 fibril_rwlock_write_unlock(&arp_globals.lock);
[a64c64d]123 printf("Cache cleaned\n");
[21580dd]124 return EOK;
125}
126
[e9caf47]127static int
128arp_clear_address_req(int arp_phone, device_id_t device_id, services_t protocol,
129 measured_string_ref address)
130{
[aadf01e]131 arp_device_ref device;
132 arp_proto_ref proto;
[21580dd]133
[aadf01e]134 fibril_rwlock_write_lock(&arp_globals.lock);
135 device = arp_cache_find(&arp_globals.cache, device_id);
[e9caf47]136 if (!device) {
[aadf01e]137 fibril_rwlock_write_unlock(&arp_globals.lock);
[21580dd]138 return ENOENT;
139 }
[aadf01e]140 proto = arp_protos_find(&device->protos, protocol);
[e9caf47]141 if (!proto) {
[aadf01e]142 fibril_rwlock_write_unlock(&arp_globals.lock);
[21580dd]143 return ENOENT;
144 }
[aadf01e]145 arp_addr_exclude(&proto->addresses, address->value, address->length);
146 fibril_rwlock_write_unlock(&arp_globals.lock);
[21580dd]147 return EOK;
148}
149
[aadf01e]150
[e9caf47]151static int arp_clear_device_req(int arp_phone, device_id_t device_id)
152{
[a64c64d]153 arp_device_ref device;
[21580dd]154
[a64c64d]155 fibril_rwlock_write_lock(&arp_globals.lock);
156 device = arp_cache_find(&arp_globals.cache, device_id);
[e9caf47]157 if (!device) {
[a64c64d]158 fibril_rwlock_write_unlock(&arp_globals.lock);
[21580dd]159 return ENOENT;
160 }
[a64c64d]161 arp_clear_device(device);
162 printf("Device %d cleared\n", device_id);
[aadf01e]163 fibril_rwlock_write_unlock(&arp_globals.lock);
[21580dd]164 return EOK;
165}
166
[e9caf47]167/** Creates new protocol specific data.
168 *
169 * Allocates and returns the needed memory block as the proto parameter.
170 *
171 * @param[out] proto The allocated protocol specific data.
172 * @param[in] service The protocol module service.
173 * @param[in] address The actual protocol device address.
174 * @returns EOK on success.
175 * @returns ENOMEM if there is not enough memory left.
176 */
177static int
178arp_proto_create(arp_proto_ref *proto, services_t service,
179 measured_string_ref address)
180{
181 ERROR_DECLARE;
182
183 *proto = (arp_proto_ref) malloc(sizeof(arp_proto_t));
184 if (!*proto)
185 return ENOMEM;
186 (*proto)->service = service;
187 (*proto)->addr = address;
188 (*proto)->addr_data = address->value;
189 if (ERROR_OCCURRED(arp_addr_initialize(&(*proto)->addresses))) {
190 free(*proto);
191 return ERROR_CODE;
192 }
193 return EOK;
194}
195
196/** Registers the device.
197 *
198 * Creates new device entry in the cache or updates the protocol address if the
199 * device with the device identifier and the driver service exists.
200 *
201 * @param[in] device_id The device identifier.
202 * @param[in] service The device driver service.
203 * @param[in] protocol The protocol service.
204 * @param[in] address The actual device protocol address.
205 * @returns EOK on success.
206 * @returns EEXIST if another device with the same device identifier
207 * and different driver service exists.
208 * @returns ENOMEM if there is not enough memory left.
209 * @returns Other error codes as defined for the
210 * measured_strings_return() function.
211 */
212static int
213arp_device_message(device_id_t device_id, services_t service,
214 services_t protocol, measured_string_ref address)
215{
[21580dd]216 ERROR_DECLARE;
217
[aadf01e]218 arp_device_ref device;
219 arp_proto_ref proto;
220 int index;
221 hw_type_t hardware;
[21580dd]222
[aadf01e]223 fibril_rwlock_write_lock(&arp_globals.lock);
[21580dd]224 // an existing device?
[aadf01e]225 device = arp_cache_find(&arp_globals.cache, device_id);
[e9caf47]226 if (device) {
227 if (device->service != service) {
[aadf01e]228 printf("Device %d already exists\n", device->device_id);
229 fibril_rwlock_write_unlock(&arp_globals.lock);
[21580dd]230 return EEXIST;
231 }
[aadf01e]232 proto = arp_protos_find(&device->protos, protocol);
[e9caf47]233 if (proto) {
[aadf01e]234 free(proto->addr);
235 free(proto->addr_data);
[21580dd]236 proto->addr = address;
237 proto->addr_data = address->value;
[e9caf47]238 } else {
239 if (ERROR_OCCURRED(arp_proto_create(&proto, protocol,
240 address))) {
[aadf01e]241 fibril_rwlock_write_unlock(&arp_globals.lock);
[21580dd]242 return ERROR_CODE;
243 }
[e9caf47]244 index = arp_protos_add(&device->protos, proto->service,
245 proto);
246 if (index < 0) {
[aadf01e]247 fibril_rwlock_write_unlock(&arp_globals.lock);
248 free(proto);
[21580dd]249 return index;
250 }
[e9caf47]251 printf("New protocol added:\n\tdevice id\t= "
252 "%d\n\tproto\t= %d", device_id, protocol);
[21580dd]253 }
[e9caf47]254 } else {
[aadf01e]255 hardware = hardware_map(service);
[e9caf47]256 if (!hardware)
[aadf01e]257 return ENOENT;
[e9caf47]258
[21580dd]259 // create a new device
[aadf01e]260 device = (arp_device_ref) malloc(sizeof(arp_device_t));
[e9caf47]261 if (!device) {
[aadf01e]262 fibril_rwlock_write_unlock(&arp_globals.lock);
[21580dd]263 return ENOMEM;
264 }
265 device->hardware = hardware;
266 device->device_id = device_id;
[e9caf47]267 if (ERROR_OCCURRED(arp_protos_initialize(&device->protos)) ||
268 ERROR_OCCURRED(arp_proto_create(&proto, protocol,
269 address))) {
[aadf01e]270 fibril_rwlock_write_unlock(&arp_globals.lock);
271 free(device);
[21580dd]272 return ERROR_CODE;
273 }
[aadf01e]274 index = arp_protos_add(&device->protos, proto->service, proto);
[e9caf47]275 if (index < 0) {
[aadf01e]276 fibril_rwlock_write_unlock(&arp_globals.lock);
277 arp_protos_destroy(&device->protos);
278 free(device);
[21580dd]279 return index;
280 }
281 device->service = service;
[e9caf47]282
[21580dd]283 // bind the new one
[e9caf47]284 device->phone = nil_bind_service(device->service,
285 (ipcarg_t) device->device_id, SERVICE_ARP,
286 arp_globals.client_connection);
287 if (device->phone < 0) {
[aadf01e]288 fibril_rwlock_write_unlock(&arp_globals.lock);
289 arp_protos_destroy(&device->protos);
290 free(device);
[21580dd]291 return EREFUSED;
292 }
[e9caf47]293
[21580dd]294 // get packet dimensions
[e9caf47]295 if (ERROR_OCCURRED(nil_packet_size_req(device->phone, device_id,
296 &device->packet_dimension))) {
[aadf01e]297 fibril_rwlock_write_unlock(&arp_globals.lock);
298 arp_protos_destroy(&device->protos);
299 free(device);
[21580dd]300 return ERROR_CODE;
301 }
[e9caf47]302
[21580dd]303 // get hardware address
[e9caf47]304 if (ERROR_OCCURRED(nil_get_addr_req(device->phone, device_id,
305 &device->addr, &device->addr_data))) {
[aadf01e]306 fibril_rwlock_write_unlock(&arp_globals.lock);
307 arp_protos_destroy(&device->protos);
308 free(device);
[21580dd]309 return ERROR_CODE;
310 }
[e9caf47]311
[21580dd]312 // get broadcast address
[e9caf47]313 if (ERROR_OCCURRED(nil_get_broadcast_addr_req(device->phone,
314 device_id, &device->broadcast_addr,
315 &device->broadcast_data))) {
[aadf01e]316 fibril_rwlock_write_unlock(&arp_globals.lock);
317 free(device->addr);
318 free(device->addr_data);
319 arp_protos_destroy(&device->protos);
320 free(device);
[21580dd]321 return ERROR_CODE;
322 }
[e9caf47]323
324 if (ERROR_OCCURRED(arp_cache_add(&arp_globals.cache,
325 device->device_id, device))) {
[aadf01e]326 fibril_rwlock_write_unlock(&arp_globals.lock);
327 free(device->addr);
328 free(device->addr_data);
329 free(device->broadcast_addr);
330 free(device->broadcast_data);
331 arp_protos_destroy(&device->protos);
332 free(device);
[21580dd]333 return ERROR_CODE;
334 }
[e9caf47]335 printf("%s: Device registered (id: %d, type: 0x%x, service: %d,"
336 " proto: %d)\n", NAME, device->device_id, device->hardware,
337 device->service, protocol);
[21580dd]338 }
[aadf01e]339 fibril_rwlock_write_unlock(&arp_globals.lock);
[e9caf47]340
[21580dd]341 return EOK;
342}
343
[e9caf47]344/** Initializes the ARP module.
345 *
346 * @param[in] client_connection The client connection processing function.
347 * The module skeleton propagates its own one.
348 * @returns EOK on success.
349 * @returns ENOMEM if there is not enough memory left.
350 */
351int arp_initialize(async_client_conn_t client_connection)
352{
[a64c64d]353 ERROR_DECLARE;
354
355 fibril_rwlock_initialize(&arp_globals.lock);
356 fibril_rwlock_write_lock(&arp_globals.lock);
357 arp_globals.client_connection = client_connection;
358 ERROR_PROPAGATE(arp_cache_initialize(&arp_globals.cache));
359 fibril_rwlock_write_unlock(&arp_globals.lock);
360 return EOK;
361}
362
[e9caf47]363/** Updates the device content length according to the new MTU value.
364 *
365 * @param[in] device_id The device identifier.
366 * @param[in] mtu The new mtu value.
367 * @returns ENOENT if device is not found.
368 * @returns EOK on success.
369 */
370static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
[14f1db0]371{
[a64c64d]372 arp_device_ref device;
373
374 fibril_rwlock_write_lock(&arp_globals.lock);
[aadf01e]375 device = arp_cache_find(&arp_globals.cache, device_id);
[e9caf47]376 if (!device) {
[a64c64d]377 fibril_rwlock_write_unlock(&arp_globals.lock);
378 return ENOENT;
[aadf01e]379 }
[a64c64d]380 device->packet_dimension.content = mtu;
381 fibril_rwlock_write_unlock(&arp_globals.lock);
[e9caf47]382 printf("arp - device %d changed mtu to %d\n\n", device_id, mtu);
[a64c64d]383 return EOK;
384}
385
[e9caf47]386/** Processes the received ARP packet.
387 *
388 * Updates the source hardware address if the source entry exists or the packet
389 * is targeted to my protocol address.
390 * Responses to the ARP request if the packet is the ARP request and is
391 * targeted to my address.
392 *
393 * @param[in] device_id The source device identifier.
394 * @param[in,out] packet The received packet.
395 * @returns EOK on success and the packet is no longer needed.
396 * @returns One on success and the packet has been reused.
397 * @returns EINVAL if the packet is too small to carry an ARP
398 * packet.
399 * @returns EINVAL if the received address lengths differs from
400 * the registered values.
401 * @returns ENOENT if the device is not found in the cache.
402 * @returns ENOENT if the protocol for the device is not found in
403 * the cache.
404 * @returns ENOMEM if there is not enough memory left.
405 */
406static int arp_receive_message(device_id_t device_id, packet_t packet)
407{
[21580dd]408 ERROR_DECLARE;
409
[aadf01e]410 size_t length;
411 arp_header_ref header;
412 arp_device_ref device;
413 arp_proto_ref proto;
414 measured_string_ref hw_source;
[e9caf47]415 uint8_t *src_hw;
416 uint8_t *src_proto;
417 uint8_t *des_hw;
418 uint8_t *des_proto;
[aadf01e]419
420 length = packet_get_data_length(packet);
[e9caf47]421 if (length <= sizeof(arp_header_t))
[aadf01e]422 return EINVAL;
[e9caf47]423
[aadf01e]424 device = arp_cache_find(&arp_globals.cache, device_id);
[e9caf47]425 if (!device)
[aadf01e]426 return ENOENT;
[e9caf47]427
[aadf01e]428 header = (arp_header_ref) packet_get_data(packet);
[e9caf47]429 if ((ntohs(header->hardware) != device->hardware) ||
430 (length < sizeof(arp_header_t) + header->hardware_length * 2U +
431 header->protocol_length * 2U)) {
[21580dd]432 return EINVAL;
433 }
[e9caf47]434
435 proto = arp_protos_find(&device->protos,
436 protocol_unmap(device->service, ntohs(header->protocol)));
437 if (!proto)
[aadf01e]438 return ENOENT;
[e9caf47]439
[aadf01e]440 src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
[21580dd]441 src_proto = src_hw + header->hardware_length;
442 des_hw = src_proto + header->protocol_length;
443 des_proto = des_hw + header->hardware_length;
[e9caf47]444 hw_source = arp_addr_find(&proto->addresses, (char *) src_proto,
445 CONVERT_SIZE(uint8_t, char, header->protocol_length));
[21580dd]446 // exists?
[e9caf47]447 if (hw_source) {
448 if (hw_source->length != CONVERT_SIZE(uint8_t, char,
449 header->hardware_length)) {
[21580dd]450 return EINVAL;
451 }
[aadf01e]452 memcpy(hw_source->value, src_hw, hw_source->length);
[21580dd]453 }
454 // is my protocol address?
[e9caf47]455 if (proto->addr->length != CONVERT_SIZE(uint8_t, char,
456 header->protocol_length)) {
[21580dd]457 return EINVAL;
458 }
[e9caf47]459 if (!str_lcmp(proto->addr->value, (char *) des_proto,
460 proto->addr->length)) {
[21580dd]461 // not already upadted?
[e9caf47]462 if (!hw_source) {
463 hw_source = measured_string_create_bulk((char *) src_hw,
464 CONVERT_SIZE(uint8_t, char,
465 header->hardware_length));
466 if (!hw_source)
[aadf01e]467 return ENOMEM;
[e9caf47]468
469 ERROR_PROPAGATE(arp_addr_add(&proto->addresses,
470 (char *) src_proto, CONVERT_SIZE(uint8_t, char,
471 header->protocol_length), hw_source));
[21580dd]472 }
[e9caf47]473 if (ntohs(header->operation) == ARPOP_REQUEST) {
[aadf01e]474 header->operation = htons(ARPOP_REPLY);
475 memcpy(des_proto, src_proto, header->protocol_length);
[e9caf47]476 memcpy(src_proto, proto->addr->value,
477 header->protocol_length);
478 memcpy(src_hw, device->addr->value,
479 device->packet_dimension.addr_len);
480 memcpy(des_hw, hw_source->value,
481 header->hardware_length);
482 ERROR_PROPAGATE(packet_set_addr(packet, src_hw, des_hw,
483 header->hardware_length));
484 nil_send_msg(device->phone, device_id, packet,
485 SERVICE_ARP);
[21580dd]486 return 1;
487 }
488 }
[e9caf47]489
[21580dd]490 return EOK;
491}
492
[e9caf47]493
494/** Returns the hardware address for the given protocol address.
495 *
496 * Sends the ARP request packet if the hardware address is not found in the
497 * cache.
498 *
499 * @param[in] device_id The device identifier.
500 * @param[in] protocol The protocol service.
501 * @param[in] target The target protocol address.
502 * @returns The hardware address of the target.
503 * @returns NULL if the target parameter is NULL.
504 * @returns NULL if the device is not found.
505 * @returns NULL if the device packet is too small to send a
506 * request.
507 * @returns NULL if the hardware address is not found in the cache.
508 */
509static measured_string_ref
510arp_translate_message(device_id_t device_id, services_t protocol,
511 measured_string_ref target)
512{
[aadf01e]513 arp_device_ref device;
[a64c64d]514 arp_proto_ref proto;
515 measured_string_ref addr;
516 size_t length;
517 packet_t packet;
518 arp_header_ref header;
[21580dd]519
[e9caf47]520 if (!target)
[a64c64d]521 return NULL;
[e9caf47]522
[aadf01e]523 device = arp_cache_find(&arp_globals.cache, device_id);
[e9caf47]524 if (!device)
[a64c64d]525 return NULL;
[e9caf47]526
[a64c64d]527 proto = arp_protos_find(&device->protos, protocol);
[e9caf47]528 if (!proto || (proto->addr->length != target->length))
[a64c64d]529 return NULL;
[e9caf47]530
[a64c64d]531 addr = arp_addr_find(&proto->addresses, target->value, target->length);
[e9caf47]532 if (addr)
[a64c64d]533 return addr;
[e9caf47]534
[a64c64d]535 // ARP packet content size = header + (address + translation) * 2
[e9caf47]536 length = 8 + 2 * (CONVERT_SIZE(char, uint8_t, proto->addr->length) +
537 CONVERT_SIZE(char, uint8_t, device->addr->length));
538 if (length > device->packet_dimension.content)
[a64c64d]539 return NULL;
[e9caf47]540
541 packet = packet_get_4_remote(arp_globals.net_phone,
542 device->packet_dimension.addr_len, device->packet_dimension.prefix,
543 length, device->packet_dimension.suffix);
544 if (!packet)
[a64c64d]545 return NULL;
[e9caf47]546
[a64c64d]547 header = (arp_header_ref) packet_suffix(packet, length);
[e9caf47]548 if (!header) {
[14f1db0]549 pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
[a64c64d]550 return NULL;
551 }
[e9caf47]552
[a64c64d]553 header->hardware = htons(device->hardware);
554 header->hardware_length = (uint8_t) device->addr->length;
555 header->protocol = htons(protocol_map(device->service, protocol));
556 header->protocol_length = (uint8_t) proto->addr->length;
557 header->operation = htons(ARPOP_REQUEST);
558 length = sizeof(arp_header_t);
[e9caf47]559 memcpy(((uint8_t *) header) + length, device->addr->value,
560 device->addr->length);
[a64c64d]561 length += device->addr->length;
[e9caf47]562 memcpy(((uint8_t *) header) + length, proto->addr->value,
563 proto->addr->length);
[a64c64d]564 length += proto->addr->length;
565 bzero(((uint8_t *) header) + length, device->addr->length);
566 length += device->addr->length;
567 memcpy(((uint8_t *) header) + length, target->value, target->length);
[e9caf47]568
569 if (packet_set_addr(packet, (uint8_t *) device->addr->value,
570 (uint8_t *) device->broadcast_addr->value,
571 CONVERT_SIZE(char, uint8_t, device->addr->length)) != EOK) {
[14f1db0]572 pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
[a64c64d]573 return NULL;
574 }
[e9caf47]575
[a64c64d]576 nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
577 return NULL;
[21580dd]578}
579
[e9caf47]580
581/** Processes the ARP message.
[849ed54]582 *
[e9caf47]583 * @param[in] callid The message identifier.
584 * @param[in] call The message parameters.
585 * @param[out] answer The message answer parameters.
586 * @param[out] answer_count The last parameter for the actual answer in the
587 * answer parameter.
588 * @returns EOK on success.
589 * @returns ENOTSUP if the message is not known.
[849ed54]590 *
[e9caf47]591 * @see arp_interface.h
592 * @see IS_NET_ARP_MESSAGE()
[849ed54]593 */
[e9caf47]594int
595arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
596 ipc_call_t *answer, int *answer_count)
597{
598 ERROR_DECLARE;
599
600 measured_string_ref address;
601 measured_string_ref translation;
602 char *data;
603 packet_t packet;
604 packet_t next;
605
606 *answer_count = 0;
607 switch (IPC_GET_METHOD(*call)) {
608 case IPC_M_PHONE_HUNGUP:
609 return EOK;
610
611 case NET_ARP_DEVICE:
612 ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
613 if (ERROR_OCCURRED(arp_device_message(IPC_GET_DEVICE(call),
614 IPC_GET_SERVICE(call), ARP_GET_NETIF(call), address))) {
615 free(address);
616 free(data);
617 }
618 return ERROR_CODE;
619
620 case NET_ARP_TRANSLATE:
621 ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
622 fibril_rwlock_read_lock(&arp_globals.lock);
623 translation = arp_translate_message(IPC_GET_DEVICE(call),
624 IPC_GET_SERVICE(call), address);
625 free(address);
626 free(data);
627 if (!translation) {
628 fibril_rwlock_read_unlock(&arp_globals.lock);
629 return ENOENT;
630 }
631 ERROR_CODE = measured_strings_reply(translation, 1);
632 fibril_rwlock_read_unlock(&arp_globals.lock);
633 return ERROR_CODE;
634
635 case NET_ARP_CLEAR_DEVICE:
636 return arp_clear_device_req(0, IPC_GET_DEVICE(call));
637
638 case NET_ARP_CLEAR_ADDRESS:
639 ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
640 arp_clear_address_req(0, IPC_GET_DEVICE(call),
641 IPC_GET_SERVICE(call), address);
642 free(address);
643 free(data);
644 return EOK;
645
646 case NET_ARP_CLEAN_CACHE:
647 return arp_clean_cache_req(0);
648
649 case NET_IL_DEVICE_STATE:
650 // do nothing - keep the cache
651 return EOK;
652
653 case NET_IL_RECEIVED:
654 if (ERROR_NONE(packet_translate_remote(arp_globals.net_phone,
655 &packet, IPC_GET_PACKET(call)))) {
656 fibril_rwlock_read_lock(&arp_globals.lock);
657 do {
658 next = pq_detach(packet);
659 ERROR_CODE =
660 arp_receive_message(IPC_GET_DEVICE(call),
661 packet);
662 if (ERROR_CODE != 1) {
663 pq_release_remote(arp_globals.net_phone,
664 packet_get_id(packet));
665 }
666 packet = next;
667 } while (packet);
668 fibril_rwlock_read_unlock(&arp_globals.lock);
669 }
670 return ERROR_CODE;
671
672 case NET_IL_MTU_CHANGED:
673 return arp_mtu_changed_message(IPC_GET_DEVICE(call),
674 IPC_GET_MTU(call));
675 }
676
677 return ENOTSUP;
678}
679
680/** Default thread for new connections.
681 *
682 * @param[in] iid The initial message identifier.
683 * @param[in] icall The initial message call structure.
684 */
685static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
[849ed54]686{
687 /*
688 * Accept the connection
689 * - Answer the first IPC_M_CONNECT_ME_TO call.
690 */
691 ipc_answer_0(iid, EOK);
692
[e9caf47]693 while (true) {
[849ed54]694 ipc_call_t answer;
695 int answer_count;
696
697 /* Clear the answer structure */
698 refresh_answer(&answer, &answer_count);
699
700 /* Fetch the next message */
701 ipc_call_t call;
702 ipc_callid_t callid = async_get_call(&call);
703
704 /* Process the message */
[14f1db0]705 int res = il_module_message_standalone(callid, &call, &answer,
706 &answer_count);
[849ed54]707
[e9caf47]708 /*
709 * End if told to either by the message or the processing
710 * result.
711 */
712 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
713 (res == EHANGUP))
[849ed54]714 return;
715
716 /* Answer the message */
717 answer_call(callid, res, &answer, answer_count);
718 }
719}
720
721/** Starts the module.
722 *
[e9caf47]723 * @returns EOK on success.
724 * @returns Other error codes as defined for each specific module
725 * start function.
[849ed54]726 */
727int main(int argc, char *argv[])
728{
729 ERROR_DECLARE;
730
731 /* Start the module */
[e9caf47]732 ERROR_PROPAGATE(il_module_start_standalone(il_client_connection));
[849ed54]733 return EOK;
734}
735
[21580dd]736/** @}
737 */
[e9caf47]738
Note: See TracBrowser for help on using the repository browser.