00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00037 #ifndef _host_addr_h_
00038 #define _host_addr_h_
00039
00040 #include "common.h"
00041 #include "misc.h"
00042
00043 enum net_type {
00044 NET_TYPE_NONE = 0,
00045 NET_TYPE_IPV4 = 4,
00046 NET_TYPE_IPV6 = 6,
00047 };
00048
00049 #ifdef USE_IPV6
00050 typedef struct host_addr {
00051 guint32 net;
00052 union {
00053 guint8 ipv6[16];
00054 guint32 ipv4;
00056 guint8 u8[16];
00057 guint16 u16[8];
00058 guint32 u32[4];
00059 } addr;
00060 } host_addr_t;
00061
00062 #else
00063
00064
00065 typedef guint32 host_addr_t;
00067 #endif
00068
00069 #if defined(USE_IPV6)
00070 static const host_addr_t ipv6_unspecified = {
00071 NET_TYPE_IPV6,
00072 { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
00073 };
00074
00075 static const host_addr_t ipv6_loopback = {
00076 NET_TYPE_IPV6,
00077 { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } },
00078 };
00079
00080 static const host_addr_t ipv6_ipv4_mapped = {
00081 NET_TYPE_IPV6,
00082 { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0 } },
00083 };
00084
00085 static const host_addr_t ipv6_multicast = {
00086 NET_TYPE_IPV6,
00087 { { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
00088 };
00089
00090 static const host_addr_t ipv6_link_local = {
00091 NET_TYPE_IPV6,
00092 { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
00093 };
00094
00095 static const host_addr_t ipv6_site_local = {
00096 NET_TYPE_IPV6,
00097 { { 0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
00098 };
00099
00100 static const host_addr_t ipv6_6to4 = {
00101 NET_TYPE_IPV6,
00102 { { 0x20, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
00103 };
00104
00105
00106 static const host_addr_t zero_host_addr;
00107
00108 gboolean host_addr_convert(const host_addr_t from, host_addr_t *to,
00109 enum net_type to_net);
00110 gboolean host_addr_can_convert(const host_addr_t from, enum net_type to_net);
00111 gboolean host_addr_6to4_to_ipv4(const host_addr_t from, host_addr_t *to);
00112
00113 static inline gboolean
00114 host_addr_initialized(const host_addr_t ha)
00115 {
00116 switch (ha.net) {
00117 case NET_TYPE_IPV4:
00118 case NET_TYPE_IPV6:
00119 return TRUE;
00120 case NET_TYPE_NONE:
00121 return FALSE;
00122 }
00123 g_assert_not_reached();
00124 return FALSE;
00125 }
00126
00127 static inline enum net_type
00128 host_addr_net(const host_addr_t ha)
00129 {
00130 return ha.net;
00131 }
00132
00133 static inline guint32
00134 host_addr_ipv4(const host_addr_t ha)
00135 {
00136 return NET_TYPE_IPV4 == ha.net ? ha.addr.ipv4 : 0;
00137 }
00138
00139 static inline const guint8 *
00140 host_addr_ipv6(const host_addr_t *ha)
00141 {
00142 return NET_TYPE_IPV6 == ha->net ? ha->addr.ipv6 : NULL;
00143 }
00144
00145 static inline host_addr_t
00146 host_addr_set_ipv4(guint32 ip)
00147 {
00148 host_addr_t ha;
00149
00150 ha.net = NET_TYPE_IPV4;
00151 ha.addr.ipv4 = ip;
00152 return ha;
00153 }
00154
00155 static inline void
00156 host_addr_set_ipv6(host_addr_t *ha, const guint8 *ipv6)
00157 {
00158 ha->net = NET_TYPE_IPV6;
00159 memcpy(ha->addr.ipv6, ipv6, 16);
00160 }
00161
00162 static inline gboolean
00163 host_addr_equal(const host_addr_t a, const host_addr_t b)
00164 {
00165 if (a.net == b.net) {
00166 switch (a.net) {
00167 case NET_TYPE_IPV4:
00168 return a.addr.ipv4 == b.addr.ipv4;
00169 case NET_TYPE_IPV6:
00170 if (0 != memcmp(a.addr.ipv6, b.addr.ipv6, sizeof a.addr.ipv6)) {
00171 host_addr_t a_ipv4, b_ipv4;
00172
00173 return host_addr_convert(a, &a_ipv4, NET_TYPE_IPV4) &&
00174 host_addr_convert(b, &b_ipv4, NET_TYPE_IPV4) &&
00175 a_ipv4.addr.ipv4 == b_ipv4.addr.ipv4;
00176 }
00177 return TRUE;
00178
00179 case NET_TYPE_NONE:
00180 return TRUE;
00181 }
00182 g_assert_not_reached();
00183 } else {
00184 host_addr_t to;
00185
00186 return host_addr_convert(a, &to, b.net) && host_addr_equal(to, b);
00187 }
00188 return FALSE;
00189 }
00190
00191 static inline gint
00192 host_addr_cmp(host_addr_t a, host_addr_t b)
00193 {
00194 gint r;
00195
00196 r = CMP(a.net, b.net);
00197 if (0 != r) {
00198 host_addr_t to;
00199
00200 if (!host_addr_convert(b, &to, a.net))
00201 return r;
00202 b = to;
00203 }
00204
00205 switch (a.net) {
00206 case NET_TYPE_IPV4:
00207 return CMP(a.addr.ipv4, b.addr.ipv4);
00208 case NET_TYPE_IPV6:
00209 {
00210 guint i;
00211
00212 for (i = 0; i < G_N_ELEMENTS(a.addr.ipv6); i++) {
00213 r = CMP(a.addr.ipv6[i], b.addr.ipv6[i]);
00214 if (0 != r)
00215 break;
00216 }
00217 }
00218 return r;
00219 case NET_TYPE_NONE:
00220 return 0;
00221 }
00222 g_assert_not_reached();
00223 return 0;
00224 }
00225
00226 static inline gboolean
00227 host_addr_matches(const host_addr_t a, const host_addr_t b, guint8 bits)
00228 {
00229 host_addr_t to;
00230 guint8 shift;
00231
00232 if (!host_addr_convert(b, &to, a.net))
00233 return FALSE;
00234
00235 switch (a.net) {
00236 case NET_TYPE_IPV4:
00237 shift = bits < 32 ? 32 - bits : 0;
00238 return (a.addr.ipv4 >> shift) == (to.addr.ipv4 >> shift);
00239
00240 case NET_TYPE_IPV6:
00241 {
00242 gint i;
00243
00244 bits = MIN(128, bits);
00245 for (i = 0; bits >= 8; i++, bits -= 8) {
00246 if (a.addr.ipv6[i] != to.addr.ipv6[i])
00247 return FALSE;
00248 }
00249
00250 if (bits > 0) {
00251 guint8 shift = 8 - bits;
00252 return (a.addr.ipv6[i] >> shift) == (to.addr.ipv6[i] >> shift);
00253 }
00254
00255 }
00256 return TRUE;
00257
00258 case NET_TYPE_NONE:
00259 return TRUE;
00260 }
00261
00262 g_assert_not_reached();
00263 return FALSE;
00264 }
00265
00266
00267 static inline gboolean
00268 is_host_addr(const host_addr_t ha)
00269 {
00270 switch (host_addr_net(ha)) {
00271 case NET_TYPE_IPV4:
00272 return 0 != ha.addr.ipv4;
00273 case NET_TYPE_IPV6:
00274 return 0 != memcmp(ha.addr.ipv6, zero_host_addr.addr.ipv6,
00275 sizeof ha.addr.ipv6);
00276 case NET_TYPE_NONE:
00277 return FALSE;
00278 }
00279 g_assert_not_reached();
00280 return FALSE;
00281 }
00282
00283 static inline int
00284 host_addr_family(const host_addr_t ha)
00285 {
00286 switch (ha.net) {
00287 case NET_TYPE_IPV4:
00288 return AF_INET;
00289 case NET_TYPE_IPV6:
00290 return AF_INET6;
00291 case NET_TYPE_NONE:
00292 break;
00293 }
00294 g_message("%u:%u", (guint8) ha.net, ha.addr.ipv4);
00295 g_assert_not_reached();
00296 return -1;
00297 }
00298
00299 static inline guint32
00300 host_addr_hash(host_addr_t ha)
00301 {
00302 switch (ha.net) {
00303 case NET_TYPE_IPV6:
00304 {
00305 host_addr_t ha_ipv4;
00306
00307 if (!host_addr_convert(ha, &ha_ipv4, NET_TYPE_IPV4)) {
00308 guint32 h = ha.net ^ ha.addr.ipv6[15];
00309 guint i;
00310
00311 for (i = 0; i < sizeof ha.addr.ipv6; i++)
00312 h ^= (guint32) ha.addr.ipv6[i] << (i * 2);
00313
00314 return h;
00315 }
00316 ha = ha_ipv4;
00317 }
00318
00319 case NET_TYPE_IPV4:
00320 return ha.net ^ ha.addr.ipv4;
00321 case NET_TYPE_NONE:
00322 return 0;
00323 }
00324 g_assert_not_reached();
00325 return -1;
00326 }
00327
00328 #else
00329
00330
00331
00332 #define host_addr_initialized(x) TRUE
00333 #define host_addr_net(x) (((void) (x)), NET_TYPE_IPV4)
00334 #define host_addr_family(x) (((void) (x)), AF_INET)
00335 #define host_addr_ipv4(x) (x)
00336 #define host_addr_set_ipv4(x) (x)
00337 #define host_addr_set_net(x, y) G_STMT_START { (void) ((x), (y)) } G_STMT_END
00338 #define is_host_addr(x) (0 != (x))
00339 #define host_addr_equal(a, b) ((a) == (b))
00340 #define host_addr_cmp(a, b) (CMP((a), (b)))
00341 #define host_addr_hash(x) (x)
00342 #define zero_host_addr 0
00343
00344 static inline gboolean
00345 host_addr_convert(const host_addr_t from, host_addr_t *to,
00346 enum net_type to_net)
00347 {
00348 if (NET_TYPE_IPV4 == to_net) {
00349 *to = from;
00350 return TRUE;
00351 }
00352 *to = zero_host_addr;
00353 return FALSE;
00354 }
00355
00356 static inline gboolean
00357 host_addr_6to4_to_ipv4(const host_addr_t unused_from, host_addr_t *to)
00358 {
00359 (void) unused_from;
00360
00361 if (to)
00362 *to = zero_host_addr;
00363 return FALSE;
00364 }
00365
00366 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00367 host_addr_matches(guint32 a, guint32 b, guint8 bits)
00368 {
00369 guint8 shift;
00370
00371 shift = bits < 32 ? 32 - bits : 0;
00372 return (a >> shift) == (b >> shift);
00373 }
00374
00375 #endif
00376
00377 guint host_addr_hash_func(gconstpointer key);
00378 gboolean host_addr_eq_func(gconstpointer p, gconstpointer q);
00379 void wfree_host_addr(gpointer key, gpointer unused_data);
00380
00381 gboolean is_private_addr(const host_addr_t addr);
00382 gboolean host_addr_is_routable(const host_addr_t addr);
00383 gboolean host_addr_is_loopback(const host_addr_t addr);
00384 const gchar *host_addr_to_string(const host_addr_t addr);
00385 size_t host_addr_to_string_buf(const host_addr_t addr, gchar *, size_t);
00386 host_addr_t string_to_host_addr(const gchar *s, const gchar **endptr);
00387 const gchar *host_addr_port_to_string(const host_addr_t addr, guint16 port);
00388 size_t host_addr_port_to_string_buf(const host_addr_t addr,
00389 guint16 port, gchar *, size_t);
00390 gboolean string_to_host_addr_port(const gchar *str, const gchar **endptr,
00391 host_addr_t *addr_ptr, guint16 *port_ptr);
00392 host_addr_t name_to_host_addr(const gchar *host);
00393 const gchar *host_addr_to_name(const host_addr_t addr);
00394 gboolean string_to_host_or_addr(const char *s, const gchar **endptr,
00395 host_addr_t *ha);
00396
00397 #endif
00398