[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     ! 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