Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/libbb/xconnect.c

    r1765 r2725  
    55 * Connect to host at port using address resolution from getaddrinfo
    66 *
     7 * Licensed under GPLv2, see file LICENSE in this source tree.
    78 */
    89
     10#include <sys/types.h>
     11#include <sys/socket.h> /* netinet/in.h needs it */
    912#include <netinet/in.h>
     13#include <net/if.h>
     14#include <sys/un.h>
    1015#include "libbb.h"
    1116
    12 void setsockopt_reuseaddr(int fd)
     17void FAST_FUNC setsockopt_reuseaddr(int fd)
    1318{
    1419    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &const_int_1, sizeof(const_int_1));
    1520}
    16 int setsockopt_broadcast(int fd)
     21int FAST_FUNC setsockopt_broadcast(int fd)
    1722{
    1823    return setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &const_int_1, sizeof(const_int_1));
    1924}
    2025
    21 void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen)
     26#ifdef SO_BINDTODEVICE
     27int FAST_FUNC setsockopt_bindtodevice(int fd, const char *iface)
     28{
     29    int r;
     30    struct ifreq ifr;
     31    strncpy_IFNAMSIZ(ifr.ifr_name, iface);
     32    /* NB: passing (iface, strlen(iface) + 1) does not work!
     33     * (maybe it works on _some_ kernels, but not on 2.6.26)
     34     * Actually, ifr_name is at offset 0, and in practice
     35     * just giving char[IFNAMSIZ] instead of struct ifreq works too.
     36     * But just in case it's not true on some obscure arch... */
     37    r = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr));
     38    if (r)
     39        bb_perror_msg("can't bind to interface %s", iface);
     40    return r;
     41}
     42#else
     43int FAST_FUNC setsockopt_bindtodevice(int fd UNUSED_PARAM,
     44        const char *iface UNUSED_PARAM)
     45{
     46    bb_error_msg("SO_BINDTODEVICE is not supported on this system");
     47    return -1;
     48}
     49#endif
     50
     51static len_and_sockaddr* get_lsa(int fd, int (*get_name)(int fd, struct sockaddr *addr, socklen_t *addrlen))
     52{
     53    len_and_sockaddr lsa;
     54    len_and_sockaddr *lsa_ptr;
     55
     56    lsa.len = LSA_SIZEOF_SA;
     57    if (get_name(fd, &lsa.u.sa, &lsa.len) != 0)
     58        return NULL;
     59
     60    lsa_ptr = xzalloc(LSA_LEN_SIZE + lsa.len);
     61    if (lsa.len > LSA_SIZEOF_SA) { /* rarely (if ever) happens */
     62        lsa_ptr->len = lsa.len;
     63        get_name(fd, &lsa_ptr->u.sa, &lsa_ptr->len);
     64    } else {
     65        memcpy(lsa_ptr, &lsa, LSA_LEN_SIZE + lsa.len);
     66    }
     67    return lsa_ptr;
     68}
     69
     70len_and_sockaddr* FAST_FUNC get_sock_lsa(int fd)
     71{
     72    return get_lsa(fd, getsockname);
     73}
     74
     75len_and_sockaddr* FAST_FUNC get_peer_lsa(int fd)
     76{
     77    return get_lsa(fd, getpeername);
     78}
     79
     80void FAST_FUNC xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen)
    2281{
    2382    if (connect(s, s_addr, addrlen) < 0) {
     
    2685        if (s_addr->sa_family == AF_INET)
    2786            bb_perror_msg_and_die("%s (%s)",
    28                 "cannot connect to remote host",
     87                "can't connect to remote host",
    2988                inet_ntoa(((struct sockaddr_in *)s_addr)->sin_addr));
    30         bb_perror_msg_and_die("cannot connect to remote host");
     89        bb_perror_msg_and_die("can't connect to remote host");
    3190    }
    3291}
     
    3493/* Return port number for a service.
    3594 * If "port" is a number use it as the port.
    36  * If "port" is a name it is looked up in /etc/services, if it isnt found return
    37  * default_port */
    38 unsigned bb_lookup_port(const char *port, const char *protocol, unsigned default_port)
     95 * If "port" is a name it is looked up in /etc/services,
     96 * if it isnt found return default_port
     97 */
     98unsigned FAST_FUNC bb_lookup_port(const char *port, const char *protocol, unsigned default_port)
    3999{
    40100    unsigned port_nr = default_port;
     
    58118
    59119
    60 /* "Old" networking API - only IPv4 */
    61 
    62 /*
    63 void bb_lookup_host(struct sockaddr_in *s_in, const char *host)
    64 {
    65     struct hostent *he;
    66 
    67     memset(s_in, 0, sizeof(struct sockaddr_in));
    68     s_in->sin_family = AF_INET;
    69     he = xgethostbyname(host);
    70     memcpy(&(s_in->sin_addr), he->h_addr_list[0], he->h_length);
    71 }
    72 
    73 
    74 int xconnect_tcp_v4(struct sockaddr_in *s_addr)
    75 {
    76     int s = xsocket(AF_INET, SOCK_STREAM, 0);
    77     xconnect(s, (struct sockaddr*) s_addr, sizeof(*s_addr));
    78     return s;
    79 }
    80 */
    81 
    82120/* "New" networking API */
    83121
    84122
    85 int get_nport(const struct sockaddr *sa)
     123int FAST_FUNC get_nport(const struct sockaddr *sa)
    86124{
    87125#if ENABLE_FEATURE_IPV6
     
    97135}
    98136
    99 void set_nport(len_and_sockaddr *lsa, unsigned port)
    100 {
    101 #if ENABLE_FEATURE_IPV6
    102     if (lsa->sa.sa_family == AF_INET6) {
    103         lsa->sin6.sin6_port = port;
     137void FAST_FUNC set_nport(len_and_sockaddr *lsa, unsigned port)
     138{
     139#if ENABLE_FEATURE_IPV6
     140    if (lsa->u.sa.sa_family == AF_INET6) {
     141        lsa->u.sin6.sin6_port = port;
    104142        return;
    105143    }
    106144#endif
    107     if (lsa->sa.sa_family == AF_INET) {
    108         lsa->sin.sin_port = port;
     145    if (lsa->u.sa.sa_family == AF_INET) {
     146        lsa->u.sin.sin_port = port;
    109147        return;
    110148    }
     
    120158static len_and_sockaddr* str2sockaddr(
    121159        const char *host, int port,
    122 USE_FEATURE_IPV6(sa_family_t af,)
     160IF_FEATURE_IPV6(sa_family_t af,)
    123161        int ai_flags)
    124162{
     163IF_NOT_FEATURE_IPV6(sa_family_t af = AF_INET;)
    125164    int rc;
    126     len_and_sockaddr *r = NULL;
     165    len_and_sockaddr *r;
    127166    struct addrinfo *result = NULL;
     167    struct addrinfo *used_res;
    128168    const char *org_host = host; /* only for error msg */
    129169    const char *cp;
    130170    struct addrinfo hint;
    131171
     172    if (ENABLE_FEATURE_UNIX_LOCAL && strncmp(host, "local:", 6) == 0) {
     173        struct sockaddr_un *sun;
     174
     175        r = xzalloc(LSA_LEN_SIZE + sizeof(struct sockaddr_un));
     176        r->len = sizeof(struct sockaddr_un);
     177        r->u.sa.sa_family = AF_UNIX;
     178        sun = (struct sockaddr_un *)&r->u.sa;
     179        safe_strncpy(sun->sun_path, host + 6, sizeof(sun->sun_path));
     180        return r;
     181    }
     182
     183    r = NULL;
     184
    132185    /* Ugly parsing of host:addr */
    133186    if (ENABLE_FEATURE_IPV6 && host[0] == '[') {
     187        /* Even uglier parsing of [xx]:nn */
    134188        host++;
    135189        cp = strchr(host, ']');
    136         if (!cp || cp[1] != ':') /* Malformed: must have [xx]:nn */
    137             bb_error_msg_and_die("bad address '%s'", org_host);
    138             //return r; /* return NULL */
     190        if (!cp || (cp[1] != ':' && cp[1] != '\0')) {
     191            /* Malformed: must be [xx]:nn or [xx] */
     192            bb_error_msg("bad address '%s'", org_host);
     193            if (ai_flags & DIE_ON_ERROR)
     194                xfunc_die();
     195            return NULL;
     196        }
    139197    } else {
    140198        cp = strrchr(host, ':');
     
    144202        }
    145203    }
    146     if (cp) {
     204    if (cp) { /* points to ":" or "]:" */
    147205        int sz = cp - host + 1;
     206
    148207        host = safe_strncpy(alloca(sz), host, sz);
    149         if (ENABLE_FEATURE_IPV6 && *cp != ':')
     208        if (ENABLE_FEATURE_IPV6 && *cp != ':') {
    150209            cp++; /* skip ']' */
     210            if (*cp == '\0') /* [xx] without port */
     211                goto skip;
     212        }
    151213        cp++; /* skip ':' */
    152         port = xatou16(cp);
    153     }
     214        port = bb_strtou(cp, NULL, 10);
     215        if (errno || (unsigned)port > 0xffff) {
     216            bb_error_msg("bad port spec '%s'", org_host);
     217            if (ai_flags & DIE_ON_ERROR)
     218                xfunc_die();
     219            return NULL;
     220        }
     221 skip: ;
     222    }
     223
     224    /* Next two if blocks allow to skip getaddrinfo()
     225     * in case host name is a numeric IP(v6) address.
     226     * getaddrinfo() initializes DNS resolution machinery,
     227     * scans network config and such - tens of syscalls.
     228     */
     229    /* If we were not asked specifically for IPv6,
     230     * check whether this is a numeric IPv4 */
     231    IF_FEATURE_IPV6(if(af != AF_INET6)) {
     232        struct in_addr in4;
     233        if (inet_aton(host, &in4) != 0) {
     234            r = xzalloc(LSA_LEN_SIZE + sizeof(struct sockaddr_in));
     235            r->len = sizeof(struct sockaddr_in);
     236            r->u.sa.sa_family = AF_INET;
     237            r->u.sin.sin_addr = in4;
     238            goto set_port;
     239        }
     240    }
     241#if ENABLE_FEATURE_IPV6
     242    /* If we were not asked specifically for IPv4,
     243     * check whether this is a numeric IPv6 */
     244    if (af != AF_INET) {
     245        struct in6_addr in6;
     246        if (inet_pton(AF_INET6, host, &in6) > 0) {
     247            r = xzalloc(LSA_LEN_SIZE + sizeof(struct sockaddr_in6));
     248            r->len = sizeof(struct sockaddr_in6);
     249            r->u.sa.sa_family = AF_INET6;
     250            r->u.sin6.sin6_addr = in6;
     251            goto set_port;
     252        }
     253    }
     254#endif
    154255
    155256    memset(&hint, 0 , sizeof(hint));
    156 #if !ENABLE_FEATURE_IPV6
    157     hint.ai_family = AF_INET; /* do not try to find IPv6 */
    158 #else
    159257    hint.ai_family = af;
    160 #endif
    161258    /* Needed. Or else we will get each address thrice (or more)
    162259     * for each possible socket type (tcp,udp,raw...): */
     
    170267        goto ret;
    171268    }
    172     r = xmalloc(offsetof(len_and_sockaddr, sa) + result->ai_addrlen);
    173     r->len = result->ai_addrlen;
    174     memcpy(&r->sa, result->ai_addr, result->ai_addrlen);
     269    used_res = result;
     270#if ENABLE_FEATURE_PREFER_IPV4_ADDRESS
     271    while (1) {
     272        if (used_res->ai_family == AF_INET)
     273            break;
     274        used_res = used_res->ai_next;
     275        if (!used_res) {
     276            used_res = result;
     277            break;
     278        }
     279    }
     280#endif
     281    r = xmalloc(LSA_LEN_SIZE + used_res->ai_addrlen);
     282    r->len = used_res->ai_addrlen;
     283    memcpy(&r->u.sa, used_res->ai_addr, used_res->ai_addrlen);
     284
     285 set_port:
    175286    set_nport(r, htons(port));
    176287 ret:
     
    183294
    184295#if ENABLE_FEATURE_IPV6
    185 len_and_sockaddr* host_and_af2sockaddr(const char *host, int port, sa_family_t af)
     296len_and_sockaddr* FAST_FUNC host_and_af2sockaddr(const char *host, int port, sa_family_t af)
    186297{
    187298    return str2sockaddr(host, port, af, 0);
    188299}
    189300
    190 len_and_sockaddr* xhost_and_af2sockaddr(const char *host, int port, sa_family_t af)
     301len_and_sockaddr* FAST_FUNC xhost_and_af2sockaddr(const char *host, int port, sa_family_t af)
    191302{
    192303    return str2sockaddr(host, port, af, DIE_ON_ERROR);
     
    194305#endif
    195306
    196 len_and_sockaddr* host2sockaddr(const char *host, int port)
     307len_and_sockaddr* FAST_FUNC host2sockaddr(const char *host, int port)
    197308{
    198309    return str2sockaddr(host, port, AF_UNSPEC, 0);
    199310}
    200311
    201 len_and_sockaddr* xhost2sockaddr(const char *host, int port)
     312len_and_sockaddr* FAST_FUNC xhost2sockaddr(const char *host, int port)
    202313{
    203314    return str2sockaddr(host, port, AF_UNSPEC, DIE_ON_ERROR);
    204315}
    205316
    206 len_and_sockaddr* xdotted2sockaddr(const char *host, int port)
     317len_and_sockaddr* FAST_FUNC xdotted2sockaddr(const char *host, int port)
    207318{
    208319    return str2sockaddr(host, port, AF_UNSPEC, AI_NUMERICHOST | DIE_ON_ERROR);
    209320}
    210321
    211 int xsocket_type(len_and_sockaddr **lsap, USE_FEATURE_IPV6(int family,) int sock_type)
    212 {
    213     SKIP_FEATURE_IPV6(enum { family = AF_INET };)
     322#undef xsocket_type
     323int FAST_FUNC xsocket_type(len_and_sockaddr **lsap, IF_FEATURE_IPV6(int family,) int sock_type)
     324{
     325    IF_NOT_FEATURE_IPV6(enum { family = AF_INET };)
    214326    len_and_sockaddr *lsa;
    215327    int fd;
     
    234346    }
    235347#endif
    236     lsa = xzalloc(offsetof(len_and_sockaddr, sa) + len);
     348    lsa = xzalloc(LSA_LEN_SIZE + len);
    237349    lsa->len = len;
    238     lsa->sa.sa_family = family;
     350    lsa->u.sa.sa_family = family;
    239351    *lsap = lsa;
    240352    return fd;
    241353}
    242354
    243 int xsocket_stream(len_and_sockaddr **lsap)
    244 {
    245     return xsocket_type(lsap, USE_FEATURE_IPV6(AF_UNSPEC,) SOCK_STREAM);
     355int FAST_FUNC xsocket_stream(len_and_sockaddr **lsap)
     356{
     357    return xsocket_type(lsap, IF_FEATURE_IPV6(AF_UNSPEC,) SOCK_STREAM);
    246358}
    247359
     
    254366        lsa = xdotted2sockaddr(bindaddr, port);
    255367        /* user specified bind addr dictates family */
    256         fd = xsocket(lsa->sa.sa_family, sock_type, 0);
     368        fd = xsocket(lsa->u.sa.sa_family, sock_type, 0);
    257369    } else {
    258         fd = xsocket_type(&lsa, USE_FEATURE_IPV6(AF_UNSPEC,) sock_type);
     370        fd = xsocket_type(&lsa, IF_FEATURE_IPV6(AF_UNSPEC,) sock_type);
    259371        set_nport(lsa, htons(port));
    260372    }
    261373    setsockopt_reuseaddr(fd);
    262     xbind(fd, &lsa->sa, lsa->len);
     374    xbind(fd, &lsa->u.sa, lsa->len);
    263375    free(lsa);
    264376    return fd;
    265377}
    266378
    267 int create_and_bind_stream_or_die(const char *bindaddr, int port)
     379int FAST_FUNC create_and_bind_stream_or_die(const char *bindaddr, int port)
    268380{
    269381    return create_and_bind_or_die(bindaddr, port, SOCK_STREAM);
    270382}
    271383
    272 int create_and_bind_dgram_or_die(const char *bindaddr, int port)
     384int FAST_FUNC create_and_bind_dgram_or_die(const char *bindaddr, int port)
    273385{
    274386    return create_and_bind_or_die(bindaddr, port, SOCK_DGRAM);
     
    276388
    277389
    278 int create_and_connect_stream_or_die(const char *peer, int port)
     390int FAST_FUNC create_and_connect_stream_or_die(const char *peer, int port)
    279391{
    280392    int fd;
     
    282394
    283395    lsa = xhost2sockaddr(peer, port);
    284     fd = xsocket(lsa->sa.sa_family, SOCK_STREAM, 0);
     396    fd = xsocket(lsa->u.sa.sa_family, SOCK_STREAM, 0);
    285397    setsockopt_reuseaddr(fd);
    286     xconnect(fd, &lsa->sa, lsa->len);
     398    xconnect(fd, &lsa->u.sa, lsa->len);
    287399    free(lsa);
    288400    return fd;
    289401}
    290402
    291 int xconnect_stream(const len_and_sockaddr *lsa)
    292 {
    293     int fd = xsocket(lsa->sa.sa_family, SOCK_STREAM, 0);
    294     xconnect(fd, &lsa->sa, lsa->len);
     403int FAST_FUNC xconnect_stream(const len_and_sockaddr *lsa)
     404{
     405    int fd = xsocket(lsa->u.sa.sa_family, SOCK_STREAM, 0);
     406    xconnect(fd, &lsa->u.sa, lsa->len);
    295407    return fd;
    296408}
     
    299411/* It doesn't hurt because we will add this bit anyway */
    300412#define IGNORE_PORT NI_NUMERICSERV
    301 static char* sockaddr2str(const struct sockaddr *sa, int flags)
     413static char* FAST_FUNC sockaddr2str(const struct sockaddr *sa, int flags)
    302414{
    303415    char host[128];
     
    305417    int rc;
    306418    socklen_t salen;
     419
     420    if (ENABLE_FEATURE_UNIX_LOCAL && sa->sa_family == AF_UNIX) {
     421        struct sockaddr_un *sun = (struct sockaddr_un *)sa;
     422        return xasprintf("local:%.*s",
     423                (int) sizeof(sun->sun_path),
     424                sun->sun_path);
     425    }
    307426
    308427    salen = LSA_SIZEOF_SA;
     
    338457}
    339458
    340 char* xmalloc_sockaddr2host(const struct sockaddr *sa)
     459char* FAST_FUNC xmalloc_sockaddr2host(const struct sockaddr *sa)
    341460{
    342461    return sockaddr2str(sa, 0);
    343462}
    344463
    345 char* xmalloc_sockaddr2host_noport(const struct sockaddr *sa)
     464char* FAST_FUNC xmalloc_sockaddr2host_noport(const struct sockaddr *sa)
    346465{
    347466    return sockaddr2str(sa, IGNORE_PORT);
    348467}
    349468
    350 char* xmalloc_sockaddr2hostonly_noport(const struct sockaddr *sa)
     469char* FAST_FUNC xmalloc_sockaddr2hostonly_noport(const struct sockaddr *sa)
    351470{
    352471    return sockaddr2str(sa, NI_NAMEREQD | IGNORE_PORT);
    353472}
    354 char* xmalloc_sockaddr2dotted(const struct sockaddr *sa)
     473char* FAST_FUNC xmalloc_sockaddr2dotted(const struct sockaddr *sa)
    355474{
    356475    return sockaddr2str(sa, NI_NUMERICHOST);
    357476}
    358477
    359 char* xmalloc_sockaddr2dotted_noport(const struct sockaddr *sa)
     478char* FAST_FUNC xmalloc_sockaddr2dotted_noport(const struct sockaddr *sa)
    360479{
    361480    return sockaddr2str(sa, NI_NUMERICHOST | IGNORE_PORT);
Note: See TracChangeset for help on using the changeset viewer.