diff --git a/gossipd/routing.c b/gossipd/routing.c index 662efea5b..fd583a020 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -427,109 +427,6 @@ static bool add_channel_direction(struct routing_state *rstate, return true; } -/* BOLT #7: - * - * The following `address descriptor` types are defined: - * - * * `0`: padding. data = none (length 0). - * * `1`: ipv4. data = `[4:ipv4_addr][2:port]` (length 6) - * * `2`: ipv6. data = `[16:ipv6_addr][2:port]` (length 18) - */ - -/* FIXME: Don't just take first one, depends whether we have IPv6 ourselves */ -/* Returns false iff it was malformed */ -bool read_ip(const tal_t *ctx, const u8 *addresses, char **hostname, - int *port) -{ - size_t len = tal_count(addresses); - const u8 *p = addresses; - char tempaddr[INET6_ADDRSTRLEN]; - be16 portnum; - - *hostname = NULL; - while (len) { - u8 type = *p; - p++; - len--; - - switch (type) { - case 0: - break; - case 1: - /* BOLT #7: - * - * The receiving node SHOULD fail the connection if - * `addrlen` is insufficient to hold the address - * descriptors of the known types. - */ - if (len < 6) - return false; - inet_ntop(AF_INET, p, tempaddr, sizeof(tempaddr)); - memcpy(&portnum, p + 4, sizeof(portnum)); - *hostname = tal_strdup(ctx, tempaddr); - *port = be16_to_cpu(portnum); - return true; - case 2: - if (len < 18) - return false; - inet_ntop(AF_INET6, p, tempaddr, sizeof(tempaddr)); - memcpy(&portnum, p + 16, sizeof(portnum)); - *hostname = tal_strdup(ctx, tempaddr); - *port = be16_to_cpu(portnum); - return true; - default: - /* BOLT #7: - * - * The receiving node SHOULD ignore the first `address - * descriptor` which does not match the types defined - * above. - */ - return true; - } - } - - /* Not a fatal error. */ - return true; -} - -/* BOLT #7: - * - * The creating node SHOULD fill `addresses` with an address descriptor for - * each public network address which expects incoming connections, and MUST - * set `addrlen` to the number of bytes in `addresses`. Non-zero typed - * address descriptors MUST be placed in ascending order; any number of - * zero-typed address descriptors MAY be placed anywhere, but SHOULD only be - * used for aligning fields following `addresses`. - * - * The creating node MUST NOT create a type 1 or type 2 address descriptor - * with `port` equal to zero, and SHOULD ensure `ipv4_addr` and `ipv6_addr` - * are routable addresses. The creating node MUST NOT include more than one - * `address descriptor` of the same type. - */ -/* FIXME: handle case where we have both ipv6 and ipv4 addresses! */ -u8 *write_ip(const tal_t *ctx, const char *srcip, int port) -{ - u8 *address; - be16 portnum = cpu_to_be16(port); - - if (!port) - return tal_arr(ctx, u8, 0); - - if (!strchr(srcip, ':')) { - address = tal_arr(ctx, u8, 7); - address[0] = 1; - inet_pton(AF_INET, srcip, address+1); - memcpy(address + 5, &portnum, sizeof(portnum)); - return address; - } else { - address = tal_arr(ctx, u8, 18); - address[0] = 2; - inet_pton(AF_INET6, srcip, address+1); - memcpy(address + 17, &portnum, sizeof(portnum)); - return address; - } -} - /* Verify the signature of a channel_update message */ static bool check_channel_update(const struct pubkey *node_key, const secp256k1_ecdsa_signature *node_sig, @@ -731,20 +628,32 @@ void handle_channel_update(struct routing_state *rstate, const u8 *update, size_ tal_free(tmpctx); } -static struct ipaddr *read_addresses(const tal_t *ctx, u8 *ser) +static struct ipaddr *read_addresses(const tal_t *ctx, const u8 *ser) { const u8 *cursor = ser; size_t max = tal_len(ser); struct ipaddr *ipaddrs = tal_arr(ctx, struct ipaddr, 0); int numaddrs = 0; - while (cursor < ser + max) { - numaddrs++; - tal_resize(&ipaddrs, numaddrs); - fromwire_ipaddr(&cursor, &max, &ipaddrs[numaddrs-1]); - if (cursor == NULL) { - /* Parsing address failed */ - return tal_free(ipaddrs); + while (cursor && cursor < ser + max) { + struct ipaddr ipaddr; + + /* BOLT #7: + * + * The receiving node SHOULD ignore the first `address + * descriptor` which does not match the types defined + * above. + */ + if (!fromwire_ipaddr(&cursor, &max, &ipaddr)) { + if (!cursor) + /* Parsing address failed */ + return tal_free(ipaddrs); + /* Unknown type, stop there. */ + break; } + + tal_resize(&ipaddrs, numaddrs+1); + ipaddrs[numaddrs] = ipaddr; + numaddrs++; } return ipaddrs; } diff --git a/gossipd/routing.h b/gossipd/routing.h index 543a7ee6d..b3e562b25 100644 --- a/gossipd/routing.h +++ b/gossipd/routing.h @@ -115,9 +115,6 @@ struct node_connection *get_connection_by_scid(const struct routing_state *rstat const struct short_channel_id *schanid, const u8 direction); -bool read_ip(const tal_t *ctx, const u8 *addresses, char **hostname, int *port); -u8 *write_ip(const tal_t *ctx, const char *srcip, int port); - /* Handlers for incoming messages */ void handle_channel_announcement(struct routing_state *rstate, const u8 *announce, size_t len); void handle_channel_update(struct routing_state *rstate, const u8 *update, size_t len); diff --git a/gossipd/test/run-find_route-specific.c b/gossipd/test/run-find_route-specific.c index d3f3577d5..7af3930cf 100644 --- a/gossipd/test/run-find_route-specific.c +++ b/gossipd/test/run-find_route-specific.c @@ -26,7 +26,7 @@ bool fromwire_channel_announcement(const tal_t *ctx UNNEEDED, const void *p UNNE bool fromwire_channel_update(const void *p UNNEEDED, size_t *plen UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, struct sha256_double *chain_hash UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, u32 *timestamp UNNEEDED, u16 *flags UNNEEDED, u16 *cltv_expiry_delta UNNEEDED, u64 *htlc_minimum_msat UNNEEDED, u32 *fee_base_msat UNNEEDED, u32 *fee_proportional_millionths UNNEEDED) { fprintf(stderr, "fromwire_channel_update called!\n"); abort(); } /* Generated stub for fromwire_ipaddr */ -void fromwire_ipaddr(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct ipaddr *addr UNNEEDED) +bool fromwire_ipaddr(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct ipaddr *addr UNNEEDED) { fprintf(stderr, "fromwire_ipaddr called!\n"); abort(); } /* Generated stub for fromwire_node_announcement */ bool fromwire_node_announcement(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, u8 **features UNNEEDED, u32 *timestamp UNNEEDED, struct pubkey *node_id UNNEEDED, u8 rgb_color[3] UNNEEDED, u8 alias[32] UNNEEDED, u8 **addresses UNNEEDED) diff --git a/gossipd/test/run-find_route.c b/gossipd/test/run-find_route.c index fcaa2f9ab..b187fb412 100644 --- a/gossipd/test/run-find_route.c +++ b/gossipd/test/run-find_route.c @@ -19,7 +19,7 @@ bool fromwire_channel_announcement(const tal_t *ctx UNNEEDED, const void *p UNNE bool fromwire_channel_update(const void *p UNNEEDED, size_t *plen UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, struct sha256_double *chain_hash UNNEEDED, struct short_channel_id *short_channel_id UNNEEDED, u32 *timestamp UNNEEDED, u16 *flags UNNEEDED, u16 *cltv_expiry_delta UNNEEDED, u64 *htlc_minimum_msat UNNEEDED, u32 *fee_base_msat UNNEEDED, u32 *fee_proportional_millionths UNNEEDED) { fprintf(stderr, "fromwire_channel_update called!\n"); abort(); } /* Generated stub for fromwire_ipaddr */ -void fromwire_ipaddr(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct ipaddr *addr UNNEEDED) +bool fromwire_ipaddr(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct ipaddr *addr UNNEEDED) { fprintf(stderr, "fromwire_ipaddr called!\n"); abort(); } /* Generated stub for fromwire_node_announcement */ bool fromwire_node_announcement(const tal_t *ctx UNNEEDED, const void *p UNNEEDED, size_t *plen UNNEEDED, secp256k1_ecdsa_signature *signature UNNEEDED, u8 **features UNNEEDED, u32 *timestamp UNNEEDED, struct pubkey *node_id UNNEEDED, u8 rgb_color[3] UNNEEDED, u8 alias[32] UNNEEDED, u8 **addresses UNNEEDED) diff --git a/lightningd/gossip_msg.c b/lightningd/gossip_msg.c index eb5307a3b..4d95ca8dd 100644 --- a/lightningd/gossip_msg.c +++ b/lightningd/gossip_msg.c @@ -9,7 +9,11 @@ void fromwire_gossip_getnodes_entry(const tal_t *ctx, const u8 **pptr, size_t *m entry->addresses = tal_arr(ctx, struct ipaddr, numaddresses); for (i=0; iaddresses); + /* Gossipd doesn't hand us addresses we can't understand. */ + if (!fromwire_ipaddr(pptr, max, entry->addresses)) { + fromwire_fail(pptr, max); + return; + } } } void towire_gossip_getnodes_entry(u8 **pptr, const struct gossip_getnodes_entry *entry) diff --git a/wire/fromwire.c b/wire/fromwire.c index f82fe8193..975b56c21 100644 --- a/wire/fromwire.c +++ b/wire/fromwire.c @@ -170,28 +170,39 @@ void fromwire_ripemd160(const u8 **cursor, size_t *max, struct ripemd160 *ripemd fromwire(cursor, max, ripemd, sizeof(*ripemd)); } -void fromwire_ipaddr(const u8 **cursor, size_t *max, struct ipaddr *addr) -{ - /* Skip any eventual padding */ - while (**cursor == 0) { - (*cursor)++; - } +/* BOLT #7: + * + * The following `address descriptor` types are defined: + * + * * `0`: padding. data = none (length 0). + * * `1`: ipv4. data = `[4:ipv4_addr][2:port]` (length 6) + * * `2`: ipv6. data = `[16:ipv6_addr][2:port]` (length 18) + */ +/* FIXME: Tor addresses! */ + +/* Returns false if we didn't parse it, and *cursor == NULL if malformed. */ +bool fromwire_ipaddr(const u8 **cursor, size_t *max, struct ipaddr *addr) +{ + addr->type = fromwire_u8(cursor, max); - addr->type = **cursor; - (*cursor)++; switch (addr->type) { - case 1: + case ADDR_TYPE_IPV4: addr->addrlen = 4; break; - case 2: + case ADDR_TYPE_IPV6: addr->addrlen = 16; break; default: - fromwire_fail(cursor, max); - return; + return false; } fromwire(cursor, max, addr->addr, addr->addrlen); addr->port = fromwire_u16(cursor, max); + + /* Skip any post-padding */ + while (*max && (*cursor)[0] == ADDR_TYPE_PADDING) + fromwire_u8(cursor, max); + + return *cursor != NULL; } void fromwire_u8_array(const u8 **cursor, size_t *max, u8 *arr, size_t num) diff --git a/wire/wire.h b/wire/wire.h index 8a0b986c4..b75143854 100644 --- a/wire/wire.h +++ b/wire/wire.h @@ -86,7 +86,7 @@ void fromwire_sha256_double(const u8 **cursor, size_t *max, struct sha256_double *sha256d); void fromwire_preimage(const u8 **cursor, size_t *max, struct preimage *preimage); void fromwire_ripemd160(const u8 **cursor, size_t *max, struct ripemd160 *ripemd); -void fromwire_ipaddr(const u8 **cursor, size_t *max, struct ipaddr *addr); +bool fromwire_ipaddr(const u8 **cursor, size_t *max, struct ipaddr *addr); void fromwire_pad(const u8 **cursor, size_t *max, size_t num); void fromwire_u8_array(const u8 **cursor, size_t *max, u8 *arr, size_t num);