#include #include #include #include #include #include #include #include #include #include #include #include #include /* Based on bitcoin's src/netaddress.cpp, hence different naming and styling! version 7f31762cb6261806542cc6d1188ca07db98a6950: Copyright (c) 2009-2010 Satoshi Nakamoto Copyright (c) 2009-2016 The Bitcoin Core developers Distributed under the MIT software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php. */ /* The common IPv4-in-IPv6 prefix */ static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; static bool IsRFC6145(const struct wireaddr *addr) { static const unsigned char pchRFC6145[] = {0,0,0,0,0,0,0,0,0xFF,0xFF,0,0}; return addr->type == ADDR_TYPE_IPV6 && memcmp(addr->addr, pchRFC6145, sizeof(pchRFC6145)) == 0; } static bool IsRFC6052(const struct wireaddr *addr) { static const unsigned char pchRFC6052[] = {0,0x64,0xFF,0x9B,0,0,0,0,0,0,0,0}; return addr->type == ADDR_TYPE_IPV6 && memcmp(addr->addr, pchRFC6052, sizeof(pchRFC6052)) == 0; } static bool IsRFC3964(const struct wireaddr *addr) { return addr->type == ADDR_TYPE_IPV6 && addr->addr[0] == 0x20 && addr->addr[1] == 0x02; } /* Return offset of IPv4 address, or 0 == not an IPv4 */ static size_t IPv4In6(const struct wireaddr *addr) { if (addr->type != ADDR_TYPE_IPV6) return 0; if (memcmp(addr->addr, pchIPv4, sizeof(pchIPv4)) == 0) return sizeof(pchIPv4); if (IsRFC6052(addr)) return 12; if (IsRFC6145(addr)) return 12; if (IsRFC3964(addr)) return 2; return 0; } /* Is this an IPv4 address, or an IPv6-wrapped IPv4 */ static bool IsIPv4(const struct wireaddr *addr) { return addr->type == ADDR_TYPE_IPV4 || IPv4In6(addr) != 0; } static bool IsIPv6(const struct wireaddr *addr) { return addr->type == ADDR_TYPE_IPV6 && IPv4In6(addr) == 0; } static bool RawEq(const struct wireaddr *addr, const void *cmp, size_t len) { size_t off = IPv4In6(addr); assert(off + len <= addr->addrlen); return memcmp(addr->addr + off, cmp, len) == 0; } /* The bitcoin code packs addresses backwards, so we map it here. */ static unsigned int GetByte(const struct wireaddr *addr, int n) { size_t off = IPv4In6(addr); assert(off + n < addr->addrlen); return addr->addr[addr->addrlen - 1 - off - n]; } static bool IsRFC1918(const struct wireaddr *addr) { return IsIPv4(addr) && ( GetByte(addr, 3) == 10 || (GetByte(addr, 3) == 192 && GetByte(addr, 2) == 168) || (GetByte(addr, 3) == 172 && (GetByte(addr, 2) >= 16 && GetByte(addr, 2) <= 31))); } static bool IsRFC2544(const struct wireaddr *addr) { return IsIPv4(addr) && GetByte(addr, 3) == 198 && (GetByte(addr, 2) == 18 || GetByte(addr, 2) == 19); } static bool IsRFC3927(const struct wireaddr *addr) { return IsIPv4(addr) && (GetByte(addr, 3) == 169 && GetByte(addr, 2) == 254); } static bool IsRFC6598(const struct wireaddr *addr) { return IsIPv4(addr) && GetByte(addr, 3) == 100 && GetByte(addr, 2) >= 64 && GetByte(addr, 2) <= 127; } static bool IsRFC5737(const struct wireaddr *addr) { return IsIPv4(addr) && ((GetByte(addr, 3) == 192 && GetByte(addr, 2) == 0 && GetByte(addr, 1) == 2) || (GetByte(addr, 3) == 198 && GetByte(addr, 2) == 51 && GetByte(addr, 1) == 100) || (GetByte(addr, 3) == 203 && GetByte(addr, 2) == 0 && GetByte(addr, 1) == 113)); } static bool IsRFC3849(const struct wireaddr *addr) { return IsIPv6(addr) && GetByte(addr, 15) == 0x20 && GetByte(addr, 14) == 0x01 && GetByte(addr, 13) == 0x0D && GetByte(addr, 12) == 0xB8; } static bool IsRFC4862(const struct wireaddr *addr) { static const unsigned char pchRFC4862[] = {0xFE,0x80,0,0,0,0,0,0}; return IsIPv6(addr) && RawEq(addr, pchRFC4862, sizeof(pchRFC4862)); } static bool IsRFC4193(const struct wireaddr *addr) { return IsIPv6(addr) && ((GetByte(addr, 15) & 0xFE) == 0xFC); } static bool IsRFC4843(const struct wireaddr *addr) { return IsIPv6(addr) && (GetByte(addr, 15) == 0x20 && GetByte(addr, 14) == 0x01 && GetByte(addr, 13) == 0x00 && (GetByte(addr, 12) & 0xF0) == 0x10); } static bool IsTor(const struct wireaddr *addr UNUSED) { /* FIXME */ return false; } static bool IsLocal(const struct wireaddr *addr) { // IPv4 loopback if (IsIPv4(addr) && (GetByte(addr, 3) == 127 || GetByte(addr, 3) == 0)) return true; // IPv6 loopback (::1/128) static const unsigned char pchLocal[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; if (IsIPv6(addr) && RawEq(addr, pchLocal, sizeof(pchLocal))) return true; return false; } static bool IsInternal(const struct wireaddr *addr) { return addr->type == ADDR_TYPE_PADDING; } static bool IsValid(const struct wireaddr *addr) { // unspecified IPv6 address (::/128) unsigned char ipNone6[16] = {}; if (IsIPv6(addr) && RawEq(addr, ipNone6, sizeof(ipNone6))) return false; // documentation IPv6 address if (IsRFC3849(addr)) return false; if (IsInternal(addr)) return false; if (IsIPv4(addr)) { // INADDR_NONE uint32_t ipNone = INADDR_NONE; if (RawEq(addr, &ipNone, sizeof(ipNone))) return false; // 0 ipNone = 0; if (RawEq(addr, &ipNone, sizeof(ipNone))) return false; } return true; } static bool IsRoutable(const struct wireaddr *addr) { return IsValid(addr) && !(IsRFC1918(addr) || IsRFC2544(addr) || IsRFC3927(addr) || IsRFC4862(addr) || IsRFC6598(addr) || IsRFC5737(addr) || (IsRFC4193(addr) && !IsTor(addr)) || IsRFC4843(addr) || IsLocal(addr) || IsInternal(addr)); } /* Trick I learned from Harald Welte: create UDP socket, connect() and * then query address. */ /* Returns 0 if protocol completely unsupported, ADDR_LISTEN if we * can't reach addr, ADDR_LISTEN_AND_ANNOUNCE if we can (and fill saddr). */ static enum addr_listen_announce get_local_sockname(int af, void *saddr, socklen_t saddrlen) { int fd = socket(af, SOCK_DGRAM, 0); if (fd < 0) { status_trace("Failed to create %u socket: %s", af, strerror(errno)); return 0; } if (connect(fd, saddr, saddrlen) != 0) { status_trace("Failed to connect %u socket: %s", af, strerror(errno)); close(fd); return ADDR_LISTEN; } if (getsockname(fd, saddr, &saddrlen) != 0) { status_trace("Failed to get %u socket name: %s", af, strerror(errno)); close(fd); return ADDR_LISTEN; } close(fd); return ADDR_LISTEN_AND_ANNOUNCE; } /* Return 0 if not available, or whether it's listenable-only or announceable. * If it's listenable only, will set wireaddr to all-zero address for universal * binding. */ static enum addr_listen_announce guess_one_address(struct wireaddr *addr, u16 portnum, enum wire_addr_type type) { enum addr_listen_announce ret; addr->type = type; addr->port = portnum; /* We point to Google nameservers, works unless you're inside Google :) */ switch (type) { case ADDR_TYPE_IPV4: { struct sockaddr_in sin; sin.sin_port = htons(53); /* 8.8.8.8 */ sin.sin_addr.s_addr = 0x08080808; sin.sin_family = AF_INET; ret = get_local_sockname(AF_INET, &sin, sizeof(sin)); addr->addrlen = sizeof(sin.sin_addr); memcpy(addr->addr, &sin.sin_addr, addr->addrlen); break; } case ADDR_TYPE_IPV6: { struct sockaddr_in6 sin6; /* 2001:4860:4860::8888 */ static const unsigned char pchGoogle[16] = {0x20,0x01,0x48,0x60,0x48,0x60,0,0,0,0,0,0,8,8,8,8}; memset(&sin6, 0, sizeof(sin6)); sin6.sin6_port = htons(53); sin6.sin6_family = AF_INET6; memcpy(sin6.sin6_addr.s6_addr, pchGoogle, sizeof(pchGoogle)); ret = get_local_sockname(AF_INET6, &sin6, sizeof(sin6)); addr->addrlen = sizeof(sin6.sin6_addr); memcpy(addr->addr, &sin6.sin6_addr, addr->addrlen); break; } case ADDR_TYPE_PADDING: status_trace("Padding address, ignoring"); return 0; } if (ret == 0) return ret; /* If we can reach it, but resulting address is unroutable, listen only */ if (ret == ADDR_LISTEN_AND_ANNOUNCE && !IsRoutable(addr)) { status_trace("Address %s is not routable", type_to_string(tmpctx, struct wireaddr, addr)); ret = ADDR_LISTEN; } if (ret == ADDR_LISTEN) { /* This corresponds to INADDR_ANY or in6addr_any */ memset(addr->addr, 0, addr->addrlen); } else { status_trace("Public address %s", type_to_string(tmpctx, struct wireaddr, addr)); } return ret; } void guess_addresses(struct wireaddr **wireaddrs, enum addr_listen_announce **listen_announce, u16 portnum) { size_t n = tal_count(*wireaddrs); status_trace("Trying to guess public addresses..."); /* We allocate an extra, then remove if it's not needed. */ tal_resize(wireaddrs, n+1); tal_resize(listen_announce, n+1); /* We do IPv6 first: on Linux, that binds to IPv4 too. */ (*listen_announce)[n] = guess_one_address(&(*wireaddrs)[n], portnum, ADDR_TYPE_IPV6); if ((*listen_announce)[n] != 0) { n++; tal_resize(wireaddrs, n+1); tal_resize(listen_announce, n+1); } (*listen_announce)[n] = guess_one_address(&(*wireaddrs)[n], portnum, ADDR_TYPE_IPV4); if ((*listen_announce)[n] == 0) { tal_resize(wireaddrs, n); tal_resize(listen_announce, n); } }