fpingのsource addressパッチ

DebianのパッケージではSourceAddreess指定可能だったりするのでFreeBSD用に移植してみました。
元ネタ: debian specific patch information for fping / 2.4b2-to-ipv6-16.1

Source Addressパッチ

このパッチはportsのパッチがすでにあたってる状態で適応してください。
元ネタはdebian specific patch information for fping / 2.4b2-to-ipv6-16.1からのほぼそのままの部分移植です。

% diff -c4 ./fping.c ~noel/temp/BKUP.fping.c
*** ./fping.c   2011-10-06 17:38:55.000000000 +0900
--- /home/noel/temp/BKUP.fping.c        2011-10-06 17:38:47.000000000 +0900
***************
*** 284,291 ****
--- 284,297 ----
  u_int ping_pkt_size;
  u_int count = 1;
  u_int trials;
  u_int report_interval = 0;
+ int src_addr_present = 0;
+ #ifndef IPV6
+ struct in_addr src_addr;
+ #else
+ struct in6_addr src_addr;
+ #endif
 
  /* global stats */
  long max_reply = 0;
  long min_reply = 1000000;
***************
*** 409,416 ****
--- 415,424 ----
        int advance;
        struct protoent *proto;
        char *buf;
        uid_t uid;
+       FPING_SOCKADDR sa;
+
        /* check if we are root */
 
        if( geteuid() )
        {
***************
*** 492,500 ****
        opterr = 1;
 
        /* get command line options */
 
!       while( ( c = getopt( argc, argv, "gedhlmnqusaAvz:t:i:p:f:r:c:b:C:Q:B:" ) ) != EOF )
        {
                switch( c )
                {
                case 't':
--- 500,508 ----
        opterr = 1;
 
        /* get command line options */
 
!       while( ( c = getopt( argc, argv, "gedhlmnqusaAvz:t:i:p:f:r:c:b:C:Q:B:S:" ) ) != EOF )
        {
                switch( c )
                {
                case 't':
***************
*** 633,641 ****
                        }/* ELSE */
 
                        break;
  #endif /* ENABLE_F_OPTION */
!
                case 'g':
                        /* use IP list generation */
                        /* mutually exclusive with using file input or command line targets */
                        generate_flag = 1;
--- 641,657 ----
                        }/* ELSE */
 
                        break;
  #endif /* ENABLE_F_OPTION */
!               case 'S':
! #ifndef IPV6
!                 if( ! inet_pton( AF_INET, optarg, &src_addr ) )
! #else
!                 if( ! inet_pton( AF_INET6, optarg, &src_addr ) )
! #endif
!                 usage();
!                 src_addr_present = 1;
!                 break;
                case 'g':
                        /* use IP list generation */
                        /* mutually exclusive with using file input or command line targets */
                        generate_flag = 1;
***************
*** 964,971 ****
--- 980,1003 ----
 
        if( !num_hosts )
                exit( 2 );
 
+       /* set the source address */
+
+       if( src_addr_present )
+         {
+           memset( &sa, 0, sizeof( FPING_SOCKADDR ) );
+ #ifndef IPV6
+           sa.sin_family = AF_INET;
+           sa.sin_addr = src_addr;
+ #else
+           sa.sin6_family = AF_INET6;
+           sa.sin6_addr = src_addr;
+ #endif
+           if ( bind( s, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 )
+             errno_crash_and_burn( "cannot bind source address" );
+         }
+
        /* allocate array to hold outstanding ping requests */
 
        table = ( HOST_ENTRY** )malloc( sizeof( HOST_ENTRY* ) * num_hosts );
        if( !table )
***************
*** 2739,2746 ****
--- 2771,2779 ----
        fprintf( stderr, "   -q         quiet (don't show per-target/per-ping results)\n" );
        fprintf( stderr, "   -Q n       same as -q, but show summary every n seconds\n" );
        fprintf( stderr, "   -r n       number of retries (default %d)\n", retry );
        fprintf( stderr, "   -s         print final stats\n" );
+       fprintf( stderr, "   -S addr    set source address\n" );
        fprintf( stderr, "   -t n       individual target initial timeout (in millisec) (default %d)\n", timeout / 100 );
        fprintf( stderr, "   -u         show targets that are unreachable\n" );
        fprintf( stderr, "   -v         show version\n" );
        fprintf( stderr, "   targets    list of targets to check (if no -f specified)\n" );