Ignore:
File:
1 edited

Legend:

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

    r014dd57b r774e6d1a  
    3535 * @see arp.h
    3636 */
     37
     38#include "ip.h"
     39#include "ip_module.h"
    3740
    3841#include <async.h>
     
    4952#include <sys/types.h>
    5053#include <byteorder.h>
    51 #include "ip.h"
    5254
    5355#include <adt/measured_strings.h>
     
    6870#include <icmp_client.h>
    6971#include <icmp_interface.h>
     72#include <il_interface.h>
    7073#include <ip_client.h>
    7174#include <ip_interface.h>
    7275#include <ip_header.h>
    7376#include <net_interface.h>
    74 #include <nil_remote.h>
    75 #include <tl_remote.h>
     77#include <nil_interface.h>
     78#include <tl_interface.h>
    7679#include <packet_remote.h>
    77 #include <il_remote.h>
    78 #include <il_skel.h>
     80#include <il_local.h>
    7981
    8082/** IP module name. */
     
    120122INT_MAP_IMPLEMENT(ip_protos, ip_proto_t);
    121123GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t);
    122 
    123 static void ip_receiver(ipc_callid_t, ipc_call_t *);
    124124
    125125/** Releases the packet and returns the result.
     
    244244}
    245245
    246 int il_initialize(int net_phone)
    247 {
     246/** Initializes the IP module.
     247 *
     248 * @param[in] client_connection The client connection processing function. The
     249 *                      module skeleton propagates its own one.
     250 * @return              EOK on success.
     251 * @return              ENOMEM if there is not enough memory left.
     252 */
     253int ip_initialize(async_client_conn_t client_connection)
     254{
     255        int rc;
     256
    248257        fibril_rwlock_initialize(&ip_globals.lock);
    249258        fibril_rwlock_write_lock(&ip_globals.lock);
    250259        fibril_rwlock_initialize(&ip_globals.protos_lock);
    251260        fibril_rwlock_initialize(&ip_globals.netifs_lock);
    252        
    253         ip_globals.net_phone = net_phone;
    254261        ip_globals.packet_counter = 0;
    255262        ip_globals.gateway.address.s_addr = 0;
     
    257264        ip_globals.gateway.gateway.s_addr = 0;
    258265        ip_globals.gateway.netif = NULL;
    259        
    260         int rc = ip_netifs_initialize(&ip_globals.netifs);
     266        ip_globals.client_connection = client_connection;
     267       
     268        rc = ip_netifs_initialize(&ip_globals.netifs);
    261269        if (rc != EOK)
    262270                goto out;
     
    423431        ip_netif->phone = nil_bind_service(ip_netif->service,
    424432            (sysarg_t) ip_netif->device_id, SERVICE_IP,
    425             ip_receiver);
     433            ip_globals.client_connection);
    426434        if (ip_netif->phone < 0) {
    427435                printf("Failed to contact the nil service %d\n",
     
    479487}
    480488
    481 static int ip_device_req_local(int il_phone, device_id_t device_id,
    482     services_t netif)
    483 {
    484         ip_netif_t *ip_netif;
    485         ip_route_t *route;
    486         int index;
    487         int rc;
    488 
    489         ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t));
    490         if (!ip_netif)
    491                 return ENOMEM;
    492 
    493         rc = ip_routes_initialize(&ip_netif->routes);
    494         if (rc != EOK) {
    495                 free(ip_netif);
    496                 return rc;
    497         }
    498 
    499         ip_netif->device_id = device_id;
    500         ip_netif->service = netif;
    501         ip_netif->state = NETIF_STOPPED;
     489/** Updates the device content length according to the new MTU value.
     490 *
     491 * @param[in] device_id The device identifier.
     492 * @param[in] mtu       The new mtu value.
     493 * @return              EOK on success.
     494 * @return              ENOENT if device is not found.
     495 */
     496static int ip_mtu_changed_message(device_id_t device_id, size_t mtu)
     497{
     498        ip_netif_t *netif;
    502499
    503500        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    504 
    505         rc = ip_netif_initialize(ip_netif);
    506         if (rc != EOK) {
     501        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     502        if (!netif) {
    507503                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    508                 ip_routes_destroy(&ip_netif->routes);
    509                 free(ip_netif);
    510                 return rc;
    511         }
    512         if (ip_netif->arp)
    513                 ip_netif->arp->usage++;
    514 
    515         // print the settings
    516         printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
    517             NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv,
    518             ip_netif->dhcp ? "dhcp" : "static");
    519        
    520         // TODO ipv6 addresses
    521        
    522         char address[INET_ADDRSTRLEN];
    523         char netmask[INET_ADDRSTRLEN];
    524         char gateway[INET_ADDRSTRLEN];
    525        
    526         for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
    527                 route = ip_routes_get_index(&ip_netif->routes, index);
    528                 if (route) {
    529                         inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr,
    530                             address, INET_ADDRSTRLEN);
    531                         inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr,
    532                             netmask, INET_ADDRSTRLEN);
    533                         inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr,
    534                             gateway, INET_ADDRSTRLEN);
    535                         printf("%s: Route %d (address: %s, netmask: %s, "
    536                             "gateway: %s)\n", NAME, index, address, netmask,
    537                             gateway);
    538                 }
    539         }
    540        
    541         inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
    542             INET_ADDRSTRLEN);
     504                return ENOENT;
     505        }
     506        netif->packet_dimension.content = mtu;
    543507        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    544508
    545         printf("%s: Broadcast (%s)\n", NAME, address);
     509        printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
    546510
    547511        return EOK;
    548512}
    549513
    550 /** Searches the network interfaces if there is a suitable route.
    551  *
    552  * @param[in] netif     The network interface to be searched for routes. May be
    553  *                      NULL.
    554  * @param[in] destination The destination address.
    555  * @return              The found route.
    556  * @return              NULL if no route was found.
    557  */
    558 static ip_route_t *ip_netif_find_route(ip_netif_t *netif,
    559     in_addr_t destination)
    560 {
    561         int index;
    562         ip_route_t *route;
    563        
    564         if (!netif)
     514/** Updates the device state.
     515 *
     516 * @param[in] device_id The device identifier.
     517 * @param[in] state     The new state value.
     518 * @return              EOK on success.
     519 * @return              ENOENT if device is not found.
     520 */
     521static int ip_device_state_message(device_id_t device_id, device_state_t state)
     522{
     523        ip_netif_t *netif;
     524
     525        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     526        // find the device
     527        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     528        if (!netif) {
     529                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     530                return ENOENT;
     531        }
     532        netif->state = state;
     533        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     534
     535        printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
     536
     537        return EOK;
     538}
     539
     540
     541/** Prefixes a middle fragment header based on the last fragment header to the
     542 * packet.
     543 *
     544 * @param[in] packet    The packet to be prefixed.
     545 * @param[in] last      The last header to be copied.
     546 * @return              The prefixed middle header.
     547 * @return              NULL on error.
     548 */
     549static ip_header_t *
     550ip_create_middle_header(packet_t *packet, ip_header_t *last)
     551{
     552        ip_header_t *middle;
     553
     554        middle = (ip_header_t *) packet_suffix(packet, IP_HEADER_LENGTH(last));
     555        if (!middle)
    565556                return NULL;
    566        
    567         /* Start with the first one (the direct route) */
    568         for (index = 0; index < ip_routes_count(&netif->routes); index++) {
    569                 route = ip_routes_get_index(&netif->routes, index);
    570                 if ((route) &&
    571                     ((route->address.s_addr & route->netmask.s_addr) ==
    572                     (destination.s_addr & route->netmask.s_addr)))
    573                         return route;
    574         }
    575 
    576         return NULL;
    577 }
    578 
    579 /** Searches all network interfaces if there is a suitable route.
    580  *
    581  * @param[in] destination The destination address.
    582  * @return              The found route.
    583  * @return              NULL if no route was found.
    584  */
    585 static ip_route_t *ip_find_route(in_addr_t destination) {
    586         int index;
    587         ip_route_t *route;
    588         ip_netif_t *netif;
    589 
    590         // start with the last netif - the newest one
    591         index = ip_netifs_count(&ip_globals.netifs) - 1;
    592         while (index >= 0) {
    593                 netif = ip_netifs_get_index(&ip_globals.netifs, index);
    594                 if (netif && (netif->state == NETIF_ACTIVE)) {
    595                         route = ip_netif_find_route(netif, destination);
    596                         if (route)
    597                                 return route;
    598                 }
    599                 index--;
    600         }
    601 
    602         return &ip_globals.gateway;
    603 }
    604 
    605 /** Returns the network interface's IP address.
    606  *
    607  * @param[in] netif     The network interface.
    608  * @return              The IP address.
    609  * @return              NULL if no IP address was found.
    610  */
    611 static in_addr_t *ip_netif_address(ip_netif_t *netif)
    612 {
    613         ip_route_t *route;
    614 
    615         route = ip_routes_get_index(&netif->routes, 0);
    616         return route ? &route->address : NULL;
     557        memcpy(middle, last, IP_HEADER_LENGTH(last));
     558        middle->flags |= IPFLAG_MORE_FRAGMENTS;
     559        return middle;
    617560}
    618561
     
    683626 *                      function.
    684627 */
    685 static int ip_prepare_packet(in_addr_t *source, in_addr_t dest,
    686     packet_t *packet, measured_string_t *destination)
     628static int
     629ip_prepare_packet(in_addr_t *source, in_addr_t dest, packet_t *packet,
     630    measured_string_t *destination)
    687631{
    688632        size_t length;
     
    813757 *                      function.
    814758 */
    815 static int ip_fragment_packet_data(packet_t *packet, packet_t *new_packet,
     759static int
     760ip_fragment_packet_data(packet_t *packet, packet_t *new_packet,
    816761    ip_header_t *header, ip_header_t *new_header, size_t length,
    817762    const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen)
     
    847792
    848793        return pq_insert_after(packet, new_packet);
    849 }
    850 
    851 /** Prefixes a middle fragment header based on the last fragment header to the
    852  * packet.
    853  *
    854  * @param[in] packet    The packet to be prefixed.
    855  * @param[in] last      The last header to be copied.
    856  * @return              The prefixed middle header.
    857  * @return              NULL on error.
    858  */
    859 static ip_header_t *ip_create_middle_header(packet_t *packet,
    860     ip_header_t *last)
    861 {
    862         ip_header_t *middle;
    863 
    864         middle = (ip_header_t *) packet_suffix(packet, IP_HEADER_LENGTH(last));
    865         if (!middle)
    866                 return NULL;
    867         memcpy(middle, last, IP_HEADER_LENGTH(last));
    868         middle->flags |= IPFLAG_MORE_FRAGMENTS;
    869         return middle;
    870794}
    871795
     
    1072996 *                      function.
    1073997 */
    1074 static int ip_send_route(packet_t *packet, ip_netif_t *netif,
    1075     ip_route_t *route, in_addr_t *src, in_addr_t dest, services_t error)
     998static int
     999ip_send_route(packet_t *packet, ip_netif_t *netif, ip_route_t *route,
     1000    in_addr_t *src, in_addr_t dest, services_t error)
    10761001{
    10771002        measured_string_t destination;
     
    11361061}
    11371062
    1138 static int ip_send_msg_local(int il_phone, device_id_t device_id,
    1139     packet_t *packet, services_t sender, services_t error)
     1063/** Searches the network interfaces if there is a suitable route.
     1064 *
     1065 * @param[in] netif     The network interface to be searched for routes. May be
     1066 *                      NULL.
     1067 * @param[in] destination The destination address.
     1068 * @return              The found route.
     1069 * @return              NULL if no route was found.
     1070 */
     1071static ip_route_t *
     1072ip_netif_find_route(ip_netif_t *netif, in_addr_t destination)
     1073{
     1074        int index;
     1075        ip_route_t *route;
     1076       
     1077        if (!netif)
     1078                return NULL;
     1079       
     1080        /* Start with the first one (the direct route) */
     1081        for (index = 0; index < ip_routes_count(&netif->routes); index++) {
     1082                route = ip_routes_get_index(&netif->routes, index);
     1083                if ((route) &&
     1084                    ((route->address.s_addr & route->netmask.s_addr) ==
     1085                    (destination.s_addr & route->netmask.s_addr)))
     1086                        return route;
     1087        }
     1088
     1089        return NULL;
     1090}
     1091
     1092/** Searches all network interfaces if there is a suitable route.
     1093 *
     1094 * @param[in] destination The destination address.
     1095 * @return              The found route.
     1096 * @return              NULL if no route was found.
     1097 */
     1098static ip_route_t *ip_find_route(in_addr_t destination) {
     1099        int index;
     1100        ip_route_t *route;
     1101        ip_netif_t *netif;
     1102
     1103        // start with the last netif - the newest one
     1104        index = ip_netifs_count(&ip_globals.netifs) - 1;
     1105        while (index >= 0) {
     1106                netif = ip_netifs_get_index(&ip_globals.netifs, index);
     1107                if (netif && (netif->state == NETIF_ACTIVE)) {
     1108                        route = ip_netif_find_route(netif, destination);
     1109                        if (route)
     1110                                return route;
     1111                }
     1112                index--;
     1113        }
     1114
     1115        return &ip_globals.gateway;
     1116}
     1117
     1118/** Returns the network interface's IP address.
     1119 *
     1120 * @param[in] netif     The network interface.
     1121 * @return              The IP address.
     1122 * @return              NULL if no IP address was found.
     1123 */
     1124static in_addr_t *ip_netif_address(ip_netif_t *netif)
     1125{
     1126        ip_route_t *route;
     1127
     1128        route = ip_routes_get_index(&netif->routes, 0);
     1129        return route ? &route->address : NULL;
     1130}
     1131
     1132/** Registers the transport layer protocol.
     1133 *
     1134 * The traffic of this protocol will be supplied using either the receive
     1135 * function or IPC message.
     1136 *
     1137 * @param[in] protocol  The transport layer module protocol.
     1138 * @param[in] service   The transport layer module service.
     1139 * @param[in] phone     The transport layer module phone.
     1140 * @param[in] received_msg The receiving function.
     1141 * @return              EOK on success.
     1142 * @return              EINVAL if the protocol parameter and/or the service
     1143 *                      parameter is zero.
     1144 * @return              EINVAL if the phone parameter is not a positive number
     1145 *                      and the tl_receive_msg is NULL.
     1146 * @return              ENOMEM if there is not enough memory left.
     1147 */
     1148static int
     1149ip_register(int protocol, services_t service, int phone,
     1150    tl_received_msg_t received_msg)
     1151{
     1152        ip_proto_t *proto;
     1153        int index;
     1154
     1155        if (!protocol || !service || ((phone < 0) && !received_msg))
     1156                return EINVAL;
     1157
     1158        proto = (ip_proto_t *) malloc(sizeof(ip_protos_t));
     1159        if (!proto)
     1160                return ENOMEM;
     1161
     1162        proto->protocol = protocol;
     1163        proto->service = service;
     1164        proto->phone = phone;
     1165        proto->received_msg = received_msg;
     1166
     1167        fibril_rwlock_write_lock(&ip_globals.protos_lock);
     1168        index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
     1169        if (index < 0) {
     1170                fibril_rwlock_write_unlock(&ip_globals.protos_lock);
     1171                free(proto);
     1172                return index;
     1173        }
     1174        fibril_rwlock_write_unlock(&ip_globals.protos_lock);
     1175
     1176        printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
     1177            NAME, proto->protocol, proto->phone);
     1178
     1179        return EOK;
     1180}
     1181
     1182static int
     1183ip_device_req_local(int il_phone, device_id_t device_id, services_t netif)
     1184{
     1185        ip_netif_t *ip_netif;
     1186        ip_route_t *route;
     1187        int index;
     1188        int rc;
     1189
     1190        ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t));
     1191        if (!ip_netif)
     1192                return ENOMEM;
     1193
     1194        rc = ip_routes_initialize(&ip_netif->routes);
     1195        if (rc != EOK) {
     1196                free(ip_netif);
     1197                return rc;
     1198        }
     1199
     1200        ip_netif->device_id = device_id;
     1201        ip_netif->service = netif;
     1202        ip_netif->state = NETIF_STOPPED;
     1203
     1204        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     1205
     1206        rc = ip_netif_initialize(ip_netif);
     1207        if (rc != EOK) {
     1208                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1209                ip_routes_destroy(&ip_netif->routes);
     1210                free(ip_netif);
     1211                return rc;
     1212        }
     1213        if (ip_netif->arp)
     1214                ip_netif->arp->usage++;
     1215
     1216        // print the settings
     1217        printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
     1218            NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv,
     1219            ip_netif->dhcp ? "dhcp" : "static");
     1220       
     1221        // TODO ipv6 addresses
     1222       
     1223        char address[INET_ADDRSTRLEN];
     1224        char netmask[INET_ADDRSTRLEN];
     1225        char gateway[INET_ADDRSTRLEN];
     1226       
     1227        for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
     1228                route = ip_routes_get_index(&ip_netif->routes, index);
     1229                if (route) {
     1230                        inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr,
     1231                            address, INET_ADDRSTRLEN);
     1232                        inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr,
     1233                            netmask, INET_ADDRSTRLEN);
     1234                        inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr,
     1235                            gateway, INET_ADDRSTRLEN);
     1236                        printf("%s: Route %d (address: %s, netmask: %s, "
     1237                            "gateway: %s)\n", NAME, index, address, netmask,
     1238                            gateway);
     1239                }
     1240        }
     1241       
     1242        inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
     1243            INET_ADDRSTRLEN);
     1244        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1245
     1246        printf("%s: Broadcast (%s)\n", NAME, address);
     1247
     1248        return EOK;
     1249}
     1250
     1251static int
     1252ip_send_msg_local(int il_phone, device_id_t device_id, packet_t *packet,
     1253    services_t sender, services_t error)
    11401254{
    11411255        int addrlen;
     
    12411355}
    12421356
    1243 /** Updates the device state.
    1244  *
     1357/** Returns the device packet dimensions for sending.
     1358 *
     1359 * @param[in] phone     The service module phone.
     1360 * @param[in] message   The service specific message.
    12451361 * @param[in] device_id The device identifier.
    1246  * @param[in] state     The new state value.
     1362 * @param[out] addr_len The minimum reserved address length.
     1363 * @param[out] prefix   The minimum reserved prefix size.
     1364 * @param[out] content  The maximum content size.
     1365 * @param[out] suffix   The minimum reserved suffix size.
    12471366 * @return              EOK on success.
    1248  * @return              ENOENT if device is not found.
    1249  */
    1250 static int ip_device_state_message(device_id_t device_id, device_state_t state)
     1367 */
     1368static int
     1369ip_packet_size_message(device_id_t device_id, size_t *addr_len, size_t *prefix,
     1370    size_t *content, size_t *suffix)
    12511371{
    12521372        ip_netif_t *netif;
    1253 
    1254         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    1255         // find the device
    1256         netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1257         if (!netif) {
    1258                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1259                 return ENOENT;
    1260         }
    1261         netif->state = state;
    1262         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1263 
    1264         printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
     1373        int index;
     1374
     1375        if (!addr_len || !prefix || !content || !suffix)
     1376                return EBADMEM;
     1377
     1378        *content = IP_MAX_CONTENT - IP_PREFIX;
     1379        fibril_rwlock_read_lock(&ip_globals.netifs_lock);
     1380        if (device_id < 0) {
     1381                *addr_len = IP_ADDR;
     1382                *prefix = 0;
     1383                *suffix = 0;
     1384
     1385                for (index = ip_netifs_count(&ip_globals.netifs) - 1;
     1386                    index >= 0; index--) {
     1387                        netif = ip_netifs_get_index(&ip_globals.netifs, index);
     1388                        if (!netif)
     1389                                continue;
     1390                       
     1391                        if (netif->packet_dimension.addr_len > *addr_len)
     1392                                *addr_len = netif->packet_dimension.addr_len;
     1393                       
     1394                        if (netif->packet_dimension.prefix > *prefix)
     1395                                *prefix = netif->packet_dimension.prefix;
     1396                               
     1397                        if (netif->packet_dimension.suffix > *suffix)
     1398                                *suffix = netif->packet_dimension.suffix;
     1399                }
     1400
     1401                *prefix = *prefix + IP_PREFIX;
     1402                *suffix = *suffix + IP_SUFFIX;
     1403        } else {
     1404                netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1405                if (!netif) {
     1406                        fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
     1407                        return ENOENT;
     1408                }
     1409
     1410                *addr_len = (netif->packet_dimension.addr_len > IP_ADDR) ?
     1411                    netif->packet_dimension.addr_len : IP_ADDR;
     1412                *prefix = netif->packet_dimension.prefix + IP_PREFIX;
     1413                *suffix = netif->packet_dimension.suffix + IP_SUFFIX;
     1414        }
     1415        fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    12651416
    12661417        return EOK;
     
    13021453 *                      tl_received_msg() function.
    13031454 */
    1304 static int ip_deliver_local(device_id_t device_id, packet_t *packet,
    1305     ip_header_t *header, services_t error)
     1455static int
     1456ip_deliver_local(device_id_t device_id, packet_t *packet, ip_header_t *header,
     1457    services_t error)
    13061458{
    13071459        ip_proto_t *proto;
     
    14031555 *                      is disabled.
    14041556 */
    1405 static int ip_process_packet(device_id_t device_id, packet_t *packet)
     1557static int
     1558ip_process_packet(device_id_t device_id, packet_t *packet)
    14061559{
    14071560        ip_header_t *header;
     
    14931646}
    14941647
    1495 /** Returns the device packet dimensions for sending.
    1496  *
    1497  * @param[in] phone     The service module phone.
    1498  * @param[in] message   The service specific message.
    1499  * @param[in] device_id The device identifier.
    1500  * @param[out] addr_len The minimum reserved address length.
    1501  * @param[out] prefix   The minimum reserved prefix size.
    1502  * @param[out] content  The maximum content size.
    1503  * @param[out] suffix   The minimum reserved suffix size.
    1504  * @return              EOK on success.
    1505  */
    1506 static int ip_packet_size_message(device_id_t device_id, size_t *addr_len,
    1507     size_t *prefix, size_t *content, size_t *suffix)
    1508 {
    1509         ip_netif_t *netif;
    1510         int index;
    1511 
    1512         if (!addr_len || !prefix || !content || !suffix)
    1513                 return EBADMEM;
    1514 
    1515         *content = IP_MAX_CONTENT - IP_PREFIX;
    1516         fibril_rwlock_read_lock(&ip_globals.netifs_lock);
    1517         if (device_id < 0) {
    1518                 *addr_len = IP_ADDR;
    1519                 *prefix = 0;
    1520                 *suffix = 0;
    1521 
    1522                 for (index = ip_netifs_count(&ip_globals.netifs) - 1;
    1523                     index >= 0; index--) {
    1524                         netif = ip_netifs_get_index(&ip_globals.netifs, index);
    1525                         if (!netif)
    1526                                 continue;
    1527                        
    1528                         if (netif->packet_dimension.addr_len > *addr_len)
    1529                                 *addr_len = netif->packet_dimension.addr_len;
    1530                        
    1531                         if (netif->packet_dimension.prefix > *prefix)
    1532                                 *prefix = netif->packet_dimension.prefix;
    1533                                
    1534                         if (netif->packet_dimension.suffix > *suffix)
    1535                                 *suffix = netif->packet_dimension.suffix;
    1536                 }
    1537 
    1538                 *prefix = *prefix + IP_PREFIX;
    1539                 *suffix = *suffix + IP_SUFFIX;
    1540         } else {
    1541                 netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1542                 if (!netif) {
    1543                         fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1544                         return ENOENT;
    1545                 }
    1546 
    1547                 *addr_len = (netif->packet_dimension.addr_len > IP_ADDR) ?
    1548                     netif->packet_dimension.addr_len : IP_ADDR;
    1549                 *prefix = netif->packet_dimension.prefix + IP_PREFIX;
    1550                 *suffix = netif->packet_dimension.suffix + IP_SUFFIX;
    1551         }
    1552         fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1553 
    1554         return EOK;
    1555 }
    1556 
    1557 /** Updates the device content length according to the new MTU value.
    1558  *
    1559  * @param[in] device_id The device identifier.
    1560  * @param[in] mtu       The new mtu value.
    1561  * @return              EOK on success.
    1562  * @return              ENOENT if device is not found.
    1563  */
    1564 static int ip_mtu_changed_message(device_id_t device_id, size_t mtu)
    1565 {
    1566         ip_netif_t *netif;
    1567 
    1568         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    1569         netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1570         if (!netif) {
    1571                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1572                 return ENOENT;
    1573         }
    1574         netif->packet_dimension.content = mtu;
    1575         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1576 
    1577         printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
    1578 
    1579         return EOK;
    1580 }
    1581 
    1582 /** Process IPC messages from the registered device driver modules
    1583  *
    1584  * @param[in]     iid   Message identifier.
    1585  * @param[in,out] icall Message parameters.
    1586  *
    1587  */
    1588 static void ip_receiver(ipc_callid_t iid, ipc_call_t *icall)
    1589 {
    1590         packet_t *packet;
    1591         int rc;
    1592        
    1593         while (true) {
    1594                 switch (IPC_GET_IMETHOD(*icall)) {
    1595                 case NET_IL_DEVICE_STATE:
    1596                         rc = ip_device_state_message(IPC_GET_DEVICE(*icall),
    1597                             IPC_GET_STATE(*icall));
    1598                         ipc_answer_0(iid, (sysarg_t) rc);
    1599                         break;
    1600                
    1601                 case NET_IL_RECEIVED:
    1602                         rc = packet_translate_remote(ip_globals.net_phone, &packet,
    1603                             IPC_GET_PACKET(*icall));
    1604                         if (rc == EOK) {
    1605                                 do {
    1606                                         packet_t *next = pq_detach(packet);
    1607                                         ip_process_packet(IPC_GET_DEVICE(*icall), packet);
    1608                                         packet = next;
    1609                                 } while (packet);
    1610                         }
    1611                        
    1612                         ipc_answer_0(iid, (sysarg_t) rc);
    1613                         break;
    1614                
    1615                 case NET_IL_MTU_CHANGED:
    1616                         rc = ip_mtu_changed_message(IPC_GET_DEVICE(*icall),
    1617                             IPC_GET_MTU(*icall));
    1618                         ipc_answer_0(iid, (sysarg_t) rc);
    1619                         break;
    1620                
    1621                 default:
    1622                         ipc_answer_0(iid, (sysarg_t) ENOTSUP);
    1623                 }
    1624                
    1625                 iid = async_get_call(icall);
    1626         }
    1627 }
    1628 
    1629 /** Registers the transport layer protocol.
    1630  *
    1631  * The traffic of this protocol will be supplied using either the receive
    1632  * function or IPC message.
    1633  *
    1634  * @param[in] protocol  The transport layer module protocol.
    1635  * @param[in] service   The transport layer module service.
    1636  * @param[in] phone     The transport layer module phone.
    1637  * @param[in] received_msg The receiving function.
    1638  * @return              EOK on success.
    1639  * @return              EINVAL if the protocol parameter and/or the service
    1640  *                      parameter is zero.
    1641  * @return              EINVAL if the phone parameter is not a positive number
    1642  *                      and the tl_receive_msg is NULL.
    1643  * @return              ENOMEM if there is not enough memory left.
    1644  */
    1645 static int
    1646 ip_register(int protocol, services_t service, int phone,
    1647     tl_received_msg_t received_msg)
    1648 {
    1649         ip_proto_t *proto;
    1650         int index;
    1651 
    1652         if (!protocol || !service || ((phone < 0) && !received_msg))
    1653                 return EINVAL;
    1654 
    1655         proto = (ip_proto_t *) malloc(sizeof(ip_protos_t));
    1656         if (!proto)
    1657                 return ENOMEM;
    1658 
    1659         proto->protocol = protocol;
    1660         proto->service = service;
    1661         proto->phone = phone;
    1662         proto->received_msg = received_msg;
    1663 
    1664         fibril_rwlock_write_lock(&ip_globals.protos_lock);
    1665         index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
    1666         if (index < 0) {
    1667                 fibril_rwlock_write_unlock(&ip_globals.protos_lock);
    1668                 free(proto);
    1669                 return index;
    1670         }
    1671         fibril_rwlock_write_unlock(&ip_globals.protos_lock);
    1672 
    1673         printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
    1674             NAME, proto->protocol, proto->phone);
    1675 
    1676         return EOK;
    1677 }
    1678 
    1679 
    16801648static int
    16811649ip_add_route_req_local(int ip_phone, device_id_t device_id, in_addr_t address,
     
    18771845}
    18781846
     1847/** Processes the received IP packet or the packet queue one by one.
     1848 *
     1849 * The packet is either passed to another module or released on error.
     1850 *
     1851 * @param[in] device_id The source device identifier.
     1852 * @param[in,out] packet The received packet.
     1853 * @return              EOK on success and the packet is no longer needed.
     1854 * @return              EINVAL if the packet is too small to carry the IP
     1855 *                      packet.
     1856 * @return              EINVAL if the received address lengths differs from the
     1857 *                      registered values.
     1858 * @return              ENOENT if the device is not found in the cache.
     1859 * @return              ENOENT if the protocol for the device is not found in
     1860 *                      the cache.
     1861 * @return              ENOMEM if there is not enough memory left.
     1862 */
     1863static int ip_receive_message(device_id_t device_id, packet_t *packet)
     1864{
     1865        packet_t *next;
     1866
     1867        do {
     1868                next = pq_detach(packet);
     1869                ip_process_packet(device_id, packet);
     1870                packet = next;
     1871        } while (packet);
     1872
     1873        return EOK;
     1874}
     1875
    18791876/** Processes the IP message.
    18801877 *
     
    18881885 *
    18891886 * @see ip_interface.h
    1890  * @see il_remote.h
     1887 * @see il_interface.h
    18911888 * @see IS_NET_IP_MESSAGE()
    18921889 */
    1893 int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
     1890int
     1891ip_message_standalone(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
    18941892    size_t *answer_count)
    18951893{
    18961894        packet_t *packet;
    18971895        struct sockaddr *addr;
    1898         void *header;
    1899         size_t headerlen;
    19001896        size_t addrlen;
    19011897        size_t prefix;
    19021898        size_t suffix;
    19031899        size_t content;
     1900        void *header;
     1901        size_t headerlen;
    19041902        device_id_t device_id;
    19051903        int rc;
     
    19141912                    IPC_GET_PHONE(*call), NULL);
    19151913       
    1916         case NET_IP_DEVICE:
     1914        case NET_IL_DEVICE:
    19171915                return ip_device_req_local(0, IPC_GET_DEVICE(*call),
    19181916                    IPC_GET_SERVICE(*call));
     1917       
     1918        case NET_IL_SEND:
     1919                rc = packet_translate_remote(ip_globals.net_phone, &packet,
     1920                    IPC_GET_PACKET(*call));
     1921                if (rc != EOK)
     1922                        return rc;
     1923                return ip_send_msg_local(0, IPC_GET_DEVICE(*call), packet, 0,
     1924                    IPC_GET_ERROR(*call));
     1925       
     1926        case NET_IL_DEVICE_STATE:
     1927                return ip_device_state_message(IPC_GET_DEVICE(*call),
     1928                    IPC_GET_STATE(*call));
     1929       
     1930        case NET_IL_RECEIVED:
     1931                rc = packet_translate_remote(ip_globals.net_phone, &packet,
     1932                    IPC_GET_PACKET(*call));
     1933                if (rc != EOK)
     1934                        return rc;
     1935                return ip_receive_message(IPC_GET_DEVICE(*call), packet);
    19191936       
    19201937        case NET_IP_RECEIVED_ERROR:
     
    19581975                return rc;
    19591976       
    1960         case NET_IP_PACKET_SPACE:
     1977        case NET_IL_PACKET_SPACE:
    19611978                rc = ip_packet_size_message(IPC_GET_DEVICE(*call), &addrlen,
    19621979                    &prefix, &content, &suffix);
     
    19711988                return EOK;
    19721989       
    1973         case NET_IP_SEND:
    1974                 rc = packet_translate_remote(ip_globals.net_phone, &packet,
    1975                     IPC_GET_PACKET(*call));
    1976                 if (rc != EOK)
    1977                         return rc;
     1990        case NET_IL_MTU_CHANGED:
     1991                return ip_mtu_changed_message(IPC_GET_DEVICE(*call),
     1992                    IPC_GET_MTU(*call));
     1993        }
     1994       
     1995        return ENOTSUP;
     1996}
     1997
     1998/** Default thread for new connections.
     1999 *
     2000 * @param[in] iid       The initial message identifier.
     2001 * @param[in] icall     The initial message call structure.
     2002 */
     2003static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
     2004{
     2005        /*
     2006         * Accept the connection
     2007         *  - Answer the first IPC_M_CONNECT_ME_TO call.
     2008         */
     2009        ipc_answer_0(iid, EOK);
     2010       
     2011        while (true) {
     2012                ipc_call_t answer;
     2013                size_t count;
    19782014               
    1979                 return ip_send_msg_local(0, IPC_GET_DEVICE(*call), packet, 0,
    1980                     IPC_GET_ERROR(*call));
    1981         }
    1982        
    1983         return ENOTSUP;
    1984 }
    1985 
     2015                /* Clear the answer structure */
     2016                refresh_answer(&answer, &count);
     2017               
     2018                /* Fetch the next message */
     2019                ipc_call_t call;
     2020                ipc_callid_t callid = async_get_call(&call);
     2021               
     2022                /* Process the message */
     2023                int res = il_module_message_standalone(callid, &call, &answer,
     2024                    &count);
     2025               
     2026                /*
     2027                 * End if told to either by the message or the processing
     2028                 * result.
     2029                 */
     2030                if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
     2031                    (res == EHANGUP)) {
     2032                        return;
     2033                }
     2034               
     2035                /* Answer the message */
     2036                answer_call(callid, res, &answer, count);
     2037        }
     2038}
     2039
     2040/** Starts the module.
     2041 *
     2042 * @return EOK on success.
     2043 * @return Other error codes as defined for each specific module start function.
     2044 */
    19862045int main(int argc, char *argv[])
    19872046{
     2047        int rc;
     2048       
    19882049        /* Start the module */
    1989         return il_module_start(SERVICE_IP);
     2050        rc = il_module_start_standalone(il_client_connection);
     2051        return rc;
    19902052}
    19912053
Note: See TracChangeset for help on using the changeset viewer.