Changeset 858fc90 in mainline for uspace/srv/net/app/ping/ping.c


Ignore:
Timestamp:
2010-03-15T19:35:25Z (14 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
6092b56e
Parents:
92307f1 (diff), 4684368 (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 bzr://bzr.helenos.org/head.

File:
1 edited

Legend:

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

    r92307f1 r858fc90  
    3939#include <task.h>
    4040#include <time.h>
     41#include <ipc/ipc.h>
    4142#include <ipc/services.h>
    4243
     
    6364 *  @returns EOK on success.
    6465 */
    65 int             main( int argc, char * argv[] );
     66int main(int argc, char * argv[]);
    6667
    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 ){
     70void ping_print_help(void);
     71
     72int 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
     266void ping_print_help(void){
    79267        printf(
    80268                "Network Ping aplication\n" \
     
    111299}
    112300
    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 }
    121 
    122 int 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 
    279301/** @}
    280302 */
Note: See TracChangeset for help on using the changeset viewer.