Merge branch 'liboping-1.2'
authorFlorian Forster <sifnfors@stud.informatik.uni-erlangen.de>
Fri, 17 Jul 2009 12:53:04 +0000 (14:53 +0200)
committerFlorian Forster <sifnfors@stud.informatik.uni-erlangen.de>
Fri, 17 Jul 2009 12:53:04 +0000 (14:53 +0200)
src/liboping.c
src/mans/oping.pod
src/mans/ping_setopt.pod
src/oping.c
src/oping.h

index dc2b449..6950103 100644 (file)
@@ -134,6 +134,8 @@ struct pingobj
        struct sockaddr         *srcaddr;
        socklen_t                srcaddrlen;
 
+       char                    *device;
+
        char                     errmsg[PING_ERRMSG_LEN];
 
        pinghost_t              *head;
@@ -1050,6 +1052,9 @@ void ping_destroy (pingobj_t *obj)
        if (obj->srcaddr != NULL)
                free (obj->srcaddr);
 
+       if (obj->device != NULL)
+               free (obj->device);
+
        free (obj);
 
        return;
@@ -1175,6 +1180,28 @@ int ping_setopt (pingobj_t *obj, int option, void *value)
                } /* case PING_OPT_SOURCE */
                break;
 
+               case PING_OPT_DEVICE:
+               {
+#ifdef SO_BINDTODEVICE
+                       char *device = strdup ((char *) value);
+
+                       if (device == NULL)
+                       {
+                               ping_set_errno (obj, errno);
+                               ret = -1;
+                               break;
+                       }
+
+                       if (obj->device != NULL)
+                               free (obj->device);
+                       obj->device = device;
+#else /* ! SO_BINDTODEVICE */
+                       ping_set_errno (obj, ENOTSUP);
+                       ret = -1;
+#endif /* ! SO_BINDTODEVICE */
+               } /* case PING_OPT_DEVICE */
+               break;
+
                default:
                        ret = -2;
        } /* switch (option) */
@@ -1348,6 +1375,25 @@ int ping_host_add (pingobj_t *obj, const char *host)
                        }
                }
 
+#ifdef SO_BINDTODEVICE
+               if (obj->device != NULL)
+               {
+                       if (setsockopt (ph->fd, SOL_SOCKET, SO_BINDTODEVICE,
+                                       obj->device, strlen (obj->device) + 1) != 0)
+                       {
+#if WITH_DEBUG
+                               char errbuf[PING_ERRMSG_LEN];
+                               dprintf ("setsockopt: %s\n",
+                                               sstrerror (errno, errbuf, sizeof (errbuf)));
+#endif
+                               ping_set_errno (obj, errno);
+                               close (ph->fd);
+                               ph->fd = -1;
+                               continue;
+                       }
+               }
+#endif /* SO_BINDTODEVICE */
+
                assert (sizeof (struct sockaddr_storage) >= ai_ptr->ai_addrlen);
                memset (ph->addr, '\0', sizeof (struct sockaddr_storage));
                memcpy (ph->addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
index 29784a8..8a3cb58 100644 (file)
@@ -45,8 +45,13 @@ including) 1E<nbsp>andE<nbsp>255. If omitted, the value B<64> is used.
 
 =item B<-I> I<address>
 
-Set the source address to use. You B<cannot> pass the interface name, as you
-can with GNU's L<ping(8)>.
+Set the source address to use. You may either specify an IP number or a
+hostname. You B<cannot> pass the interface name, as you can with GNU's
+L<ping(8)> - use the B<-D> option for that purpose.
+
+=item B<-D> I<interface name>
+
+Set the outgoing network device to use.
 
 =item B<-f> I<filename>
 
index 2452701..ad85979 100644 (file)
@@ -53,10 +53,19 @@ L<ping(1)> command.
 =item B<PING_OPT_SOURCE>
 
 Set the source address to use. The value passed must be a char-pointer to a
-null-terminated string. This option will ignore the address family setting (as
+null-terminated string specifying either a numerical network address or
+network hostname. This option will ignore the address family setting (as
 set with B<PING_OPT_AF>) and will set the object's address family according to
 the source address assigned.
 
+=item B<PING_OPT_DEVICE>
+
+Set the outgoing network device to be used. The value passed must be a
+char-pointer to a null-terminated string specifying an interface name
+(e.E<nbsp>g. C<eth0>). Please note that this might not be supported by all
+operating systems. In that case, B<ping_setopt> sets the error to C<operation
+not supported>.
+
 =back
 
 The I<val> argument is a pointer to the new value. It must not be NULL. It is
index a1dbade..fc4cb5f 100644 (file)
@@ -73,6 +73,7 @@ typedef struct ping_context
 static double  opt_interval   = 1.0;
 static int     opt_addrfamily = PING_DEF_AF;
 static char   *opt_srcaddr    = NULL;
+static char   *opt_device     = NULL;
 static char   *opt_filename   = NULL;
 static int     opt_count      = -1;
 static int     opt_send_ttl   = 64;
@@ -122,6 +123,7 @@ static void usage_exit (const char *name, int status)
                        "  -i interval  interval with which to send ICMP packets\n"
                        "  -t ttl       time to live for each ICMP packet\n"
                        "  -I srcaddr   source address\n"
+                       "  -D device    outgoing interface name\n"
                        "  -f filename  filename to read hosts from\n"
 
                        "\noping "PACKAGE_VERSION", http://verplant.org/liboping/\n"
@@ -137,7 +139,7 @@ static int read_options (int argc, char **argv)
 
        while (1)
        {
-               optchar = getopt (argc, argv, "46c:hi:I:t:f:");
+               optchar = getopt (argc, argv, "46c:hi:I:t:f:D:");
 
                if (optchar == -1)
                        break;
@@ -188,6 +190,10 @@ static int read_options (int argc, char **argv)
                                }
                                break;
 
+                       case 'D':
+                               opt_device = optarg;
+                               break;
+
                        case 't':
                        {
                                int new_send_ttl;
@@ -375,6 +381,15 @@ int main (int argc, char **argv)
                }
        }
 
+       if (opt_device != NULL)
+       {
+               if (ping_setopt (ping, PING_OPT_DEVICE, (void *) opt_device) != 0)
+               {
+                       fprintf (stderr, "Setting device failed: %s\n",
+                                       ping_get_error (ping));
+               }
+       }
+
        if (opt_filename != NULL)
        {
                FILE *infile;
index 0debadf..2ffdf1f 100644 (file)
@@ -59,6 +59,7 @@ typedef struct pingobj pingobj_t;
 #define PING_OPT_AF      0x04
 #define PING_OPT_DATA    0x08
 #define PING_OPT_SOURCE  0x10
+#define PING_OPT_DEVICE  0x20
 
 #define PING_DEF_TIMEOUT 1.0
 #define PING_DEF_TTL     255