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
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 <async.h>
39#include <malloc.h>
40#include <mem.h>
41#include <fibril_synch.h>
42#include <stdio.h>
43#include <str.h>
44#include <task.h>
45#include <ipc/ipc.h>
46#include <ipc/services.h>
47#include <ipc/net.h>
48#include <ipc/arp.h>
49#include <ipc/il.h>
50#include <byteorder.h>
51#include <err.h>
52
53#include <net/modules.h>
54#include <net/device.h>
55#include <arp_interface.h>
56#include <nil_interface.h>
57#include <protocol_map.h>
58#include <adt/measured_strings.h>
59#include <net/packet.h>
60#include <packet_client.h>
61#include <packet_remote.h>
62#include <il_interface.h>
63#include <il_local.h>
64
65#include "arp.h"
66#include "arp_header.h"
67#include "arp_oc.h"
68#include "arp_module.h"
69
70
71/** ARP module name.
72 */
73#define NAME "arp"
74
75/** ARP global data.
76 */
77arp_globals_t arp_globals;
78
79/** Clears the device specific data.
80 * @param[in] device The device specific data.
81 */
82void arp_clear_device(arp_device_ref device);
83
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 */
92int arp_proto_create(arp_proto_ref * proto, services_t service, measured_string_ref address);
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 */
109int arp_device_message(device_id_t device_id, services_t service, services_t protocol, measured_string_ref address);
110
111/** Updates the device content length according to the new MTU value.
112 * @param[in] device_id The device identifier.
113 * @param[in] mtu The new mtu value.
114 * @returns ENOENT if device is not found.
115 * @returns EOK on success.
116 */
117int arp_mtu_changed_message(device_id_t device_id, size_t mtu);
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 */
132int arp_receive_message(device_id_t device_id, packet_t packet);
133
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.
136 * @param[in] device_id The device identifier.
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.
144 */
145measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target);
146
147/*@}*/
148
149DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t)
150
151INT_MAP_IMPLEMENT(arp_protos, arp_proto_t)
152
153GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t)
154
155int arp_clean_cache_req(int arp_phone){
156 int count;
157 arp_device_ref device;
158
159 fibril_rwlock_write_lock(&arp_globals.lock);
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 }
171 }
172 arp_cache_clear(&arp_globals.cache);
173 fibril_rwlock_write_unlock(&arp_globals.lock);
174 printf("Cache cleaned\n");
175 return EOK;
176}
177
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;
181
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);
186 return ENOENT;
187 }
188 proto = arp_protos_find(&device->protos, protocol);
189 if(! proto){
190 fibril_rwlock_write_unlock(&arp_globals.lock);
191 return ENOENT;
192 }
193 arp_addr_exclude(&proto->addresses, address->value, address->length);
194 fibril_rwlock_write_unlock(&arp_globals.lock);
195 return EOK;
196}
197
198void arp_clear_device(arp_device_ref device){
199 int count;
200 arp_proto_ref proto;
201
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);
207 }
208 if(proto->addr_data){
209 free(proto->addr_data);
210 }
211 arp_addr_destroy(&proto->addresses);
212 }
213 }
214 arp_protos_clear(&device->protos);
215}
216
217int arp_clear_device_req(int arp_phone, device_id_t device_id){
218 arp_device_ref device;
219
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);
224 return ENOENT;
225 }
226 arp_clear_device(device);
227 printf("Device %d cleared\n", device_id);
228 fibril_rwlock_write_unlock(&arp_globals.lock);
229 return EOK;
230}
231
232int arp_device_message(device_id_t device_id, services_t service, services_t protocol, measured_string_ref address){
233 ERROR_DECLARE;
234
235 arp_device_ref device;
236 arp_proto_ref proto;
237 int index;
238 hw_type_t hardware;
239
240 fibril_rwlock_write_lock(&arp_globals.lock);
241 // an existing device?
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);
247 return EEXIST;
248 }
249 proto = arp_protos_find(&device->protos, protocol);
250 if(proto){
251 free(proto->addr);
252 free(proto->addr_data);
253 proto->addr = address;
254 proto->addr_data = address->value;
255 }else{
256 if(ERROR_OCCURRED(arp_proto_create(&proto, protocol, address))){
257 fibril_rwlock_write_unlock(&arp_globals.lock);
258 return ERROR_CODE;
259 }
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);
264 return index;
265 }
266 printf("New protocol added:\n\tdevice id\t= %d\n\tproto\t= %d", device_id, protocol);
267 }
268 }else{
269 hardware = hardware_map(service);
270 if(! hardware){
271 return ENOENT;
272 }
273 // create a new device
274 device = (arp_device_ref) malloc(sizeof(arp_device_t));
275 if(! device){
276 fibril_rwlock_write_unlock(&arp_globals.lock);
277 return ENOMEM;
278 }
279 device->hardware = hardware;
280 device->device_id = device_id;
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);
285 return ERROR_CODE;
286 }
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);
292 return index;
293 }
294 device->service = service;
295 // bind the new one
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);
301 return EREFUSED;
302 }
303 // get packet dimensions
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);
308 return ERROR_CODE;
309 }
310 // get hardware address
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);
315 return ERROR_CODE;
316 }
317 // get broadcast address
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);
324 return ERROR_CODE;
325 }
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);
334 return ERROR_CODE;
335 }
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);
338 }
339 fibril_rwlock_write_unlock(&arp_globals.lock);
340 return EOK;
341}
342
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
368int arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
369 ipc_call_t *answer, int *answer_count)
370{
371 ERROR_DECLARE;
372
373 measured_string_ref address;
374 measured_string_ref translation;
375 char * data;
376 packet_t packet;
377 packet_t next;
378
379 *answer_count = 0;
380 switch (IPC_GET_METHOD(*call)) {
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:
417 if(! ERROR_OCCURRED(packet_translate_remote(arp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
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){
423 pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
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));
432 }
433
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);
441 device = arp_cache_find(&arp_globals.cache, device_id);
442 if(! device){
443 fibril_rwlock_write_unlock(&arp_globals.lock);
444 return ENOENT;
445 }
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;
458 }
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;
465 }
466 return EOK;
467}
468
469int arp_receive_message(device_id_t device_id, packet_t packet){
470 ERROR_DECLARE;
471
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)){
493 return EINVAL;
494 }
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);
500 src_proto = src_hw + header->hardware_length;
501 des_hw = src_proto + header->protocol_length;
502 des_proto = des_hw + header->hardware_length;
503 hw_source = arp_addr_find(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length));
504 // exists?
505 if(hw_source){
506 if(hw_source->length != CONVERT_SIZE(uint8_t, char, header->hardware_length)){
507 return EINVAL;
508 }
509 memcpy(hw_source->value, src_hw, hw_source->length);
510 }
511 // is my protocol address?
512 if(proto->addr->length != CONVERT_SIZE(uint8_t, char, header->protocol_length)){
513 return EINVAL;
514 }
515 if(! str_lcmp(proto->addr->value, (char *) des_proto, proto->addr->length)){
516 // not already upadted?
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));
523 }
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);
532 return 1;
533 }
534 }
535 return EOK;
536}
537
538task_id_t arp_task_get_id(void){
539 return task_get_id();
540}
541
542measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target){
543 arp_device_ref device;
544 arp_proto_ref proto;
545 measured_string_ref addr;
546 size_t length;
547 packet_t packet;
548 arp_header_ref header;
549
550 if(! target){
551 return NULL;
552 }
553 device = arp_cache_find(&arp_globals.cache, device_id);
554 if(! device){
555 return NULL;
556 }
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 }
570 packet = packet_get_4_remote(arp_globals.net_phone, device->packet_dimension.addr_len, device->packet_dimension.prefix, length, device->packet_dimension.suffix);
571 if(! packet){
572 return NULL;
573 }
574 header = (arp_header_ref) packet_suffix(packet, length);
575 if(! header){
576 pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
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){
593 pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
594 return NULL;
595 }
596 nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
597 return NULL;
598}
599
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 */
626 int res = il_module_message_standalone(callid, &call, &answer,
627 &answer_count);
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 */
652 if (ERROR_OCCURRED(il_module_start_standalone(il_client_connection)))
653 return ERROR_CODE;
654
655 return EOK;
656}
657
658/** @}
659 */
Note: See TracBrowser for help on using the repository browser.