Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/app/ping/ping.c

    r3be62bc r4be390b  
    3939#include <task.h>
    4040#include <time.h>
    41 #include <ipc/ipc.h>
    4241#include <ipc/services.h>
    4342
     
    6463 *  @returns EOK on success.
    6564 */
    66 int main(int argc, char * argv[]);
     65int             main( int argc, char * argv[] );
    6766
    6867/** Prints the application help.
    6968 */
    70 void ping_print_help(void);
    71 
    72 int main(int argc, char * argv[]){
    73         ERROR_DECLARE;
    74 
    75         size_t size                     = 38;
    76         int verbose                     = 0;
    77         int dont_fragment       = 0;
    78         ip_ttl_t ttl            = 0;
    79         ip_tos_t tos            = 0;
    80         int count                       = 3;
    81         suseconds_t timeout     = 3000;
    82         int family                      = AF_INET;
    83 
    84         socklen_t max_length                            = sizeof(struct sockaddr_in6);
    85         uint8_t address_data[max_length];
    86         struct sockaddr * address                       = (struct sockaddr *) address_data;
    87         struct sockaddr_in * address_in         = (struct sockaddr_in *) address;
    88         struct sockaddr_in6 * address_in6       = (struct sockaddr_in6 *) address;
    89         socklen_t addrlen;
    90         char address_string[INET6_ADDRSTRLEN];
    91         uint8_t * address_start;
    92         int icmp_phone;
    93         struct timeval time_before;
    94         struct timeval time_after;
    95         int result;
    96         int value;
    97         int index;
    98 
    99         // print the program label
    100         printf("Task %d - ", task_get_id());
    101         printf("%s\n", NAME);
    102 
    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 ('-')
    107                 if(argv[index][0] == '-'){
    108                         switch(argv[index][1]){
    109                                 // short options with only one letter
    110                                 case 'c':
    111                                         ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &count, "count", 0));
    112                                         break;
    113                                 case 'f':
    114                                         ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "address family", 0, parse_address_family));
    115                                         break;
    116                                 case 'h':
    117                                         ping_print_help();
    118                                         return EOK;
    119                                         break;
    120                                 case 's':
    121                                         ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "packet size", 0));
    122                                         size = (value >= 0) ? (size_t) value : 0;
    123                                         break;
    124                                 case 't':
    125                                         ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "timeout", 0));
    126                                         timeout = (value >= 0) ? (suseconds_t) value : 0;
    127                                         break;
    128                                 case 'v':
    129                                         verbose = 1;
    130                                         break;
    131                                 // long options with the double minus sign ('-')
    132                                 case '-':
    133                                         if(str_lcmp(argv[index] + 2, "count=", 6) == 0){
    134                                                 ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &count, "received count", 8));
    135                                         }else if(str_lcmp(argv[index] + 2, "dont_fragment", 13) == 0){
    136                                                 dont_fragment = 1;
    137                                         }else if(str_lcmp(argv[index] + 2, "family=", 7) == 0){
    138                                                 ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "address family", 9, parse_address_family));
    139                                         }else if(str_lcmp(argv[index] + 2, "help", 5) == 0){
    140                                                 ping_print_help();
    141                                                 return EOK;
    142                                         }else if(str_lcmp(argv[index] + 2, "size=", 5) == 0){
    143                                                 ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "packet size", 7));
    144                                                 size = (value >= 0) ? (size_t) value : 0;
    145                                         }else if(str_lcmp(argv[index] + 2, "timeout=", 8) == 0){
    146                                                 ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "timeout", 7));
    147                                                 timeout = (value >= 0) ? (suseconds_t) value : 0;
    148                                         }else if(str_lcmp(argv[index] + 2, "tos=", 4) == 0){
    149                                                 ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "type of service", 7));
    150                                                 tos = (value >= 0) ? (ip_tos_t) value : 0;
    151                                         }else if(str_lcmp(argv[index] + 2, "ttl=", 4) == 0){
    152                                                 ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "time to live", 7));
    153                                                 ttl = (value >= 0) ? (ip_ttl_t) value : 0;
    154                                         }else if(str_lcmp(argv[index] + 2, "verbose", 8) == 0){
    155                                                 verbose = 1;
    156                                         }else{
    157                                                 print_unrecognized(index, argv[index] + 2);
    158                                                 ping_print_help();
    159                                                 return EINVAL;
    160                                         }
    161                                         break;
    162                                 default:
    163                                         print_unrecognized(index, argv[index] + 1);
    164                                         ping_print_help();
    165                                         return EINVAL;
    166                         }
    167                 }else{
    168                         print_unrecognized(index, argv[index]);
    169                         ping_print_help();
    170                         return EINVAL;
    171                 }
    172         }
    173 
    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
    182         bzero(address_data, max_length);
    183         switch(family){
    184                 case AF_INET:
    185                         address_in->sin_family = AF_INET;
    186                         address_start = (uint8_t *) &address_in->sin_addr.s_addr;
    187                         addrlen = sizeof(struct sockaddr_in);
    188                         break;
    189                 case AF_INET6:
    190                         address_in6->sin6_family = AF_INET6;
    191                         address_start = (uint8_t *) &address_in6->sin6_addr.s6_addr;
    192                         addrlen = sizeof(struct sockaddr_in6);
    193                         break;
    194                 default:
    195                         fprintf(stderr, "Address family is not supported\n");
    196                         return EAFNOSUPPORT;
    197         }
    198 
    199         // parse the last argument which should contain the address
    200         if(ERROR_OCCURRED(inet_pton(family, argv[argc - 1], address_start))){
    201                 fprintf(stderr, "Address parse error %d\n", ERROR_CODE);
    202                 return ERROR_CODE;
    203         }
    204 
    205         // connect to the ICMP module
    206         icmp_phone = icmp_connect_module(SERVICE_ICMP, ICMP_CONNECT_TIMEOUT);
    207         if(icmp_phone < 0){
    208                 fprintf(stderr, "ICMP connect error %d\n", icmp_phone);
    209                 return icmp_phone;
    210         }
    211 
    212         // print the ping header
    213         printf("PING %d bytes of data\n", size);
    214         if(ERROR_OCCURRED(inet_ntop(address->sa_family, address_start, address_string, sizeof(address_string)))){
    215                 fprintf(stderr, "Address error %d\n", ERROR_CODE);
    216         }else{
    217                 printf("Address %s:\n", address_string);
    218         }
    219 
    220         // do count times
    221         while(count > 0){
    222 
    223                 // get the starting time
    224                 if(ERROR_OCCURRED(gettimeofday(&time_before, NULL))){
    225                         fprintf(stderr, "Get time of day error %d\n", ERROR_CODE);
    226                         // release the ICMP phone
    227                         ipc_hangup(icmp_phone);
    228                         return ERROR_CODE;
    229                 }
    230 
    231                 // request the ping
    232                 result = icmp_echo_msg(icmp_phone, size, timeout, ttl, tos, dont_fragment, address, addrlen);
    233 
    234                 // get the ending time
    235                 if(ERROR_OCCURRED(gettimeofday(&time_after, NULL))){
    236                         fprintf(stderr, "Get time of day error %d\n", ERROR_CODE);
    237                         // release the ICMP phone
    238                         ipc_hangup(icmp_phone);
    239                         return ERROR_CODE;
    240                 }
    241 
    242                 // print the result
    243                 switch(result){
    244                         case ICMP_ECHO:
    245                                 printf("Ping round trip time %d miliseconds\n", tv_sub(&time_after, &time_before) / 1000);
    246                                 break;
    247                         case ETIMEOUT:
    248                                 printf("Timed out.\n");
    249                                 break;
    250                         default:
    251                                 print_error(stdout, result, NULL, "\n");
    252                 }
    253                 -- count;
    254         }
    255 
    256         if(verbose){
    257                 printf("Exiting\n");
    258         }
    259 
    260         // release the ICMP phone
    261         ipc_hangup(icmp_phone);
    262 
    263         return EOK;
    264 }
    265 
    266 void ping_print_help(void){
     69void    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 */
     76int             parse_address_family( const char * name );
     77
     78void print_help( void ){
    26779        printf(
    26880                "Network Ping aplication\n" \
     
    299111}
    300112
     113int 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}
     121
     122int main( int argc, char * argv[] ){
     123        ERROR_DECLARE;
     124
     125        size_t                          size                    = 38;
     126        int                                     verbose                 = 0;
     127        int                                     dont_fragment   = 0;
     128        ip_ttl_t                        ttl                             = 0;
     129        ip_tos_t                        tos                             = 0;
     130        int                                     count                   = 3;
     131        suseconds_t                     timeout                 = 3000;
     132        int                                     family                  = AF_INET;
     133
     134        socklen_t                       max_length              = sizeof( struct sockaddr_in6 );
     135        uint8_t                         address_data[ max_length ];
     136        struct sockaddr *               address         = ( struct sockaddr * ) address_data;
     137        struct sockaddr_in *    address_in              = ( struct sockaddr_in * ) address;
     138        struct sockaddr_in6 *   address_in6     = ( struct sockaddr_in6 * ) address;
     139        socklen_t                       addrlen;
     140        char                            address_string[ INET6_ADDRSTRLEN ];
     141        uint8_t *                       address_start;
     142        int                                     icmp_phone;
     143        struct timeval          time_before;
     144        struct timeval          time_after;
     145        int                                     result;
     146        int                                     value;
     147        int                                     index;
     148
     149        printf( "Task %d - ", task_get_id());
     150        printf( "%s\n", NAME );
     151
     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 ){
     158                if( argv[ index ][ 0 ] == '-' ){
     159                        switch( argv[ index ][ 1 ] ){
     160                                case 'c':       ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & count, "count", 0 ));
     161                                                        break;
     162                                case 'f':       ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "address family", 0, parse_address_family ));
     163                                                        break;
     164                                case 'h':       print_help();
     165                                                        return EOK;
     166                                                        break;
     167                                case 's':       ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "packet size", 0 ));
     168                                                        size = (value >= 0 ) ? ( size_t ) value : 0;
     169                                                        break;
     170                                case 't':       ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "timeout", 0 ));
     171                                                        timeout = (value >= 0 ) ? ( suseconds_t ) value : 0;
     172                                                        break;
     173                                case 'v':       verbose = 1;
     174                                                        break;
     175                                case '-':       if( str_lcmp( argv[ index ] + 2, "count=", 6 ) == 0 ){
     176                                                                ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & count, "received count", 8 ));
     177                                                        }else if( str_lcmp( argv[ index ] + 2, "dont_fragment", 13 ) == 0 ){
     178                                                                dont_fragment = 1;
     179                                                        }else if( str_lcmp( argv[ index ] + 2, "family=", 7 ) == 0 ){
     180                                                                ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "address family", 9, parse_address_family ));
     181                                                        }else if( str_lcmp( argv[ index ] + 2, "help", 5 ) == 0 ){
     182                                                                print_help();
     183                                                                return EOK;
     184                                                        }else if( str_lcmp( argv[ index ] + 2, "size=", 5 ) == 0 ){
     185                                                                ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "packet size", 7 ));
     186                                                                size = (value >= 0 ) ? ( size_t ) value : 0;
     187                                                        }else if( str_lcmp( argv[ index ] + 2, "timeout=", 8 ) == 0 ){
     188                                                                ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "timeout", 7 ));
     189                                                                timeout = (value >= 0 ) ? ( suseconds_t ) value : 0;
     190                                                        }else if( str_lcmp( argv[ index ] + 2, "tos=", 4 ) == 0 ){
     191                                                                ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "type of service", 7 ));
     192                                                                tos = (value >= 0 ) ? ( ip_tos_t ) value : 0;
     193                                                        }else if( str_lcmp( argv[ index ] + 2, "ttl=", 4 ) == 0 ){
     194                                                                ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "time to live", 7 ));
     195                                                                ttl = (value >= 0 ) ? ( ip_ttl_t ) value : 0;
     196                                                        }else if( str_lcmp( argv[ index ] + 2, "verbose", 8 ) == 0 ){
     197                                                                verbose = 1;
     198                                                        }else{
     199                                                                print_unrecognized( index, argv[ index ] + 2 );
     200                                                                print_help();
     201                                                                return EINVAL;
     202                                                        }
     203                                                        break;
     204                                default:
     205                                        print_unrecognized( index, argv[ index ] + 1 );
     206                                        print_help();
     207                                        return EINVAL;
     208                        }
     209                }else{
     210                        print_unrecognized( index, argv[ index ] );
     211                        print_help();
     212                        return EINVAL;
     213                }
     214        }
     215
     216        bzero( address_data, max_length );
     217        switch( family ){
     218                case AF_INET:
     219                        address_in->sin_family = AF_INET;
     220                        address_start = ( uint8_t * ) & address_in->sin_addr.s_addr;
     221                        addrlen = sizeof( struct sockaddr_in );
     222                        break;
     223                case AF_INET6:
     224                        address_in6->sin6_family = AF_INET6;
     225                        address_start = ( uint8_t * ) & address_in6->sin6_addr.s6_addr;
     226                        addrlen = sizeof( struct sockaddr_in6 );
     227                        break;
     228                default:
     229                        fprintf( stderr, "Address family is not supported\n" );
     230                        return EAFNOSUPPORT;
     231        }
     232
     233        if( ERROR_OCCURRED( inet_pton( family, argv[ argc - 1 ], address_start ))){
     234                fprintf( stderr, "Address parse error %d\n", ERROR_CODE );
     235                return ERROR_CODE;
     236        }
     237
     238        icmp_phone = icmp_connect_module( SERVICE_ICMP, ICMP_CONNECT_TIMEOUT );
     239        if( icmp_phone < 0 ){
     240                fprintf( stderr, "ICMP connect error %d\n", icmp_phone );
     241                return icmp_phone;
     242        }
     243
     244        printf( "PING %d bytes of data\n", size );
     245        if( ERROR_OCCURRED( inet_ntop( address->sa_family, address_start, address_string, sizeof( address_string )))){
     246                fprintf( stderr, "Address error %d\n", ERROR_CODE );
     247        }else{
     248                printf( "Address %s:\n", address_string );
     249        }
     250
     251        while( count > 0 ){
     252                if( ERROR_OCCURRED( gettimeofday( & time_before, NULL ))){
     253                        fprintf( stderr, "Get time of day error %d\n", ERROR_CODE );
     254                        return ERROR_CODE;
     255                }
     256                result = icmp_echo_msg( icmp_phone, size, timeout, ttl, tos, dont_fragment, address, addrlen );
     257                if( ERROR_OCCURRED( gettimeofday( & time_after, NULL ))){
     258                        fprintf( stderr, "Get time of day error %d\n", ERROR_CODE );
     259                        return ERROR_CODE;
     260                }
     261                switch( result ){
     262                        case ICMP_ECHO:
     263                                printf( "Ping round trip time %d miliseconds\n", tv_sub( & time_after, & time_before ) / 1000 );
     264                                break;
     265                        case ETIMEOUT:
     266                                printf( "Timed out.\n" );
     267                                break;
     268                        default:
     269                                print_error( stdout, result, NULL, "\n" );
     270                }
     271                -- count;
     272        }
     273
     274        if( verbose ) printf( "Exiting\n" );
     275
     276        return EOK;
     277}
     278
    301279/** @}
    302280 */
Note: See TracChangeset for help on using the changeset viewer.