Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 60ab6c3 in mainline


Ignore:
Timestamp:
2010-03-10T05:46:54Z (12 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master
Children:
5782081
Parents:
71b00dcc (diff), b48ebd19 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge from lp:~lukasmejdrech/helenos/network.

Location:
uspace/srv/net
Files:
2 added
46 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/Doxyfile

    r71b00dcc r60ab6c3  
    66DOXYFILE_ENCODING      = UTF-8
    77PROJECT_NAME           = "Networking and TCP/IP stack for HelenOS system"
    8 PROJECT_NUMBER         = "Master thesis 2009"
     8PROJECT_NUMBER         = ""
    99OUTPUT_DIRECTORY       = doc/
    1010CREATE_SUBDIRS         = YES
  • uspace/srv/net/Makefile

    r71b00dcc r60ab6c3  
    2929include ../../../Makefile.config
    3030
    31 DIRS = \
     31# keep netif drivers before nil modules
     32# in order to support networking architectures build
     33
     34ifeq ($(CONFIG_NETIF_DP8390),y)
     35        DIRS = netif/dp8390
     36else
     37        DIRS =
     38endif
     39
     40DIRS += \
    3241        netif/lo \
    3342        nil/eth \
     
    4756                tl/udp \
    4857                tl/tcp \
    49 
    50 ifeq ($(CONFIG_NETIF_DP8390),y)
    51         DIRS += netif/dp8390
    52 endif
    5358
    5459DIRS_ALL = $(DIRS) $(DIRS_MODULAR)
  • uspace/srv/net/app/echo/echo.c

    r71b00dcc r60ab6c3  
    5555#define NAME    "Echo"
    5656
     57/** Prints the application help.
     58 */
     59void echo_print_help(void);
     60
    5761/** Module entry point.
    5862 *  Reads command line parameters and starts listenning.
     
    6266 */
    6367int main(int argc, char * argv[]);
    64 
    65 /** Prints the application help.
    66  */
    67 void echo_print_help(void);
    68 
    69 /** Translates the character string to the protocol family number.
    70  *  @param[in] name The protocol family name.
    71  *  @returns The corresponding protocol family number.
    72  *  @returns EPFNOSUPPORTED if the protocol family is not supported.
    73  */
    74 int echo_parse_protocol_family(const char * name);
    75 
    76 /** Translates the character string to the socket type number.
    77  *  @param[in] name The socket type name.
    78  *  @returns The corresponding socket type number.
    79  *  @returns ESOCKNOSUPPORTED if the socket type is not supported.
    80  */
    81 int echo_parse_socket_type(const char * name);
    8268
    8369void echo_print_help(void){
     
    115101}
    116102
    117 int echo_parse_protocol_family(const char * name){
    118         if(str_lcmp(name, "PF_INET", 7) == 0){
    119                 return PF_INET;
    120         }else if(str_lcmp(name, "PF_INET6", 8) == 0){
    121                 return PF_INET6;
    122         }
    123         return EPFNOSUPPORT;
    124 }
    125 
    126 int echo_parse_socket_type(const char * name){
    127         if(str_lcmp(name, "SOCK_DGRAM", 11) == 0){
    128                 return SOCK_DGRAM;
    129         }else if(str_lcmp(name, "SOCK_STREAM", 12) == 0){
    130                 return SOCK_STREAM;
    131         }
    132         return ESOCKTNOSUPPORT;
    133 }
    134 
    135103int main(int argc, char * argv[]){
    136104        ERROR_DECLARE;
     
    138106        size_t size                     = 1024;
    139107        int verbose                     = 0;
    140         char * reply                    = NULL;
    141         sock_type_t type                        = SOCK_DGRAM;
     108        char * reply            = NULL;
     109        sock_type_t type        = SOCK_DGRAM;
    142110        int count                       = -1;
    143111        int family                      = PF_INET;
    144         uint16_t port                   = 7;
     112        uint16_t port           = 7;
    145113        int backlog                     = 3;
    146114
    147         socklen_t max_length            = sizeof(struct sockaddr_in6);
     115        socklen_t max_length                            = sizeof(struct sockaddr_in6);
    148116        uint8_t address_data[max_length];
    149         struct sockaddr * address               = (struct sockaddr *) address_data;
     117        struct sockaddr * address                       = (struct sockaddr *) address_data;
    150118        struct sockaddr_in * address_in         = (struct sockaddr_in *) address;
    151119        struct sockaddr_in6 * address_in6       = (struct sockaddr_in6 *) address;
     
    155123        int socket_id;
    156124        int listening_id;
    157         char *                          data;
     125        char * data;
    158126        size_t length;
    159127        int index;
     
    161129        int value;
    162130
     131        // print the program label
    163132        printf("Task %d - ", task_get_id());
    164133        printf("%s\n", NAME);
    165134
     135        // parse the command line arguments
    166136        for(index = 1; index < argc; ++ index){
    167137                if(argv[index][0] == '-'){
     
    174144                                        break;
    175145                                case 'f':
    176                                         ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 0, echo_parse_protocol_family));
     146                                        ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 0, parse_protocol_family));
    177147                                        break;
    178148                                case 'h':
     
    192162                                        break;
    193163                                case 't':
    194                                         ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &value, "socket type", 0, echo_parse_socket_type));
     164                                        ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &value, "socket type", 0, parse_socket_type));
    195165                                        type = (sock_type_t) value;
    196166                                        break;
     
    198168                                        verbose = 1;
    199169                                        break;
     170                                // long options with the double minus sign ('-')
    200171                                case '-':
    201172                                        if(str_lcmp(argv[index] + 2, "backlog=", 6) == 0){
     
    204175                                                ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &count, "message count", 8));
    205176                                        }else if(str_lcmp(argv[index] + 2, "family=", 7) == 0){
    206                                                 ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 9, echo_parse_protocol_family));
     177                                                ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 9, parse_protocol_family));
    207178                                        }else if(str_lcmp(argv[index] + 2, "help", 5) == 0){
    208179                                                echo_print_help();
     
    217188                                                size = (value >= 0) ? (size_t) value : 0;
    218189                                        }else if(str_lcmp(argv[index] + 2, "type=", 5) == 0){
    219                                                 ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &value, "socket type", 7, echo_parse_socket_type));
     190                                                ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &value, "socket type", 7, parse_socket_type));
    220191                                                type = (sock_type_t) value;
    221192                                        }else if(str_lcmp(argv[index] + 2, "verbose", 8) == 0){
     
    239210        }
    240211
     212        // check the buffer size
    241213        if(size <= 0){
    242214                fprintf(stderr, "Receive size too small (%d). Using 1024 bytes instead.\n", size);
    243215                size = 1024;
    244216        }
    245         // size plus terminating null (\0)
     217        // size plus the terminating null (\0)
    246218        data = (char *) malloc(size + 1);
    247219        if(! data){
     
    250222        }
    251223
     224        // set the reply size if set
    252225        reply_length = reply ? str_length(reply) : 0;
    253226
    254         listening_id = socket(family, type, 0);
    255         if(listening_id < 0){
    256                 socket_print_error(stderr, listening_id, "Socket create: ", "\n");
    257                 return listening_id;
    258         }
    259 
     227        // prepare the address buffer
    260228        bzero(address_data, max_length);
    261229        switch(family){
     
    275243        }
    276244
     245        // get a listening socket
    277246        listening_id = socket(family, type, 0);
    278247        if(listening_id < 0){
     
    281250        }
    282251
     252        // if the stream socket is used
    283253        if(type == SOCK_STREAM){
     254                // check the backlog
    284255                if(backlog <= 0){
    285256                        fprintf(stderr, "Accepted sockets queue size too small (%d). Using 3 instead.\n", size);
    286257                        backlog = 3;
    287258                }
     259                // set the backlog
    288260                if(ERROR_OCCURRED(listen(listening_id, backlog))){
    289261                        socket_print_error(stderr, ERROR_CODE, "Socket listen: ", "\n");
     
    292264        }
    293265
     266        // bind the listenning socket
    294267        if(ERROR_OCCURRED(bind(listening_id, address, addrlen))){
    295268                socket_print_error(stderr, ERROR_CODE, "Socket bind: ", "\n");
     
    303276        socket_id = listening_id;
    304277
     278        // do count times
     279        // or indefinitely if set to a negative value
    305280        while(count){
     281
    306282                addrlen = max_length;
    307283                if(type == SOCK_STREAM){
     284                        // acceept a socket if the stream socket is used
    308285                        socket_id = accept(listening_id, address, &addrlen);
    309286                        if(socket_id <= 0){
     
    315292                        }
    316293                }
     294
     295                // if the datagram socket is used or the stream socked was accepted
    317296                if(socket_id > 0){
     297
     298                        // receive an echo request
    318299                        value = recvfrom(socket_id, data, size, 0, address, &addrlen);
    319300                        if(value < 0){
     
    322303                                length = (size_t) value;
    323304                                if(verbose){
     305                                        // print the header
     306
     307                                        // get the source port and prepare the address buffer
    324308                                        address_start = NULL;
    325309                                        switch(address->sa_family){
     
    335319                                                        fprintf(stderr, "Address family %d (0x%X) is not supported.\n", address->sa_family);
    336320                                        }
     321                                        // parse the source address
    337322                                        if(address_start){
    338323                                                if(ERROR_OCCURRED(inet_ntop(address->sa_family, address_start, address_string, sizeof(address_string)))){
     
    344329                                        }
    345330                                }
     331
     332                                // answer the request either with the static reply or the original data
    346333                                if(ERROR_OCCURRED(sendto(socket_id, reply ? reply : data, reply ? reply_length : length, 0, address, addrlen))){
    347334                                        socket_print_error(stderr, ERROR_CODE, "Socket send: ", "\n");
    348335                                }
    349                         }
     336
     337                        }
     338
     339                        // close the accepted stream socket
    350340                        if(type == SOCK_STREAM){
    351341                                if(ERROR_OCCURRED(closesocket(socket_id))){
     
    353343                                }
    354344                        }
    355                 }
     345
     346                }
     347
     348                // decrease the count if positive
    356349                if(count > 0){
    357350                        -- count;
     
    366359        }
    367360
     361        // close the listenning socket
    368362        if(ERROR_OCCURRED(closesocket(listening_id))){
    369363                socket_print_error(stderr, ERROR_CODE, "Close socket: ", "\n");
  • uspace/srv/net/app/nettest1/Makefile

    r71b00dcc r60ab6c3  
    4040SOURCES = \
    4141        $(NAME).c \
     42        $(NET_BASE)app/nettest.c \
    4243        $(NET_BASE)app/parse.c \
    4344        $(NET_BASE)app/print_error.c
  • uspace/srv/net/app/nettest1/nettest1.c

    r71b00dcc r60ab6c3  
    4848#include "../../err.h"
    4949
     50#include "../nettest.h"
    5051#include "../parse.h"
    5152#include "../print_error.h"
     
    6970/** Prints the application help.
    7071 */
    71 void print_help(void);
    72 
    73 /** Translates the character string to the protocol family number.
    74  *  @param[in] name The protocol family name.
    75  *  @returns The corresponding protocol family number.
    76  *  @returns EPFNOSUPPORTED if the protocol family is not supported.
    77  */
    78 int parse_protocol_family(const char * name);
    79 
    80 /** Translates the character string to the socket type number.
    81  *  @param[in] name The socket type name.
    82  *  @returns The corresponding socket type number.
    83  *  @returns ESOCKNOSUPPORTED if the socket type is not supported.
    84  */
    85 int parse_socket_type(const char * name);
     72void nettest1_print_help(void);
    8673
    8774/** Refreshes the data.
     
    9077 *  @param[in] size The data block size in bytes.
    9178 */
    92 void refresh_data(char * data, size_t size);
    93 
    94 /** Creates new sockets.
    95  *  @param[in] verbose A value indicating whether to print out verbose information.
    96  *  @param[out] socket_ids A field to store the socket identifiers.
    97  *  @param[in] sockets The number of sockets to create. Should be at most the size of the field.
    98  *  @param[in] family The socket address family.
    99  *  @param[in] type The socket type.
    100  *  @returns EOK on success.
    101  *  @returns Other error codes as defined for the socket() function.
    102  */
    103 int sockets_create(int verbose, int * socket_ids, int sockets, int family, sock_type_t type);
    104 
    105 /** Closes sockets.
    106  *  @param[in] verbose A value indicating whether to print out verbose information.
    107  *  @param[in] socket_ids A field of stored socket identifiers.
    108  *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
    109  *  @returns EOK on success.
    110  *  @returns Other error codes as defined for the closesocket() function.
    111  */
    112 int sockets_close(int verbose, int * socket_ids, int sockets);
    113 
    114 /** Connects sockets.
    115  *  @param[in] verbose A value indicating whether to print out verbose information.
    116  *  @param[in] socket_ids A field of stored socket identifiers.
    117  *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
    118  *  @param[in] address The destination host address to connect to.
    119  *  @param[in] addrlen The length of the destination address in bytes.
    120  *  @returns EOK on success.
    121  *  @returns Other error codes as defined for the connect() function.
    122  */
    123 int sockets_connect(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen);
    124 
    125 /** Sends data via sockets.
    126  *  @param[in] verbose A value indicating whether to print out verbose information.
    127  *  @param[in] socket_ids A field of stored socket identifiers.
    128  *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
    129  *  @param[in] address The destination host address to send data to.
    130  *  @param[in] addrlen The length of the destination address in bytes.
    131  *  @param[in] data The data to be sent.
    132  *  @param[in] size The data size in bytes.
    133  *  @param[in] messages The number of datagrams per socket to be sent.
    134  *  @returns EOK on success.
    135  *  @returns Other error codes as defined for the sendto() function.
    136  */
    137 int sockets_sendto(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen, char * data, int size, int messages);
    138 
    139 /** Receives data via sockets.
    140  *  @param[in] verbose A value indicating whether to print out verbose information.
    141  *  @param[in] socket_ids A field of stored socket identifiers.
    142  *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
    143  *  @param[in] address The source host address of received datagrams.
    144  *  @param[in,out] addrlen The maximum length of the source address in bytes. The actual size of the source address is set instead.
    145  *  @param[out] data The received data.
    146  *  @param[in] size The maximum data size in bytes.
    147  *  @param[in] messages The number of datagrams per socket to be received.
    148  *  @returns EOK on success.
    149  *  @returns Other error codes as defined for the recvfrom() function.
    150  */
    151 int sockets_recvfrom(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages);
    152 
    153 /** Sends and receives data via sockets.
    154  *  Each datagram is sent and a reply read consequently.
    155  *  The next datagram is sent after the reply is received.
    156  *  @param[in] verbose A value indicating whether to print out verbose information.
    157  *  @param[in] socket_ids A field of stored socket identifiers.
    158  *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
    159  *  @param[in,out] address The destination host address to send data to. The source host address of received datagrams is set instead.
    160  *  @param[in] addrlen The length of the destination address in bytes.
    161  *  @param[in,out] data The data to be sent. The received data are set instead.
    162  *  @param[in] size The data size in bytes.
    163  *  @param[in] messages The number of datagrams per socket to be received.
    164  *  @returns EOK on success.
    165  *  @returns Other error codes as defined for the recvfrom() function.
    166  */
    167 int sockets_sendto_recvfrom(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages);
    168 
    169 /** Prints a mark.
    170  *  If the index is a multiple of ten, a different mark is printed.
    171  *  @param[in] index The index of the mark to be printed.
    172  */
    173 void print_mark(int index);
    174 
    175 void print_help(void){
    176         printf(
    177                 "Network Networking test 1 aplication - sockets\n" \
    178                 "Usage: echo [options] numeric_address\n" \
    179                 "Where options are:\n" \
    180                 "-f protocol_family | --family=protocol_family\n" \
    181                 "\tThe listenning socket protocol family. Only the PF_INET and PF_INET6 are supported.\n"
    182                 "\n" \
    183                 "-h | --help\n" \
    184                 "\tShow this application help.\n"
    185                 "\n" \
    186                 "-m count | --messages=count\n" \
    187                 "\tThe number of messages to send and receive per socket. The default is 10.\n" \
    188                 "\n" \
    189                 "-n sockets | --sockets=count\n" \
    190                 "\tThe number of sockets to use. The default is 10.\n" \
    191                 "\n" \
    192                 "-p port_number | --port=port_number\n" \
    193                 "\tThe port number the application should send messages to. The default is 7.\n" \
    194                 "\n" \
    195                 "-s packet_size | --size=packet_size\n" \
    196                 "\tThe packet data size the application sends. The default is 28 bytes.\n" \
    197                 "\n" \
    198                 "-v | --verbose\n" \
    199                 "\tShow all output messages.\n"
    200         );
    201 }
    202 
    203 int parse_protocol_family(const char * name){
    204         if(str_lcmp(name, "PF_INET", 7) == 0){
    205                 return PF_INET;
    206         }else if(str_lcmp(name, "PF_INET6", 8) == 0){
    207                 return PF_INET6;
    208         }
    209         return EPFNOSUPPORT;
    210 }
    211 
    212 int parse_socket_type(const char * name){
    213         if(str_lcmp(name, "SOCK_DGRAM", 11) == 0){
    214                 return SOCK_DGRAM;
    215         }else if(str_lcmp(name, "SOCK_STREAM", 12) == 0){
    216                 return SOCK_STREAM;
    217         }
    218         return ESOCKTNOSUPPORT;
    219 }
    220 
    221 void refresh_data(char * data, size_t size){
    222         size_t length;
    223 
    224         // fill the data
    225         length = 0;
    226         while(size > length + sizeof(NETTEST1_TEXT) - 1){
    227                 memcpy(data + length, NETTEST1_TEXT, sizeof(NETTEST1_TEXT) - 1);
    228                 length += sizeof(NETTEST1_TEXT) - 1;
    229         }
    230         memcpy(data + length, NETTEST1_TEXT, size - length);
    231         data[size] = '\0';
    232 }
    233 
    234 int sockets_create(int verbose, int * socket_ids, int sockets, int family, sock_type_t type){
    235         int index;
    236 
    237         if(verbose){
    238                 printf("Create\t");
    239         }
    240         fflush(stdout);
    241         for(index = 0; index < sockets; ++ index){
    242                 socket_ids[index] = socket(family, type, 0);
    243                 if(socket_ids[index] < 0){
    244                         printf("Socket %d (%d) error:\n", index, socket_ids[index]);
    245                         socket_print_error(stderr, socket_ids[index], "Socket create: ", "\n");
    246                         return socket_ids[index];
    247                 }
    248                 if(verbose){
    249                         print_mark(index);
    250                 }
    251         }
    252         return EOK;
    253 }
    254 
    255 int sockets_close(int verbose, int * socket_ids, int sockets){
    256         ERROR_DECLARE;
    257 
    258         int index;
    259 
    260         if(verbose){
    261                 printf("\tClose\t");
    262         }
    263         fflush(stdout);
    264         for(index = 0; index < sockets; ++ index){
    265                 if(ERROR_OCCURRED(closesocket(socket_ids[index]))){
    266                         printf("Socket %d (%d) error:\n", index, socket_ids[index]);
    267                         socket_print_error(stderr, ERROR_CODE, "Socket close: ", "\n");
    268                         return ERROR_CODE;
    269                 }
    270                 if(verbose){
    271                         print_mark(index);
    272                 }
    273         }
    274         return EOK;
    275 }
    276 
    277 int sockets_connect(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen){
    278         ERROR_DECLARE;
    279 
    280         int index;
    281 
    282         if(verbose){
    283                 printf("\tConnect\t");
    284         }
    285         fflush(stdout);
    286         for(index = 0; index < sockets; ++ index){
    287                 if(ERROR_OCCURRED(connect(socket_ids[index], address, addrlen))){
    288                         socket_print_error(stderr, ERROR_CODE, "Socket connect: ", "\n");
    289                         return ERROR_CODE;
    290                 }
    291                 if(verbose){
    292                         print_mark(index);
    293                 }
    294         }
    295         return EOK;
    296 }
    297 
    298 int sockets_sendto(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen, char * data, int size, int messages){
    299         ERROR_DECLARE;
    300 
    301         int index;
    302         int message;
    303 
    304         if(verbose){
    305                 printf("\tSendto\t");
    306         }
    307         fflush(stdout);
    308         for(index = 0; index < sockets; ++ index){
    309                 for(message = 0; message < messages; ++ message){
    310                         if(ERROR_OCCURRED(sendto(socket_ids[index], data, size, 0, address, addrlen))){
    311                                 printf("Socket %d (%d), message %d error:\n", index, socket_ids[index], message);
    312                                 socket_print_error(stderr, ERROR_CODE, "Socket send: ", "\n");
    313                                 return ERROR_CODE;
    314                         }
    315                 }
    316                 if(verbose){
    317                         print_mark(index);
    318                 }
    319         }
    320         return EOK;
    321 }
    322 
    323 int sockets_recvfrom(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages){
    324         int value;
    325         int index;
    326         int message;
    327 
    328         if(verbose){
    329                 printf("\tRecvfrom\t");
    330         }
    331         fflush(stdout);
    332         for(index = 0; index < sockets; ++ index){
    333                 for(message = 0; message < messages; ++ message){
    334                         value = recvfrom(socket_ids[index], data, size, 0, address, addrlen);
    335                         if(value < 0){
    336                                 printf("Socket %d (%d), message %d error:\n", index, socket_ids[index], message);
    337                                 socket_print_error(stderr, value, "Socket receive: ", "\n");
    338                                 return value;
    339                         }
    340                 }
    341                 if(verbose){
    342                         print_mark(index);
    343                 }
    344         }
    345         return EOK;
    346 }
    347 
    348 int sockets_sendto_recvfrom(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages){
    349         ERROR_DECLARE;
    350 
    351         int value;
    352         int index;
    353         int message;
    354 
    355         if(verbose){
    356                 printf("\tSendto and recvfrom\t");
    357         }
    358         fflush(stdout);
    359         for(index = 0; index < sockets; ++ index){
    360                 for(message = 0; message < messages; ++ message){
    361                         if(ERROR_OCCURRED(sendto(socket_ids[index], data, size, 0, address, * addrlen))){
    362                                 printf("Socket %d (%d), message %d error:\n", index, socket_ids[index], message);
    363                                 socket_print_error(stderr, ERROR_CODE, "Socket send: ", "\n");
    364                                 return ERROR_CODE;
    365                         }
    366                         value = recvfrom(socket_ids[index], data, size, 0, address, addrlen);
    367                         if(value < 0){
    368                                 printf("Socket %d (%d), message %d error:\n", index, socket_ids[index], message);
    369                                 socket_print_error(stderr, value, "Socket receive: ", "\n");
    370                                 return value;
    371                         }
    372                 }
    373                 if(verbose){
    374                         print_mark(index);
    375                 }
    376         }
    377         return EOK;
    378 }
    379 
    380 void print_mark(int index){
    381         if((index + 1) % 10){
    382                 printf("*");
    383         }else{
    384                 printf("|");
    385         }
    386         fflush(stdout);
    387 }
     79void nettest1_refresh_data(char * data, size_t size);
    38880
    38981int main(int argc, char * argv[]){
     
    39284        size_t size                     = 27;
    39385        int verbose                     = 0;
    394         sock_type_t type                        = SOCK_DGRAM;
     86        sock_type_t type        = SOCK_DGRAM;
    39587        int sockets                     = 10;
    39688        int messages            = 10;
    39789        int family                      = PF_INET;
    398         uint16_t port                   = 7;
    399 
    400         socklen_t max_length            = sizeof(struct sockaddr_in6);
     90        uint16_t port           = 7;
     91
     92        socklen_t max_length                            = sizeof(struct sockaddr_in6);
    40193        uint8_t address_data[max_length];
    402         struct sockaddr * address               = (struct sockaddr *) address_data;
     94        struct sockaddr * address                       = (struct sockaddr *) address_data;
    40395        struct sockaddr_in * address_in         = (struct sockaddr_in *) address;
    40496        struct sockaddr_in6 * address_in6       = (struct sockaddr_in6 *) address;
    40597        socklen_t addrlen;
    406 //      char                            address_string[INET6_ADDRSTRLEN];
     98//      char address_string[INET6_ADDRSTRLEN];
    40799        uint8_t * address_start;
    408100
    409101        int * socket_ids;
    410         char *                          data;
     102        char * data;
    411103        int value;
    412104        int index;
     
    414106        struct timeval time_after;
    415107
     108        // print the program label
    416109        printf("Task %d - ", task_get_id());
    417110        printf("%s\n", NAME);
    418111
    419         if(argc <= 1){
    420                 print_help();
    421                 return EINVAL;
    422         }
    423 
    424         for(index = 1; (index < argc - 1) || ((index == argc) && (argv[index][0] == '-')); ++ index){
     112        // parse the command line arguments
     113        // stop before the last argument if it does not start with the minus sign ('-')
     114        for(index = 1; (index < argc - 1) || ((index == argc - 1) && (argv[index][0] == '-')); ++ index){
     115                // options should start with the minus sign ('-')
    425116                if(argv[index][0] == '-'){
    426117                        switch(argv[index][1]){
     118                                // short options with only one letter
    427119                                case 'f':
    428120                                        ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 0, parse_protocol_family));
    429121                                        break;
    430122                                case 'h':
    431                                         print_help();
     123                                        nettest1_print_help();
    432124                                        return EOK;
    433125                                        break;
     
    453145                                        verbose = 1;
    454146                                        break;
     147                                // long options with the double minus sign ('-')
    455148                                case '-':
    456149                                        if(str_lcmp(argv[index] + 2, "family=", 7) == 0){
    457150                                                ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 9, parse_protocol_family));
    458151                                        }else if(str_lcmp(argv[index] + 2, "help", 5) == 0){
    459                                                 print_help();
     152                                                nettest1_print_help();
    460153                                                return EOK;
    461154                                        }else if(str_lcmp(argv[index] + 2, "messages=", 6) == 0){
     
    473166                                        }else{
    474167                                                print_unrecognized(index, argv[index] + 2);
    475                                                 print_help();
     168                                                nettest1_print_help();
    476169                                                return EINVAL;
    477170                                        }
     
    479172                                default:
    480173                                        print_unrecognized(index, argv[index] + 1);
    481                                         print_help();
     174                                        nettest1_print_help();
    482175                                        return EINVAL;
    483176                        }
    484177                }else{
    485178                        print_unrecognized(index, argv[index]);
    486                         print_help();
     179                        nettest1_print_help();
    487180                        return EINVAL;
    488181                }
    489182        }
    490183
     184        // if not before the last argument containing the address
     185        if(index >= argc){
     186                printf("Command line error: missing address\n");
     187                nettest1_print_help();
     188                return EINVAL;
     189        }
     190
     191        // prepare the address buffer
    491192        bzero(address_data, max_length);
    492193        switch(family){
     
    508209        }
    509210
     211        // parse the last argument which should contain the address
    510212        if(ERROR_OCCURRED(inet_pton(family, argv[argc - 1], address_start))){
    511213                fprintf(stderr, "Address parse error %d\n", ERROR_CODE);
     
    513215        }
    514216
     217        // check the buffer size
    515218        if(size <= 0){
    516219                fprintf(stderr, "Data buffer size too small (%d). Using 1024 bytes instead.\n", size);
    517220                size = 1024;
    518221        }
    519         // size plus terminating null (\0)
     222
     223        // prepare the buffer
     224        // size plus the terminating null (\0)
    520225        data = (char *) malloc(size + 1);
    521226        if(! data){
     
    523228                return ENOMEM;
    524229        }
    525         refresh_data(data, size);
    526 
     230        nettest1_refresh_data(data, size);
     231
     232        // check the socket count
    527233        if(sockets <= 0){
    528234                fprintf(stderr, "Socket count too small (%d). Using 2 instead.\n", sockets);
    529235                sockets = 2;
    530236        }
    531         // count plus terminating null (\0)
     237
     238        // prepare the socket buffer
     239        // count plus the terminating null (\0)
    532240        socket_ids = (int *) malloc(sizeof(int) * (sockets + 1));
    533241        if(! socket_ids){
     
    673381}
    674382
     383void nettest1_print_help(void){
     384        printf(
     385                "Network Networking test 1 aplication - sockets\n" \
     386                "Usage: echo [options] numeric_address\n" \
     387                "Where options are:\n" \
     388                "-f protocol_family | --family=protocol_family\n" \
     389                "\tThe listenning socket protocol family. Only the PF_INET and PF_INET6 are supported.\n"
     390                "\n" \
     391                "-h | --help\n" \
     392                "\tShow this application help.\n"
     393                "\n" \
     394                "-m count | --messages=count\n" \
     395                "\tThe number of messages to send and receive per socket. The default is 10.\n" \
     396                "\n" \
     397                "-n sockets | --sockets=count\n" \
     398                "\tThe number of sockets to use. The default is 10.\n" \
     399                "\n" \
     400                "-p port_number | --port=port_number\n" \
     401                "\tThe port number the application should send messages to. The default is 7.\n" \
     402                "\n" \
     403                "-s packet_size | --size=packet_size\n" \
     404                "\tThe packet data size the application sends. The default is 28 bytes.\n" \
     405                "\n" \
     406                "-v | --verbose\n" \
     407                "\tShow all output messages.\n"
     408        );
     409}
     410
     411void nettest1_refresh_data(char * data, size_t size){
     412        size_t length;
     413
     414        // fill the data
     415        length = 0;
     416        while(size > length + sizeof(NETTEST1_TEXT) - 1){
     417                memcpy(data + length, NETTEST1_TEXT, sizeof(NETTEST1_TEXT) - 1);
     418                length += sizeof(NETTEST1_TEXT) - 1;
     419        }
     420        memcpy(data + length, NETTEST1_TEXT, size - length);
     421        data[size] = '\0';
     422}
     423
    675424/** @}
    676425 */
  • uspace/srv/net/app/nettest2/Makefile

    r71b00dcc r60ab6c3  
    4040SOURCES = \
    4141        $(NAME).c \
     42        $(NET_BASE)app/nettest.c \
    4243        $(NET_BASE)app/parse.c \
    4344        $(NET_BASE)app/print_error.c
  • uspace/srv/net/app/nettest2/nettest2.c

    r71b00dcc r60ab6c3  
    4848#include "../../err.h"
    4949
     50#include "../nettest.h"
    5051#include "../parse.h"
    5152#include "../print_error.h"
     
    6970/** Prints the application help.
    7071 */
    71 void print_help(void);
    72 
    73 /** Translates the character string to the protocol family number.
    74  *  @param[in] name The protocol family name.
    75  *  @returns The corresponding protocol family number.
    76  *  @returns EPFNOSUPPORTED if the protocol family is not supported.
    77  */
    78 int parse_protocol_family(const char * name);
    79 
    80 /** Translates the character string to the socket type number.
    81  *  @param[in] name The socket type name.
    82  *  @returns The corresponding socket type number.
    83  *  @returns ESOCKNOSUPPORTED if the socket type is not supported.
    84  */
    85 int parse_socket_type(const char * name);
     72void nettest2_print_help(void);
    8673
    8774/** Refreshes the data.
     
    9077 *  @param[in] size The data block size in bytes.
    9178 */
    92 void refresh_data(char * data, size_t size);
    93 
    94 /** Creates new sockets.
    95  *  @param[in] verbose A value indicating whether to print out verbose information.
    96  *  @param[out] socket_ids A field to store the socket identifiers.
    97  *  @param[in] sockets The number of sockets to create. Should be at most the size of the field.
    98  *  @param[in] family The socket address family.
    99  *  @param[in] type The socket type.
    100  *  @returns EOK on success.
    101  *  @returns Other error codes as defined for the socket() function.
    102  */
    103 int sockets_create(int verbose, int * socket_ids, int sockets, int family, sock_type_t type);
    104 
    105 /** Closes sockets.
    106  *  @param[in] verbose A value indicating whether to print out verbose information.
    107  *  @param[in] socket_ids A field of stored socket identifiers.
    108  *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
    109  *  @returns EOK on success.
    110  *  @returns Other error codes as defined for the closesocket() function.
    111  */
    112 int sockets_close(int verbose, int * socket_ids, int sockets);
    113 
    114 /** Connects sockets.
    115  *  @param[in] verbose A value indicating whether to print out verbose information.
    116  *  @param[in] socket_ids A field of stored socket identifiers.
    117  *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
    118  *  @param[in] address The destination host address to connect to.
    119  *  @param[in] addrlen The length of the destination address in bytes.
    120  *  @returns EOK on success.
    121  *  @returns Other error codes as defined for the connect() function.
    122  */
    123 int sockets_connect(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen);
    124 
    125 /** Sends data via sockets.
    126  *  @param[in] verbose A value indicating whether to print out verbose information.
    127  *  @param[in] socket_ids A field of stored socket identifiers.
    128  *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
    129  *  @param[in] address The destination host address to send data to.
    130  *  @param[in] addrlen The length of the destination address in bytes.
    131  *  @param[in] data The data to be sent.
    132  *  @param[in] size The data size in bytes.
    133  *  @param[in] messages The number of datagrams per socket to be sent.
    134  *  @returns EOK on success.
    135  *  @returns Other error codes as defined for the sendto() function.
    136  */
    137 int sockets_sendto(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen, char * data, int size, int messages);
    138 
    139 /** Receives data via sockets.
    140  *  @param[in] verbose A value indicating whether to print out verbose information.
    141  *  @param[in] socket_ids A field of stored socket identifiers.
    142  *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
    143  *  @param[in] address The source host address of received datagrams.
    144  *  @param[in,out] addrlen The maximum length of the source address in bytes. The actual size of the source address is set instead.
    145  *  @param[out] data The received data.
    146  *  @param[in] size The maximum data size in bytes.
    147  *  @param[in] messages The number of datagrams per socket to be received.
    148  *  @returns EOK on success.
    149  *  @returns Other error codes as defined for the recvfrom() function.
    150  */
    151 int sockets_recvfrom(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages);
    152 
    153 /** Sends and receives data via sockets.
    154  *  Each datagram is sent and a reply read consequently.
    155  *  The next datagram is sent after the reply is received.
    156  *  @param[in] verbose A value indicating whether to print out verbose information.
    157  *  @param[in] socket_ids A field of stored socket identifiers.
    158  *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
    159  *  @param[in,out] address The destination host address to send data to. The source host address of received datagrams is set instead.
    160  *  @param[in] addrlen The length of the destination address in bytes.
    161  *  @param[in,out] data The data to be sent. The received data are set instead.
    162  *  @param[in] size The data size in bytes.
    163  *  @param[in] messages The number of datagrams per socket to be received.
    164  *  @returns EOK on success.
    165  *  @returns Other error codes as defined for the recvfrom() function.
    166  */
    167 int sockets_sendto_recvfrom(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages);
    168 
    169 /** Prints a mark.
    170  *  If the index is a multiple of ten, a different mark is printed.
    171  *  @param[in] index The index of the mark to be printed.
    172  */
    173 void print_mark(int index);
    174 
    175 void print_help(void){
    176         printf(
    177                 "Network Networking test 2 aplication - UDP transfer\n" \
    178                 "Usage: echo [options] numeric_address\n" \
    179                 "Where options are:\n" \
    180                 "-f protocol_family | --family=protocol_family\n" \
    181                 "\tThe listenning socket protocol family. Only the PF_INET and PF_INET6 are supported.\n"
    182                 "\n" \
    183                 "-h | --help\n" \
    184                 "\tShow this application help.\n"
    185                 "\n" \
    186                 "-m count | --messages=count\n" \
    187                 "\tThe number of messages to send and receive per socket. The default is 10.\n" \
    188                 "\n" \
    189                 "-n sockets | --sockets=count\n" \
    190                 "\tThe number of sockets to use. The default is 10.\n" \
    191                 "\n" \
    192                 "-p port_number | --port=port_number\n" \
    193                 "\tThe port number the application should send messages to. The default is 7.\n" \
    194                 "\n" \
    195                 "-s packet_size | --size=packet_size\n" \
    196                 "\tThe packet data size the application sends. The default is 29 bytes.\n" \
    197                 "\n" \
    198                 "-v | --verbose\n" \
    199                 "\tShow all output messages.\n"
    200         );
    201 }
    202 
    203 int parse_protocol_family(const char * name){
    204         if(str_lcmp(name, "PF_INET", 7) == 0){
    205                 return PF_INET;
    206         }else if(str_lcmp(name, "PF_INET6", 8) == 0){
    207                 return PF_INET6;
    208         }
    209         return EPFNOSUPPORT;
    210 }
    211 
    212 int parse_socket_type(const char * name){
    213         if(str_lcmp(name, "SOCK_DGRAM", 11) == 0){
    214                 return SOCK_DGRAM;
    215         }else if(str_lcmp(name, "SOCK_STREAM", 12) == 0){
    216                 return SOCK_STREAM;
    217         }
    218         return ESOCKTNOSUPPORT;
    219 }
    220 
    221 void refresh_data(char * data, size_t size){
    222         size_t length;
    223 
    224         // fill the data
    225         length = 0;
    226         while(size > length + sizeof(NETTEST2_TEXT) - 1){
    227                 memcpy(data + length, NETTEST2_TEXT, sizeof(NETTEST2_TEXT) - 1);
    228                 length += sizeof(NETTEST2_TEXT) - 1;
    229         }
    230         memcpy(data + length, NETTEST2_TEXT, size - length);
    231         data[size] = '\0';
    232 }
    233 
    234 int sockets_create(int verbose, int * socket_ids, int sockets, int family, sock_type_t type){
    235         int index;
    236 
    237         if(verbose){
    238                 printf("Create\t");
    239         }
    240         fflush(stdout);
    241         for(index = 0; index < sockets; ++ index){
    242                 socket_ids[index] = socket(family, type, 0);
    243                 if(socket_ids[index] < 0){
    244                         printf("Socket %d (%d) error:\n", index, socket_ids[index]);
    245                         socket_print_error(stderr, socket_ids[index], "Socket create: ", "\n");
    246                         return socket_ids[index];
    247                 }
    248                 if(verbose){
    249                         print_mark(index);
    250                 }
    251         }
    252         return EOK;
    253 }
    254 
    255 int sockets_close(int verbose, int * socket_ids, int sockets){
    256         ERROR_DECLARE;
    257 
    258         int index;
    259 
    260         if(verbose){
    261                 printf("\tClose\t");
    262         }
    263         fflush(stdout);
    264         for(index = 0; index < sockets; ++ index){
    265                 if(ERROR_OCCURRED(closesocket(socket_ids[index]))){
    266                         printf("Socket %d (%d) error:\n", index, socket_ids[index]);
    267                         socket_print_error(stderr, ERROR_CODE, "Socket close: ", "\n");
    268                         return ERROR_CODE;
    269                 }
    270                 if(verbose){
    271                         print_mark(index);
    272                 }
    273         }
    274         return EOK;
    275 }
    276 
    277 int sockets_connect(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen){
    278         ERROR_DECLARE;
    279 
    280         int index;
    281 
    282         if(verbose){
    283                 printf("\tConnect\t");
    284         }
    285         fflush(stdout);
    286         for(index = 0; index < sockets; ++ index){
    287                 if(ERROR_OCCURRED(connect(socket_ids[index], address, addrlen))){
    288                         socket_print_error(stderr, ERROR_CODE, "Socket connect: ", "\n");
    289                         return ERROR_CODE;
    290                 }
    291                 if(verbose){
    292                         print_mark(index);
    293                 }
    294         }
    295         return EOK;
    296 }
    297 
    298 int sockets_sendto(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen, char * data, int size, int messages){
    299         ERROR_DECLARE;
    300 
    301         int index;
    302         int message;
    303 
    304         if(verbose){
    305                 printf("\tSendto\t");
    306         }
    307         fflush(stdout);
    308         for(index = 0; index < sockets; ++ index){
    309                 for(message = 0; message < messages; ++ message){
    310                         if(ERROR_OCCURRED(sendto(socket_ids[index], data, size, 0, address, addrlen))){
    311                                 printf("Socket %d (%d), message %d error:\n", index, socket_ids[index], message);
    312                                 socket_print_error(stderr, ERROR_CODE, "Socket send: ", "\n");
    313                                 return ERROR_CODE;
    314                         }
    315                 }
    316                 if(verbose){
    317                         print_mark(index);
    318                 }
    319         }
    320         return EOK;
    321 }
    322 
    323 int sockets_recvfrom(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages){
    324         int value;
    325         int index;
    326         int message;
    327 
    328         if(verbose){
    329                 printf("\tRecvfrom\t");
    330         }
    331         fflush(stdout);
    332         for(index = 0; index < sockets; ++ index){
    333                 for(message = 0; message < messages; ++ message){
    334                         value = recvfrom(socket_ids[index], data, size, 0, address, addrlen);
    335                         if(value < 0){
    336                                 printf("Socket %d (%d), message %d error:\n", index, socket_ids[index], message);
    337                                 socket_print_error(stderr, value, "Socket receive: ", "\n");
    338                                 return value;
    339                         }
    340                 }
    341                 if(verbose){
    342                         print_mark(index);
    343                 }
    344         }
    345         return EOK;
    346 }
    347 
    348 int sockets_sendto_recvfrom(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages){
    349         ERROR_DECLARE;
    350 
    351         int value;
    352         int index;
    353         int message;
    354 
    355         if(verbose){
    356                 printf("\tSendto and recvfrom\t");
    357         }
    358         fflush(stdout);
    359         for(index = 0; index < sockets; ++ index){
    360                 for(message = 0; message < messages; ++ message){
    361                         if(ERROR_OCCURRED(sendto(socket_ids[index], data, size, 0, address, * addrlen))){
    362                                 printf("Socket %d (%d), message %d error:\n", index, socket_ids[index], message);
    363                                 socket_print_error(stderr, ERROR_CODE, "Socket send: ", "\n");
    364                                 return ERROR_CODE;
    365                         }
    366                         value = recvfrom(socket_ids[index], data, size, 0, address, addrlen);
    367                         if(value < 0){
    368                                 printf("Socket %d (%d), message %d error:\n", index, socket_ids[index], message);
    369                                 socket_print_error(stderr, value, "Socket receive: ", "\n");
    370                                 return value;
    371                         }
    372                 }
    373                 if(verbose){
    374                         print_mark(index);
    375                 }
    376         }
    377         return EOK;
    378 }
    379 
    380 void print_mark(int index){
    381         if((index + 1) % 10){
    382                 printf("*");
    383         }else{
    384                 printf("|");
    385         }
    386         fflush(stdout);
    387 }
     79void nettest2_refresh_data(char * data, size_t size);
    38880
    38981int main(int argc, char * argv[]){
     
    39284        size_t size                     = 28;
    39385        int verbose                     = 0;
    394         sock_type_t type                        = SOCK_DGRAM;
     86        sock_type_t type        = SOCK_DGRAM;
    39587        int sockets                     = 10;
    39688        int messages            = 10;
    39789        int family                      = PF_INET;
    398         uint16_t port                   = 7;
    399 
    400         socklen_t max_length            = sizeof(struct sockaddr_in6);
     90        uint16_t port           = 7;
     91
     92        socklen_t max_length                            = sizeof(struct sockaddr_in6);
    40193        uint8_t address_data[max_length];
    402         struct sockaddr * address               = (struct sockaddr *) address_data;
     94        struct sockaddr * address                       = (struct sockaddr *) address_data;
    40395        struct sockaddr_in * address_in         = (struct sockaddr_in *) address;
    40496        struct sockaddr_in6 * address_in6       = (struct sockaddr_in6 *) address;
    40597        socklen_t addrlen;
    406 //      char                            address_string[INET6_ADDRSTRLEN];
     98//      char address_string[INET6_ADDRSTRLEN];
    40799        uint8_t * address_start;
    408100
    409101        int * socket_ids;
    410         char *                          data;
     102        char * data;
    411103        int value;
    412104        int index;
     
    417109        printf("%s\n", NAME);
    418110
    419         if(argc <= 1){
    420                 print_help();
    421                 return EINVAL;
    422         }
    423 
    424         for(index = 1; (index < argc - 1) || ((index == argc) && (argv[index][0] == '-')); ++ index){
     111        // parse the command line arguments
     112        // stop before the last argument if it does not start with the minus sign ('-')
     113        for(index = 1; (index < argc - 1) || ((index == argc - 1) && (argv[index][0] == '-')); ++ index){
     114                // options should start with the minus sign ('-')
    425115                if(argv[index][0] == '-'){
    426116                        switch(argv[index][1]){
     117                                // short options with only one letter
    427118                                case 'f':
    428119                                        ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 0, parse_protocol_family));
    429120                                        break;
    430121                                case 'h':
    431                                         print_help();
     122                                        nettest2_print_help();
    432123                                        return EOK;
    433124                                        break;
     
    453144                                        verbose = 1;
    454145                                        break;
     146                                // long options with the double minus sign ('-')
    455147                                case '-':
    456148                                        if(str_lcmp(argv[index] + 2, "family=", 7) == 0){
    457149                                                ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 9, parse_protocol_family));
    458150                                        }else if(str_lcmp(argv[index] + 2, "help", 5) == 0){
    459                                                 print_help();
     151                                                nettest2_print_help();
    460152                                                return EOK;
    461153                                        }else if(str_lcmp(argv[index] + 2, "messages=", 6) == 0){
     
    473165                                        }else{
    474166                                                print_unrecognized(index, argv[index] + 2);
    475                                                 print_help();
     167                                                nettest2_print_help();
    476168                                                return EINVAL;
    477169                                        }
     
    479171                                default:
    480172                                        print_unrecognized(index, argv[index] + 1);
    481                                         print_help();
     173                                        nettest2_print_help();
    482174                                        return EINVAL;
    483175                        }
    484176                }else{
    485177                        print_unrecognized(index, argv[index]);
    486                         print_help();
     178                        nettest2_print_help();
    487179                        return EINVAL;
    488180                }
    489181        }
    490182
     183        // if not before the last argument containing the address
     184        if(index >= argc){
     185                printf("Command line error: missing address\n");
     186                nettest2_print_help();
     187                return EINVAL;
     188        }
     189
     190        // prepare the address buffer
    491191        bzero(address_data, max_length);
    492192        switch(family){
     
    508208        }
    509209
     210        // parse the last argument which should contain the address
    510211        if(ERROR_OCCURRED(inet_pton(family, argv[argc - 1], address_start))){
    511212                fprintf(stderr, "Address parse error %d\n", ERROR_CODE);
     
    513214        }
    514215
     216        // check the buffer size
    515217        if(size <= 0){
    516218                fprintf(stderr, "Data buffer size too small (%d). Using 1024 bytes instead.\n", size);
    517219                size = 1024;
    518220        }
     221
     222        // prepare the buffer
    519223        // size plus terminating null (\0)
    520224        data = (char *) malloc(size + 1);
     
    523227                return ENOMEM;
    524228        }
    525         refresh_data(data, size);
    526 
     229        nettest2_refresh_data(data, size);
     230
     231        // check the socket count
    527232        if(sockets <= 0){
    528233                fprintf(stderr, "Socket count too small (%d). Using 2 instead.\n", sockets);
    529234                sockets = 2;
    530235        }
    531         // count plus terminating null (\0)
     236
     237        // prepare the socket buffer
     238        // count plus the terminating null (\0)
    532239        socket_ids = (int *) malloc(sizeof(int) * (sockets + 1));
    533240        if(! socket_ids){
     
    597304}
    598305
     306void nettest2_print_help(void){
     307        printf(
     308                "Network Networking test 2 aplication - UDP transfer\n" \
     309                "Usage: echo [options] numeric_address\n" \
     310                "Where options are:\n" \
     311                "-f protocol_family | --family=protocol_family\n" \
     312                "\tThe listenning socket protocol family. Only the PF_INET and PF_INET6 are supported.\n"
     313                "\n" \
     314                "-h | --help\n" \
     315                "\tShow this application help.\n"
     316                "\n" \
     317                "-m count | --messages=count\n" \
     318                "\tThe number of messages to send and receive per socket. The default is 10.\n" \
     319                "\n" \
     320                "-n sockets | --sockets=count\n" \
     321                "\tThe number of sockets to use. The default is 10.\n" \
     322                "\n" \
     323                "-p port_number | --port=port_number\n" \
     324                "\tThe port number the application should send messages to. The default is 7.\n" \
     325                "\n" \
     326                "-s packet_size | --size=packet_size\n" \
     327                "\tThe packet data size the application sends. The default is 29 bytes.\n" \
     328                "\n" \
     329                "-v | --verbose\n" \
     330                "\tShow all output messages.\n"
     331        );
     332}
     333
     334void nettest2_refresh_data(char * data, size_t size){
     335        size_t length;
     336
     337        // fill the data
     338        length = 0;
     339        while(size > length + sizeof(NETTEST2_TEXT) - 1){
     340                memcpy(data + length, NETTEST2_TEXT, sizeof(NETTEST2_TEXT) - 1);
     341                length += sizeof(NETTEST2_TEXT) - 1;
     342        }
     343        memcpy(data + length, NETTEST2_TEXT, size - length);
     344        data[size] = '\0';
     345}
     346
    599347/** @}
    600348 */
  • uspace/srv/net/app/parse.c

    r71b00dcc r60ab6c3  
    3838#include <string.h>
    3939
     40#include "../include/socket.h"
     41
    4042#include "../err.h"
    4143
    4244#include "parse.h"
     45
     46int parse_address_family(const char * name){
     47        if(str_lcmp(name, "AF_INET", 7) == 0){
     48                return AF_INET;
     49        }else if(str_lcmp(name, "AF_INET6", 8) == 0){
     50                return AF_INET6;
     51        }
     52        return EAFNOSUPPORT;
     53}
    4354
    4455int parse_parameter_int(int argc, char ** argv, int * index, int * value, const char * name, int offset){
     
    6172}
    6273
    63 int parse_parameter_string(int argc, char ** argv, int * index, char ** value, const char * name, int offset){
    64         if(offset){
    65                 *value = argv[*index] + offset;
    66         }else if((*index) + 1 < argc){
    67                 ++ (*index);
    68                 *value = argv[*index];
    69         }else{
    70                 fprintf(stderr, "Command line error: missing %s\n", name);
    71                 return EINVAL;
    72         }
    73         return EOK;
    74 }
    75 
    7674int parse_parameter_name_int(int argc, char ** argv, int * index, int * value, const char * name, int offset, int (*parse_value)(const char * value)){
    7775        ERROR_DECLARE;
     
    8886}
    8987
     88int parse_parameter_string(int argc, char ** argv, int * index, char ** value, const char * name, int offset){
     89        if(offset){
     90                *value = argv[*index] + offset;
     91        }else if((*index) + 1 < argc){
     92                ++ (*index);
     93                *value = argv[*index];
     94        }else{
     95                fprintf(stderr, "Command line error: missing %s\n", name);
     96                return EINVAL;
     97        }
     98        return EOK;
     99}
     100
     101int parse_protocol_family(const char * name){
     102        if(str_lcmp(name, "PF_INET", 7) == 0){
     103                return PF_INET;
     104        }else if(str_lcmp(name, "PF_INET6", 8) == 0){
     105                return PF_INET6;
     106        }
     107        return EPFNOSUPPORT;
     108}
     109
     110int parse_socket_type(const char * name){
     111        if(str_lcmp(name, "SOCK_DGRAM", 11) == 0){
     112                return SOCK_DGRAM;
     113        }else if(str_lcmp(name, "SOCK_STREAM", 12) == 0){
     114                return SOCK_STREAM;
     115        }
     116        return ESOCKTNOSUPPORT;
     117}
     118
    90119void print_unrecognized(int index, const char * parameter){
    91         fprintf(stderr, "Command line error - unrecognized parameter (%d: %s)\n", index, parameter);
     120        fprintf(stderr, "Command line error: unrecognized argument (%d: %s)\n", index, parameter);
    92121}
    93122
  • uspace/srv/net/app/parse.h

    r71b00dcc r60ab6c3  
    3838#define __NET_APP_PARSE__
    3939
    40 /** Prints the parameter unrecognized message and the application help.
    41  *  @param[in] index The index of the parameter.
    42  *  @param[in] parameter The parameter name.
     40#include "../include/socket.h"
     41
     42/** Translates the character string to the address family number.
     43 *  @param[in] name The address family name.
     44 *  @returns The corresponding address family number.
     45 *  @returns EAFNOSUPPORTED if the address family is not supported.
    4346 */
    44 void print_unrecognized(int index, const char * parameter);
     47int parse_address_family(const char * name);
    4548
    4649/** Parses the next parameter as an integral number.
     
    5861 */
    5962int parse_parameter_int(int argc, char ** argv, int * index, int * value, const char * name, int offset);
    60 
    61 /** Parses the next parameter as a character string.
    62  *  The actual parameter is pointed by the index.
    63  *  Uses the offseted actual parameter value if the offset is set or the next one if not.
    64  *  Increments the actual index by the number of processed parameters.
    65  *  @param[in] argc The total number of the parameters.
    66  *  @param[in] argv The parameters.
    67  *  @param[in,out] index The actual parameter index. The index is incremented by the number of processed parameters.
    68  *  @param[out] value The parsed parameter value.
    69  *  @param[in] name The parameter name to be printed on errors.
    70  *  @param[in] offset The value offset in the actual parameter. If not set, the next parameter is parsed instead.
    71  *  @returns EOK on success.
    72  *  @returns EINVAL if the parameter is missing.
    73  */
    74 int parse_parameter_string(int argc, char ** argv, int * index, char ** value, const char * name, int offset);
    7563
    7664/** Parses the next named parameter as an integral number.
     
    9280int parse_parameter_name_int(int argc, char ** argv, int * index, int * value, const char * name, int offset, int (*parse_value)(const char * value));
    9381
     82/** Parses the next parameter as a character string.
     83 *  The actual parameter is pointed by the index.
     84 *  Uses the offseted actual parameter value if the offset is set or the next one if not.
     85 *  Increments the actual index by the number of processed parameters.
     86 *  @param[in] argc The total number of the parameters.
     87 *  @param[in] argv The parameters.
     88 *  @param[in,out] index The actual parameter index. The index is incremented by the number of processed parameters.
     89 *  @param[out] value The parsed parameter value.
     90 *  @param[in] name The parameter name to be printed on errors.
     91 *  @param[in] offset The value offset in the actual parameter. If not set, the next parameter is parsed instead.
     92 *  @returns EOK on success.
     93 *  @returns EINVAL if the parameter is missing.
     94 */
     95int parse_parameter_string(int argc, char ** argv, int * index, char ** value, const char * name, int offset);
     96
     97/** Translates the character string to the protocol family number.
     98 *  @param[in] name The protocol family name.
     99 *  @returns The corresponding protocol family number.
     100 *  @returns EPFNOSUPPORTED if the protocol family is not supported.
     101 */
     102int parse_protocol_family(const char * name);
     103
     104/** Translates the character string to the socket type number.
     105 *  @param[in] name The socket type name.
     106 *  @returns The corresponding socket type number.
     107 *  @returns ESOCKNOSUPPORTED if the socket type is not supported.
     108 */
     109int parse_socket_type(const char * name);
     110
     111/** Prints the parameter unrecognized message and the application help.
     112 *  @param[in] index The index of the parameter.
     113 *  @param[in] parameter The parameter name.
     114 */
     115void print_unrecognized(int index, const char * parameter);
     116
    94117#endif
    95118
  • uspace/srv/net/app/ping/ping.c

    r71b00dcc r60ab6c3  
    3939#include <task.h>
    4040#include <time.h>
     41#include <ipc/ipc.h>
    4142#include <ipc/services.h>
    4243
     
    6768/** Prints the application help.
    6869 */
    69 void print_help(void);
    70 
    71 /** Translates the character string to the address family number.
    72  *  @param[in] name The address family name.
    73  *  @returns The corresponding address family number.
    74  *  @returns EAFNOSUPPORTED if the address family is not supported.
    75  */
    76 int parse_address_family(const char * name);
    77 
    78 void print_help(void){
    79         printf(
    80                 "Network Ping aplication\n" \
    81                 "Usage: ping [options] numeric_address\n" \
    82                 "Where options are:\n" \
    83                 "\n" \
    84                 "-c request_count | --count=request_count\n" \
    85                 "\tThe number of packets the application sends. The default is three (3).\n" \
    86                 "\n" \
    87                 "--dont_fragment\n" \
    88                 "\tDisable packet fragmentation.\n"
    89                 "\n" \
    90                 "-f address_family | --family=address_family\n" \
    91                 "\tThe given address family. Only the AF_INET and AF_INET6 are supported.\n"
    92                 "\n" \
    93                 "-h | --help\n" \
    94                 "\tShow this application help.\n"
    95                 "\n" \
    96                 "-s packet_size | --size=packet_size\n" \
    97                 "\tThe packet data size the application sends. The default is 38 bytes.\n" \
    98                 "\n" \
    99                 "-t timeout | --timeout=timeout\n" \
    100                 "\tThe number of miliseconds the application waits for a reply. The default is three thousands (3 000).\n" \
    101                 "\n" \
    102                 "--tos=tos\n" \
    103                 "\tThe type of service to be used.\n" \
    104                 "\n" \
    105                 "--ttl=ttl\n" \
    106                 "\tThe time to live to be used.\n" \
    107                 "\n" \
    108                 "-v | --verbose\n" \
    109                 "\tShow all output messages.\n"
    110         );
    111 }
    112 
    113 int parse_address_family(const char * name){
    114         if(str_lcmp(name, "AF_INET", 7) == 0){
    115                 return AF_INET;
    116         }else if(str_lcmp(name, "AF_INET6", 8) == 0){
    117                 return AF_INET6;
    118         }
    119         return EAFNOSUPPORT;
    120 }
     70void ping_print_help(void);
    12171
    12272int main(int argc, char * argv[]){
     
    12676        int verbose                     = 0;
    12777        int dont_fragment       = 0;
    128         ip_ttl_t ttl                            = 0;
    129         ip_tos_t tos                            = 0;
     78        ip_ttl_t ttl            = 0;
     79        ip_tos_t tos            = 0;
    13080        int count                       = 3;
    131         suseconds_t timeout                     = 3000;
     81        suseconds_t timeout     = 3000;
    13282        int family                      = AF_INET;
    13383
    134         socklen_t max_length            = sizeof(struct sockaddr_in6);
     84        socklen_t max_length                            = sizeof(struct sockaddr_in6);
    13585        uint8_t address_data[max_length];
    136         struct sockaddr * address               = (struct sockaddr *) address_data;
     86        struct sockaddr * address                       = (struct sockaddr *) address_data;
    13787        struct sockaddr_in * address_in         = (struct sockaddr_in *) address;
    13888        struct sockaddr_in6 * address_in6       = (struct sockaddr_in6 *) address;
     
    14797        int index;
    14898
     99        // print the program label
    149100        printf("Task %d - ", task_get_id());
    150101        printf("%s\n", NAME);
    151102
    152         if(argc <= 1){
    153                 print_help();
    154                 return EINVAL;
    155         }
    156 
    157         for(index = 1; (index < argc - 1) || ((index == argc) && (argv[index][0] == '-')); ++ index){
     103        // parse the command line arguments
     104        // stop before the last argument if it does not start with the minus sign ('-')
     105        for(index = 1; (index < argc - 1) || ((index == argc - 1) && (argv[index][0] == '-')); ++ index){
     106                // options should start with the minus sign ('-')
    158107                if(argv[index][0] == '-'){
    159108                        switch(argv[index][1]){
     109                                // short options with only one letter
    160110                                case 'c':
    161111                                        ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &count, "count", 0));
     
    165115                                        break;
    166116                                case 'h':
    167                                         print_help();
     117                                        ping_print_help();
    168118                                        return EOK;
    169119                                        break;
     
    179129                                        verbose = 1;
    180130                                        break;
     131                                // long options with the double minus sign ('-')
    181132                                case '-':
    182133                                        if(str_lcmp(argv[index] + 2, "count=", 6) == 0){
     
    187138                                                ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "address family", 9, parse_address_family));
    188139                                        }else if(str_lcmp(argv[index] + 2, "help", 5) == 0){
    189                                                 print_help();
     140                                                ping_print_help();
    190141                                                return EOK;
    191142                                        }else if(str_lcmp(argv[index] + 2, "size=", 5) == 0){
     
    205156                                        }else{
    206157                                                print_unrecognized(index, argv[index] + 2);
    207                                                 print_help();
     158                                                ping_print_help();
    208159                                                return EINVAL;
    209160                                        }
     
    211162                                default:
    212163                                        print_unrecognized(index, argv[index] + 1);
    213                                         print_help();
     164                                        ping_print_help();
    214165                                        return EINVAL;
    215166                        }
    216167                }else{
    217168                        print_unrecognized(index, argv[index]);
    218                         print_help();
     169                        ping_print_help();
    219170                        return EINVAL;
    220171                }
    221172        }
    222173
     174        // if not before the last argument containing the address
     175        if(index >= argc){
     176                printf("Command line error: missing address\n");
     177                ping_print_help();
     178                return EINVAL;
     179        }
     180
     181        // prepare the address buffer
    223182        bzero(address_data, max_length);
    224183        switch(family){
     
    238197        }
    239198
     199        // parse the last argument which should contain the address
    240200        if(ERROR_OCCURRED(inet_pton(family, argv[argc - 1], address_start))){
    241201                fprintf(stderr, "Address parse error %d\n", ERROR_CODE);
     
    243203        }
    244204
     205        // connect to the ICMP module
    245206        icmp_phone = icmp_connect_module(SERVICE_ICMP, ICMP_CONNECT_TIMEOUT);
    246207        if(icmp_phone < 0){
     
    249210        }
    250211
     212        // print the ping header
    251213        printf("PING %d bytes of data\n", size);
    252214        if(ERROR_OCCURRED(inet_ntop(address->sa_family, address_start, address_string, sizeof(address_string)))){
     
    256218        }
    257219
     220        // do count times
    258221        while(count > 0){
     222
     223                // get the starting time
    259224                if(ERROR_OCCURRED(gettimeofday(&time_before, NULL))){
    260225                        fprintf(stderr, "Get time of day error %d\n", ERROR_CODE);
     226                        // release the ICMP phone
     227                        ipc_hangup(icmp_phone);
    261228                        return ERROR_CODE;
    262229                }
     230
     231                // request the ping
    263232                result = icmp_echo_msg(icmp_phone, size, timeout, ttl, tos, dont_fragment, address, addrlen);
     233
     234                // get the ending time
    264235                if(ERROR_OCCURRED(gettimeofday(&time_after, NULL))){
    265236                        fprintf(stderr, "Get time of day error %d\n", ERROR_CODE);
     237                        // release the ICMP phone
     238                        ipc_hangup(icmp_phone);
    266239                        return ERROR_CODE;
    267240                }
     241
     242                // print the result
    268243                switch(result){
    269244                        case ICMP_ECHO:
     
    283258        }
    284259
     260        // release the ICMP phone
     261        ipc_hangup(icmp_phone);
     262
    285263        return EOK;
    286264}
    287265
     266void ping_print_help(void){
     267        printf(
     268                "Network Ping aplication\n" \
     269                "Usage: ping [options] numeric_address\n" \
     270                "Where options are:\n" \
     271                "\n" \
     272                "-c request_count | --count=request_count\n" \
     273                "\tThe number of packets the application sends. The default is three (3).\n" \
     274                "\n" \
     275                "--dont_fragment\n" \
     276                "\tDisable packet fragmentation.\n"
     277                "\n" \
     278                "-f address_family | --family=address_family\n" \
     279                "\tThe given address family. Only the AF_INET and AF_INET6 are supported.\n"
     280                "\n" \
     281                "-h | --help\n" \
     282                "\tShow this application help.\n"
     283                "\n" \
     284                "-s packet_size | --size=packet_size\n" \
     285                "\tThe packet data size the application sends. The default is 38 bytes.\n" \
     286                "\n" \
     287                "-t timeout | --timeout=timeout\n" \
     288                "\tThe number of miliseconds the application waits for a reply. The default is three thousands (3 000).\n" \
     289                "\n" \
     290                "--tos=tos\n" \
     291                "\tThe type of service to be used.\n" \
     292                "\n" \
     293                "--ttl=ttl\n" \
     294                "\tThe time to live to be used.\n" \
     295                "\n" \
     296                "-v | --verbose\n" \
     297                "\tShow all output messages.\n"
     298        );
     299}
     300
    288301/** @}
    289302 */
  • uspace/srv/net/app/print_error.c

    r71b00dcc r60ab6c3  
    4141
    4242#include "print_error.h"
    43 
    44 void print_error(FILE * output, int error_code, const char * prefix, const char * suffix){
    45         if(IS_ICMP_ERROR(error_code)){
    46                 icmp_print_error(output, error_code, prefix, suffix);
    47         }else if(IS_SOCKET_ERROR(error_code)){
    48                 socket_print_error(output, error_code, prefix, suffix);
    49         }
    50 }
    5143
    5244void icmp_print_error(FILE * output, int error_code, const char * prefix, const char * suffix){
     
    10193}
    10294
     95void print_error(FILE * output, int error_code, const char * prefix, const char * suffix){
     96        if(IS_ICMP_ERROR(error_code)){
     97                icmp_print_error(output, error_code, prefix, suffix);
     98        }else if(IS_SOCKET_ERROR(error_code)){
     99                socket_print_error(output, error_code, prefix, suffix);
     100        }
     101}
     102
    103103void socket_print_error(FILE * output, int error_code, const char * prefix, const char * suffix){
    104104        if(output){
  • uspace/srv/net/app/print_error.h

    r71b00dcc r60ab6c3  
    5050#define IS_SOCKET_ERROR(error_code)     ((error_code) < 0)
    5151
     52/** Prints the specific ICMP error description.
     53 *  @param[in] output The description output stream. May be NULL.
     54 *  @param[in] error_code The ICMP error code.
     55 *  @param[in] prefix The error description prefix. May be NULL.
     56 *  @param[in] suffix The error description suffix. May be NULL.
     57 */
     58void icmp_print_error(FILE * output, int error_code, const char * prefix, const char * suffix);
     59
    5260/** Prints the error description.
    5361 *  Supports ICMP and socket error codes.
     
    5866 */
    5967void print_error(FILE * output, int error_code, const char * prefix, const char * suffix);
    60 
    61 /** Prints the specific ICMP error description.
    62  *  @param[in] output The description output stream. May be NULL.
    63  *  @param[in] error_code The ICMP error code.
    64  *  @param[in] prefix The error description prefix. May be NULL.
    65  *  @param[in] suffix The error description suffix. May be NULL.
    66  */
    67 void icmp_print_error(FILE * output, int error_code, const char * prefix, const char * suffix);
    6868
    6969/** Prints the specific socket error description.
  • uspace/srv/net/cfg/modular/general

    r71b00dcc r60ab6c3  
    33IPV=4
    44IP_ROUTING=no
     5
    56MTU=1500
     7
    68ICMP_ERROR_REPORTING=yes
    79ICMP_ECHO_REPLYING=yes
     10
    811UDP_CHECKSUM_COMPUTING=yes
    912UDP_AUTOBINDING=yes
  • uspace/srv/net/cfg/module/general

    r71b00dcc r60ab6c3  
    33IPV=4
    44IP_ROUTING=no
     5
    56MTU=1500
     7
    68ICMP_ERROR_REPORTING=yes
    79ICMP_ECHO_REPLYING=yes
     10
    811UDP_CHECKSUM_COMPUTING=yes
    912UDP_AUTOBINDING=yes
  • uspace/srv/net/checksum.c

    r71b00dcc r60ab6c3  
    4747#define CRC_DIVIDER_LE  0xEDB88320
    4848
    49 uint32_t compute_crc32_le(uint32_t seed, uint8_t * data, size_t length){
    50         size_t index;
     49uint16_t compact_checksum(uint32_t sum){
     50        // shorten to the 16 bits
     51        while(sum >> 16){
     52                sum = (sum &0xFFFF) + (sum >> 16);
     53        }
    5154
    52         while(length >= 8){
    53                 seed ^= (*data);
    54                 for(index = 0; index < 8; ++ index){
    55                         if(seed &1){
    56                                 seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE);
    57                         }else{
    58                                 seed >>= 1;
    59                         }
    60                 }
    61                 ++ data;
    62                 length -= 8;
    63         }
    64         if(length > 0){
    65                 seed ^= (*data) >> (8 - length);
    66                 for(index = 0; index < length; ++ index){
    67                         if(seed &1){
    68                                 seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE);
    69                         }else{
    70                                 seed >>= 1;
    71                         }
    72                 }
    73                 length -= 8;
    74         }
    75         return seed;
    76 }
    77 
    78 uint32_t compute_crc32_be(uint32_t seed, uint8_t * data, size_t length){
    79         size_t index;
    80 
    81         while(length >= 8){
    82                 seed ^= (*data) << 24;
    83                 for(index = 0; index < 8; ++ index){
    84                         if(seed &0x80000000){
    85                                 seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
    86                         }else{
    87                                 seed <<= 1;
    88                         }
    89                 }
    90                 ++ data;
    91                 length -= 8;
    92         }
    93         if(length > 0){
    94                 seed ^= ((*data) &(0xFF << (8 - length))) << 24;
    95                 for(index = 0; index < length; ++ index){
    96                         if(seed &0x80000000){
    97                                 seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
    98                         }else{
    99                                 seed <<= 1;
    100                         }
    101                 }
    102                 length -= 8;
    103         }
    104         return seed;
     55        return (uint16_t) sum;
    10556}
    10657
     
    12172}
    12273
    123 uint16_t compact_checksum(uint32_t sum){
    124         // shorten to the 16 bits
    125         while(sum >> 16){
    126                 sum = (sum &0xFFFF) + (sum >> 16);
     74uint32_t compute_crc32_be(uint32_t seed, uint8_t * data, size_t length){
     75        size_t index;
     76
     77        // process full bytes
     78        while(length >= 8){
     79                // add the data
     80                seed ^= (*data) << 24;
     81                // for each added bit
     82                for(index = 0; index < 8; ++ index){
     83                        // if the first bit is set
     84                        if(seed &0x80000000){
     85                                // shift and divide the checksum
     86                                seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
     87                        }else{
     88                                // shift otherwise
     89                                seed <<= 1;
     90                        }
     91                }
     92                // move to the next byte
     93                ++ data;
     94                length -= 8;
    12795        }
    12896
    129         return (uint16_t) sum;
     97        // process the odd bits
     98        if(length > 0){
     99                // add the data with zero padding
     100                seed ^= ((*data) &(0xFF << (8 - length))) << 24;
     101                // for each added bit
     102                for(index = 0; index < length; ++ index){
     103                        // if the first bit is set
     104                        if(seed &0x80000000){
     105                                // shift and divide the checksum
     106                                seed = (seed << 1) ^ ((uint32_t) CRC_DIVIDER_BE);
     107                        }else{
     108                                // shift otherwise
     109                                seed <<= 1;
     110                        }
     111                }
     112        }
     113
     114        return seed;
     115}
     116
     117uint32_t compute_crc32_le(uint32_t seed, uint8_t * data, size_t length){
     118        size_t index;
     119
     120        // process full bytes
     121        while(length >= 8){
     122                // add the data
     123                seed ^= (*data);
     124                // for each added bit
     125                for(index = 0; index < 8; ++ index){
     126                        // if the last bit is set
     127                        if(seed &1){
     128                                // shift and divide the checksum
     129                                seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE);
     130                        }else{
     131                                // shift otherwise
     132                                seed >>= 1;
     133                        }
     134                }
     135                // move to the next byte
     136                ++ data;
     137                length -= 8;
     138        }
     139
     140        // process the odd bits
     141        if(length > 0){
     142                // add the data with zero padding
     143                seed ^= (*data) >> (8 - length);
     144                for(index = 0; index < length; ++ index){
     145                        // if the last bit is set
     146                        if(seed &1){
     147                                // shift and divide the checksum
     148                                seed = (seed >> 1) ^ ((uint32_t) CRC_DIVIDER_LE);
     149                        }else{
     150                                // shift otherwise
     151                                seed >>= 1;
     152                        }
     153                }
     154        }
     155
     156        return seed;
    130157}
    131158
     
    137164
    138165uint16_t ip_checksum(uint8_t * data, size_t length){
     166        // compute, compact and flip the data checksum
    139167        return flip_checksum(compact_checksum(compute_checksum(0, data, length)));
    140168}
  • uspace/srv/net/configuration.h

    r71b00dcc r60ab6c3  
    4646/*@{*/
    4747
    48 /** Activates the measured strings self test.
    49  *  The NET_SELF_TEST has to be activated.
    50  *  @see measured_strings.h
    51  */
    52 #define NET_SELF_TEST_MEASURED_STRINGS  1
    53 
    5448/** Activates the char map self test.
    5549 *  The NET_SELF_TEST has to be activated.
     
    5751 */
    5852#define NET_SELF_TEST_CHAR_MAP                  1
     53
     54/** Activates the CRC computation self test.
     55 *  The NET_SELF_TEST has to be activated.
     56 *  @see crc.h
     57 */
     58#define NET_SELF_TEST_CRC                               1
     59
     60/** Activates the dynamic fifo self test.
     61 *  The NET_SELF_TEST has to be activated.
     62 *  @see dynamic_fifo.h
     63 */
     64#define NET_SELF_TEST_DYNAMIC_FIFO              1
     65
     66/** Activates the generic char map self test.
     67 *  The NET_SELF_TEST has to be activated.
     68 *  @see generic_char_map.h
     69 */
     70#define NET_SELF_TEST_GENERIC_CHAR_MAP  1
     71
     72/** Activates the generic field self test.
     73 *  The NET_SELF_TEST has to be activated.
     74 *  @see generic_field.h
     75 */
     76#define NET_SELF_TEST_GENERIC_FIELD             1
    5977
    6078/** Activates the integral map self test.
     
    6482#define NET_SELF_TEST_INT_MAP                   1
    6583
    66 /** Activates the generic field self test.
     84/** Activates the measured strings self test.
    6785 *  The NET_SELF_TEST has to be activated.
    68  *  @see generic_field.h
     86 *  @see measured_strings.h
    6987 */
    70 #define NET_SELF_TEST_GENERIC_FIELD             1
    71 
    72 /** Activates the generic char map self test.
    73  *  The NET_SELF_TEST has to be activated.
    74  *  @see generic_char_map.h
    75  */
    76 #define NET_SELF_TEST_GENERIC_CHAR_MAP  1
    77 
    78 /** Activates the CRC computation self test.
    79  *  The NET_SELF_TEST has to be activated.
    80  *  @see crc.h
    81  */
    82 #define NET_SELF_TEST_CRC       1
    83 
    84 /** Activates the dynamic fifo self test.
    85  *  The NET_SELF_TEST has to be activated.
    86  *  @see dynamic_fifo.h
    87  */
    88 #define NET_SELF_TEST_DYNAMIC_FIFO      1
     88#define NET_SELF_TEST_MEASURED_STRINGS  1
    8989
    9090/*@}*/
  • uspace/srv/net/err.h

    r71b00dcc r60ab6c3  
    6262#ifdef CONFIG_DEBUG
    6363
    64 #define ERROR_OCCURRED(value)           (((ERROR_CODE = (value)) != EOK) && ({printf("error at %s:%d %d\n", __FILE__, __LINE__, ERROR_CODE); 1;}))
     64#define ERROR_OCCURRED(value)                                                                                           \
     65        (((ERROR_CODE = (value)) != EOK)                                                                                \
     66        && ({printf("error at %s:%d %d\n", __FILE__, __LINE__, ERROR_CODE); 1;}))
    6567
    6668#else
  • uspace/srv/net/il/arp/arp.c

    r71b00dcc r60ab6c3  
    7373arp_globals_t   arp_globals;
    7474
     75/** Clears the device specific data.
     76 *  @param[in] device The device specific data.
     77 */
     78void arp_clear_device(arp_device_ref device);
     79
    7580/** Creates new protocol specific data.
    7681 *  Allocates and returns the needed memory block as the proto parameter.
     
    8287 */
    8388int arp_proto_create(arp_proto_ref * proto, services_t service, measured_string_ref address);
    84 
    85 /** Clears the device specific data.
    86  *  @param[in] device The device specific data.
    87  */
    88 void arp_clear_device(arp_device_ref device);
    8989
    9090/** @name Message processing functions
     
    105105int arp_device_message(device_id_t device_id, services_t service, services_t protocol, measured_string_ref address);
    106106
    107 /** Returns the hardware address for the given protocol address.
    108  *  Sends the ARP request packet if the hardware address is not found in the cache.
     107/** Updates the device content length according to the new MTU value.
    109108 *  @param[in] device_id The device identifier.
    110  *  @param[in] protocol The protocol service.
    111  *  @param[in] target The target protocol address.
    112  *  @returns The hardware address of the target.
    113  *  @returns NULL if the target parameter is NULL.
    114  *  @returns NULL if the device is not found.
    115  *  @returns NULL if the device packet is too small to send a&nbsp;request.
    116  *  @returns NULL if the hardware address is not found in the cache.
    117  */
    118 measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target);
     109 *  @param[in] mtu The new mtu value.
     110 *  @returns ENOENT if device is not found.
     111 *  @returns EOK on success.
     112 */
     113int arp_mtu_changed_message(device_id_t device_id, size_t mtu);
    119114
    120115/** Processes the received ARP packet.
     
    133128int arp_receive_message(device_id_t device_id, packet_t packet);
    134129
    135 /** Updates the device content length according to the new MTU value.
     130/** Returns the hardware address for the given protocol address.
     131 *  Sends the ARP request packet if the hardware address is not found in the cache.
    136132 *  @param[in] device_id The device identifier.
    137  *  @param[in] mtu The new mtu value.
    138  *  @returns ENOENT if device is not found.
    139  *  @returns EOK on success.
    140  */
    141 int arp_mtu_changed_message(device_id_t device_id, size_t mtu);
     133 *  @param[in] protocol The protocol service.
     134 *  @param[in] target The target protocol address.
     135 *  @returns The hardware address of the target.
     136 *  @returns NULL if the target parameter is NULL.
     137 *  @returns NULL if the device is not found.
     138 *  @returns NULL if the device packet is too small to send a&nbsp;request.
     139 *  @returns NULL if the hardware address is not found in the cache.
     140 */
     141measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target);
    142142
    143143/*@}*/
     
    148148
    149149GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t)
    150 
    151 task_id_t arp_task_get_id(void){
    152         return task_get_id();
    153 }
    154 
    155 int arp_clear_device_req(int arp_phone, device_id_t device_id){
    156         arp_device_ref device;
    157 
    158         fibril_rwlock_write_lock(&arp_globals.lock);
    159         device = arp_cache_find(&arp_globals.cache, device_id);
    160         if(! device){
    161                 fibril_rwlock_write_unlock(&arp_globals.lock);
    162                 return ENOENT;
    163         }
    164         arp_clear_device(device);
    165         printf("Device %d cleared\n", device_id);
    166         fibril_rwlock_write_unlock(&arp_globals.lock);
    167         return EOK;
    168 }
    169 
    170 int arp_clear_address_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address){
    171         arp_device_ref device;
    172         arp_proto_ref proto;
    173 
    174         fibril_rwlock_write_lock(&arp_globals.lock);
    175         device = arp_cache_find(&arp_globals.cache, device_id);
    176         if(! device){
    177                 fibril_rwlock_write_unlock(&arp_globals.lock);
    178                 return ENOENT;
    179         }
    180         proto = arp_protos_find(&device->protos, protocol);
    181         if(! proto){
    182                 fibril_rwlock_write_unlock(&arp_globals.lock);
    183                 return ENOENT;
    184         }
    185         arp_addr_exclude(&proto->addresses, address->value, address->length);
    186         fibril_rwlock_write_unlock(&arp_globals.lock);
    187         return EOK;
    188 }
    189150
    190151int arp_clean_cache_req(int arp_phone){
     
    211172}
    212173
    213 int arp_device_req(int arp_phone, device_id_t device_id, services_t protocol, services_t netif, measured_string_ref address){
    214         ERROR_DECLARE;
    215 
    216         measured_string_ref tmp;
    217 
    218         // copy the given address for exclusive use
    219         tmp = measured_string_copy(address);
    220         if(ERROR_OCCURRED(arp_device_message(device_id, netif, protocol, tmp))){
    221                 free(tmp->value);
    222                 free(tmp);
    223         }
    224         return ERROR_CODE;
    225 }
    226 
    227 int arp_translate_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address, measured_string_ref * translation, char ** data){
    228         measured_string_ref tmp;
    229 
    230         fibril_rwlock_read_lock(&arp_globals.lock);
    231         tmp = arp_translate_message(device_id, protocol, address);
    232         if(tmp){
    233                 *translation = measured_string_copy(tmp);
    234                 fibril_rwlock_read_unlock(&arp_globals.lock);
    235                 if(*translation){
    236                         *data = (** translation).value;
    237                         return EOK;
    238                 }else{
    239                         return ENOMEM;
    240                 }
    241         }else{
    242                 fibril_rwlock_read_unlock(&arp_globals.lock);
     174int arp_clear_address_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address){
     175        arp_device_ref device;
     176        arp_proto_ref proto;
     177
     178        fibril_rwlock_write_lock(&arp_globals.lock);
     179        device = arp_cache_find(&arp_globals.cache, device_id);
     180        if(! device){
     181                fibril_rwlock_write_unlock(&arp_globals.lock);
    243182                return ENOENT;
    244183        }
    245 }
    246 
    247 int arp_initialize(async_client_conn_t client_connection){
    248         ERROR_DECLARE;
    249 
    250         fibril_rwlock_initialize(&arp_globals.lock);
     184        proto = arp_protos_find(&device->protos, protocol);
     185        if(! proto){
     186                fibril_rwlock_write_unlock(&arp_globals.lock);
     187                return ENOENT;
     188        }
     189        arp_addr_exclude(&proto->addresses, address->value, address->length);
     190        fibril_rwlock_write_unlock(&arp_globals.lock);
     191        return EOK;
     192}
     193
     194void arp_clear_device(arp_device_ref device){
     195        int count;
     196        arp_proto_ref proto;
     197
     198        for(count = arp_protos_count(&device->protos) - 1; count >= 0; -- count){
     199                proto = arp_protos_get_index(&device->protos, count);
     200                if(proto){
     201                        if(proto->addr){
     202                                free(proto->addr);
     203                        }
     204                        if(proto->addr_data){
     205                                free(proto->addr_data);
     206                        }
     207                        arp_addr_destroy(&proto->addresses);
     208                }
     209        }
     210        arp_protos_clear(&device->protos);
     211}
     212
     213int arp_clear_device_req(int arp_phone, device_id_t device_id){
     214        arp_device_ref device;
     215
    251216        fibril_rwlock_write_lock(&arp_globals.lock);
    252         arp_globals.client_connection = client_connection;
    253         ERROR_PROPAGATE(arp_cache_initialize(&arp_globals.cache));
     217        device = arp_cache_find(&arp_globals.cache, device_id);
     218        if(! device){
     219                fibril_rwlock_write_unlock(&arp_globals.lock);
     220                return ENOENT;
     221        }
     222        arp_clear_device(device);
     223        printf("Device %d cleared\n", device_id);
    254224        fibril_rwlock_write_unlock(&arp_globals.lock);
    255225        return EOK;
    256226}
    257227
    258 int arp_proto_create(arp_proto_ref * proto, services_t service, measured_string_ref address){
    259         ERROR_DECLARE;
    260 
    261         *proto = (arp_proto_ref) malloc(sizeof(arp_proto_t));
    262         if(!(*proto)){
    263                 return ENOMEM;
    264         }
    265         (** proto).service = service;
    266         (** proto).addr = address;
    267         (** proto).addr_data = address->value;
    268         if(ERROR_OCCURRED(arp_addr_initialize(&(** proto).addresses))){
    269                 free(*proto);
    270                 return ERROR_CODE;
     228int arp_connect_module(services_t service){
     229        if(service != SERVICE_ARP){
     230                return EINVAL;
    271231        }
    272232        return EOK;
     
    383343}
    384344
    385 measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target){
    386         arp_device_ref device;
    387         arp_proto_ref proto;
    388         measured_string_ref addr;
    389         size_t length;
    390         packet_t packet;
    391         arp_header_ref header;
    392 
    393         if(! target){
    394                 return NULL;
    395         }
    396         device = arp_cache_find(&arp_globals.cache, device_id);
    397         if(! device){
    398                 return NULL;
    399         }
    400         proto = arp_protos_find(&device->protos, protocol);
    401         if((! proto) || (proto->addr->length != target->length)){
    402                 return NULL;
    403         }
    404         addr = arp_addr_find(&proto->addresses, target->value, target->length);
    405         if(addr){
    406                 return addr;
    407         }
    408         // ARP packet content size = header + (address + translation) * 2
    409         length = 8 + (CONVERT_SIZE(char, uint8_t, proto->addr->length) + CONVERT_SIZE(char, uint8_t, device->addr->length)) * 2;
    410         if(length > device->packet_dimension.content){
    411                 return NULL;
    412         }
    413         packet = packet_get_4(arp_globals.net_phone, device->packet_dimension.addr_len, device->packet_dimension.prefix, length, device->packet_dimension.suffix);
    414         if(! packet){
    415                 return NULL;
    416         }
    417         header = (arp_header_ref) packet_suffix(packet, length);
    418         if(! header){
    419                 pq_release(arp_globals.net_phone, packet_get_id(packet));
    420                 return NULL;
    421         }
    422         header->hardware = htons(device->hardware);
    423         header->hardware_length = (uint8_t) device->addr->length;
    424         header->protocol = htons(protocol_map(device->service, protocol));
    425         header->protocol_length = (uint8_t) proto->addr->length;
    426         header->operation = htons(ARPOP_REQUEST);
    427         length = sizeof(arp_header_t);
    428         memcpy(((uint8_t *) header) + length, device->addr->value, device->addr->length);
    429         length += device->addr->length;
    430         memcpy(((uint8_t *) header) + length, proto->addr->value, proto->addr->length);
    431         length += proto->addr->length;
    432         bzero(((uint8_t *) header) + length, device->addr->length);
    433         length += device->addr->length;
    434         memcpy(((uint8_t *) header) + length, target->value, target->length);
    435         if(packet_set_addr(packet, (uint8_t *) device->addr->value, (uint8_t *) device->broadcast_addr->value, CONVERT_SIZE(char, uint8_t, device->addr->length)) != EOK){
    436                 pq_release(arp_globals.net_phone, packet_get_id(packet));
    437                 return NULL;
    438         }
    439         nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
    440         return NULL;
    441 }
    442 
    443 int arp_receive_message(device_id_t device_id, packet_t packet){
     345int arp_device_req(int arp_phone, device_id_t device_id, services_t protocol, services_t netif, measured_string_ref address){
    444346        ERROR_DECLARE;
    445347
    446         size_t length;
    447         arp_header_ref header;
    448         arp_device_ref device;
    449         arp_proto_ref proto;
    450         measured_string_ref hw_source;
    451         uint8_t * src_hw;
    452         uint8_t * src_proto;
    453         uint8_t * des_hw;
    454         uint8_t * des_proto;
    455 
    456         length = packet_get_data_length(packet);
    457         if(length <= sizeof(arp_header_t)){
    458                 return EINVAL;
    459         }
    460         device = arp_cache_find(&arp_globals.cache, device_id);
    461         if(! device){
    462                 return ENOENT;
    463         }
    464         header = (arp_header_ref) packet_get_data(packet);
    465         if((ntohs(header->hardware) != device->hardware)
    466                 || (length < sizeof(arp_header_t) + header->hardware_length * 2u + header->protocol_length * 2u)){
    467                 return EINVAL;
    468         }
    469         proto = arp_protos_find(&device->protos, protocol_unmap(device->service, ntohs(header->protocol)));
    470         if(! proto){
    471                 return ENOENT;
    472         }
    473         src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
    474         src_proto = src_hw + header->hardware_length;
    475         des_hw = src_proto + header->protocol_length;
    476         des_proto = des_hw + header->hardware_length;
    477         hw_source = arp_addr_find(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length));
    478         // exists?
    479         if(hw_source){
    480                 if(hw_source->length != CONVERT_SIZE(uint8_t, char, header->hardware_length)){
    481                         return EINVAL;
    482                 }
    483                 memcpy(hw_source->value, src_hw, hw_source->length);
    484         }
    485         // is my protocol address?
    486         if(proto->addr->length != CONVERT_SIZE(uint8_t, char, header->protocol_length)){
    487                 return EINVAL;
    488         }
    489         if(! str_lcmp(proto->addr->value, (char *) des_proto, proto->addr->length)){
    490                 // not already upadted?
    491                 if(! hw_source){
    492                         hw_source = measured_string_create_bulk((char *) src_hw, CONVERT_SIZE(uint8_t, char, header->hardware_length));
    493                         if(! hw_source){
    494                                 return ENOMEM;
    495                         }
    496                         ERROR_PROPAGATE(arp_addr_add(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length), hw_source));
    497                 }
    498                 if(ntohs(header->operation) == ARPOP_REQUEST){
    499                         header->operation = htons(ARPOP_REPLY);
    500                         memcpy(des_proto, src_proto, header->protocol_length);
    501                         memcpy(src_proto, proto->addr->value, header->protocol_length);
    502                         memcpy(src_hw, device->addr->value, device->packet_dimension.addr_len);
    503                         memcpy(des_hw, hw_source->value, header->hardware_length);
    504                         ERROR_PROPAGATE(packet_set_addr(packet, src_hw, des_hw, header->hardware_length));
    505                         nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
    506                         return 1;
    507                 }
    508         }
    509         return EOK;
    510 }
    511 
    512 void arp_clear_device(arp_device_ref device){
    513         int count;
    514         arp_proto_ref proto;
    515 
    516         for(count = arp_protos_count(&device->protos) - 1; count >= 0; -- count){
    517                 proto = arp_protos_get_index(&device->protos, count);
    518                 if(proto){
    519                         if(proto->addr){
    520                                 free(proto->addr);
    521                         }
    522                         if(proto->addr_data){
    523                                 free(proto->addr_data);
    524                         }
    525                         arp_addr_destroy(&proto->addresses);
    526                 }
    527         }
    528         arp_protos_clear(&device->protos);
    529 }
    530 
    531 int arp_connect_module(services_t service){
    532         if(service != SERVICE_ARP){
    533                 return EINVAL;
    534         }
    535         return EOK;
    536 }
    537 
    538 int arp_mtu_changed_message(device_id_t device_id, size_t mtu){
    539         arp_device_ref device;
    540 
     348        measured_string_ref tmp;
     349
     350        // copy the given address for exclusive use
     351        tmp = measured_string_copy(address);
     352        if(ERROR_OCCURRED(arp_device_message(device_id, netif, protocol, tmp))){
     353                free(tmp->value);
     354                free(tmp);
     355        }
     356        return ERROR_CODE;
     357}
     358
     359int arp_initialize(async_client_conn_t client_connection){
     360        ERROR_DECLARE;
     361
     362        fibril_rwlock_initialize(&arp_globals.lock);
    541363        fibril_rwlock_write_lock(&arp_globals.lock);
    542         device = arp_cache_find(&arp_globals.cache, device_id);
    543         if(! device){
    544                 fibril_rwlock_write_unlock(&arp_globals.lock);
    545                 return ENOENT;
    546         }
    547         device->packet_dimension.content = mtu;
    548         printf("arp - device %d changed mtu to %d\n\n", device_id, mtu);
     364        arp_globals.client_connection = client_connection;
     365        ERROR_PROPAGATE(arp_cache_initialize(&arp_globals.cache));
    549366        fibril_rwlock_write_unlock(&arp_globals.lock);
    550367        return EOK;
     
    618435}
    619436
     437int arp_mtu_changed_message(device_id_t device_id, size_t mtu){
     438        arp_device_ref device;
     439
     440        fibril_rwlock_write_lock(&arp_globals.lock);
     441        device = arp_cache_find(&arp_globals.cache, device_id);
     442        if(! device){
     443                fibril_rwlock_write_unlock(&arp_globals.lock);
     444                return ENOENT;
     445        }
     446        device->packet_dimension.content = mtu;
     447        printf("arp - device %d changed mtu to %d\n\n", device_id, mtu);
     448        fibril_rwlock_write_unlock(&arp_globals.lock);
     449        return EOK;
     450}
     451
     452int arp_proto_create(arp_proto_ref * proto, services_t service, measured_string_ref address){
     453        ERROR_DECLARE;
     454
     455        *proto = (arp_proto_ref) malloc(sizeof(arp_proto_t));
     456        if(!(*proto)){
     457                return ENOMEM;
     458        }
     459        (** proto).service = service;
     460        (** proto).addr = address;
     461        (** proto).addr_data = address->value;
     462        if(ERROR_OCCURRED(arp_addr_initialize(&(** proto).addresses))){
     463                free(*proto);
     464                return ERROR_CODE;
     465        }
     466        return EOK;
     467}
     468
     469int arp_receive_message(device_id_t device_id, packet_t packet){
     470        ERROR_DECLARE;
     471
     472        size_t length;
     473        arp_header_ref header;
     474        arp_device_ref device;
     475        arp_proto_ref proto;
     476        measured_string_ref hw_source;
     477        uint8_t * src_hw;
     478        uint8_t * src_proto;
     479        uint8_t * des_hw;
     480        uint8_t * des_proto;
     481
     482        length = packet_get_data_length(packet);
     483        if(length <= sizeof(arp_header_t)){
     484                return EINVAL;
     485        }
     486        device = arp_cache_find(&arp_globals.cache, device_id);
     487        if(! device){
     488                return ENOENT;
     489        }
     490        header = (arp_header_ref) packet_get_data(packet);
     491        if((ntohs(header->hardware) != device->hardware)
     492                || (length < sizeof(arp_header_t) + header->hardware_length * 2u + header->protocol_length * 2u)){
     493                return EINVAL;
     494        }
     495        proto = arp_protos_find(&device->protos, protocol_unmap(device->service, ntohs(header->protocol)));
     496        if(! proto){
     497                return ENOENT;
     498        }
     499        src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
     500        src_proto = src_hw + header->hardware_length;
     501        des_hw = src_proto + header->protocol_length;
     502        des_proto = des_hw + header->hardware_length;
     503        hw_source = arp_addr_find(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length));
     504        // exists?
     505        if(hw_source){
     506                if(hw_source->length != CONVERT_SIZE(uint8_t, char, header->hardware_length)){
     507                        return EINVAL;
     508                }
     509                memcpy(hw_source->value, src_hw, hw_source->length);
     510        }
     511        // is my protocol address?
     512        if(proto->addr->length != CONVERT_SIZE(uint8_t, char, header->protocol_length)){
     513                return EINVAL;
     514        }
     515        if(! str_lcmp(proto->addr->value, (char *) des_proto, proto->addr->length)){
     516                // not already upadted?
     517                if(! hw_source){
     518                        hw_source = measured_string_create_bulk((char *) src_hw, CONVERT_SIZE(uint8_t, char, header->hardware_length));
     519                        if(! hw_source){
     520                                return ENOMEM;
     521                        }
     522                        ERROR_PROPAGATE(arp_addr_add(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length), hw_source));
     523                }
     524                if(ntohs(header->operation) == ARPOP_REQUEST){
     525                        header->operation = htons(ARPOP_REPLY);
     526                        memcpy(des_proto, src_proto, header->protocol_length);
     527                        memcpy(src_proto, proto->addr->value, header->protocol_length);
     528                        memcpy(src_hw, device->addr->value, device->packet_dimension.addr_len);
     529                        memcpy(des_hw, hw_source->value, header->hardware_length);
     530                        ERROR_PROPAGATE(packet_set_addr(packet, src_hw, des_hw, header->hardware_length));
     531                        nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
     532                        return 1;
     533                }
     534        }
     535        return EOK;
     536}
     537
     538task_id_t arp_task_get_id(void){
     539        return task_get_id();
     540}
     541
     542measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target){
     543        arp_device_ref device;
     544        arp_proto_ref proto;
     545        measured_string_ref addr;
     546        size_t length;
     547        packet_t packet;
     548        arp_header_ref header;
     549
     550        if(! target){
     551                return NULL;
     552        }
     553        device = arp_cache_find(&arp_globals.cache, device_id);
     554        if(! device){
     555                return NULL;
     556        }
     557        proto = arp_protos_find(&device->protos, protocol);
     558        if((! proto) || (proto->addr->length != target->length)){
     559                return NULL;
     560        }
     561        addr = arp_addr_find(&proto->addresses, target->value, target->length);
     562        if(addr){
     563                return addr;
     564        }
     565        // ARP packet content size = header + (address + translation) * 2
     566        length = 8 + (CONVERT_SIZE(char, uint8_t, proto->addr->length) + CONVERT_SIZE(char, uint8_t, device->addr->length)) * 2;
     567        if(length > device->packet_dimension.content){
     568                return NULL;
     569        }
     570        packet = packet_get_4(arp_globals.net_phone, device->packet_dimension.addr_len, device->packet_dimension.prefix, length, device->packet_dimension.suffix);
     571        if(! packet){
     572                return NULL;
     573        }
     574        header = (arp_header_ref) packet_suffix(packet, length);
     575        if(! header){
     576                pq_release(arp_globals.net_phone, packet_get_id(packet));
     577                return NULL;
     578        }
     579        header->hardware = htons(device->hardware);
     580        header->hardware_length = (uint8_t) device->addr->length;
     581        header->protocol = htons(protocol_map(device->service, protocol));
     582        header->protocol_length = (uint8_t) proto->addr->length;
     583        header->operation = htons(ARPOP_REQUEST);
     584        length = sizeof(arp_header_t);
     585        memcpy(((uint8_t *) header) + length, device->addr->value, device->addr->length);
     586        length += device->addr->length;
     587        memcpy(((uint8_t *) header) + length, proto->addr->value, proto->addr->length);
     588        length += proto->addr->length;
     589        bzero(((uint8_t *) header) + length, device->addr->length);
     590        length += device->addr->length;
     591        memcpy(((uint8_t *) header) + length, target->value, target->length);
     592        if(packet_set_addr(packet, (uint8_t *) device->addr->value, (uint8_t *) device->broadcast_addr->value, CONVERT_SIZE(char, uint8_t, device->addr->length)) != EOK){
     593                pq_release(arp_globals.net_phone, packet_get_id(packet));
     594                return NULL;
     595        }
     596        nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
     597        return NULL;
     598}
     599
     600int arp_translate_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address, measured_string_ref * translation, char ** data){
     601        measured_string_ref tmp;
     602
     603        fibril_rwlock_read_lock(&arp_globals.lock);
     604        tmp = arp_translate_message(device_id, protocol, address);
     605        if(tmp){
     606                *translation = measured_string_copy(tmp);
     607                fibril_rwlock_read_unlock(&arp_globals.lock);
     608                if(*translation){
     609                        *data = (** translation).value;
     610                        return EOK;
     611                }else{
     612                        return ENOMEM;
     613                }
     614        }else{
     615                fibril_rwlock_read_unlock(&arp_globals.lock);
     616                return ENOENT;
     617        }
     618}
     619
    620620/** @}
    621621 */
  • uspace/srv/net/il/arp/arp.h

    r71b00dcc r60ab6c3  
    5151
    5252
    53 /** Type definition of the ARP global data.
    54  *  @see arp_globals
    55  */
    56 typedef struct arp_globals      arp_globals_t;
    57 
    5853/** Type definition of the ARP device specific data.
    5954 *  @see arp_device
     
    6661typedef arp_device_t *          arp_device_ref;
    6762
     63/** Type definition of the ARP global data.
     64 *  @see arp_globals
     65 */
     66typedef struct arp_globals      arp_globals_t;
     67
    6868/** Type definition of the ARP protocol specific data.
    6969 *  @see arp_proto
     
    7575 */
    7676typedef arp_proto_t *           arp_proto_ref;
     77
     78/** ARP address map.
     79 *  Translates addresses.
     80 *  @see generic_char_map.h
     81 */
     82GENERIC_CHAR_MAP_DECLARE(arp_addr, measured_string_t)
    7783
    7884/** ARP address cache.
     
    8894INT_MAP_DECLARE(arp_protos, arp_proto_t)
    8995
    90 /** ARP address map.
    91  *  Translates addresses.
    92  *  @see generic_char_map.h
    93  */
    94 GENERIC_CHAR_MAP_DECLARE(arp_addr, measured_string_t)
    95 
    9696/** ARP device specific data.
    9797 */
    9898struct arp_device{
    99         /** Device identifier.
    100          */
    101         device_id_t device_id;
    102         /** Hardware type.
    103          */
    104         hw_type_t hardware;
    105         /** Packet dimension.
    106          */
    107         packet_dimension_t packet_dimension;
    10899        /** Actual device hardware address.
    109100         */
     
    118109         */
    119110        char * broadcast_data;
    120         /** Device module service.
     111        /** Device identifier.
    121112         */
    122         services_t service;
     113        device_id_t device_id;
     114        /** Hardware type.
     115         */
     116        hw_type_t hardware;
     117        /** Packet dimension.
     118         */
     119        packet_dimension_t packet_dimension;
    123120        /** Device module phone.
    124121         */
     
    128125         */
    129126        arp_protos_t protos;
     127        /** Device module service.
     128         */
     129        services_t service;
     130};
     131
     132/** ARP global data.
     133 */
     134struct  arp_globals{
     135        /** ARP address cache.
     136         */
     137        arp_cache_t cache;
     138        /** The client connection processing function.
     139         *  The module skeleton propagates its own one.
     140         */
     141        async_client_conn_t client_connection;
     142        /** Networking module phone.
     143         */
     144        int net_phone;
     145        /** Safety lock.
     146         */
     147        fibril_rwlock_t lock;
    130148};
    131149
     
    133151 */
    134152struct arp_proto{
    135         /** Protocol service.
    136          */
    137         services_t service;
    138153        /** Actual device protocol address.
    139154         */
     
    145160         */
    146161        arp_addr_t addresses;
    147 };
    148 
    149 /** ARP global data.
    150  */
    151 struct  arp_globals{
    152         /** Networking module phone.
     162        /** Protocol service.
    153163         */
    154         int net_phone;
    155         /** Safety lock.
    156          */
    157         fibril_rwlock_t lock;
    158         /** ARP address cache.
    159          */
    160         arp_cache_t cache;
    161         /** The client connection processing function.
    162          *  The module skeleton propagates its own one.
    163          */
    164         async_client_conn_t client_connection;
     164        services_t service;
    165165};
    166166
  • uspace/srv/net/il/arp/arp_messages.h

    r71b00dcc r60ab6c3  
    4646 */
    4747typedef enum{
    48         /** New device message.
    49          *  @see arp_device_req()
     48        /** Clean cache message.
     49         *  @see arp_clean_cache()
    5050         */
    51         NET_ARP_DEVICE = NET_ARP_FIRST,
    52         /** Address translation message.
    53          *  @see arp_translate_req()
     51        NET_ARP_CLEAN_CACHE = NET_ARP_FIRST,
     52        /** Clear address cache message.
     53         *  @see arp_clear_address_msg()
    5454         */
    55         NET_ARP_TRANSLATE,
     55        NET_ARP_CLEAR_ADDRESS,
    5656        /** Clear device cache message.
    5757         *  @see arp_clear_device_req()
    5858         */
    5959        NET_ARP_CLEAR_DEVICE,
    60         /** Clear address cache message.
    61          *  @see arp_clear_address_msg()
     60        /** New device message.
     61         *  @see arp_device_req()
    6262         */
    63         NET_ARP_CLEAR_ADDRESS,
    64         /** Clean cache message.
    65          *  @see arp_clean_cache()
     63        NET_ARP_DEVICE,
     64        /** Address translation message.
     65         *  @see arp_translate_req()
    6666         */
    67         NET_ARP_CLEAN_CACHE,
     67        NET_ARP_TRANSLATE
    6868} arp_messages;
    6969
  • uspace/srv/net/il/arp/arp_module.c

    r71b00dcc r60ab6c3  
    5858#define NAME    "ARP protocol"
    5959
     60/** ARP module global data.
     61 */
     62extern arp_globals_t    arp_globals;
     63
     64/** Processes the ARP message.
     65 *  @param[in] callid The message identifier.
     66 *  @param[in] call The message parameters.
     67 *  @param[out] answer The message answer parameters.
     68 *  @param[out] answer_count The last parameter for the actual answer in the answer parameter.
     69 *  @returns EOK on success.
     70 *  @returns Other error codes as defined for the arp_message() function.
     71 */
     72int module_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
     73
    6074/** Prints the module name.
    6175 *  @see NAME
     
    7286int module_start(async_client_conn_t client_connection);
    7387
    74 /** Processes the ARP message.
    75  *  @param[in] callid The message identifier.
    76  *  @param[in] call The message parameters.
    77  *  @param[out] answer The message answer parameters.
    78  *  @param[out] answer_count The last parameter for the actual answer in the answer parameter.
    79  *  @returns EOK on success.
    80  *  @returns Other error codes as defined for the arp_message() function.
    81  */
    82 int module_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
    83 
    84 /** ARP module global data.
    85  */
    86 extern arp_globals_t    arp_globals;
     88int module_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
     89        return arp_message(callid, call, answer, answer_count);
     90}
    8791
    8892void module_print_name(void){
     
    110114}
    111115
    112 int module_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
    113         return arp_message(callid, call, answer, answer_count);
    114 }
    115 
    116116/** @}
    117117 */
  • uspace/srv/net/il/arp/arp_oc.h

    r71b00dcc r60ab6c3  
    4444/** REQUEST operation code.
    4545 */
    46 #define ARPOP_REQUEST           1
     46#define ARPOP_REQUEST                                   1
    4747
    4848/** REPLY operation code.
    4949 */
    50 #define ARPOP_REPLY             2
     50#define ARPOP_REPLY                                             2
    5151
    5252/** Reverse request operation code.
    5353 */
    54 #define ARPOP_RREQUEST          3
     54#define ARPOP_RREQUEST                                  3
    5555
    5656/** Reverse reply operation code.
    5757 */
    58 #define ARPOP_RREPLY            4
     58#define ARPOP_RREPLY                                    4
    5959
    6060/** DRARP-Request operation code.
    6161 */
    62 #define ARPOP_DRARP_Request             5
     62#define ARPOP_DRARP_Request                             5
    6363
    6464/** DRARP-Reply operation code.
    6565 */
    66 #define ARPOP_DRARP_Reply               6
     66#define ARPOP_DRARP_Reply                               6
    6767
    6868/** DRARP-Error operation code.
    6969 */
    70 #define ARPOP_DRARP_Error               7
     70#define ARPOP_DRARP_Error                               7
    7171
    7272/** InARP-Request operation code.
    7373 */
    74 #define ARPOP_InREQUEST         8
     74#define ARPOP_InREQUEST                                 8
    7575
    7676/** InARP-Reply operation code.
    7777 */
    78 #define ARPOP_InREPLY           9
     78#define ARPOP_InREPLY                                   9
    7979
    8080/** ARP-NAK operation code.
    8181 */
    82 #define ARPOP_NAK               10
     82#define ARPOP_NAK                                               10
    8383
    8484/** MARS-Request operation code.
    8585 */
    86 #define ARPOP_MARS_Request              11
     86#define ARPOP_MARS_Request                              11
    8787
    8888/** MARS-Multi operation code.
    8989 */
    90 #define ARPOP_MARS_Multi                12
     90#define ARPOP_MARS_Multi                                12
    9191
    9292/** MARS-MServ operation code.
    9393 */
    94 #define ARPOP_MARS_MServ                13
     94#define ARPOP_MARS_MServ                                13
    9595
    9696/** MARS-Join operation code.
    9797 */
    98 #define ARPOP_MARS_Join         14
     98#define ARPOP_MARS_Join                                 14
    9999
    100100/** MARS-Leave operation code.
    101101 */
    102 #define ARPOP_MARS_Leave                15
     102#define ARPOP_MARS_Leave                                15
    103103
    104104/** MARS-NAK operation code.
    105105 */
    106 #define ARPOP_MARS_NAK          16
     106#define ARPOP_MARS_NAK                                  16
    107107
    108108/** MARS-Unserv operation code.
    109109 */
    110 #define ARPOP_MARS_Unserv               17
     110#define ARPOP_MARS_Unserv                               17
    111111
    112112/** MARS-SJoin operation code.
    113113 */
    114 #define ARPOP_MARS_SJoin                18
     114#define ARPOP_MARS_SJoin                                18
    115115
    116116/** MARS-SLeave operation code.
    117117 */
    118 #define ARPOP_MARS_SLeave               19
     118#define ARPOP_MARS_SLeave                               19
    119119
    120120/** MARS-Grouplist-Request operation code.
    121121 */
    122 #define ARPOP_MARS_Grouplist_Request            20
     122#define ARPOP_MARS_Grouplist_Request    20
    123123
    124124/** MARS-Grouplist-Reply operation code.
     
    128128/** MARS-Redirect-Map operation code.
    129129 */
    130 #define ARPOP_MARS_Redirect_Map         22
     130#define ARPOP_MARS_Redirect_Map                 22
    131131
    132132/** MAPOS-UNARP operation code.
    133133 */
    134 #define ARPOP_MAPOS_UNARP               23
     134#define ARPOP_MAPOS_UNARP                               23
    135135
    136136/*@}*/
  • uspace/srv/net/il/arp/arp_remote.c

    r71b00dcc r60ab6c3  
    5252#include "arp_messages.h"
    5353
    54 int arp_device_req(int arp_phone, device_id_t device_id, services_t protocol, services_t netif, measured_string_ref address){
    55         aid_t message_id;
    56         ipcarg_t result;
    57 
    58         message_id = async_send_3(arp_phone, NET_ARP_DEVICE, (ipcarg_t) device_id, protocol, netif, NULL);
    59         measured_strings_send(arp_phone, address, 1);
    60         async_wait_for(message_id, &result);
    61         return (int) result;
     54int arp_connect_module(services_t service){
     55        if(service != SERVICE_ARP){
     56                return EINVAL;
     57        }
     58        return connect_to_service(SERVICE_ARP);
    6259}
    6360
    64 int arp_translate_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address, measured_string_ref * translation, char ** data){
    65         return generic_translate_req(arp_phone, NET_ARP_TRANSLATE, device_id, protocol, address, 1, translation, data);
    66 }
    67 
    68 int arp_clear_device_req(int arp_phone, device_id_t device_id){
    69         return (int) async_req_1_0(arp_phone, NET_ARP_CLEAR_DEVICE, (ipcarg_t) device_id);
     61int arp_clean_cache_req(int arp_phone){
     62        return (int) async_req_0_0(arp_phone, NET_ARP_CLEAN_CACHE);
    7063}
    7164
     
    8073}
    8174
    82 int arp_clean_cache_req(int arp_phone){
    83         return (int) async_req_0_0(arp_phone, NET_ARP_CLEAN_CACHE);
     75int arp_clear_device_req(int arp_phone, device_id_t device_id){
     76        return (int) async_req_1_0(arp_phone, NET_ARP_CLEAR_DEVICE, (ipcarg_t) device_id);
    8477}
    8578
    86 int arp_connect_module(services_t service){
    87         if(service != SERVICE_ARP){
    88                 return EINVAL;
    89         }
    90         return connect_to_service(SERVICE_ARP);
     79int arp_device_req(int arp_phone, device_id_t device_id, services_t protocol, services_t netif, measured_string_ref address){
     80        aid_t message_id;
     81        ipcarg_t result;
     82
     83        message_id = async_send_3(arp_phone, NET_ARP_DEVICE, (ipcarg_t) device_id, protocol, netif, NULL);
     84        measured_strings_send(arp_phone, address, 1);
     85        async_wait_for(message_id, &result);
     86        return (int) result;
    9187}
    9288
     
    9591}
    9692
     93int arp_translate_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address, measured_string_ref * translation, char ** data){
     94        return generic_translate_req(arp_phone, NET_ARP_TRANSLATE, device_id, protocol, address, 1, translation, data);
     95}
     96
    9797/** @}
    9898 */
  • uspace/srv/net/il/il_messages.h

    r71b00dcc r60ab6c3  
    5353         */
    5454        NET_IL_DEVICE_STATE,
     55        /** Device MTU changed message.
     56         *  @see il_mtu_changed_msg()
     57         */
     58        NET_IL_MTU_CHANGED,
     59        /** Packet size message.
     60         *  @see il_packet_size_req()
     61         */
     62        NET_IL_PACKET_SPACE,
    5563        /** Packet received message.
    5664         *  @see il_received_msg()
     
    6068         *  @see il_send_msg()
    6169         */
    62         NET_IL_SEND,
    63         /** Packet size message.
    64          *  @see il_packet_size_req()
    65          */
    66         NET_IL_PACKET_SPACE,
    67         /** Device MTU changed message.
    68          *  @see il_mtu_changed_msg()
    69          */
    70         NET_IL_MTU_CHANGED
     70        NET_IL_SEND
    7171} il_messages;
    7272
     
    8383 *  @param[in] call The message call structure.
    8484 */
    85 #define IL_GET_SERVICE(call)            (services_t) IPC_GET_ARG2(*call)
     85#define IL_GET_SERVICE(call)    (services_t) IPC_GET_ARG2(*call)
    8686
    8787/*@}*/
  • uspace/srv/net/il/ip/ip.h

    r71b00dcc r60ab6c3  
    106106 */
    107107struct  ip_netif{
    108         /** Device identifier.
    109          */
    110         device_id_t device_id;
    111         /** Netif module service.
    112          */
    113         services_t service;
    114         /** Netif module phone.
    115          */
    116         int phone;
    117108        /** ARP module.
    118109         *  Assigned if using ARP.
    119110         */
    120111        module_ref arp;
     112        /** Broadcast address.
     113         */
     114        in_addr_t broadcast;
     115        /** Device identifier.
     116         */
     117        device_id_t device_id;
     118        /** Indicates whether using DHCP.
     119         */
     120        int dhcp;
    121121        /** IP version.
    122122         */
    123123        int ipv;
    124         /** Indicates whether using DHCP.
    125          */
    126         int dhcp;
     124        /** Packet dimension.
     125         */
     126        packet_dimension_t packet_dimension;
     127        /** Netif module phone.
     128         */
     129        int phone;
     130        /** Routing table.
     131         */
     132        ip_routes_t routes;
    127133        /** Indicates whether IP routing is enabled.
    128134         */
    129135        int routing;
     136        /** Netif module service.
     137         */
     138        services_t service;
    130139        /** Device state.
    131140         */
    132141        device_state_t state;
    133         /** Broadcast address.
    134          */
    135         in_addr_t broadcast;
    136         /** Routing table.
    137          */
    138         ip_routes_t routes;
    139         /** Packet dimension.
    140          */
    141         packet_dimension_t packet_dimension;
    142142};
    143143
     
    145145 */
    146146struct ip_proto{
     147        /** Protocol module phone.
     148         */
     149        int phone;
    147150        /** Protocol number.
    148151         */
    149152        int protocol;
     153        /** Protocol packet receiving function.
     154         */
     155        tl_received_msg_t received_msg;
    150156        /** Protocol module service.
    151157         */
    152158        services_t service;
    153         /** Protocol module phone.
    154          */
    155         int phone;
    156         /** Protocol packet receiving function.
    157          */
    158         tl_received_msg_t received_msg;
    159159};
    160160
     
    165165         */
    166166        in_addr_t address;
    167         /** Target network mask.
    168          */
    169         in_addr_t netmask;
    170167        /** Gateway.
    171168         */
     
    174171         */
    175172        ip_netif_ref netif;
     173        /** Target network mask.
     174         */
     175        in_addr_t netmask;
    176176};
    177177
     
    179179 */
    180180struct  ip_globals{
     181        /** Default client connection function for support modules.
     182         */
     183        async_client_conn_t client_connection;
     184        /** Default gateway.
     185         */
     186        ip_route_t gateway;
     187        /** Safety lock.
     188         */
     189        fibril_rwlock_t lock;
     190        /** Known support modules.
     191         */
     192        modules_t modules;
    181193        /** Networking module phone.
    182194         */
     
    188200         */
    189201        fibril_rwlock_t netifs_lock;
     202        /** Packet counter.
     203         */
     204        uint16_t packet_counter;
    190205        /** Registered protocols.
    191206         */
     
    194209         */
    195210        fibril_rwlock_t protos_lock;
    196         /** Default gateway.
    197          */
    198         ip_route_t gateway;
    199         /** Known support modules.
    200          */
    201         modules_t modules;
    202         /** Default client connection function for support modules.
    203          */
    204         async_client_conn_t client_connection;
    205         /** Packet counter.
    206          */
    207         uint16_t packet_counter;
    208         /** Safety lock.
    209          */
    210         fibril_rwlock_t lock;
    211211};
    212212
  • uspace/srv/net/il/ip/ip_client.c

    r71b00dcc r60ab6c3  
    4848#include "ip_header.h"
    4949
    50 int ip_client_prepare_packet(packet_t packet, ip_protocol_t protocol, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, size_t ipopt_length){
    51         ip_header_ref header;
    52         uint8_t * data;
    53         size_t padding;
    54 
    55         padding =  ipopt_length % 4;
    56         if(padding){
    57                 padding = 4 - padding;
    58                 ipopt_length += padding;
    59         }
    60         data = (uint8_t *) packet_prefix(packet, sizeof(ip_header_t) + padding);
    61         if(! data){
    62                 return ENOMEM;
    63         }
    64         while(padding --){
    65                 data[sizeof(ip_header_t) + padding] = IPOPT_NOOP;
    66         }
    67         header = (ip_header_ref) data;
    68         header->header_length = IP_COMPUTE_HEADER_LENGTH(sizeof(ip_header_t) + ipopt_length);
    69         header->ttl = (ttl ? ttl : IPDEFTTL); //(((ttl) <= MAXTTL) ? ttl : MAXTTL) : IPDEFTTL;
    70         header->tos = tos;
    71         header->protocol = protocol;
    72         if(dont_fragment){
    73                 header->flags = IPFLAG_DONT_FRAGMENT;
    74         }
    75         return EOK;
    76 }
    77 
    78 int ip_client_process_packet(packet_t packet, ip_protocol_t * protocol, ip_ttl_t * ttl, ip_tos_t * tos, int * dont_fragment, size_t * ipopt_length){
    79         ip_header_ref header;
    80 
    81         header = (ip_header_ref) packet_get_data(packet);
    82         if((! header)
    83                 || (packet_get_data_length(packet) < sizeof(ip_header_t))){
    84                 return ENOMEM;
    85         }
    86         if(protocol){
    87                 *protocol = header->protocol;
    88         }
    89         if(ttl){
    90                 *ttl = header->ttl;
    91         }
    92         if(tos){
    93                 *tos = header->tos;
    94         }
    95         if(dont_fragment){
    96                 *dont_fragment = header->flags &IPFLAG_DONT_FRAGMENT;
    97         }
    98         if(ipopt_length){
    99                 *ipopt_length = IP_HEADER_LENGTH(header) - sizeof(ip_header_t);
    100                 return sizeof(ip_header_t);
    101         }else{
    102                 return IP_HEADER_LENGTH(header);
    103         }
    104 }
    105 
    10650size_t ip_client_header_length(packet_t packet){
    10751        ip_header_ref header;
     
    11357        }
    11458        return IP_HEADER_LENGTH(header);
    115 }
    116 
    117 int ip_client_set_pseudo_header_data_length(ip_pseudo_header_ref header, size_t headerlen, size_t data_length){
    118         ipv4_pseudo_header_ref header_in;
    119 
    120         if(! header){
    121                 return EBADMEM;
    122         }
    123         if(headerlen == sizeof(ipv4_pseudo_header_t)){
    124                 header_in = (ipv4_pseudo_header_ref) header;
    125                 header_in->data_length = htons(data_length);
    126                 return EOK;
    127         }else{
    128                 return EINVAL;
    129         }
    13059}
    13160
     
    14069                return EINVAL;
    14170        }
     71
    14272        switch(src->sa_family){
    14373                case AF_INET:
     
    171101}
    172102
     103int ip_client_prepare_packet(packet_t packet, ip_protocol_t protocol, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, size_t ipopt_length){
     104        ip_header_ref header;
     105        uint8_t * data;
     106        size_t padding;
     107
     108        // compute the padding if IP options are set
     109        // multiple of 4 bytes
     110        padding =  ipopt_length % 4;
     111        if(padding){
     112                padding = 4 - padding;
     113                ipopt_length += padding;
     114        }
     115
     116        // prefix the header
     117        data = (uint8_t *) packet_prefix(packet, sizeof(ip_header_t) + padding);
     118        if(! data){
     119                return ENOMEM;
     120        }
     121
     122        // add the padding
     123        while(padding --){
     124                data[sizeof(ip_header_t) + padding] = IPOPT_NOOP;
     125        }
     126
     127        // set the header
     128        header = (ip_header_ref) data;
     129        header->header_length = IP_COMPUTE_HEADER_LENGTH(sizeof(ip_header_t) + ipopt_length);
     130        header->ttl = (ttl ? ttl : IPDEFTTL); //(((ttl) <= MAXTTL) ? ttl : MAXTTL) : IPDEFTTL;
     131        header->tos = tos;
     132        header->protocol = protocol;
     133
     134        if(dont_fragment){
     135                header->flags = IPFLAG_DONT_FRAGMENT;
     136        }
     137        return EOK;
     138}
     139
     140int ip_client_process_packet(packet_t packet, ip_protocol_t * protocol, ip_ttl_t * ttl, ip_tos_t * tos, int * dont_fragment, size_t * ipopt_length){
     141        ip_header_ref header;
     142
     143        header = (ip_header_ref) packet_get_data(packet);
     144        if((! header)
     145                || (packet_get_data_length(packet) < sizeof(ip_header_t))){
     146                return ENOMEM;
     147        }
     148
     149        if(protocol){
     150                *protocol = header->protocol;
     151        }
     152        if(ttl){
     153                *ttl = header->ttl;
     154        }
     155        if(tos){
     156                *tos = header->tos;
     157        }
     158        if(dont_fragment){
     159                *dont_fragment = header->flags &IPFLAG_DONT_FRAGMENT;
     160        }
     161        if(ipopt_length){
     162                *ipopt_length = IP_HEADER_LENGTH(header) - sizeof(ip_header_t);
     163                return sizeof(ip_header_t);
     164        }else{
     165                return IP_HEADER_LENGTH(header);
     166        }
     167}
     168
     169int ip_client_set_pseudo_header_data_length(ip_pseudo_header_ref header, size_t headerlen, size_t data_length){
     170        ipv4_pseudo_header_ref header_in;
     171
     172        if(! header){
     173                return EBADMEM;
     174        }
     175
     176        if(headerlen == sizeof(ipv4_pseudo_header_t)){
     177                header_in = (ipv4_pseudo_header_ref) header;
     178                header_in->data_length = htons(data_length);
     179                return EOK;
     180        // TODO IPv6
     181        }else{
     182                return EINVAL;
     183        }
     184}
     185
    173186/** @}
    174187 */
  • uspace/srv/net/il/ip/ip_header.h

    r71b00dcc r60ab6c3  
    4242#include <sys/types.h>
    4343
    44 /** Returns the actual IP header length in bytes.
    45  *  @param[in] header The IP packet header.
    46  */
    47 #define IP_HEADER_LENGTH(header)                ((header)->header_length * 4u)
     44/** Returns the fragment offest high bits.
     45 *  @param[in] length The prefixed data total length.
     46 */
     47#define IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length) ((((length) / 8u) &0x1F00) >> 8)
     48
     49/** Returns the fragment offest low bits.
     50 *  @param[in] length The prefixed data total length.
     51 */
     52#define IP_COMPUTE_FRAGMENT_OFFSET_LOW(length) (((length) / 8u) &0xFF)
    4853
    4954/** Returns the IP header length.
     
    5257#define IP_COMPUTE_HEADER_LENGTH(length)                ((uint8_t) ((length) / 4u))
    5358
     59/** Returns the fragment offest.
     60 *  @param[in] header The IP packet header.
     61 */
     62#define IP_FRAGMENT_OFFSET(header) ((((header)->fragment_offset_high << 8) + (header)->fragment_offset_low) * 8u)
     63
     64/** Returns the IP packet header checksum.
     65 *  @param[in] header The IP packet header.
     66 */
     67#define IP_HEADER_CHECKSUM(header)      (htons(ip_checksum((uint8_t *)(header), IP_HEADER_LENGTH(header))))
     68
     69/** Returns the actual IP packet data length.
     70 *  @param[in] header The IP packet header.
     71 */
     72#define IP_HEADER_DATA_LENGTH(header)   (IP_TOTAL_LENGTH(header) - IP_HEADER_LENGTH(header))
     73
     74/** Returns the actual IP header length in bytes.
     75 *  @param[in] header The IP packet header.
     76 */
     77#define IP_HEADER_LENGTH(header)                ((header)->header_length * 4u)
     78
    5479/** Returns the actual IP packet total length.
    5580 *  @param[in] header The IP packet header.
     
    5782#define IP_TOTAL_LENGTH(header)         ntohs((header)->total_length)
    5883
    59 /** Returns the actual IP packet data length.
    60  *  @param[in] header The IP packet header.
    61  */
    62 #define IP_HEADER_DATA_LENGTH(header)   (IP_TOTAL_LENGTH(header) - IP_HEADER_LENGTH(header))
    63 
    64 /** Returns the IP packet header checksum.
    65  *  @param[in] header The IP packet header.
    66  */
    67 #define IP_HEADER_CHECKSUM(header)      (htons(ip_checksum((uint8_t *)(header), IP_HEADER_LENGTH(header))))
    68 
    69 /** Returns the fragment offest.
    70  *  @param[in] header The IP packet header.
    71  */
    72 #define IP_FRAGMENT_OFFSET(header) ((((header)->fragment_offset_high << 8) + (header)->fragment_offset_low) * 8u)
    73 
    74 /** Returns the fragment offest high bits.
    75  *  @param[in] length The prefixed data total length.
    76  */
    77 #define IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length) ((((length) / 8u) &0x1F00) >> 8)
    78 
    79 /** Returns the fragment offest low bits.
    80  *  @param[in] length The prefixed data total length.
    81  */
    82 #define IP_COMPUTE_FRAGMENT_OFFSET_LOW(length) (((length) / 8u) &0xFF)
     84/** @name IP flags definitions
     85 */
     86/*@{*/
     87
     88/** Fragment flag field shift.
     89 */
     90#define IPFLAG_FRAGMENT_SHIFT           1
     91
     92/** Fragmented flag field shift.
     93 */
     94#define IPFLAG_FRAGMENTED_SHIFT         0
     95
     96/** Don't fragment flag value.
     97 *  Permits the packet fragmentation.
     98 */
     99#define IPFLAG_DONT_FRAGMENT            (0x1 << IPFLAG_FRAGMENT_SHIFT)
     100
     101/** Last fragment flag value.
     102 *  Indicates the last packet fragment.
     103 */
     104#define IPFLAG_LAST_FRAGMENT            (0x0 << IPFLAG_FRAGMENTED_SHIFT)
     105
     106/** May fragment flag value.
     107 *  Allows the packet fragmentation.
     108 */
     109#define IPFLAG_MAY_FRAGMENT                     (0x0 << IPFLAG_FRAGMENT_SHIFT)
     110
     111/** More fragments flag value.
     112 *  Indicates that more packet fragments follow.
     113 */
     114#define IPFLAG_MORE_FRAGMENTS           (0x1 << IPFLAG_FRAGMENTED_SHIFT)
     115
     116/*@}*/
    83117
    84118/** Type definition of the internet header.
     
    91125 */
    92126typedef ip_header_t *           ip_header_ref;
     127
     128/** Type definition of the internet option header.
     129 *  @see ip_header
     130 */
     131typedef struct ip_option        ip_option_t;
     132
     133/** Type definition of the internet option header pointer.
     134 *  @see ip_header
     135 */
     136typedef ip_option_t *           ip_option_ref;
     137
     138/** Type definition of the internet version 4 pseudo header.
     139 *  @see ipv4_pseudo_header
     140 */
     141typedef struct ipv4_pseudo_header       ipv4_pseudo_header_t;
     142
     143/** Type definition of the internet version 4 pseudo header pointer.
     144 *  @see ipv4_pseudo_header
     145 */
     146typedef ipv4_pseudo_header_t *          ipv4_pseudo_header_ref;
    93147
    94148/** Internet header.
     
    171225} __attribute__ ((packed));
    172226
    173 /** Type definition of the internet option header.
    174  *  @see ip_header
    175  */
    176 typedef struct ip_option        ip_option_t;
    177 
    178 /** Type definition of the internet option header pointer.
    179  *  @see ip_header
    180  */
    181 typedef ip_option_t *           ip_option_ref;
    182 
    183227/** Internet option header.
    184228 *  Only type field is always valid.
     
    212256} __attribute__ ((packed));
    213257
    214 /** @name IP flags definitions
    215  */
    216 /*@{*/
    217 
    218 /** Fragment flag field shift.
    219  */
    220 #define IPFLAG_FRAGMENT_SHIFT           1
    221 
    222 /** Fragmented flag field shift.
    223  */
    224 #define IPFLAG_FRAGMENTED_SHIFT         0
    225 
    226 /** May fragment flag value.
    227  *  Allows the packet fragmentation.
    228  */
    229 #define IPFLAG_MAY_FRAGMENT                     (0x0 << IPFLAG_FRAGMENT_SHIFT)
    230 
    231 /** Don't fragment flag value.
    232  *  Permits the packet fragmentation.
    233  */
    234 #define IPFLAG_DONT_FRAGMENT            (0x1 << IPFLAG_FRAGMENT_SHIFT)
    235 
    236 /** Last fragment flag value.
    237  *  Indicates the last packet fragment.
    238  */
    239 #define IPFLAG_LAST_FRAGMENT            (0x0 << IPFLAG_FRAGMENTED_SHIFT)
    240 
    241 /** More fragments flag value.
    242  *  Indicates that more packet fragments follow.
    243  */
    244 #define IPFLAG_MORE_FRAGMENTS           (0x1 << IPFLAG_FRAGMENTED_SHIFT)
    245 
    246 /*@}*/
    247 
    248 /** Type definition of the internet version 4 pseudo header.
    249  *  @see ipv4_pseudo_header
    250  */
    251 typedef struct ipv4_pseudo_header       ipv4_pseudo_header_t;
    252 
    253 /** Type definition of the internet version 4 pseudo header pointer.
    254  *  @see ipv4_pseudo_header
    255  */
    256 typedef ipv4_pseudo_header_t *          ipv4_pseudo_header_ref;
    257 
    258258/** Internet version 4 pseudo header.
    259259 */
  • uspace/srv/net/il/ip/ip_messages.h

    r71b00dcc r60ab6c3  
    5151         */
    5252        NET_IP_ADD_ROUTE = NET_IP_FIRST,
    53         /** Sets the default gateway.
    54          *  @see ip_set_default_gateway()
     53        /** Gets the actual route information.
     54         *  @see ip_get_route()
    5555         */
    56         NET_IP_SET_GATEWAY,
     56        NET_IP_GET_ROUTE,
    5757        /** Processes the received error notification.
    5858         *  @see ip_received_error_msg()
    5959         */
    6060        NET_IP_RECEIVED_ERROR,
    61         /** Gets the actual route information.
    62          *  @see ip_get_route()
     61        /** Sets the default gateway.
     62         *  @see ip_set_default_gateway()
    6363         */
    64         NET_IP_GET_ROUTE
     64        NET_IP_SET_GATEWAY
    6565} ip_messages;
    6666
     
    6969/*@{*/
    7070
     71/** Returns the address message parameter.
     72 *  @param[in] call The message call structure.
     73 */
     74#define IP_GET_ADDRESS(call)            ({in_addr_t addr; addr.s_addr = IPC_GET_ARG3(*call); addr;})
     75
    7176/** Returns the gateway message parameter.
    7277 *  @param[in] call The message call structure.
     
    7479#define IP_GET_GATEWAY(call)            ({in_addr_t addr; addr.s_addr = IPC_GET_ARG2(*call); addr;})
    7580
    76 /** Returns the address message parameter.
    77  *  @param[in] call The message call structure.
     81/** Sets the header length in the message answer.
     82 *  @param[out] answer The message answer structure.
    7883 */
    79 #define IP_GET_ADDRESS(call)            ({in_addr_t addr; addr.s_addr = IPC_GET_ARG3(*call); addr;})
     84#define IP_SET_HEADERLEN(answer)        ((size_t *) &IPC_GET_ARG2(*answer))
    8085
    8186/** Returns the network mask message parameter.
     
    8994#define IP_GET_PROTOCOL(call)           ((ip_protocol_t) IPC_GET_ARG1(*call))
    9095
    91 /** Sets the header length in the message answer.
    92  *  @param[out] answer The message answer structure.
    93  */
    94 #define IP_SET_HEADERLEN(answer)        ((size_t *) &IPC_GET_ARG2(*answer))
    95 
    9696/*@}*/
    9797
  • uspace/srv/net/il/ip/ip_module.c

    r71b00dcc r60ab6c3  
    5858#define NAME    "IP protocol"
    5959
     60/** IP module global data.
     61 */
     62extern ip_globals_t     ip_globals;
     63
     64/** Processes the IP message.
     65 *  @param[in] callid The message identifier.
     66 *  @param[in] call The message parameters.
     67 *  @param[out] answer The message answer parameters.
     68 *  @param[out] answer_count The last parameter for the actual answer in the answer parameter.
     69 *  @returns EOK on success.
     70 *  @returns Other error codes as defined for the ip_message() function.
     71 */
     72int module_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
     73
    6074/** Prints the module name.
    6175 *  @see NAME
     
    7286int module_start(async_client_conn_t client_connection);
    7387
    74 /** Processes the IP message.
    75  *  @param[in] callid The message identifier.
    76  *  @param[in] call The message parameters.
    77  *  @param[out] answer The message answer parameters.
    78  *  @param[out] answer_count The last parameter for the actual answer in the answer parameter.
    79  *  @returns EOK on success.
    80  *  @returns Other error codes as defined for the ip_message() function.
    81  */
    82 int module_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
    83 
    84 /** IP module global data.
    85  */
    86 extern ip_globals_t     ip_globals;
     88int module_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
     89        return ip_message(callid, call, answer, answer_count);
     90}
    8791
    8892void module_print_name(void){
     
    110114}
    111115
    112 int module_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
    113         return ip_message(callid, call, answer, answer_count);
    114 }
    115 
    116116/** @}
    117117 */
  • uspace/srv/net/il/ip/ip_remote.c

    r71b00dcc r60ab6c3  
    5252#include "ip_messages.h"
    5353
    54 int ip_device_req(int ip_phone, device_id_t device_id, services_t service){
    55         return generic_device_req(ip_phone, NET_IL_DEVICE, device_id, 0, service);
     54int ip_add_route_req(int ip_phone, device_id_t device_id, in_addr_t address, in_addr_t netmask, in_addr_t gateway){
     55        return (int) async_req_4_0(ip_phone, NET_IP_ADD_ROUTE, (ipcarg_t) device_id, (ipcarg_t) gateway.s_addr, (ipcarg_t) address.s_addr, (ipcarg_t) netmask.s_addr);
    5656}
    5757
    58 int ip_send_msg(int ip_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error){
    59         return generic_send_msg(ip_phone, NET_IL_SEND, device_id, packet_get_id(packet), sender, error);
     58int ip_bind_service(services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t tl_received_msg){
     59        return (int) bind_service(service, (ipcarg_t) protocol, me, service, receiver);
    6060}
    6161
     
    6464}
    6565
    66 int ip_add_route_req(int ip_phone, device_id_t device_id, in_addr_t address, in_addr_t netmask, in_addr_t gateway){
    67         return (int) async_req_4_0(ip_phone, NET_IP_ADD_ROUTE, (ipcarg_t) device_id, (ipcarg_t) gateway.s_addr, (ipcarg_t) address.s_addr, (ipcarg_t) netmask.s_addr);
    68 }
    69 
    70 int ip_set_gateway_req(int ip_phone, device_id_t device_id, in_addr_t gateway){
    71         return (int) async_req_2_0(ip_phone, NET_IP_SET_GATEWAY, (ipcarg_t) device_id, (ipcarg_t) gateway.s_addr);
    72 }
    73 
    74 int ip_packet_size_req(int ip_phone, device_id_t device_id, packet_dimension_ref packet_dimension){
    75         return generic_packet_size_req(ip_phone, NET_IL_PACKET_SPACE, device_id, packet_dimension);
    76 }
    77 
    78 int ip_bind_service(services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t tl_received_msg){
    79         return (int) bind_service(service, (ipcarg_t) protocol, me, service, receiver);
    80 }
    81 
    82 int ip_received_error_msg(int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error){
    83         return generic_received_msg(ip_phone, NET_IP_RECEIVED_ERROR, device_id, packet_get_id(packet), target, error);
     66int ip_device_req(int ip_phone, device_id_t device_id, services_t service){
     67        return generic_device_req(ip_phone, NET_IL_DEVICE, device_id, 0, service);
    8468}
    8569
     
    9579                return EBADMEM;
    9680        }
     81
    9782        *header = NULL;
    9883        message_id = async_send_1(ip_phone, NET_IP_GET_ROUTE, (ipcarg_t) protocol, &answer);
     
    10893        }
    10994        async_wait_for(message_id, &result);
     95
    11096        if((result != EOK) && (*header)){
    11197                free(*header);
     
    116102}
    117103
     104int ip_packet_size_req(int ip_phone, device_id_t device_id, packet_dimension_ref packet_dimension){
     105        return generic_packet_size_req(ip_phone, NET_IL_PACKET_SPACE, device_id, packet_dimension);
     106}
     107
     108int ip_received_error_msg(int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error){
     109        return generic_received_msg(ip_phone, NET_IP_RECEIVED_ERROR, device_id, packet_get_id(packet), target, error);
     110}
     111
     112int ip_send_msg(int ip_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error){
     113        return generic_send_msg(ip_phone, NET_IL_SEND, device_id, packet_get_id(packet), sender, error);
     114}
     115
     116int ip_set_gateway_req(int ip_phone, device_id_t device_id, in_addr_t gateway){
     117        return (int) async_req_2_0(ip_phone, NET_IP_SET_GATEWAY, (ipcarg_t) device_id, (ipcarg_t) gateway.s_addr);
     118}
     119
    118120/** @}
    119121 */
  • uspace/srv/net/inet.c

    r71b00dcc r60ab6c3  
    4545#include "include/socket_codes.h"
    4646
     47int inet_ntop(uint16_t family, const uint8_t * data, char * address, size_t length){
     48        if((! data) || (! address)){
     49                return EINVAL;
     50        }
     51
     52        switch(family){
     53                case AF_INET:
     54                        // check the output buffer size
     55                        if(length < INET_ADDRSTRLEN){
     56                                return ENOMEM;
     57                        }
     58                        // fill the buffer with the IPv4 address
     59                        snprintf(address, length, "%hhu.%hhu.%hhu.%hhu", data[0], data[1], data[2], data[3]);
     60                        return EOK;
     61                case AF_INET6:
     62                        // check the output buffer size
     63                        if(length < INET6_ADDRSTRLEN){
     64                                return ENOMEM;
     65                        }
     66                        // fill the buffer with the IPv6 address
     67                        snprintf(address, length, "%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);
     68                        return EOK;
     69                default:
     70                        return ENOTSUP;
     71        }
     72}
     73
    4774int inet_pton(uint16_t family, const char * address, uint8_t * data){
     75        /** The base number of the values.
     76         */
     77        int base;
     78        /** The number of bytes per a section.
     79         */
     80        size_t bytes;
     81        /** The number of bytes of the address data.
     82         */
     83        int count;
     84
    4885        const char * next;
    4986        char * last;
    5087        int index;
    51         int count;
    52         int base;
    53         size_t bytes;
    5488        size_t shift;
    5589        unsigned long value;
     
    5892                return EINVAL;
    5993        }
     94
     95        // set the processing parameters
    6096        switch(family){
    6197                case AF_INET:
     
    72108                        return ENOTSUP;
    73109        }
     110
     111        // erase if no address
    74112        if(! address){
    75113                bzero(data, count);
    76114                return ENOENT;
    77115        }
     116
     117        // process the string from the beginning
    78118        next = address;
    79119        index = 0;
    80120        do{
     121                // if the actual character is set
    81122                if(next && (*next)){
     123
     124                        // if not on the first character
    82125                        if(index){
     126                                // move to the next character
    83127                                ++ next;
    84128                        }
     129
     130                        // parse the actual integral value
    85131                        value = strtoul(next, &last, base);
     132                        // remember the last problematic character
     133                        // should be either '.' or ':' but is ignored to be more generic
    86134                        next = last;
     135
     136                        // fill the address data byte by byte
    87137                        shift = bytes - 1;
    88138                        do{
     
    91141                                value >>= 8;
    92142                        }while(shift --);
     143
    93144                        index += bytes;
    94145                }else{
     146                        // erase the rest of the address
    95147                        bzero(data + index, count - index);
    96148                        return EOK;
    97149                }
    98150        }while(index < count);
     151
    99152        return EOK;
    100 }
    101 
    102 int inet_ntop(uint16_t family, const uint8_t * data, char * address, size_t length){
    103         if((! data) || (! address)){
    104                 return EINVAL;
    105         }
    106         switch(family){
    107                 case AF_INET:
    108                         if(length < INET_ADDRSTRLEN){
    109                                 return ENOMEM;
    110                         }
    111                         snprintf(address, length, "%hhu.%hhu.%hhu.%hhu", data[0], data[1], data[2], data[3]);
    112                         return EOK;
    113                 case AF_INET6:
    114                         if(length < INET6_ADDRSTRLEN){
    115                                 return ENOMEM;
    116                         }
    117                         snprintf(address, length, "%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);
    118                         return EOK;
    119                 default:
    120                         return ENOTSUP;
    121         }
    122153}
    123154
  • uspace/srv/net/messages.h

    r71b00dcc r60ab6c3  
    4848#include "structures/packet/packet.h"
    4949
    50 /** @name Networking message counts
    51  */
    52 /*@{*/
    53 
    54 /** The number of network interface driver messages.
    55  */
    56 #define NET_NETIF_COUNT         6
    57 
    58 /** The number of general networking messages.
    59  */
    60 #define NET_NET_COUNT           3
    61 
    62 /** The number of network interface layer messages.
    63  */
    64 #define NET_NIL_COUNT           7
    65 
    66 /** The number of Ethernet messages.
    67  */
    68 #define NET_ETH_COUNT           0
    69 
    70 /** The number of inter-network messages.
    71  */
    72 #define NET_IL_COUNT            6
    73 
    74 /** The number of IP messages.
    75  */
    76 #define NET_IP_COUNT            4
    77 
    78 /** The number of ARP messages.
    79  */
    80 #define NET_ARP_COUNT           5
    81 
    82 /** The number of ICMP messages.
    83  */
    84 #define NET_ICMP_COUNT          6
    85 
    86 /** The number of transport layer messages.
    87  */
    88 #define NET_TL_COUNT            1
    89 
    90 /** The number of UDP messages.
    91  */
    92 #define NET_UDP_COUNT           0
    93 
    94 /** The number of TCP messages.
    95  */
    96 #define NET_TCP_COUNT           0
    97 
    98 /** The number of packet management system messages.
    99  */
    100 #define NET_PACKET_COUNT        5
    101 
    102 /** The number of socket messages.
    103  */
    104 #define NET_SOCKET_COUNT        14
    105 
    106 /*@}*/
    107 
    108 /** @name Networking message intervals
    109  */
    110 /*@{*/
    111 
    112 /** The first networking message.
    113  */
    114 #define NET_FIRST                       2000
    115 
    116 /** The first network interface layer message.
    117  */
    118 #define NET_NETIF_FIRST         NET_FIRST
    119 
    120 /** The last network interface layer message.
    121  */
    122 #define NET_NETIF_LAST          (NET_NETIF_FIRST + NET_NETIF_COUNT)
    123 
    124 /** The first general networking message.
    125  */
    126 #define NET_NET_FIRST           (NET_NETIF_LAST + 0)
    127 
    128 /** The last general networking message.
    129  */
    130 #define NET_NET_LAST            (NET_NET_FIRST + NET_NET_COUNT)
    131 
    132 /** The first network interface layer message.
    133  */
    134 #define NET_NIL_FIRST           (NET_NET_LAST + 0)
    135 
    136 /** The last network interface layer message.
    137  */
    138 #define NET_NIL_LAST            (NET_NIL_FIRST + NET_NIL_COUNT)
    139 
    140 /** The first Ethernet message.
    141  */
    142 #define NET_ETH_FIRST           (NET_NIL_LAST + 0)
    143 
    144 /** The last Ethernet message.
    145  */
    146 #define NET_ETH_LAST            (NET_ETH_FIRST + NET_ETH_COUNT)
    147 
    148 /** The first inter-network message.
    149  */
    150 #define NET_IL_FIRST            (NET_ETH_LAST + 0)
    151 
    152 /** The last inter-network message.
    153  */
    154 #define NET_IL_LAST                     (NET_IL_FIRST + NET_IL_COUNT)
    155 
    156 /** The first IP message.
    157  */
    158 #define NET_IP_FIRST            (NET_IL_LAST + 0)
    159 
    160 /** The last IP message.
    161  */
    162 #define NET_IP_LAST                     (NET_IP_FIRST + NET_IP_COUNT)
    163 
    164 /** The first ARP message.
    165  */
    166 #define NET_ARP_FIRST           (NET_IP_LAST + 0)
    167 
    168 /** The last ARP message.
    169  */
    170 #define NET_ARP_LAST            (NET_ARP_FIRST + NET_ARP_COUNT)
    171 
    172 /** The first ICMP message.
    173  */
    174 #define NET_ICMP_FIRST          (NET_ARP_LAST + 0)
    175 
    176 /** The last ICMP message.
    177  */
    178 #define NET_ICMP_LAST           (NET_ICMP_FIRST + NET_ICMP_COUNT)
    179 
    180 /** The first ICMP message.
    181  */
    182 #define NET_TL_FIRST            (NET_ICMP_LAST + 0)
    183 
    184 /** The last ICMP message.
    185  */
    186 #define NET_TL_LAST                     (NET_TL_FIRST + NET_TL_COUNT)
    187 
    188 /** The first UDP message.
    189  */
    190 #define NET_UDP_FIRST           (NET_TL_LAST + 0)
    191 
    192 /** The last UDP message.
    193  */
    194 #define NET_UDP_LAST            (NET_UDP_FIRST + NET_UDP_COUNT)
    195 
    196 /** The first TCP message.
    197  */
    198 #define NET_TCP_FIRST           (NET_UDP_LAST + 0)
    199 
    200 /** The last TCP message.
    201  */
    202 #define NET_TCP_LAST            (NET_TCP_FIRST + NET_TCP_COUNT)
    203 
    204 /** The first socket message.
    205  */
    206 #define NET_SOCKET_FIRST        (NET_TCP_LAST + 0)
    207 
    208 /** The last socket message.
    209  */
    210 #define NET_SOCKET_LAST         (NET_SOCKET_FIRST + NET_SOCKET_COUNT)
    211 
    212 /** The first packet management system message.
    213  */
    214 #define NET_PACKET_FIRST        (NET_SOCKET_LAST + 0)
    215 
    216 /** The last packet management system message.
    217  */
    218 #define NET_PACKET_LAST         (NET_PACKET_FIRST + NET_PACKET_COUNT)
    219 
    220 /** The last networking message.
    221  */
    222 #define NET_LAST                        NET_PACKET_LAST
    223 
    224 /** The number of networking messages.
    225  */
    226 #define NET_COUNT                       (NET_LAST - NET_FIRST)
    227 
    22850/** Returns a value indicating whether the value is in the interval.
    22951 *  @param[in] item The value to be checked.
     
    23355#define IS_IN_INTERVAL(item, first_inclusive, last_exclusive)   (((item) >= (first_inclusive)) && ((item) < (last_exclusive)))
    23456
     57/** @name Networking message counts
     58 */
     59/*@{*/
     60
     61/** The number of ARP messages.
     62 */
     63#define NET_ARP_COUNT           5
     64
     65/** The number of Ethernet messages.
     66 */
     67#define NET_ETH_COUNT           0
     68
     69/** The number of ICMP messages.
     70 */
     71#define NET_ICMP_COUNT          6
     72
     73/** The number of inter-network messages.
     74 */
     75#define NET_IL_COUNT            6
     76
     77/** The number of IP messages.
     78 */
     79#define NET_IP_COUNT            4
     80
     81/** The number of general networking messages.
     82 */
     83#define NET_NET_COUNT           3
     84
     85/** The number of network interface driver messages.
     86 */
     87#define NET_NETIF_COUNT         6
     88
     89/** The number of network interface layer messages.
     90 */
     91#define NET_NIL_COUNT           7
     92
     93/** The number of packet management system messages.
     94 */
     95#define NET_PACKET_COUNT        5
     96
     97/** The number of socket messages.
     98 */
     99#define NET_SOCKET_COUNT        14
     100
     101/** The number of TCP messages.
     102 */
     103#define NET_TCP_COUNT           0
     104
     105/** The number of transport layer messages.
     106 */
     107#define NET_TL_COUNT            1
     108
     109/** The number of UDP messages.
     110 */
     111#define NET_UDP_COUNT           0
     112
     113/*@}*/
     114
     115/** @name Networking message intervals
     116 */
     117/*@{*/
     118
     119/** The first networking message.
     120 */
     121#define NET_FIRST                       2000
     122
     123/** The first network interface layer message.
     124 */
     125#define NET_NETIF_FIRST         NET_FIRST
     126
     127/** The last network interface layer message.
     128 */
     129#define NET_NETIF_LAST          (NET_NETIF_FIRST + NET_NETIF_COUNT)
     130
     131/** The first general networking message.
     132 */
     133#define NET_NET_FIRST           (NET_NETIF_LAST + 0)
     134
     135/** The last general networking message.
     136 */
     137#define NET_NET_LAST            (NET_NET_FIRST + NET_NET_COUNT)
     138
     139/** The first network interface layer message.
     140 */
     141#define NET_NIL_FIRST           (NET_NET_LAST + 0)
     142
     143/** The last network interface layer message.
     144 */
     145#define NET_NIL_LAST            (NET_NIL_FIRST + NET_NIL_COUNT)
     146
     147/** The first Ethernet message.
     148 */
     149#define NET_ETH_FIRST           (NET_NIL_LAST + 0)
     150
     151/** The last Ethernet message.
     152 */
     153#define NET_ETH_LAST            (NET_ETH_FIRST + NET_ETH_COUNT)
     154
     155/** The first inter-network message.
     156 */
     157#define NET_IL_FIRST            (NET_ETH_LAST + 0)
     158
     159/** The last inter-network message.
     160 */
     161#define NET_IL_LAST                     (NET_IL_FIRST + NET_IL_COUNT)
     162
     163/** The first IP message.
     164 */
     165#define NET_IP_FIRST            (NET_IL_LAST + 0)
     166
     167/** The last IP message.
     168 */
     169#define NET_IP_LAST                     (NET_IP_FIRST + NET_IP_COUNT)
     170
     171/** The first ARP message.
     172 */
     173#define NET_ARP_FIRST           (NET_IP_LAST + 0)
     174
     175/** The last ARP message.
     176 */
     177#define NET_ARP_LAST            (NET_ARP_FIRST + NET_ARP_COUNT)
     178
     179/** The first ICMP message.
     180 */
     181#define NET_ICMP_FIRST          (NET_ARP_LAST + 0)
     182
     183/** The last ICMP message.
     184 */
     185#define NET_ICMP_LAST           (NET_ICMP_FIRST + NET_ICMP_COUNT)
     186
     187/** The first ICMP message.
     188 */
     189#define NET_TL_FIRST            (NET_ICMP_LAST + 0)
     190
     191/** The last ICMP message.
     192 */
     193#define NET_TL_LAST                     (NET_TL_FIRST + NET_TL_COUNT)
     194
     195/** The first UDP message.
     196 */
     197#define NET_UDP_FIRST           (NET_TL_LAST + 0)
     198
     199/** The last UDP message.
     200 */
     201#define NET_UDP_LAST            (NET_UDP_FIRST + NET_UDP_COUNT)
     202
     203/** The first TCP message.
     204 */
     205#define NET_TCP_FIRST           (NET_UDP_LAST + 0)
     206
     207/** The last TCP message.
     208 */
     209#define NET_TCP_LAST            (NET_TCP_FIRST + NET_TCP_COUNT)
     210
     211/** The first socket message.
     212 */
     213#define NET_SOCKET_FIRST        (NET_TCP_LAST + 0)
     214
     215/** The last socket message.
     216 */
     217#define NET_SOCKET_LAST         (NET_SOCKET_FIRST + NET_SOCKET_COUNT)
     218
     219/** The first packet management system message.
     220 */
     221#define NET_PACKET_FIRST        (NET_SOCKET_LAST + 0)
     222
     223/** The last packet management system message.
     224 */
     225#define NET_PACKET_LAST         (NET_PACKET_FIRST + NET_PACKET_COUNT)
     226
     227/** The last networking message.
     228 */
     229#define NET_LAST                        NET_PACKET_LAST
     230
     231/** The number of networking messages.
     232 */
     233#define NET_COUNT                       (NET_LAST - NET_FIRST)
     234
    235235/** Returns a value indicating whether the IPC call is a generic networking message.
    236236 *  @param[in] call The IPC call to be checked.
     
    238238#define IS_NET_MESSAGE(call)                    IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_FIRST, NET_LAST)
    239239
     240/** Returns a value indicating whether the IPC call is an ARP message.
     241 *  @param[in] call The IPC call to be checked.
     242 */
     243#define IS_NET_ARP_MESSAGE(call)                IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_ARP_FIRST, NET_ARP_LAST)
     244
     245/** Returns a value indicating whether the IPC call is an Ethernet message.
     246 *  @param[in] call The IPC call to be checked.
     247 */
     248#define IS_NET_ETH_MESSAGE(call)                IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_ETH_FIRST, NET_ETH_LAST)
     249
     250/** Returns a value indicating whether the IPC call is an ICMP message.
     251 *  @param[in] call The IPC call to be checked.
     252 */
     253#define IS_NET_ICMP_MESSAGE(call)               IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_ICMP_FIRST, NET_ICMP_LAST)
     254
     255/** Returns a value indicating whether the IPC call is an inter-network layer message.
     256 *  @param[in] call The IPC call to be checked.
     257 */
     258#define IS_NET_IL_MESSAGE(call)         IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_IL_FIRST, NET_IL_LAST)
     259
     260/** Returns a value indicating whether the IPC call is an IP message.
     261 *  @param[in] call The IPC call to be checked.
     262 */
     263#define IS_NET_IP_MESSAGE(call)         IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_IP_FIRST, NET_IP_LAST)
     264
    240265/** Returns a value indicating whether the IPC call is a generic networking message.
    241266 *  @param[in] call The IPC call to be checked.
     
    248273#define IS_NET_NIL_MESSAGE(call)                IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_NIL_FIRST, NET_NIL_LAST)
    249274
    250 /** Returns a value indicating whether the IPC call is an Ethernet message.
    251  *  @param[in] call The IPC call to be checked.
    252  */
    253 #define IS_NET_ETH_MESSAGE(call)                IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_ETH_FIRST, NET_ETH_LAST)
    254 
    255 /** Returns a value indicating whether the IPC call is an inter-network layer message.
    256  *  @param[in] call The IPC call to be checked.
    257  */
    258 #define IS_NET_IL_MESSAGE(call)         IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_IL_FIRST, NET_IL_LAST)
    259 
    260 /** Returns a value indicating whether the IPC call is an IP message.
    261  *  @param[in] call The IPC call to be checked.
    262  */
    263 #define IS_NET_IP_MESSAGE(call)         IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_IP_FIRST, NET_IP_LAST)
    264 
    265 /** Returns a value indicating whether the IPC call is an ARP message.
    266  *  @param[in] call The IPC call to be checked.
    267  */
    268 #define IS_NET_ARP_MESSAGE(call)                IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_ARP_FIRST, NET_ARP_LAST)
    269 
    270 /** Returns a value indicating whether the IPC call is an ICMP message.
    271  *  @param[in] call The IPC call to be checked.
    272  */
    273 #define IS_NET_ICMP_MESSAGE(call)               IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_ICMP_FIRST, NET_ICMP_LAST)
     275/** Returns a value indicating whether the IPC call is a packet manaagement system message.
     276 *  @param[in] call The IPC call to be checked.
     277 */
     278#define IS_NET_PACKET_MESSAGE(call)     IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_PACKET_FIRST, NET_PACKET_LAST)
     279
     280/** Returns a value indicating whether the IPC call is a socket message.
     281 *  @param[in] call The IPC call to be checked.
     282 */
     283#define IS_NET_SOCKET_MESSAGE(call)     IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_SOCKET_FIRST, NET_SOCKET_LAST)
     284
     285/** Returns a value indicating whether the IPC call is a TCP message.
     286 *  @param[in] call The IPC call to be checked.
     287 */
     288#define IS_NET_TCP_MESSAGE(call)                IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_TCP_FIRST, NET_TCP_LAST)
    274289
    275290/** Returns a value indicating whether the IPC call is a transport layer message.
     
    283298#define IS_NET_UDP_MESSAGE(call)                IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_UDP_FIRST, NET_UDP_LAST)
    284299
    285 /** Returns a value indicating whether the IPC call is a TCP message.
    286  *  @param[in] call The IPC call to be checked.
    287  */
    288 #define IS_NET_TCP_MESSAGE(call)                IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_TCP_FIRST, NET_TCP_LAST)
    289 
    290 /** Returns a value indicating whether the IPC call is a socket message.
    291  *  @param[in] call The IPC call to be checked.
    292  */
    293 #define IS_NET_SOCKET_MESSAGE(call)     IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_SOCKET_FIRST, NET_SOCKET_LAST)
    294 
    295 /** Returns a value indicating whether the IPC call is a packet manaagement system message.
    296  *  @param[in] call The IPC call to be checked.
    297  */
    298 #define IS_NET_PACKET_MESSAGE(call)     IS_IN_INTERVAL(IPC_GET_METHOD(*call), NET_PACKET_FIRST, NET_PACKET_LAST)
    299 
    300 /*@}*/
    301 
    302 /** @name Networking specific message parameters definitions
    303  */
    304 /*@{*/
    305 
    306 /** Returns the device identifier message parameter.
     300/*@}*/
     301
     302/** @name Networking specific message arguments definitions
     303 */
     304/*@{*/
     305
     306/** @name First arguments
     307 */
     308/*@{*/
     309
     310/** Returns the device identifier message argument.
    307311 *  @param[in] call The message call structure.
    308312 */
    309313#define IPC_GET_DEVICE(call)            (device_id_t) IPC_GET_ARG1(*call)
    310314
    311 /** Returns the packet identifier message parameter.
     315/*@}*/
     316
     317/** @name Second arguments
     318 */
     319/*@{*/
     320
     321/** Returns the packet identifier message argument.
    312322 *  @param[in] call The message call structure.
    313323 */
    314324#define IPC_GET_PACKET(call)            (packet_id_t) IPC_GET_ARG2(*call)
    315325
    316 /** Returns the count message parameter.
     326/** Returns the count message argument.
    317327 *  @param[in] call The message call structure.
    318328 */
    319329#define IPC_GET_COUNT(call)             (size_t) IPC_GET_ARG2(*call)
    320330
    321 /** Returns the device state message parameter.
     331/** Returns the device state message argument.
    322332 *  @param[in] call The message call structure.
    323333 */
    324334#define IPC_GET_STATE(call)             (device_state_t) IPC_GET_ARG2(*call)
    325335
    326 /** Returns the maximum transmission unit message parameter.
     336/** Returns the maximum transmission unit message argument.
    327337 *  @param[in] call The message call structure.
    328338 */
    329339#define IPC_GET_MTU(call)                       (size_t) IPC_GET_ARG2(*call)
    330340
    331 /** Returns the device driver service message parameter.
     341/*@}*/
     342
     343/** @name Third arguments
     344 */
     345/*@{*/
     346
     347/** Returns the device driver service message argument.
    332348 *  @param[in] call The message call structure.
    333349 */
    334350#define IPC_GET_SERVICE(call)           (services_t) IPC_GET_ARG3(*call)
    335351
    336 /** Returns the target service message parameter.
     352/** Returns the target service message argument.
    337353 *  @param[in] call The message call structure.
    338354 */
    339355#define IPC_GET_TARGET(call)            (services_t) IPC_GET_ARG3(*call)
    340356
    341 /** Returns the sender service message parameter.
     357/** Returns the sender service message argument.
    342358 *  @param[in] call The message call structure.
    343359 */
    344360#define IPC_GET_SENDER(call)            (services_t) IPC_GET_ARG3(*call)
    345361
    346 /** Returns the error service message parameter.
     362/*@}*/
     363
     364/** @name Fourth arguments
     365 */
     366/*@{*/
     367
     368/** Returns the error service message argument.
    347369 *  @param[in] call The message call structure.
    348370 */
    349371#define IPC_GET_ERROR(call)             (services_t) IPC_GET_ARG4(*call)
    350372
    351 /** Returns the phone message parameter.
     373/*@}*/
     374
     375/** @name Fifth arguments
     376 */
     377/*@{*/
     378
     379/** Returns the phone message argument.
    352380 *  @param[in] call The message call structure.
    353381 */
    354382#define IPC_GET_PHONE(call)             (int) IPC_GET_ARG5(*call)
     383
     384/*@}*/
     385
     386/** @name First answers
     387 */
     388/*@{*/
    355389
    356390/** Sets the device identifier in the message answer.
     
    364398#define IPC_SET_ADDR(answer)            ((size_t *) &IPC_GET_ARG1(*answer))
    365399
     400/*@}*/
     401
     402/** @name Second answers
     403 */
     404/*@{*/
     405
    366406/** Sets the minimum prefix size in the message answer.
    367407 *  @param[out] answer The message answer structure.
     
    369409#define IPC_SET_PREFIX(answer)  ((size_t *) &IPC_GET_ARG2(*answer))
    370410
     411/*@}*/
     412
     413/** @name Third answers
     414 */
     415/*@{*/
     416
    371417/** Sets the maximum content size in the message answer.
    372418 *  @param[out] answer The message answer structure.
     
    374420#define IPC_SET_CONTENT(answer) ((size_t *) &IPC_GET_ARG3(*answer))
    375421
     422/*@}*/
     423
     424/** @name Fourth answers
     425 */
     426/*@{*/
     427
    376428/** Sets the minimum suffix size in the message answer.
    377429 *  @param[out] answer The message answer structure.
     
    380432
    381433/*@}*/
     434
     435/*@}*/
     436
     437/** Notifies the module about the device state change.
     438 *  @param[in] phone The service module phone.
     439 *  @param[in] message The service specific message.
     440 *  @param[in] device_id The device identifier.
     441 *  @param[in] state The new device state.
     442 *  @param[in] target The target module service.
     443 *  @returns EOK on success.
     444 */
     445static inline int generic_device_state_msg(int phone, int message, device_id_t device_id, int state, services_t target){
     446        async_msg_3(phone, (ipcarg_t) message, (ipcarg_t) device_id, (ipcarg_t) state, target);
     447        return EOK;
     448}
     449
     450/** Notifies a module about the device.
     451 *  @param[in] phone The service module phone.
     452 *  @param[in] message The service specific message.
     453 *  @param[in] device_id The device identifier.
     454 *  @param[in] arg2 The second argument of the message.
     455 *  @param[in] service The device module service.
     456 *  @returns EOK on success.
     457 *  @returns Other error codes as defined for the specific service message.
     458 */
     459static inline int generic_device_req(int phone, int message, device_id_t device_id, int arg2, services_t service){
     460        return (int) async_req_3_0(phone, (ipcarg_t) message, (ipcarg_t) device_id, (ipcarg_t) arg2, (ipcarg_t) service);
     461}
    382462
    383463/** Returns the address.
     
    399479                return EBADMEM;
    400480        }
     481
     482        // request the address
    401483        message_id = async_send_1(phone, (ipcarg_t) message, (ipcarg_t) device_id, NULL);
    402484        string = measured_strings_return(phone, address, data, 1);
    403485        async_wait_for(message_id, &result);
     486
     487        // if not successful
    404488        if((string == EOK) && (result != EOK)){
     489                // clear the data
    405490                free(*address);
    406491                free(*data);
    407492        }
    408493        return (int) result;
     494}
     495
     496/** Returns the device packet dimension for sending.
     497 *  @param[in] phone The service module phone.
     498 *  @param[in] message The service specific message.
     499 *  @param[in] device_id The device identifier.
     500 *  @param[out] packet_dimension The packet dimension.
     501 *  @returns EOK on success.
     502 *  @returns EBADMEM if the packet_dimension parameter is NULL.
     503 *  @returns Other error codes as defined for the specific service message.
     504 */
     505static inline int generic_packet_size_req(int phone, int message, device_id_t device_id, packet_dimension_ref packet_dimension){
     506        ipcarg_t result;
     507        ipcarg_t prefix;
     508        ipcarg_t content;
     509        ipcarg_t suffix;
     510        ipcarg_t addr_len;
     511
     512        if(! packet_dimension){
     513                return EBADMEM;
     514        }
     515        result = async_req_1_4(phone, (ipcarg_t) message, (ipcarg_t) device_id, &addr_len, &prefix, &content, &suffix);
     516        packet_dimension->prefix = (size_t) prefix;
     517        packet_dimension->content = (size_t) content;
     518        packet_dimension->suffix = (size_t) suffix;
     519        packet_dimension->addr_len = (size_t) addr_len;
     520        return (int) result;
     521}
     522
     523/** Passes the packet queue to the module.
     524 *  @param[in] phone The service module phone.
     525 *  @param[in] message The service specific message.
     526 *  @param[in] device_id The device identifier.
     527 *  @param[in] packet_id The received packet or the received packet queue identifier.
     528 *  @param[in] target The target module service.
     529 *  @param[in] error The error module service.
     530 *  @returns EOK on success.
     531 */
     532static inline int generic_received_msg(int phone, int message, device_id_t device_id, packet_id_t packet_id, services_t target, services_t error){
     533        if(error){
     534                async_msg_4(phone, (ipcarg_t) message, (ipcarg_t) device_id, (ipcarg_t) packet_id, (ipcarg_t) target, (ipcarg_t) error);
     535        }else{
     536                async_msg_3(phone, (ipcarg_t) message, (ipcarg_t) device_id, (ipcarg_t) packet_id, (ipcarg_t) target);
     537        }
     538        return EOK;
     539}
     540
     541/** Sends the packet queue.
     542 *  @param[in] phone The service module phone.
     543 *  @param[in] message The service specific message.
     544 *  @param[in] device_id The device identifier.
     545 *  @param[in] packet_id The packet or the packet queue identifier.
     546 *  @param[in] sender The sending module service.
     547 *  @param[in] error The error module service.
     548 *  @returns EOK on success.
     549 */
     550static inline int generic_send_msg(int phone, int message, device_id_t device_id, packet_id_t packet_id, services_t sender, services_t error){
     551        if(error){
     552                async_msg_4(phone, (ipcarg_t) message, (ipcarg_t) device_id, (ipcarg_t) packet_id, (ipcarg_t) sender, (ipcarg_t) error);
     553        }else{
     554                async_msg_3(phone, (ipcarg_t) message, (ipcarg_t) device_id, (ipcarg_t) packet_id, (ipcarg_t) sender);
     555        }
     556        return EOK;
    409557}
    410558
     
    436584                return EBADMEM;
    437585        }
     586
     587        // request the translation
    438588        message_id = async_send_3(phone, (ipcarg_t) message, (ipcarg_t) device_id, (ipcarg_t) count, (ipcarg_t) service, NULL);
    439589        measured_strings_send(phone, configuration, count);
    440590        string = measured_strings_return(phone, translation, data, count);
    441591        async_wait_for(message_id, &result);
     592
     593        // if not successful
    442594        if((string == EOK) && (result != EOK)){
     595                // clear the data
    443596                free(*translation);
    444597                free(*data);
    445598        }
     599
    446600        return (int) result;
    447601}
    448602
    449 /** Sends the packet queue.
    450  *  @param[in] phone The service module phone.
    451  *  @param[in] message The service specific message.
    452  *  @param[in] device_id The device identifier.
    453  *  @param[in] packet_id The packet or the packet queue identifier.
    454  *  @param[in] sender The sending module service.
    455  *  @param[in] error The error module service.
    456  *  @returns EOK on success.
    457  */
    458 static inline int generic_send_msg(int phone, int message, device_id_t device_id, packet_id_t packet_id, services_t sender, services_t error){
    459         if(error){
    460                 async_msg_4(phone, (ipcarg_t) message, (ipcarg_t) device_id, (ipcarg_t) packet_id, (ipcarg_t) sender, (ipcarg_t) error);
    461         }else{
    462                 async_msg_3(phone, (ipcarg_t) message, (ipcarg_t) device_id, (ipcarg_t) packet_id, (ipcarg_t) sender);
    463         }
    464         return EOK;
    465 }
    466 
    467 /** Returns the device packet dimension for sending.
    468  *  @param[in] phone The service module phone.
    469  *  @param[in] message The service specific message.
    470  *  @param[in] device_id The device identifier.
    471  *  @param[out] packet_dimension The packet dimension.
    472  *  @returns EOK on success.
    473  *  @returns EBADMEM if the packet_dimension parameter is NULL.
    474  *  @returns Other error codes as defined for the specific service message.
    475  */
    476 static inline int generic_packet_size_req(int phone, int message, device_id_t device_id, packet_dimension_ref packet_dimension){
    477         ipcarg_t result;
    478         ipcarg_t prefix;
    479         ipcarg_t content;
    480         ipcarg_t suffix;
    481         ipcarg_t addr_len;
    482 
    483         if(! packet_dimension){
    484                 return EBADMEM;
    485         }
    486         result = async_req_1_4(phone, (ipcarg_t) message, (ipcarg_t) device_id, &addr_len, &prefix, &content, &suffix);
    487         packet_dimension->prefix = (size_t) prefix;
    488         packet_dimension->content = (size_t) content;
    489         packet_dimension->suffix = (size_t) suffix;
    490         packet_dimension->addr_len = (size_t) addr_len;
    491         return (int) result;
    492 }
    493 
    494 /** Notifies the module about the device state change.
    495  *  @param[in] phone The service module phone.
    496  *  @param[in] message The service specific message.
    497  *  @param[in] device_id The device identifier.
    498  *  @param[in] state The new device state.
    499  *  @param[in] target The target module service.
    500  *  @returns EOK on success.
    501  */
    502 static inline int generic_device_state_msg(int phone, int message, device_id_t device_id, int state, services_t target){
    503         async_msg_3(phone, (ipcarg_t) message, (ipcarg_t) device_id, (ipcarg_t) state, target);
    504         return EOK;
    505 }
    506 
    507 /** Passes the packet queue to the module.
    508  *  @param[in] phone The service module phone.
    509  *  @param[in] message The service specific message.
    510  *  @param[in] device_id The device identifier.
    511  *  @param[in] packet_id The received packet or the received packet queue identifier.
    512  *  @param[in] target The target module service.
    513  *  @param[in] error The error module service.
    514  *  @returns EOK on success.
    515  */
    516 static inline int generic_received_msg(int phone, int message, device_id_t device_id, packet_id_t packet_id, services_t target, services_t error){
    517         if(error){
    518                 async_msg_4(phone, (ipcarg_t) message, (ipcarg_t) device_id, (ipcarg_t) packet_id, (ipcarg_t) target, (ipcarg_t) error);
    519         }else{
    520                 async_msg_3(phone, (ipcarg_t) message, (ipcarg_t) device_id, (ipcarg_t) packet_id, (ipcarg_t) target);
    521         }
    522         return EOK;
    523 }
    524 
    525 /** Notifies a module about the device.
    526  *  @param[in] phone The service module phone.
    527  *  @param[in] message The service specific message.
    528  *  @param[in] device_id The device identifier.
    529  *  @param[in] arg2 The second argument of the message.
    530  *  @param[in] service The device module service.
    531  *  @returns EOK on success.
    532  *  @returns Other error codes as defined for the specific service message.
    533  */
    534 static inline int generic_device_req(int phone, int message, device_id_t device_id, int arg2, services_t service){
    535         return (int) async_req_3_0(phone, (ipcarg_t) message, (ipcarg_t) device_id, (ipcarg_t) arg2, (ipcarg_t) service);
    536 }
    537 
    538603#endif
    539604
  • uspace/srv/net/module.c

    r71b00dcc r60ab6c3  
    104104        ipc_answer_0(iid, EOK);
    105105
     106        // process additional messages
    106107        while(true){
     108
     109                // clear the answer structure
    107110                refresh_answer(&answer, &answer_count);
    108111
     112                // fetch the next message
    109113                callid = async_get_call(&call);
     114
     115                // process the message
    110116                res = module_message(callid, &call, &answer, &answer_count);
    111117
     118                // end if said to either by the message or the processing result
    112119                if((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP)){
    113120                        return;
    114121                }
    115122
     123                // answer the message
    116124                answer_call(callid, res, &answer, answer_count);
    117125        }
     
    121129        ERROR_DECLARE;
    122130
     131        // print the module label
    123132        printf("Task %d - ", task_get_id());
    124133        module_print_name();
    125134        printf("\n");
     135
     136        // start the module
    126137        if(ERROR_OCCURRED(module_start(client_connection))){
    127138                printf(" - ERROR %i\n", ERROR_CODE);
    128139                return ERROR_CODE;
    129140        }
     141
    130142        return EOK;
    131143}
  • uspace/srv/net/modules.c

    r71b00dcc r60ab6c3  
    5151
    5252void answer_call(ipc_callid_t callid, int result, ipc_call_t * answer, int answer_count){
     53        // choose the most efficient answer function
    5354        if(answer || (! answer_count)){
    5455                switch(answer_count){
     
    8687        ipcarg_t phonehash;
    8788
     89        // connect to the needed service
    8890        phone = connect_to_service_timeout(need, timeout);
     91        // if connected
    8992        if(phone >= 0){
     93                // request the bidirectional connection
    9094                if(ERROR_OCCURRED(ipc_connect_to_me(phone, arg1, arg2, arg3, &phonehash))){
    9195                        ipc_hangup(phone);
     
    102106
    103107int connect_to_service_timeout(services_t need, suseconds_t timeout){
    104         if (timeout <= 0)
     108        int phone;
     109
     110        // if no timeout is set
     111        if (timeout <= 0){
    105112                return async_connect_me_to_blocking(PHONE_NS, need, 0, 0);
    106        
     113        }
     114
    107115        while(true){
    108                 int phone;
     116                phone = async_connect_me_to(PHONE_NS, need, 0, 0);
     117                if((phone >= 0) || (phone != ENOENT)){
     118                        return phone;
     119                }
    109120
    110                 phone = async_connect_me_to(PHONE_NS, need, 0, 0);
    111                 if((phone >= 0) || (phone != ENOENT))
    112                         return phone;
    113        
    114                 timeout -= MODULE_WAIT_TIME;
     121                // end if no time is left
    115122                if(timeout <= 0){
    116123                        return ETIMEOUT;
    117124                }
    118125
    119                 usleep(MODULE_WAIT_TIME);
     126                // wait the minimum of the module wait time and the timeout
     127                usleep((timeout <= MODULE_WAIT_TIME) ? timeout : MODULE_WAIT_TIME);
     128                timeout -= MODULE_WAIT_TIME;
    120129        }
    121130}
     
    129138                return EBADMEM;
    130139        }
     140
     141        // fetch the request
    131142        if(! async_data_write_receive(&callid, length)){
    132143                return EINVAL;
    133144        }
     145
     146        // allocate the buffer
    134147        *data = malloc(*length);
    135148        if(!(*data)){
    136149                return ENOMEM;
    137150        }
     151
     152        // fetch the data
    138153        if(ERROR_OCCURRED(async_data_write_finalize(callid, * data, * length))){
    139154                free(data);
     
    147162        ipc_callid_t callid;
    148163
     164        // fetch the request
    149165        if(! async_data_read_receive(&callid, &length)){
    150166                return EINVAL;
    151167        }
     168
     169        // check the requested data size
    152170        if(length < data_length){
    153171                async_data_read_finalize(callid, data, length);
    154172                return EOVERFLOW;
    155173        }
     174
     175        // send the data
    156176        return async_data_read_finalize(callid, data, data_length);
    157177}
    158178
    159179void refresh_answer(ipc_call_t * answer, int * answer_count){
     180
    160181        if(answer_count){
    161182                *answer_count = 0;
    162183        }
     184
    163185        if(answer){
    164186                IPC_SET_RETVAL(*answer, 0);
  • uspace/srv/net/net/net.c

    r71b00dcc r60ab6c3  
    6666#include "net_messages.h"
    6767
     68/** File read buffer size.
     69 */
     70#define BUFFER_SIZE     256
     71
    6872/** Networking module name.
    6973 */
    7074#define NAME    "Networking"
    7175
    72 /** File read buffer size.
    73  */
    74 #define BUFFER_SIZE     256
     76/** Networking module global data.
     77 */
     78net_globals_t   net_globals;
     79
     80/** Generates new system-unique device identifier.
     81 *  @returns The system-unique devic identifier.
     82 */
     83device_id_t generate_new_device_id(void);
    7584
    7685/** Prints the module name.
     
    8897int module_start(async_client_conn_t client_connection);
    8998
    90 /** \todo
    91  */
    92 int read_configuration_file(const char * directory, const char * filename, measured_strings_ref configuration);
     99/** Returns the configured values.
     100 *  The network interface configuration is searched first.
     101 *  @param[in] netif_conf The network interface configuration setting.
     102 *  @param[out] configuration The found configured values.
     103 *  @param[in] count The desired settings count.
     104 *  @param[out] data The found configuration settings data.
     105 *  @returns EOK.
     106 */
     107int net_get_conf(measured_strings_ref netif_conf, measured_string_ref configuration, size_t count, char ** data);
     108
     109/** Initializes the networking module.
     110 *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
     111 *  @returns EOK on success.
     112 *  @returns ENOMEM if there is not enough memory left.
     113 */
     114int net_initialize(async_client_conn_t client_connection);
    93115
    94116/** \todo
     
    101123 */
    102124int read_configuration(void);
     125
     126/** \todo
     127 */
     128int read_configuration_file(const char * directory, const char * filename, measured_strings_ref configuration);
     129
     130/** Reads the network interface specific configuration.
     131 *  @param[in] name The network interface name.
     132 *  @param[in,out] netif The network interface structure.
     133 *  @returns EOK on success.
     134 *  @returns Other error codes as defined for the add_configuration() function.
     135 */
     136int read_netif_configuration(const char * name, netif_ref netif);
    103137
    104138/** Starts the network interface according to its configuration.
     
    126160int startup(void);
    127161
    128 /** Generates new system-unique device identifier.
    129  *  @returns The system-unique devic identifier.
    130  */
    131 device_id_t generate_new_device_id(void);
    132 
    133 /** Returns the configured values.
    134  *  The network interface configuration is searched first.
    135  *  @param[in] netif_conf The network interface configuration setting.
    136  *  @param[out] configuration The found configured values.
    137  *  @param[in] count The desired settings count.
    138  *  @param[out] data The found configuration settings data.
    139  *  @returns EOK.
    140  */
    141 int net_get_conf(measured_strings_ref netif_conf, measured_string_ref configuration, size_t count, char ** data);
    142 
    143 /** Initializes the networking module.
    144  *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
    145  *  @returns EOK on success.
    146  *  @returns ENOMEM if there is not enough memory left.
    147  */
    148 int net_initialize(async_client_conn_t client_connection);
    149 
    150 /** Reads the network interface specific configuration.
    151  *  @param[in] name The network interface name.
    152  *  @param[in,out] netif The network interface structure.
    153  *  @returns EOK on success.
    154  *  @returns Other error codes as defined for the add_configuration() function.
    155  */
    156 int read_netif_configuration(const char * name, netif_ref netif);
    157 
    158 /** Networking module global data.
    159  */
    160 net_globals_t   net_globals;
     162GENERIC_CHAR_MAP_IMPLEMENT(measured_strings, measured_string_t)
    161163
    162164DEVICE_MAP_IMPLEMENT(netifs, netif_t)
    163165
    164 GENERIC_CHAR_MAP_IMPLEMENT(measured_strings, measured_string_t)
     166int add_configuration(measured_strings_ref configuration, const char * name, const char * value){
     167        ERROR_DECLARE;
     168
     169        measured_string_ref setting;
     170
     171        setting = measured_string_create_bulk(value, 0);
     172        if(! setting){
     173                return ENOMEM;
     174        }
     175        // add the configuration setting
     176        if(ERROR_OCCURRED(measured_strings_add(configuration, name, 0, setting))){
     177                free(setting);
     178                return ERROR_CODE;
     179        }
     180        return EOK;
     181}
     182
     183device_id_t generate_new_device_id(void){
     184        return device_assign_devno();
     185}
    165186
    166187void module_print_name(void){
     
    187208}
    188209
    189 int net_initialize(async_client_conn_t client_connection){
    190         ERROR_DECLARE;
    191 
    192         netifs_initialize(&net_globals.netifs);
    193         char_map_initialize(&net_globals.netif_names);
    194         modules_initialize(&net_globals.modules);
    195         measured_strings_initialize(&net_globals.configuration);
    196 
    197         // TODO dynamic configuration
    198         ERROR_PROPAGATE(read_configuration());
    199 
    200         ERROR_PROPAGATE(add_module(NULL, &net_globals.modules, LO_NAME, LO_FILENAME, SERVICE_LO, 0, connect_to_service));
    201         ERROR_PROPAGATE(add_module(NULL, &net_globals.modules, DP8390_NAME, DP8390_FILENAME, SERVICE_DP8390, 0, connect_to_service));
    202         ERROR_PROPAGATE(add_module(NULL, &net_globals.modules, ETHERNET_NAME, ETHERNET_FILENAME, SERVICE_ETHERNET, 0, connect_to_service));
    203         ERROR_PROPAGATE(add_module(NULL, &net_globals.modules, NILDUMMY_NAME, NILDUMMY_FILENAME, SERVICE_NILDUMMY, 0, connect_to_service));
    204 
    205         // build specific initialization
    206         return net_initialize_build(client_connection);
    207 }
    208 
    209 int net_get_device_conf_req(int net_phone, device_id_t device_id, measured_string_ref * configuration, size_t count, char ** data){
    210         netif_ref netif;
    211 
    212         if(!(configuration && (count > 0))){
    213                 return EINVAL;
    214         }
    215         netif = netifs_find(&net_globals.netifs, device_id);
    216         if(netif){
    217                 return net_get_conf(&netif->configuration, * configuration, count, data);
    218         }else{
    219                 return net_get_conf(NULL, * configuration, count, data);
    220         }
    221 }
    222 
    223 int net_get_conf_req(int net_phone, measured_string_ref * configuration, size_t count, char ** data){
    224         if(!(configuration && (count > 0))){
    225                 return EINVAL;
    226         }
    227         return net_get_conf(NULL, * configuration, count, data);
     210int net_connect_module(services_t service){
     211        return EOK;
     212}
     213
     214void net_free_settings(measured_string_ref settings, char * data){
    228215}
    229216
     
    235222                *data = NULL;
    236223        }
     224
    237225        for(index = 0; index < count; ++ index){
    238226                setting = measured_strings_find(netif_conf, configuration[index].value, 0);
     
    251239}
    252240
    253 void net_free_settings(measured_string_ref settings, char * data){
    254 }
    255 
    256 int net_connect_module(services_t service){
    257         return EOK;
     241int net_get_conf_req(int net_phone, measured_string_ref * configuration, size_t count, char ** data){
     242        if(!(configuration && (count > 0))){
     243                return EINVAL;
     244        }
     245
     246        return net_get_conf(NULL, * configuration, count, data);
     247}
     248
     249int net_get_device_conf_req(int net_phone, device_id_t device_id, measured_string_ref * configuration, size_t count, char ** data){
     250        netif_ref netif;
     251
     252        if(!(configuration && (count > 0))){
     253                return EINVAL;
     254        }
     255
     256        netif = netifs_find(&net_globals.netifs, device_id);
     257        if(netif){
     258                return net_get_conf(&netif->configuration, * configuration, count, data);
     259        }else{
     260                return net_get_conf(NULL, * configuration, count, data);
     261        }
     262}
     263
     264int net_initialize(async_client_conn_t client_connection){
     265        ERROR_DECLARE;
     266
     267        netifs_initialize(&net_globals.netifs);
     268        char_map_initialize(&net_globals.netif_names);
     269        modules_initialize(&net_globals.modules);
     270        measured_strings_initialize(&net_globals.configuration);
     271
     272        // TODO dynamic configuration
     273        ERROR_PROPAGATE(read_configuration());
     274
     275        ERROR_PROPAGATE(add_module(NULL, &net_globals.modules, LO_NAME, LO_FILENAME, SERVICE_LO, 0, connect_to_service));
     276        ERROR_PROPAGATE(add_module(NULL, &net_globals.modules, DP8390_NAME, DP8390_FILENAME, SERVICE_DP8390, 0, connect_to_service));
     277        ERROR_PROPAGATE(add_module(NULL, &net_globals.modules, ETHERNET_NAME, ETHERNET_FILENAME, SERVICE_ETHERNET, 0, connect_to_service));
     278        ERROR_PROPAGATE(add_module(NULL, &net_globals.modules, NILDUMMY_NAME, NILDUMMY_FILENAME, SERVICE_NILDUMMY, 0, connect_to_service));
     279
     280        // build specific initialization
     281        return net_initialize_build(client_connection);
    258282}
    259283
     
    288312        }
    289313        return ENOTSUP;
     314}
     315
     316int parse_line(measured_strings_ref configuration, char * line){
     317        ERROR_DECLARE;
     318
     319        measured_string_ref setting;
     320        char * name;
     321        char * value;
     322
     323        // from the beginning
     324        name = line;
     325
     326        // skip comments and blank lines
     327        if((*name == '#') || (*name == '\0')){
     328                return EOK;
     329        }
     330        // skip spaces
     331        while(isspace(*name)){
     332                ++ name;
     333        }
     334
     335        // remember the name start
     336        value = name;
     337        // skip the name
     338        while(isalnum(*value) || (*value == '_')){
     339                // make uppercase
     340//              *value = toupper(*value);
     341                ++ value;
     342        }
     343
     344        if(*value == '='){
     345                // terminate the name
     346                *value = '\0';
     347        }else{
     348                // terminate the name
     349                *value = '\0';
     350                // skip until '='
     351                ++ value;
     352                while((*value) && (*value != '=')){
     353                        ++ value;
     354                }
     355                // not found?
     356                if(*value != '='){
     357                        return EINVAL;
     358                }
     359        }
     360
     361        ++ value;
     362        // skip spaces
     363        while(isspace(*value)){
     364                ++ value;
     365        }
     366        // create a bulk measured string till the end
     367        setting = measured_string_create_bulk(value, 0);
     368        if(! setting){
     369                return ENOMEM;
     370        }
     371
     372        // add the configuration setting
     373        if(ERROR_OCCURRED(measured_strings_add(configuration, name, 0, setting))){
     374                free(setting);
     375                return ERROR_CODE;
     376        }
     377        return EOK;
     378}
     379
     380int read_configuration(void){
     381        // read the general configuration file
     382        return read_configuration_file(CONF_DIR, CONF_GENERAL_FILE, &net_globals.configuration);
    290383}
    291384
     
    341434}
    342435
    343 int parse_line(measured_strings_ref configuration, char * line){
    344         ERROR_DECLARE;
    345 
    346         measured_string_ref setting;
    347         char * name;
    348         char * value;
    349 
    350         // from the beginning
    351         name = line;
    352 
    353         // skip comments and blank lines
    354         if((*name == '#') || (*name == '\0')){
    355                 return EOK;
    356         }
    357         // skip spaces
    358         while(isspace(*name)){
    359                 ++ name;
    360         }
    361 
    362         // remember the name start
    363         value = name;
    364         // skip the name
    365         while(isalnum(*value) || (*value == '_')){
    366                 // make uppercase
    367 //              *value = toupper(*value);
    368                 ++ value;
    369         }
    370 
    371         if(*value == '='){
    372                 // terminate the name
    373                 *value = '\0';
    374         }else{
    375                 // terminate the name
    376                 *value = '\0';
    377                 // skip until '='
    378                 ++ value;
    379                 while((*value) && (*value != '=')){
    380                         ++ value;
    381                 }
    382                 // not found?
    383                 if(*value != '='){
    384                         return EINVAL;
    385                 }
    386         }
    387 
    388         ++ value;
    389         // skip spaces
    390         while(isspace(*value)){
    391                 ++ value;
    392         }
    393         // create a bulk measured string till the end
    394         setting = measured_string_create_bulk(value, 0);
    395         if(! setting){
    396                 return ENOMEM;
    397         }
    398 
    399         // add the configuration setting
    400         if(ERROR_OCCURRED(measured_strings_add(configuration, name, 0, setting))){
    401                 free(setting);
    402                 return ERROR_CODE;
    403         }
    404         return EOK;
    405 }
    406 
    407 int add_configuration(measured_strings_ref configuration, const char * name, const char * value){
    408         ERROR_DECLARE;
    409 
    410         measured_string_ref setting;
    411 
    412         setting = measured_string_create_bulk(value, 0);
    413         if(! setting){
    414                 return ENOMEM;
    415         }
    416         // add the configuration setting
    417         if(ERROR_OCCURRED(measured_strings_add(configuration, name, 0, setting))){
    418                 free(setting);
    419                 return ERROR_CODE;
    420         }
    421         return EOK;
    422 }
    423 
    424 device_id_t generate_new_device_id(void){
    425         return device_assign_devno();
    426 }
    427 
    428 int read_configuration(void){
    429         // read the general configuration file
    430         return read_configuration_file(CONF_DIR, CONF_GENERAL_FILE, &net_globals.configuration);
    431 }
    432 
    433436int read_netif_configuration(const char * name, netif_ref netif){
    434437        // read the netif configuration file
     
    452455                return EINVAL;
    453456        }
     457
    454458        // optional network interface layer
    455459        setting = measured_strings_find(&netif->configuration, CONF_NIL, 0);
     
    463467                netif->nil = NULL;
    464468        }
     469
    465470        // mandatory internet layer
    466471        setting = measured_strings_find(&netif->configuration, CONF_IL, 0);
     
    470475                return EINVAL;
    471476        }
    472         // end of the static loopback initialization
    473         // startup the loopback interface
     477
     478        // hardware configuration
    474479        setting = measured_strings_find(&netif->configuration, CONF_IRQ, 0);
    475480        irq = setting ? strtol(setting->value, NULL, 10) : 0;
     
    477482        io = setting ? strtol(setting->value, NULL, 16) : 0;
    478483        ERROR_PROPAGATE(netif_probe_req(netif->driver->phone, netif->id, irq, io));
     484
     485        // network interface layer startup
    479486        if(netif->nil){
    480487                setting = measured_strings_find(&netif->configuration, CONF_MTU, 0);
     
    488495                internet_service = netif->driver->service;
    489496        }
     497
     498        // inter-network layer startup
    490499        switch(netif->il->service){
    491500                case SERVICE_IP:
     
    525534                }
    526535                ERROR_PROPAGATE(measured_strings_initialize(&netif->configuration));
     536
    527537                // read configuration files
    528538                if(ERROR_OCCURRED(read_netif_configuration(conf_files[i], netif))){
     
    531541                        return ERROR_CODE;