Changeset 289bd2d for lib


Ignore:
Timestamp:
2010-08-07T14:55:18Z (9 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
daae10f
Parents:
e193aeb
Message:

Applied patch from wahjava (with some modifications) for bug #644. This
lets proxy_connect() connect to IPv6 hosts.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • lib/proxy.c

    re193aeb r289bd2d  
    5858};
    5959
    60 
    61 
    62 static struct sockaddr_in *gaim_gethostbyname(const char *host, int port)
    63 {
    64         static struct sockaddr_in sin;
    65 
    66         if (!inet_aton(host, &sin.sin_addr)) {
    67                 struct hostent *hp;
    68                 if (!(hp = gethostbyname(host))) {
    69                         return NULL;
    70                 }
    71                 memset(&sin, 0, sizeof(struct sockaddr_in));
    72                 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
    73                 sin.sin_family = hp->h_addrtype;
    74         } else
    75                 sin.sin_family = AF_INET;
    76         sin.sin_port = htons(port);
    77 
    78         return &sin;
    79 }
    80 
    8160static gboolean gaim_io_connected(gpointer data, gint source, b_input_condition cond)
    8261{
     
    11190}
    11291
    113 static int proxy_connect_none(const char *host, unsigned short port, struct PHB *phb)
    114 {
    115         struct sockaddr_in *sin;
     92static int proxy_connect_none(const char *host, unsigned short port_, struct PHB *phb)
     93{
    11694        struct sockaddr_in me;
    11795        int fd = -1;
    118 
    119         if (!(sin = gaim_gethostbyname(host, port))) {
    120                 g_free(phb);
    121                 return -1;
    122         }
    123 
    124         if ((fd = socket(sin->sin_family, SOCK_STREAM, 0)) < 0) {
    125                 g_free(phb);
    126                 return -1;
    127         }
    128 
    129         sock_make_nonblocking(fd);
    130        
    131         if( global.conf->iface_out )
     96        int ret;
     97        char port[6];
     98        struct addrinfo hints;
     99        struct addrinfo* result;
     100
     101        g_snprintf(port, sizeof(port), "%d", port_);
     102
     103        memset(&hints, 0, sizeof(struct addrinfo));
     104        hints.ai_family = AF_UNSPEC;
     105        hints.ai_socktype = SOCK_STREAM;
     106        hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
     107
     108        if (!(ret = getaddrinfo(host, port, &hints, &result)))
    132109        {
    133                 me.sin_family = AF_INET;
    134                 me.sin_port = 0;
    135                 me.sin_addr.s_addr = inet_addr( global.conf->iface_out );
    136                
    137                 if( bind( fd, (struct sockaddr *) &me, sizeof( me ) ) != 0 )
    138                         event_debug( "bind( %d, \"%s\" ) failure\n", fd, global.conf->iface_out );
    139         }
    140        
    141         event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd);
    142        
    143         if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0 && !sockerr_again()) {
    144                 closesocket(fd);
    145                 g_free(phb);
    146                
    147                 return -1;
    148         } else {
    149                 phb->inpa = b_input_add(fd, B_EV_IO_WRITE, gaim_io_connected, phb);
    150                 phb->fd = fd;
    151                
    152                 return fd;
    153         }
     110                struct addrinfo* rp;
     111
     112                for (rp = result; rp; rp = rp->ai_next)
     113                {
     114                        if ((fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0) {
     115                                event_debug( "socket failed: %d\n", errno);
     116                                continue;
     117                        }
     118
     119                        sock_make_nonblocking(fd);
     120
     121                        if (global.conf->iface_out)
     122                        {
     123                                me.sin_family = AF_INET;
     124                                me.sin_port = 0;
     125                                me.sin_addr.s_addr = inet_addr( global.conf->iface_out );
     126                               
     127                                if (bind(fd, (struct sockaddr *) &me, sizeof(me)) != 0)
     128                                        event_debug("bind( %d, \"%s\" ) failure\n", fd, global.conf->iface_out);
     129                        }
     130
     131                        event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd);
     132       
     133                        if (connect(fd, rp->ai_addr, rp->ai_addrlen) < 0 && !sockerr_again()) {
     134                                event_debug( "connect failed: %s\n", strerror(errno));
     135                                closesocket(fd);
     136                                fd = -1;
     137                                continue;
     138                        } else {
     139                                phb->inpa = b_input_add(fd, B_EV_IO_WRITE, gaim_io_connected, phb);
     140                                phb->fd = fd;
     141                               
     142                                break;
     143                        }
     144                }
     145
     146                freeaddrinfo(result);
     147        }
     148        else
     149        {
     150                event_debug("gai(): %s\n", gai_strerror(ret));
     151        }
     152       
     153        if(fd < 0)
     154                g_free(phb);
     155
     156        return fd;
    154157}
    155158
Note: See TracChangeset for help on using the changeset viewer.