From a88301a8d21ae864a4c56745f4b0ab8c4cd0d03a Mon Sep 17 00:00:00 2001 From: Michal Sojka Date: Thu, 28 May 2009 00:56:03 +0200 Subject: [PATCH] Added handling of FORB_EXTERNAL_IP environment variable This variable specifies the IP address of some local interface, which FORB announces for contacting by others. --- src/proto_inet.c | 53 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/src/proto_inet.c b/src/proto_inet.c index 5cef70d..32a45c8 100644 --- a/src/proto_inet.c +++ b/src/proto_inet.c @@ -60,6 +60,7 @@ #include #include #include "discovery.h" +#include #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 #include -#include 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 */ -- 2.39.2