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