Avoid Windows interface macro collision in local transport
This commit is contained in:
1 parent
4c62f45984
commit
03ff431d78
3 files changed
+39
-39
No files matched your search
@@ -25,7 +25,7 @@ enum packet_drop {
|
||||
struct local_socket {
|
||||
struct local_socket* next;
|
||||
struct local_transport* owner;
|
||||
struct local_interface interface;
|
||||
struct local_interface iface;
|
||||
socket_t fd;
|
||||
void* handle;
|
||||
int present;
|
||||
@@ -122,7 +122,7 @@ static int same_address(const struct sockaddr_storage* a, const struct sockaddr_
|
||||
|
||||
static struct local_socket* find_socket(struct local_transport* t, const struct sockaddr_storage* source, uint32_t index) {
|
||||
for (struct local_socket* s = t->sockets; s; s = s->next)
|
||||
if (s->interface.index == index && index && local_on_interface(&s->interface, source)) return s;
|
||||
if (s->iface.index == index && index && local_on_interface(&s->iface, source)) return s;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -139,11 +139,11 @@ static int send_packet(struct local_socket* s, const struct sockaddr_storage* ad
|
||||
ssize_t result = socket_sendto(s->fd, data, LOCAL_HEADER_SIZE + len, (const struct sockaddr*)address, address_len);
|
||||
if (result != (ssize_t)(LOCAL_HEADER_SIZE + len)) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DISCOVERY, "send failed type=%u interface=%u destination=%s bytes=%zu result=%zd error=%s",
|
||||
type, s->interface.index, sockaddr_storage_to_str(address).str, len, result, socket_strerror(socket_get_error()));
|
||||
type, s->iface.index, sockaddr_storage_to_str(address).str, len, result, socket_strerror(socket_get_error()));
|
||||
return -1;
|
||||
}
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_DISCOVERY, "sent type=%u interface=%u destination=%s peer=%016llx request=%llu bytes=%zu",
|
||||
type, s->interface.index, sockaddr_storage_to_str(address).str, (unsigned long long)peer, (unsigned long long)request, len);
|
||||
type, s->iface.index, sockaddr_storage_to_str(address).str, (unsigned long long)peer, (unsigned long long)request, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ static void announce(struct local_socket* s, const struct sockaddr_storage* addr
|
||||
static void announce_all(struct local_transport* t) {
|
||||
if (!t->active || !t->broadcasts) return;
|
||||
for (struct local_socket* s = t->sockets; s; s = s->next)
|
||||
if (s->interface.index) announce(s, &s->interface.broadcast);
|
||||
if (s->iface.index) announce(s, &s->iface.broadcast);
|
||||
}
|
||||
|
||||
static void delivery(struct local_transport* t, struct pending_entry* p, int status) {
|
||||
@@ -210,7 +210,7 @@ static void receive_packet(struct local_socket* s, struct sockaddr_storage* sour
|
||||
uint64_t now = get_time_tb();
|
||||
struct peer_entry* p = find_peer(t, peer_id);
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_DISCOVERY, "received type=%u peer=%016llx interface=%u source=%s request=%llu bytes=%zu",
|
||||
type, (unsigned long long)peer_id, s->interface.index, sockaddr_storage_to_str(source).str, (unsigned long long)request, len);
|
||||
type, (unsigned long long)peer_id, s->iface.index, sockaddr_storage_to_str(source).str, (unsigned long long)request, len);
|
||||
if (type == LOCAL_ANNOUNCE) {
|
||||
if (destination || destination_epoch || request || !local_name_valid(payload, len)) {
|
||||
drop_packet(t, DROP_ANNOUNCE); return;
|
||||
@@ -228,7 +228,7 @@ static void receive_packet(struct local_socket* s, struct sockaddr_storage* sour
|
||||
}
|
||||
size_t j;
|
||||
for (j = 0; j < p->count; j++)
|
||||
if (p->endpoints[j].index == s->interface.index && same_address(&p->endpoints[j].address, source)) break;
|
||||
if (p->endpoints[j].index == s->iface.index && same_address(&p->endpoints[j].address, source)) break;
|
||||
int new_endpoint = j == p->count;
|
||||
if (new_endpoint) {
|
||||
if (j == ENDPOINT_MAX) {
|
||||
@@ -236,7 +236,7 @@ static void receive_packet(struct local_socket* s, struct sockaddr_storage* sour
|
||||
}
|
||||
p->count++;
|
||||
}
|
||||
p->endpoints[j] = (struct local_endpoint){ .address = *source, .index = s->interface.index, .seen = now };
|
||||
p->endpoints[j] = (struct local_endpoint){ .address = *source, .index = s->iface.index, .seen = now };
|
||||
if (changed) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_DISCOVERY, "device discovered/updated peer=%016llx name=%s endpoints=%zu",
|
||||
(unsigned long long)peer_id, p->peer.name, p->count); peers_changed(t);
|
||||
@@ -250,7 +250,7 @@ static void receive_packet(struct local_socket* s, struct sockaddr_storage* sour
|
||||
}
|
||||
size_t j;
|
||||
for (j = 0; j < p->count; j++)
|
||||
if (p->endpoints[j].index == s->interface.index && same_address(&p->endpoints[j].address, source) &&
|
||||
if (p->endpoints[j].index == s->iface.index && same_address(&p->endpoints[j].address, source) &&
|
||||
now - p->endpoints[j].seen < EXPIRE_TB) break;
|
||||
if (j == p->count) { drop_packet(t, DROP_ENDPOINT); return; }
|
||||
if (type == LOCAL_ACK) {
|
||||
@@ -313,14 +313,14 @@ static void socket_read(socket_t fd, void* arg) {
|
||||
if (size == -2) { drop_packet(t, DROP_HEADER); continue; }
|
||||
/* Unicast-сокет уже привязан к адресу интерфейса. При обмене двух процессов на одном
|
||||
* хосте ОС может указать loopback как ingress, но IPv6 scope нужен от локальной привязки. */
|
||||
if (socket->interface.index) index = socket->interface.index;
|
||||
if (socket->iface.index) index = socket->iface.index;
|
||||
struct local_socket* s = find_socket(t, &source, index);
|
||||
if (!s) {
|
||||
drop_packet(t, DROP_NONLOCAL);
|
||||
continue;
|
||||
}
|
||||
if (source.ss_family == AF_INET6) ((struct sockaddr_in6*)&source)->sin6_scope_id = index;
|
||||
receive_packet(s, &source, data, (size_t)size, !socket->interface.index);
|
||||
receive_packet(s, &source, data, (size_t)size, !socket->iface.index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,34 +329,34 @@ static void close_socket(struct local_socket* s) {
|
||||
socket_close_wrapper(s->fd); u_free(s);
|
||||
}
|
||||
|
||||
static struct local_socket* open_socket(struct local_transport* t, const struct local_interface* interface) {
|
||||
int family = interface->address.ss_family, enabled = 1;
|
||||
static struct local_socket* open_socket(struct local_transport* t, const struct local_interface* iface) {
|
||||
int family = iface->address.ss_family, enabled = 1;
|
||||
struct local_socket* s = u_calloc(1, sizeof(*s));
|
||||
if (!s) { DEBUG_ERROR(DEBUG_CATEGORY_DISCOVERY, "socket record allocation failed"); return NULL; }
|
||||
s->owner = t; s->interface = *interface; s->present = 1; s->fd = socket_create_udp(family);
|
||||
s->owner = t; s->iface = *iface; s->present = 1; s->fd = socket_create_udp(family);
|
||||
if (s->fd == SOCKET_INVALID) goto error;
|
||||
/* Общий порт используется только broadcast/multicast-приёмниками; unicast уходит на уникальные ephemeral-порты. */
|
||||
if ((!interface->index && socket_set_reuseaddr(s->fd, 1)) || socket_set_nonblocking(s->fd) ||
|
||||
if ((!iface->index && socket_set_reuseaddr(s->fd, 1)) || socket_set_nonblocking(s->fd) ||
|
||||
local_receive_options(s->fd, family)) goto error;
|
||||
if (family == AF_INET && setsockopt(s->fd, SOL_SOCKET, SO_BROADCAST, (const char*)&enabled, sizeof(enabled))) goto error;
|
||||
if (family == AF_INET && interface->index) {
|
||||
if (family == AF_INET && iface->index) {
|
||||
int ttl = 1;
|
||||
if (setsockopt(s->fd, IPPROTO_IP, IP_TTL, (const char*)&ttl, sizeof(ttl))) goto error;
|
||||
#ifdef IP_UNICAST_IF
|
||||
/* bind(IP) фиксирует источник, но не egress при перекрывающихся подсетях/VPN. */
|
||||
uint32_t index = htonl(interface->index);
|
||||
uint32_t index = htonl(iface->index);
|
||||
if (setsockopt(s->fd, IPPROTO_IP, IP_UNICAST_IF, (const char*)&index, sizeof(index))) goto error;
|
||||
#endif
|
||||
}
|
||||
if (family == AF_INET6) {
|
||||
int hops = 1;
|
||||
if (setsockopt(s->fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&enabled, sizeof(enabled))) goto error;
|
||||
if (interface->index && (setsockopt(s->fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
|
||||
(const char*)&interface->index, sizeof(interface->index)) ||
|
||||
if (iface->index && (setsockopt(s->fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
|
||||
(const char*)&iface->index, sizeof(iface->index)) ||
|
||||
setsockopt(s->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char*)&hops, sizeof(hops)))) goto error;
|
||||
}
|
||||
struct sockaddr_storage address = interface->address;
|
||||
if (!interface->index) {
|
||||
struct sockaddr_storage address = iface->address;
|
||||
if (!iface->index) {
|
||||
if (family == AF_INET) ((struct sockaddr_in*)&address)->sin_port = htons(LOCAL_TRANSPORT_PORT);
|
||||
else ((struct sockaddr_in6*)&address)->sin6_port = htons(LOCAL_TRANSPORT_PORT);
|
||||
}
|
||||
@@ -366,11 +366,11 @@ static struct local_socket* open_socket(struct local_transport* t, const struct
|
||||
if (!s->handle) goto error;
|
||||
s->next = t->sockets; t->sockets = s;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_DISCOVERY, "local UDP socket opened family=%d interface=%u address=%s port=%u",
|
||||
family, interface->index, sockaddr_storage_to_str(&address).str, socket_get_bound_port(s->fd));
|
||||
family, iface->index, sockaddr_storage_to_str(&address).str, socket_get_bound_port(s->fd));
|
||||
return s;
|
||||
error:
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_DISCOVERY, "local UDP socket failed family=%d interface=%u: %s",
|
||||
family, interface->index, socket_strerror(socket_get_error()));
|
||||
family, iface->index, socket_strerror(socket_get_error()));
|
||||
if (s->fd != SOCKET_INVALID) socket_close_wrapper(s->fd);
|
||||
u_free(s); return NULL;
|
||||
}
|
||||
@@ -394,9 +394,9 @@ static void reconcile(struct local_transport* t) {
|
||||
struct local_socket* receiver6 = NULL;
|
||||
int receiver4_found = 0;
|
||||
for (struct local_socket* s = t->sockets; s; s = s->next) {
|
||||
s->present = !s->interface.index;
|
||||
if (!s->interface.index && s->interface.address.ss_family == AF_INET6) receiver6 = s;
|
||||
if (!s->interface.index && s->interface.address.ss_family == AF_INET) receiver4_found = 1;
|
||||
s->present = !s->iface.index;
|
||||
if (!s->iface.index && s->iface.address.ss_family == AF_INET6) receiver6 = s;
|
||||
if (!s->iface.index && s->iface.address.ss_family == AF_INET) receiver4_found = 1;
|
||||
}
|
||||
if (!receiver4_found) {
|
||||
struct local_interface listener = {0}; listener.address.ss_family = AF_INET;
|
||||
@@ -410,9 +410,9 @@ static void reconcile(struct local_transport* t) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
struct local_socket* found = NULL;
|
||||
for (struct local_socket* s = t->sockets; s; s = s->next)
|
||||
if (s->interface.index == interfaces[i].index && same_address(&s->interface.address, &interfaces[i].address)) { found = s; break; }
|
||||
if (s->iface.index == interfaces[i].index && same_address(&s->iface.address, &interfaces[i].address)) { found = s; break; }
|
||||
if (found) {
|
||||
found->present = 1; found->interface = interfaces[i];
|
||||
found->present = 1; found->iface = interfaces[i];
|
||||
continue;
|
||||
}
|
||||
open_socket(t, &interfaces[i]);
|
||||
@@ -422,22 +422,22 @@ static void reconcile(struct local_transport* t) {
|
||||
struct local_socket* s = *link;
|
||||
if (s->present) { link = &s->next; continue; }
|
||||
DEBUG_INFO(DEBUG_CATEGORY_DISCOVERY, "local UDP socket removed interface=%u address=%s",
|
||||
s->interface.index, sockaddr_storage_to_str(&s->interface.address).str);
|
||||
s->iface.index, sockaddr_storage_to_str(&s->iface.address).str);
|
||||
*link = s->next; close_socket(s);
|
||||
}
|
||||
if (!receiver6) return;
|
||||
for (size_t i = 0; i < t->joined6_count;) {
|
||||
int present = 0;
|
||||
for (struct local_socket* s = t->sockets; s; s = s->next)
|
||||
if (s->interface.index == t->joined6[i] && s->interface.address.ss_family == AF_INET6) present = 1;
|
||||
if (s->iface.index == t->joined6[i] && s->iface.address.ss_family == AF_INET6) present = 1;
|
||||
if (present) { i++; continue; }
|
||||
membership(receiver6, t->joined6[i], 0); t->joined6[i] = t->joined6[--t->joined6_count];
|
||||
}
|
||||
for (struct local_socket* s = t->sockets; s; s = s->next) {
|
||||
if (!s->interface.index || s->interface.address.ss_family != AF_INET6) continue;
|
||||
if (!s->iface.index || s->iface.address.ss_family != AF_INET6) continue;
|
||||
size_t i;
|
||||
for (i = 0; i < t->joined6_count; i++) if (t->joined6[i] == s->interface.index) break;
|
||||
if (i == t->joined6_count && !membership(receiver6, s->interface.index, 1)) t->joined6[t->joined6_count++] = s->interface.index;
|
||||
for (i = 0; i < t->joined6_count; i++) if (t->joined6[i] == s->iface.index) break;
|
||||
if (i == t->joined6_count && !membership(receiver6, s->iface.index, 1)) t->joined6[t->joined6_count++] = s->iface.index;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -168,11 +168,11 @@ ssize_t local_receive(socket_t fd, void* data, size_t capacity, struct sockaddr_
|
||||
#endif
|
||||
}
|
||||
|
||||
int local_on_interface(const struct local_interface* interface, const struct sockaddr_storage* source) {
|
||||
if (source->ss_family != interface->address.ss_family || !ss_get_port(source)) return 0;
|
||||
int local_on_interface(const struct local_interface* iface, const struct sockaddr_storage* source) {
|
||||
if (source->ss_family != iface->address.ss_family || !ss_get_port(source)) return 0;
|
||||
if (source->ss_family == AF_INET6) return IN6_IS_ADDR_LINKLOCAL(&((const struct sockaddr_in6*)source)->sin6_addr);
|
||||
uint32_t address = ((const struct sockaddr_in*)source)->sin_addr.s_addr;
|
||||
uint32_t own = ((const struct sockaddr_in*)&interface->address)->sin_addr.s_addr;
|
||||
return address && address != UINT32_MAX && (address & interface->mask4) == (own & interface->mask4) &&
|
||||
address != (own | ~interface->mask4) && address != (own & interface->mask4);
|
||||
uint32_t own = ((const struct sockaddr_in*)&iface->address)->sin_addr.s_addr;
|
||||
return address && address != UINT32_MAX && (address & iface->mask4) == (own & iface->mask4) &&
|
||||
address != (own | ~iface->mask4) && address != (own & iface->mask4);
|
||||
}
|
||||
@@ -22,6 +22,6 @@ int local_receive_options(socket_t fd, int family);
|
||||
/* -2 = пакет усечён, -1 = ошибка ОС. index — входящий интерфейс (в том числе для IPv4 broadcast). */
|
||||
ssize_t local_receive(socket_t fd, void* data, size_t capacity, struct sockaddr_storage* source, uint32_t* index);
|
||||
/* Проверить адрес/порт источника: IPv4 той же подсети либо IPv6 link-local; 1 = подходит. */
|
||||
int local_on_interface(const struct local_interface* interface, const struct sockaddr_storage* source);
|
||||
int local_on_interface(const struct local_interface* iface, const struct sockaddr_storage* source);
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user