Signed-off-by: Davide Brini <dave...@gmx.com>

This patch creates two new environment variables: "multihome_iface" and
"multihome_ip", which contain respectively the interface name and IP address
where the client connection came in, so scripts can use them.

Tested on IPv4, "works for me". The patch is against the master branch.

Besides the style issues or the errors that surely this patch contains, I have
some questions:

- Is this (ie, function link_socket_connection_initiated()) the right place to
  do it?

- Currently it uses the same variable names for IPv4 and IPv6; would using 
  multihome_ip and multihome_ip6 make more sense, for example? (I don't think
  so, but asking for confirmation)

- For consistency, I think it would be nice to set the same variables even
  when --multihome is not in effect. However, as it is now, OpenVPN explicitly
  checks for --multihome and if it's not set, it doesn't set the 
  IP_PKTINFO/IP_RECVDSTADDR option in the socket, so that information is not
  always available (hence the addr_defined_ipi() check is needed). Any reason
  why this is so? What would be the problem in always setting 
  IP_PKTINFO/IP_RECVDSTADDR (if supported by the platform, of course)?

- Again for consistency, the same variables could/should be set for TCP
  connections, however I have no idea where to look for that (I don't even 
  know whether link_socket_connection_initiated() is called at all when using
  TCP). Any suggestions?

Thanks.

---
 socket.c |   68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 68 insertions(+), 0 deletions(-)

diff --git a/socket.c b/socket.c
index a2f9511..e21294f 100644
--- a/socket.c
+++ b/socket.c
@@ -2112,6 +2112,74 @@ link_socket_connection_initiated (const struct buffer 
*buf,
   /* set environmental vars */
   setenv_str (es, "common_name", common_name);

+#if ENABLE_IP_PKTINFO
+  {
+    /* determine server's IP and interface where the connection came in,
+       and create corresponding environment variables  */
+
+    char ifname[IF_NAMESIZE];
+    int ok_ifindex = 1;     /* whether if_indextoname() succeeded */
+
+    if (addr_defined_ipi(act))
+      {
+        switch(act->dest.addr.sa.sa_family)
+          {
+          case AF_INET:
+              {
+                struct openvpn_sockaddr sa;
+                char v4addr[INET_ADDRSTRLEN];
+                CLEAR (sa);
+                CLEAR (v4addr);
+
+#ifdef IP_PKTINFO
+                sa.addr.in4.sin_addr = act->pi.in4.ipi_spec_dst;
+                if (!if_indextoname(act->pi.in4.ipi_ifindex, ifname))
+                  ok_ifindex = 0;
+
+#elif defined(IP_RECVDSTADDR)
+                sa.addr.in4.sin_addr = act->pi.in4;
+                ifname[0] = 0;
+
+#else
+#error ENABLE_IP_PKTINFO is set without IP_PKTINFO xor IP_RECVDSTADDR (fix 
syshead.h)
+#endif
+
+                if (ok_ifindex)
+                  setenv_str (es, "multihome_iface", ifname);
+                else
+                  msg (M_WARN, "WARNING: if_indextoname() failed for index %d: 
%s", act->pi.in4.ipi_ifindex, strerror(errno));
+
+                if (inet_ntop(AF_INET, &(sa.addr.in4.sin_addr), v4addr, 
INET_ADDRSTRLEN))
+                  setenv_str (es, "multihome_ip", v4addr);
+                else
+                  msg (M_WARN, "WARNING: inet_ntop() failed when converting 
address: %s", strerror(errno));
+
+              }
+            break;
+          case AF_INET6:
+              {
+                struct sockaddr_in6 sin6;
+                char v6addr[INET6_ADDRSTRLEN];
+                CLEAR(sin6);
+                CLEAR(v6addr);
+                sin6.sin6_addr = act->pi.in6.ipi6_addr;
+
+                if (if_indextoname(act->pi.in6.ipi6_ifindex, ifname))
+                  setenv_str (es, "multihome_iface", ifname);
+                else
+                  msg (M_WARN, "WARNING: if_indextoname() failed for index %d: 
%s", act->pi.in6.ipi6_ifindex, strerror(errno));
+
+                if (inet_ntop(AF_INET6, &(sin6.sin6_addr), v6addr, 
INET6_ADDRSTRLEN))
+                  setenv_str (es, "multihome_ip", v6addr);
+                else
+                  msg (M_WARN, "WARNING: inet_ntop() failed wen converting 
address: %s", strerror(errno));
+              }
+            break;
+          }
+      }
+  }
+#endif
+
   /* Process --ipchange plugin */
   if (plugin_defined (info->plugins, OPENVPN_PLUGIN_IPCHANGE))
     {
-- 
1.7.5.4


Reply via email to