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
00042 #include "lib/endian.h"
00043 #include "lib/misc.h"
00044
00051 enum net_type {
00052 NET_TYPE_NONE = 0,
00053 NET_TYPE_LOCAL = 1,
00054 NET_TYPE_IPV4 = 4,
00055 NET_TYPE_IPV6 = 6
00056 };
00057
00058 static inline gint
00059 net_type_to_pf(enum net_type net)
00060 {
00061 switch (net) {
00062 case NET_TYPE_NONE: return PF_UNSPEC;
00063 case NET_TYPE_LOCAL: return PF_LOCAL;
00064 case NET_TYPE_IPV4: return PF_INET;
00065 case NET_TYPE_IPV6:
00066 #ifdef HAS_IPV6
00067 return PF_INET6;
00068 #else
00069 return PF_UNSPEC;
00070 #endif
00071 }
00072 g_assert_not_reached();
00073 return PF_UNSPEC;
00074 }
00075
00076 static inline gint
00077 net_type_to_af(enum net_type net)
00078 {
00079 switch (net) {
00080 case NET_TYPE_NONE: return AF_UNSPEC;
00081 case NET_TYPE_LOCAL: return AF_LOCAL;
00082 case NET_TYPE_IPV4: return AF_INET;
00083 case NET_TYPE_IPV6:
00084 #ifdef HAS_IPV6
00085 return AF_INET6;
00086 #else
00087 return AF_UNSPEC;
00088 #endif
00089 }
00090 g_assert_not_reached();
00091 return AF_UNSPEC;
00092 }
00093
00094
00095 typedef struct host_addr {
00096 guint32 net;
00097 union {
00098 guint8 ipv6[16];
00099 guint32 ipv4;
00100 } addr;
00101 } host_addr_t;
00102
00103 struct packed_host_addr {
00104 guchar net;
00105 guchar addr[sizeof ((host_addr_t *) 0)->addr];
00106 };
00107
00108 struct packed_host {
00109 guchar port[sizeof (guint16)];
00110 struct packed_host_addr ha;
00111 };
00112
00113 typedef union socket_addr {
00114 guint8 len;
00115 struct sockaddr_in inet4;
00116 #ifdef HAS_IPV6
00117 struct sockaddr_in6 inet6;
00118 #endif
00119 } socket_addr_t;
00120
00121 static const host_addr_t ipv4_unspecified = {
00122 NET_TYPE_IPV4,
00123 { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
00124 };
00125
00126 static const host_addr_t ipv4_loopback = {
00127 NET_TYPE_IPV4,
00128 { { 0x7f, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
00129 };
00130
00131 static const host_addr_t ipv6_unspecified = {
00132 NET_TYPE_IPV6,
00133 { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
00134 };
00135
00136 static const host_addr_t ipv6_loopback = {
00137 NET_TYPE_IPV6,
00138 { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } },
00139 };
00140
00141 static const host_addr_t ipv6_ipv4_mapped = {
00142 NET_TYPE_IPV6,
00143 { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0 } },
00144 };
00145
00146 static const host_addr_t ipv6_multicast = {
00147 NET_TYPE_IPV6,
00148 { { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
00149 };
00150
00151 static const host_addr_t ipv6_link_local = {
00152 NET_TYPE_IPV6,
00153 { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
00154 };
00155
00156 static const host_addr_t ipv6_site_local = {
00157 NET_TYPE_IPV6,
00158 { { 0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
00159 };
00160
00161 static const host_addr_t ipv6_6to4 = {
00162 NET_TYPE_IPV6,
00163 { { 0x20, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
00164 };
00165
00166
00167 static const host_addr_t local_host_addr = {
00168 NET_TYPE_LOCAL,
00169 { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
00170 };
00171
00172 static const host_addr_t zero_host_addr;
00173
00174 gboolean host_addr_convert(const host_addr_t from, host_addr_t *to,
00175 enum net_type to_net);
00176 gboolean host_addr_can_convert(const host_addr_t from, enum net_type to_net);
00177 gboolean host_addr_6to4_to_ipv4(const host_addr_t from, host_addr_t *to);
00178
00179
00180 static inline gboolean
00181 host_addr_initialized(const host_addr_t ha)
00182 {
00183 switch (ha.net) {
00184 case NET_TYPE_IPV4:
00185 case NET_TYPE_IPV6:
00186 case NET_TYPE_LOCAL:
00187 return TRUE;
00188 case NET_TYPE_NONE:
00189 return FALSE;
00190 }
00191 g_assert_not_reached();
00192 return FALSE;
00193 }
00194
00195 static inline const gchar *
00196 net_type_to_string(enum net_type net)
00197 {
00198 switch (net) {
00199 case NET_TYPE_IPV4: return "IPv4";
00200 case NET_TYPE_IPV6: return "IPv6";
00201 case NET_TYPE_LOCAL: return "<local>";
00202 case NET_TYPE_NONE: return "<none>";
00203 }
00204 g_assert_not_reached();
00205 return NULL;
00206 }
00207
00208 static inline enum net_type
00209 host_addr_net(const host_addr_t ha)
00210 {
00211 return ha.net;
00212 }
00213
00214 static inline guint32
00215 host_addr_ipv4(const host_addr_t ha)
00216 {
00217 return NET_TYPE_IPV4 == ha.net ? ha.addr.ipv4 : 0;
00218 }
00219
00220 static inline const guint8 *
00221 host_addr_ipv6(const host_addr_t *ha)
00222 {
00223 return NET_TYPE_IPV6 == ha->net ? ha->addr.ipv6 : NULL;
00224 }
00225
00226 static inline host_addr_t
00227 host_addr_get_ipv4(guint32 ip)
00228 {
00229 host_addr_t ha;
00230
00231 ha.net = NET_TYPE_IPV4;
00232 ha.addr.ipv4 = ip;
00233 return ha;
00234 }
00235
00236 static inline host_addr_t
00237 host_addr_peek_ipv4(const void *ipv4)
00238 {
00239 return host_addr_get_ipv4(peek_be32(ipv4));
00240 }
00241
00242 static inline host_addr_t
00243 host_addr_peek_ipv6(const guint8 *ipv6)
00244 {
00245 host_addr_t ha;
00246
00247 ha.net = NET_TYPE_IPV6;
00248 memcpy(ha.addr.ipv6, ipv6, 16);
00249 return ha;
00250 }
00251
00252 static inline gboolean
00253 host_addr_equal(const host_addr_t a, const host_addr_t b)
00254 {
00255 if (a.net == b.net) {
00256 switch (a.net) {
00257 case NET_TYPE_IPV4:
00258 return host_addr_ipv4(a) == host_addr_ipv4(b);
00259 case NET_TYPE_IPV6:
00260 if (0 != memcmp(a.addr.ipv6, b.addr.ipv6, sizeof a.addr.ipv6)) {
00261 host_addr_t a_ipv4, b_ipv4;
00262
00263 return host_addr_convert(a, &a_ipv4, NET_TYPE_IPV4) &&
00264 host_addr_convert(b, &b_ipv4, NET_TYPE_IPV4) &&
00265 host_addr_ipv4(a_ipv4) == host_addr_ipv4(b_ipv4);
00266 }
00267 return TRUE;
00268
00269 case NET_TYPE_LOCAL:
00270 case NET_TYPE_NONE:
00271 return TRUE;
00272 }
00273 g_assert_not_reached();
00274 } else {
00275 host_addr_t to;
00276
00277 return host_addr_convert(a, &to, b.net) && host_addr_equal(to, b);
00278 }
00279 return FALSE;
00280 }
00281
00282 static inline gint
00283 host_addr_cmp(host_addr_t a, host_addr_t b)
00284 {
00285 gint r;
00286
00287 r = CMP(a.net, b.net);
00288 if (0 != r) {
00289 host_addr_t to;
00290
00291 if (!host_addr_convert(b, &to, a.net))
00292 return r;
00293 b = to;
00294 }
00295
00296 switch (a.net) {
00297 case NET_TYPE_IPV4:
00298 return CMP(host_addr_ipv4(a), host_addr_ipv4(b));
00299 case NET_TYPE_IPV6:
00300 {
00301 guint i;
00302
00303 for (i = 0; i < G_N_ELEMENTS(a.addr.ipv6); i++) {
00304 r = CMP(a.addr.ipv6[i], b.addr.ipv6[i]);
00305 if (0 != r)
00306 break;
00307 }
00308 }
00309 return r;
00310 case NET_TYPE_LOCAL:
00311 case NET_TYPE_NONE:
00312 return 0;
00313 }
00314 g_assert_not_reached();
00315 return 0;
00316 }
00317
00318 static inline gboolean
00319 host_addr_matches(const host_addr_t a, const host_addr_t b, guint8 bits)
00320 {
00321 host_addr_t to;
00322 guint8 shift;
00323
00324 if (!host_addr_convert(b, &to, a.net))
00325 return FALSE;
00326
00327 switch (a.net) {
00328 case NET_TYPE_IPV4:
00329 shift = bits < 32 ? 32 - bits : 0;
00330 return host_addr_ipv4(a) >> shift == host_addr_ipv4(to) >> shift;
00331
00332 case NET_TYPE_IPV6:
00333 {
00334 gint i;
00335
00336 bits = MIN(128, bits);
00337 for (i = 0; bits >= 8; i++, bits -= 8) {
00338 if (a.addr.ipv6[i] != to.addr.ipv6[i])
00339 return FALSE;
00340 }
00341
00342 if (bits > 0) {
00343 shift = 8 - bits;
00344 return (a.addr.ipv6[i] >> shift) == (to.addr.ipv6[i] >> shift);
00345 }
00346
00347 }
00348 return TRUE;
00349
00350 case NET_TYPE_LOCAL:
00351 case NET_TYPE_NONE:
00352 return TRUE;
00353 }
00354
00355 g_assert_not_reached();
00356 return FALSE;
00357 }
00358
00359
00360 static inline gboolean
00361 is_host_addr(const host_addr_t ha)
00362 {
00363 switch (host_addr_net(ha)) {
00364 case NET_TYPE_IPV4:
00365 return 0 != host_addr_ipv4(ha);
00366 case NET_TYPE_IPV6:
00367 return 0 != memcmp(ha.addr.ipv6, zero_host_addr.addr.ipv6,
00368 sizeof ha.addr.ipv6);
00369 case NET_TYPE_LOCAL:
00370 case NET_TYPE_NONE:
00371 return FALSE;
00372 }
00373 g_assert_not_reached();
00374 return FALSE;
00375 }
00376
00377 static inline guint32
00378 host_addr_hash(host_addr_t ha)
00379 {
00380 switch (ha.net) {
00381 case NET_TYPE_IPV6:
00382 {
00383 host_addr_t ha_ipv4;
00384
00385 if (!host_addr_convert(ha, &ha_ipv4, NET_TYPE_IPV4)) {
00386 guint32 h = ha.net ^ ha.addr.ipv6[15];
00387 guint i;
00388
00389 for (i = 0; i < sizeof ha.addr.ipv6; i++)
00390 h ^= (guint32) ha.addr.ipv6[i] << (i * 2);
00391
00392 return h;
00393 }
00394 ha = ha_ipv4;
00395 }
00396
00397 case NET_TYPE_IPV4:
00398 return ha.net ^ host_addr_ipv4(ha);
00399 case NET_TYPE_LOCAL:
00400 case NET_TYPE_NONE:
00401 return ha.net;
00402 }
00403 g_assert_not_reached();
00404 return -1;
00405 }
00406
00413 static inline host_addr_t
00414 socket_addr_get_addr(const socket_addr_t *addr)
00415 {
00416 host_addr_t ha;
00417
00418 g_assert(addr);
00419
00420 if (AF_INET == addr->inet4.sin_family) {
00421 ha = host_addr_peek_ipv4(&addr->inet4.sin_addr.s_addr);
00422 #if defined(HAS_IPV6)
00423 } else if (AF_INET6 == addr->inet6.sin6_family) {
00424 ha = host_addr_peek_ipv6(addr->inet6.sin6_addr.s6_addr);
00425 #endif
00426 } else {
00427 ha = zero_host_addr;
00428 }
00429
00430 return ha;
00431 }
00432
00439 static inline guint16
00440 socket_addr_get_port(const socket_addr_t *addr)
00441 {
00442 g_assert(addr != NULL);
00443
00444 if (AF_INET == addr->inet4.sin_family) {
00445 return ntohs(addr->inet4.sin_port);
00446 #if defined(HAS_IPV6)
00447 } else if (AF_INET6 == addr->inet6.sin6_family) {
00448 return ntohs(addr->inet6.sin6_port);
00449 #endif
00450 }
00451
00452 return 0;
00453 }
00454
00455 static inline socklen_t
00456 socket_addr_get_len(const socket_addr_t *addr)
00457 {
00458 g_assert(addr != NULL);
00459
00460 if (AF_INET == addr->inet4.sin_family) {
00461 return sizeof addr->inet4;
00462 #if defined(HAS_IPV6)
00463 } else if (AF_INET6 == addr->inet6.sin6_family) {
00464 return sizeof addr->inet6;
00465 #endif
00466 }
00467
00468 return 0;
00469 }
00470
00471 static inline const struct sockaddr *
00472 socket_addr_get_const_sockaddr(const socket_addr_t *addr)
00473 {
00474 g_assert(addr != NULL);
00475
00476 if (AF_INET == addr->inet4.sin_family) {
00477 return cast_to_gconstpointer(&addr->inet4);
00478 #if defined(HAS_IPV6)
00479 } else if (AF_INET6 == addr->inet6.sin6_family) {
00480 return cast_to_gconstpointer(&addr->inet6);
00481 #endif
00482 }
00483
00484 return NULL;
00485 }
00486
00487 static inline struct sockaddr *
00488 socket_addr_get_sockaddr(socket_addr_t *addr)
00489 {
00490 return (struct sockaddr *) socket_addr_get_const_sockaddr(addr);
00491 }
00492
00493 static inline gint
00494 socket_addr_get_family(const socket_addr_t *addr)
00495 {
00496 g_assert(addr != NULL);
00497
00498 if (AF_INET == addr->inet4.sin_family) {
00499 return AF_INET;
00500 #if defined(HAS_IPV6)
00501 } else if (AF_INET6 == addr->inet6.sin6_family) {
00502 return AF_INET6;
00503 #endif
00504 }
00505
00506 return 0;
00507 }
00508
00509 socklen_t socket_addr_set(socket_addr_t *sa_ptr,
00510 const host_addr_t addr, guint16 port);
00511 socklen_t socket_addr_init(socket_addr_t *sa_ptr, enum net_type net);
00512
00513 guint host_addr_hash_func(gconstpointer key);
00514 gboolean host_addr_eq_func(gconstpointer p, gconstpointer q);
00515 void wfree_host_addr(gpointer key, gpointer unused_data);
00516
00517 int host_addr_family(const host_addr_t ha);
00518 gboolean is_private_addr(const host_addr_t addr);
00519 gboolean host_addr_is_routable(const host_addr_t addr);
00520 gboolean host_addr_is_loopback(const host_addr_t addr);
00521
00522 static inline gboolean
00523 host_addr_is_ipv4_mapped(const host_addr_t addr)
00524 {
00525 return NET_TYPE_IPV6 == host_addr_net(addr) &&
00526 host_addr_matches(addr, ipv6_ipv4_mapped, 96);
00527 }
00528
00529 const gchar *host_addr_to_string(const host_addr_t addr);
00530 size_t host_addr_to_string_buf(const host_addr_t addr, gchar *, size_t);
00531 gboolean string_to_host_addr(const gchar *s, const gchar **endptr, host_addr_t *addr_ptr);
00532 const gchar *host_addr_port_to_string(const host_addr_t addr, guint16 port);
00533 const gchar *host_addr_port_to_string2(const host_addr_t addr, guint16 port);
00534 size_t host_addr_port_to_string_buf(const host_addr_t addr,
00535 guint16 port, gchar *, size_t);
00536 gboolean string_to_host_addr_port(const gchar *str, const gchar **endptr,
00537 host_addr_t *addr_ptr, guint16 *port_ptr);
00538 const gchar *host_port_to_string(const gchar *hostname,
00539 host_addr_t addr, guint16 port);
00540
00541 GSList *name_to_host_addr(const gchar *host, enum net_type net);
00542 void host_addr_free_list(GSList **sl_ptr);
00543
00544 host_addr_t name_to_single_host_addr(const gchar *host, enum net_type net);
00545
00546 const gchar *host_addr_to_name(const host_addr_t addr);
00547 gboolean string_to_host_or_addr(const char *s, const gchar **endptr,
00548 host_addr_t *ha);
00549
00550 GSList *host_addr_get_interface_addrs(enum net_type net);
00551 void host_addr_free_interface_addrs(GSList **sl_ptr);
00552
00553 guint packed_host_addr_size(const struct packed_host_addr paddr);
00554 struct packed_host_addr host_addr_pack(const host_addr_t addr);
00555 host_addr_t packed_host_addr_unpack(const struct packed_host_addr paddr);
00556
00557 guint packed_host_size(const struct packed_host paddr);
00558 struct packed_host host_pack(const host_addr_t addr, guint16 port);
00559 gboolean packed_host_unpack(const struct packed_host phost,
00560 host_addr_t *addr_ptr, guint16 *port_ptr);
00561
00562 guint packed_host_hash_func(gconstpointer key);
00563 gboolean packed_host_eq_func(gconstpointer p, gconstpointer q);
00564 gpointer walloc_packed_host(const host_addr_t addr, guint16 port);
00565 void wfree_packed_host(gpointer key, gpointer unused_data);
00566
00567 #endif
00568