Changes in / [069015f2:f2d2c604] in mainline


Ignore:
Location:
uspace
Files:
1 added
11 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/net/il/ip_remote.c

    r069015f2 rf2d2c604  
    5757 * The target network is routed using this device.
    5858 *
    59  * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
    60  * @param[in] device_id The device identifier.
    61  * @param[in] address   The target network address.
    62  * @param[in] netmask   The target network mask.
    63  * @param[in] gateway   The target network gateway. Not used if zero.
     59 * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
     60 * @param[in] device_id The device identifier.
     61 * @param[in] address   The target network address.
     62 * @param[in] netmask   The target network mask.
     63 * @param[in] gateway   The target network gateway. Not used if zero.
     64 *
    6465 */
    6566int ip_add_route_req_remote(int ip_phone, device_id_t device_id,
     
    105106 * If the device uses ARP registers also the new ARP device.
    106107 *
    107  * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
    108  * @param[in] device_id The new device identifier.
    109  * @param[in] netif     The underlying device network interface layer service.
    110  * @return              EOK on success.
    111  * @return              ENOMEM if there is not enough memory left.
    112  * @return              EINVAL if the device configuration is invalid.
    113  * @return              ENOTSUP if the device uses IPv6.
    114  * @return              ENOTSUP if the device uses DHCP.
    115  * @return              Other error codes as defined for the
    116  *                      net_get_device_conf_req() function.
    117  * @return              Other error codes as defined for the arp_device_req()
    118  *                      function.
     108 * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
     109 * @param[in] device_id The new device identifier.
     110 * @param[in] netif     The underlying device network interface layer service.
     111 *
     112 * @return EOK on success.
     113 * @return ENOMEM if there is not enough memory left.
     114 * @return EINVAL if the device configuration is invalid.
     115 * @return ENOTSUP if the device uses IPv6.
     116 * @return ENOTSUP if the device uses DHCP.
     117 * @return Other error codes as defined for the net_get_device_conf_req()
     118 *         function.
     119 * @return Other error codes as defined for the arp_device_req() function.
     120 *
    119121 */
    120122int ip_device_req_remote(int ip_phone, device_id_t device_id,
     
    128130 * destination address.
    129131 *
    130  * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
    131  * @param[in] protocol  The transport protocol.
    132  * @param[in] destination The destination address.
    133  * @param[in] addrlen   The destination address length.
    134  * @param[out] device_id The device identifier.
    135  * @param[out] header   The constructed IP pseudo header.
    136  * @param[out] headerlen The IP pseudo header length.
     132 * @param[in]  ip_phone    The IP module phone used for (semi)remote calls.
     133 * @param[in]  protocol    The transport protocol.
     134 * @param[in]  destination The destination address.
     135 * @param[in]  addrlen     The destination address length.
     136 * @param[out] device_id   The device identifier.
     137 * @param[out] header      The constructed IP pseudo header.
     138 * @param[out] headerlen   The IP pseudo header length.
    137139 *
    138140 */
     
    141143    device_id_t *device_id, void **header, size_t *headerlen)
    142144{
    143         if (!destination || (addrlen == 0))
     145        if ((!destination) || (addrlen == 0))
    144146                return EINVAL;
    145147       
    146         if (!device_id || !header || !headerlen)
     148        if ((!device_id) || (!header) || (!headerlen))
    147149                return EBADMEM;
    148150       
     
    167169        async_wait_for(message_id, &result);
    168170       
    169         if ((result != EOK) && *header)
     171        if ((result != EOK) && (*header))
    170172                free(*header);
    171173        else
     
    177179/** Return the device packet dimension for sending.
    178180 *
    179  * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
    180  * @param[in] device_id The device identifier.
     181 * @param[in]  ip_phone         The IP module phone used for (semi)remote calls.
     182 * @param[in]  device_id        The device identifier.
    181183 * @param[out] packet_dimension The packet dimension.
    182  * @return              EOK on success.
    183  * @return              ENOENT if there is no such device.
    184  * @return              Other error codes as defined for the
    185  *                      generic_packet_size_req_remote() function.
     184 *
     185 * @return EOK on success.
     186 * @return ENOENT if there is no such device.
     187 * @return Other error codes as defined for the
     188 *         generic_packet_size_req_remote() function.
     189 *
    186190 */
    187191int ip_packet_size_req_remote(int ip_phone, device_id_t device_id,
     
    194198/** Notify the IP module about the received error notification packet.
    195199 *
    196  * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
    197  * @param[in] device_id The device identifier.
    198  * @param[in] packet    The received packet or the received packet queue.
    199  * @param[in] target    The target internetwork module service to be
    200  *                      delivered to.
    201  * @param[in] error     The packet error reporting service. Prefixes the
    202  *                      received packet.
    203  * @return              EOK on success.
     200 * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
     201 * @param[in] device_id The device identifier.
     202 * @param[in] packet    The received packet or the received packet queue.
     203 * @param[in] target    The target internetwork module service to be
     204 *                      delivered to.
     205 * @param[in] error     The packet error reporting service. Prefixes the
     206 *                      received packet.
     207 *
     208 * @return EOK on success.
     209 *
    204210 */
    205211int ip_received_error_msg_remote(int ip_phone, device_id_t device_id,
     
    214220 * The packets may get fragmented if needed.
    215221 *
    216  * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
    217  * @param[in] device_id The device identifier.
    218  * @param[in] packet    The packet fragments as a packet queue. All the
    219  *                      packets have to have the same destination address.
    220  * @param[in] sender    The sending module service.
    221  * @param[in] error     The packet error reporting service. Prefixes the
    222  *                      received packet.
    223  * @return              EOK on success.
    224  * @return              Other error codes as defined for the generic_send_msg()
    225  *                      function.
     222 * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
     223 * @param[in] device_id The device identifier.
     224 * @param[in] packet    The packet fragments as a packet queue. All the
     225 *                      packets have to have the same destination address.
     226 * @param[in] sender    The sending module service.
     227 * @param[in] error     The packet error reporting service. Prefixes the
     228 *                      received packet.
     229 *
     230 * @return EOK on success.
     231 * @return Other error codes as defined for the generic_send_msg() function.
     232 *
    226233 */
    227234int ip_send_msg_remote(int ip_phone, device_id_t device_id, packet_t packet,
     
    236243 * This gateway is used if no other route is found.
    237244 *
    238  * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
    239  * @param[in] device_id The device identifier.
    240  * @param[in] gateway   The default gateway.
     245 * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
     246 * @param[in] device_id The device identifier.
     247 * @param[in] gateway   The default gateway.
     248 *
    241249 */
    242250int ip_set_gateway_req_remote(int ip_phone, device_id_t device_id,
  • uspace/srv/net/il/arp/arp.c

    r069015f2 rf2d2c604  
    2828
    2929/** @addtogroup arp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @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"
     34 *  ARP module implementation.
     35 *  @see arp.h
     36 */
    4237
    4338#include <async.h>
     
    4843#include <str.h>
    4944#include <task.h>
    50 #include <adt/measured_strings.h>
    5145#include <ipc/ipc.h>
    5246#include <ipc/services.h>
     
    5953#include <net/modules.h>
    6054#include <net/device.h>
    61 #include <net/packet.h>
    62 
     55#include <arp_interface.h>
    6356#include <nil_interface.h>
    6457#include <protocol_map.h>
     58#include <adt/measured_strings.h>
     59#include <net/packet.h>
    6560#include <packet_client.h>
    6661#include <packet_remote.h>
     
    6863#include <il_local.h>
    6964
    70 
    71 /** ARP module name. */
     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 */
    7273#define NAME  "arp"
    7374
    74 /** ARP global data. */
    75 arp_globals_t arp_globals;
    76 
    77 DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t);
    78 INT_MAP_IMPLEMENT(arp_protos, arp_proto_t);
    79 GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t);
     75/** ARP global data.
     76 */
     77arp_globals_t   arp_globals;
    8078
    8179/** Clears the device specific data.
    82  *
    83  * @param[in] device    The device specific data.
    84  */
    85 static 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 
    104 static int arp_clean_cache_req(int arp_phone)
    105 {
     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){
    106156        int count;
    107157        arp_device_ref device;
    108158
    109159        fibril_rwlock_write_lock(&arp_globals.lock);
    110         for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
    111             count--) {
     160        for(count = arp_cache_count(&arp_globals.cache) - 1; count >= 0; -- count){
    112161                device = arp_cache_get_index(&arp_globals.cache, count);
    113                 if (device) {
     162                if(device){
    114163                        arp_clear_device(device);
    115                         if (device->addr_data)
     164                        if(device->addr_data){
    116165                                free(device->addr_data);
    117                         if (device->broadcast_data)
     166                        }
     167                        if(device->broadcast_data){
    118168                                free(device->broadcast_data);
     169                        }
    119170                }
    120171        }
     
    125176}
    126177
    127 static int
    128 arp_clear_address_req(int arp_phone, device_id_t device_id, services_t protocol,
    129     measured_string_ref address)
    130 {
     178int arp_clear_address_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address){
    131179        arp_device_ref device;
    132180        arp_proto_ref proto;
     
    134182        fibril_rwlock_write_lock(&arp_globals.lock);
    135183        device = arp_cache_find(&arp_globals.cache, device_id);
    136         if (!device) {
     184        if(! device){
    137185                fibril_rwlock_write_unlock(&arp_globals.lock);
    138186                return ENOENT;
    139187        }
    140188        proto = arp_protos_find(&device->protos, protocol);
    141         if (!proto) {
     189        if(! proto){
    142190                fibril_rwlock_write_unlock(&arp_globals.lock);
    143191                return ENOENT;
     
    148196}
    149197
    150 
    151 static int arp_clear_device_req(int arp_phone, device_id_t device_id)
    152 {
     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){
    153218        arp_device_ref device;
    154219
    155220        fibril_rwlock_write_lock(&arp_globals.lock);
    156221        device = arp_cache_find(&arp_globals.cache, device_id);
    157         if (!device) {
     222        if(! device){
    158223                fibril_rwlock_write_unlock(&arp_globals.lock);
    159224                return ENOENT;
     
    165230}
    166231
    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  */
    177 static int
    178 arp_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  */
    212 static int
    213 arp_device_message(device_id_t device_id, services_t service,
    214     services_t protocol, measured_string_ref address)
    215 {
     232int arp_device_message(device_id_t device_id, services_t service, services_t protocol, measured_string_ref address){
    216233        ERROR_DECLARE;
    217234
     
    224241        // an existing device?
    225242        device = arp_cache_find(&arp_globals.cache, device_id);
    226         if (device) {
    227                 if (device->service != service) {
     243        if(device){
     244                if(device->service != service){
    228245                        printf("Device %d already exists\n", device->device_id);
    229246                        fibril_rwlock_write_unlock(&arp_globals.lock);
     
    231248                }
    232249                proto = arp_protos_find(&device->protos, protocol);
    233                 if (proto) {
     250                if(proto){
    234251                        free(proto->addr);
    235252                        free(proto->addr_data);
    236253                        proto->addr = address;
    237254                        proto->addr_data = address->value;
    238                 } else {
    239                         if (ERROR_OCCURRED(arp_proto_create(&proto, protocol,
    240                             address))) {
     255                }else{
     256                        if(ERROR_OCCURRED(arp_proto_create(&proto, protocol, address))){
    241257                                fibril_rwlock_write_unlock(&arp_globals.lock);
    242258                                return ERROR_CODE;
    243259                        }
    244                         index = arp_protos_add(&device->protos, proto->service,
    245                             proto);
    246                         if (index < 0) {
     260                        index = arp_protos_add(&device->protos, proto->service, proto);
     261                        if(index < 0){
    247262                                fibril_rwlock_write_unlock(&arp_globals.lock);
    248263                                free(proto);
    249264                                return index;
    250265                        }
    251                         printf("New protocol added:\n\tdevice id\t= "
    252                             "%d\n\tproto\t= %d", device_id, protocol);
    253                 }
    254         } else {
     266                        printf("New protocol added:\n\tdevice id\t= %d\n\tproto\t= %d", device_id, protocol);
     267                }
     268        }else{
    255269                hardware = hardware_map(service);
    256                 if (!hardware)
     270                if(! hardware){
    257271                        return ENOENT;
    258                
     272                }
    259273                // create a new device
    260274                device = (arp_device_ref) malloc(sizeof(arp_device_t));
    261                 if (!device) {
     275                if(! device){
    262276                        fibril_rwlock_write_unlock(&arp_globals.lock);
    263277                        return ENOMEM;
     
    265279                device->hardware = hardware;
    266280                device->device_id = device_id;
    267                 if (ERROR_OCCURRED(arp_protos_initialize(&device->protos)) ||
    268                     ERROR_OCCURRED(arp_proto_create(&proto, protocol,
    269                     address))) {
     281                if(ERROR_OCCURRED(arp_protos_initialize(&device->protos))
     282                        || ERROR_OCCURRED(arp_proto_create(&proto, protocol, address))){
    270283                        fibril_rwlock_write_unlock(&arp_globals.lock);
    271284                        free(device);
     
    273286                }
    274287                index = arp_protos_add(&device->protos, proto->service, proto);
    275                 if (index < 0) {
     288                if(index < 0){
    276289                        fibril_rwlock_write_unlock(&arp_globals.lock);
    277290                        arp_protos_destroy(&device->protos);
     
    280293                }
    281294                device->service = service;
    282                
    283295                // 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) {
     296                device->phone = nil_bind_service(device->service, (ipcarg_t) device->device_id, SERVICE_ARP, arp_globals.client_connection);
     297                if(device->phone < 0){
    288298                        fibril_rwlock_write_unlock(&arp_globals.lock);
    289299                        arp_protos_destroy(&device->protos);
     
    291301                        return EREFUSED;
    292302                }
    293                
    294303                // get packet dimensions
    295                 if (ERROR_OCCURRED(nil_packet_size_req(device->phone, device_id,
    296                     &device->packet_dimension))) {
     304                if(ERROR_OCCURRED(nil_packet_size_req(device->phone, device_id, &device->packet_dimension))){
    297305                        fibril_rwlock_write_unlock(&arp_globals.lock);
    298306                        arp_protos_destroy(&device->protos);
     
    300308                        return ERROR_CODE;
    301309                }
    302                
    303310                // get hardware address
    304                 if (ERROR_OCCURRED(nil_get_addr_req(device->phone, device_id,
    305                     &device->addr, &device->addr_data))) {
     311                if(ERROR_OCCURRED(nil_get_addr_req(device->phone, device_id, &device->addr, &device->addr_data))){
    306312                        fibril_rwlock_write_unlock(&arp_globals.lock);
    307313                        arp_protos_destroy(&device->protos);
     
    309315                        return ERROR_CODE;
    310316                }
    311                
    312317                // get broadcast address
    313                 if (ERROR_OCCURRED(nil_get_broadcast_addr_req(device->phone,
    314                     device_id, &device->broadcast_addr,
    315                     &device->broadcast_data))) {
     318                if(ERROR_OCCURRED(nil_get_broadcast_addr_req(device->phone, device_id, &device->broadcast_addr, &device->broadcast_data))){
    316319                        fibril_rwlock_write_unlock(&arp_globals.lock);
    317320                        free(device->addr);
     
    321324                        return ERROR_CODE;
    322325                }
    323                
    324                 if (ERROR_OCCURRED(arp_cache_add(&arp_globals.cache,
    325                     device->device_id, device))) {
     326                if(ERROR_OCCURRED(arp_cache_add(&arp_globals.cache, device->device_id, device))){
    326327                        fibril_rwlock_write_unlock(&arp_globals.lock);
    327328                        free(device->addr);
     
    333334                        return ERROR_CODE;
    334335                }
    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);
     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);
    338338        }
    339339        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  */
    351 int arp_initialize(async_client_conn_t client_connection)
    352 {
     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){
    353358        ERROR_DECLARE;
    354359
     
    361366}
    362367
    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  */
    370 static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
     368int arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     369    ipc_call_t *answer, int *answer_count)
    371370{
     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){
    372438        arp_device_ref device;
    373439
    374440        fibril_rwlock_write_lock(&arp_globals.lock);
    375441        device = arp_cache_find(&arp_globals.cache, device_id);
    376         if (!device) {
     442        if(! device){
    377443                fibril_rwlock_write_unlock(&arp_globals.lock);
    378444                return ENOENT;
    379445        }
    380446        device->packet_dimension.content = mtu;
     447        printf("arp - device %d changed mtu to %d\n\n", device_id, mtu);
    381448        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  */
    406 static int arp_receive_message(device_id_t device_id, packet_t packet)
    407 {
     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){
    408470        ERROR_DECLARE;
    409471
     
    413475        arp_proto_ref proto;
    414476        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;
     477        uint8_t * src_hw;
     478        uint8_t * src_proto;
     479        uint8_t * des_hw;
     480        uint8_t * des_proto;
    419481
    420482        length = packet_get_data_length(packet);
    421         if (length <= sizeof(arp_header_t))
     483        if(length <= sizeof(arp_header_t)){
    422484                return EINVAL;
    423 
     485        }
    424486        device = arp_cache_find(&arp_globals.cache, device_id);
    425         if (!device)
     487        if(! device){
    426488                return ENOENT;
    427 
     489        }
    428490        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)) {
     491        if((ntohs(header->hardware) != device->hardware)
     492                || (length < sizeof(arp_header_t) + header->hardware_length * 2u + header->protocol_length * 2u)){
    432493                return EINVAL;
    433494        }
    434 
    435         proto = arp_protos_find(&device->protos,
    436             protocol_unmap(device->service, ntohs(header->protocol)));
    437         if (!proto)
     495        proto = arp_protos_find(&device->protos, protocol_unmap(device->service, ntohs(header->protocol)));
     496        if(! proto){
    438497                return ENOENT;
    439 
     498        }
    440499        src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
    441500        src_proto = src_hw + header->hardware_length;
    442501        des_hw = src_proto + header->protocol_length;
    443502        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));
     503        hw_source = arp_addr_find(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length));
    446504        // exists?
    447         if (hw_source) {
    448                 if (hw_source->length != CONVERT_SIZE(uint8_t, char,
    449                     header->hardware_length)) {
     505        if(hw_source){
     506                if(hw_source->length != CONVERT_SIZE(uint8_t, char, header->hardware_length)){
    450507                        return EINVAL;
    451508                }
     
    453510        }
    454511        // is my protocol address?
    455         if (proto->addr->length != CONVERT_SIZE(uint8_t, char,
    456             header->protocol_length)) {
     512        if(proto->addr->length != CONVERT_SIZE(uint8_t, char, header->protocol_length)){
    457513                return EINVAL;
    458514        }
    459         if (!str_lcmp(proto->addr->value, (char *) des_proto,
    460             proto->addr->length)) {
     515        if(! str_lcmp(proto->addr->value, (char *) des_proto, proto->addr->length)){
    461516                // 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)
     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){
    467520                                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) {
     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){
    474525                        header->operation = htons(ARPOP_REPLY);
    475526                        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);
     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);
    486532                        return 1;
    487533                }
    488534        }
    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  */
    509 static measured_string_ref
    510 arp_translate_message(device_id_t device_id, services_t protocol,
    511     measured_string_ref target)
    512 {
     535        return EOK;
     536}
     537
     538measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target){
    513539        arp_device_ref device;
    514540        arp_proto_ref proto;
     
    518544        arp_header_ref header;
    519545
    520         if (!target)
     546        if(! target){
    521547                return NULL;
    522 
     548        }
    523549        device = arp_cache_find(&arp_globals.cache, device_id);
    524         if (!device)
     550        if(! device){
    525551                return NULL;
    526 
     552        }
    527553        proto = arp_protos_find(&device->protos, protocol);
    528         if (!proto || (proto->addr->length != target->length))
     554        if((! proto) || (proto->addr->length != target->length)){
    529555                return NULL;
    530 
     556        }
    531557        addr = arp_addr_find(&proto->addresses, target->value, target->length);
    532         if (addr)
     558        if(addr){
    533559                return addr;
    534 
     560        }
    535561        // 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)
     562        length = 8 + (CONVERT_SIZE(char, uint8_t, proto->addr->length) + CONVERT_SIZE(char, uint8_t, device->addr->length)) * 2;
     563        if(length > device->packet_dimension.content){
    539564                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)
     565        }
     566        packet = packet_get_4_remote(arp_globals.net_phone, device->packet_dimension.addr_len, device->packet_dimension.prefix, length, device->packet_dimension.suffix);
     567        if(! packet){
    545568                return NULL;
    546 
     569        }
    547570        header = (arp_header_ref) packet_suffix(packet, length);
    548         if (!header) {
     571        if(! header){
    549572                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    550573                return NULL;
    551574        }
    552 
    553575        header->hardware = htons(device->hardware);
    554576        header->hardware_length = (uint8_t) device->addr->length;
     
    557579        header->operation = htons(ARPOP_REQUEST);
    558580        length = sizeof(arp_header_t);
    559         memcpy(((uint8_t *) header) + length, device->addr->value,
    560             device->addr->length);
     581        memcpy(((uint8_t *) header) + length, device->addr->value, device->addr->length);
    561582        length += device->addr->length;
    562         memcpy(((uint8_t *) header) + length, proto->addr->value,
    563             proto->addr->length);
     583        memcpy(((uint8_t *) header) + length, proto->addr->value, proto->addr->length);
    564584        length += proto->addr->length;
    565585        bzero(((uint8_t *) header) + length, device->addr->length);
    566586        length += device->addr->length;
    567587        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) {
     588        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){
    572589                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    573590                return NULL;
    574591        }
    575 
    576592        nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
    577593        return NULL;
    578594}
    579595
    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  */
    594 int
    595 arp_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 
    680596/** Default thread for new connections.
    681597 *
    682  * @param[in] iid       The initial message identifier.
    683  * @param[in] icall     The initial message call structure.
    684  */
    685 static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
     598 *  @param[in] iid The initial message identifier.
     599 *  @param[in] icall The initial message call structure.
     600 *
     601 */
     602static void il_client_connection(ipc_callid_t iid, ipc_call_t * icall)
    686603{
    687604        /*
     
    691608        ipc_answer_0(iid, EOK);
    692609       
    693         while (true) {
     610        while(true) {
    694611                ipc_call_t answer;
    695612                int answer_count;
     
    706623                    &answer_count);
    707624               
    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))
     625                /* End if said to either by the message or the processing result */
     626                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
    714627                        return;
    715628               
     
    721634/** Starts the module.
    722635 *
    723  * @returns             EOK on success.
    724  * @returns             Other error codes as defined for each specific module
    725  *                      start function.
     636 *  @param argc The count of the command line arguments. Ignored parameter.
     637 *  @param argv The command line parameters. Ignored parameter.
     638 *
     639 *  @returns EOK on success.
     640 *  @returns Other error codes as defined for each specific module start function.
     641 *
    726642 */
    727643int main(int argc, char *argv[])
     
    730646       
    731647        /* Start the module */
    732         ERROR_PROPAGATE(il_module_start_standalone(il_client_connection));
     648        if (ERROR_OCCURRED(il_module_start_standalone(il_client_connection)))
     649                return ERROR_CODE;
     650       
    733651        return EOK;
    734652}
     
    736654/** @}
    737655 */
    738 
  • uspace/srv/net/il/arp/arp.h

    r069015f2 rf2d2c604  
    2828
    2929/** @addtogroup arp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @file
    34  * ARP module.
     34 *  ARP module.
    3535 */
    3636
    37 #ifndef NET_ARP_H_
    38 #define NET_ARP_H_
     37#ifndef __NET_ARP_H__
     38#define __NET_ARP_H__
    3939
    4040#include <fibril_synch.h>
     
    4444
    4545#include <net/device.h>
    46 #include <net/packet.h>
    4746#include <net_hardware.h>
    4847#include <adt/generic_char_map.h>
     
    5049#include <adt/measured_strings.h>
    5150
     51
    5252/** Type definition of the ARP device specific data.
    53  * @see arp_device
     53 *  @see arp_device
    5454 */
    55 typedef struct arp_device arp_device_t;
     55typedef struct arp_device       arp_device_t;
    5656
    5757/** Type definition of the ARP device specific data pointer.
    58  * @see arp_device
     58 *  @see arp_device
    5959 */
    60 typedef arp_device_t *arp_device_ref;
     60typedef arp_device_t *          arp_device_ref;
    6161
    6262/** Type definition of the ARP global data.
    63  * @see arp_globals
     63 *  @see arp_globals
    6464 */
    65 typedef struct arp_globals arp_globals_t;
     65typedef struct arp_globals      arp_globals_t;
    6666
    6767/** Type definition of the ARP protocol specific data.
    68  * @see arp_proto
     68 *  @see arp_proto
    6969 */
    70 typedef struct arp_proto arp_proto_t;
     70typedef struct arp_proto        arp_proto_t;
    7171
    7272/** Type definition of the ARP protocol specific data pointer.
    73  * @see arp_proto
     73 *  @see arp_proto
    7474 */
    75 typedef arp_proto_t *arp_proto_ref;
     75typedef arp_proto_t *           arp_proto_ref;
    7676
    7777/** ARP address map.
    78  *
    79  * Translates addresses.
    80  * @see generic_char_map.h
     78 *  Translates addresses.
     79 *  @see generic_char_map.h
    8180 */
    82 GENERIC_CHAR_MAP_DECLARE(arp_addr, measured_string_t);
     81GENERIC_CHAR_MAP_DECLARE(arp_addr, measured_string_t)
    8382
    8483/** ARP address cache.
    85  *
    86  * Maps devices to the ARP device specific data.
    87  * @see device.h
     84 *  Maps devices to the ARP device specific data.
     85 *  @see device.h
    8886 */
    89 DEVICE_MAP_DECLARE(arp_cache, arp_device_t);
     87DEVICE_MAP_DECLARE(arp_cache, arp_device_t)
    9088
    9189/** ARP protocol map.
    92  *
    93  * Maps protocol identifiers to the ARP protocol specific data.
    94  * @see int_map.h
     90 *  Maps protocol identifiers to the ARP protocol specific data.
     91 *  @see int_map.h
    9592 */
    96 INT_MAP_DECLARE(arp_protos, arp_proto_t);
     93INT_MAP_DECLARE(arp_protos, arp_proto_t)
    9794
    98 /** ARP device specific data. */
    99 struct arp_device {
    100         /** Actual device hardware address. */
     95/** ARP device specific data.
     96 */
     97struct arp_device{
     98        /** Actual device hardware address.
     99         */
    101100        measured_string_ref addr;
    102         /** Actual device hardware address data. */
    103         char *addr_data;
    104         /** Broadcast device hardware address. */
     101        /** Actual device hardware address data.
     102         */
     103        char * addr_data;
     104        /** Broadcast device hardware address.
     105         */
    105106        measured_string_ref broadcast_addr;
    106         /** Broadcast device hardware address data. */
    107         char *broadcast_data;
    108         /** Device identifier. */
     107        /** Broadcast device hardware address data.
     108         */
     109        char * broadcast_data;
     110        /** Device identifier.
     111         */
    109112        device_id_t device_id;
    110         /** Hardware type. */
     113        /** Hardware type.
     114         */
    111115        hw_type_t hardware;
    112         /** Packet dimension. */
     116        /** Packet dimension.
     117         */
    113118        packet_dimension_t packet_dimension;
    114         /** Device module phone. */
     119        /** Device module phone.
     120         */
    115121        int phone;
    116        
    117         /**
    118          * Protocol map.
    119          * Address map for each protocol.
     122        /** Protocol map.
     123         *  Address map for each protocol.
    120124         */
    121125        arp_protos_t protos;
    122        
    123         /** Device module service. */
     126        /** Device module service.
     127        */
    124128        services_t service;
    125129};
    126130
    127 /** ARP global data. */
    128 struct arp_globals {
    129         /** ARP address cache. */
     131/** ARP global data.
     132 */
     133struct  arp_globals{
     134        /** ARP address cache.
     135         */
    130136        arp_cache_t cache;
    131        
    132         /**
    133          * The client connection processing function.
    134          * The module skeleton propagates its own one.
     137        /** The client connection processing function.
     138         *  The module skeleton propagates its own one.
    135139         */
    136140        async_client_conn_t client_connection;
    137        
    138         /** Networking module phone. */
     141        /** Networking module phone.
     142        */
    139143        int net_phone;
    140         /** Safety lock. */
     144        /** Safety lock.
     145         */
    141146        fibril_rwlock_t lock;
    142147};
    143148
    144 /** ARP protocol specific data. */
    145 struct arp_proto {
    146         /** Actual device protocol address. */
     149/** ARP protocol specific data.
     150 */
     151struct arp_proto{
     152        /** Actual device protocol address.
     153         */
    147154        measured_string_ref addr;
    148         /** Actual device protocol address data. */
    149         char *addr_data;
    150         /** Address map. */
     155        /** Actual device protocol address data.
     156         */
     157        char * addr_data;
     158        /** Address map.
     159         */
    151160        arp_addr_t addresses;
    152         /** Protocol service. */
     161        /** Protocol service.
     162         */
    153163        services_t service;
    154164};
  • uspace/srv/net/il/arp/arp_header.h

    r069015f2 rf2d2c604  
    3232
    3333/** @file
    34  * ARP protocol header.
    35  * Based on the RFC 826.
     34 *  ARP protocol header.
     35 *  Based on the RFC~826.
    3636 */
    3737
    38 #ifndef NET_ARP_HEADER_H_
    39 #define NET_ARP_HEADER_H_
     38#ifndef __NET_ARP_HEADER_H__
     39#define __NET_ARP_HEADER_H__
    4040
    4141#include <sys/types.h>
    4242
    4343/** Type definition of an ARP protocol header.
    44  * @see arp_header
     44 *  @see arp_header
    4545 */
    46 typedef struct arp_header arp_header_t;
     46typedef struct arp_header       arp_header_t;
    4747
    4848/** Type definition of an ARP protocol header pointer.
    49  * @see arp_header
     49 *  @see arp_header
    5050 */
    51 typedef arp_header_t *arp_header_ref;
     51typedef arp_header_t *          arp_header_ref;
    5252
    53 /** ARP protocol header. */
    54 struct arp_header {
    55         /**
    56          * Hardware type identifier.
    57          * @see hardware.h
     53/** ARP protocol header.
     54 */
     55struct arp_header{
     56        /** Hardware type identifier.
     57         *  @see hardware.h
    5858         */
    5959        uint16_t hardware;
    60        
    61         /** Protocol identifier. */
     60        /** Protocol identifier.
     61        */
    6262        uint16_t protocol;
    63         /** Hardware address length in bytes. */
     63        /** Hardware address length in bytes.
     64         */
    6465        uint8_t hardware_length;
    65         /** Protocol address length in bytes. */
     66        /** Protocol address length in bytes.
     67         */
    6668        uint8_t protocol_length;
    67        
    68         /**
    69          * ARP packet type.
    70          * @see arp_oc.h
     69        /** ARP packet type.
     70         *  @see arp_oc.h
    7171         */
    7272        uint16_t operation;
  • uspace/srv/net/il/arp/arp_module.c

    r069015f2 rf2d2c604  
    3232
    3333/** @file
    34  * ARP standalone module implementation.
    35  * Contains skeleton module functions mapping.
    36  * The functions are used by the module skeleton as module specific entry
    37  * points.
    38  * @see module.c
     34 *  ARP standalone module implementation.
     35 *  Contains skeleton module functions mapping.
     36 *  The functions are used by the module skeleton as module specific entry points.
     37 *  @see module.c
    3938 */
    4039
     
    5453#include "arp_module.h"
    5554
    56 /** ARP module global data. */
    57 extern arp_globals_t arp_globals;
     55/** ARP module global data.
     56 */
     57extern arp_globals_t    arp_globals;
    5858
    59 int
    60 il_module_message_standalone(ipc_callid_t callid, ipc_call_t *call,
    61     ipc_call_t *answer, int *answer_count)
    62 {
     59int il_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
    6360        return arp_message_standalone(callid, call, answer, answer_count);
    6461}
    6562
    66 int il_module_start_standalone(async_client_conn_t client_connection)
    67 {
     63int il_module_start_standalone(async_client_conn_t client_connection){
    6864        ERROR_DECLARE;
    6965       
     
    7369       
    7470        ipcarg_t phonehash;
    75         if (ERROR_OCCURRED(arp_initialize(client_connection)) ||
    76             ERROR_OCCURRED(REGISTER_ME(SERVICE_ARP, &phonehash))) {
     71        if (ERROR_OCCURRED(arp_initialize(client_connection))
     72            || ERROR_OCCURRED(REGISTER_ME(SERVICE_ARP, &phonehash))) {
    7773                pm_destroy();
    7874                return ERROR_CODE;
  • uspace/srv/net/il/arp/arp_module.h

    r069015f2 rf2d2c604  
    2828
    2929/** @addtogroup arp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @file
    34  * ARP module functions.
    35  * The functions are used as ARP module entry points.
     34 *  ARP module functions.
     35 *  The functions are used as ARP module entry points.
    3636 */
    3737
    38 #ifndef NET_ARP_MODULE_H_
    39 #define NET_ARP_MODULE_H_
     38#ifndef __NET_ARP_MODULE_H__
     39#define __NET_ARP_MODULE_H__
    4040
    4141#include <ipc/ipc.h>
    42 #include <async.h>
    4342
    44 extern int arp_initialize(async_client_conn_t);
    45 extern int arp_message_standalone(ipc_callid_t, ipc_call_t *, ipc_call_t *,
    46     int *);
     43/** Initializes the ARP module.
     44 *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
     45 *  @returns EOK on success.
     46 *  @returns ENOMEM if there is not enough memory left.
     47 */
     48int arp_initialize(async_client_conn_t client_connection);
     49
     50/** Processes the ARP message.
     51 *  @param[in] callid The message identifier.
     52 *  @param[in] call The message parameters.
     53 *  @param[out] answer The message answer parameters.
     54 *  @param[out] answer_count The last parameter for the actual answer in the answer parameter.
     55 *  @returns EOK on success.
     56 *  @returns ENOTSUP if the message is not known.
     57 *  @see arp_interface.h
     58 *  @see IS_NET_ARP_MESSAGE()
     59 */
     60int arp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
    4761
    4862#endif
  • uspace/srv/net/il/arp/arp_oc.h

    r069015f2 rf2d2c604  
    3232
    3333/** @file
    34  * ARP operation codes according to the on-line IANA - Address Resolution
    35  * Protocol (ARP) Parameters
    36  * http://www.iana.org/assignments/arp-parameters/arp-parameters.xml
    37  * cited January 14 2009.
     34 *  ARP operation codes according to the on-line IANA - Address Resolution Protocol (ARP) Parameters - <http://www.iana.org/assignments/arp-parameters/arp-parameters.xml>, cited January 14 2009.
    3835 */
    3936
    40 #ifndef NET_ARP_ARPOP_H_
    41 #define NET_ARP_ARPOP_H_
     37#ifndef __NET_ARP_ARPOP_H__
     38#define __NET_ARP_ARPOP_H__
    4239
    43 /** @name ARP operation codes definitions */
     40/** @name ARP operation codes definitions
     41 */
    4442/*@{*/
    4543
    46 /** REQUEST operation code. */
    47 #define ARPOP_REQUEST   1
     44/** REQUEST operation code.
     45 */
     46#define ARPOP_REQUEST                                   1
    4847
    49 /** REPLY operation code. */
    50 #define ARPOP_REPLY     2
     48/** REPLY operation code.
     49 */
     50#define ARPOP_REPLY                                             2
     51
     52/** Reverse request operation code.
     53 */
     54#define ARPOP_RREQUEST                                  3
     55
     56/** Reverse reply operation code.
     57 */
     58#define ARPOP_RREPLY                                    4
     59
     60/** DRARP-Request operation code.
     61 */
     62#define ARPOP_DRARP_Request                             5
     63
     64/** DRARP-Reply operation code.
     65 */
     66#define ARPOP_DRARP_Reply                               6
     67
     68/** DRARP-Error operation code.
     69 */
     70#define ARPOP_DRARP_Error                               7
     71
     72/** InARP-Request operation code.
     73 */
     74#define ARPOP_InREQUEST                                 8
     75
     76/** InARP-Reply operation code.
     77 */
     78#define ARPOP_InREPLY                                   9
     79
     80/** ARP-NAK operation code.
     81 */
     82#define ARPOP_NAK                                               10
     83
     84/** MARS-Request operation code.
     85 */
     86#define ARPOP_MARS_Request                              11
     87
     88/** MARS-Multi operation code.
     89 */
     90#define ARPOP_MARS_Multi                                12
     91
     92/** MARS-MServ operation code.
     93 */
     94#define ARPOP_MARS_MServ                                13
     95
     96/** MARS-Join operation code.
     97 */
     98#define ARPOP_MARS_Join                                 14
     99
     100/** MARS-Leave operation code.
     101 */
     102#define ARPOP_MARS_Leave                                15
     103
     104/** MARS-NAK operation code.
     105 */
     106#define ARPOP_MARS_NAK                                  16
     107
     108/** MARS-Unserv operation code.
     109 */
     110#define ARPOP_MARS_Unserv                               17
     111
     112/** MARS-SJoin operation code.
     113 */
     114#define ARPOP_MARS_SJoin                                18
     115
     116/** MARS-SLeave operation code.
     117 */
     118#define ARPOP_MARS_SLeave                               19
     119
     120/** MARS-Grouplist-Request operation code.
     121 */
     122#define ARPOP_MARS_Grouplist_Request    20
     123
     124/** MARS-Grouplist-Reply operation code.
     125 */
     126#define ARPOP_MARS_Grouplist_Reply              21
     127
     128/** MARS-Redirect-Map operation code.
     129 */
     130#define ARPOP_MARS_Redirect_Map                 22
     131
     132/** MAPOS-UNARP operation code.
     133 */
     134#define ARPOP_MAPOS_UNARP                               23
    51135
    52136/*@}*/
  • uspace/srv/net/il/ip/ip.c

    r069015f2 rf2d2c604  
    2828
    2929/** @addtogroup ip
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @file
    34  * IP module implementation.
    35  * @see arp.h
    36  */
    37 
    38 #include "ip.h"
    39 #include "ip_module.h"
     34 *  IP module implementation.
     35 *  @see arp.h
     36 */
    4037
    4138#include <async.h>
     
    5451#include <byteorder.h>
    5552
    56 #include <adt/measured_strings.h>
    57 #include <adt/module_map.h>
    58 
    59 #include <packet_client.h>
    6053#include <net/socket_codes.h>
    6154#include <net/in.h>
     
    7871#include <nil_interface.h>
    7972#include <tl_interface.h>
     73#include <adt/measured_strings.h>
     74#include <adt/module_map.h>
     75#include <packet_client.h>
    8076#include <packet_remote.h>
    8177#include <il_local.h>
    8278
    83 /** IP module name. */
    84 #define NAME                    "ip"
    85 
    86 /** IP version 4. */
    87 #define IPV4                    4
    88 
    89 /** Default network interface IP version. */
     79#include "ip.h"
     80#include "ip_module.h"
     81#include "ip_local.h"
     82
     83/** IP module name.
     84 */
     85#define NAME  "ip"
     86
     87/** IP version 4.
     88 */
     89#define IPV4                            4
     90
     91/** Default network interface IP version.
     92 */
    9093#define NET_DEFAULT_IPV         IPV4
    9194
    92 /** Default network interface IP routing. */
     95/** Default network interface IP routing.
     96 */
    9397#define NET_DEFAULT_IP_ROUTING  false
    9498
    95 /** Minimum IP packet content. */
    96 #define IP_MIN_CONTENT          576
    97 
    98 /** ARP module name. */
    99 #define ARP_NAME                "arp"
    100 
    101 /** ARP module filename. */
    102 #define ARP_FILENAME            "/srv/arp"
    103 
    104 /** IP packet address length. */
    105 #define IP_ADDR                 sizeof(struct sockaddr_in6)
    106 
    107 /** IP packet prefix length. */
    108 #define IP_PREFIX               sizeof(ip_header_t)
    109 
    110 /** IP packet suffix length. */
    111 #define IP_SUFFIX               0
    112 
    113 /** IP packet maximum content length. */
    114 #define IP_MAX_CONTENT          65535
    115 
    116 /** The IP localhost address. */
     99/** Minimum IP packet content.
     100 */
     101#define IP_MIN_CONTENT  576
     102
     103/** ARP module name.
     104 */
     105#define ARP_NAME                                "arp"
     106
     107/** ARP module filename.
     108 */
     109#define ARP_FILENAME                    "/srv/arp"
     110
     111/** IP packet address length.
     112 */
     113#define IP_ADDR                                                 sizeof(struct sockaddr_in6)
     114
     115/** IP packet prefix length.
     116 */
     117#define IP_PREFIX                                               sizeof(ip_header_t)
     118
     119/** IP packet suffix length.
     120 */
     121#define IP_SUFFIX                                               0
     122
     123/** IP packet maximum content length.
     124 */
     125#define IP_MAX_CONTENT                                  65535
     126
     127/** The IP localhost address.
     128 */
    117129#define IPV4_LOCALHOST_ADDRESS  htonl((127 << 24) + 1)
    118130
    119 /** IP global data. */
    120 ip_globals_t ip_globals;
    121 
    122 DEVICE_MAP_IMPLEMENT(ip_netifs, ip_netif_t);
    123 INT_MAP_IMPLEMENT(ip_protos, ip_proto_t);
    124 GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t);
     131/** IP global data.
     132 */
     133ip_globals_t    ip_globals;
     134
     135DEVICE_MAP_IMPLEMENT(ip_netifs, ip_netif_t)
     136
     137INT_MAP_IMPLEMENT(ip_protos, ip_proto_t)
     138
     139GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t)
     140
     141/** Updates the device content length according to the new MTU value.
     142 *  @param[in] device_id The device identifier.
     143 *  @param[in] mtu The new mtu value.
     144 *  @returns EOK on success.
     145 *  @returns ENOENT if device is not found.
     146 */
     147int ip_mtu_changed_message(device_id_t device_id, size_t mtu);
     148
     149/** Updates the device state.
     150 *  @param[in] device_id The device identifier.
     151 *  @param[in] state The new state value.
     152 *  @returns EOK on success.
     153 *  @returns ENOENT if device is not found.
     154 */
     155int ip_device_state_message(device_id_t device_id, device_state_t state);
     156
     157/** Returns the device packet dimensions for sending.
     158 *  @param[in] phone The service module phone.
     159 *  @param[in] message The service specific message.
     160 *  @param[in] device_id The device identifier.
     161 *  @param[out] addr_len The minimum reserved address length.
     162 *  @param[out] prefix The minimum reserved prefix size.
     163 *  @param[out] content The maximum content size.
     164 *  @param[out] suffix The minimum reserved suffix size.
     165 *  @returns EOK on success.
     166 */
     167int ip_packet_size_message(device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix);
     168
     169/** Registers the transport layer protocol.
     170 *  The traffic of this protocol will be supplied using either the receive function or IPC message.
     171 *  @param[in] protocol The transport layer module protocol.
     172 *  @param[in] service The transport layer module service.
     173 *  @param[in] phone The transport layer module phone.
     174 *  @param[in] tl_received_msg The receiving function.
     175 *  @returns EOK on success.
     176 *  @returns EINVAL if the protocol parameter and/or the service parameter is zero (0).
     177 *  @returns EINVAL if the phone parameter is not a positive number and the tl_receive_msg is NULL.
     178 *  @returns ENOMEM if there is not enough memory left.
     179 */
     180int ip_register(int protocol, services_t service, int phone, tl_received_msg_t tl_received_msg);
     181
     182/** Initializes a new network interface specific data.
     183 *  Connects to the network interface layer module, reads the netif configuration, starts an ARP module if needed and sets the netif routing table.
     184 *  The device identifier and the nil service has to be set.
     185 *  @param[in,out] ip_netif Network interface specific data.
     186 *  @returns EOK on success.
     187 *  @returns ENOTSUP if DHCP is configured.
     188 *  @returns ENOTSUP if IPv6 is configured.
     189 *  @returns EINVAL if any of the addresses is invalid.
     190 *  @returns EINVAL if the used ARP module is not known.
     191 *  @returns ENOMEM if there is not enough memory left.
     192 *  @returns Other error codes as defined for the net_get_device_conf_req() function.
     193 *  @returns Other error codes as defined for the bind_service() function.
     194 *  @returns Other error codes as defined for the specific arp_device_req() function.
     195 *  @returns Other error codes as defined for the nil_packet_size_req() function.
     196 */
     197int ip_netif_initialize(ip_netif_ref ip_netif);
     198
     199/** Sends the packet or the packet queue via the specified route.
     200 *  The ICMP_HOST_UNREACH error notification may be sent if route hardware destination address is found.
     201 *  @param[in,out] packet The packet to be sent.
     202 *  @param[in] netif The target network interface.
     203 *  @param[in] route The target route.
     204 *  @param[in] src The source address.
     205 *  @param[in] dest The destination address.
     206 *  @param[in] error The error module service.
     207 *  @returns EOK on success.
     208 *  @returns Other error codes as defined for the arp_translate_req() function.
     209 *  @returns Other error codes as defined for the ip_prepare_packet() function.
     210 */
     211int ip_send_route(packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest, services_t error);
     212
     213/** Prepares the outgoing packet or the packet queue.
     214 *  The packet queue is a fragmented packet
     215 *  Updates the first packet's IP header.
     216 *  Prefixes the additional packets with fragment headers.
     217 *  @param[in] source The source address.
     218 *  @param[in] dest The destination address.
     219 *  @param[in,out] packet The packet to be sent.
     220 *  @param[in] destination The destination hardware address.
     221 *  @returns EOK on success.
     222 *  @returns EINVAL if the packet is too small to contain the IP header.
     223 *  @returns EINVAL if the packet is too long than the IP allows.
     224 *  @returns ENOMEM if there is not enough memory left.
     225 *  @returns Other error codes as defined for the packet_set_addr() function.
     226 */
     227int ip_prepare_packet(in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination);
     228
     229/** Checks the packet queue lengths and fragments the packets if needed.
     230 *  The ICMP_FRAG_NEEDED error notification may be sent if the packet needs to be fragmented and the fragmentation is not allowed.
     231 *  @param[in,out] packet The packet or the packet queue to be checked.
     232 *  @param[in] prefix The minimum prefix size.
     233 *  @param[in] content The maximum content size.
     234 *  @param[in] suffix The minimum suffix size.
     235 *  @param[in] addr_len The minimum address length.
     236 *  @param[in] error The error module service.
     237 *  @returns The packet or the packet queue of the allowed length.
     238 *  @returns NULL if there are no packets left.
     239 */
     240packet_t ip_split_packet(packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error);
     241
     242/** Checks the packet length and fragments it if needed.
     243 *  The new fragments are queued before the original packet.
     244 *  @param[in,out] packet The packet to be checked.
     245 *  @param[in] length The maximum packet length.
     246 *  @param[in] prefix The minimum prefix size.
     247 *  @param[in] suffix The minimum suffix size.
     248 *  @param[in] addr_len The minimum address length.
     249 *  @returns EOK on success.
     250 *  @returns EINVAL if the packet_get_addr() function fails.
     251 *  @returns EINVAL if the packet does not contain the IP header.
     252 *  @returns EPERM if the packet needs to be fragmented and the fragmentation is not allowed.
     253 *  @returns ENOMEM if there is not enough memory left.
     254 *  @returns ENOMEM if there is no packet available.
     255 *  @returns ENOMEM if the packet is too small to contain the IP header.
     256 *  @returns Other error codes as defined for the packet_trim() function.
     257 *  @returns Other error codes as defined for the ip_create_middle_header() function.
     258 *  @returns Other error codes as defined for the ip_fragment_packet_data() function.
     259 */
     260int ip_fragment_packet(packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len);
     261
     262/** Fragments the packet from the end.
     263 *  @param[in] packet The packet to be fragmented.
     264 *  @param[in,out] new_packet The new packet fragment.
     265 *  @param[in,out] header The original packet header.
     266 *  @param[in,out] new_header The new packet fragment header.
     267 *  @param[in] length The new fragment length.
     268 *  @param[in] src The source address.
     269 *  @param[in] dest The destiantion address.
     270 *  @param[in] addrlen The address length.
     271 *  @returns EOK on success.
     272 *  @returns ENOMEM if the target packet is too small.
     273 *  @returns Other error codes as defined for the packet_set_addr() function.
     274 *  @returns Other error codes as defined for the pq_insert_after() function.
     275 */
     276int ip_fragment_packet_data(packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, const struct sockaddr * src, const struct sockaddr * dest, socklen_t addrlen);
     277
     278/** Prefixes a middle fragment header based on the last fragment header to the packet.
     279 *  @param[in] packet The packet to be prefixed.
     280 *  @param[in] last The last header to be copied.
     281 *  @returns The prefixed middle header.
     282 *  @returns NULL on error.
     283 */
     284ip_header_ref ip_create_middle_header(packet_t packet, ip_header_ref last);
     285
     286/** Copies the fragment header.
     287 *  Copies only the header itself and relevant IP options.
     288 *  @param[out] last The created header.
     289 *  @param[in] first The original header to be copied.
     290 */
     291void ip_create_last_header(ip_header_ref last, ip_header_ref first);
     292
     293/** Returns the network interface's IP address.
     294 *  @param[in] netif The network interface.
     295 *  @returns The IP address.
     296 *  @returns NULL if no IP address was found.
     297 */
     298in_addr_t * ip_netif_address(ip_netif_ref netif);
     299
     300/** Searches all network interfaces if there is a suitable route.
     301 *  @param[in] destination The destination address.
     302 *  @returns The found route.
     303 *  @returns NULL if no route was found.
     304 */
     305ip_route_ref ip_find_route(in_addr_t destination);
     306
     307/** Searches the network interfaces if there is a suitable route.
     308 *  @param[in] netif The network interface to be searched for routes. May be NULL.
     309 *  @param[in] destination The destination address.
     310 *  @returns The found route.
     311 *  @returns NULL if no route was found.
     312 */
     313ip_route_ref ip_netif_find_route(ip_netif_ref netif, in_addr_t destination);
     314
     315/** Processes the received IP packet or the packet queue one by one.
     316 *  The packet is either passed to another module or released on error.
     317 *  @param[in] device_id The source device identifier.
     318 *  @param[in,out] packet The received packet.
     319 *  @returns EOK on success and the packet is no longer needed.
     320 *  @returns EINVAL if the packet is too small to carry the IP packet.
     321 *  @returns EINVAL if the received address lengths differs from the registered values.
     322 *  @returns ENOENT if the device is not found in the cache.
     323 *  @returns ENOENT if the protocol for the device is not found in the cache.
     324 *  @returns ENOMEM if there is not enough memory left.
     325 */
     326int ip_receive_message(device_id_t device_id, packet_t packet);
     327
     328/** Processes the received packet.
     329 *  The packet is either passed to another module or released on error.
     330 *  The ICMP_PARAM_POINTER error notification may be sent if the checksum is invalid.
     331 *  The ICMP_EXC_TTL error notification may be sent if the TTL is less than two (2).
     332 *  The ICMP_HOST_UNREACH error notification may be sent if no route was found.
     333 *  The ICMP_HOST_UNREACH error notification may be sent if the packet is for another host and the routing is disabled.
     334 *  @param[in] device_id The source device identifier.
     335 *  @param[in] packet The received packet to be processed.
     336 *  @returns EOK on success.
     337 *  @returns EINVAL if the TTL is less than two (2).
     338 *  @returns EINVAL if the checksum is invalid.
     339 *  @returns EAFNOSUPPORT if the address family is not supported.
     340 *  @returns ENOENT if no route was found.
     341 *  @returns ENOENT if the packet is for another host and the routing is disabled.
     342 */
     343int ip_process_packet(device_id_t device_id, packet_t packet);
     344
     345/** Returns the packet destination address from the IP header.
     346 *  @param[in] header The packet IP header to be read.
     347 *  @returns The packet destination address.
     348 */
     349in_addr_t ip_get_destination(ip_header_ref header);
     350
     351/** Delivers the packet to the local host.
     352 *  The packet is either passed to another module or released on error.
     353 *  The ICMP_PROT_UNREACH error notification may be sent if the protocol is not found.
     354 *  @param[in] device_id The source device identifier.
     355 *  @param[in] packet The packet to be delivered.
     356 *  @param[in] header The first packet IP header. May be NULL.
     357 *  @param[in] error The packet error service.
     358 *  @returns EOK on success.
     359 *  @returns ENOTSUP if the packet is a fragment.
     360 *  @returns EAFNOSUPPORT if the address family is not supported.
     361 *  @returns ENOENT if the target protocol is not found.
     362 *  @returns Other error codes as defined for the packet_set_addr() function.
     363 *  @returns Other error codes as defined for the packet_trim() function.
     364 *  @returns Other error codes as defined for the protocol specific tl_received_msg function.
     365 */
     366int ip_deliver_local(device_id_t device_id, packet_t packet, ip_header_ref header, services_t error);
     367
     368/** Prepares the ICMP notification packet.
     369 *  Releases additional packets and keeps only the first one.
     370 *  All packets is released on error.
     371 *  @param[in] error The packet error service.
     372 *  @param[in] packet The packet or the packet queue to be reported as faulty.
     373 *  @param[in] header The first packet IP header. May be NULL.
     374 *  @returns The found ICMP phone.
     375 *  @returns EINVAL if the error parameter is set.
     376 *  @returns EINVAL if the ICMP phone is not found.
     377 *  @returns EINVAL if the ip_prepare_icmp() fails.
     378 */
     379int ip_prepare_icmp_and_get_phone(services_t error, packet_t packet, ip_header_ref header);
     380
     381/** Returns the ICMP phone.
     382 *  Searches the registered protocols.
     383 *  @returns The found ICMP phone.
     384 *  @returns ENOENT if the ICMP is not registered.
     385 */
     386int ip_get_icmp_phone(void);
     387
     388/** Prepares the ICMP notification packet.
     389 *  Releases additional packets and keeps only the first one.
     390 *  @param[in] packet The packet or the packet queue to be reported as faulty.
     391 *  @param[in] header The first packet IP header. May be NULL.
     392 *  @returns EOK on success.
     393 *  @returns EINVAL if there are no data in the packet.
     394 *  @returns EINVAL if the packet is a fragment.
     395 *  @returns ENOMEM if the packet is too short to contain the IP header.
     396 *  @returns EAFNOSUPPORT if the address family is not supported.
     397 *  @returns EPERM if the protocol is not allowed to send ICMP notifications. The ICMP protocol itself.
     398 *  @returns Other error codes as defined for the packet_set_addr().
     399 */
     400int ip_prepare_icmp(packet_t packet, ip_header_ref header);
    125401
    126402/** Releases the packet and returns the result.
    127  *
    128  * @param[in] packet    The packet queue to be released.
    129  * @param[in] result    The result to be returned.
    130  * @return              The result parameter.
    131  */
    132 static int ip_release_and_return(packet_t packet, int result)
    133 {
    134         pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
    135         return result;
    136 }
    137 
    138 /** Returns the ICMP phone.
    139  *
    140  * Searches the registered protocols.
    141  *
    142  * @returns             The found ICMP phone.
    143  * @returns             ENOENT if the ICMP is not registered.
    144  */
    145 static int ip_get_icmp_phone(void)
    146 {
    147         ip_proto_ref proto;
    148         int phone;
    149 
    150         fibril_rwlock_read_lock(&ip_globals.protos_lock);
    151         proto = ip_protos_find(&ip_globals.protos, IPPROTO_ICMP);
    152         phone = proto ? proto->phone : ENOENT;
    153         fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    154         return phone;
    155 }
    156 
    157 /** Prepares the ICMP notification packet.
    158  *
    159  * Releases additional packets and keeps only the first one.
    160  *
    161  * @param[in] packet    The packet or the packet queue to be reported as faulty.
    162  * @param[in] header    The first packet IP header. May be NULL.
    163  * @returns             EOK on success.
    164  * @returns             EINVAL if there are no data in the packet.
    165  * @returns             EINVAL if the packet is a fragment.
    166  * @returns             ENOMEM if the packet is too short to contain the IP
    167  *                      header.
    168  * @returns             EAFNOSUPPORT if the address family is not supported.
    169  * @returns             EPERM if the protocol is not allowed to send ICMP
    170  *                      notifications. The ICMP protocol itself.
    171  * @returns             Other error codes as defined for the packet_set_addr().
    172  */
    173 static int ip_prepare_icmp(packet_t packet, ip_header_ref header)
    174 {
    175         packet_t next;
    176         struct sockaddr *dest;
    177         struct sockaddr_in dest_in;
    178         socklen_t addrlen;
    179 
    180         // detach the first packet and release the others
    181         next = pq_detach(packet);
    182         if (next)
    183                 pq_release_remote(ip_globals.net_phone, packet_get_id(next));
    184 
    185         if (!header) {
    186                 if (packet_get_data_length(packet) <= sizeof(ip_header_t))
    187                         return ENOMEM;
    188 
    189                 // get header
    190                 header = (ip_header_ref) packet_get_data(packet);
    191                 if (!header)
    192                         return EINVAL;
    193 
    194         }
    195 
    196         // only for the first fragment
    197         if (IP_FRAGMENT_OFFSET(header))
    198                 return EINVAL;
    199 
    200         // not for the ICMP protocol
    201         if (header->protocol == IPPROTO_ICMP)
    202                 return EPERM;
    203 
    204         // set the destination address
    205         switch (header->version) {
    206         case IPVERSION:
    207                 addrlen = sizeof(dest_in);
    208                 bzero(&dest_in, addrlen);
    209                 dest_in.sin_family = AF_INET;
    210                 memcpy(&dest_in.sin_addr.s_addr, &header->source_address,
    211                     sizeof(header->source_address));
    212                 dest = (struct sockaddr *) &dest_in;
    213                 break;
    214 
    215         default:
    216                 return EAFNOSUPPORT;
    217         }
    218 
    219         return packet_set_addr(packet, NULL, (uint8_t *) dest, addrlen);
    220 }
    221 
    222 /** Prepares the ICMP notification packet.
    223  *
    224  * Releases additional packets and keeps only the first one.
    225  * All packets are released on error.
    226  *
    227  * @param[in] error     The packet error service.
    228  * @param[in] packet    The packet or the packet queue to be reported as faulty.
    229  * @param[in] header    The first packet IP header. May be NULL.
    230  * @returns             The found ICMP phone.
    231  * @returns             EINVAL if the error parameter is set.
    232  * @returns             EINVAL if the ICMP phone is not found.
    233  * @returns             EINVAL if the ip_prepare_icmp() fails.
    234  */
    235 static int
    236 ip_prepare_icmp_and_get_phone(services_t error, packet_t packet,
    237     ip_header_ref header)
    238 {
    239         int phone;
    240 
    241         phone = ip_get_icmp_phone();
    242         if (error || (phone < 0) || ip_prepare_icmp(packet, header))
    243                 return ip_release_and_return(packet, EINVAL);
    244         return phone;
    245 }
    246 
    247 /** Initializes the IP module.
    248  *
    249  * @param[in] client_connection The client connection processing function. The
    250  *                      module skeleton propagates its own one.
    251  * @returns             EOK on success.
    252  * @returns             ENOMEM if there is not enough memory left.
    253  */
    254 int ip_initialize(async_client_conn_t client_connection)
    255 {
     403 *  @param[in] packet The packet queue to be released.
     404 *  @param[in] result The result to be returned.
     405 *  @return The result parameter.
     406 */
     407int ip_release_and_return(packet_t packet, int result);
     408
     409int ip_initialize(async_client_conn_t client_connection){
    256410        ERROR_DECLARE;
    257411
     
    269423        ip_globals.client_connection = client_connection;
    270424        ERROR_PROPAGATE(modules_initialize(&ip_globals.modules));
    271         ERROR_PROPAGATE(add_module(NULL, &ip_globals.modules, ARP_NAME,
    272             ARP_FILENAME, SERVICE_ARP, 0, arp_connect_module));
     425        ERROR_PROPAGATE(add_module(NULL, &ip_globals.modules, ARP_NAME, ARP_FILENAME, SERVICE_ARP, 0, arp_connect_module));
    273426        fibril_rwlock_write_unlock(&ip_globals.lock);
    274 
    275427        return EOK;
    276428}
    277429
    278 /** Initializes a new network interface specific data.
    279  *
    280  * Connects to the network interface layer module, reads the netif
    281  * configuration, starts an ARP module if needed and sets the netif routing
    282  * table.
    283  *
    284  * The device identifier and the nil service has to be set.
    285  *
    286  * @param[in,out] ip_netif Network interface specific data.
    287  * @returns             EOK on success.
    288  * @returns             ENOTSUP if DHCP is configured.
    289  * @returns             ENOTSUP if IPv6 is configured.
    290  * @returns             EINVAL if any of the addresses is invalid.
    291  * @returns             EINVAL if the used ARP module is not known.
    292  * @returns             ENOMEM if there is not enough memory left.
    293  * @returns             Other error codes as defined for the
    294  *                      net_get_device_conf_req() function.
    295  * @returns             Other error codes as defined for the bind_service()
    296  *                      function.
    297  * @returns             Other error codes as defined for the specific
    298  *                      arp_device_req() function.
    299  * @returns             Other error codes as defined for the
    300  *                      nil_packet_size_req() function.
    301  */
    302 static int ip_netif_initialize(ip_netif_ref ip_netif)
    303 {
    304         ERROR_DECLARE;
    305 
    306         measured_string_t names[] = {
    307                 {
    308                         (char *) "IPV",
    309                         3
    310                 },
    311                 {
    312                         (char *) "IP_CONFIG",
    313                         9
    314                 },
    315                 {
    316                         (char *) "IP_ADDR",
    317                         7
    318                 },
    319                 {
    320                         (char *) "IP_NETMASK",
    321                         10
    322                 },
    323                 {
    324                         (char *) "IP_GATEWAY",
    325                         10
    326                 },
    327                 {
    328                         (char *) "IP_BROADCAST",
    329                         12
    330                 },
    331                 {
    332                         (char *) "ARP",
    333                         3
    334                 },
    335                 {
    336                         (char *) "IP_ROUTING",
    337                         10
    338                 }
    339         };
    340         measured_string_ref configuration;
    341         size_t count = sizeof(names) / sizeof(measured_string_t);
    342         char *data;
    343         measured_string_t address;
    344         int index;
    345         ip_route_ref route;
    346         in_addr_t gateway;
    347 
    348         ip_netif->arp = NULL;
    349         route = NULL;
    350         ip_netif->ipv = NET_DEFAULT_IPV;
    351         ip_netif->dhcp = false;
    352         ip_netif->routing = NET_DEFAULT_IP_ROUTING;
    353         configuration = &names[0];
    354 
    355         // get configuration
    356         ERROR_PROPAGATE(net_get_device_conf_req(ip_globals.net_phone,
    357             ip_netif->device_id, &configuration, count, &data));
    358         if (configuration) {
    359                 if (configuration[0].value)
    360                         ip_netif->ipv = strtol(configuration[0].value, NULL, 0);
    361 
    362                 ip_netif->dhcp = !str_lcmp(configuration[1].value, "dhcp",
    363                     configuration[1].length);
    364                
    365                 if (ip_netif->dhcp) {
    366                         // TODO dhcp
    367                         net_free_settings(configuration, data);
    368                         return ENOTSUP;
    369                 } else if (ip_netif->ipv == IPV4) {
    370                         route = (ip_route_ref) malloc(sizeof(ip_route_t));
    371                         if (!route) {
    372                                 net_free_settings(configuration, data);
    373                                 return ENOMEM;
    374                         }
    375                         route->address.s_addr = 0;
    376                         route->netmask.s_addr = 0;
    377                         route->gateway.s_addr = 0;
    378                         route->netif = ip_netif;
    379                         index = ip_routes_add(&ip_netif->routes, route);
    380                         if (index < 0) {
    381                                 net_free_settings(configuration, data);
    382                                 free(route);
    383                                 return index;
    384                         }
    385                         if (ERROR_OCCURRED(inet_pton(AF_INET,
    386                             configuration[2].value,
    387                             (uint8_t *) &route->address.s_addr)) ||
    388                             ERROR_OCCURRED(inet_pton(AF_INET,
    389                             configuration[3].value,
    390                             (uint8_t *) &route->netmask.s_addr)) ||
    391                             (inet_pton(AF_INET, configuration[4].value,
    392                             (uint8_t *) &gateway.s_addr) == EINVAL) ||
    393                             (inet_pton(AF_INET, configuration[5].value,
    394                             (uint8_t *) &ip_netif->broadcast.s_addr) == EINVAL))
    395                             {
    396                                 net_free_settings(configuration, data);
    397                                 return EINVAL;
    398                         }
    399                 } else {
    400                         // TODO ipv6 in separate module
    401                         net_free_settings(configuration, data);
    402                         return ENOTSUP;
    403                 }
    404 
    405                 if (configuration[6].value) {
    406                         ip_netif->arp = get_running_module(&ip_globals.modules,
    407                             configuration[6].value);
    408                         if (!ip_netif->arp) {
    409                                 printf("Failed to start the arp %s\n",
    410                                     configuration[6].value);
    411                                 net_free_settings(configuration, data);
    412                                 return EINVAL;
    413                         }
    414                 }
    415                 if (configuration[7].value)
    416                         ip_netif->routing = (configuration[7].value[0] == 'y');
    417 
    418                 net_free_settings(configuration, data);
    419         }
    420 
    421         // binds the netif service which also initializes the device
    422         ip_netif->phone = nil_bind_service(ip_netif->service,
    423             (ipcarg_t) ip_netif->device_id, SERVICE_IP,
    424             ip_globals.client_connection);
    425         if (ip_netif->phone < 0) {
    426                 printf("Failed to contact the nil service %d\n",
    427                     ip_netif->service);
    428                 return ip_netif->phone;
    429         }
    430 
    431         // has to be after the device netif module initialization
    432         if (ip_netif->arp) {
    433                 if (route) {
    434                         address.value = (char *) &route->address.s_addr;
    435                         address.length = CONVERT_SIZE(in_addr_t, char, 1);
    436                         ERROR_PROPAGATE(arp_device_req(ip_netif->arp->phone,
    437                             ip_netif->device_id, SERVICE_IP, ip_netif->service,
    438                             &address));
    439                 } else {
    440                         ip_netif->arp = 0;
    441                 }
    442         }
    443 
    444         // get packet dimensions
    445         ERROR_PROPAGATE(nil_packet_size_req(ip_netif->phone,
    446             ip_netif->device_id, &ip_netif->packet_dimension));
    447         if (ip_netif->packet_dimension.content < IP_MIN_CONTENT) {
    448                 printf("Maximum transmission unit %d bytes is too small, at "
    449                     "least %d bytes are needed\n",
    450                     ip_netif->packet_dimension.content, IP_MIN_CONTENT);
    451                 ip_netif->packet_dimension.content = IP_MIN_CONTENT;
    452         }
    453 
    454         index = ip_netifs_add(&ip_globals.netifs, ip_netif->device_id, ip_netif);
    455         if (index < 0)
    456                 return index;
    457        
    458         if (gateway.s_addr) {
    459                 // the default gateway
    460                 ip_globals.gateway.address.s_addr = 0;
    461                 ip_globals.gateway.netmask.s_addr = 0;
    462                 ip_globals.gateway.gateway.s_addr = gateway.s_addr;
    463                 ip_globals.gateway.netif = ip_netif;
    464         }
    465 
    466         return EOK;
    467 }
    468 
    469 /** Updates the device content length according to the new MTU value.
    470  *
    471  * @param[in] device_id The device identifier.
    472  * @param[in] mtu       The new mtu value.
    473  * @returns             EOK on success.
    474  * @returns             ENOENT if device is not found.
    475  */
    476 static int ip_mtu_changed_message(device_id_t device_id, size_t mtu)
    477 {
    478         ip_netif_ref netif;
    479 
    480         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    481         netif = ip_netifs_find(&ip_globals.netifs, device_id);
    482         if (!netif) {
    483                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    484                 return ENOENT;
    485         }
    486         netif->packet_dimension.content = mtu;
    487         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    488 
    489         printf("%s: Device %d changed MTU to %d\n", NAME, device_id, mtu);
    490 
    491         return EOK;
    492 }
    493 
    494 /** Updates the device state.
    495  *
    496  * @param[in] device_id The device identifier.
    497  * @param[in] state     The new state value.
    498  * @returns             EOK on success.
    499  * @returns             ENOENT if device is not found.
    500  */
    501 static int ip_device_state_message(device_id_t device_id, device_state_t state)
    502 {
    503         ip_netif_ref netif;
    504 
    505         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    506         // find the device
    507         netif = ip_netifs_find(&ip_globals.netifs, device_id);
    508         if (!netif) {
    509                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    510                 return ENOENT;
    511         }
    512         netif->state = state;
    513         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    514 
    515         printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
    516 
    517         return EOK;
    518 }
    519 
    520 
    521 /** Prefixes a middle fragment header based on the last fragment header to the
    522  * packet.
    523  *
    524  * @param[in] packet    The packet to be prefixed.
    525  * @param[in] last      The last header to be copied.
    526  * @returns             The prefixed middle header.
    527  * @returns             NULL on error.
    528  */
    529 static ip_header_ref
    530 ip_create_middle_header(packet_t packet, ip_header_ref last)
    531 {
    532         ip_header_ref middle;
    533 
    534         middle = (ip_header_ref) packet_suffix(packet, IP_HEADER_LENGTH(last));
    535         if (!middle)
    536                 return NULL;
    537         memcpy(middle, last, IP_HEADER_LENGTH(last));
    538         middle->flags |= IPFLAG_MORE_FRAGMENTS;
    539         return middle;
    540 }
    541 
    542 /** Copies the fragment header.
    543  *
    544  * Copies only the header itself and relevant IP options.
    545  *
    546  * @param[out] last     The created header.
    547  * @param[in] first     The original header to be copied.
    548  */
    549 static void ip_create_last_header(ip_header_ref last, ip_header_ref first)
    550 {
    551         ip_option_ref option;
    552         size_t next;
    553         size_t length;
    554 
    555         // copy first itself
    556         memcpy(last, first, sizeof(ip_header_t));
    557         length = sizeof(ip_header_t);
    558         next = sizeof(ip_header_t);
    559 
    560         // process all ip options
    561         while (next < first->header_length) {
    562                 option = (ip_option_ref) (((uint8_t *) first) + next);
    563                 // skip end or noop
    564                 if ((option->type == IPOPT_END) ||
    565                     (option->type == IPOPT_NOOP)) {
    566                         next++;
    567                 } else {
    568                         // copy if told so or skip
    569                         if (IPOPT_COPIED(option->type)) {
    570                                 memcpy(((uint8_t *) last) + length,
    571                                     ((uint8_t *) first) + next, option->length);
    572                                 length += option->length;
    573                         }
    574                         // next option
    575                         next += option->length;
    576                 }
    577         }
    578 
    579         // align 4 byte boundary
    580         if (length % 4) {
    581                 bzero(((uint8_t *) last) + length, 4 - (length % 4));
    582                 last->header_length = length / 4 + 1;
    583         } else {
    584                 last->header_length = length / 4;
    585         }
    586 
    587         last->header_checksum = 0;
    588 }
    589 
    590 /** Prepares the outgoing packet or the packet queue.
    591  *
    592  * The packet queue is a fragmented packet
    593  * Updates the first packet's IP header.
    594  * Prefixes the additional packets with fragment headers.
    595  *
    596  * @param[in] source    The source address.
    597  * @param[in] dest      The destination address.
    598  * @param[in,out] packet The packet to be sent.
    599  * @param[in] destination The destination hardware address.
    600  * @returns             EOK on success.
    601  * @returns             EINVAL if the packet is too small to contain the IP
    602  *                      header.
    603  * @returns             EINVAL if the packet is too long than the IP allows.
    604  * @returns             ENOMEM if there is not enough memory left.
    605  * @returns             Other error codes as defined for the packet_set_addr()
    606  *                      function.
    607  */
    608 static int
    609 ip_prepare_packet(in_addr_t *source, in_addr_t dest, packet_t packet,
    610     measured_string_ref destination)
    611 {
    612         ERROR_DECLARE;
    613 
    614         size_t length;
    615         ip_header_ref header;
    616         ip_header_ref last_header;
    617         ip_header_ref middle_header;
    618         packet_t next;
    619 
    620         length = packet_get_data_length(packet);
    621         if ((length < sizeof(ip_header_t)) || (length > IP_MAX_CONTENT))
    622                 return EINVAL;
    623 
    624         header = (ip_header_ref) packet_get_data(packet);
    625         if (destination) {
    626                 ERROR_PROPAGATE(packet_set_addr(packet, NULL,
    627                     (uint8_t *) destination->value,
    628                     CONVERT_SIZE(char, uint8_t, destination->length)));
    629         } else {
    630                 ERROR_PROPAGATE(packet_set_addr(packet, NULL, NULL, 0));
    631         }
    632         header->version = IPV4;
    633         header->fragment_offset_high = 0;
    634         header->fragment_offset_low = 0;
    635         header->header_checksum = 0;
    636         if (source)
    637                 header->source_address = source->s_addr;
    638         header->destination_address = dest.s_addr;
    639 
    640         fibril_rwlock_write_lock(&ip_globals.lock);
    641         ip_globals.packet_counter++;
    642         header->identification = htons(ip_globals.packet_counter);
    643         fibril_rwlock_write_unlock(&ip_globals.lock);
    644 
    645         if (pq_next(packet)) {
    646                 last_header = (ip_header_ref) malloc(IP_HEADER_LENGTH(header));
    647                 if (!last_header)
    648                         return ENOMEM;
    649                 ip_create_last_header(last_header, header);
    650                 next = pq_next(packet);
    651                 while (pq_next(next)) {
    652                         middle_header = (ip_header_ref) packet_prefix(next,
    653                             IP_HEADER_LENGTH(last_header));
    654                         if (!middle_header) {
    655                                 free(last_header);
    656                                 return ENOMEM;
    657                         }
    658 
    659                         memcpy(middle_header, last_header,
    660                             IP_HEADER_LENGTH(last_header));
    661                         header->flags |= IPFLAG_MORE_FRAGMENTS;
    662                         middle_header->total_length =
    663                             htons(packet_get_data_length(next));
    664                         middle_header->fragment_offset_high =
    665                             IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
    666                         middle_header->fragment_offset_low =
    667                             IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
    668                         middle_header->header_checksum =
    669                             IP_HEADER_CHECKSUM(middle_header);
    670                         if (destination) {
    671                                 if (ERROR_OCCURRED(packet_set_addr(next, NULL,
    672                                     (uint8_t *) destination->value,
    673                                     CONVERT_SIZE(char, uint8_t,
    674                                     destination->length)))) {
    675                                         free(last_header);
    676                                         return ERROR_CODE;
    677                                 }
    678                         }
    679                         length += packet_get_data_length(next);
    680                         next = pq_next(next);
    681                 }
    682 
    683                 middle_header = (ip_header_ref) packet_prefix(next,
    684                     IP_HEADER_LENGTH(last_header));
    685                 if (!middle_header) {
    686                         free(last_header);
    687                         return ENOMEM;
    688                 }
    689 
    690                 memcpy(middle_header, last_header,
    691                     IP_HEADER_LENGTH(last_header));
    692                 middle_header->total_length =
    693                     htons(packet_get_data_length(next));
    694                 middle_header->fragment_offset_high =
    695                     IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
    696                 middle_header->fragment_offset_low =
    697                     IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
    698                 middle_header->header_checksum =
    699                     IP_HEADER_CHECKSUM(middle_header);
    700                 if (destination) {
    701                         if (ERROR_OCCURRED(packet_set_addr(next, NULL,
    702                             (uint8_t *) destination->value,
    703                             CONVERT_SIZE(char, uint8_t,
    704                             destination->length)))) {
    705                                 free(last_header);
    706                                 return ERROR_CODE;
    707                             }
    708                 }
    709                 length += packet_get_data_length(next);
    710                 free(last_header);
    711                 header->flags |= IPFLAG_MORE_FRAGMENTS;
    712         }
    713 
    714         header->total_length = htons(length);
    715         // unnecessary for all protocols
    716         header->header_checksum = IP_HEADER_CHECKSUM(header);
    717 
    718         return EOK;
    719 }
    720 
    721 /** Fragments the packet from the end.
    722  *
    723  * @param[in] packet    The packet to be fragmented.
    724  * @param[in,out] new_packet The new packet fragment.
    725  * @param[in,out] header The original packet header.
    726  * @param[in,out] new_header The new packet fragment header.
    727  * @param[in] length    The new fragment length.
    728  * @param[in] src       The source address.
    729  * @param[in] dest      The destiantion address.
    730  * @param[in] addrlen   The address length.
    731  * @returns             EOK on success.
    732  * @returns             ENOMEM if the target packet is too small.
    733  * @returns             Other error codes as defined for the packet_set_addr()
    734  *                      function.
    735  * @returns             Other error codes as defined for the pq_insert_after()
    736  *                      function.
    737  */
    738 static int
    739 ip_fragment_packet_data(packet_t packet, packet_t new_packet,
    740     ip_header_ref header, ip_header_ref new_header, size_t length,
    741     const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen)
    742 {
    743         ERROR_DECLARE;
    744 
    745         void *data;
    746         size_t offset;
    747 
    748         data = packet_suffix(new_packet, length);
    749         if (!data)
    750                 return ENOMEM;
    751 
    752         memcpy(data, ((void *) header) + IP_TOTAL_LENGTH(header) - length,
    753             length);
    754         ERROR_PROPAGATE(packet_trim(packet, 0, length));
    755         header->total_length = htons(IP_TOTAL_LENGTH(header) - length);
    756         new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
    757         offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);
    758         new_header->fragment_offset_high =
    759             IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset);
    760         new_header->fragment_offset_low =
    761             IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
    762         new_header->header_checksum = IP_HEADER_CHECKSUM(new_header);
    763         ERROR_PROPAGATE(packet_set_addr(new_packet, (const uint8_t *) src,
    764             (const uint8_t *) dest, addrlen));
    765 
    766         return pq_insert_after(packet, new_packet);
    767 }
    768 
    769 /** Checks the packet length and fragments it if needed.
    770  *
    771  * The new fragments are queued before the original packet.
    772  *
    773  * @param[in,out] packet The packet to be checked.
    774  * @param[in] length    The maximum packet length.
    775  * @param[in] prefix    The minimum prefix size.
    776  * @param[in] suffix    The minimum suffix size.
    777  * @param[in] addr_len  The minimum address length.
    778  * @returns             EOK on success.
    779  * @returns             EINVAL if the packet_get_addr() function fails.
    780  * @returns             EINVAL if the packet does not contain the IP header.
    781  * @returns             EPERM if the packet needs to be fragmented and the
    782  *                      fragmentation is not allowed.
    783  * @returns             ENOMEM if there is not enough memory left.
    784  * @returns             ENOMEM if there is no packet available.
    785  * @returns             ENOMEM if the packet is too small to contain the IP
    786  *                      header.
    787  * @returns             Other error codes as defined for the packet_trim()
    788  *                      function.
    789  * @returns             Other error codes as defined for the
    790  *                      ip_create_middle_header() function.
    791  * @returns             Other error codes as defined for the
    792  *                      ip_fragment_packet_data() function.
    793  */
    794 static int
    795 ip_fragment_packet(packet_t packet, size_t length, size_t prefix, size_t suffix,
    796     socklen_t addr_len)
    797 {
    798         ERROR_DECLARE;
    799 
    800         packet_t new_packet;
    801         ip_header_ref header;
    802         ip_header_ref middle_header;
    803         ip_header_ref last_header;
    804         struct sockaddr *src;
    805         struct sockaddr *dest;
    806         socklen_t addrlen;
    807         int result;
    808 
    809         result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
    810         if (result <= 0)
    811                 return EINVAL;
    812 
    813         addrlen = (socklen_t) result;
    814         if (packet_get_data_length(packet) <= sizeof(ip_header_t))
    815                 return ENOMEM;
    816 
    817         // get header
    818         header = (ip_header_ref) packet_get_data(packet);
    819         if (!header)
    820                 return EINVAL;
    821 
    822         // fragmentation forbidden?
    823         if(header->flags & IPFLAG_DONT_FRAGMENT)
    824                 return EPERM;
    825 
    826         // create the last fragment
    827         new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length,
    828             suffix, ((addrlen > addr_len) ? addrlen : addr_len));
    829         if (!new_packet)
    830                 return ENOMEM;
    831 
    832         // allocate as much as originally
    833         last_header = (ip_header_ref) packet_suffix(new_packet,
    834             IP_HEADER_LENGTH(header));
    835         if (!last_header)
    836                 return ip_release_and_return(packet, ENOMEM);
    837 
    838         ip_create_last_header(last_header, header);
    839 
    840         // trim the unused space
    841         if (ERROR_OCCURRED(packet_trim(new_packet, 0,
    842             IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header)))) {
    843                 return ip_release_and_return(packet, ERROR_CODE);
    844         }
    845 
    846         // biggest multiple of 8 lower than content
    847         // TODO even fragmentation?
    848         length = length & ~0x7;
    849         if (ERROR_OCCURRED(ip_fragment_packet_data(packet, new_packet, header,
    850             last_header,
    851             ((IP_HEADER_DATA_LENGTH(header) -
    852             ((length - IP_HEADER_LENGTH(header)) & ~0x7)) %
    853             ((length - IP_HEADER_LENGTH(last_header)) & ~0x7)), src, dest,
    854             addrlen))) {
    855                 return ip_release_and_return(packet, ERROR_CODE);
    856         }
    857 
    858         // mark the first as fragmented
    859         header->flags |= IPFLAG_MORE_FRAGMENTS;
    860 
    861         // create middle framgents
    862         while (IP_TOTAL_LENGTH(header) > length) {
    863                 new_packet = packet_get_4_remote(ip_globals.net_phone, prefix,
    864                     length, suffix,
    865                     ((addrlen >= addr_len) ? addrlen : addr_len));
    866                 if (!new_packet)
    867                         return ENOMEM;
    868 
    869                 middle_header = ip_create_middle_header(new_packet,
    870                     last_header);
    871                 if (!middle_header)
    872                         return ip_release_and_return(packet, ENOMEM);
    873 
    874                 if (ERROR_OCCURRED(ip_fragment_packet_data(packet, new_packet,
    875                     header, middle_header,
    876                     (length - IP_HEADER_LENGTH(middle_header)) & ~0x7, src,
    877                     dest, addrlen))) {
    878                         return ip_release_and_return(packet, ERROR_CODE);
    879                 }
    880         }
    881 
    882         // finish the first fragment
    883         header->header_checksum = IP_HEADER_CHECKSUM(header);
    884 
    885         return EOK;
    886 }
    887 
    888 /** Checks the packet queue lengths and fragments the packets if needed.
    889  *
    890  * The ICMP_FRAG_NEEDED error notification may be sent if the packet needs to
    891  * be fragmented and the fragmentation is not allowed.
    892  *
    893  * @param[in,out] packet The packet or the packet queue to be checked.
    894  * @param[in] prefix    The minimum prefix size.
    895  * @param[in] content   The maximum content size.
    896  * @param[in] suffix    The minimum suffix size.
    897  * @param[in] addr_len  The minimum address length.
    898  * @param[in] error     The error module service.
    899  * @returns             The packet or the packet queue of the allowed length.
    900  * @returns             NULL if there are no packets left.
    901  */
    902 static packet_t
    903 ip_split_packet(packet_t packet, size_t prefix, size_t content, size_t suffix,
    904     socklen_t addr_len, services_t error)
    905 {
    906         size_t length;
    907         packet_t next;
    908         packet_t new_packet;
    909         int result;
    910         int phone;
    911 
    912         next = packet;
    913         // check all packets
    914         while (next) {
    915                 length = packet_get_data_length(next);
    916                
    917                 if (length <= content) {
    918                         next = pq_next(next);
    919                         continue;
    920                 }
    921 
    922                 // too long
    923                 result = ip_fragment_packet(next, content, prefix,
    924                     suffix, addr_len);
    925                 if (result != EOK) {
    926                         new_packet = pq_detach(next);
    927                         if (next == packet) {
    928                                 // the new first packet of the queue
    929                                 packet = new_packet;
    930                         }
    931                         // fragmentation needed?
    932                         if (result == EPERM) {
    933                                 phone = ip_prepare_icmp_and_get_phone(
    934                                     error, next, NULL);
    935                                 if (phone >= 0) {
    936                                         // fragmentation necessary ICMP
    937                                         icmp_destination_unreachable_msg(phone,
    938                                             ICMP_FRAG_NEEDED, content, next);
    939                                 }
    940                         } else {
    941                                 pq_release_remote(ip_globals.net_phone,
    942                                     packet_get_id(next));
    943                         }
    944 
    945                         next = new_packet;
    946                         continue;
    947                 }
    948 
    949                 next = pq_next(next);
    950         }
    951 
    952         return packet;
    953 }
    954 
    955 /** Sends the packet or the packet queue via the specified route.
    956  *
    957  * The ICMP_HOST_UNREACH error notification may be sent if route hardware
    958  * destination address is found.
    959  *
    960  * @param[in,out] packet The packet to be sent.
    961  * @param[in] netif     The target network interface.
    962  * @param[in] route     The target route.
    963  * @param[in] src       The source address.
    964  * @param[in] dest      The destination address.
    965  * @param[in] error     The error module service.
    966  * @returns             EOK on success.
    967  * @returns             Other error codes as defined for the arp_translate_req()
    968  *                      function.
    969  * @returns             Other error codes as defined for the ip_prepare_packet()
    970  *                      function.
    971  */
    972 static int
    973 ip_send_route(packet_t packet, ip_netif_ref netif, ip_route_ref route,
    974     in_addr_t *src, in_addr_t dest, services_t error)
    975 {
    976         ERROR_DECLARE;
    977 
    978         measured_string_t destination;
    979         measured_string_ref translation;
    980         char *data;
    981         int phone;
    982 
    983         // get destination hardware address
    984         if (netif->arp && (route->address.s_addr != dest.s_addr)) {
    985                 destination.value = route->gateway.s_addr ?
    986                     (char *) &route->gateway.s_addr : (char *) &dest.s_addr;
    987                 destination.length = CONVERT_SIZE(dest.s_addr, char, 1);
    988 
    989                 if (ERROR_OCCURRED(arp_translate_req(netif->arp->phone,
    990                     netif->device_id, SERVICE_IP, &destination, &translation,
    991                     &data))) {
    992                         pq_release_remote(ip_globals.net_phone,
    993                             packet_get_id(packet));
    994                         return ERROR_CODE;
    995                 }
    996 
    997                 if (!translation || !translation->value) {
    998                         if (translation) {
    999                                 free(translation);
    1000                                 free(data);
    1001                         }
    1002                         phone = ip_prepare_icmp_and_get_phone(error, packet,
    1003                             NULL);
    1004                         if (phone >= 0) {
    1005                                 // unreachable ICMP if no routing
    1006                                 icmp_destination_unreachable_msg(phone,
    1007                                     ICMP_HOST_UNREACH, 0, packet);
    1008                         }
    1009                         return EINVAL;
    1010                 }
    1011 
    1012         } else {
    1013                 translation = NULL;
    1014         }
    1015 
    1016         if (ERROR_OCCURRED(ip_prepare_packet(src, dest, packet, translation))) {
    1017                 pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
    1018         } else {
    1019                 packet = ip_split_packet(packet, netif->packet_dimension.prefix,
    1020                     netif->packet_dimension.content,
    1021                     netif->packet_dimension.suffix,
    1022                     netif->packet_dimension.addr_len, error);
    1023                 if (packet) {
    1024                         nil_send_msg(netif->phone, netif->device_id, packet,
    1025                             SERVICE_IP);
    1026                 }
    1027         }
    1028 
    1029         if (translation) {
    1030                 free(translation);
    1031                 free(data);
    1032         }
    1033 
    1034         return ERROR_CODE;
    1035 }
    1036 
    1037 /** Searches the network interfaces if there is a suitable route.
    1038  *
    1039  * @param[in] netif     The network interface to be searched for routes. May be
    1040  *                      NULL.
    1041  * @param[in] destination The destination address.
    1042  * @returns             The found route.
    1043  * @returns             NULL if no route was found.
    1044  */
    1045 static ip_route_ref
    1046 ip_netif_find_route(ip_netif_ref netif, in_addr_t destination)
    1047 {
    1048         int index;
    1049         ip_route_ref route;
    1050 
    1051         if (!netif)
    1052                 return NULL;
    1053 
    1054         // start with the first one - the direct route
    1055         for (index = 0; index < ip_routes_count(&netif->routes); index++) {
    1056                 route = ip_routes_get_index(&netif->routes, index);
    1057                 if (route &&
    1058                     ((route->address.s_addr & route->netmask.s_addr) ==
    1059                     (destination.s_addr & route->netmask.s_addr))) {
    1060                         return route;
    1061                 }
    1062         }
    1063 
    1064         return NULL;
    1065 }
    1066 
    1067 /** Searches all network interfaces if there is a suitable route.
    1068  *
    1069  * @param[in] destination The destination address.
    1070  * @returns             The found route.
    1071  * @returns             NULL if no route was found.
    1072  */
    1073 static ip_route_ref ip_find_route(in_addr_t destination) {
    1074         int index;
    1075         ip_route_ref route;
    1076         ip_netif_ref netif;
    1077 
    1078         // start with the last netif - the newest one
    1079         index = ip_netifs_count(&ip_globals.netifs) - 1;
    1080         while (index >= 0) {
    1081                 netif = ip_netifs_get_index(&ip_globals.netifs, index);
    1082                 if (netif && (netif->state == NETIF_ACTIVE)) {
    1083                         route = ip_netif_find_route(netif, destination);
    1084                         if (route)
    1085                                 return route;
    1086                 }
    1087                 index--;
    1088         }
    1089 
    1090         return &ip_globals.gateway;
    1091 }
    1092 
    1093 /** Returns the network interface's IP address.
    1094  *
    1095  * @param[in] netif     The network interface.
    1096  * @returns             The IP address.
    1097  * @returns             NULL if no IP address was found.
    1098  */
    1099 static in_addr_t *ip_netif_address(ip_netif_ref netif)
    1100 {
    1101         ip_route_ref route;
    1102 
    1103         route = ip_routes_get_index(&netif->routes, 0);
    1104         return route ? &route->address : NULL;
    1105 }
    1106 
    1107 /** Registers the transport layer protocol.
    1108  *
    1109  * The traffic of this protocol will be supplied using either the receive
    1110  * function or IPC message.
    1111  *
    1112  * @param[in] protocol  The transport layer module protocol.
    1113  * @param[in] service   The transport layer module service.
    1114  * @param[in] phone     The transport layer module phone.
    1115  * @param[in] received_msg The receiving function.
    1116  * @returns             EOK on success.
    1117  * @returns             EINVAL if the protocol parameter and/or the service
    1118  *                      parameter is zero.
    1119  * @returns             EINVAL if the phone parameter is not a positive number
    1120  *                      and the tl_receive_msg is NULL.
    1121  * @returns             ENOMEM if there is not enough memory left.
    1122  */
    1123 static int
    1124 ip_register(int protocol, services_t service, int phone,
    1125     tl_received_msg_t received_msg)
    1126 {
    1127         ip_proto_ref proto;
    1128         int index;
    1129 
    1130         if (!protocol || !service || ((phone < 0) && !received_msg))
    1131                 return EINVAL;
    1132 
    1133         proto = (ip_proto_ref) malloc(sizeof(ip_protos_t));
    1134         if (!proto)
    1135                 return ENOMEM;
    1136 
    1137         proto->protocol = protocol;
    1138         proto->service = service;
    1139         proto->phone = phone;
    1140         proto->received_msg = received_msg;
    1141 
    1142         fibril_rwlock_write_lock(&ip_globals.protos_lock);
    1143         index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
    1144         if (index < 0) {
    1145                 fibril_rwlock_write_unlock(&ip_globals.protos_lock);
    1146                 free(proto);
    1147                 return index;
    1148         }
    1149         fibril_rwlock_write_unlock(&ip_globals.protos_lock);
    1150 
    1151         printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
    1152             NAME, proto->protocol, proto->phone);
    1153 
    1154         return EOK;
    1155 }
    1156 
    1157 static int
    1158 ip_device_req_local(int il_phone, device_id_t device_id, services_t netif)
    1159 {
     430int ip_device_req_local(int il_phone, device_id_t device_id, services_t netif){
    1160431        ERROR_DECLARE;
    1161432
     
    1165436
    1166437        ip_netif = (ip_netif_ref) malloc(sizeof(ip_netif_t));
    1167         if (!ip_netif)
     438        if(! ip_netif){
    1168439                return ENOMEM;
    1169 
    1170         if (ERROR_OCCURRED(ip_routes_initialize(&ip_netif->routes))) {
     440        }
     441        if(ERROR_OCCURRED(ip_routes_initialize(&ip_netif->routes))){
    1171442                free(ip_netif);
    1172443                return ERROR_CODE;
    1173444        }
    1174 
    1175445        ip_netif->device_id = device_id;
    1176446        ip_netif->service = netif;
    1177447        ip_netif->state = NETIF_STOPPED;
    1178 
    1179448        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    1180         if (ERROR_OCCURRED(ip_netif_initialize(ip_netif))) {
     449        if(ERROR_OCCURRED(ip_netif_initialize(ip_netif))){
    1181450                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1182451                ip_routes_destroy(&ip_netif->routes);
     
    1184453                return ERROR_CODE;
    1185454        }
    1186         if (ip_netif->arp)
    1187                 ip_netif->arp->usage++;
    1188 
     455        if(ip_netif->arp){
     456                ++ ip_netif->arp->usage;
     457        }
    1189458        // print the settings
    1190459        printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
     
    1198467        char gateway[INET_ADDRSTRLEN];
    1199468       
    1200         for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
     469        for (index = 0; index < ip_routes_count(&ip_netif->routes); ++ index){
    1201470                route = ip_routes_get_index(&ip_netif->routes, index);
    1202471                if (route) {
    1203                         inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr,
    1204                             address, INET_ADDRSTRLEN);
    1205                         inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr,
    1206                             netmask, INET_ADDRSTRLEN);
    1207                         inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr,
    1208                             gateway, INET_ADDRSTRLEN);
    1209                         printf("%s: Route %d (address: %s, netmask: %s, "
    1210                             "gateway: %s)\n", NAME, index, address, netmask,
    1211                             gateway);
     472                        inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr, address, INET_ADDRSTRLEN);
     473                        inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr, netmask, INET_ADDRSTRLEN);
     474                        inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr, gateway, INET_ADDRSTRLEN);
     475                        printf("%s: Route %d (address: %s, netmask: %s, gateway: %s)\n",
     476                            NAME, index, address, netmask, gateway);
    1212477                }
    1213478        }
    1214479       
    1215         inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
    1216             INET_ADDRSTRLEN);
     480        inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address, INET_ADDRSTRLEN);
     481        printf("%s: Broadcast (%s)\n", NAME, address);
     482       
    1217483        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1218 
    1219         printf("%s: Broadcast (%s)\n", NAME, address);
    1220 
    1221484        return EOK;
    1222485}
    1223486
    1224 static int
    1225 ip_send_msg_local(int il_phone, device_id_t device_id, packet_t packet,
    1226     services_t sender, services_t error)
    1227 {
     487int ip_netif_initialize(ip_netif_ref ip_netif){
     488        ERROR_DECLARE;
     489
     490        measured_string_t names[] = {{str_dup("IPV"), 3}, {str_dup("IP_CONFIG"), 9}, {str_dup("IP_ADDR"), 7}, {str_dup("IP_NETMASK"), 10}, {str_dup("IP_GATEWAY"), 10}, {str_dup("IP_BROADCAST"), 12}, {str_dup("ARP"), 3}, {str_dup("IP_ROUTING"), 10}};
     491        measured_string_ref configuration;
     492        size_t count = sizeof(names) / sizeof(measured_string_t);
     493        char * data;
     494        measured_string_t address;
     495        int index;
     496        ip_route_ref route;
     497        in_addr_t gateway;
     498
     499        ip_netif->arp = NULL;
     500        route = NULL;
     501        ip_netif->ipv = NET_DEFAULT_IPV;
     502        ip_netif->dhcp = false;
     503        ip_netif->routing = NET_DEFAULT_IP_ROUTING;
     504        configuration = &names[0];
     505        // get configuration
     506        ERROR_PROPAGATE(net_get_device_conf_req(ip_globals.net_phone, ip_netif->device_id, &configuration, count, &data));
     507        if(configuration){
     508                if(configuration[0].value){
     509                        ip_netif->ipv = strtol(configuration[0].value, NULL, 0);
     510                }
     511                ip_netif->dhcp = ! str_lcmp(configuration[1].value, "dhcp", configuration[1].length);
     512                if(ip_netif->dhcp){
     513                        // TODO dhcp
     514                        net_free_settings(configuration, data);
     515                        return ENOTSUP;
     516                }else if(ip_netif->ipv == IPV4){
     517                        route = (ip_route_ref) malloc(sizeof(ip_route_t));
     518                        if(! route){
     519                                net_free_settings(configuration, data);
     520                                return ENOMEM;
     521                        }
     522                        route->address.s_addr = 0;
     523                        route->netmask.s_addr = 0;
     524                        route->gateway.s_addr = 0;
     525                        route->netif = ip_netif;
     526                        index = ip_routes_add(&ip_netif->routes, route);
     527                        if(index < 0){
     528                                net_free_settings(configuration, data);
     529                                free(route);
     530                                return index;
     531                        }
     532                        if(ERROR_OCCURRED(inet_pton(AF_INET, configuration[2].value, (uint8_t *) &route->address.s_addr))
     533                                || ERROR_OCCURRED(inet_pton(AF_INET, configuration[3].value, (uint8_t *) &route->netmask.s_addr))
     534                                || (inet_pton(AF_INET, configuration[4].value, (uint8_t *) &gateway.s_addr) == EINVAL)
     535                                || (inet_pton(AF_INET, configuration[5].value, (uint8_t *) &ip_netif->broadcast.s_addr) == EINVAL)){
     536                                net_free_settings(configuration, data);
     537                                return EINVAL;
     538                        }
     539                }else{
     540                        // TODO ipv6 in separate module
     541                        net_free_settings(configuration, data);
     542                        return ENOTSUP;
     543                }
     544                if(configuration[6].value){
     545                        ip_netif->arp = get_running_module(&ip_globals.modules, configuration[6].value);
     546                        if(! ip_netif->arp){
     547                                printf("Failed to start the arp %s\n", configuration[6].value);
     548                                net_free_settings(configuration, data);
     549                                return EINVAL;
     550                        }
     551                }
     552                if(configuration[7].value){
     553                        ip_netif->routing = (configuration[7].value[0] == 'y');
     554                }
     555                net_free_settings(configuration, data);
     556        }
     557        // binds the netif service which also initializes the device
     558        ip_netif->phone = nil_bind_service(ip_netif->service, (ipcarg_t) ip_netif->device_id, SERVICE_IP, ip_globals.client_connection);
     559        if(ip_netif->phone < 0){
     560                printf("Failed to contact the nil service %d\n", ip_netif->service);
     561                return ip_netif->phone;
     562        }
     563        // has to be after the device netif module initialization
     564        if(ip_netif->arp){
     565                if(route){
     566                        address.value = (char *) &route->address.s_addr;
     567                        address.length = CONVERT_SIZE(in_addr_t, char, 1);
     568                        ERROR_PROPAGATE(arp_device_req(ip_netif->arp->phone, ip_netif->device_id, SERVICE_IP, ip_netif->service, &address));
     569                }else{
     570                        ip_netif->arp = 0;
     571                }
     572        }
     573        // get packet dimensions
     574        ERROR_PROPAGATE(nil_packet_size_req(ip_netif->phone, ip_netif->device_id, &ip_netif->packet_dimension));
     575        if(ip_netif->packet_dimension.content < IP_MIN_CONTENT){
     576                printf("Maximum transmission unit %d bytes is too small, at least %d bytes are needed\n", ip_netif->packet_dimension.content, IP_MIN_CONTENT);
     577                ip_netif->packet_dimension.content = IP_MIN_CONTENT;
     578        }
     579        index = ip_netifs_add(&ip_globals.netifs, ip_netif->device_id, ip_netif);
     580        if(index < 0){
     581                return index;
     582        }
     583        if(gateway.s_addr){
     584                // the default gateway
     585                ip_globals.gateway.address.s_addr = 0;
     586                ip_globals.gateway.netmask.s_addr = 0;
     587                ip_globals.gateway.gateway.s_addr = gateway.s_addr;
     588                ip_globals.gateway.netif = ip_netif;
     589        }
     590        return EOK;
     591}
     592
     593int ip_mtu_changed_message(device_id_t device_id, size_t mtu){
     594        ip_netif_ref netif;
     595
     596        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     597        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     598        if(! netif){
     599                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     600                return ENOENT;
     601        }
     602        netif->packet_dimension.content = mtu;
     603        printf("%s: Device %d changed MTU to %d\n", NAME, device_id, mtu);
     604        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     605        return EOK;
     606}
     607
     608int ip_device_state_message(device_id_t device_id, device_state_t state){
     609        ip_netif_ref netif;
     610
     611        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     612        // find the device
     613        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     614        if(! netif){
     615                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     616                return ENOENT;
     617        }
     618        netif->state = state;
     619        printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
     620        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     621        return EOK;
     622}
     623
     624int ip_register(int protocol, services_t service, int phone, tl_received_msg_t received_msg){
     625        ip_proto_ref proto;
     626        int index;
     627
     628        if(!(protocol && service && ((phone > 0) || (received_msg)))){
     629                return EINVAL;
     630        }
     631        proto = (ip_proto_ref) malloc(sizeof(ip_protos_t));
     632        if(! proto){
     633                return ENOMEM;
     634        }
     635        proto->protocol = protocol;
     636        proto->service = service;
     637        proto->phone = phone;
     638        proto->received_msg = received_msg;
     639        fibril_rwlock_write_lock(&ip_globals.protos_lock);
     640        index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
     641        if(index < 0){
     642                fibril_rwlock_write_unlock(&ip_globals.protos_lock);
     643                free(proto);
     644                return index;
     645        }
     646       
     647        printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
     648            NAME, proto->protocol, proto->phone);
     649       
     650        fibril_rwlock_write_unlock(&ip_globals.protos_lock);
     651        return EOK;
     652}
     653
     654int ip_send_msg_local(int il_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error){
    1228655        ERROR_DECLARE;
    1229656
     
    1231658        ip_netif_ref netif;
    1232659        ip_route_ref route;
    1233         struct sockaddr *addr;
    1234         struct sockaddr_in *address_in;
    1235         in_addr_t *dest;
    1236         in_addr_t *src;
     660        struct sockaddr * addr;
     661        struct sockaddr_in * address_in;
     662//      struct sockaddr_in6 *   address_in6;
     663        in_addr_t * dest;
     664        in_addr_t * src;
    1237665        int phone;
    1238666
     
    1240668        // should be the next hop address or the target destination address
    1241669        addrlen = packet_get_addr(packet, NULL, (uint8_t **) &addr);
    1242         if (addrlen < 0)
     670        if(addrlen < 0){
    1243671                return ip_release_and_return(packet, addrlen);
    1244         if ((size_t) addrlen < sizeof(struct sockaddr))
     672        }
     673        if((size_t) addrlen < sizeof(struct sockaddr)){
    1245674                return ip_release_and_return(packet, EINVAL);
    1246 
    1247         switch (addr->sa_family) {
    1248         case AF_INET:
    1249                 if (addrlen != sizeof(struct sockaddr_in))
    1250                         return ip_release_and_return(packet, EINVAL);
    1251                 address_in = (struct sockaddr_in *) addr;
    1252                 dest = &address_in->sin_addr;
    1253                 if (!dest->s_addr)
    1254                         dest->s_addr = IPV4_LOCALHOST_ADDRESS;
    1255                 break;
    1256         case AF_INET6:
    1257         default:
    1258                 return ip_release_and_return(packet, EAFNOSUPPORT);
    1259         }
    1260 
     675        }
     676        switch(addr->sa_family){
     677                case AF_INET:
     678                        if(addrlen != sizeof(struct sockaddr_in)){
     679                                return ip_release_and_return(packet, EINVAL);
     680                        }
     681                        address_in = (struct sockaddr_in *) addr;
     682                        dest = &address_in->sin_addr;
     683                        if(! dest->s_addr){
     684                                dest->s_addr = IPV4_LOCALHOST_ADDRESS;
     685                        }
     686                        break;
     687                // TODO IPv6
     688/*              case AF_INET6:
     689                        if(addrlen != sizeof(struct sockaddr_in6)){
     690                                return EINVAL;
     691                        }
     692                        address_in6 = (struct sockaddr_in6 *) dest;
     693                        address_in6.sin6_addr.s6_addr;
     694                        IPV6_LOCALHOST_ADDRESS;
     695*/              default:
     696                        return ip_release_and_return(packet, EAFNOSUPPORT);
     697        }
    1261698        netif = NULL;
    1262699        route = NULL;
    1263700        fibril_rwlock_read_lock(&ip_globals.netifs_lock);
    1264 
    1265701        // device specified?
    1266         if (device_id > 0) {
     702        if(device_id > 0){
    1267703                netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1268704                route = ip_netif_find_route(netif, * dest);
    1269                 if (netif && !route && (ip_globals.gateway.netif == netif))
     705                if(netif && (! route) && (ip_globals.gateway.netif == netif)){
    1270706                        route = &ip_globals.gateway;
    1271         }
    1272 
    1273         if (!route) {
     707                }
     708        }
     709        if(! route){
    1274710                route = ip_find_route(*dest);
    1275711                netif = route ? route->netif : NULL;
    1276712        }
    1277         if (!netif || !route) {
     713        if(!(netif && route)){
    1278714                fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1279715                phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
    1280                 if (phone >= 0) {
     716                if(phone >= 0){
    1281717                        // unreachable ICMP if no routing
    1282                         icmp_destination_unreachable_msg(phone,
    1283                             ICMP_NET_UNREACH, 0, packet);
     718                        icmp_destination_unreachable_msg(phone, ICMP_NET_UNREACH, 0, packet);
    1284719                }
    1285720                return ENOENT;
    1286721        }
    1287 
    1288         if (error) {
    1289                 // do not send for broadcast, anycast packets or network
    1290                 // broadcast
    1291                 if (!dest->s_addr || !(~dest->s_addr) ||
    1292                     !(~((dest->s_addr & ~route->netmask.s_addr) |
    1293                     route->netmask.s_addr)) ||
    1294                     (!(dest->s_addr & ~route->netmask.s_addr))) {
     722        if(error){
     723                // do not send for broadcast, anycast packets or network broadcast
     724                if((! dest->s_addr)
     725                        || (!(~ dest->s_addr))
     726                        || (!(~((dest->s_addr &(~ route->netmask.s_addr)) | route->netmask.s_addr)))
     727                        || (!(dest->s_addr &(~ route->netmask.s_addr)))){
    1295728                        return ip_release_and_return(packet, EINVAL);
    1296729                }
    1297730        }
    1298 
    1299731        // if the local host is the destination
    1300         if ((route->address.s_addr == dest->s_addr) &&
    1301             (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
     732        if((route->address.s_addr == dest->s_addr)
     733                && (dest->s_addr != IPV4_LOCALHOST_ADDRESS)){
    1302734                // find the loopback device to deliver
    1303735                dest->s_addr = IPV4_LOCALHOST_ADDRESS;
    1304736                route = ip_find_route(*dest);
    1305737                netif = route ? route->netif : NULL;
    1306                 if (!netif || !route) {
     738                if(!(netif && route)){
    1307739                        fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1308                         phone = ip_prepare_icmp_and_get_phone(error, packet,
    1309                             NULL);
    1310                         if (phone >= 0) {
     740                        phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
     741                        if(phone >= 0){
    1311742                                // unreachable ICMP if no routing
    1312                                 icmp_destination_unreachable_msg(phone,
    1313                                     ICMP_HOST_UNREACH, 0, packet);
     743                                icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
    1314744                        }
    1315745                        return ENOENT;
    1316746                }
    1317747        }
    1318        
    1319748        src = ip_netif_address(netif);
    1320         if (!src) {
     749        if(! src){
    1321750                fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1322751                return ip_release_and_return(packet, ENOENT);
    1323752        }
    1324 
    1325         ERROR_CODE = ip_send_route(packet, netif, route, src, *dest, error);
     753        ERROR_CODE = ip_send_route(packet, netif, route, src, * dest, error);
    1326754        fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1327 
    1328755        return ERROR_CODE;
    1329756}
    1330757
    1331 /** Returns the device packet dimensions for sending.
    1332  *
    1333  * @param[in] phone     The service module phone.
    1334  * @param[in] message   The service specific message.
    1335  * @param[in] device_id The device identifier.
    1336  * @param[out] addr_len The minimum reserved address length.
    1337  * @param[out] prefix   The minimum reserved prefix size.
    1338  * @param[out] content  The maximum content size.
    1339  * @param[out] suffix   The minimum reserved suffix size.
    1340  * @returns             EOK on success.
    1341  */
    1342 static int
    1343 ip_packet_size_message(device_id_t device_id, size_t *addr_len, size_t *prefix,
    1344     size_t *content, size_t *suffix)
    1345 {
    1346         ip_netif_ref netif;
    1347         int index;
    1348 
    1349         if (!addr_len || !prefix || !content || !suffix)
    1350                 return EBADMEM;
    1351 
    1352         *content = IP_MAX_CONTENT - IP_PREFIX;
    1353         fibril_rwlock_read_lock(&ip_globals.netifs_lock);
    1354         if (device_id < 0) {
    1355                 *addr_len = IP_ADDR;
    1356                 *prefix = 0;
    1357                 *suffix = 0;
    1358 
    1359                 for (index = ip_netifs_count(&ip_globals.netifs) - 1;
    1360                     index >= 0; index--) {
    1361                         netif = ip_netifs_get_index(&ip_globals.netifs, index);
    1362                         if (!netif)
    1363                                 continue;
    1364                        
    1365                         if (netif->packet_dimension.addr_len > *addr_len)
    1366                                 *addr_len = netif->packet_dimension.addr_len;
    1367                        
    1368                         if (netif->packet_dimension.prefix > *prefix)
    1369                                 *prefix = netif->packet_dimension.prefix;
    1370                                
    1371                         if (netif->packet_dimension.suffix > *suffix)
    1372                                 *suffix = netif->packet_dimension.suffix;
    1373                 }
    1374 
    1375                 *prefix = *prefix + IP_PREFIX;
    1376                 *suffix = *suffix + IP_SUFFIX;
    1377         } else {
    1378                 netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1379                 if (!netif) {
    1380                         fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1381                         return ENOENT;
    1382                 }
    1383 
    1384                 *addr_len = (netif->packet_dimension.addr_len > IP_ADDR) ?
    1385                     netif->packet_dimension.addr_len : IP_ADDR;
    1386                 *prefix = netif->packet_dimension.prefix + IP_PREFIX;
    1387                 *suffix = netif->packet_dimension.suffix + IP_SUFFIX;
    1388         }
    1389         fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1390 
     758in_addr_t * ip_netif_address(ip_netif_ref netif){
     759        ip_route_ref route;
     760
     761        route = ip_routes_get_index(&netif->routes, 0);
     762        return route ? &route->address : NULL;
     763}
     764
     765int ip_send_route(packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest, services_t error){
     766        ERROR_DECLARE;
     767
     768        measured_string_t destination;
     769        measured_string_ref translation;
     770        char * data;
     771        int phone;
     772
     773        // get destination hardware address
     774        if(netif->arp && (route->address.s_addr != dest.s_addr)){
     775                destination.value = route->gateway.s_addr ? (char *) &route->gateway.s_addr : (char *) &dest.s_addr;
     776                destination.length = CONVERT_SIZE(dest.s_addr, char, 1);
     777                if(ERROR_OCCURRED(arp_translate_req(netif->arp->phone, netif->device_id, SERVICE_IP, &destination, &translation, &data))){
     778//                      sleep(1);
     779//                      ERROR_PROPAGATE(arp_translate_req(netif->arp->phone, netif->device_id, SERVICE_IP, &destination, &translation, &data));
     780                        pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
     781                        return ERROR_CODE;
     782                }
     783                if(!(translation && translation->value)){
     784                        if(translation){
     785                                free(translation);
     786                                free(data);
     787                        }
     788                        phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
     789                        if(phone >= 0){
     790                                // unreachable ICMP if no routing
     791                                icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
     792                        }
     793                        return EINVAL;
     794                }
     795        }else translation = NULL;
     796        if(ERROR_OCCURRED(ip_prepare_packet(src, dest, packet, translation))){
     797                pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
     798        }else{
     799                packet = ip_split_packet(packet, netif->packet_dimension.prefix, netif->packet_dimension.content, netif->packet_dimension.suffix, netif->packet_dimension.addr_len, error);
     800                if(packet){
     801                        nil_send_msg(netif->phone, netif->device_id, packet, SERVICE_IP);
     802                }
     803        }
     804        if(translation){
     805                free(translation);
     806                free(data);
     807        }
     808        return ERROR_CODE;
     809}
     810
     811int ip_prepare_packet(in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination){
     812        ERROR_DECLARE;
     813
     814        size_t length;
     815        ip_header_ref header;
     816        ip_header_ref last_header;
     817        ip_header_ref middle_header;
     818        packet_t next;
     819
     820        length = packet_get_data_length(packet);
     821        if((length < sizeof(ip_header_t)) || (length > IP_MAX_CONTENT)){
     822                return EINVAL;
     823        }
     824        header = (ip_header_ref) packet_get_data(packet);
     825        if(destination){
     826                ERROR_PROPAGATE(packet_set_addr(packet, NULL, (uint8_t *) destination->value, CONVERT_SIZE(char, uint8_t, destination->length)));
     827        }else{
     828                ERROR_PROPAGATE(packet_set_addr(packet, NULL, NULL, 0));
     829        }
     830        header->version = IPV4;
     831        header->fragment_offset_high = 0;
     832        header->fragment_offset_low = 0;
     833        header->header_checksum = 0;
     834        if(source){
     835                header->source_address = source->s_addr;
     836        }
     837        header->destination_address = dest.s_addr;
     838        fibril_rwlock_write_lock(&ip_globals.lock);
     839        ++ ip_globals.packet_counter;
     840        header->identification = htons(ip_globals.packet_counter);
     841        fibril_rwlock_write_unlock(&ip_globals.lock);
     842//      length = packet_get_data_length(packet);
     843        if(pq_next(packet)){
     844                last_header = (ip_header_ref) malloc(IP_HEADER_LENGTH(header));
     845                if(! last_header){
     846                        return ENOMEM;
     847                }
     848                ip_create_last_header(last_header, header);
     849                next = pq_next(packet);
     850                while(pq_next(next)){
     851                        middle_header = (ip_header_ref) packet_prefix(next, IP_HEADER_LENGTH(last_header));
     852                        if(! middle_header){
     853                                return ENOMEM;
     854                        }
     855                        memcpy(middle_header, last_header, IP_HEADER_LENGTH(last_header));
     856                        header->flags |= IPFLAG_MORE_FRAGMENTS;
     857                        middle_header->total_length = htons(packet_get_data_length(next));
     858                        middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
     859                        middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
     860                        middle_header->header_checksum = IP_HEADER_CHECKSUM(middle_header);
     861                        if(destination){
     862                                ERROR_PROPAGATE(packet_set_addr(next, NULL, (uint8_t *) destination->value, CONVERT_SIZE(char, uint8_t, destination->length)));
     863                        }
     864                        length += packet_get_data_length(next);
     865                        next = pq_next(next);
     866                }
     867                middle_header = (ip_header_ref) packet_prefix(next, IP_HEADER_LENGTH(last_header));
     868                if(! middle_header){
     869                        return ENOMEM;
     870                }
     871                memcpy(middle_header, last_header, IP_HEADER_LENGTH(last_header));
     872                middle_header->total_length = htons(packet_get_data_length(next));
     873                middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
     874                middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
     875                middle_header->header_checksum = IP_HEADER_CHECKSUM(middle_header);
     876                if(destination){
     877                        ERROR_PROPAGATE(packet_set_addr(next, NULL, (uint8_t *) destination->value, CONVERT_SIZE(char, uint8_t, destination->length)));
     878                }
     879                length += packet_get_data_length(next);
     880                free(last_header);
     881                header->flags |= IPFLAG_MORE_FRAGMENTS;
     882        }
     883        header->total_length = htons(length);
     884        // unnecessary for all protocols
     885        header->header_checksum = IP_HEADER_CHECKSUM(header);
    1391886        return EOK;
    1392887}
    1393888
    1394 /** Returns the packet destination address from the IP header.
    1395  *
    1396  * @param[in] header    The packet IP header to be read.
    1397  * @returns             The packet destination address.
    1398  */
    1399 static in_addr_t ip_get_destination(ip_header_ref header)
    1400 {
    1401         in_addr_t destination;
    1402 
    1403         // TODO search set ipopt route?
    1404         destination.s_addr = header->destination_address;
    1405         return destination;
    1406 }
    1407 
    1408 /** Delivers the packet to the local host.
    1409  *
    1410  * The packet is either passed to another module or released on error.
    1411  * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not
    1412  * found.
    1413  *
    1414  * @param[in] device_id The source device identifier.
    1415  * @param[in] packet    The packet to be delivered.
    1416  * @param[in] header    The first packet IP header. May be NULL.
    1417  * @param[in] error     The packet error service.
    1418  * @returns             EOK on success.
    1419  * @returns             ENOTSUP if the packet is a fragment.
    1420  * @returns             EAFNOSUPPORT if the address family is not supported.
    1421  * @returns             ENOENT if the target protocol is not found.
    1422  * @returns             Other error codes as defined for the packet_set_addr()
    1423  *                      function.
    1424  * @returns             Other error codes as defined for the packet_trim()
    1425  *                      function.
    1426  * @returns             Other error codes as defined for the protocol specific
    1427  *                      tl_received_msg() function.
    1428  */
    1429 static int
    1430 ip_deliver_local(device_id_t device_id, packet_t packet, ip_header_ref header,
    1431     services_t error)
    1432 {
    1433         ERROR_DECLARE;
    1434 
    1435         ip_proto_ref proto;
    1436         int phone;
    1437         services_t service;
    1438         tl_received_msg_t received_msg;
    1439         struct sockaddr *src;
    1440         struct sockaddr *dest;
    1441         struct sockaddr_in src_in;
    1442         struct sockaddr_in dest_in;
    1443         socklen_t addrlen;
    1444 
    1445         if ((header->flags & IPFLAG_MORE_FRAGMENTS) ||
    1446             IP_FRAGMENT_OFFSET(header)) {
    1447                 // TODO fragmented
    1448                 return ENOTSUP;
    1449         }
    1450        
    1451         switch (header->version) {
    1452         case IPVERSION:
    1453                 addrlen = sizeof(src_in);
    1454                 bzero(&src_in, addrlen);
    1455                 src_in.sin_family = AF_INET;
    1456                 memcpy(&dest_in, &src_in, addrlen);
    1457                 memcpy(&src_in.sin_addr.s_addr, &header->source_address,
    1458                     sizeof(header->source_address));
    1459                 memcpy(&dest_in.sin_addr.s_addr, &header->destination_address,
    1460                     sizeof(header->destination_address));
    1461                 src = (struct sockaddr *) &src_in;
    1462                 dest = (struct sockaddr *) &dest_in;
    1463                 break;
    1464 
    1465         default:
    1466                 return ip_release_and_return(packet, EAFNOSUPPORT);
    1467         }
    1468 
    1469         if (ERROR_OCCURRED(packet_set_addr(packet, (uint8_t *) src,
    1470             (uint8_t *) dest, addrlen))) {
    1471                 return ip_release_and_return(packet, ERROR_CODE);
    1472         }
    1473 
    1474         // trim padding if present
    1475         if (!error &&
    1476             (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
    1477                 if (ERROR_OCCURRED(packet_trim(packet, 0,
    1478                     packet_get_data_length(packet) - IP_TOTAL_LENGTH(header))))
    1479                         return ip_release_and_return(packet, ERROR_CODE);
    1480         }
    1481 
    1482         fibril_rwlock_read_lock(&ip_globals.protos_lock);
    1483 
    1484         proto = ip_protos_find(&ip_globals.protos, header->protocol);
    1485         if (!proto) {
    1486                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1487                 phone = ip_prepare_icmp_and_get_phone(error, packet, header);
    1488                 if (phone >= 0) {
    1489                         // unreachable ICMP
    1490                         icmp_destination_unreachable_msg(phone,
    1491                             ICMP_PROT_UNREACH, 0, packet);
    1492                 }
    1493                 return ENOENT;
    1494         }
    1495 
    1496         if (proto->received_msg) {
    1497                 service = proto->service;
    1498                 received_msg = proto->received_msg;
    1499                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1500                 ERROR_CODE = received_msg(device_id, packet, service, error);
    1501         } else {
    1502                 ERROR_CODE = tl_received_msg(proto->phone, device_id, packet,
    1503                     proto->service, error);
    1504                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1505         }
    1506 
    1507         return ERROR_CODE;
    1508 }
    1509 
    1510 /** Processes the received packet.
    1511  *
    1512  * The packet is either passed to another module or released on error.
    1513  *
    1514  * The ICMP_PARAM_POINTER error notification may be sent if the checksum is
    1515  * invalid.
    1516  * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two.
    1517  * The ICMP_HOST_UNREACH error notification may be sent if no route was found.
    1518  * The ICMP_HOST_UNREACH error notification may be sent if the packet is for
    1519  * another host and the routing is disabled.
    1520  *
    1521  * @param[in] device_id The source device identifier.
    1522  * @param[in] packet    The received packet to be processed.
    1523  * @returns             EOK on success.
    1524  * @returns             EINVAL if the TTL is less than two.
    1525  * @returns             EINVAL if the checksum is invalid.
    1526  * @returns             EAFNOSUPPORT if the address family is not supported.
    1527  * @returns             ENOENT if no route was found.
    1528  * @returns             ENOENT if the packet is for another host and the routing
    1529  *                      is disabled.
    1530  */
    1531 static int
    1532 ip_process_packet(device_id_t device_id, packet_t packet)
    1533 {
    1534         ERROR_DECLARE;
    1535 
    1536         ip_header_ref header;
    1537         in_addr_t dest;
    1538         ip_route_ref route;
    1539         int phone;
    1540         struct sockaddr *addr;
    1541         struct sockaddr_in addr_in;
    1542         socklen_t addrlen;
    1543 
    1544         header = (ip_header_ref) packet_get_data(packet);
    1545         if (!header)
    1546                 return ip_release_and_return(packet, ENOMEM);
    1547 
    1548         // checksum
    1549         if ((header->header_checksum) &&
    1550             (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
    1551                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1552                 if (phone >= 0) {
    1553                         // checksum error ICMP
    1554                         icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER,
    1555                             ((size_t) ((void *) &header->header_checksum)) -
    1556                             ((size_t) ((void *) header)), packet);
    1557                 }
    1558                 return EINVAL;
    1559         }
    1560 
    1561         if (header->ttl <= 1) {
    1562                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1563                 if (phone >= 0) {
    1564                         // ttl exceeded ICMP
    1565                         icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
    1566                 }
    1567                 return EINVAL;
    1568         }
    1569 
    1570         // process ipopt and get destination
    1571         dest = ip_get_destination(header);
    1572 
    1573         // set the addrination address
    1574         switch (header->version) {
    1575         case IPVERSION:
    1576                 addrlen = sizeof(addr_in);
    1577                 bzero(&addr_in, addrlen);
    1578                 addr_in.sin_family = AF_INET;
    1579                 memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
    1580                 addr = (struct sockaddr *) &addr_in;
    1581                 break;
    1582 
    1583         default:
    1584                 return ip_release_and_return(packet, EAFNOSUPPORT);
    1585         }
    1586 
    1587         ERROR_PROPAGATE(packet_set_addr(packet, NULL, (uint8_t *) &addr,
    1588             addrlen));
    1589 
    1590         route = ip_find_route(dest);
    1591         if (!route) {
    1592                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1593                 if (phone >= 0) {
    1594                         // unreachable ICMP
    1595                         icmp_destination_unreachable_msg(phone,
    1596                             ICMP_HOST_UNREACH, 0, packet);
    1597                 }
    1598                 return ENOENT;
    1599         }
    1600 
    1601         if (route->address.s_addr == dest.s_addr) {
    1602                 // local delivery
    1603                 return ip_deliver_local(device_id, packet, header, 0);
    1604         }
    1605 
    1606         if (route->netif->routing) {
    1607                 header->ttl--;
    1608                 return ip_send_route(packet, route->netif, route, NULL, dest,
    1609                     0);
    1610         }
    1611 
    1612         phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1613         if (phone >= 0) {
    1614                 // unreachable ICMP if no routing
    1615                 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0,
    1616                     packet);
    1617         }
    1618        
    1619         return ENOENT;
    1620 }
    1621 
    1622 static int
    1623 ip_add_route_req_local(int ip_phone, device_id_t device_id, in_addr_t address,
    1624     in_addr_t netmask, in_addr_t gateway)
    1625 {
    1626         ip_route_ref route;
    1627         ip_netif_ref netif;
    1628         int index;
    1629 
    1630         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    1631 
    1632         netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1633         if (!netif) {
    1634                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1635                 return ENOENT;
    1636         }
    1637 
    1638         route = (ip_route_ref) malloc(sizeof(ip_route_t));
    1639         if (!route) {
    1640                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1641                 return ENOMEM;
    1642         }
    1643 
    1644         route->address.s_addr = address.s_addr;
    1645         route->netmask.s_addr = netmask.s_addr;
    1646         route->gateway.s_addr = gateway.s_addr;
    1647         route->netif = netif;
    1648         index = ip_routes_add(&netif->routes, route);
    1649         if (index < 0)
    1650                 free(route);
    1651 
    1652         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1653        
    1654         return index;
    1655 }
    1656 
    1657 static int
    1658 ip_set_gateway_req_local(int ip_phone, device_id_t device_id, in_addr_t gateway)
    1659 {
    1660         ip_netif_ref netif;
    1661 
    1662         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    1663 
    1664         netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1665         if (!netif) {
    1666                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1667                 return ENOENT;
    1668         }
    1669 
    1670         ip_globals.gateway.address.s_addr = 0;
    1671         ip_globals.gateway.netmask.s_addr = 0;
    1672         ip_globals.gateway.gateway.s_addr = gateway.s_addr;
    1673         ip_globals.gateway.netif = netif;
    1674        
    1675         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1676        
    1677         return EOK;
    1678 }
    1679 
    1680 /** Notify the IP module about the received error notification packet.
    1681  *
    1682  * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
    1683  * @param[in] device_id The device identifier.
    1684  * @param[in] packet    The received packet or the received packet queue.
    1685  * @param[in] target    The target internetwork module service to be
    1686  *                      delivered to.
    1687  * @param[in] error     The packet error reporting service. Prefixes the
    1688  *                      received packet.
    1689  * @return              EOK on success.
    1690  *
    1691  */
    1692 static int
    1693 ip_received_error_msg_local(int ip_phone, device_id_t device_id,
    1694     packet_t packet, services_t target, services_t error)
    1695 {
    1696         uint8_t *data;
    1697         int offset;
    1698         icmp_type_t type;
    1699         icmp_code_t code;
    1700         ip_netif_ref netif;
    1701         measured_string_t address;
    1702         ip_route_ref route;
    1703         ip_header_ref header;
    1704 
    1705         switch (error) {
    1706         case SERVICE_ICMP:
    1707                 offset = icmp_client_process_packet(packet, &type, &code, NULL,
    1708                     NULL);
    1709                 if (offset < 0)
    1710                         return ip_release_and_return(packet, ENOMEM);
    1711 
    1712                 data = packet_get_data(packet);
    1713                 header = (ip_header_ref)(data + offset);
    1714 
    1715                 // destination host unreachable?
    1716                 if ((type != ICMP_DEST_UNREACH) ||
    1717                     (code != ICMP_HOST_UNREACH)) {
    1718                         // no, something else
    1719                         break;
    1720                 }
    1721 
    1722                 fibril_rwlock_read_lock(&ip_globals.netifs_lock);
    1723 
    1724                 netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1725                 if (!netif || !netif->arp) {
    1726                         fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1727                         break;
    1728                 }
    1729 
    1730                 route = ip_routes_get_index(&netif->routes, 0);
    1731 
    1732                 // from the same network?
    1733                 if (route && ((route->address.s_addr & route->netmask.s_addr) ==
    1734                     (header->destination_address & route->netmask.s_addr))) {
    1735                         // clear the ARP mapping if any
    1736                         address.value = (char *) &header->destination_address;
    1737                         address.length = CONVERT_SIZE(uint8_t, char,
    1738                             sizeof(header->destination_address));
    1739                         arp_clear_address_req(netif->arp->phone,
    1740                             netif->device_id, SERVICE_IP, &address);
    1741                 }
    1742 
    1743                 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1744                 break;
    1745 
    1746         default:
    1747                 return ip_release_and_return(packet, ENOTSUP);
    1748         }
    1749 
    1750         return ip_deliver_local(device_id, packet, header, error);
    1751 }
    1752 
    1753 static int
    1754 ip_get_route_req_local(int ip_phone, ip_protocol_t protocol,
    1755     const struct sockaddr *destination, socklen_t addrlen,
    1756     device_id_t *device_id, void **header, size_t *headerlen)
    1757 {
    1758         struct sockaddr_in *address_in;
    1759         in_addr_t *dest;
    1760         in_addr_t *src;
    1761         ip_route_ref route;
    1762         ipv4_pseudo_header_ref header_in;
    1763 
    1764         if (!destination || (addrlen <= 0))
    1765                 return EINVAL;
    1766 
    1767         if (!device_id || !header || !headerlen)
    1768                 return EBADMEM;
    1769 
    1770         if ((size_t) addrlen < sizeof(struct sockaddr))
    1771                 return EINVAL;
    1772 
    1773         switch (destination->sa_family) {
    1774         case AF_INET:
    1775                 if (addrlen != sizeof(struct sockaddr_in))
    1776                         return EINVAL;
    1777                 address_in = (struct sockaddr_in *) destination;
    1778                 dest = &address_in->sin_addr;
    1779                 if (!dest->s_addr)
    1780                         dest->s_addr = IPV4_LOCALHOST_ADDRESS;
    1781                 break;
    1782 
    1783         case AF_INET6:
    1784         default:
    1785                 return EAFNOSUPPORT;
    1786         }
    1787 
    1788         fibril_rwlock_read_lock(&ip_globals.lock);
    1789         route = ip_find_route(*dest);
    1790         // if the local host is the destination
    1791         if (route && (route->address.s_addr == dest->s_addr) &&
    1792             (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
    1793                 // find the loopback device to deliver
    1794                 dest->s_addr = IPV4_LOCALHOST_ADDRESS;
    1795                 route = ip_find_route(*dest);
    1796         }
    1797 
    1798         if (!route || !route->netif) {
    1799                 fibril_rwlock_read_unlock(&ip_globals.lock);
    1800                 return ENOENT;
    1801         }
    1802 
    1803         *device_id = route->netif->device_id;
    1804         src = ip_netif_address(route->netif);
    1805         fibril_rwlock_read_unlock(&ip_globals.lock);
    1806 
    1807         *headerlen = sizeof(*header_in);
    1808         header_in = (ipv4_pseudo_header_ref) malloc(*headerlen);
    1809         if (!header_in)
    1810                 return ENOMEM;
    1811 
    1812         bzero(header_in, *headerlen);
    1813         header_in->destination_address = dest->s_addr;
    1814         header_in->source_address = src->s_addr;
    1815         header_in->protocol = protocol;
    1816         header_in->data_length = 0;
    1817         *header = header_in;
    1818 
    1819         return EOK;
    1820 }
    1821 
    1822 /** Processes the received IP packet or the packet queue one by one.
    1823  *
    1824  * The packet is either passed to another module or released on error.
    1825  *
    1826  * @param[in] device_id The source device identifier.
    1827  * @param[in,out] packet The received packet.
    1828  * @returns             EOK on success and the packet is no longer needed.
    1829  * @returns             EINVAL if the packet is too small to carry the IP
    1830  *                      packet.
    1831  * @returns             EINVAL if the received address lengths differs from the
    1832  *                      registered values.
    1833  * @returns             ENOENT if the device is not found in the cache.
    1834  * @returns             ENOENT if the protocol for the device is not found in
    1835  *                      the cache.
    1836  * @returns             ENOMEM if there is not enough memory left.
    1837  */
    1838 static int ip_receive_message(device_id_t device_id, packet_t packet)
    1839 {
    1840         packet_t next;
    1841 
    1842         do {
    1843                 next = pq_detach(packet);
    1844                 ip_process_packet(device_id, packet);
    1845                 packet = next;
    1846         } while (packet);
    1847 
    1848         return EOK;
    1849 }
    1850 
    1851 /** Processes the IP message.
    1852  *
    1853  * @param[in] callid    The message identifier.
    1854  * @param[in] call      The message parameters.
    1855  * @param[out] answer   The message answer parameters.
    1856  * @param[out] answer_count The last parameter for the actual answer in the
    1857  *                      answer parameter.
    1858  * @returns             EOK on success.
    1859  * @returns             ENOTSUP if the message is not known.
    1860  *
    1861  * @see ip_interface.h
    1862  * @see il_interface.h
    1863  * @see IS_NET_IP_MESSAGE()
    1864  */
    1865 int
    1866 ip_message_standalone(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
    1867     int *answer_count)
     889int ip_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     890    ipc_call_t *answer, int * answer_count)
    1868891{
    1869892        ERROR_DECLARE;
     
    1881904        *answer_count = 0;
    1882905        switch (IPC_GET_METHOD(*call)) {
    1883         case IPC_M_PHONE_HUNGUP:
    1884                 return EOK;
    1885        
    1886         case IPC_M_CONNECT_TO_ME:
    1887                 return ip_register(IL_GET_PROTO(call), IL_GET_SERVICE(call),
    1888                     IPC_GET_PHONE(call), NULL);
    1889        
    1890         case NET_IL_DEVICE:
    1891                 return ip_device_req_local(0, IPC_GET_DEVICE(call),
    1892                     IPC_GET_SERVICE(call));
    1893        
    1894         case NET_IL_SEND:
    1895                 ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone,
    1896                     &packet, IPC_GET_PACKET(call)));
    1897                 return ip_send_msg_local(0, IPC_GET_DEVICE(call), packet, 0,
    1898                     IPC_GET_ERROR(call));
    1899        
    1900         case NET_IL_DEVICE_STATE:
    1901                 return ip_device_state_message(IPC_GET_DEVICE(call),
    1902                     IPC_GET_STATE(call));
    1903        
    1904         case NET_IL_RECEIVED:
    1905                 ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone,
    1906                     &packet, IPC_GET_PACKET(call)));
    1907                 return ip_receive_message(IPC_GET_DEVICE(call), packet);
    1908        
    1909         case NET_IP_RECEIVED_ERROR:
    1910                 ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone,
    1911                     &packet, IPC_GET_PACKET(call)));
    1912                 return ip_received_error_msg_local(0, IPC_GET_DEVICE(call),
    1913                     packet, IPC_GET_TARGET(call), IPC_GET_ERROR(call));
    1914        
    1915         case NET_IP_ADD_ROUTE:
    1916                 return ip_add_route_req_local(0, IPC_GET_DEVICE(call),
    1917                     IP_GET_ADDRESS(call), IP_GET_NETMASK(call),
    1918                     IP_GET_GATEWAY(call));
    1919 
    1920         case NET_IP_SET_GATEWAY:
    1921                 return ip_set_gateway_req_local(0, IPC_GET_DEVICE(call),
    1922                     IP_GET_GATEWAY(call));
    1923 
    1924         case NET_IP_GET_ROUTE:
    1925                 ERROR_PROPAGATE(data_receive((void **) &addr, &addrlen));
    1926                 ERROR_PROPAGATE(ip_get_route_req_local(0, IP_GET_PROTOCOL(call),
    1927                     addr, (socklen_t) addrlen, &device_id, &header,
    1928                     &headerlen));
    1929                 IPC_SET_DEVICE(answer, device_id);
    1930                 IP_SET_HEADERLEN(answer, headerlen);
    1931                
    1932                 *answer_count = 2;
     906                case IPC_M_PHONE_HUNGUP:
     907                        return EOK;
     908                case NET_IL_DEVICE:
     909                        return ip_device_req_local(0, IPC_GET_DEVICE(call),
     910                            IPC_GET_SERVICE(call));
     911                case IPC_M_CONNECT_TO_ME:
     912                        return ip_register(IL_GET_PROTO(call), IL_GET_SERVICE(call),
     913                            IPC_GET_PHONE(call), NULL);
     914                case NET_IL_SEND:
     915                        ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, &packet,
     916                            IPC_GET_PACKET(call)));
     917                        return ip_send_msg_local(0, IPC_GET_DEVICE(call), packet, 0,
     918                            IPC_GET_ERROR(call));
     919                case NET_IL_DEVICE_STATE:
     920                        return ip_device_state_message(IPC_GET_DEVICE(call),
     921                            IPC_GET_STATE(call));
     922                case NET_IL_RECEIVED:
     923                        ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, &packet,
     924                            IPC_GET_PACKET(call)));
     925                        return ip_receive_message(IPC_GET_DEVICE(call), packet);
     926                case NET_IP_RECEIVED_ERROR:
     927                        ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, &packet,
     928                            IPC_GET_PACKET(call)));
     929                        return ip_received_error_msg_local(0, IPC_GET_DEVICE(call), packet,
     930                            IPC_GET_TARGET(call), IPC_GET_ERROR(call));
     931                case NET_IP_ADD_ROUTE:
     932                        return ip_add_route_req_local(0, IPC_GET_DEVICE(call),
     933                            IP_GET_ADDRESS(call), IP_GET_NETMASK(call), IP_GET_GATEWAY(call));
     934                case NET_IP_SET_GATEWAY:
     935                        return ip_set_gateway_req_local(0, IPC_GET_DEVICE(call),
     936                            IP_GET_GATEWAY(call));
     937                case NET_IP_GET_ROUTE:
     938                        ERROR_PROPAGATE(data_receive((void **) &addr, &addrlen));
     939                        ERROR_PROPAGATE(ip_get_route_req_local(0, IP_GET_PROTOCOL(call),
     940                            addr, (socklen_t) addrlen, &device_id, &header, &headerlen));
     941                        IPC_SET_DEVICE(answer, device_id);
     942                        IP_SET_HEADERLEN(answer, headerlen);
    1933943                       
    1934                 if (ERROR_NONE(data_reply(&headerlen, sizeof(headerlen))))
    1935                         ERROR_CODE = data_reply(header, headerlen);
     944                        *answer_count = 2;
    1936945                       
    1937                 free(header);
    1938                 return ERROR_CODE;
    1939        
    1940         case NET_IL_PACKET_SPACE:
    1941                 ERROR_PROPAGATE(ip_packet_size_message(IPC_GET_DEVICE(call),
    1942                     &addrlen, &prefix, &content, &suffix));
    1943                 IPC_SET_ADDR(answer, addrlen);
    1944                 IPC_SET_PREFIX(answer, prefix);
    1945                 IPC_SET_CONTENT(answer, content);
    1946                 IPC_SET_SUFFIX(answer, suffix);
    1947                 *answer_count = 4;
    1948                 return EOK;
    1949        
    1950         case NET_IL_MTU_CHANGED:
    1951                 return ip_mtu_changed_message(IPC_GET_DEVICE(call),
    1952                     IPC_GET_MTU(call));
     946                        if (!ERROR_OCCURRED(data_reply(&headerlen, sizeof(headerlen))))
     947                                ERROR_CODE = data_reply(header, headerlen);
     948                       
     949                        free(header);
     950                        return ERROR_CODE;
     951                case NET_IL_PACKET_SPACE:
     952                        ERROR_PROPAGATE(ip_packet_size_message(IPC_GET_DEVICE(call),
     953                            &addrlen, &prefix, &content, &suffix));
     954                        IPC_SET_ADDR(answer, addrlen);
     955                        IPC_SET_PREFIX(answer, prefix);
     956                        IPC_SET_CONTENT(answer, content);
     957                        IPC_SET_SUFFIX(answer, suffix);
     958                        *answer_count = 4;
     959                        return EOK;
     960                case NET_IL_MTU_CHANGED:
     961                        return ip_mtu_changed_message(IPC_GET_DEVICE(call),
     962                            IPC_GET_MTU(call));
    1953963        }
    1954964       
     
    1956966}
    1957967
     968int ip_packet_size_req_local(int ip_phone, device_id_t device_id,
     969    packet_dimension_ref packet_dimension)
     970{
     971        if (!packet_dimension)
     972                return EBADMEM;
     973       
     974        return ip_packet_size_message(device_id, &packet_dimension->addr_len,
     975            &packet_dimension->prefix, &packet_dimension->content,
     976            &packet_dimension->suffix);
     977}
     978
     979int ip_packet_size_message(device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix){
     980        ip_netif_ref netif;
     981        int index;
     982
     983        if(!(addr_len && prefix && content && suffix)){
     984                return EBADMEM;
     985        }
     986        *content = IP_MAX_CONTENT - IP_PREFIX;
     987        fibril_rwlock_read_lock(&ip_globals.netifs_lock);
     988        if(device_id < 0){
     989                *addr_len = IP_ADDR;
     990                *prefix = 0;
     991                *suffix = 0;
     992                for(index = ip_netifs_count(&ip_globals.netifs) - 1; index >= 0; -- index){
     993                        netif = ip_netifs_get_index(&ip_globals.netifs, index);
     994                        if(netif){
     995                                if(netif->packet_dimension.addr_len > * addr_len){
     996                                        *addr_len = netif->packet_dimension.addr_len;
     997                                }
     998                                if(netif->packet_dimension.prefix > * prefix){
     999                                        *prefix = netif->packet_dimension.prefix;
     1000                                }
     1001                                if(netif->packet_dimension.suffix > * suffix){
     1002                                        *suffix = netif->packet_dimension.suffix;
     1003                                }
     1004                        }
     1005                }
     1006                *prefix = * prefix + IP_PREFIX;
     1007                *suffix = * suffix + IP_SUFFIX;
     1008        }else{
     1009                netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1010                if(! netif){
     1011                        fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
     1012                        return ENOENT;
     1013                }
     1014                *addr_len = (netif->packet_dimension.addr_len > IP_ADDR) ? netif->packet_dimension.addr_len : IP_ADDR;
     1015                *prefix = netif->packet_dimension.prefix + IP_PREFIX;
     1016                *suffix = netif->packet_dimension.suffix + IP_SUFFIX;
     1017        }
     1018        fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
     1019        return EOK;
     1020}
     1021
     1022int ip_add_route_req_local(int ip_phone, device_id_t device_id, in_addr_t address, in_addr_t netmask, in_addr_t gateway){
     1023        ip_route_ref route;
     1024        ip_netif_ref netif;
     1025        int index;
     1026
     1027        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     1028        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1029        if(! netif){
     1030                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1031                return ENOENT;
     1032        }
     1033        route = (ip_route_ref) malloc(sizeof(ip_route_t));
     1034        if(! route){
     1035                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1036                return ENOMEM;
     1037        }
     1038        route->address.s_addr = address.s_addr;
     1039        route->netmask.s_addr = netmask.s_addr;
     1040        route->gateway.s_addr = gateway.s_addr;
     1041        route->netif = netif;
     1042        index = ip_routes_add(&netif->routes, route);
     1043        if(index < 0){
     1044                free(route);
     1045        }
     1046        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1047        return index;
     1048}
     1049
     1050ip_route_ref ip_find_route(in_addr_t destination){
     1051        int index;
     1052        ip_route_ref route;
     1053        ip_netif_ref netif;
     1054
     1055        // start with the last netif - the newest one
     1056        index = ip_netifs_count(&ip_globals.netifs) - 1;
     1057        while(index >= 0){
     1058                netif = ip_netifs_get_index(&ip_globals.netifs, index);
     1059                if(netif && (netif->state == NETIF_ACTIVE)){
     1060                        route = ip_netif_find_route(netif, destination);
     1061                        if(route){
     1062                                return route;
     1063                        }
     1064                }
     1065                -- index;
     1066        }
     1067        return &ip_globals.gateway;
     1068}
     1069
     1070ip_route_ref ip_netif_find_route(ip_netif_ref netif, in_addr_t destination){
     1071        int index;
     1072        ip_route_ref route;
     1073
     1074        if(netif){
     1075                // start with the first one - the direct route
     1076                for(index = 0; index < ip_routes_count(&netif->routes); ++ index){
     1077                        route = ip_routes_get_index(&netif->routes, index);
     1078                        if(route && ((route->address.s_addr &route->netmask.s_addr) == (destination.s_addr &route->netmask.s_addr))){
     1079                                return route;
     1080                        }
     1081                }
     1082        }
     1083        return NULL;
     1084}
     1085
     1086int ip_set_gateway_req_local(int ip_phone, device_id_t device_id, in_addr_t gateway)
     1087{
     1088        ip_netif_ref netif;
     1089
     1090        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     1091        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1092        if(! netif){
     1093                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1094                return ENOENT;
     1095        }
     1096        ip_globals.gateway.address.s_addr = 0;
     1097        ip_globals.gateway.netmask.s_addr = 0;
     1098        ip_globals.gateway.gateway.s_addr = gateway.s_addr;
     1099        ip_globals.gateway.netif = netif;
     1100        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1101        return EOK;
     1102}
     1103
     1104packet_t ip_split_packet(packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error){
     1105        size_t length;
     1106        packet_t next;
     1107        packet_t new_packet;
     1108        int result;
     1109        int phone;
     1110
     1111        next = packet;
     1112        // check all packets
     1113        while(next){
     1114                length = packet_get_data_length(next);
     1115                // too long?
     1116                if(length > content){
     1117                        result = ip_fragment_packet(next, content, prefix, suffix, addr_len);
     1118                        if(result != EOK){
     1119                                new_packet = pq_detach(next);
     1120                                if(next == packet){
     1121                                        // the new first packet of the queue
     1122                                        packet = new_packet;
     1123                                }
     1124                                // fragmentation needed?
     1125                                if(result == EPERM){
     1126                                        phone = ip_prepare_icmp_and_get_phone(error, next, NULL);
     1127                                        if(phone >= 0){
     1128                                                // fragmentation necessary ICMP
     1129                                                icmp_destination_unreachable_msg(phone, ICMP_FRAG_NEEDED, content, next);
     1130                                        }
     1131                                }else{
     1132                                        pq_release_remote(ip_globals.net_phone, packet_get_id(next));
     1133                                }
     1134                                next = new_packet;
     1135                                continue;
     1136                        }
     1137                }
     1138                next = pq_next(next);
     1139        }
     1140        return packet;
     1141}
     1142
     1143int ip_fragment_packet(packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len){
     1144        ERROR_DECLARE;
     1145
     1146        packet_t new_packet;
     1147        ip_header_ref header;
     1148        ip_header_ref middle_header;
     1149        ip_header_ref last_header;
     1150        struct sockaddr * src;
     1151        struct sockaddr * dest;
     1152        socklen_t addrlen;
     1153        int result;
     1154
     1155        result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
     1156        if(result <= 0){
     1157                return EINVAL;
     1158        }
     1159        addrlen = (socklen_t) result;
     1160        if(packet_get_data_length(packet) <= sizeof(ip_header_t)){
     1161                return ENOMEM;
     1162        }
     1163        // get header
     1164        header = (ip_header_ref) packet_get_data(packet);
     1165        if(! header){
     1166                return EINVAL;
     1167        }
     1168        // fragmentation forbidden?
     1169        if(header->flags &IPFLAG_DONT_FRAGMENT){
     1170                return EPERM;
     1171        }
     1172        // create the last fragment
     1173        new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length, suffix, ((addrlen > addr_len) ? addrlen : addr_len));
     1174        if(! new_packet){
     1175                return ENOMEM;
     1176        }
     1177        // allocate as much as originally
     1178        last_header = (ip_header_ref) packet_suffix(new_packet, IP_HEADER_LENGTH(header));
     1179        if(! last_header){
     1180                return ip_release_and_return(packet, ENOMEM);
     1181        }
     1182        ip_create_last_header(last_header, header);
     1183        // trim the unused space
     1184        if(ERROR_OCCURRED(packet_trim(new_packet, 0, IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header)))){
     1185                return ip_release_and_return(packet, ERROR_CODE);
     1186        }
     1187        // biggest multiple of 8 lower than content
     1188        // TODO even fragmentation?
     1189        length = length &(~ 0x7);// (content / 8) * 8
     1190        if(ERROR_OCCURRED(ip_fragment_packet_data(packet, new_packet, header, last_header, ((IP_HEADER_DATA_LENGTH(header) - ((length - IP_HEADER_LENGTH(header)) &(~ 0x7))) % ((length - IP_HEADER_LENGTH(last_header)) &(~ 0x7))), src, dest, addrlen))){
     1191                return ip_release_and_return(packet, ERROR_CODE);
     1192        }
     1193        // mark the first as fragmented
     1194        header->flags |= IPFLAG_MORE_FRAGMENTS;
     1195        // create middle framgents
     1196        while(IP_TOTAL_LENGTH(header) > length){
     1197                new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length, suffix, ((addrlen >= addr_len) ? addrlen : addr_len));
     1198                if(! new_packet){
     1199                        return ENOMEM;
     1200                }
     1201                middle_header = ip_create_middle_header(new_packet, last_header);
     1202                if(! middle_header){
     1203                        return ip_release_and_return(packet, ENOMEM);
     1204                }
     1205                if(ERROR_OCCURRED(ip_fragment_packet_data(packet, new_packet, header, middle_header, (length - IP_HEADER_LENGTH(middle_header)) &(~ 0x7), src, dest, addrlen))){
     1206                        return ip_release_and_return(packet, ERROR_CODE);
     1207                }
     1208        }
     1209        // finish the first fragment
     1210        header->header_checksum = IP_HEADER_CHECKSUM(header);
     1211        return EOK;
     1212}
     1213
     1214int ip_fragment_packet_data(packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, const struct sockaddr * src, const struct sockaddr * dest, socklen_t addrlen){
     1215        ERROR_DECLARE;
     1216
     1217        void * data;
     1218        size_t offset;
     1219
     1220        data = packet_suffix(new_packet, length);
     1221        if(! data){
     1222                return ENOMEM;
     1223        }
     1224        memcpy(data, ((void *) header) + IP_TOTAL_LENGTH(header) - length, length);
     1225        ERROR_PROPAGATE(packet_trim(packet, 0, length));
     1226        header->total_length = htons(IP_TOTAL_LENGTH(header) - length);
     1227        new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
     1228        offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);
     1229        new_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset);
     1230        new_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
     1231        new_header->header_checksum = IP_HEADER_CHECKSUM(new_header);
     1232        ERROR_PROPAGATE(packet_set_addr(new_packet, (const uint8_t *) src, (const uint8_t *) dest, addrlen));
     1233        return pq_insert_after(packet, new_packet);
     1234}
     1235
     1236ip_header_ref ip_create_middle_header(packet_t packet, ip_header_ref last){
     1237        ip_header_ref middle;
     1238
     1239        middle = (ip_header_ref) packet_suffix(packet, IP_HEADER_LENGTH(last));
     1240        if(! middle){
     1241                return NULL;
     1242        }
     1243        memcpy(middle, last, IP_HEADER_LENGTH(last));
     1244        middle->flags |= IPFLAG_MORE_FRAGMENTS;
     1245        return middle;
     1246}
     1247
     1248void ip_create_last_header(ip_header_ref last, ip_header_ref first){
     1249        ip_option_ref option;
     1250        size_t next;
     1251        size_t length;
     1252
     1253        // copy first itself
     1254        memcpy(last, first, sizeof(ip_header_t));
     1255        length = sizeof(ip_header_t);
     1256        next = sizeof(ip_header_t);
     1257        // process all ip options
     1258        while(next < first->header_length){
     1259                option = (ip_option_ref) (((uint8_t *) first) + next);
     1260                // skip end or noop
     1261                if((option->type == IPOPT_END) || (option->type == IPOPT_NOOP)){
     1262                        ++ next;
     1263                }else{
     1264                        // copy if said so or skip
     1265                        if(IPOPT_COPIED(option->type)){
     1266                                memcpy(((uint8_t *) last) + length, ((uint8_t *) first) + next, option->length);
     1267                                length += option->length;
     1268                        }
     1269                        // next option
     1270                        next += option->length;
     1271                }
     1272        }
     1273        // align 4 byte boundary
     1274        if(length % 4){
     1275                bzero(((uint8_t *) last) + length, 4 - (length % 4));
     1276                last->header_length = length / 4 + 1;
     1277        }else{
     1278                last->header_length = length / 4;
     1279        }
     1280        last->header_checksum = 0;
     1281}
     1282
     1283int ip_receive_message(device_id_t device_id, packet_t packet){
     1284        packet_t next;
     1285
     1286        do{
     1287                next = pq_detach(packet);
     1288                ip_process_packet(device_id, packet);
     1289                packet = next;
     1290        }while(packet);
     1291        return EOK;
     1292}
     1293
     1294int ip_process_packet(device_id_t device_id, packet_t packet){
     1295        ERROR_DECLARE;
     1296
     1297        ip_header_ref header;
     1298        in_addr_t dest;
     1299        ip_route_ref route;
     1300        int phone;
     1301        struct sockaddr * addr;
     1302        struct sockaddr_in addr_in;
     1303//      struct sockaddr_in      addr_in6;
     1304        socklen_t addrlen;
     1305
     1306        header = (ip_header_ref) packet_get_data(packet);
     1307        if(! header){
     1308                return ip_release_and_return(packet, ENOMEM);
     1309        }
     1310        // checksum
     1311        if((header->header_checksum) && (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)){
     1312                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1313                if(phone >= 0){
     1314                        // checksum error ICMP
     1315                        icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER, ((size_t) ((void *) &header->header_checksum)) - ((size_t) ((void *) header)), packet);
     1316                }
     1317                return EINVAL;
     1318        }
     1319        if(header->ttl <= 1){
     1320                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1321                if(phone >= 0){
     1322                        // ttl oxceeded ICMP
     1323                        icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
     1324                }
     1325                return EINVAL;
     1326        }
     1327        // process ipopt and get destination
     1328        dest = ip_get_destination(header);
     1329        // set the addrination address
     1330        switch(header->version){
     1331                case IPVERSION:
     1332                        addrlen = sizeof(addr_in);
     1333                        bzero(&addr_in, addrlen);
     1334                        addr_in.sin_family = AF_INET;
     1335                        memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
     1336                        addr = (struct sockaddr *) &addr_in;
     1337                        break;
     1338/*              case IPv6VERSION:
     1339                        addrlen = sizeof(dest_in6);
     1340                        bzero(&dest_in6, addrlen);
     1341                        dest_in6.sin6_family = AF_INET6;
     1342                        memcpy(&dest_in6.sin6_addr.s6_addr,);
     1343                        dest = (struct sockaddr *) &dest_in;
     1344                        break;
     1345*/              default:
     1346                        return ip_release_and_return(packet, EAFNOSUPPORT);
     1347        }
     1348        ERROR_PROPAGATE(packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen));
     1349        route = ip_find_route(dest);
     1350        if(! route){
     1351                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1352                if(phone >= 0){
     1353                        // unreachable ICMP
     1354                        icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
     1355                }
     1356                return ENOENT;
     1357        }
     1358        if(route->address.s_addr == dest.s_addr){
     1359                // local delivery
     1360                return ip_deliver_local(device_id, packet, header, 0);
     1361        }else{
     1362                // only if routing enabled
     1363                if(route->netif->routing){
     1364                        -- header->ttl;
     1365                        return ip_send_route(packet, route->netif, route, NULL, dest, 0);
     1366                }else{
     1367                        phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1368                        if(phone >= 0){
     1369                                // unreachable ICMP if no routing
     1370                                icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
     1371                        }
     1372                        return ENOENT;
     1373                }
     1374        }
     1375}
     1376
     1377/** Notify the IP module about the received error notification packet.
     1378 *
     1379 * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
     1380 * @param[in] device_id The device identifier.
     1381 * @param[in] packet    The received packet or the received packet queue.
     1382 * @param[in] target    The target internetwork module service to be
     1383 *                      delivered to.
     1384 * @param[in] error     The packet error reporting service. Prefixes the
     1385 *                      received packet.
     1386 *
     1387 * @return EOK on success.
     1388 *
     1389 */
     1390int ip_received_error_msg_local(int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error){
     1391        uint8_t * data;
     1392        int offset;
     1393        icmp_type_t type;
     1394        icmp_code_t code;
     1395        ip_netif_ref netif;
     1396        measured_string_t address;
     1397        ip_route_ref route;
     1398        ip_header_ref header;
     1399
     1400        switch(error){
     1401                case SERVICE_ICMP:
     1402                        offset = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
     1403                        if(offset < 0){
     1404                                return ip_release_and_return(packet, ENOMEM);
     1405                        }
     1406                        data = packet_get_data(packet);
     1407                        header = (ip_header_ref)(data + offset);
     1408                        // destination host unreachable?
     1409                        if((type == ICMP_DEST_UNREACH) && (code == ICMP_HOST_UNREACH)){
     1410                                fibril_rwlock_read_lock(&ip_globals.netifs_lock);
     1411                                netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1412                                if(netif && netif->arp){
     1413                                        route = ip_routes_get_index(&netif->routes, 0);
     1414                                        // from the same network?
     1415                                        if(route && ((route->address.s_addr &route->netmask.s_addr) == (header->destination_address &route->netmask.s_addr))){
     1416                                                // clear the ARP mapping if any
     1417                                                address.value = (char *) &header->destination_address;
     1418                                                address.length = CONVERT_SIZE(uint8_t, char, sizeof(header->destination_address));
     1419                                                arp_clear_address_req(netif->arp->phone, netif->device_id, SERVICE_IP, &address);
     1420                                        }
     1421                                }
     1422                                fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
     1423                        }
     1424                        break;
     1425                default:
     1426                        return ip_release_and_return(packet, ENOTSUP);
     1427        }
     1428        return ip_deliver_local(device_id, packet, header, error);
     1429}
     1430
     1431int ip_deliver_local(device_id_t device_id, packet_t packet, ip_header_ref header, services_t error){
     1432        ERROR_DECLARE;
     1433
     1434        ip_proto_ref proto;
     1435        int phone;
     1436        services_t service;
     1437        tl_received_msg_t received_msg;
     1438        struct sockaddr * src;
     1439        struct sockaddr * dest;
     1440        struct sockaddr_in src_in;
     1441        struct sockaddr_in dest_in;
     1442//      struct sockaddr_in      src_in6;
     1443//      struct sockaddr_in      dest_in6;
     1444        socklen_t addrlen;
     1445
     1446        if((header->flags &IPFLAG_MORE_FRAGMENTS) || IP_FRAGMENT_OFFSET(header)){
     1447                // TODO fragmented
     1448                return ENOTSUP;
     1449        }else{
     1450                switch(header->version){
     1451                        case IPVERSION:
     1452                                addrlen = sizeof(src_in);
     1453                                bzero(&src_in, addrlen);
     1454                                src_in.sin_family = AF_INET;
     1455                                memcpy(&dest_in, &src_in, addrlen);
     1456                                memcpy(&src_in.sin_addr.s_addr, &header->source_address, sizeof(header->source_address));
     1457                                memcpy(&dest_in.sin_addr.s_addr, &header->destination_address, sizeof(header->destination_address));
     1458                                src = (struct sockaddr *) &src_in;
     1459                                dest = (struct sockaddr *) &dest_in;
     1460                                break;
     1461/*                      case IPv6VERSION:
     1462                                addrlen = sizeof(src_in6);
     1463                                bzero(&src_in6, addrlen);
     1464                                src_in6.sin6_family = AF_INET6;
     1465                                memcpy(&dest_in6, &src_in6, addrlen);
     1466                                memcpy(&src_in6.sin6_addr.s6_addr,);
     1467                                memcpy(&dest_in6.sin6_addr.s6_addr,);
     1468                                src = (struct sockaddr *) &src_in;
     1469                                dest = (struct sockaddr *) &dest_in;
     1470                                break;
     1471*/                      default:
     1472                                return ip_release_and_return(packet, EAFNOSUPPORT);
     1473                }
     1474                if(ERROR_OCCURRED(packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest, addrlen))){
     1475                        return ip_release_and_return(packet, ERROR_CODE);
     1476                }
     1477                // trim padding if present
     1478                if((! error) && (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))){
     1479                        if(ERROR_OCCURRED(packet_trim(packet, 0, packet_get_data_length(packet) - IP_TOTAL_LENGTH(header)))){
     1480                                return ip_release_and_return(packet, ERROR_CODE);
     1481                        }
     1482                }
     1483                fibril_rwlock_read_lock(&ip_globals.protos_lock);
     1484                proto = ip_protos_find(&ip_globals.protos, header->protocol);
     1485                if(! proto){
     1486                        fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1487                        phone = ip_prepare_icmp_and_get_phone(error, packet, header);
     1488                        if(phone >= 0){
     1489                                // unreachable ICMP
     1490                                icmp_destination_unreachable_msg(phone, ICMP_PROT_UNREACH, 0, packet);
     1491                        }
     1492                        return ENOENT;
     1493                }
     1494                if(proto->received_msg){
     1495                        service = proto->service;
     1496                        received_msg = proto->received_msg;
     1497                        fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1498                        ERROR_CODE = received_msg(device_id, packet, service, error);
     1499                }else{
     1500                        ERROR_CODE = tl_received_msg(proto->phone, device_id, packet, proto->service, error);
     1501                        fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1502                }
     1503                return ERROR_CODE;
     1504        }
     1505}
     1506
     1507in_addr_t ip_get_destination(ip_header_ref header){
     1508        in_addr_t destination;
     1509
     1510        // TODO search set ipopt route?
     1511        destination.s_addr = header->destination_address;
     1512        return destination;
     1513}
     1514
     1515int ip_prepare_icmp(packet_t packet, ip_header_ref header){
     1516        packet_t next;
     1517        struct sockaddr * dest;
     1518        struct sockaddr_in dest_in;
     1519//      struct sockaddr_in      dest_in6;
     1520        socklen_t addrlen;
     1521
     1522        // detach the first packet and release the others
     1523        next = pq_detach(packet);
     1524        if(next){
     1525                pq_release_remote(ip_globals.net_phone, packet_get_id(next));
     1526        }
     1527        if(! header){
     1528                if(packet_get_data_length(packet) <= sizeof(ip_header_t)){
     1529                        return ENOMEM;
     1530                }
     1531                // get header
     1532                header = (ip_header_ref) packet_get_data(packet);
     1533                if(! header){
     1534                        return EINVAL;
     1535                }
     1536        }
     1537        // only for the first fragment
     1538        if(IP_FRAGMENT_OFFSET(header)){
     1539                return EINVAL;
     1540        }
     1541        // not for the ICMP protocol
     1542        if(header->protocol == IPPROTO_ICMP){
     1543                return EPERM;
     1544        }
     1545        // set the destination address
     1546        switch(header->version){
     1547                case IPVERSION:
     1548                        addrlen = sizeof(dest_in);
     1549                        bzero(&dest_in, addrlen);
     1550                        dest_in.sin_family = AF_INET;
     1551                        memcpy(&dest_in.sin_addr.s_addr, &header->source_address, sizeof(header->source_address));
     1552                        dest = (struct sockaddr *) &dest_in;
     1553                        break;
     1554/*              case IPv6VERSION:
     1555                        addrlen = sizeof(dest_in6);
     1556                        bzero(&dest_in6, addrlen);
     1557                        dest_in6.sin6_family = AF_INET6;
     1558                        memcpy(&dest_in6.sin6_addr.s6_addr,);
     1559                        dest = (struct sockaddr *) &dest_in;
     1560                        break;
     1561*/              default:
     1562                        return EAFNOSUPPORT;
     1563        }
     1564        return packet_set_addr(packet, NULL, (uint8_t *) dest, addrlen);
     1565}
     1566
     1567int ip_get_icmp_phone(void){
     1568        ip_proto_ref proto;
     1569        int phone;
     1570
     1571        fibril_rwlock_read_lock(&ip_globals.protos_lock);
     1572        proto = ip_protos_find(&ip_globals.protos, IPPROTO_ICMP);
     1573        phone = proto ? proto->phone : ENOENT;
     1574        fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1575        return phone;
     1576}
     1577
     1578int ip_prepare_icmp_and_get_phone(services_t error, packet_t packet, ip_header_ref header){
     1579        int phone;
     1580
     1581        phone = ip_get_icmp_phone();
     1582        if(error || (phone < 0) || ip_prepare_icmp(packet, header)){
     1583                return ip_release_and_return(packet, EINVAL);
     1584        }
     1585        return phone;
     1586}
     1587
     1588int ip_release_and_return(packet_t packet, int result){
     1589        pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
     1590        return result;
     1591}
     1592
     1593int ip_get_route_req_local(int ip_phone, ip_protocol_t protocol, const struct sockaddr * destination, socklen_t addrlen, device_id_t * device_id, void **header, size_t * headerlen){
     1594        struct sockaddr_in * address_in;
     1595//      struct sockaddr_in6 *   address_in6;
     1596        in_addr_t * dest;
     1597        in_addr_t * src;
     1598        ip_route_ref route;
     1599        ipv4_pseudo_header_ref header_in;
     1600
     1601        if(!(destination && (addrlen > 0))){
     1602                return EINVAL;
     1603        }
     1604        if(!(device_id && header && headerlen)){
     1605                return EBADMEM;
     1606        }
     1607        if((size_t) addrlen < sizeof(struct sockaddr)){
     1608                return EINVAL;
     1609        }
     1610        switch(destination->sa_family){
     1611                case AF_INET:
     1612                        if(addrlen != sizeof(struct sockaddr_in)){
     1613                                return EINVAL;
     1614                        }
     1615                        address_in = (struct sockaddr_in *) destination;
     1616                        dest = &address_in->sin_addr;
     1617                        if(! dest->s_addr){
     1618                                dest->s_addr = IPV4_LOCALHOST_ADDRESS;
     1619                        }
     1620                        break;
     1621                // TODO IPv6
     1622/*              case AF_INET6:
     1623                        if(addrlen != sizeof(struct sockaddr_in6)){
     1624                                return EINVAL;
     1625                        }
     1626                        address_in6 = (struct sockaddr_in6 *) dest;
     1627                        address_in6.sin6_addr.s6_addr;
     1628*/              default:
     1629                        return EAFNOSUPPORT;
     1630        }
     1631        fibril_rwlock_read_lock(&ip_globals.lock);
     1632        route = ip_find_route(*dest);
     1633        // if the local host is the destination
     1634        if(route && (route->address.s_addr == dest->s_addr)
     1635                && (dest->s_addr != IPV4_LOCALHOST_ADDRESS)){
     1636                // find the loopback device to deliver
     1637                dest->s_addr = IPV4_LOCALHOST_ADDRESS;
     1638                route = ip_find_route(*dest);
     1639        }
     1640        if(!(route && route->netif)){
     1641                fibril_rwlock_read_unlock(&ip_globals.lock);
     1642                return ENOENT;
     1643        }
     1644        *device_id = route->netif->device_id;
     1645        src = ip_netif_address(route->netif);
     1646        fibril_rwlock_read_unlock(&ip_globals.lock);
     1647        *headerlen = sizeof(*header_in);
     1648        header_in = (ipv4_pseudo_header_ref) malloc(*headerlen);
     1649        if(! header_in){
     1650                return ENOMEM;
     1651        }
     1652        bzero(header_in, * headerlen);
     1653        header_in->destination_address = dest->s_addr;
     1654        header_in->source_address = src->s_addr;
     1655        header_in->protocol = protocol;
     1656        header_in->data_length = 0;
     1657        *header = header_in;
     1658        return EOK;
     1659}
     1660
    19581661/** Default thread for new connections.
    19591662 *
    1960  * @param[in] iid       The initial message identifier.
    1961  * @param[in] icall     The initial message call structure.
    1962  */
    1963 static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
     1663 *  @param[in] iid The initial message identifier.
     1664 *  @param[in] icall The initial message call structure.
     1665 *
     1666 */
     1667static void il_client_connection(ipc_callid_t iid, ipc_call_t * icall)
    19641668{
    19651669        /*
     
    19691673        ipc_answer_0(iid, EOK);
    19701674       
    1971         while (true) {
     1675        while(true) {
    19721676                ipc_call_t answer;
    19731677                int answer_count;
     
    19841688                    &answer_count);
    19851689               
    1986                 /*
    1987                  * End if told to either by the message or the processing
    1988                  * result.
    1989                  */
    1990                 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
    1991                     (res == EHANGUP)) {
     1690                /* End if said to either by the message or the processing result */
     1691                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
    19921692                        return;
    1993                 }
    19941693               
    19951694                /* Answer the message */
     
    20001699/** Starts the module.
    20011700 *
    2002  * @returns EOK on success.
    2003  * @returns Other error codes as defined for each specific module start function.
     1701 *  @param argc The count of the command line arguments. Ignored parameter.
     1702 *  @param argv The command line parameters. Ignored parameter.
     1703 *
     1704 *  @returns EOK on success.
     1705 *  @returns Other error codes as defined for each specific module start function.
     1706 *
    20041707 */
    20051708int main(int argc, char *argv[])
     
    20081711       
    20091712        /* Start the module */
    2010         ERROR_PROPAGATE(il_module_start_standalone(il_client_connection));
     1713        if (ERROR_OCCURRED(il_module_start_standalone(il_client_connection)))
     1714                return ERROR_CODE;
     1715       
    20111716        return EOK;
    20121717}
  • uspace/srv/net/il/ip/ip.h

    r069015f2 rf2d2c604  
    2828
    2929/** @addtogroup ip
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @file
    34  * IP module.
    35  */
    36 
    37 #ifndef NET_IP_H_
    38 #define NET_IP_H_
     34 *  IP module.
     35 */
     36
     37#ifndef __NET_IP_H__
     38#define __NET_IP_H__
    3939
    4040#include <fibril_synch.h>
     
    5050
    5151/** Type definition of the IP global data.
    52  * @see ip_globals
    53  */
    54 typedef struct ip_globals ip_globals_t;
     52 *  @see ip_globals
     53 */
     54typedef struct ip_globals       ip_globals_t;
    5555
    5656/** Type definition of the IP network interface specific data.
    57  * @see ip_netif
    58  */
    59 typedef struct ip_netif ip_netif_t;
     57 *  @see ip_netif
     58 */
     59typedef struct ip_netif ip_netif_t;
    6060
    6161/** Type definition of the IP network interface specific data pointer.
    62  * @see ip_netif
    63  */
    64 typedef ip_netif_t *ip_netif_ref;
     62 *  @see ip_netif
     63 */
     64typedef ip_netif_t *    ip_netif_ref;
    6565
    6666/** Type definition of the IP protocol specific data.
    67  * @see ip_proto
    68  */
    69 typedef struct ip_proto ip_proto_t;
     67 *  @see ip_proto
     68 */
     69typedef struct ip_proto ip_proto_t;
    7070
    7171/** Type definition of the IP protocol specific data pointer.
    72  * @see ip_proto
    73  */
    74 typedef ip_proto_t *ip_proto_ref;
     72 *  @see ip_proto
     73 */
     74typedef ip_proto_t *    ip_proto_ref;
    7575
    7676/** Type definition of the IP route specific data.
     
    8282 *  @see ip_route
    8383 */
    84 typedef ip_route_t *ip_route_ref;
     84typedef ip_route_t *    ip_route_ref;
    8585
    8686/** IP network interfaces.
    87  * Maps devices to the IP network interface specific data.
    88  * @see device.h
    89  */
    90 DEVICE_MAP_DECLARE(ip_netifs, ip_netif_t);
     87 *  Maps devices to the IP network interface specific data.
     88 *  @see device.h
     89 */
     90DEVICE_MAP_DECLARE(ip_netifs, ip_netif_t)
    9191
    9292/** IP registered protocols.
    93  * Maps protocols to the IP protocol specific data.
    94  * @see int_map.h
    95  */
    96 INT_MAP_DECLARE(ip_protos, ip_proto_t);
     93 *  Maps protocols to the IP protocol specific data.
     94 *  @see int_map.h
     95 */
     96INT_MAP_DECLARE(ip_protos, ip_proto_t)
    9797
    9898/** IP routing table.
    99  * @see generic_field.h
    100  */
    101 GENERIC_FIELD_DECLARE(ip_routes, ip_route_t);
    102 
    103 /** IP network interface specific data. */
    104 struct ip_netif {
    105         /** ARP module. Assigned if using ARP. */
     99 *  @see generic_field.h
     100 */
     101GENERIC_FIELD_DECLARE(ip_routes, ip_route_t)
     102
     103/** IP network interface specific data.
     104 */
     105struct  ip_netif{
     106        /** ARP module.
     107         *  Assigned if using ARP.
     108         */
    106109        module_ref arp;
    107         /** Broadcast address. */
     110        /** Broadcast address.
     111         */
    108112        in_addr_t broadcast;
    109         /** Device identifier. */
     113        /** Device identifier.
     114         */
    110115        device_id_t device_id;
    111         /** Indicates whether using DHCP. */
     116        /** Indicates whether using DHCP.
     117         */
    112118        int dhcp;
    113         /** IP version. */
     119        /** IP version.
     120         */
    114121        int ipv;
    115         /** Packet dimension. */
     122        /** Packet dimension.
     123         */
    116124        packet_dimension_t packet_dimension;
    117         /** Netif module phone. */
     125        /** Netif module phone.
     126         */
    118127        int phone;
    119         /** Routing table. */
     128        /** Routing table.
     129         */
    120130        ip_routes_t routes;
    121         /** Indicates whether IP routing is enabled. */
     131        /** Indicates whether IP routing is enabled.
     132         */
    122133        int routing;
    123         /** Netif module service. */
     134        /** Netif module service.
     135         */
    124136        services_t service;
    125         /** Device state. */
     137        /** Device state.
     138         */
    126139        device_state_t state;
    127140};
    128141
    129 /** IP protocol specific data. */
    130 struct ip_proto {
    131         /** Protocol module phone. */
     142/** IP protocol specific data.
     143 */
     144struct ip_proto{
     145        /** Protocol module phone.
     146         */
    132147        int phone;
    133         /** Protocol number. */
     148        /** Protocol number.
     149         */
    134150        int protocol;
    135         /** Protocol packet receiving function. */
     151        /** Protocol packet receiving function.
     152         */
    136153        tl_received_msg_t received_msg;
    137         /** Protocol module service. */
     154        /** Protocol module service.
     155         */
    138156        services_t service;
    139157};
    140158
    141 /** IP route specific data. */
    142 struct ip_route {
    143         /** Target address. */
     159/** IP route specific data.
     160 */
     161struct ip_route{
     162        /** Target address.
     163         */
    144164        in_addr_t address;
    145         /** Gateway. */
     165        /** Gateway.
     166         */
    146167        in_addr_t gateway;
    147         /** Parent netif. */
     168        /** Parent netif.
     169         */
    148170        ip_netif_ref netif;
    149         /** Target network mask. */
     171        /** Target network mask.
     172         */
    150173        in_addr_t netmask;
    151174};
    152175
    153 /** IP global data. */
    154 struct ip_globals {
    155         /** Default client connection function for support modules. */
     176/** IP global data.
     177 */
     178struct  ip_globals{
     179        /** Default client connection function for support modules.
     180         */
    156181        async_client_conn_t client_connection;
    157         /** Default gateway. */
     182        /** Default gateway.
     183         */
    158184        ip_route_t gateway;
    159         /** Safety lock. */
     185        /** Safety lock.
     186         */
    160187        fibril_rwlock_t lock;
    161         /** Known support modules. */
     188        /** Known support modules.
     189         */
    162190        modules_t modules;
    163         /** Networking module phone. */
     191        /** Networking module phone.
     192         */
    164193        int net_phone;
    165         /** Registered network interfaces. */
     194        /** Registered network interfaces.
     195         */
    166196        ip_netifs_t netifs;
    167         /** Netifs safeyt lock. */
     197        /** Netifs safeyt lock.
     198         */
    168199        fibril_rwlock_t netifs_lock;
    169         /** Packet counter. */
     200        /** Packet counter.
     201         */
    170202        uint16_t packet_counter;
    171         /** Registered protocols. */
     203        /** Registered protocols.
     204         */
    172205        ip_protos_t protos;
    173         /** Protocols safety lock. */
     206        /** Protocols safety lock.
     207         */
    174208        fibril_rwlock_t protos_lock;
    175209};
  • uspace/srv/net/il/ip/ip_module.c

    r069015f2 rf2d2c604  
    3232
    3333/** @file
    34  * IP standalone module implementation.
    35  * Contains skeleton module functions mapping.
    36  * The functions are used by the module skeleton as module specific entry
    37  * points.
    38  *
    39  * @see module.c
     34 *  IP standalone module implementation.
     35 *  Contains skeleton module functions mapping.
     36 *  The functions are used by the module skeleton as module specific entry points.
     37 *  @see module.c
    4038 */
    4139
     
    5452#include "ip_module.h"
    5553
    56 /** IP module global data. */
     54/** IP module global data.
     55 */
    5756extern ip_globals_t ip_globals;
    5857
    59 int
    60 il_module_message_standalone(ipc_callid_t callid, ipc_call_t *call,
    61     ipc_call_t *answer, int *answer_count)
    62 {
     58int il_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
    6359        return ip_message_standalone(callid, call, answer, answer_count);
    6460}
    6561
    66 int il_module_start_standalone(async_client_conn_t client_connection)
    67 {
     62int il_module_start_standalone(async_client_conn_t client_connection){
    6863        ERROR_DECLARE;
    6964       
     
    7368       
    7469        ipcarg_t phonehash;
    75         if (ERROR_OCCURRED(ip_initialize(client_connection)) ||
    76             ERROR_OCCURRED(REGISTER_ME(SERVICE_IP, &phonehash))) {
     70        if (ERROR_OCCURRED(ip_initialize(client_connection))
     71            || ERROR_OCCURRED(REGISTER_ME(SERVICE_IP, &phonehash))) {
    7772                pm_destroy();
    7873                return ERROR_CODE;
  • uspace/srv/net/il/ip/ip_module.h

    r069015f2 rf2d2c604  
    2828
    2929/** @addtogroup ip
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @file
    34  * IP module functions.
    35  * The functions are used as IP module entry points.
     34 *  IP module functions.
     35 *  The functions are used as IP module entry points.
    3636 */
    3737
    38 #ifndef NET_IP_MODULE_H_
    39 #define NET_IP_MODULE_H_
     38#ifndef __NET_IP_MODULE_H__
     39#define __NET_IP_MODULE_H__
    4040
    4141#include <ipc/ipc.h>
    4242
    43 extern int ip_initialize(async_client_conn_t);
    44 extern int ip_message_standalone(ipc_callid_t, ipc_call_t *, ipc_call_t *,
    45     int *);
     43/** Initializes the IP module.
     44 *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
     45 *  @returns EOK on success.
     46 *  @returns ENOMEM if there is not enough memory left.
     47 */
     48int ip_initialize(async_client_conn_t client_connection);
     49
     50/** Processes the IP message.
     51 *  @param[in] callid The message identifier.
     52 *  @param[in] call The message parameters.
     53 *  @param[out] answer The message answer parameters.
     54 *  @param[out] answer_count The last parameter for the actual answer in the answer parameter.
     55 *  @returns EOK on success.
     56 *  @returns ENOTSUP if the message is not known.
     57 *  @see ip_interface.h
     58 *  @see il_interface.h
     59 *  @see IS_NET_IP_MESSAGE()
     60 */
     61int ip_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
    4662
    4763#endif
Note: See TracChangeset for help on using the changeset viewer.