Fix Broadcast on FreeBSD

This commit is contained in:
Florian Märkl 2019-08-25 16:38:14 +02:00
commit 9a006423bf
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
3 changed files with 57 additions and 2 deletions

View file

@ -163,6 +163,13 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_init(ChiakiDiscovery *discovery,
if(r < 0)
CHIAKI_LOGE(discovery->log, "Discovery failed to setsockopt SO_BROADCAST");
//#ifdef __FreeBSD__
// const int onesbcast = 1;
// r = setsockopt(discovery->socket, IPPROTO_IP, IP_ONESBCAST, &onesbcast, sizeof(onesbcast));
// if(r < 0)
// CHIAKI_LOGE(discovery->log, "Discovery failed to setsockopt IP_ONESBCAST");
//#endif
return CHIAKI_ERR_SUCCESS;
}
@ -183,7 +190,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_send(ChiakiDiscovery *discovery,
if((size_t)len >= sizeof(buf))
return CHIAKI_ERR_BUF_TOO_SMALL;
int rc = sendto(discovery->socket, buf, (size_t)len + 1, 0, addr, addr_size);
int rc = sendto_broadcast(discovery->log, discovery->socket, buf, (size_t)len + 1, 0, addr, addr_size);
if(rc < 0)
{
CHIAKI_LOGE(discovery->log, "Discovery failed to send: %s", strerror(errno));

View file

@ -276,7 +276,7 @@ static ChiakiErrorCode regist_search(ChiakiRegist *regist, struct addrinfo *addr
ChiakiErrorCode err = CHIAKI_ERR_SUCCESS;
CHIAKI_LOGI(regist->log, "Regist sending search packet");
int r = sendto(sock, "SRC2", 4, 0, &send_addr, send_addr_len);
int r = sendto_broadcast(regist->log, sock, "SRC2", 4, 0, &send_addr, send_addr_len);
if(r < 0)
{
CHIAKI_LOGE(regist->log, "Regist failed to send search: %s", strerror(errno));

View file

@ -19,6 +19,7 @@
#define CHIAKI_UTILS_H
#include <chiaki/common.h>
#include <chiaki/log.h>
#ifdef _WIN32
#include <ws2tcpip.h>
#else
@ -27,6 +28,13 @@
#include <sys/socket.h>
#endif
#ifdef __FreeBSD__
#include <ifaddrs.h>
#include <string.h>
#include <errno.h>
#include <net/if.h>
#endif
#include <stdint.h>
static inline ChiakiErrorCode set_port(struct sockaddr *sa, uint16_t port)
@ -60,6 +68,46 @@ static inline const char *sockaddr_str(struct sockaddr *addr, char *addr_buf, si
return NULL;
}
static inline int sendto_broadcast(ChiakiLog *log, chiaki_socket_t s, const void *msg, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
{
#ifdef __FreeBSD__
// see https://wiki.freebsd.org/NetworkRFCCompliance
if(to->sa_family == AF_INET && ((const struct sockaddr_in *)to)->sin_addr.s_addr == htonl(INADDR_BROADCAST))
{
struct ifaddrs *ifap;
if(getifaddrs(&ifap) < 0)
{
CHIAKI_LOGE(log, "Failed to getifaddrs for Broadcast: %s", strerror(errno));
return -1;
}
int r = -1;
for(struct ifaddrs *a=ifap; a; a=a->ifa_next)
{
if(!a->ifa_broadaddr)
continue;
if(!(a->ifa_flags & IFF_BROADCAST))
continue;
if(a->ifa_broadaddr->sa_family != to->sa_family)
continue;
((struct sockaddr_in *)a->ifa_broadaddr)->sin_port = ((const struct sockaddr_in *)to)->sin_port;
char addr_buf[64];
const char *addr_str = sockaddr_str(a->ifa_broadaddr, addr_buf, sizeof(addr_buf));
CHIAKI_LOGV(log, "Broadcast to %s on %s", addr_str ? addr_str : "(null)", a->ifa_name);
int sr = sendto(s, msg, len, flags, a->ifa_broadaddr, sizeof(*a->ifa_broadaddr));
if(sr < 0)
{
CHIAKI_LOGE(log, "Broadcast on iface %s failed: %s", a->ifa_name, strerror(errno));
continue;
}
r = sr;
}
freeifaddrs(ifap);
return r;
}
#endif
return sendto(s, msg, len, flags, to, tolen);
}
static inline void xor_bytes(uint8_t *dst, uint8_t *src, size_t sz)
{
while(sz > 0)