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