core/forward.c Fixed mhomed behavior.
authorMarius Zbihlei <marius.zbihlei@1and1.ro>
Thu, 4 Nov 2010 14:11:41 +0000 (16:11 +0200)
committerMarius Zbihlei <marius.zbihlei@1and1.ro>
Thu, 4 Nov 2010 14:13:27 +0000 (16:13 +0200)
As connect() dones't re-bound a UDP sock if the socket is already
bound to an interface, first unbind the socket by connecting to AF_UNSPEC

forward.c

index 25bc11d..3d7aed1 100644 (file)
--- a/forward.c
+++ b/forward.c
@@ -131,6 +131,10 @@ struct socket_info* get_out_socket(union sockaddr_union* to, int proto)
        union sockaddr_union from; 
        struct socket_info* si;
        struct ip_addr ip;
+       union sockaddr_union uncon;
+
+       memset(&uncon, 0, sizeof(union sockaddr_union));
+       uncon.sin.sin_family = AF_UNSPEC;
 
        if (unlikely(proto!=PROTO_UDP)) {
                LOG(L_CRIT, "BUG: get_out_socket can only be called for UDP\n");
@@ -167,6 +171,14 @@ retry:
                return 0;
        }
        }
+
+       if( !mhomed_sock_cache_disabled ){
+               /* some Linux kernel versions (all?) along with other UNIXes don't re-bound the sock if already bound */
+               /* to un-bound a socket set sin_family to AF_UNSPEC and zero out the rest*/
+               if (unlikely(connect(*temp_sock, &uncon.s, sockaddru_len(uncon))) < 0)
+                               mhomed_sock_cache_disabled = 1;
+       }
+
        if (unlikely(connect(*temp_sock, &to->s, sockaddru_len(*to))==-1)) {
                if (unlikely(errno==EISCONN && !mhomed_sock_cache_disabled)){
                        /*  no multiple connects support on the same socket */