[BACK]Return to ng_ipaddr.c CVS log [TXT][DIR] Up to [local] / ircnowd / src / ipaddr

Annotation of ircnowd/src/ipaddr/ng_ipaddr.c, Revision 1.1.1.1

1.1       tomglok     1: /*
                      2:  * (c) 2008 Florian Westphal <fw@strlen.de>, public domain.
                      3:  */
                      4:
                      5: #include "portab.h"
                      6:
                      7: /**
                      8:  * @file
                      9:  * Functions for AF_ agnostic ipv4/ipv6 handling.
                     10:  */
                     11:
                     12: #include <assert.h>
                     13: #include <stdio.h>
                     14: #include <string.h>
                     15:
                     16: #ifdef HAVE_GETADDRINFO
                     17: #include <netdb.h>
                     18: #include <sys/types.h>
                     19: #endif
                     20:
                     21: #include "ng_ipaddr.h"
                     22:
                     23: GLOBAL bool
                     24: ng_ipaddr_init(ng_ipaddr_t *addr, const char *ip_str, UINT16 port)
                     25: {
                     26: #ifdef HAVE_WORKING_GETADDRINFO
                     27:        int ret;
                     28:        char portstr[64];
                     29:        struct addrinfo *res0;
                     30:        struct addrinfo hints;
                     31:
                     32:        assert(ip_str);
                     33:
                     34:        memset(&hints, 0, sizeof(hints));
                     35: #ifdef AI_NUMERICHOST
                     36:        hints.ai_flags = AI_NUMERICHOST;
                     37: #endif
                     38: #ifndef WANT_IPV6      /* do not convert ipv6 addresses */
                     39:        hints.ai_family = AF_INET;
                     40: #endif
                     41:
                     42:        /* some getaddrinfo implementations require that ai_socktype is set. */
                     43:        hints.ai_socktype = SOCK_STREAM;
                     44:
                     45:        /* silly, but ngircd stores UINT16 in server config, not string */
                     46:        snprintf(portstr, sizeof(portstr), "%u", (unsigned int) port);
                     47:
                     48:        ret = getaddrinfo(ip_str, portstr, &hints, &res0);
                     49:        if (ret != 0)
                     50:                return false;
                     51:
                     52:        assert(sizeof(*addr) >= (size_t)res0->ai_addrlen);
                     53:        if (sizeof(*addr) >= (size_t)res0->ai_addrlen)
                     54:                memcpy(addr, res0->ai_addr, res0->ai_addrlen);
                     55:        else
                     56:                ret = -1;
                     57:        freeaddrinfo(res0);
                     58:        return ret == 0;
                     59: #else /* HAVE_GETADDRINFO */
                     60:        assert(ip_str);
                     61:        memset(addr, 0, sizeof *addr);
                     62: #ifdef HAVE_sockaddr_in_len
                     63:        addr->sin4.sin_len = sizeof(addr->sin4);
                     64: #endif
                     65:        addr->sin4.sin_family = AF_INET;
                     66: # ifdef HAVE_INET_ATON
                     67:        if (inet_aton(ip_str, &addr->sin4.sin_addr) == 0)
                     68:                return false;
                     69: # else
                     70:        addr->sin4.sin_addr.s_addr = inet_addr(ip_str);
                     71:        if (addr->sin4.sin_addr.s_addr == (unsigned) -1)
                     72:                return false;
                     73: # endif
                     74:        ng_ipaddr_setport(addr, port);
                     75:        return true;
                     76: #endif /* HAVE_GETADDRINFO */
                     77: }
                     78:
                     79:
                     80: GLOBAL void
                     81: ng_ipaddr_setport(ng_ipaddr_t *a, UINT16 port)
                     82: {
                     83: #ifdef WANT_IPV6
                     84:        int af;
                     85:
                     86:        assert(a != NULL);
                     87:
                     88:        af = a->sa.sa_family;
                     89:
                     90:        assert(af == AF_INET || af == AF_INET6);
                     91:
                     92:        switch (af) {
                     93:        case AF_INET:
                     94:                a->sin4.sin_port = htons(port);
                     95:                break;
                     96:        case AF_INET6:
                     97:                a->sin6.sin6_port = htons(port);
                     98:                break;
                     99:        }
                    100: #else /* WANT_IPV6 */
                    101:        assert(a != NULL);
                    102:        assert(a->sin4.sin_family == AF_INET);
                    103:        a->sin4.sin_port = htons(port);
                    104: #endif /* WANT_IPV6 */
                    105: }
                    106:
                    107:
                    108:
                    109: GLOBAL bool
                    110: ng_ipaddr_ipequal(const ng_ipaddr_t *a, const ng_ipaddr_t *b)
                    111: {
                    112:        assert(a != NULL);
                    113:        assert(b != NULL);
                    114: #ifdef WANT_IPV6
                    115:        if (a->sa.sa_family != b->sa.sa_family)
                    116:                return false;
                    117:        assert(ng_ipaddr_salen(a) == ng_ipaddr_salen(b));
                    118:        switch (a->sa.sa_family) {
                    119:        case AF_INET6:
                    120:                return IN6_ARE_ADDR_EQUAL(&a->sin6.sin6_addr, &b->sin6.sin6_addr);
                    121:        case AF_INET:
                    122:                return memcmp(&a->sin4.sin_addr, &b->sin4.sin_addr, sizeof(a->sin4.sin_addr)) == 0;
                    123:        }
                    124:        return false;
                    125: #else
                    126:        assert(a->sin4.sin_family == AF_INET);
                    127:        assert(b->sin4.sin_family == AF_INET);
                    128:        return memcmp(&a->sin4.sin_addr, &b->sin4.sin_addr, sizeof(a->sin4.sin_addr)) == 0;
                    129: #endif
                    130: }
                    131:
                    132:
                    133: #ifdef WANT_IPV6
                    134: GLOBAL const char *
                    135: ng_ipaddr_tostr(const ng_ipaddr_t *addr)
                    136: {
                    137:        static char strbuf[NG_INET_ADDRSTRLEN];
                    138:
                    139:        strbuf[0] = 0;
                    140:
                    141:        ng_ipaddr_tostr_r(addr, strbuf);
                    142:        return strbuf;
                    143: }
                    144:
                    145:
                    146: /* str must be at least NG_INET_ADDRSTRLEN bytes long */
                    147: GLOBAL bool
                    148: ng_ipaddr_tostr_r(const ng_ipaddr_t *addr, char *str)
                    149: {
                    150: #ifdef HAVE_GETNAMEINFO
                    151:        const struct sockaddr *sa = (const struct sockaddr *) addr;
                    152:        int ret;
                    153:
                    154:        *str = 0;
                    155:
                    156:        ret = getnameinfo(sa, ng_ipaddr_salen(addr),
                    157:                        str, NG_INET_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
                    158:        /*
                    159:         * avoid leading ':'.
                    160:         * causes mis-interpretation of client host in e.g. /WHOIS
                    161:         */
                    162:        if (*str == ':') {
                    163:                char tmp[NG_INET_ADDRSTRLEN] = "0";
                    164:                ret = getnameinfo(sa, ng_ipaddr_salen(addr),
                    165:                                  tmp + 1, (socklen_t)sizeof(tmp) - 1,
                    166:                                  NULL, 0, NI_NUMERICHOST);
                    167:                if (ret == 0)
                    168:                        strlcpy(str, tmp, NG_INET_ADDRSTRLEN);
                    169:        }
                    170:        assert (ret == 0);
                    171:        return ret == 0;
                    172: #else
                    173:        abort(); /* WANT_IPV6 depends on HAVE_GETNAMEINFO */
                    174: #endif
                    175: }
                    176:
                    177: #endif /* WANT_IPV6 */
                    178:
                    179: /* -eof- */

CVSweb