Changeset 60b2b69 in mainline for uspace/srv/net/il/ip/ip.c


Ignore:
Timestamp:
2011-01-14T13:04:10Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5f635ca
Parents:
5ccb15c (diff), 00c2d035 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge development/ changes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/il/ip/ip.c

    r5ccb15c r60b2b69  
    3535 * @see arp.h
    3636 */
    37 
    38 #include "ip.h"
    39 #include "ip_module.h"
    4037
    4138#include <async.h>
     
    5249#include <sys/types.h>
    5350#include <byteorder.h>
     51#include "ip.h"
    5452
    5553#include <adt/measured_strings.h>
     
    7068#include <icmp_client.h>
    7169#include <icmp_interface.h>
    72 #include <il_interface.h>
    7370#include <ip_client.h>
    7471#include <ip_interface.h>
    7572#include <ip_header.h>
    7673#include <net_interface.h>
    77 #include <nil_interface.h>
    78 #include <tl_interface.h>
     74#include <nil_remote.h>
     75#include <tl_remote.h>
    7976#include <packet_remote.h>
    80 #include <il_local.h>
     77#include <il_remote.h>
     78#include <il_skel.h>
    8179
    8280/** IP module name. */
     
    122120INT_MAP_IMPLEMENT(ip_protos, ip_proto_t);
    123121GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t);
     122
     123static void ip_receiver(ipc_callid_t, ipc_call_t *);
    124124
    125125/** Releases the packet and returns the result.
     
    244244}
    245245
    246 /** Initializes the IP module.
    247  *
    248  * @param[in] client_connection The client connection processing function. The
    249  *                      module skeleton propagates its own one.
    250  * @return              EOK on success.
    251  * @return              ENOMEM if there is not enough memory left.
    252  */
    253 int ip_initialize(async_client_conn_t client_connection)
    254 {
    255         int rc;
    256 
     246int il_initialize(int net_phone)
     247{
    257248        fibril_rwlock_initialize(&ip_globals.lock);
    258249        fibril_rwlock_write_lock(&ip_globals.lock);
    259250        fibril_rwlock_initialize(&ip_globals.protos_lock);
    260251        fibril_rwlock_initialize(&ip_globals.netifs_lock);
     252       
     253        ip_globals.net_phone = net_phone;
    261254        ip_globals.packet_counter = 0;
    262255        ip_globals.gateway.address.s_addr = 0;
     
    264257        ip_globals.gateway.gateway.s_addr = 0;
    265258        ip_globals.gateway.netif = NULL;
    266         ip_globals.client_connection = client_connection;
    267        
    268         rc = ip_netifs_initialize(&ip_globals.netifs);
     259       
     260        int rc = ip_netifs_initialize(&ip_globals.netifs);
    269261        if (rc != EOK)
    270262                goto out;
     
    431423        ip_netif->phone = nil_bind_service(ip_netif->service,
    432424            (sysarg_t) ip_netif->device_id, SERVICE_IP,
    433             ip_globals.client_connection);
     425            ip_receiver);
    434426        if (ip_netif->phone < 0) {
    435427                printf("Failed to contact the nil service %d\n",
     
    487479}
    488480
    489 /** Updates the device content length according to the new MTU value.
    490  *
    491  * @param[in] device_id The device identifier.
    492  * @param[in] mtu       The new mtu value.
    493  * @return              EOK on success.
    494  * @return              ENOENT if device is not found.
    495  */
    496 static int ip_mtu_changed_message(device_id_t device_id, size_t mtu)
    497 {
     481static int ip_device_req_local(int il_phone, device_id_t device_id,
     482    services_t netif)
     483{
     484        ip_netif_t *ip_netif;
     485        ip_route_t *route;
     486        int index;
     487        int rc;
     488
     489        ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t));
     490        if (!ip_netif)
     491                return ENOMEM;
     492
     493        rc = ip_routes_initialize(&ip_netif->routes);
     494        if (rc != EOK) {
     495                free(ip_netif);
     496                return rc;
     497        }
     498
     499        ip_netif->device_id = device_id;
     500        ip_netif->service = netif;
     501        ip_netif->state = NETIF_STOPPED;
     502
     503        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     504
     505        rc = ip_netif_initialize(ip_netif);
     506        if (rc != EOK) {
     507                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     508                ip_routes_destroy(&ip_netif->routes);
     509                free(ip_netif);
     510                return rc;
     511        }
     512        if (ip_netif->arp)
     513                ip_netif->arp->usage++;
     514
     515        // print the settings
     516        printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
     517            NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv,
     518            ip_netif->dhcp ? "dhcp" : "static");
     519       
     520        // TODO ipv6 addresses
     521       
     522        char address[INET_ADDRSTRLEN];
     523        char netmask[INET_ADDRSTRLEN];
     524        char gateway[INET_ADDRSTRLEN];
     525       
     526        for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
     527                route = ip_routes_get_index(&ip_netif->routes, index);
     528                if (route) {
     529                        inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr,
     530                            address, INET_ADDRSTRLEN);
     531                        inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr,
     532                            netmask, INET_ADDRSTRLEN);
     533                        inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr,
     534                            gateway, INET_ADDRSTRLEN);
     535                        printf("%s: Route %d (address: %s, netmask: %s, "
     536                            "gateway: %s)\n", NAME, index, address, netmask,
     537                            gateway);
     538                }
     539        }
     540       
     541        inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
     542            INET_ADDRSTRLEN);
     543        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     544
     545        printf("%s: Broadcast (%s)\n", NAME, address);
     546
     547        return EOK;
     548}
     549
     550/** Searches the network interfaces if there is a suitable route.
     551 *
     552 * @param[in] netif     The network interface to be searched for routes. May be
     553 *                      NULL.
     554 * @param[in] destination The destination address.
     555 * @return              The found route.
     556 * @return              NULL if no route was found.
     557 */
     558static ip_route_t *ip_netif_find_route(ip_netif_t *netif,
     559    in_addr_t destination)
     560{
     561        int index;
     562        ip_route_t *route;
     563       
     564        if (!netif)
     565                return NULL;
     566       
     567        /* Start with the first one (the direct route) */
     568        for (index = 0; index < ip_routes_count(&netif->routes); index++) {
     569                route = ip_routes_get_index(&netif->routes, index);
     570                if ((route) &&
     571                    ((route->address.s_addr & route->netmask.s_addr) ==
     572                    (destination.s_addr & route->netmask.s_addr)))
     573                        return route;
     574        }
     575
     576        return NULL;
     577}
     578
     579/** Searches all network interfaces if there is a suitable route.
     580 *
     581 * @param[in] destination The destination address.
     582 * @return              The found route.
     583 * @return              NULL if no route was found.
     584 */
     585static ip_route_t *ip_find_route(in_addr_t destination) {
     586        int index;
     587        ip_route_t *route;
    498588        ip_netif_t *netif;
    499589
    500         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    501         netif = ip_netifs_find(&ip_globals.netifs, device_id);
    502         if (!netif) {
    503                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    504                 return ENOENT;
    505         }
    506         netif->packet_dimension.content = mtu;
    507         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    508 
    509         printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
    510 
    511         return EOK;
    512 }
    513 
    514 /** Updates the device state.
    515  *
    516  * @param[in] device_id The device identifier.
    517  * @param[in] state     The new state value.
    518  * @return              EOK on success.
    519  * @return              ENOENT if device is not found.
    520  */
    521 static int ip_device_state_message(device_id_t device_id, device_state_t state)
    522 {
    523         ip_netif_t *netif;
    524 
    525         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    526         // find the device
    527         netif = ip_netifs_find(&ip_globals.netifs, device_id);
    528         if (!netif) {
    529                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    530                 return ENOENT;
    531         }
    532         netif->state = state;
    533         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    534 
    535         printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
    536 
    537         return EOK;
    538 }
    539 
    540 
    541 /** Prefixes a middle fragment header based on the last fragment header to the
    542  * packet.
    543  *
    544  * @param[in] packet    The packet to be prefixed.
    545  * @param[in] last      The last header to be copied.
    546  * @return              The prefixed middle header.
    547  * @return              NULL on error.
    548  */
    549 static ip_header_t *
    550 ip_create_middle_header(packet_t *packet, ip_header_t *last)
    551 {
    552         ip_header_t *middle;
    553 
    554         middle = (ip_header_t *) packet_suffix(packet, IP_HEADER_LENGTH(last));
    555         if (!middle)
    556                 return NULL;
    557         memcpy(middle, last, IP_HEADER_LENGTH(last));
    558         middle->flags |= IPFLAG_MORE_FRAGMENTS;
    559         return middle;
     590        // start with the last netif - the newest one
     591        index = ip_netifs_count(&ip_globals.netifs) - 1;
     592        while (index >= 0) {
     593                netif = ip_netifs_get_index(&ip_globals.netifs, index);
     594                if (netif && (netif->state == NETIF_ACTIVE)) {
     595                        route = ip_netif_find_route(netif, destination);
     596                        if (route)
     597                                return route;
     598                }
     599                index--;
     600        }
     601
     602        return &ip_globals.gateway;
     603}
     604
     605/** Returns the network interface's IP address.
     606 *
     607 * @param[in] netif     The network interface.
     608 * @return              The IP address.
     609 * @return              NULL if no IP address was found.
     610 */
     611static in_addr_t *ip_netif_address(ip_netif_t *netif)
     612{
     613        ip_route_t *route;
     614
     615        route = ip_routes_get_index(&netif->routes, 0);
     616        return route ? &route->address : NULL;
    560617}
    561618
     
    626683 *                      function.
    627684 */
    628 static int
    629 ip_prepare_packet(in_addr_t *source, in_addr_t dest, packet_t *packet,
    630     measured_string_t *destination)
     685static int ip_prepare_packet(in_addr_t *source, in_addr_t dest,
     686    packet_t *packet, measured_string_t *destination)
    631687{
    632688        size_t length;
     
    757813 *                      function.
    758814 */
    759 static int
    760 ip_fragment_packet_data(packet_t *packet, packet_t *new_packet,
     815static int ip_fragment_packet_data(packet_t *packet, packet_t *new_packet,
    761816    ip_header_t *header, ip_header_t *new_header, size_t length,
    762817    const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen)
     
    792847
    793848        return pq_insert_after(packet, new_packet);
     849}
     850
     851/** Prefixes a middle fragment header based on the last fragment header to the
     852 * packet.
     853 *
     854 * @param[in] packet    The packet to be prefixed.
     855 * @param[in] last      The last header to be copied.
     856 * @return              The prefixed middle header.
     857 * @return              NULL on error.
     858 */
     859static ip_header_t *ip_create_middle_header(packet_t *packet,
     860    ip_header_t *last)
     861{
     862        ip_header_t *middle;
     863
     864        middle = (ip_header_t *) packet_suffix(packet, IP_HEADER_LENGTH(last));
     865        if (!middle)
     866                return NULL;
     867        memcpy(middle, last, IP_HEADER_LENGTH(last));
     868        middle->flags |= IPFLAG_MORE_FRAGMENTS;
     869        return middle;
    794870}
    795871
     
    9961072 *                      function.
    9971073 */
    998 static int
    999 ip_send_route(packet_t *packet, ip_netif_t *netif, ip_route_t *route,
    1000     in_addr_t *src, in_addr_t dest, services_t error)
     1074static int ip_send_route(packet_t *packet, ip_netif_t *netif,
     1075    ip_route_t *route, in_addr_t *src, in_addr_t dest, services_t error)
    10011076{
    10021077        measured_string_t destination;
     
    10611136}
    10621137
    1063 /** Searches the network interfaces if there is a suitable route.
    1064  *
    1065  * @param[in] netif     The network interface to be searched for routes. May be
    1066  *                      NULL.
    1067  * @param[in] destination The destination address.
    1068  * @return              The found route.
    1069  * @return              NULL if no route was found.
    1070  */
    1071 static ip_route_t *
    1072 ip_netif_find_route(ip_netif_t *netif, in_addr_t destination)
    1073 {
    1074         int index;
    1075         ip_route_t *route;
    1076        
    1077         if (!netif)
    1078                 return NULL;
    1079        
    1080         /* Start with the first one (the direct route) */
    1081         for (index = 0; index < ip_routes_count(&netif->routes); index++) {
    1082                 route = ip_routes_get_index(&netif->routes, index);
    1083                 if ((route) &&
    1084                     ((route->address.s_addr & route->netmask.s_addr) ==
    1085                     (destination.s_addr & route->netmask.s_addr)))
    1086                         return route;
    1087         }
    1088 
    1089         return NULL;
    1090 }
    1091 
    1092 /** Searches all network interfaces if there is a suitable route.
    1093  *
    1094  * @param[in] destination The destination address.
    1095  * @return              The found route.
    1096  * @return              NULL if no route was found.
    1097  */
    1098 static ip_route_t *ip_find_route(in_addr_t destination) {
    1099         int index;
    1100         ip_route_t *route;
    1101         ip_netif_t *netif;
    1102 
    1103         // start with the last netif - the newest one
    1104         index = ip_netifs_count(&ip_globals.netifs) - 1;
    1105         while (index >= 0) {
    1106                 netif = ip_netifs_get_index(&ip_globals.netifs, index);
    1107                 if (netif && (netif->state == NETIF_ACTIVE)) {
    1108                         route = ip_netif_find_route(netif, destination);
    1109                         if (route)
    1110                                 return route;
    1111                 }
    1112                 index--;
    1113         }
    1114 
    1115         return &ip_globals.gateway;
    1116 }
    1117 
    1118 /** Returns the network interface's IP address.
    1119  *
    1120  * @param[in] netif     The network interface.
    1121  * @return              The IP address.
    1122  * @return              NULL if no IP address was found.
    1123  */
    1124 static in_addr_t *ip_netif_address(ip_netif_t *netif)
    1125 {
    1126         ip_route_t *route;
    1127 
    1128         route = ip_routes_get_index(&netif->routes, 0);
    1129         return route ? &route->address : NULL;
    1130 }
    1131 
    1132 /** Registers the transport layer protocol.
    1133  *
    1134  * The traffic of this protocol will be supplied using either the receive
    1135  * function or IPC message.
    1136  *
    1137  * @param[in] protocol  The transport layer module protocol.
    1138  * @param[in] service   The transport layer module service.
    1139  * @param[in] phone     The transport layer module phone.
    1140  * @param[in] received_msg The receiving function.
    1141  * @return              EOK on success.
    1142  * @return              EINVAL if the protocol parameter and/or the service
    1143  *                      parameter is zero.
    1144  * @return              EINVAL if the phone parameter is not a positive number
    1145  *                      and the tl_receive_msg is NULL.
    1146  * @return              ENOMEM if there is not enough memory left.
    1147  */
    1148 static int
    1149 ip_register(int protocol, services_t service, int phone,
    1150     tl_received_msg_t received_msg)
    1151 {
    1152         ip_proto_t *proto;
    1153         int index;
    1154 
    1155         if (!protocol || !service || ((phone < 0) && !received_msg))
    1156                 return EINVAL;
    1157 
    1158         proto = (ip_proto_t *) malloc(sizeof(ip_protos_t));
    1159         if (!proto)
    1160                 return ENOMEM;
    1161 
    1162         proto->protocol = protocol;
    1163         proto->service = service;
    1164         proto->phone = phone;
    1165         proto->received_msg = received_msg;
    1166 
    1167         fibril_rwlock_write_lock(&ip_globals.protos_lock);
    1168         index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
    1169         if (index < 0) {
    1170                 fibril_rwlock_write_unlock(&ip_globals.protos_lock);
    1171                 free(proto);
    1172                 return index;
    1173         }
    1174         fibril_rwlock_write_unlock(&ip_globals.protos_lock);
    1175 
    1176         printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
    1177             NAME, proto->protocol, proto->phone);
    1178 
    1179         return EOK;
    1180 }
    1181 
    1182 static int
    1183 ip_device_req_local(int il_phone, device_id_t device_id, services_t netif)
    1184 {
    1185         ip_netif_t *ip_netif;
    1186         ip_route_t *route;
    1187         int index;
    1188         int rc;
    1189 
    1190         ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t));
    1191         if (!ip_netif)
    1192                 return ENOMEM;
    1193 
    1194         rc = ip_routes_initialize(&ip_netif->routes);
    1195         if (rc != EOK) {
    1196                 free(ip_netif);
    1197                 return rc;
    1198         }
    1199 
    1200         ip_netif->device_id = device_id;
    1201         ip_netif->service = netif;
    1202         ip_netif->state = NETIF_STOPPED;
    1203 
    1204         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    1205 
    1206         rc = ip_netif_initialize(ip_netif);
    1207         if (rc != EOK) {
    1208                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1209                 ip_routes_destroy(&ip_netif->routes);
    1210                 free(ip_netif);
    1211                 return rc;
    1212         }
    1213         if (ip_netif->arp)
    1214                 ip_netif->arp->usage++;
    1215 
    1216         // print the settings
    1217         printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
    1218             NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv,
    1219             ip_netif->dhcp ? "dhcp" : "static");
    1220        
    1221         // TODO ipv6 addresses
    1222        
    1223         char address[INET_ADDRSTRLEN];
    1224         char netmask[INET_ADDRSTRLEN];
    1225         char gateway[INET_ADDRSTRLEN];
    1226        
    1227         for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
    1228                 route = ip_routes_get_index(&ip_netif->routes, index);
    1229                 if (route) {
    1230                         inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr,
    1231                             address, INET_ADDRSTRLEN);
    1232                         inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr,
    1233                             netmask, INET_ADDRSTRLEN);
    1234                         inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr,
    1235                             gateway, INET_ADDRSTRLEN);
    1236                         printf("%s: Route %d (address: %s, netmask: %s, "
    1237                             "gateway: %s)\n", NAME, index, address, netmask,
    1238                             gateway);
    1239                 }
    1240         }
    1241        
    1242         inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
    1243             INET_ADDRSTRLEN);
    1244         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1245 
    1246         printf("%s: Broadcast (%s)\n", NAME, address);
    1247 
    1248         return EOK;
    1249 }
    1250 
    1251 static int
    1252 ip_send_msg_local(int il_phone, device_id_t device_id, packet_t *packet,
    1253     services_t sender, services_t error)
     1138static int ip_send_msg_local(int il_phone, device_id_t device_id,
     1139    packet_t *packet, services_t sender, services_t error)
    12541140{
    12551141        int addrlen;
     
    13551241}
    13561242
     1243/** Updates the device state.
     1244 *
     1245 * @param[in] device_id The device identifier.
     1246 * @param[in] state     The new state value.
     1247 * @return              EOK on success.
     1248 * @return              ENOENT if device is not found.
     1249 */
     1250static int ip_device_state_message(device_id_t device_id, device_state_t state)
     1251{
     1252        ip_netif_t *netif;
     1253
     1254        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     1255        // find the device
     1256        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1257        if (!netif) {
     1258                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1259                return ENOENT;
     1260        }
     1261        netif->state = state;
     1262        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1263
     1264        printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
     1265
     1266        return EOK;
     1267}
     1268
     1269/** Returns the packet destination address from the IP header.
     1270 *
     1271 * @param[in] header    The packet IP header to be read.
     1272 * @return              The packet destination address.
     1273 */
     1274static in_addr_t ip_get_destination(ip_header_t *header)
     1275{
     1276        in_addr_t destination;
     1277
     1278        // TODO search set ipopt route?
     1279        destination.s_addr = header->destination_address;
     1280        return destination;
     1281}
     1282
     1283/** Delivers the packet to the local host.
     1284 *
     1285 * The packet is either passed to another module or released on error.
     1286 * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not
     1287 * found.
     1288 *
     1289 * @param[in] device_id The source device identifier.
     1290 * @param[in] packet    The packet to be delivered.
     1291 * @param[in] header    The first packet IP header. May be NULL.
     1292 * @param[in] error     The packet error service.
     1293 * @return              EOK on success.
     1294 * @return              ENOTSUP if the packet is a fragment.
     1295 * @return              EAFNOSUPPORT if the address family is not supported.
     1296 * @return              ENOENT if the target protocol is not found.
     1297 * @return              Other error codes as defined for the packet_set_addr()
     1298 *                      function.
     1299 * @return              Other error codes as defined for the packet_trim()
     1300 *                      function.
     1301 * @return              Other error codes as defined for the protocol specific
     1302 *                      tl_received_msg() function.
     1303 */
     1304static int ip_deliver_local(device_id_t device_id, packet_t *packet,
     1305    ip_header_t *header, services_t error)
     1306{
     1307        ip_proto_t *proto;
     1308        int phone;
     1309        services_t service;
     1310        tl_received_msg_t received_msg;
     1311        struct sockaddr *src;
     1312        struct sockaddr *dest;
     1313        struct sockaddr_in src_in;
     1314        struct sockaddr_in dest_in;
     1315        socklen_t addrlen;
     1316        int rc;
     1317
     1318        if ((header->flags & IPFLAG_MORE_FRAGMENTS) ||
     1319            IP_FRAGMENT_OFFSET(header)) {
     1320                // TODO fragmented
     1321                return ENOTSUP;
     1322        }
     1323       
     1324        switch (header->version) {
     1325        case IPVERSION:
     1326                addrlen = sizeof(src_in);
     1327                bzero(&src_in, addrlen);
     1328                src_in.sin_family = AF_INET;
     1329                memcpy(&dest_in, &src_in, addrlen);
     1330                memcpy(&src_in.sin_addr.s_addr, &header->source_address,
     1331                    sizeof(header->source_address));
     1332                memcpy(&dest_in.sin_addr.s_addr, &header->destination_address,
     1333                    sizeof(header->destination_address));
     1334                src = (struct sockaddr *) &src_in;
     1335                dest = (struct sockaddr *) &dest_in;
     1336                break;
     1337
     1338        default:
     1339                return ip_release_and_return(packet, EAFNOSUPPORT);
     1340        }
     1341
     1342        rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest,
     1343            addrlen);
     1344        if (rc != EOK)
     1345                return ip_release_and_return(packet, rc);
     1346
     1347        // trim padding if present
     1348        if (!error &&
     1349            (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
     1350                rc = packet_trim(packet, 0,
     1351                    packet_get_data_length(packet) - IP_TOTAL_LENGTH(header));
     1352                if (rc != EOK)
     1353                        return ip_release_and_return(packet, rc);
     1354        }
     1355
     1356        fibril_rwlock_read_lock(&ip_globals.protos_lock);
     1357
     1358        proto = ip_protos_find(&ip_globals.protos, header->protocol);
     1359        if (!proto) {
     1360                fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1361                phone = ip_prepare_icmp_and_get_phone(error, packet, header);
     1362                if (phone >= 0) {
     1363                        // unreachable ICMP
     1364                        icmp_destination_unreachable_msg(phone,
     1365                            ICMP_PROT_UNREACH, 0, packet);
     1366                }
     1367                return ENOENT;
     1368        }
     1369
     1370        if (proto->received_msg) {
     1371                service = proto->service;
     1372                received_msg = proto->received_msg;
     1373                fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1374                rc = received_msg(device_id, packet, service, error);
     1375        } else {
     1376                rc = tl_received_msg(proto->phone, device_id, packet,
     1377                    proto->service, error);
     1378                fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1379        }
     1380
     1381        return rc;
     1382}
     1383
     1384/** Processes the received packet.
     1385 *
     1386 * The packet is either passed to another module or released on error.
     1387 *
     1388 * The ICMP_PARAM_POINTER error notification may be sent if the checksum is
     1389 * invalid.
     1390 * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two.
     1391 * The ICMP_HOST_UNREACH error notification may be sent if no route was found.
     1392 * The ICMP_HOST_UNREACH error notification may be sent if the packet is for
     1393 * another host and the routing is disabled.
     1394 *
     1395 * @param[in] device_id The source device identifier.
     1396 * @param[in] packet    The received packet to be processed.
     1397 * @return              EOK on success.
     1398 * @return              EINVAL if the TTL is less than two.
     1399 * @return              EINVAL if the checksum is invalid.
     1400 * @return              EAFNOSUPPORT if the address family is not supported.
     1401 * @return              ENOENT if no route was found.
     1402 * @return              ENOENT if the packet is for another host and the routing
     1403 *                      is disabled.
     1404 */
     1405static int ip_process_packet(device_id_t device_id, packet_t *packet)
     1406{
     1407        ip_header_t *header;
     1408        in_addr_t dest;
     1409        ip_route_t *route;
     1410        int phone;
     1411        struct sockaddr *addr;
     1412        struct sockaddr_in addr_in;
     1413        socklen_t addrlen;
     1414        int rc;
     1415       
     1416        header = (ip_header_t *) packet_get_data(packet);
     1417        if (!header)
     1418                return ip_release_and_return(packet, ENOMEM);
     1419
     1420        // checksum
     1421        if ((header->header_checksum) &&
     1422            (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
     1423                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1424                if (phone >= 0) {
     1425                        // checksum error ICMP
     1426                        icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER,
     1427                            ((size_t) ((void *) &header->header_checksum)) -
     1428                            ((size_t) ((void *) header)), packet);
     1429                }
     1430                return EINVAL;
     1431        }
     1432
     1433        if (header->ttl <= 1) {
     1434                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1435                if (phone >= 0) {
     1436                        // ttl exceeded ICMP
     1437                        icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
     1438                }
     1439                return EINVAL;
     1440        }
     1441       
     1442        // process ipopt and get destination
     1443        dest = ip_get_destination(header);
     1444
     1445        // set the addrination address
     1446        switch (header->version) {
     1447        case IPVERSION:
     1448                addrlen = sizeof(addr_in);
     1449                bzero(&addr_in, addrlen);
     1450                addr_in.sin_family = AF_INET;
     1451                memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
     1452                addr = (struct sockaddr *) &addr_in;
     1453                break;
     1454
     1455        default:
     1456                return ip_release_and_return(packet, EAFNOSUPPORT);
     1457        }
     1458
     1459        rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen);
     1460        if (rc != EOK)
     1461                return rc;
     1462       
     1463        route = ip_find_route(dest);
     1464        if (!route) {
     1465                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1466                if (phone >= 0) {
     1467                        // unreachable ICMP
     1468                        icmp_destination_unreachable_msg(phone,
     1469                            ICMP_HOST_UNREACH, 0, packet);
     1470                }
     1471                return ENOENT;
     1472        }
     1473
     1474        if (route->address.s_addr == dest.s_addr) {
     1475                // local delivery
     1476                return ip_deliver_local(device_id, packet, header, 0);
     1477        }
     1478
     1479        if (route->netif->routing) {
     1480                header->ttl--;
     1481                return ip_send_route(packet, route->netif, route, NULL, dest,
     1482                    0);
     1483        }
     1484
     1485        phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1486        if (phone >= 0) {
     1487                // unreachable ICMP if no routing
     1488                icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0,
     1489                    packet);
     1490        }
     1491       
     1492        return ENOENT;
     1493}
     1494
    13571495/** Returns the device packet dimensions for sending.
    13581496 *
     
    13661504 * @return              EOK on success.
    13671505 */
    1368 static int
    1369 ip_packet_size_message(device_id_t device_id, size_t *addr_len, size_t *prefix,
    1370     size_t *content, size_t *suffix)
     1506static int ip_packet_size_message(device_id_t device_id, size_t *addr_len,
     1507    size_t *prefix, size_t *content, size_t *suffix)
    13711508{
    13721509        ip_netif_t *netif;
     
    14181555}
    14191556
    1420 /** Returns the packet destination address from the IP header.
    1421  *
    1422  * @param[in] header    The packet IP header to be read.
    1423  * @return              The packet destination address.
    1424  */
    1425 static in_addr_t ip_get_destination(ip_header_t *header)
    1426 {
    1427         in_addr_t destination;
    1428 
    1429         // TODO search set ipopt route?
    1430         destination.s_addr = header->destination_address;
    1431         return destination;
    1432 }
    1433 
    1434 /** Delivers the packet to the local host.
    1435  *
    1436  * The packet is either passed to another module or released on error.
    1437  * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not
    1438  * found.
    1439  *
    1440  * @param[in] device_id The source device identifier.
    1441  * @param[in] packet    The packet to be delivered.
    1442  * @param[in] header    The first packet IP header. May be NULL.
    1443  * @param[in] error     The packet error service.
     1557/** Updates the device content length according to the new MTU value.
     1558 *
     1559 * @param[in] device_id The device identifier.
     1560 * @param[in] mtu       The new mtu value.
    14441561 * @return              EOK on success.
    1445  * @return              ENOTSUP if the packet is a fragment.
    1446  * @return              EAFNOSUPPORT if the address family is not supported.
    1447  * @return              ENOENT if the target protocol is not found.
    1448  * @return              Other error codes as defined for the packet_set_addr()
    1449  *                      function.
    1450  * @return              Other error codes as defined for the packet_trim()
    1451  *                      function.
    1452  * @return              Other error codes as defined for the protocol specific
    1453  *                      tl_received_msg() function.
     1562 * @return              ENOENT if device is not found.
     1563 */
     1564static int ip_mtu_changed_message(device_id_t device_id, size_t mtu)
     1565{
     1566        ip_netif_t *netif;
     1567
     1568        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     1569        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1570        if (!netif) {
     1571                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1572                return ENOENT;
     1573        }
     1574        netif->packet_dimension.content = mtu;
     1575        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1576
     1577        printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
     1578
     1579        return EOK;
     1580}
     1581
     1582/** Process IPC messages from the registered device driver modules
     1583 *
     1584 * @param[in]     iid   Message identifier.
     1585 * @param[in,out] icall Message parameters.
     1586 *
     1587 */
     1588static void ip_receiver(ipc_callid_t iid, ipc_call_t *icall)
     1589{
     1590        packet_t *packet;
     1591        int rc;
     1592       
     1593        while (true) {
     1594                switch (IPC_GET_IMETHOD(*icall)) {
     1595                case NET_IL_DEVICE_STATE:
     1596                        rc = ip_device_state_message(IPC_GET_DEVICE(*icall),
     1597                            IPC_GET_STATE(*icall));
     1598                        ipc_answer_0(iid, (sysarg_t) rc);
     1599                        break;
     1600               
     1601                case NET_IL_RECEIVED:
     1602                        rc = packet_translate_remote(ip_globals.net_phone, &packet,
     1603                            IPC_GET_PACKET(*icall));
     1604                        if (rc == EOK) {
     1605                                do {
     1606                                        packet_t *next = pq_detach(packet);
     1607                                        ip_process_packet(IPC_GET_DEVICE(*icall), packet);
     1608                                        packet = next;
     1609                                } while (packet);
     1610                        }
     1611                       
     1612                        ipc_answer_0(iid, (sysarg_t) rc);
     1613                        break;
     1614               
     1615                case NET_IL_MTU_CHANGED:
     1616                        rc = ip_mtu_changed_message(IPC_GET_DEVICE(*icall),
     1617                            IPC_GET_MTU(*icall));
     1618                        ipc_answer_0(iid, (sysarg_t) rc);
     1619                        break;
     1620               
     1621                default:
     1622                        ipc_answer_0(iid, (sysarg_t) ENOTSUP);
     1623                }
     1624               
     1625                iid = async_get_call(icall);
     1626        }
     1627}
     1628
     1629/** Registers the transport layer protocol.
     1630 *
     1631 * The traffic of this protocol will be supplied using either the receive
     1632 * function or IPC message.
     1633 *
     1634 * @param[in] protocol  The transport layer module protocol.
     1635 * @param[in] service   The transport layer module service.
     1636 * @param[in] phone     The transport layer module phone.
     1637 * @param[in] received_msg The receiving function.
     1638 * @return              EOK on success.
     1639 * @return              EINVAL if the protocol parameter and/or the service
     1640 *                      parameter is zero.
     1641 * @return              EINVAL if the phone parameter is not a positive number
     1642 *                      and the tl_receive_msg is NULL.
     1643 * @return              ENOMEM if there is not enough memory left.
    14541644 */
    14551645static int
    1456 ip_deliver_local(device_id_t device_id, packet_t *packet, ip_header_t *header,
    1457     services_t error)
     1646ip_register(int protocol, services_t service, int phone,
     1647    tl_received_msg_t received_msg)
    14581648{
    14591649        ip_proto_t *proto;
    1460         int phone;
    1461         services_t service;
    1462         tl_received_msg_t received_msg;
    1463         struct sockaddr *src;
    1464         struct sockaddr *dest;
    1465         struct sockaddr_in src_in;
    1466         struct sockaddr_in dest_in;
    1467         socklen_t addrlen;
    1468         int rc;
    1469 
    1470         if ((header->flags & IPFLAG_MORE_FRAGMENTS) ||
    1471             IP_FRAGMENT_OFFSET(header)) {
    1472                 // TODO fragmented
    1473                 return ENOTSUP;
    1474         }
    1475        
    1476         switch (header->version) {
    1477         case IPVERSION:
    1478                 addrlen = sizeof(src_in);
    1479                 bzero(&src_in, addrlen);
    1480                 src_in.sin_family = AF_INET;
    1481                 memcpy(&dest_in, &src_in, addrlen);
    1482                 memcpy(&src_in.sin_addr.s_addr, &header->source_address,
    1483                     sizeof(header->source_address));
    1484                 memcpy(&dest_in.sin_addr.s_addr, &header->destination_address,
    1485                     sizeof(header->destination_address));
    1486                 src = (struct sockaddr *) &src_in;
    1487                 dest = (struct sockaddr *) &dest_in;
    1488                 break;
    1489 
    1490         default:
    1491                 return ip_release_and_return(packet, EAFNOSUPPORT);
    1492         }
    1493 
    1494         rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest,
    1495             addrlen);
    1496         if (rc != EOK)
    1497                 return ip_release_and_return(packet, rc);
    1498 
    1499         // trim padding if present
    1500         if (!error &&
    1501             (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
    1502                 rc = packet_trim(packet, 0,
    1503                     packet_get_data_length(packet) - IP_TOTAL_LENGTH(header));
    1504                 if (rc != EOK)
    1505                         return ip_release_and_return(packet, rc);
    1506         }
    1507 
    1508         fibril_rwlock_read_lock(&ip_globals.protos_lock);
    1509 
    1510         proto = ip_protos_find(&ip_globals.protos, header->protocol);
    1511         if (!proto) {
    1512                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1513                 phone = ip_prepare_icmp_and_get_phone(error, packet, header);
    1514                 if (phone >= 0) {
    1515                         // unreachable ICMP
    1516                         icmp_destination_unreachable_msg(phone,
    1517                             ICMP_PROT_UNREACH, 0, packet);
    1518                 }
    1519                 return ENOENT;
    1520         }
    1521 
    1522         if (proto->received_msg) {
    1523                 service = proto->service;
    1524                 received_msg = proto->received_msg;
    1525                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1526                 rc = received_msg(device_id, packet, service, error);
    1527         } else {
    1528                 rc = tl_received_msg(proto->phone, device_id, packet,
    1529                     proto->service, error);
    1530                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1531         }
    1532 
    1533         return rc;
    1534 }
    1535 
    1536 /** Processes the received packet.
    1537  *
    1538  * The packet is either passed to another module or released on error.
    1539  *
    1540  * The ICMP_PARAM_POINTER error notification may be sent if the checksum is
    1541  * invalid.
    1542  * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two.
    1543  * The ICMP_HOST_UNREACH error notification may be sent if no route was found.
    1544  * The ICMP_HOST_UNREACH error notification may be sent if the packet is for
    1545  * another host and the routing is disabled.
    1546  *
    1547  * @param[in] device_id The source device identifier.
    1548  * @param[in] packet    The received packet to be processed.
    1549  * @return              EOK on success.
    1550  * @return              EINVAL if the TTL is less than two.
    1551  * @return              EINVAL if the checksum is invalid.
    1552  * @return              EAFNOSUPPORT if the address family is not supported.
    1553  * @return              ENOENT if no route was found.
    1554  * @return              ENOENT if the packet is for another host and the routing
    1555  *                      is disabled.
    1556  */
    1557 static int
    1558 ip_process_packet(device_id_t device_id, packet_t *packet)
    1559 {
    1560         ip_header_t *header;
    1561         in_addr_t dest;
    1562         ip_route_t *route;
    1563         int phone;
    1564         struct sockaddr *addr;
    1565         struct sockaddr_in addr_in;
    1566         socklen_t addrlen;
    1567         int rc;
    1568        
    1569         header = (ip_header_t *) packet_get_data(packet);
    1570         if (!header)
    1571                 return ip_release_and_return(packet, ENOMEM);
    1572 
    1573         // checksum
    1574         if ((header->header_checksum) &&
    1575             (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
    1576                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1577                 if (phone >= 0) {
    1578                         // checksum error ICMP
    1579                         icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER,
    1580                             ((size_t) ((void *) &header->header_checksum)) -
    1581                             ((size_t) ((void *) header)), packet);
    1582                 }
     1650        int index;
     1651
     1652        if (!protocol || !service || ((phone < 0) && !received_msg))
    15831653                return EINVAL;
    1584         }
    1585 
    1586         if (header->ttl <= 1) {
    1587                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1588                 if (phone >= 0) {
    1589                         // ttl exceeded ICMP
    1590                         icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
    1591                 }
    1592                 return EINVAL;
    1593         }
    1594        
    1595         // process ipopt and get destination
    1596         dest = ip_get_destination(header);
    1597 
    1598         // set the addrination address
    1599         switch (header->version) {
    1600         case IPVERSION:
    1601                 addrlen = sizeof(addr_in);
    1602                 bzero(&addr_in, addrlen);
    1603                 addr_in.sin_family = AF_INET;
    1604                 memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
    1605                 addr = (struct sockaddr *) &addr_in;
    1606                 break;
    1607 
    1608         default:
    1609                 return ip_release_and_return(packet, EAFNOSUPPORT);
    1610         }
    1611 
    1612         rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen);
    1613         if (rc != EOK)
    1614                 return rc;
    1615        
    1616         route = ip_find_route(dest);
    1617         if (!route) {
    1618                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1619                 if (phone >= 0) {
    1620                         // unreachable ICMP
    1621                         icmp_destination_unreachable_msg(phone,
    1622                             ICMP_HOST_UNREACH, 0, packet);
    1623                 }
    1624                 return ENOENT;
    1625         }
    1626 
    1627         if (route->address.s_addr == dest.s_addr) {
    1628                 // local delivery
    1629                 return ip_deliver_local(device_id, packet, header, 0);
    1630         }
    1631 
    1632         if (route->netif->routing) {
    1633                 header->ttl--;
    1634                 return ip_send_route(packet, route->netif, route, NULL, dest,
    1635                     0);
    1636         }
    1637 
    1638         phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1639         if (phone >= 0) {
    1640                 // unreachable ICMP if no routing
    1641                 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0,
    1642                     packet);
    1643         }
    1644        
    1645         return ENOENT;
    1646 }
     1654
     1655        proto = (ip_proto_t *) malloc(sizeof(ip_protos_t));
     1656        if (!proto)
     1657                return ENOMEM;
     1658
     1659        proto->protocol = protocol;
     1660        proto->service = service;
     1661        proto->phone = phone;
     1662        proto->received_msg = received_msg;
     1663
     1664        fibril_rwlock_write_lock(&ip_globals.protos_lock);
     1665        index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
     1666        if (index < 0) {
     1667                fibril_rwlock_write_unlock(&ip_globals.protos_lock);
     1668                free(proto);
     1669                return index;
     1670        }
     1671        fibril_rwlock_write_unlock(&ip_globals.protos_lock);
     1672
     1673        printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
     1674            NAME, proto->protocol, proto->phone);
     1675
     1676        return EOK;
     1677}
     1678
    16471679
    16481680static int
     
    18451877}
    18461878
    1847 /** Processes the received IP packet or the packet queue one by one.
    1848  *
    1849  * The packet is either passed to another module or released on error.
    1850  *
    1851  * @param[in] device_id The source device identifier.
    1852  * @param[in,out] packet The received packet.
    1853  * @return              EOK on success and the packet is no longer needed.
    1854  * @return              EINVAL if the packet is too small to carry the IP
    1855  *                      packet.
    1856  * @return              EINVAL if the received address lengths differs from the
    1857  *                      registered values.
    1858  * @return              ENOENT if the device is not found in the cache.
    1859  * @return              ENOENT if the protocol for the device is not found in
    1860  *                      the cache.
    1861  * @return              ENOMEM if there is not enough memory left.
    1862  */
    1863 static int ip_receive_message(device_id_t device_id, packet_t *packet)
    1864 {
    1865         packet_t *next;
    1866 
    1867         do {
    1868                 next = pq_detach(packet);
    1869                 ip_process_packet(device_id, packet);
    1870                 packet = next;
    1871         } while (packet);
    1872 
    1873         return EOK;
    1874 }
    1875 
    18761879/** Processes the IP message.
    18771880 *
     
    18851888 *
    18861889 * @see ip_interface.h
    1887  * @see il_interface.h
     1890 * @see il_remote.h
    18881891 * @see IS_NET_IP_MESSAGE()
    18891892 */
    1890 int
    1891 ip_message_standalone(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
     1893int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
    18921894    size_t *answer_count)
    18931895{
    18941896        packet_t *packet;
    18951897        struct sockaddr *addr;
     1898        void *header;
     1899        size_t headerlen;
    18961900        size_t addrlen;
    18971901        size_t prefix;
    18981902        size_t suffix;
    18991903        size_t content;
    1900         void *header;
    1901         size_t headerlen;
    19021904        device_id_t device_id;
    19031905        int rc;
     
    19121914                    IPC_GET_PHONE(*call), NULL);
    19131915       
    1914         case NET_IL_DEVICE:
     1916        case NET_IP_DEVICE:
    19151917                return ip_device_req_local(0, IPC_GET_DEVICE(*call),
    19161918                    IPC_GET_SERVICE(*call));
    1917        
    1918         case NET_IL_SEND:
    1919                 rc = packet_translate_remote(ip_globals.net_phone, &packet,
    1920                     IPC_GET_PACKET(*call));
    1921                 if (rc != EOK)
    1922                         return rc;
    1923                 return ip_send_msg_local(0, IPC_GET_DEVICE(*call), packet, 0,
    1924                     IPC_GET_ERROR(*call));
    1925        
    1926         case NET_IL_DEVICE_STATE:
    1927                 return ip_device_state_message(IPC_GET_DEVICE(*call),
    1928                     IPC_GET_STATE(*call));
    1929        
    1930         case NET_IL_RECEIVED:
    1931                 rc = packet_translate_remote(ip_globals.net_phone, &packet,
    1932                     IPC_GET_PACKET(*call));
    1933                 if (rc != EOK)
    1934                         return rc;
    1935                 return ip_receive_message(IPC_GET_DEVICE(*call), packet);
    19361919       
    19371920        case NET_IP_RECEIVED_ERROR:
     
    19751958                return rc;
    19761959       
    1977         case NET_IL_PACKET_SPACE:
     1960        case NET_IP_PACKET_SPACE:
    19781961                rc = ip_packet_size_message(IPC_GET_DEVICE(*call), &addrlen,
    19791962                    &prefix, &content, &suffix);
     
    19881971                return EOK;
    19891972       
    1990         case NET_IL_MTU_CHANGED:
    1991                 return ip_mtu_changed_message(IPC_GET_DEVICE(*call),
    1992                     IPC_GET_MTU(*call));
     1973        case NET_IP_SEND:
     1974                rc = packet_translate_remote(ip_globals.net_phone, &packet,
     1975                    IPC_GET_PACKET(*call));
     1976                if (rc != EOK)
     1977                        return rc;
     1978               
     1979                return ip_send_msg_local(0, IPC_GET_DEVICE(*call), packet, 0,
     1980                    IPC_GET_ERROR(*call));
    19931981        }
    19941982       
     
    19961984}
    19971985
    1998 /** Default thread for new connections.
    1999  *
    2000  * @param[in] iid       The initial message identifier.
    2001  * @param[in] icall     The initial message call structure.
    2002  */
    2003 static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
    2004 {
    2005         /*
    2006          * Accept the connection
    2007          *  - Answer the first IPC_M_CONNECT_ME_TO call.
    2008          */
    2009         ipc_answer_0(iid, EOK);
    2010        
    2011         while (true) {
    2012                 ipc_call_t answer;
    2013                 size_t count;
    2014                
    2015                 /* Clear the answer structure */
    2016                 refresh_answer(&answer, &count);
    2017                
    2018                 /* Fetch the next message */
    2019                 ipc_call_t call;
    2020                 ipc_callid_t callid = async_get_call(&call);
    2021                
    2022                 /* Process the message */
    2023                 int res = il_module_message_standalone(callid, &call, &answer,
    2024                     &count);
    2025                
    2026                 /*
    2027                  * End if told to either by the message or the processing
    2028                  * result.
    2029                  */
    2030                 if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
    2031                     (res == EHANGUP)) {
    2032                         return;
    2033                 }
    2034                
    2035                 /* Answer the message */
    2036                 answer_call(callid, res, &answer, count);
    2037         }
    2038 }
    2039 
    2040 /** Starts the module.
    2041  *
    2042  * @return EOK on success.
    2043  * @return Other error codes as defined for each specific module start function.
    2044  */
    20451986int main(int argc, char *argv[])
    20461987{
    2047         int rc;
    2048        
    20491988        /* Start the module */
    2050         rc = il_module_start_standalone(il_client_connection);
    2051         return rc;
     1989        return il_module_start(SERVICE_IP);
    20521990}
    20531991
Note: See TracChangeset for help on using the changeset viewer.