]> rtime.felk.cvut.cz Git - frescor/forb.git/commitdiff
Added handling of FORB_EXTERNAL_IP environment variable
authorMichal Sojka <sojkam1@fel.cvut.cz>
Wed, 27 May 2009 22:56:03 +0000 (00:56 +0200)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Wed, 27 May 2009 23:20:15 +0000 (01:20 +0200)
This variable specifies the IP address of some local interface, which FORB
announces for contacting by others.

src/proto_inet.c

index 5cef70dc70f203a0c27d0a8625f9da52f72d0452..32a45c8c8e8ef0df90c72cdc8e8435df8bb80e8e 100644 (file)
@@ -60,6 +60,7 @@
 #include <unistd.h>
 #include <forb/config.h>
 #include "discovery.h"
+#include <stdlib.h>
 #include "iop.h" /* FIXME: Sending hello should be handled in IOP layer */
 
 /**
@@ -442,7 +443,6 @@ size_t inet_addr2str(char *dest, size_t maxlen, const void *addr)
 
 #include <fcb.h>
 #include <fcb_contact_info.h>
-#include <stdlib.h>
 
 static void inet_register_cb(forb_port_t *port)
 {
@@ -479,7 +479,19 @@ int get_local_address(int sock, struct in_addr *addr)
 {
        struct ifconf  ifc;
        struct ifreq   *ifr, req[MAX_INTERFACES];
+       char *env;
+       bool loopback = false;
+       int ret;
+       struct in_addr env_addr;
        
+       env = getenv("FORB_EXTERNAL_IP");
+       if (env) {
+               if (inet_aton(env, &env_addr) == 0) {
+                       ul_logerr("Cannot convert FORB_EXTERNAL_IP\n");
+                       errno = EINVAL;
+                       return -1;
+               }
+       }
 
        ifc.ifc_len = sizeof(req);
        ifc.ifc_req = req;
@@ -489,13 +501,32 @@ int get_local_address(int sock, struct in_addr *addr)
        for (ifr = req; ifr < &req[MAX_INTERFACES]; ifr++) {
                struct sockaddr_in ia;
                memcpy(&ia, &ifr->ifr_addr, sizeof(ia));
-               ioctl(sock, SIOCGIFFLAGS, ifr);
-               if ((ifr->ifr_flags & IFF_UP) && !(ifr->ifr_flags & IFF_LOOPBACK)) {
-                       *addr = ia.sin_addr;
-                       return 0;
+               ret = ioctl(sock, SIOCGIFFLAGS, ifr);
+               if ((ret == 0) && (ifr->ifr_flags & IFF_UP)) {
+                       if (env && env_addr.s_addr == ia.sin_addr.s_addr) {
+                               *addr = env_addr;
+                               return 0;
+                       }
+                       if (!(ifr->ifr_flags & IFF_LOOPBACK)) {
+                               if (!env) {
+                                       *addr = ia.sin_addr;
+                                       return 0;
+                               }
+                       } else {
+                               *addr = ia.sin_addr;
+                               loopback = true;
+                       }
                }
        }
-       return -1;
+       if (env) {
+               ul_logerr("FORB_EXTERNAL_IP doesn't match local interface\n");
+               errno = ENODEV;
+               return -1;
+       }
+       if (loopback)
+               return 0;
+       else
+               return -1;
 }
 
 /** 
@@ -539,6 +570,7 @@ forb_inet_port_init(struct forb_port_desc *port_desc, struct in_addr listen_on,
 
        setnonblocking(port_priv->udp_socket);
 
+#ifndef CONFIG_FORB_PROTO_INET_DEFAULT
        struct ip_mreq mreq;
        inet_aton(MCAST_ADDR, &port_priv->multicast_addr);
        mreq.imr_multiaddr = port_priv->multicast_addr;
@@ -547,6 +579,7 @@ forb_inet_port_init(struct forb_port_desc *port_desc, struct in_addr listen_on,
                         IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
        if (ret)
                goto err_close_udp;
+#endif
 
        addr.sin_family = AF_INET;
        addr.sin_port = htons(MCAST_PORT);
@@ -593,9 +626,11 @@ forb_inet_port_init(struct forb_port_desc *port_desc, struct in_addr listen_on,
        }
 
        port_priv->addr.port = addr.sin_port;
-       if (listen_on.s_addr == INADDR_ANY)
-               get_local_address(port_priv->listen_socket, &port_priv->addr.addr);
-       else
+       if (listen_on.s_addr == INADDR_ANY) {
+               if (get_local_address(port_priv->listen_socket, &port_priv->addr.addr)) {
+                       goto err_close_listen;
+               }
+       } else
                port_priv->addr.addr = listen_on;
 
        /* Initialize epoll descriptor */