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

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

Cleanup arp.

  • Property mode set to 100644
File size: 20.8 KB
Line 
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 "arp.h"
39#include "arp_header.h"
40#include "arp_oc.h"
41#include "arp_module.h"
42
43#include <async.h>
44#include <malloc.h>
45#include <mem.h>
46#include <fibril_synch.h>
47#include <stdio.h>
48#include <str.h>
49#include <task.h>
50#include <adt/measured_strings.h>
51#include <ipc/ipc.h>
52#include <ipc/services.h>
53#include <ipc/net.h>
54#include <ipc/arp.h>
55#include <ipc/il.h>
56#include <byteorder.h>
57#include <err.h>
58
59#include <net/modules.h>
60#include <net/device.h>
61#include <net/packet.h>
62
63#include <nil_interface.h>
64#include <protocol_map.h>
65#include <packet_client.h>
66#include <packet_remote.h>
67#include <il_interface.h>
68#include <il_local.h>
69
70
71/** ARP module name. */
72#define NAME "arp"
73
74/** ARP global data. */
75arp_globals_t arp_globals;
76
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);
80
81/** Clears the device specific data.
82 *
83 * @param[in] device The device specific data.
84 */
85static void arp_clear_device(arp_device_ref device)
86{
87 int count;
88 arp_proto_ref proto;
89
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}
103
104static int arp_clean_cache_req(int arp_phone)
105{
106 int count;
107 arp_device_ref device;
108
109 fibril_rwlock_write_lock(&arp_globals.lock);
110 for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
111 count--) {
112 device = arp_cache_get_index(&arp_globals.cache, count);
113 if (device) {
114 arp_clear_device(device);
115 if (device->addr_data)
116 free(device->addr_data);
117 if (device->broadcast_data)
118 free(device->broadcast_data);
119 }
120 }
121 arp_cache_clear(&arp_globals.cache);
122 fibril_rwlock_write_unlock(&arp_globals.lock);
123 printf("Cache cleaned\n");
124 return EOK;
125}
126
127static int
128arp_clear_address_req(int arp_phone, device_id_t device_id, services_t protocol,
129 measured_string_ref address)
130{
131 arp_device_ref device;
132 arp_proto_ref proto;
133
134 fibril_rwlock_write_lock(&arp_globals.lock);
135 device = arp_cache_find(&arp_globals.cache, device_id);
136 if (!device) {
137 fibril_rwlock_write_unlock(&arp_globals.lock);
138 return ENOENT;
139 }
140 proto = arp_protos_find(&device->protos, protocol);
141 if (!proto) {
142 fibril_rwlock_write_unlock(&arp_globals.lock);
143 return ENOENT;
144 }
145 arp_addr_exclude(&proto->addresses, address->value, address->length);
146 fibril_rwlock_write_unlock(&arp_globals.lock);
147 return EOK;
148}
149
150
151static int arp_clear_device_req(int arp_phone, device_id_t device_id)
152{
153 arp_device_ref device;
154
155 fibril_rwlock_write_lock(&arp_globals.lock);
156 device = arp_cache_find(&arp_globals.cache, device_id);
157 if (!device) {
158 fibril_rwlock_write_unlock(&arp_globals.lock);
159 return ENOENT;
160 }
161 arp_clear_device(device);
162 printf("Device %d cleared\n", device_id);
163 fibril_rwlock_write_unlock(&arp_globals.lock);
164 return EOK;
165}
166
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{
216 ERROR_DECLARE;
217
218 arp_device_ref device;
219 arp_proto_ref proto;
220 int index;
221 hw_type_t hardware;
222
223 fibril_rwlock_write_lock(&arp_globals.lock);
224 // an existing device?
225 device = arp_cache_find(&arp_globals.cache, device_id);
226 if (device) {
227 if (device->service != service) {
228 printf("Device %d already exists\n", device->device_id);
229 fibril_rwlock_write_unlock(&arp_globals.lock);
230 return EEXIST;
231 }
232 proto = arp_protos_find(&device->protos, protocol);
233 if (proto) {
234 free(proto->addr);
235 free(proto->addr_data);
236 proto->addr = address;
237 proto->addr_data = address->value;
238 } else {
239 if (ERROR_OCCURRED(arp_proto_create(&proto, protocol,
240 address))) {
241 fibril_rwlock_write_unlock(&arp_globals.lock);
242 return ERROR_CODE;
243 }
244 index = arp_protos_add(&device->protos, proto->service,
245 proto);
246 if (index < 0) {
247 fibril_rwlock_write_unlock(&arp_globals.lock);
248 free(proto);
249 return index;
250 }
251 printf("New protocol added:\n\tdevice id\t= "
252 "%d\n\tproto\t= %d", device_id, protocol);
253 }
254 } else {
255 hardware = hardware_map(service);
256 if (!hardware)
257 return ENOENT;
258
259 // create a new device
260 device = (arp_device_ref) malloc(sizeof(arp_device_t));
261 if (!device) {
262 fibril_rwlock_write_unlock(&arp_globals.lock);
263 return ENOMEM;
264 }
265 device->hardware = hardware;
266 device->device_id = device_id;
267 if (ERROR_OCCURRED(arp_protos_initialize(&device->protos)) ||
268 ERROR_OCCURRED(arp_proto_create(&proto, protocol,
269 address))) {
270 fibril_rwlock_write_unlock(&arp_globals.lock);
271 free(device);
272 return ERROR_CODE;
273 }
274 index = arp_protos_add(&device->protos, proto->service, proto);
275 if (index < 0) {
276 fibril_rwlock_write_unlock(&arp_globals.lock);
277 arp_protos_destroy(&device->protos);
278 free(device);
279 return index;
280 }
281 device->service = service;
282
283 // bind the new one
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) {
288 fibril_rwlock_write_unlock(&arp_globals.lock);
289 arp_protos_destroy(&device->protos);
290 free(device);
291 return EREFUSED;
292 }
293
294 // get packet dimensions
295 if (ERROR_OCCURRED(nil_packet_size_req(device->phone, device_id,
296 &device->packet_dimension))) {
297 fibril_rwlock_write_unlock(&arp_globals.lock);
298 arp_protos_destroy(&device->protos);
299 free(device);
300 return ERROR_CODE;
301 }
302
303 // get hardware address
304 if (ERROR_OCCURRED(nil_get_addr_req(device->phone, device_id,
305 &device->addr, &device->addr_data))) {
306 fibril_rwlock_write_unlock(&arp_globals.lock);
307 arp_protos_destroy(&device->protos);
308 free(device);
309 return ERROR_CODE;
310 }
311
312 // get broadcast address
313 if (ERROR_OCCURRED(nil_get_broadcast_addr_req(device->phone,
314 device_id, &device->broadcast_addr,
315 &device->broadcast_data))) {
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);
321 return ERROR_CODE;
322 }
323
324 if (ERROR_OCCURRED(arp_cache_add(&arp_globals.cache,
325 device->device_id, device))) {
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);
333 return ERROR_CODE;
334 }
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);
338 }
339 fibril_rwlock_write_unlock(&arp_globals.lock);
340
341 return EOK;
342}
343
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{
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
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)
371{
372 arp_device_ref device;
373
374 fibril_rwlock_write_lock(&arp_globals.lock);
375 device = arp_cache_find(&arp_globals.cache, device_id);
376 if (!device) {
377 fibril_rwlock_write_unlock(&arp_globals.lock);
378 return ENOENT;
379 }
380 device->packet_dimension.content = mtu;
381 fibril_rwlock_write_unlock(&arp_globals.lock);
382 printf("arp - device %d changed mtu to %d\n\n", device_id, mtu);
383 return EOK;
384}
385
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{
408 ERROR_DECLARE;
409
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;
415 uint8_t *src_hw;
416 uint8_t *src_proto;
417 uint8_t *des_hw;
418 uint8_t *des_proto;
419
420 length = packet_get_data_length(packet);
421 if (length <= sizeof(arp_header_t))
422 return EINVAL;
423
424 device = arp_cache_find(&arp_globals.cache, device_id);
425 if (!device)
426 return ENOENT;
427
428 header = (arp_header_ref) packet_get_data(packet);
429 if ((ntohs(header->hardware) != device->hardware) ||
430 (length < sizeof(arp_header_t) + header->hardware_length * 2U +
431 header->protocol_length * 2U)) {
432 return EINVAL;
433 }
434
435 proto = arp_protos_find(&device->protos,
436 protocol_unmap(device->service, ntohs(header->protocol)));
437 if (!proto)
438 return ENOENT;
439
440 src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
441 src_proto = src_hw + header->hardware_length;
442 des_hw = src_proto + header->protocol_length;
443 des_proto = des_hw + header->hardware_length;
444 hw_source = arp_addr_find(&proto->addresses, (char *) src_proto,
445 CONVERT_SIZE(uint8_t, char, header->protocol_length));
446 // exists?
447 if (hw_source) {
448 if (hw_source->length != CONVERT_SIZE(uint8_t, char,
449 header->hardware_length)) {
450 return EINVAL;
451 }
452 memcpy(hw_source->value, src_hw, hw_source->length);
453 }
454 // is my protocol address?
455 if (proto->addr->length != CONVERT_SIZE(uint8_t, char,
456 header->protocol_length)) {
457 return EINVAL;
458 }
459 if (!str_lcmp(proto->addr->value, (char *) des_proto,
460 proto->addr->length)) {
461 // not already upadted?
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)
467 return ENOMEM;
468
469 ERROR_PROPAGATE(arp_addr_add(&proto->addresses,
470 (char *) src_proto, CONVERT_SIZE(uint8_t, char,
471 header->protocol_length), hw_source));
472 }
473 if (ntohs(header->operation) == ARPOP_REQUEST) {
474 header->operation = htons(ARPOP_REPLY);
475 memcpy(des_proto, src_proto, header->protocol_length);
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);
486 return 1;
487 }
488 }
489
490 return EOK;
491}
492
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{
513 arp_device_ref device;
514 arp_proto_ref proto;
515 measured_string_ref addr;
516 size_t length;
517 packet_t packet;
518 arp_header_ref header;
519
520 if (!target)
521 return NULL;
522
523 device = arp_cache_find(&arp_globals.cache, device_id);
524 if (!device)
525 return NULL;
526
527 proto = arp_protos_find(&device->protos, protocol);
528 if (!proto || (proto->addr->length != target->length))
529 return NULL;
530
531 addr = arp_addr_find(&proto->addresses, target->value, target->length);
532 if (addr)
533 return addr;
534
535 // ARP packet content size = header + (address + translation) * 2
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)
539 return NULL;
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)
545 return NULL;
546
547 header = (arp_header_ref) packet_suffix(packet, length);
548 if (!header) {
549 pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
550 return NULL;
551 }
552
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);
559 memcpy(((uint8_t *) header) + length, device->addr->value,
560 device->addr->length);
561 length += device->addr->length;
562 memcpy(((uint8_t *) header) + length, proto->addr->value,
563 proto->addr->length);
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);
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) {
572 pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
573 return NULL;
574 }
575
576 nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
577 return NULL;
578}
579
580
581/** Processes the ARP message.
582 *
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.
590 *
591 * @see arp_interface.h
592 * @see IS_NET_ARP_MESSAGE()
593 */
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)
686{
687 /*
688 * Accept the connection
689 * - Answer the first IPC_M_CONNECT_ME_TO call.
690 */
691 ipc_answer_0(iid, EOK);
692
693 while (true) {
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 */
705 int res = il_module_message_standalone(callid, &call, &answer,
706 &answer_count);
707
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))
714 return;
715
716 /* Answer the message */
717 answer_call(callid, res, &answer, answer_count);
718 }
719}
720
721/** Starts the module.
722 *
723 * @returns EOK on success.
724 * @returns Other error codes as defined for each specific module
725 * start function.
726 */
727int main(int argc, char *argv[])
728{
729 ERROR_DECLARE;
730
731 /* Start the module */
732 ERROR_PROPAGATE(il_module_start_standalone(il_client_connection));
733 return EOK;
734}
735
736/** @}
737 */
738
Note: See TracBrowser for help on using the repository browser.