Ignore:
File:
1 edited

Legend:

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

    rfd8e8e1 r14f1db0  
    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>
    4239#include <errno.h>
    43 #include <err.h>
    4440#include <fibril_synch.h>
    4541#include <stdio.h>
     
    4743#include <ipc/ipc.h>
    4844#include <ipc/services.h>
    49 #include <ipc/net.h>
    50 #include <ipc/nil.h>
    51 #include <ipc/il.h>
    52 #include <ipc/ip.h>
    5345#include <sys/types.h>
    54 #include <byteorder.h>
    55 
    56 #include <adt/measured_strings.h>
    57 #include <adt/module_map.h>
    58 
    59 #include <packet_client.h>
    60 #include <net/socket_codes.h>
    61 #include <net/in.h>
    62 #include <net/in6.h>
    63 #include <net/inet.h>
    64 #include <net/modules.h>
    65 #include <net/device.h>
    66 #include <net/packet.h>
    67 #include <net/icmp_codes.h>
    68 
     46
     47#include <net_err.h>
     48#include <net_messages.h>
     49#include <net_modules.h>
    6950#include <arp_interface.h>
     51#include <net_byteorder.h>
    7052#include <net_checksum.h>
     53#include <net_device.h>
    7154#include <icmp_client.h>
     55#include <icmp_codes.h>
    7256#include <icmp_interface.h>
    7357#include <il_interface.h>
     58#include <in.h>
     59#include <in6.h>
     60#include <inet.h>
    7461#include <ip_client.h>
    7562#include <ip_interface.h>
    76 #include <ip_header.h>
    7763#include <net_interface.h>
    7864#include <nil_interface.h>
    7965#include <tl_interface.h>
     66#include <socket_codes.h>
     67#include <socket_errno.h>
     68#include <adt/measured_strings.h>
     69#include <adt/module_map.h>
     70#include <packet/packet_client.h>
    8071#include <packet_remote.h>
     72#include <nil_messages.h>
     73#include <il_messages.h>
    8174#include <il_local.h>
    82 
    83 /** IP module name. */
    84 #define NAME                    "ip"
    85 
    86 /** IP version 4. */
    87 #define IPV4                    4
    88 
    89 /** Default network interface IP version. */
     75#include <ip_local.h>
     76
     77#include "ip.h"
     78#include "ip_header.h"
     79#include "ip_messages.h"
     80#include "ip_module.h"
     81
     82/** IP module name.
     83 */
     84#define NAME  "ip"
     85
     86/** IP version 4.
     87 */
     88#define IPV4                            4
     89
     90/** Default network interface IP version.
     91 */
    9092#define NET_DEFAULT_IPV         IPV4
    9193
    92 /** Default network interface IP routing. */
     94/** Default network interface IP routing.
     95 */
    9396#define NET_DEFAULT_IP_ROUTING  false
    9497
    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. */
     98/** Minimum IP packet content.
     99 */
     100#define IP_MIN_CONTENT  576
     101
     102/** ARP module name.
     103 */
     104#define ARP_NAME                                "arp"
     105
     106/** ARP module filename.
     107 */
     108#define ARP_FILENAME                    "/srv/arp"
     109
     110/** IP packet address length.
     111 */
     112#define IP_ADDR                                                 sizeof(struct sockaddr_in6)
     113
     114/** IP packet prefix length.
     115 */
     116#define IP_PREFIX                                               sizeof(ip_header_t)
     117
     118/** IP packet suffix length.
     119 */
     120#define IP_SUFFIX                                               0
     121
     122/** IP packet maximum content length.
     123 */
     124#define IP_MAX_CONTENT                                  65535
     125
     126/** The IP localhost address.
     127 */
    117128#define IPV4_LOCALHOST_ADDRESS  htonl((127 << 24) + 1)
    118129
    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);
     130/** IP global data.
     131 */
     132ip_globals_t    ip_globals;
     133
     134DEVICE_MAP_IMPLEMENT(ip_netifs, ip_netif_t)
     135
     136INT_MAP_IMPLEMENT(ip_protos, ip_proto_t)
     137
     138GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t)
     139
     140/** Updates the device content length according to the new MTU value.
     141 *  @param[in] device_id The device identifier.
     142 *  @param[in] mtu The new mtu value.
     143 *  @returns EOK on success.
     144 *  @returns ENOENT if device is not found.
     145 */
     146int ip_mtu_changed_message(device_id_t device_id, size_t mtu);
     147
     148/** Updates the device state.
     149 *  @param[in] device_id The device identifier.
     150 *  @param[in] state The new state value.
     151 *  @returns EOK on success.
     152 *  @returns ENOENT if device is not found.
     153 */
     154int ip_device_state_message(device_id_t device_id, device_state_t state);
     155
     156/** Returns the device packet dimensions for sending.
     157 *  @param[in] phone The service module phone.
     158 *  @param[in] message The service specific message.
     159 *  @param[in] device_id The device identifier.
     160 *  @param[out] addr_len The minimum reserved address length.
     161 *  @param[out] prefix The minimum reserved prefix size.
     162 *  @param[out] content The maximum content size.
     163 *  @param[out] suffix The minimum reserved suffix size.
     164 *  @returns EOK on success.
     165 */
     166int ip_packet_size_message(device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix);
     167
     168/** Registers the transport layer protocol.
     169 *  The traffic of this protocol will be supplied using either the receive function or IPC message.
     170 *  @param[in] protocol The transport layer module protocol.
     171 *  @param[in] service The transport layer module service.
     172 *  @param[in] phone The transport layer module phone.
     173 *  @param[in] tl_received_msg The receiving function.
     174 *  @returns EOK on success.
     175 *  @returns EINVAL if the protocol parameter and/or the service parameter is zero (0).
     176 *  @returns EINVAL if the phone parameter is not a positive number and the tl_receive_msg is NULL.
     177 *  @returns ENOMEM if there is not enough memory left.
     178 */
     179int ip_register(int protocol, services_t service, int phone, tl_received_msg_t tl_received_msg);
     180
     181/** Initializes a new network interface specific data.
     182 *  Connects to the network interface layer module, reads the netif configuration, starts an ARP module if needed and sets the netif routing table.
     183 *  The device identifier and the nil service has to be set.
     184 *  @param[in,out] ip_netif Network interface specific data.
     185 *  @returns EOK on success.
     186 *  @returns ENOTSUP if DHCP is configured.
     187 *  @returns ENOTSUP if IPv6 is configured.
     188 *  @returns EINVAL if any of the addresses is invalid.
     189 *  @returns EINVAL if the used ARP module is not known.
     190 *  @returns ENOMEM if there is not enough memory left.
     191 *  @returns Other error codes as defined for the net_get_device_conf_req() function.
     192 *  @returns Other error codes as defined for the bind_service() function.
     193 *  @returns Other error codes as defined for the specific arp_device_req() function.
     194 *  @returns Other error codes as defined for the nil_packet_size_req() function.
     195 */
     196int ip_netif_initialize(ip_netif_ref ip_netif);
     197
     198/** Sends the packet or the packet queue via the specified route.
     199 *  The ICMP_HOST_UNREACH error notification may be sent if route hardware destination address is found.
     200 *  @param[in,out] packet The packet to be sent.
     201 *  @param[in] netif The target network interface.
     202 *  @param[in] route The target route.
     203 *  @param[in] src The source address.
     204 *  @param[in] dest The destination address.
     205 *  @param[in] error The error module service.
     206 *  @returns EOK on success.
     207 *  @returns Other error codes as defined for the arp_translate_req() function.
     208 *  @returns Other error codes as defined for the ip_prepare_packet() function.
     209 */
     210int 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);
     211
     212/** Prepares the outgoing packet or the packet queue.
     213 *  The packet queue is a fragmented packet
     214 *  Updates the first packet's IP header.
     215 *  Prefixes the additional packets with fragment headers.
     216 *  @param[in] source The source address.
     217 *  @param[in] dest The destination address.
     218 *  @param[in,out] packet The packet to be sent.
     219 *  @param[in] destination The destination hardware address.
     220 *  @returns EOK on success.
     221 *  @returns EINVAL if the packet is too small to contain the IP header.
     222 *  @returns EINVAL if the packet is too long than the IP allows.
     223 *  @returns ENOMEM if there is not enough memory left.
     224 *  @returns Other error codes as defined for the packet_set_addr() function.
     225 */
     226int ip_prepare_packet(in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination);
     227
     228/** Checks the packet queue lengths and fragments the packets if needed.
     229 *  The ICMP_FRAG_NEEDED error notification may be sent if the packet needs to be fragmented and the fragmentation is not allowed.
     230 *  @param[in,out] packet The packet or the packet queue to be checked.
     231 *  @param[in] prefix The minimum prefix size.
     232 *  @param[in] content The maximum content size.
     233 *  @param[in] suffix The minimum suffix size.
     234 *  @param[in] addr_len The minimum address length.
     235 *  @param[in] error The error module service.
     236 *  @returns The packet or the packet queue of the allowed length.
     237 *  @returns NULL if there are no packets left.
     238 */
     239packet_t ip_split_packet(packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error);
     240
     241/** Checks the packet length and fragments it if needed.
     242 *  The new fragments are queued before the original packet.
     243 *  @param[in,out] packet The packet to be checked.
     244 *  @param[in] length The maximum packet length.
     245 *  @param[in] prefix The minimum prefix size.
     246 *  @param[in] suffix The minimum suffix size.
     247 *  @param[in] addr_len The minimum address length.
     248 *  @returns EOK on success.
     249 *  @returns EINVAL if the packet_get_addr() function fails.
     250 *  @returns EINVAL if the packet does not contain the IP header.
     251 *  @returns EPERM if the packet needs to be fragmented and the fragmentation is not allowed.
     252 *  @returns ENOMEM if there is not enough memory left.
     253 *  @returns ENOMEM if there is no packet available.
     254 *  @returns ENOMEM if the packet is too small to contain the IP header.
     255 *  @returns Other error codes as defined for the packet_trim() function.
     256 *  @returns Other error codes as defined for the ip_create_middle_header() function.
     257 *  @returns Other error codes as defined for the ip_fragment_packet_data() function.
     258 */
     259int ip_fragment_packet(packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len);
     260
     261/** Fragments the packet from the end.
     262 *  @param[in] packet The packet to be fragmented.
     263 *  @param[in,out] new_packet The new packet fragment.
     264 *  @param[in,out] header The original packet header.
     265 *  @param[in,out] new_header The new packet fragment header.
     266 *  @param[in] length The new fragment length.
     267 *  @param[in] src The source address.
     268 *  @param[in] dest The destiantion address.
     269 *  @param[in] addrlen The address length.
     270 *  @returns EOK on success.
     271 *  @returns ENOMEM if the target packet is too small.
     272 *  @returns Other error codes as defined for the packet_set_addr() function.
     273 *  @returns Other error codes as defined for the pq_insert_after() function.
     274 */
     275int 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);
     276
     277/** Prefixes a middle fragment header based on the last fragment header to the packet.
     278 *  @param[in] packet The packet to be prefixed.
     279 *  @param[in] last The last header to be copied.
     280 *  @returns The prefixed middle header.
     281 *  @returns NULL on error.
     282 */
     283ip_header_ref ip_create_middle_header(packet_t packet, ip_header_ref last);
     284
     285/** Copies the fragment header.
     286 *  Copies only the header itself and relevant IP options.
     287 *  @param[out] last The created header.
     288 *  @param[in] first The original header to be copied.
     289 */
     290void ip_create_last_header(ip_header_ref last, ip_header_ref first);
     291
     292/** Returns the network interface's IP address.
     293 *  @param[in] netif The network interface.
     294 *  @returns The IP address.
     295 *  @returns NULL if no IP address was found.
     296 */
     297in_addr_t * ip_netif_address(ip_netif_ref netif);
     298
     299/** Searches all network interfaces if there is a suitable route.
     300 *  @param[in] destination The destination address.
     301 *  @returns The found route.
     302 *  @returns NULL if no route was found.
     303 */
     304ip_route_ref ip_find_route(in_addr_t destination);
     305
     306/** Searches the network interfaces if there is a suitable route.
     307 *  @param[in] netif The network interface to be searched for routes. May be NULL.
     308 *  @param[in] destination The destination address.
     309 *  @returns The found route.
     310 *  @returns NULL if no route was found.
     311 */
     312ip_route_ref ip_netif_find_route(ip_netif_ref netif, in_addr_t destination);
     313
     314/** Processes the received IP packet or the packet queue one by one.
     315 *  The packet is either passed to another module or released on error.
     316 *  @param[in] device_id The source device identifier.
     317 *  @param[in,out] packet The received packet.
     318 *  @returns EOK on success and the packet is no longer needed.
     319 *  @returns EINVAL if the packet is too small to carry the IP packet.
     320 *  @returns EINVAL if the received address lengths differs from the registered values.
     321 *  @returns ENOENT if the device is not found in the cache.
     322 *  @returns ENOENT if the protocol for the device is not found in the cache.
     323 *  @returns ENOMEM if there is not enough memory left.
     324 */
     325int ip_receive_message(device_id_t device_id, packet_t packet);
     326
     327/** Processes the received packet.
     328 *  The packet is either passed to another module or released on error.
     329 *  The ICMP_PARAM_POINTER error notification may be sent if the checksum is invalid.
     330 *  The ICMP_EXC_TTL error notification may be sent if the TTL is less than two (2).
     331 *  The ICMP_HOST_UNREACH error notification may be sent if no route was found.
     332 *  The ICMP_HOST_UNREACH error notification may be sent if the packet is for another host and the routing is disabled.
     333 *  @param[in] device_id The source device identifier.
     334 *  @param[in] packet The received packet to be processed.
     335 *  @returns EOK on success.
     336 *  @returns EINVAL if the TTL is less than two (2).
     337 *  @returns EINVAL if the checksum is invalid.
     338 *  @returns EAFNOSUPPORT if the address family is not supported.
     339 *  @returns ENOENT if no route was found.
     340 *  @returns ENOENT if the packet is for another host and the routing is disabled.
     341 */
     342int ip_process_packet(device_id_t device_id, packet_t packet);
     343
     344/** Returns the packet destination address from the IP header.
     345 *  @param[in] header The packet IP header to be read.
     346 *  @returns The packet destination address.
     347 */
     348in_addr_t ip_get_destination(ip_header_ref header);
     349
     350/** Delivers the packet to the local host.
     351 *  The packet is either passed to another module or released on error.
     352 *  The ICMP_PROT_UNREACH error notification may be sent if the protocol is not found.
     353 *  @param[in] device_id The source device identifier.
     354 *  @param[in] packet The packet to be delivered.
     355 *  @param[in] header The first packet IP header. May be NULL.
     356 *  @param[in] error The packet error service.
     357 *  @returns EOK on success.
     358 *  @returns ENOTSUP if the packet is a fragment.
     359 *  @returns EAFNOSUPPORT if the address family is not supported.
     360 *  @returns ENOENT if the target protocol is not found.
     361 *  @returns Other error codes as defined for the packet_set_addr() function.
     362 *  @returns Other error codes as defined for the packet_trim() function.
     363 *  @returns Other error codes as defined for the protocol specific tl_received_msg function.
     364 */
     365int ip_deliver_local(device_id_t device_id, packet_t packet, ip_header_ref header, services_t error);
     366
     367/** Prepares the ICMP notification packet.
     368 *  Releases additional packets and keeps only the first one.
     369 *  All packets is released on error.
     370 *  @param[in] error The packet error service.
     371 *  @param[in] packet The packet or the packet queue to be reported as faulty.
     372 *  @param[in] header The first packet IP header. May be NULL.
     373 *  @returns The found ICMP phone.
     374 *  @returns EINVAL if the error parameter is set.
     375 *  @returns EINVAL if the ICMP phone is not found.
     376 *  @returns EINVAL if the ip_prepare_icmp() fails.
     377 */
     378int ip_prepare_icmp_and_get_phone(services_t error, packet_t packet, ip_header_ref header);
     379
     380/** Returns the ICMP phone.
     381 *  Searches the registered protocols.
     382 *  @returns The found ICMP phone.
     383 *  @returns ENOENT if the ICMP is not registered.
     384 */
     385int ip_get_icmp_phone(void);
     386
     387/** Prepares the ICMP notification packet.
     388 *  Releases additional packets and keeps only the first one.
     389 *  @param[in] packet The packet or the packet queue to be reported as faulty.
     390 *  @param[in] header The first packet IP header. May be NULL.
     391 *  @returns EOK on success.
     392 *  @returns EINVAL if there are no data in the packet.
     393 *  @returns EINVAL if the packet is a fragment.
     394 *  @returns ENOMEM if the packet is too short to contain the IP header.
     395 *  @returns EAFNOSUPPORT if the address family is not supported.
     396 *  @returns EPERM if the protocol is not allowed to send ICMP notifications. The ICMP protocol itself.
     397 *  @returns Other error codes as defined for the packet_set_addr().
     398 */
     399int ip_prepare_icmp(packet_t packet, ip_header_ref header);
    125400
    126401/** 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 {
     402 *  @param[in] packet The packet queue to be released.
     403 *  @param[in] result The result to be returned.
     404 *  @return The result parameter.
     405 */
     406int ip_release_and_return(packet_t packet, int result);
     407
     408int ip_initialize(async_client_conn_t client_connection){
    256409        ERROR_DECLARE;
    257410
     
    269422        ip_globals.client_connection = client_connection;
    270423        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));
     424        ERROR_PROPAGATE(add_module(NULL, &ip_globals.modules, ARP_NAME, ARP_FILENAME, SERVICE_ARP, arp_task_get_id(), arp_connect_module));
    273425        fibril_rwlock_write_unlock(&ip_globals.lock);
    274 
    275426        return EOK;
    276427}
    277428
    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 {
     429int ip_device_req_local(int il_phone, device_id_t device_id, services_t netif){
    1160430        ERROR_DECLARE;
    1161431
     
    1165435
    1166436        ip_netif = (ip_netif_ref) malloc(sizeof(ip_netif_t));
    1167         if (!ip_netif)
     437        if(! ip_netif){
    1168438                return ENOMEM;
    1169 
    1170         if (ERROR_OCCURRED(ip_routes_initialize(&ip_netif->routes))) {
     439        }
     440        if(ERROR_OCCURRED(ip_routes_initialize(&ip_netif->routes))){
    1171441                free(ip_netif);
    1172442                return ERROR_CODE;
    1173443        }
    1174 
    1175444        ip_netif->device_id = device_id;
    1176445        ip_netif->service = netif;
    1177446        ip_netif->state = NETIF_STOPPED;
    1178 
    1179447        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    1180         if (ERROR_OCCURRED(ip_netif_initialize(ip_netif))) {
     448        if(ERROR_OCCURRED(ip_netif_initialize(ip_netif))){
    1181449                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1182450                ip_routes_destroy(&ip_netif->routes);
     
    1184452                return ERROR_CODE;
    1185453        }
    1186         if (ip_netif->arp)
    1187                 ip_netif->arp->usage++;
    1188 
     454        if(ip_netif->arp){
     455                ++ ip_netif->arp->usage;
     456        }
    1189457        // print the settings
    1190458        printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
     
    1198466        char gateway[INET_ADDRSTRLEN];
    1199467       
    1200         for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
     468        for (index = 0; index < ip_routes_count(&ip_netif->routes); ++ index){
    1201469                route = ip_routes_get_index(&ip_netif->routes, index);
    1202470                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);
     471                        inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr, address, INET_ADDRSTRLEN);
     472                        inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr, netmask, INET_ADDRSTRLEN);
     473                        inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr, gateway, INET_ADDRSTRLEN);
     474                        printf("%s: Route %d (address: %s, netmask: %s, gateway: %s)\n",
     475                            NAME, index, address, netmask, gateway);
    1212476                }
    1213477        }
    1214478       
    1215         inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
    1216             INET_ADDRSTRLEN);
     479        inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address, INET_ADDRSTRLEN);
     480        printf("%s: Broadcast (%s)\n", NAME, address);
     481       
    1217482        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1218 
    1219         printf("%s: Broadcast (%s)\n", NAME, address);
    1220 
    1221483        return EOK;
    1222484}
    1223485
    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 {
     486int ip_netif_initialize(ip_netif_ref ip_netif){
     487        ERROR_DECLARE;
     488
     489        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}};
     490        measured_string_ref configuration;
     491        size_t count = sizeof(names) / sizeof(measured_string_t);
     492        char * data;
     493        measured_string_t address;
     494        int index;
     495        ip_route_ref route;
     496        in_addr_t gateway;
     497
     498        ip_netif->arp = NULL;
     499        route = NULL;
     500        ip_netif->ipv = NET_DEFAULT_IPV;
     501        ip_netif->dhcp = false;
     502        ip_netif->routing = NET_DEFAULT_IP_ROUTING;
     503        configuration = &names[0];
     504        // get configuration
     505        ERROR_PROPAGATE(net_get_device_conf_req(ip_globals.net_phone, ip_netif->device_id, &configuration, count, &data));
     506        if(configuration){
     507                if(configuration[0].value){
     508                        ip_netif->ipv = strtol(configuration[0].value, NULL, 0);
     509                }
     510                ip_netif->dhcp = ! str_lcmp(configuration[1].value, "dhcp", configuration[1].length);
     511                if(ip_netif->dhcp){
     512                        // TODO dhcp
     513                        net_free_settings(configuration, data);
     514                        return ENOTSUP;
     515                }else if(ip_netif->ipv == IPV4){
     516                        route = (ip_route_ref) malloc(sizeof(ip_route_t));
     517                        if(! route){
     518                                net_free_settings(configuration, data);
     519                                return ENOMEM;
     520                        }
     521                        route->address.s_addr = 0;
     522                        route->netmask.s_addr = 0;
     523                        route->gateway.s_addr = 0;
     524                        route->netif = ip_netif;
     525                        index = ip_routes_add(&ip_netif->routes, route);
     526                        if(index < 0){
     527                                net_free_settings(configuration, data);
     528                                free(route);
     529                                return index;
     530                        }
     531                        if(ERROR_OCCURRED(inet_pton(AF_INET, configuration[2].value, (uint8_t *) &route->address.s_addr))
     532                                || ERROR_OCCURRED(inet_pton(AF_INET, configuration[3].value, (uint8_t *) &route->netmask.s_addr))
     533                                || (inet_pton(AF_INET, configuration[4].value, (uint8_t *) &gateway.s_addr) == EINVAL)
     534                                || (inet_pton(AF_INET, configuration[5].value, (uint8_t *) &ip_netif->broadcast.s_addr) == EINVAL)){
     535                                net_free_settings(configuration, data);
     536                                return EINVAL;
     537                        }
     538                }else{
     539                        // TODO ipv6 in separate module
     540                        net_free_settings(configuration, data);
     541                        return ENOTSUP;
     542                }
     543                if(configuration[6].value){
     544                        ip_netif->arp = get_running_module(&ip_globals.modules, configuration[6].value);
     545                        if(! ip_netif->arp){
     546                                printf("Failed to start the arp %s\n", configuration[6].value);
     547                                net_free_settings(configuration, data);
     548                                return EINVAL;
     549                        }
     550                }
     551                if(configuration[7].value){
     552                        ip_netif->routing = (configuration[7].value[0] == 'y');
     553                }
     554                net_free_settings(configuration, data);
     555        }
     556        // binds the netif service which also initializes the device
     557        ip_netif->phone = nil_bind_service(ip_netif->service, (ipcarg_t) ip_netif->device_id, SERVICE_IP, ip_globals.client_connection);
     558        if(ip_netif->phone < 0){
     559                printf("Failed to contact the nil service %d\n", ip_netif->service);
     560                return ip_netif->phone;
     561        }
     562        // has to be after the device netif module initialization
     563        if(ip_netif->arp){
     564                if(route){
     565                        address.value = (char *) &route->address.s_addr;
     566                        address.length = CONVERT_SIZE(in_addr_t, char, 1);
     567                        ERROR_PROPAGATE(arp_device_req(ip_netif->arp->phone, ip_netif->device_id, SERVICE_IP, ip_netif->service, &address));
     568                }else{
     569                        ip_netif->arp = 0;
     570                }
     571        }
     572        // get packet dimensions
     573        ERROR_PROPAGATE(nil_packet_size_req(ip_netif->phone, ip_netif->device_id, &ip_netif->packet_dimension));
     574        if(ip_netif->packet_dimension.content < IP_MIN_CONTENT){
     575                printf("Maximum transmission unit %d bytes is too small, at least %d bytes are needed\n", ip_netif->packet_dimension.content, IP_MIN_CONTENT);
     576                ip_netif->packet_dimension.content = IP_MIN_CONTENT;
     577        }
     578        index = ip_netifs_add(&ip_globals.netifs, ip_netif->device_id, ip_netif);
     579        if(index < 0){
     580                return index;
     581        }
     582        if(gateway.s_addr){
     583                // the default gateway
     584                ip_globals.gateway.address.s_addr = 0;
     585                ip_globals.gateway.netmask.s_addr = 0;
     586                ip_globals.gateway.gateway.s_addr = gateway.s_addr;
     587                ip_globals.gateway.netif = ip_netif;
     588        }
     589        return EOK;
     590}
     591
     592int ip_mtu_changed_message(device_id_t device_id, size_t mtu){
     593        ip_netif_ref netif;
     594
     595        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     596        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     597        if(! netif){
     598                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     599                return ENOENT;
     600        }
     601        netif->packet_dimension.content = mtu;
     602        printf("%s: Device %d changed MTU to %d\n", NAME, device_id, mtu);
     603        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     604        return EOK;
     605}
     606
     607int ip_device_state_message(device_id_t device_id, device_state_t state){
     608        ip_netif_ref netif;
     609
     610        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     611        // find the device
     612        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     613        if(! netif){
     614                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     615                return ENOENT;
     616        }
     617        netif->state = state;
     618        printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
     619        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     620        return EOK;
     621}
     622
     623int ip_connect_module(services_t service){
     624        return EOK;
     625}
     626
     627int ip_bind_service(services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t received_msg){
     628        return ip_register(protocol, me, 0, received_msg);
     629}
     630
     631int ip_register(int protocol, services_t service, int phone, tl_received_msg_t received_msg){
     632        ip_proto_ref proto;
     633        int index;
     634
     635        if(!(protocol && service && ((phone > 0) || (received_msg)))){
     636                return EINVAL;
     637        }
     638        proto = (ip_proto_ref) malloc(sizeof(ip_protos_t));
     639        if(! proto){
     640                return ENOMEM;
     641        }
     642        proto->protocol = protocol;
     643        proto->service = service;
     644        proto->phone = phone;
     645        proto->received_msg = received_msg;
     646        fibril_rwlock_write_lock(&ip_globals.protos_lock);
     647        index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
     648        if(index < 0){
     649                fibril_rwlock_write_unlock(&ip_globals.protos_lock);
     650                free(proto);
     651                return index;
     652        }
     653       
     654        printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
     655            NAME, proto->protocol, proto->phone);
     656       
     657        fibril_rwlock_write_unlock(&ip_globals.protos_lock);
     658        return EOK;
     659}
     660
     661int ip_send_msg_local(int il_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error){
    1228662        ERROR_DECLARE;
    1229663
     
    1231665        ip_netif_ref netif;
    1232666        ip_route_ref route;
    1233         struct sockaddr *addr;
    1234         struct sockaddr_in *address_in;
    1235         in_addr_t *dest;
    1236         in_addr_t *src;
     667        struct sockaddr * addr;
     668        struct sockaddr_in * address_in;
     669//      struct sockaddr_in6 *   address_in6;
     670        in_addr_t * dest;
     671        in_addr_t * src;
    1237672        int phone;
    1238673
     
    1240675        // should be the next hop address or the target destination address
    1241676        addrlen = packet_get_addr(packet, NULL, (uint8_t **) &addr);
    1242         if (addrlen < 0)
     677        if(addrlen < 0){
    1243678                return ip_release_and_return(packet, addrlen);
    1244         if ((size_t) addrlen < sizeof(struct sockaddr))
     679        }
     680        if((size_t) addrlen < sizeof(struct sockaddr)){
    1245681                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 
     682        }
     683        switch(addr->sa_family){
     684                case AF_INET:
     685                        if(addrlen != sizeof(struct sockaddr_in)){
     686                                return ip_release_and_return(packet, EINVAL);
     687                        }
     688                        address_in = (struct sockaddr_in *) addr;
     689                        dest = &address_in->sin_addr;
     690                        if(! dest->s_addr){
     691                                dest->s_addr = IPV4_LOCALHOST_ADDRESS;
     692                        }
     693                        break;
     694                // TODO IPv6
     695/*              case AF_INET6:
     696                        if(addrlen != sizeof(struct sockaddr_in6)){
     697                                return EINVAL;
     698                        }
     699                        address_in6 = (struct sockaddr_in6 *) dest;
     700                        address_in6.sin6_addr.s6_addr;
     701                        IPV6_LOCALHOST_ADDRESS;
     702*/              default:
     703                        return ip_release_and_return(packet, EAFNOSUPPORT);
     704        }
    1261705        netif = NULL;
    1262706        route = NULL;
    1263707        fibril_rwlock_read_lock(&ip_globals.netifs_lock);
    1264 
    1265708        // device specified?
    1266         if (device_id > 0) {
     709        if(device_id > 0){
    1267710                netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1268711                route = ip_netif_find_route(netif, * dest);
    1269                 if (netif && !route && (ip_globals.gateway.netif == netif))
     712                if(netif && (! route) && (ip_globals.gateway.netif == netif)){
    1270713                        route = &ip_globals.gateway;
    1271         }
    1272 
    1273         if (!route) {
     714                }
     715        }
     716        if(! route){
    1274717                route = ip_find_route(*dest);
    1275718                netif = route ? route->netif : NULL;
    1276719        }
    1277         if (!netif || !route) {
     720        if(!(netif && route)){
    1278721                fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1279722                phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
    1280                 if (phone >= 0) {
     723                if(phone >= 0){
    1281724                        // unreachable ICMP if no routing
    1282                         icmp_destination_unreachable_msg(phone,
    1283                             ICMP_NET_UNREACH, 0, packet);
     725                        icmp_destination_unreachable_msg(phone, ICMP_NET_UNREACH, 0, packet);
    1284726                }
    1285727                return ENOENT;
    1286728        }
    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))) {
     729        if(error){
     730                // do not send for broadcast, anycast packets or network broadcast
     731                if((! dest->s_addr)
     732                        || (!(~ dest->s_addr))
     733                        || (!(~((dest->s_addr &(~ route->netmask.s_addr)) | route->netmask.s_addr)))
     734                        || (!(dest->s_addr &(~ route->netmask.s_addr)))){
    1295735                        return ip_release_and_return(packet, EINVAL);
    1296736                }
    1297737        }
    1298 
    1299738        // if the local host is the destination
    1300         if ((route->address.s_addr == dest->s_addr) &&
    1301             (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
     739        if((route->address.s_addr == dest->s_addr)
     740                && (dest->s_addr != IPV4_LOCALHOST_ADDRESS)){
    1302741                // find the loopback device to deliver
    1303742                dest->s_addr = IPV4_LOCALHOST_ADDRESS;
    1304743                route = ip_find_route(*dest);
    1305744                netif = route ? route->netif : NULL;
    1306                 if (!netif || !route) {
     745                if(!(netif && route)){
    1307746                        fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1308                         phone = ip_prepare_icmp_and_get_phone(error, packet,
    1309                             NULL);
    1310                         if (phone >= 0) {
     747                        phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
     748                        if(phone >= 0){
    1311749                                // unreachable ICMP if no routing
    1312                                 icmp_destination_unreachable_msg(phone,
    1313                                     ICMP_HOST_UNREACH, 0, packet);
     750                                icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
    1314751                        }
    1315752                        return ENOENT;
    1316753                }
    1317754        }
    1318        
    1319755        src = ip_netif_address(netif);
    1320         if (!src) {
     756        if(! src){
    1321757                fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1322758                return ip_release_and_return(packet, ENOENT);
    1323759        }
    1324 
    1325         ERROR_CODE = ip_send_route(packet, netif, route, src, *dest, error);
     760        ERROR_CODE = ip_send_route(packet, netif, route, src, * dest, error);
    1326761        fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1327 
    1328762        return ERROR_CODE;
    1329763}
    1330764
    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 
     765in_addr_t * ip_netif_address(ip_netif_ref netif){
     766        ip_route_ref route;
     767
     768        route = ip_routes_get_index(&netif->routes, 0);
     769        return route ? &route->address : NULL;
     770}
     771
     772int 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){
     773        ERROR_DECLARE;
     774
     775        measured_string_t destination;
     776        measured_string_ref translation;
     777        char * data;
     778        int phone;
     779
     780        // get destination hardware address
     781        if(netif->arp && (route->address.s_addr != dest.s_addr)){
     782                destination.value = route->gateway.s_addr ? (char *) &route->gateway.s_addr : (char *) &dest.s_addr;
     783                destination.length = CONVERT_SIZE(dest.s_addr, char, 1);
     784                if(ERROR_OCCURRED(arp_translate_req(netif->arp->phone, netif->device_id, SERVICE_IP, &destination, &translation, &data))){
     785//                      sleep(1);
     786//                      ERROR_PROPAGATE(arp_translate_req(netif->arp->phone, netif->device_id, SERVICE_IP, &destination, &translation, &data));
     787                        pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
     788                        return ERROR_CODE;
     789                }
     790                if(!(translation && translation->value)){
     791                        if(translation){
     792                                free(translation);
     793                                free(data);
     794                        }
     795                        phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
     796                        if(phone >= 0){
     797                                // unreachable ICMP if no routing
     798                                icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
     799                        }
     800                        return EINVAL;
     801                }
     802        }else translation = NULL;
     803        if(ERROR_OCCURRED(ip_prepare_packet(src, dest, packet, translation))){
     804                pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
     805        }else{
     806                packet = ip_split_packet(packet, netif->packet_dimension.prefix, netif->packet_dimension.content, netif->packet_dimension.suffix, netif->packet_dimension.addr_len, error);
     807                if(packet){
     808                        nil_send_msg(netif->phone, netif->device_id, packet, SERVICE_IP);
     809                }
     810        }
     811        if(translation){
     812                free(translation);
     813                free(data);
     814        }
     815        return ERROR_CODE;
     816}
     817
     818int ip_prepare_packet(in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination){
     819        ERROR_DECLARE;
     820
     821        size_t length;
     822        ip_header_ref header;
     823        ip_header_ref last_header;
     824        ip_header_ref middle_header;
     825        packet_t next;
     826
     827        length = packet_get_data_length(packet);
     828        if((length < sizeof(ip_header_t)) || (length > IP_MAX_CONTENT)){
     829                return EINVAL;
     830        }
     831        header = (ip_header_ref) packet_get_data(packet);
     832        if(destination){
     833                ERROR_PROPAGATE(packet_set_addr(packet, NULL, (uint8_t *) destination->value, CONVERT_SIZE(char, uint8_t, destination->length)));
     834        }else{
     835                ERROR_PROPAGATE(packet_set_addr(packet, NULL, NULL, 0));
     836        }
     837        header->version = IPV4;
     838        header->fragment_offset_high = 0;
     839        header->fragment_offset_low = 0;
     840        header->header_checksum = 0;
     841        if(source){
     842                header->source_address = source->s_addr;
     843        }
     844        header->destination_address = dest.s_addr;
     845        fibril_rwlock_write_lock(&ip_globals.lock);
     846        ++ ip_globals.packet_counter;
     847        header->identification = htons(ip_globals.packet_counter);
     848        fibril_rwlock_write_unlock(&ip_globals.lock);
     849//      length = packet_get_data_length(packet);
     850        if(pq_next(packet)){
     851                last_header = (ip_header_ref) malloc(IP_HEADER_LENGTH(header));
     852                if(! last_header){
     853                        return ENOMEM;
     854                }
     855                ip_create_last_header(last_header, header);
     856                next = pq_next(packet);
     857                while(pq_next(next)){
     858                        middle_header = (ip_header_ref) packet_prefix(next, IP_HEADER_LENGTH(last_header));
     859                        if(! middle_header){
     860                                return ENOMEM;
     861                        }
     862                        memcpy(middle_header, last_header, IP_HEADER_LENGTH(last_header));
     863                        header->flags |= IPFLAG_MORE_FRAGMENTS;
     864                        middle_header->total_length = htons(packet_get_data_length(next));
     865                        middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
     866                        middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
     867                        middle_header->header_checksum = IP_HEADER_CHECKSUM(middle_header);
     868                        if(destination){
     869                                ERROR_PROPAGATE(packet_set_addr(next, NULL, (uint8_t *) destination->value, CONVERT_SIZE(char, uint8_t, destination->length)));
     870                        }
     871                        length += packet_get_data_length(next);
     872                        next = pq_next(next);
     873                }
     874                middle_header = (ip_header_ref) packet_prefix(next, IP_HEADER_LENGTH(last_header));
     875                if(! middle_header){
     876                        return ENOMEM;
     877                }
     878                memcpy(middle_header, last_header, IP_HEADER_LENGTH(last_header));
     879                middle_header->total_length = htons(packet_get_data_length(next));
     880                middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
     881                middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
     882                middle_header->header_checksum = IP_HEADER_CHECKSUM(middle_header);
     883                if(destination){
     884                        ERROR_PROPAGATE(packet_set_addr(next, NULL, (uint8_t *) destination->value, CONVERT_SIZE(char, uint8_t, destination->length)));
     885                }
     886                length += packet_get_data_length(next);
     887                free(last_header);
     888                header->flags |= IPFLAG_MORE_FRAGMENTS;
     889        }
     890        header->total_length = htons(length);
     891        // unnecessary for all protocols
     892        header->header_checksum = IP_HEADER_CHECKSUM(header);
    1391893        return EOK;
    1392894}
    1393895
    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)
     896int ip_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     897    ipc_call_t *answer, int * answer_count)
    1868898{
    1869899        ERROR_DECLARE;
     
    1881911        *answer_count = 0;
    1882912        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;
     913                case IPC_M_PHONE_HUNGUP:
     914                        return EOK;
     915                case NET_IL_DEVICE:
     916                        return ip_device_req_local(0, IPC_GET_DEVICE(call),
     917                            IPC_GET_SERVICE(call));
     918                case IPC_M_CONNECT_TO_ME:
     919                        return ip_register(IL_GET_PROTO(call), IL_GET_SERVICE(call),
     920                            IPC_GET_PHONE(call), NULL);
     921                case NET_IL_SEND:
     922                        ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, &packet,
     923                            IPC_GET_PACKET(call)));
     924                        return ip_send_msg_local(0, IPC_GET_DEVICE(call), packet, 0,
     925                            IPC_GET_ERROR(call));
     926                case NET_IL_DEVICE_STATE:
     927                        return ip_device_state_message(IPC_GET_DEVICE(call),
     928                            IPC_GET_STATE(call));
     929                case NET_IL_RECEIVED:
     930                        ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, &packet,
     931                            IPC_GET_PACKET(call)));
     932                        return ip_receive_message(IPC_GET_DEVICE(call), packet);
     933                case NET_IP_RECEIVED_ERROR:
     934                        ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, &packet,
     935                            IPC_GET_PACKET(call)));
     936                        return ip_received_error_msg_local(0, IPC_GET_DEVICE(call), packet,
     937                            IPC_GET_TARGET(call), IPC_GET_ERROR(call));
     938                case NET_IP_ADD_ROUTE:
     939                        return ip_add_route_req_local(0, IPC_GET_DEVICE(call),
     940                            IP_GET_ADDRESS(call), IP_GET_NETMASK(call), IP_GET_GATEWAY(call));
     941                case NET_IP_SET_GATEWAY:
     942                        return ip_set_gateway_req_local(0, IPC_GET_DEVICE(call),
     943                            IP_GET_GATEWAY(call));
     944                case NET_IP_GET_ROUTE:
     945                        ERROR_PROPAGATE(data_receive((void **) &addr, &addrlen));
     946                        ERROR_PROPAGATE(ip_get_route_req_local(0, IP_GET_PROTOCOL(call),
     947                            addr, (socklen_t) addrlen, &device_id, &header, &headerlen));
     948                        IPC_SET_DEVICE(answer, device_id);
     949                        IP_SET_HEADERLEN(answer, headerlen);
    1933950                       
    1934                 if (ERROR_NONE(data_reply(&headerlen, sizeof(headerlen))))
    1935                         ERROR_CODE = data_reply(header, headerlen);
     951                        *answer_count = 2;
    1936952                       
    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));
     953                        if (!ERROR_OCCURRED(data_reply(&headerlen, sizeof(headerlen))))
     954                                ERROR_CODE = data_reply(header, headerlen);
     955                       
     956                        free(header);
     957                        return ERROR_CODE;
     958                case NET_IL_PACKET_SPACE:
     959                        ERROR_PROPAGATE(ip_packet_size_message(IPC_GET_DEVICE(call),
     960                            &addrlen, &prefix, &content, &suffix));
     961                        IPC_SET_ADDR(answer, addrlen);
     962                        IPC_SET_PREFIX(answer, prefix);
     963                        IPC_SET_CONTENT(answer, content);
     964                        IPC_SET_SUFFIX(answer, suffix);
     965                        *answer_count = 4;
     966                        return EOK;
     967                case NET_IL_MTU_CHANGED:
     968                        return ip_mtu_changed_message(IPC_GET_DEVICE(call),
     969                            IPC_GET_MTU(call));
    1953970        }
    1954971       
     
    1956973}
    1957974
     975int ip_packet_size_req_local(int ip_phone, device_id_t device_id,
     976    packet_dimension_ref packet_dimension)
     977{
     978        if (!packet_dimension)
     979                return EBADMEM;
     980       
     981        return ip_packet_size_message(device_id, &packet_dimension->addr_len,
     982            &packet_dimension->prefix, &packet_dimension->content,
     983            &packet_dimension->suffix);
     984}
     985
     986int ip_packet_size_message(device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix){
     987        ip_netif_ref netif;
     988        int index;
     989
     990        if(!(addr_len && prefix && content && suffix)){
     991                return EBADMEM;
     992        }
     993        *content = IP_MAX_CONTENT - IP_PREFIX;
     994        fibril_rwlock_read_lock(&ip_globals.netifs_lock);
     995        if(device_id < 0){
     996                *addr_len = IP_ADDR;
     997                *prefix = 0;
     998                *suffix = 0;
     999                for(index = ip_netifs_count(&ip_globals.netifs) - 1; index >= 0; -- index){
     1000                        netif = ip_netifs_get_index(&ip_globals.netifs, index);
     1001                        if(netif){
     1002                                if(netif->packet_dimension.addr_len > * addr_len){
     1003                                        *addr_len = netif->packet_dimension.addr_len;
     1004                                }
     1005                                if(netif->packet_dimension.prefix > * prefix){
     1006                                        *prefix = netif->packet_dimension.prefix;
     1007                                }
     1008                                if(netif->packet_dimension.suffix > * suffix){
     1009                                        *suffix = netif->packet_dimension.suffix;
     1010                                }
     1011                        }
     1012                }
     1013                *prefix = * prefix + IP_PREFIX;
     1014                *suffix = * suffix + IP_SUFFIX;
     1015        }else{
     1016                netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1017                if(! netif){
     1018                        fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
     1019                        return ENOENT;
     1020                }
     1021                *addr_len = (netif->packet_dimension.addr_len > IP_ADDR) ? netif->packet_dimension.addr_len : IP_ADDR;
     1022                *prefix = netif->packet_dimension.prefix + IP_PREFIX;
     1023                *suffix = netif->packet_dimension.suffix + IP_SUFFIX;
     1024        }
     1025        fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
     1026        return EOK;
     1027}
     1028
     1029int 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){
     1030        ip_route_ref route;
     1031        ip_netif_ref netif;
     1032        int index;
     1033
     1034        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     1035        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1036        if(! netif){
     1037                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1038                return ENOENT;
     1039        }
     1040        route = (ip_route_ref) malloc(sizeof(ip_route_t));
     1041        if(! route){
     1042                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1043                return ENOMEM;
     1044        }
     1045        route->address.s_addr = address.s_addr;
     1046        route->netmask.s_addr = netmask.s_addr;
     1047        route->gateway.s_addr = gateway.s_addr;
     1048        route->netif = netif;
     1049        index = ip_routes_add(&netif->routes, route);
     1050        if(index < 0){
     1051                free(route);
     1052        }
     1053        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1054        return index;
     1055}
     1056
     1057ip_route_ref ip_find_route(in_addr_t destination){
     1058        int index;
     1059        ip_route_ref route;
     1060        ip_netif_ref netif;
     1061
     1062        // start with the last netif - the newest one
     1063        index = ip_netifs_count(&ip_globals.netifs) - 1;
     1064        while(index >= 0){
     1065                netif = ip_netifs_get_index(&ip_globals.netifs, index);
     1066                if(netif && (netif->state == NETIF_ACTIVE)){
     1067                        route = ip_netif_find_route(netif, destination);
     1068                        if(route){
     1069                                return route;
     1070                        }
     1071                }
     1072                -- index;
     1073        }
     1074        return &ip_globals.gateway;
     1075}
     1076
     1077ip_route_ref ip_netif_find_route(ip_netif_ref netif, in_addr_t destination){
     1078        int index;
     1079        ip_route_ref route;
     1080
     1081        if(netif){
     1082                // start with the first one - the direct route
     1083                for(index = 0; index < ip_routes_count(&netif->routes); ++ index){
     1084                        route = ip_routes_get_index(&netif->routes, index);
     1085                        if(route && ((route->address.s_addr &route->netmask.s_addr) == (destination.s_addr &route->netmask.s_addr))){
     1086                                return route;
     1087                        }
     1088                }
     1089        }
     1090        return NULL;
     1091}
     1092
     1093int ip_set_gateway_req_local(int ip_phone, device_id_t device_id, in_addr_t gateway)
     1094{
     1095        ip_netif_ref netif;
     1096
     1097        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     1098        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1099        if(! netif){
     1100                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1101                return ENOENT;
     1102        }
     1103        ip_globals.gateway.address.s_addr = 0;
     1104        ip_globals.gateway.netmask.s_addr = 0;
     1105        ip_globals.gateway.gateway.s_addr = gateway.s_addr;
     1106        ip_globals.gateway.netif = netif;
     1107        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1108        return EOK;
     1109}
     1110
     1111packet_t ip_split_packet(packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error){
     1112        size_t length;
     1113        packet_t next;
     1114        packet_t new_packet;
     1115        int result;
     1116        int phone;
     1117
     1118        next = packet;
     1119        // check all packets
     1120        while(next){
     1121                length = packet_get_data_length(next);
     1122                // too long?
     1123                if(length > content){
     1124                        result = ip_fragment_packet(next, content, prefix, suffix, addr_len);
     1125                        if(result != EOK){
     1126                                new_packet = pq_detach(next);
     1127                                if(next == packet){
     1128                                        // the new first packet of the queue
     1129                                        packet = new_packet;
     1130                                }
     1131                                // fragmentation needed?
     1132                                if(result == EPERM){
     1133                                        phone = ip_prepare_icmp_and_get_phone(error, next, NULL);
     1134                                        if(phone >= 0){
     1135                                                // fragmentation necessary ICMP
     1136                                                icmp_destination_unreachable_msg(phone, ICMP_FRAG_NEEDED, content, next);
     1137                                        }
     1138                                }else{
     1139                                        pq_release_remote(ip_globals.net_phone, packet_get_id(next));
     1140                                }
     1141                                next = new_packet;
     1142                                continue;
     1143                        }
     1144                }
     1145                next = pq_next(next);
     1146        }
     1147        return packet;
     1148}
     1149
     1150int ip_fragment_packet(packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len){
     1151        ERROR_DECLARE;
     1152
     1153        packet_t new_packet;
     1154        ip_header_ref header;
     1155        ip_header_ref middle_header;
     1156        ip_header_ref last_header;
     1157        struct sockaddr * src;
     1158        struct sockaddr * dest;
     1159        socklen_t addrlen;
     1160        int result;
     1161
     1162        result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
     1163        if(result <= 0){
     1164                return EINVAL;
     1165        }
     1166        addrlen = (socklen_t) result;
     1167        if(packet_get_data_length(packet) <= sizeof(ip_header_t)){
     1168                return ENOMEM;
     1169        }
     1170        // get header
     1171        header = (ip_header_ref) packet_get_data(packet);
     1172        if(! header){
     1173                return EINVAL;
     1174        }
     1175        // fragmentation forbidden?
     1176        if(header->flags &IPFLAG_DONT_FRAGMENT){
     1177                return EPERM;
     1178        }
     1179        // create the last fragment
     1180        new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length, suffix, ((addrlen > addr_len) ? addrlen : addr_len));
     1181        if(! new_packet){
     1182                return ENOMEM;
     1183        }
     1184        // allocate as much as originally
     1185        last_header = (ip_header_ref) packet_suffix(new_packet, IP_HEADER_LENGTH(header));
     1186        if(! last_header){
     1187                return ip_release_and_return(packet, ENOMEM);
     1188        }
     1189        ip_create_last_header(last_header, header);
     1190        // trim the unused space
     1191        if(ERROR_OCCURRED(packet_trim(new_packet, 0, IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header)))){
     1192                return ip_release_and_return(packet, ERROR_CODE);
     1193        }
     1194        // biggest multiple of 8 lower than content
     1195        // TODO even fragmentation?
     1196        length = length &(~ 0x7);// (content / 8) * 8
     1197        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))){
     1198                return ip_release_and_return(packet, ERROR_CODE);
     1199        }
     1200        // mark the first as fragmented
     1201        header->flags |= IPFLAG_MORE_FRAGMENTS;
     1202        // create middle framgents
     1203        while(IP_TOTAL_LENGTH(header) > length){
     1204                new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length, suffix, ((addrlen >= addr_len) ? addrlen : addr_len));
     1205                if(! new_packet){
     1206                        return ENOMEM;
     1207                }
     1208                middle_header = ip_create_middle_header(new_packet, last_header);
     1209                if(! middle_header){
     1210                        return ip_release_and_return(packet, ENOMEM);
     1211                }
     1212                if(ERROR_OCCURRED(ip_fragment_packet_data(packet, new_packet, header, middle_header, (length - IP_HEADER_LENGTH(middle_header)) &(~ 0x7), src, dest, addrlen))){
     1213                        return ip_release_and_return(packet, ERROR_CODE);
     1214                }
     1215        }
     1216        // finish the first fragment
     1217        header->header_checksum = IP_HEADER_CHECKSUM(header);
     1218        return EOK;
     1219}
     1220
     1221int 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){
     1222        ERROR_DECLARE;
     1223
     1224        void * data;
     1225        size_t offset;
     1226
     1227        data = packet_suffix(new_packet, length);
     1228        if(! data){
     1229                return ENOMEM;
     1230        }
     1231        memcpy(data, ((void *) header) + IP_TOTAL_LENGTH(header) - length, length);
     1232        ERROR_PROPAGATE(packet_trim(packet, 0, length));
     1233        header->total_length = htons(IP_TOTAL_LENGTH(header) - length);
     1234        new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
     1235        offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);
     1236        new_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset);
     1237        new_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
     1238        new_header->header_checksum = IP_HEADER_CHECKSUM(new_header);
     1239        ERROR_PROPAGATE(packet_set_addr(new_packet, (const uint8_t *) src, (const uint8_t *) dest, addrlen));
     1240        return pq_insert_after(packet, new_packet);
     1241}
     1242
     1243ip_header_ref ip_create_middle_header(packet_t packet, ip_header_ref last){
     1244        ip_header_ref middle;
     1245
     1246        middle = (ip_header_ref) packet_suffix(packet, IP_HEADER_LENGTH(last));
     1247        if(! middle){
     1248                return NULL;
     1249        }
     1250        memcpy(middle, last, IP_HEADER_LENGTH(last));
     1251        middle->flags |= IPFLAG_MORE_FRAGMENTS;
     1252        return middle;
     1253}
     1254
     1255void ip_create_last_header(ip_header_ref last, ip_header_ref first){
     1256        ip_option_ref option;
     1257        size_t next;
     1258        size_t length;
     1259
     1260        // copy first itself
     1261        memcpy(last, first, sizeof(ip_header_t));
     1262        length = sizeof(ip_header_t);
     1263        next = sizeof(ip_header_t);
     1264        // process all ip options
     1265        while(next < first->header_length){
     1266                option = (ip_option_ref) (((uint8_t *) first) + next);
     1267                // skip end or noop
     1268                if((option->type == IPOPT_END) || (option->type == IPOPT_NOOP)){
     1269                        ++ next;
     1270                }else{
     1271                        // copy if said so or skip
     1272                        if(IPOPT_COPIED(option->type)){
     1273                                memcpy(((uint8_t *) last) + length, ((uint8_t *) first) + next, option->length);
     1274                                length += option->length;
     1275                        }
     1276                        // next option
     1277                        next += option->length;
     1278                }
     1279        }
     1280        // align 4 byte boundary
     1281        if(length % 4){
     1282                bzero(((uint8_t *) last) + length, 4 - (length % 4));
     1283                last->header_length = length / 4 + 1;
     1284        }else{
     1285                last->header_length = length / 4;
     1286        }
     1287        last->header_checksum = 0;
     1288}
     1289
     1290int ip_receive_message(device_id_t device_id, packet_t packet){
     1291        packet_t next;
     1292
     1293        do{
     1294                next = pq_detach(packet);
     1295                ip_process_packet(device_id, packet);
     1296                packet = next;
     1297        }while(packet);
     1298        return EOK;
     1299}
     1300
     1301int ip_process_packet(device_id_t device_id, packet_t packet){
     1302        ERROR_DECLARE;
     1303
     1304        ip_header_ref header;
     1305        in_addr_t dest;
     1306        ip_route_ref route;
     1307        int phone;
     1308        struct sockaddr * addr;
     1309        struct sockaddr_in addr_in;
     1310//      struct sockaddr_in      addr_in6;
     1311        socklen_t addrlen;
     1312
     1313        header = (ip_header_ref) packet_get_data(packet);
     1314        if(! header){
     1315                return ip_release_and_return(packet, ENOMEM);
     1316        }
     1317        // checksum
     1318        if((header->header_checksum) && (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)){
     1319                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1320                if(phone >= 0){
     1321                        // checksum error ICMP
     1322                        icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER, ((size_t) ((void *) &header->header_checksum)) - ((size_t) ((void *) header)), packet);
     1323                }
     1324                return EINVAL;
     1325        }
     1326        if(header->ttl <= 1){
     1327                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1328                if(phone >= 0){
     1329                        // ttl oxceeded ICMP
     1330                        icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
     1331                }
     1332                return EINVAL;
     1333        }
     1334        // process ipopt and get destination
     1335        dest = ip_get_destination(header);
     1336        // set the addrination address
     1337        switch(header->version){
     1338                case IPVERSION:
     1339                        addrlen = sizeof(addr_in);
     1340                        bzero(&addr_in, addrlen);
     1341                        addr_in.sin_family = AF_INET;
     1342                        memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
     1343                        addr = (struct sockaddr *) &addr_in;
     1344                        break;
     1345/*              case IPv6VERSION:
     1346                        addrlen = sizeof(dest_in6);
     1347                        bzero(&dest_in6, addrlen);
     1348                        dest_in6.sin6_family = AF_INET6;
     1349                        memcpy(&dest_in6.sin6_addr.s6_addr,);
     1350                        dest = (struct sockaddr *) &dest_in;
     1351                        break;
     1352*/              default:
     1353                        return ip_release_and_return(packet, EAFNOSUPPORT);
     1354        }
     1355        ERROR_PROPAGATE(packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen));
     1356        route = ip_find_route(dest);
     1357        if(! route){
     1358                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1359                if(phone >= 0){
     1360                        // unreachable ICMP
     1361                        icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
     1362                }
     1363                return ENOENT;
     1364        }
     1365        if(route->address.s_addr == dest.s_addr){
     1366                // local delivery
     1367                return ip_deliver_local(device_id, packet, header, 0);
     1368        }else{
     1369                // only if routing enabled
     1370                if(route->netif->routing){
     1371                        -- header->ttl;
     1372                        return ip_send_route(packet, route->netif, route, NULL, dest, 0);
     1373                }else{
     1374                        phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1375                        if(phone >= 0){
     1376                                // unreachable ICMP if no routing
     1377                                icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
     1378                        }
     1379                        return ENOENT;
     1380                }
     1381        }
     1382}
     1383
     1384/** Notify the IP module about the received error notification packet.
     1385 *
     1386 * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
     1387 * @param[in] device_id The device identifier.
     1388 * @param[in] packet    The received packet or the received packet queue.
     1389 * @param[in] target    The target internetwork module service to be
     1390 *                      delivered to.
     1391 * @param[in] error     The packet error reporting service. Prefixes the
     1392 *                      received packet.
     1393 *
     1394 * @return EOK on success.
     1395 *
     1396 */
     1397int ip_received_error_msg_local(int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error){
     1398        uint8_t * data;
     1399        int offset;
     1400        icmp_type_t type;
     1401        icmp_code_t code;
     1402        ip_netif_ref netif;
     1403        measured_string_t address;
     1404        ip_route_ref route;
     1405        ip_header_ref header;
     1406
     1407        switch(error){
     1408                case SERVICE_ICMP:
     1409                        offset = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
     1410                        if(offset < 0){
     1411                                return ip_release_and_return(packet, ENOMEM);
     1412                        }
     1413                        data = packet_get_data(packet);
     1414                        header = (ip_header_ref)(data + offset);
     1415                        // destination host unreachable?
     1416                        if((type == ICMP_DEST_UNREACH) && (code == ICMP_HOST_UNREACH)){
     1417                                fibril_rwlock_read_lock(&ip_globals.netifs_lock);
     1418                                netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1419                                if(netif && netif->arp){
     1420                                        route = ip_routes_get_index(&netif->routes, 0);
     1421                                        // from the same network?
     1422                                        if(route && ((route->address.s_addr &route->netmask.s_addr) == (header->destination_address &route->netmask.s_addr))){
     1423                                                // clear the ARP mapping if any
     1424                                                address.value = (char *) &header->destination_address;
     1425                                                address.length = CONVERT_SIZE(uint8_t, char, sizeof(header->destination_address));
     1426                                                arp_clear_address_req(netif->arp->phone, netif->device_id, SERVICE_IP, &address);
     1427                                        }
     1428                                }
     1429                                fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
     1430                        }
     1431                        break;
     1432                default:
     1433                        return ip_release_and_return(packet, ENOTSUP);
     1434        }
     1435        return ip_deliver_local(device_id, packet, header, error);
     1436}
     1437
     1438int ip_deliver_local(device_id_t device_id, packet_t packet, ip_header_ref header, services_t error){
     1439        ERROR_DECLARE;
     1440
     1441        ip_proto_ref proto;
     1442        int phone;
     1443        services_t service;
     1444        tl_received_msg_t received_msg;
     1445        struct sockaddr * src;
     1446        struct sockaddr * dest;
     1447        struct sockaddr_in src_in;
     1448        struct sockaddr_in dest_in;
     1449//      struct sockaddr_in      src_in6;
     1450//      struct sockaddr_in      dest_in6;
     1451        socklen_t addrlen;
     1452
     1453        if((header->flags &IPFLAG_MORE_FRAGMENTS) || IP_FRAGMENT_OFFSET(header)){
     1454                // TODO fragmented
     1455                return ENOTSUP;
     1456        }else{
     1457                switch(header->version){
     1458                        case IPVERSION:
     1459                                addrlen = sizeof(src_in);
     1460                                bzero(&src_in, addrlen);
     1461                                src_in.sin_family = AF_INET;
     1462                                memcpy(&dest_in, &src_in, addrlen);
     1463                                memcpy(&src_in.sin_addr.s_addr, &header->source_address, sizeof(header->source_address));
     1464                                memcpy(&dest_in.sin_addr.s_addr, &header->destination_address, sizeof(header->destination_address));
     1465                                src = (struct sockaddr *) &src_in;
     1466                                dest = (struct sockaddr *) &dest_in;
     1467                                break;
     1468/*                      case IPv6VERSION:
     1469                                addrlen = sizeof(src_in6);
     1470                                bzero(&src_in6, addrlen);
     1471                                src_in6.sin6_family = AF_INET6;
     1472                                memcpy(&dest_in6, &src_in6, addrlen);
     1473                                memcpy(&src_in6.sin6_addr.s6_addr,);
     1474                                memcpy(&dest_in6.sin6_addr.s6_addr,);
     1475                                src = (struct sockaddr *) &src_in;
     1476                                dest = (struct sockaddr *) &dest_in;
     1477                                break;
     1478*/                      default:
     1479                                return ip_release_and_return(packet, EAFNOSUPPORT);
     1480                }
     1481                if(ERROR_OCCURRED(packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest, addrlen))){
     1482                        return ip_release_and_return(packet, ERROR_CODE);
     1483                }
     1484                // trim padding if present
     1485                if((! error) && (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))){
     1486                        if(ERROR_OCCURRED(packet_trim(packet, 0, packet_get_data_length(packet) - IP_TOTAL_LENGTH(header)))){
     1487                                return ip_release_and_return(packet, ERROR_CODE);
     1488                        }
     1489                }
     1490                fibril_rwlock_read_lock(&ip_globals.protos_lock);
     1491                proto = ip_protos_find(&ip_globals.protos, header->protocol);
     1492                if(! proto){
     1493                        fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1494                        phone = ip_prepare_icmp_and_get_phone(error, packet, header);
     1495                        if(phone >= 0){
     1496                                // unreachable ICMP
     1497                                icmp_destination_unreachable_msg(phone, ICMP_PROT_UNREACH, 0, packet);
     1498                        }
     1499                        return ENOENT;
     1500                }
     1501                if(proto->received_msg){
     1502                        service = proto->service;
     1503                        received_msg = proto->received_msg;
     1504                        fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1505                        ERROR_CODE = received_msg(device_id, packet, service, error);
     1506                }else{
     1507                        ERROR_CODE = tl_received_msg(proto->phone, device_id, packet, proto->service, error);
     1508                        fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1509                }
     1510                return ERROR_CODE;
     1511        }
     1512}
     1513
     1514in_addr_t ip_get_destination(ip_header_ref header){
     1515        in_addr_t destination;
     1516
     1517        // TODO search set ipopt route?
     1518        destination.s_addr = header->destination_address;
     1519        return destination;
     1520}
     1521
     1522int ip_prepare_icmp(packet_t packet, ip_header_ref header){
     1523        packet_t next;
     1524        struct sockaddr * dest;
     1525        struct sockaddr_in dest_in;
     1526//      struct sockaddr_in      dest_in6;
     1527        socklen_t addrlen;
     1528
     1529        // detach the first packet and release the others
     1530        next = pq_detach(packet);
     1531        if(next){
     1532                pq_release_remote(ip_globals.net_phone, packet_get_id(next));
     1533        }
     1534        if(! header){
     1535                if(packet_get_data_length(packet) <= sizeof(ip_header_t)){
     1536                        return ENOMEM;
     1537                }
     1538                // get header
     1539                header = (ip_header_ref) packet_get_data(packet);
     1540                if(! header){
     1541                        return EINVAL;
     1542                }
     1543        }
     1544        // only for the first fragment
     1545        if(IP_FRAGMENT_OFFSET(header)){
     1546                return EINVAL;
     1547        }
     1548        // not for the ICMP protocol
     1549        if(header->protocol == IPPROTO_ICMP){
     1550                return EPERM;
     1551        }
     1552        // set the destination address
     1553        switch(header->version){
     1554                case IPVERSION:
     1555                        addrlen = sizeof(dest_in);
     1556                        bzero(&dest_in, addrlen);
     1557                        dest_in.sin_family = AF_INET;
     1558                        memcpy(&dest_in.sin_addr.s_addr, &header->source_address, sizeof(header->source_address));
     1559                        dest = (struct sockaddr *) &dest_in;
     1560                        break;
     1561/*              case IPv6VERSION:
     1562                        addrlen = sizeof(dest_in6);
     1563                        bzero(&dest_in6, addrlen);
     1564                        dest_in6.sin6_family = AF_INET6;
     1565                        memcpy(&dest_in6.sin6_addr.s6_addr,);
     1566                        dest = (struct sockaddr *) &dest_in;
     1567                        break;
     1568*/              default:
     1569                        return EAFNOSUPPORT;
     1570        }
     1571        return packet_set_addr(packet, NULL, (uint8_t *) dest, addrlen);
     1572}
     1573
     1574int ip_get_icmp_phone(void){
     1575        ip_proto_ref proto;
     1576        int phone;
     1577
     1578        fibril_rwlock_read_lock(&ip_globals.protos_lock);
     1579        proto = ip_protos_find(&ip_globals.protos, IPPROTO_ICMP);
     1580        phone = proto ? proto->phone : ENOENT;
     1581        fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1582        return phone;
     1583}
     1584
     1585int ip_prepare_icmp_and_get_phone(services_t error, packet_t packet, ip_header_ref header){
     1586        int phone;
     1587
     1588        phone = ip_get_icmp_phone();
     1589        if(error || (phone < 0) || ip_prepare_icmp(packet, header)){
     1590                return ip_release_and_return(packet, EINVAL);
     1591        }
     1592        return phone;
     1593}
     1594
     1595int ip_release_and_return(packet_t packet, int result){
     1596        pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
     1597        return result;
     1598}
     1599
     1600int 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){
     1601        struct sockaddr_in * address_in;
     1602//      struct sockaddr_in6 *   address_in6;
     1603        in_addr_t * dest;
     1604        in_addr_t * src;
     1605        ip_route_ref route;
     1606        ipv4_pseudo_header_ref header_in;
     1607
     1608        if(!(destination && (addrlen > 0))){
     1609                return EINVAL;
     1610        }
     1611        if(!(device_id && header && headerlen)){
     1612                return EBADMEM;
     1613        }
     1614        if((size_t) addrlen < sizeof(struct sockaddr)){
     1615                return EINVAL;
     1616        }
     1617        switch(destination->sa_family){
     1618                case AF_INET:
     1619                        if(addrlen != sizeof(struct sockaddr_in)){
     1620                                return EINVAL;
     1621                        }
     1622                        address_in = (struct sockaddr_in *) destination;
     1623                        dest = &address_in->sin_addr;
     1624                        if(! dest->s_addr){
     1625                                dest->s_addr = IPV4_LOCALHOST_ADDRESS;
     1626                        }
     1627                        break;
     1628                // TODO IPv6
     1629/*              case AF_INET6:
     1630                        if(addrlen != sizeof(struct sockaddr_in6)){
     1631                                return EINVAL;
     1632                        }
     1633                        address_in6 = (struct sockaddr_in6 *) dest;
     1634                        address_in6.sin6_addr.s6_addr;
     1635*/              default:
     1636                        return EAFNOSUPPORT;
     1637        }
     1638        fibril_rwlock_read_lock(&ip_globals.lock);
     1639        route = ip_find_route(*dest);
     1640        // if the local host is the destination
     1641        if(route && (route->address.s_addr == dest->s_addr)
     1642                && (dest->s_addr != IPV4_LOCALHOST_ADDRESS)){
     1643                // find the loopback device to deliver
     1644                dest->s_addr = IPV4_LOCALHOST_ADDRESS;
     1645                route = ip_find_route(*dest);
     1646        }
     1647        if(!(route && route->netif)){
     1648                fibril_rwlock_read_unlock(&ip_globals.lock);
     1649                return ENOENT;
     1650        }
     1651        *device_id = route->netif->device_id;
     1652        src = ip_netif_address(route->netif);
     1653        fibril_rwlock_read_unlock(&ip_globals.lock);
     1654        *headerlen = sizeof(*header_in);
     1655        header_in = (ipv4_pseudo_header_ref) malloc(*headerlen);
     1656        if(! header_in){
     1657                return ENOMEM;
     1658        }
     1659        bzero(header_in, * headerlen);
     1660        header_in->destination_address = dest->s_addr;
     1661        header_in->source_address = src->s_addr;
     1662        header_in->protocol = protocol;
     1663        header_in->data_length = 0;
     1664        *header = header_in;
     1665        return EOK;
     1666}
     1667
    19581668/** Default thread for new connections.
    19591669 *
    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)
     1670 *  @param[in] iid The initial message identifier.
     1671 *  @param[in] icall The initial message call structure.
     1672 *
     1673 */
     1674static void il_client_connection(ipc_callid_t iid, ipc_call_t * icall)
    19641675{
    19651676        /*
     
    19691680        ipc_answer_0(iid, EOK);
    19701681       
    1971         while (true) {
     1682        while(true) {
    19721683                ipc_call_t answer;
    19731684                int answer_count;
     
    19841695                    &answer_count);
    19851696               
    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)) {
     1697                /* End if said to either by the message or the processing result */
     1698                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
    19921699                        return;
    1993                 }
    19941700               
    19951701                /* Answer the message */
     
    20001706/** Starts the module.
    20011707 *
    2002  * @returns EOK on success.
    2003  * @returns Other error codes as defined for each specific module start function.
     1708 *  @param argc The count of the command line arguments. Ignored parameter.
     1709 *  @param argv The command line parameters. Ignored parameter.
     1710 *
     1711 *  @returns EOK on success.
     1712 *  @returns Other error codes as defined for each specific module start function.
     1713 *
    20041714 */
    20051715int main(int argc, char *argv[])
     
    20081718       
    20091719        /* Start the module */
    2010         ERROR_PROPAGATE(il_module_start_standalone(il_client_connection));
     1720        if (ERROR_OCCURRED(il_module_start_standalone(il_client_connection)))
     1721                return ERROR_CODE;
     1722       
    20111723        return EOK;
    20121724}
Note: See TracChangeset for help on using the changeset viewer.