Code

Added the ability to set the source address in the library.
authorFlorian Forster <octo@verplant.org>
Mon, 12 Jun 2006 20:30:13 +0000 (22:30 +0200)
committerFlorian Forster <octo@verplant.org>
Mon, 12 Jun 2006 20:30:13 +0000 (22:30 +0200)
Use `ping_setopt' and `PING_OPT_SOURCE' to set it. This _might_ fail under *BSD
and/or Mac OS X, I have to test that..

src/liboping.c
src/oping.h

index 6131107a03509c320168e0c36d9cffd0edcc2fff..d74659fd24df0a9a7d48dd3763d2cdb2878a303c 100644 (file)
@@ -115,14 +115,17 @@ struct pinghost
 
 struct pingobj
 {
-       double      timeout;
-       int         ttl;
-       int         addrfamily;
-       char       *data;
+       double                   timeout;
+       int                      ttl;
+       int                      addrfamily;
+       char                    *data;
+
+       struct sockaddr_storage *srcaddr;
+       socklen_t                srcaddrlen;
 
-       char        errmsg[PING_ERRMSG_LEN];
+       char                     errmsg[PING_ERRMSG_LEN];
 
-       pinghost_t *head;
+       pinghost_t              *head;
 };
 
 /*
@@ -824,6 +827,9 @@ void ping_destroy (pingobj_t *obj)
        if (obj->data != NULL)
                free (obj->data);
 
+       if (obj->srcaddr != NULL)
+               free (obj->srcaddr);
+
        free (obj);
 
        return;
@@ -862,6 +868,11 @@ int ping_setopt (pingobj_t *obj, int option, void *value)
                                obj->addrfamily = PING_DEF_AF;
                                ret = -1;
                        }
+                       if (obj->srcaddr != NULL)
+                       {
+                               free (obj->srcaddr);
+                               obj->srcaddr = NULL;
+                       }
                        break;
 
                case PING_OPT_DATA:
@@ -873,6 +884,57 @@ int ping_setopt (pingobj_t *obj, int option, void *value)
                        obj->data = strdup ((const char *) value);
                        break;
 
+               case PING_OPT_SOURCE:
+               {
+                       char            *hostname = (char *) value;
+                       struct addrinfo  ai_hints;
+                       struct addrinfo *ai_list;
+                       int              status;
+
+                       memset ((void *) &ai_hints, '\0', sizeof (ai_hints));
+                       ai_hints.ai_family = obj->addrfamily;
+#if defined(AI_ADDRCONFIG)
+                       ai_hints.ai_flags = AI_ADDRCONFIG;
+#endif
+                       status = getaddrinfo (hostname, NULL, &ai_hints, &ai_list);
+                       if (status != 0)
+                       {
+                               ping_set_error (obj, "getaddrinfo",
+                                               status == EAI_SYSTEM
+                                               ? strerror (errno)
+                                               : gai_strerror (status));
+                               ret = -1;
+                               break;
+                       }
+#if WITH_DEBUG
+                       if (ai_list->ai_next != NULL)
+                       {
+                               dprintf ("hostname = `%s' is ambiguous.\n", hostname);
+                       }
+#endif
+                       if (obj->srcaddr == NULL)
+                       {
+                               obj->srcaddrlen = 0;
+                               obj->srcaddr = (struct sockaddr_storage *) malloc (sizeof (struct sockaddr_storage));
+                               if (obj->srcaddr == NULL)
+                               {
+                                       ping_set_error (obj, "malloc",
+                                                       strerror (errno));
+                                       ret = -1;
+                                       freeaddrinfo (ai_list);
+                                       break;
+                               }
+                       }
+                       memset ((void *) obj->srcaddr, '\0', sizeof (struct sockaddr_storage));
+                       assert (ai_list->ai_addrlen <= sizeof (struct sockaddr_storage));
+                       memcpy ((void *) obj->srcaddr, (const void *) ai_list->ai_addr,
+                                       ai_list->ai_addrlen);
+                       obj->srcaddrlen = ai_list->ai_addrlen;
+
+                       freeaddrinfo (ai_list);
+               } /* case PING_OPT_SOURCE */
+               break;
+
                default:
                        ret = -2;
        } /* switch (option) */
index 54d031017166495d0378ab7f6942902e123b4bf4..4cdb3cf3608cefe2cf7a91d75a73e0b69d102b4f 100644 (file)
@@ -49,6 +49,7 @@ typedef struct pingobj pingobj_t;
 #define PING_OPT_TTL     0x02
 #define PING_OPT_AF      0x04
 #define PING_OPT_DATA    0x08
+#define PING_OPT_SOURCE  0x10
 
 #define PING_DEF_TIMEOUT 1.0
 #define PING_DEF_TTL     255