tadd local address to dial - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit e5d68728eb1fb4526b67358e7e55698eea4ed315
 (DIR) parent fb7a39bc56092ecd2a52d8b6fc403eda6b905ba1
 (HTM) Author: rsc <devnull@localhost>
       Date:   Sun, 13 Feb 2005 18:33:26 +0000
       
       add local address to dial
       
       Diffstat:
         M src/lib9/dial.c                     |      45 +++++++++++++++++++++++++++++---
       
       1 file changed, 42 insertions(+), 3 deletions(-)
       ---
 (DIR) diff --git a/src/lib9/dial.c b/src/lib9/dial.c
       t@@ -19,18 +19,20 @@
        #undef unix
        
        int
       -p9dial(char *addr, char *dummy1, char *dummy2, int *dummy3)
       +p9dial(char *addr, char *local, char *dummy2, int *dummy3)
        {
                char *buf;
                char *net, *unix;
                u32int host;
                int port;
                int proto;
       -        struct sockaddr_in sa;        
       +        socklen_t sn;
       +        int n;
       +        struct sockaddr_in sa, sal;        
                struct sockaddr_un su;
                int s;
        
       -        if(dummy1 || dummy2 || dummy3){
       +        if(dummy2 || dummy3){
                        werrstr("cannot handle extra arguments in dial");
                        return -1;
                }
       t@@ -63,6 +65,38 @@ p9dial(char *addr, char *dummy1, char *dummy2, int *dummy3)
                sa.sin_port = htons(port);
                if((s = socket(AF_INET, proto, 0)) < 0)
                        return -1;
       +                
       +        if(local){
       +                buf = strdup(local);
       +                if(buf == nil){
       +                        close(s);
       +                        return -1;
       +                }
       +                if(p9dialparse(buf, &net, &unix, &host, &port) < 0){
       +                badlocal:
       +                        free(buf);
       +                        close(s);
       +                        return -1;
       +                }
       +                if(unix){
       +                        werrstr("bad local address %s for dial %s", local, addr);
       +                        goto badlocal;
       +                }
       +                memset(&sal, 0, sizeof sal);
       +                memmove(&sal.sin_addr, &local, 4);
       +                sal.sin_family = AF_INET;
       +                sal.sin_port = htons(port);
       +                sn = sizeof n;
       +                if(port && getsockopt(s, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) >= 0
       +                && n == SOCK_STREAM){
       +                        n = 1;
       +                        setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n);
       +                }
       +                if(bind(s, (struct sockaddr*)&sal, sizeof sal) < 0)
       +                        goto badlocal;
       +                free(buf);
       +        }
       +
                if(connect(s, (struct sockaddr*)&sa, sizeof sa) < 0){
                        close(s);
                        return -1;
       t@@ -74,6 +108,11 @@ p9dial(char *addr, char *dummy1, char *dummy2, int *dummy3)
                return s;
        
        Unix:
       +        if(local){
       +                werrstr("local address not supported on unix network");
       +                free(buf);
       +                return -1;
       +        }
                memset(&su, 0, sizeof su);
                su.sun_family = AF_UNIX;
                if(strlen(unix)+1 > sizeof su.sun_path){