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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1bfd3d3 was 1bfd3d3, checked in by Jiri Svoboda <jiri@…>, 15 years ago

Replace @returns with @return.

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