// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2022 Felix Fietkau */ #ifndef __UNETD_HOST_H #define __UNETD_HOST_H enum peer_endpoint_type { ENDPOINT_TYPE_STATIC, ENDPOINT_TYPE_PEX, ENDPOINT_TYPE_ENDPOINT_NOTIFY, ENDPOINT_TYPE_ENDPOINT_PORT_NOTIFY, __ENDPOINT_TYPE_MAX, }; struct network_peer { struct vlist_node node; uint8_t key[CURVE25519_KEY_SIZE]; union network_addr local_addr; const char *endpoint; struct blob_attr *ipaddr; struct blob_attr *subnet; struct blob_attr *meta; int port; int pex_port; bool dynamic; bool indirect; struct { int connect_attempt; bool connected; bool handshake; bool has_local_ep_addr; union network_addr local_ep_addr; union network_endpoint endpoint; uint8_t next_endpoint_idx; union network_endpoint next_endpoint[__ENDPOINT_TYPE_MAX]; uint64_t last_ep_update; uint64_t rx_bytes, tx_bytes; uint64_t last_handshake; uint64_t last_request; uint64_t last_query_sent; int ping_wait; int last_handshake_diff; int idle; int num_net_queries; } state; }; struct network_dynamic_peer { struct list_head list; struct network_peer peer; }; struct network_host { struct avl_node node; const char *gateway; struct network_peer peer; }; struct network_group { struct avl_node node; const char *name; int n_members; struct network_host **members; }; static inline const char *network_host_name(struct network_host *host) { if (!host) return "(none)"; return host->node.key; } static inline bool network_host_is_peer(struct network_host *host) { return !!host->peer.node.avl.key; } static inline const char *network_peer_name(struct network_peer *peer) { struct network_host *host; if (!peer || peer->dynamic) return "(none)"; host = container_of(peer, struct network_host, peer); return network_host_name(host); } static inline bool network_host_uses_peer_route(struct network_host *host, struct network *net, struct network_peer *peer) { struct network_host *peer_host = container_of(peer, struct network_host, peer); if (host == peer_host || host == net->net_config.local_host) return false; if (net->net_config.local_host->gateway && !strcmp(net->net_config.local_host->gateway, network_peer_name(peer))) return true; if (peer_host->gateway && !strcmp(peer_host->gateway, network_host_name(net->net_config.local_host))) return true; if (!host->gateway) return false; return !strcmp(host->gateway, network_peer_name(peer)); } #define for_each_routed_host(cur_host, net, peer) \ avl_for_each_element(&(net)->hosts, cur_host, node) \ if (network_host_uses_peer_route(host, net, peer)) void network_hosts_update_start(struct network *net); void network_hosts_update_done(struct network *net); void network_hosts_add(struct network *net, struct blob_attr *hosts); void network_hosts_reload_dynamic_peers(struct network *net); void network_hosts_init(struct network *net); void network_hosts_free(struct network *net); #endif